当前位置: 首页 > wzjs >正文

北京手机网站设计价格站长工具无内鬼放心开车禁止收费

北京手机网站设计价格,站长工具无内鬼放心开车禁止收费,wordpress二级页面菜单,深圳的网站建设公司排名文章目录 前言一、点亮多个led灯的基础实验以及其中的问题1.1 基础流程1.1.1 alinx教程的问题1.1.1.1 驱动程序中的亮/灭逻辑修改!1.1.1.1.1 逻辑错误的修改1.1.1.1.2 多灯亮/灭 1.1.1.2 驱动程序中引脚的问题以及与裸机开发的区别(重要)1.1.…

文章目录

  • 前言
  • 一、点亮多个led灯的基础实验以及其中的问题
    • 1.1 基础流程
      • 1.1.1 alinx教程的问题
        • 1.1.1.1 驱动程序中的亮/灭逻辑修改!
          • 1.1.1.1.1 逻辑错误的修改
          • 1.1.1.1.2 多灯亮/灭
        • 1.1.1.2 驱动程序中引脚的问题以及与裸机开发的区别(重要)
        • 1.1.1.3 “AMBA外设时钟使能寄存器”是怎么回事儿?
      • 1.1.2 全部流程
        • 1.1.2.1 编辑和编译驱动
        • 1.1.2.2 编辑和编译测试程序
        • 1.1.2.3 测试结果
    • 1.2 设备树和驱动程序的优先级与延申思考
      • 1.2.1 insmod驱动以后cat /proc/devices显示什么(回答优先级的问题)?
      • 1.2.2 延申思考——4个led的控制驱动就只有1个。
  • 二、后续魔改
  • 总结


前言

本文补全嵌入式系统内核镜像相关(二)中提到的驱动开发和测试流程,并且也进一步探索存在的问题,并进行了额外的思考和推敲。


一、点亮多个led灯的基础实验以及其中的问题

1.1 基础流程

依旧沿用嵌入式系统内核镜像相关(二)的PS最小系统,至于设备树,就如下:

/include/ "system-conf.dtsi"/ {  model ="ZYNQ7035"; compatible = "xlnx,zynq-7000"; usb_phy0: phy0@e0002000 {compatible = "ulpi-phy";#phy-cells = <0>;reg = <0xe0002000 0x1000>;view-port = <0x0170>;drv-vbus;};
};&usb0 {status = "okay";dr_mode = "host";usb-phy = <&usb_phy0>;
};&uart0 {
u-boot,dm-pre-reloc;
};&uart1 {
u-boot,dm-pre-reloc;
};

通过上述设备树和petalinux-config的配置得到启动镜像后,略去不表,咱接着研究驱动。

开发板还是使用璞致的7035!

1.1.1 alinx教程的问题

本来大体上参考alinx的字符设备教程,但琢磨发现一些问题和疑惑了。

alinx提供的驱动程序如下:

#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/fs.h>
#include <linux/init.h>
#include <linux/ide.h>
#include <linux/types.h>/* 驱动名称 */
#define DEVICE_NAME "gpio_leds"
/* 驱动主设备号 */
#define GPIO_LED_MAJOR 200/* gpio 寄存器虚拟地址 */
static unsigned int gpio_add_minor;
/* gpio 寄存器物理基地址 */
#define GPIO_BASE 0xE000A000
/* gpio 寄存器所占空间大小 */
#define GPIO_SIZE 0x1000
/* gpio 方向寄存器 */
#define GPIO_DIRM_0 (unsigned int *)(0xE000A204 - GPIO_BASE + gpio_add_minor)
/* gpio 使能寄存器 */
#define GPIO_OEN_0 (unsigned int *)(0xE000A208 - GPIO_BASE + gpio_add_minor)
/* gpio 控制寄存器 */
#define GPIO_DATA_0 (unsigned int *)(0xE000A040 - GPIO_BASE + gpio_add_minor)/* 时钟使能寄存器虚拟地址 */
static unsigned int clk_add_minor;
/* 时钟使能寄存器物理基地址 */
#define CLK_BASE 0xF8000000
/* 时钟使能寄存器所占空间大小 */
#define CLK_SIZE 0x1000
/* AMBA 外设时钟使能寄存器 */
#define APER_CLK_CTRL (unsigned int *)(0xF800012C - CLK_BASE + clk_add_minor)/* open 函数实现, 对应到 Linux 系统调用函数的 open 函数 */
static int gpio_leds_open(struct inode *inode_p, struct file *file_p)
{
/* 把需要修改的物理地址映射到虚拟地址 */
gpio_add_minor = (unsigned int)ioremap(GPIO_BASE, GPIO_SIZE);
clk_add_minor = (unsigned int)ioremap(CLK_BASE, CLK_SIZE);/* MIO_0 时钟使能 */
*APER_CLK_CTRL |= 0x00400000;
/* MIO_0 设置成输出 */
*GPIO_DIRM_0 |= 0x00000001;
/* MIO_0 使能 */
*GPIO_OEN_0 |= 0x00000001;printk("gpio_test module open\n");return 0;
}/* write 函数实现, 对应到 Linux 系统调用函数的 write 函数 */
static ssize_t gpio_leds_write(struct file *file_p, const char __user *buf, size_t len, loff_t *loff_t_p)
{
int rst;
char writeBuf[5] = {0};printk("gpio_test module write\n");rst = copy_from_user(writeBuf, buf, len);
if(0 != rst)
{
return -1;
}if(1 != len)
{
printk("gpio_test len err\n");
return -2;
}
if(1 == writeBuf[0])
{
*GPIO_DATA_0 &= 0xFFFFFFFE;
printk("gpio_test ON\n");
}
else if(0 == writeBuf[0])
{
*GPIO_DATA_0 |= 0x00000001;
printk("gpio_test OFF\n");
}
else
{
printk("gpio_test para err\n");
return -3;
}return 0;
}/* release 函数实现, 对应到 Linux 系统调用函数的 close 函数 */
static int gpio_leds_release(struct inode *inode_p, struct file *file_p)
{
printk("gpio_test module release\n");
return 0;
}/* file_operations 结构体声明, 是上面 open、write 实现函数与系统调用函数对应的关键 */
static struct file_operations gpio_leds_fops = {
.owner = THIS_MODULE,
.open = gpio_leds_open,
.write = gpio_leds_write,
.release = gpio_leds_release,
};/* 模块加载时会调用的函数 */
static int __init gpio_led_init(void)
{
int ret;/* 通过模块主设备号、名称、模块带有的功能函数(及 file_operations 结构体)来注册模块 */
ret = register_chrdev(GPIO_LED_MAJOR, DEVICE_NAME, &gpio_leds_fops);
if (ret < 0)
{
printk("gpio_led_dev_init_ng\n");
return ret;
}
else
{
/* 注册成功 */
printk("gpio_led_dev_init_ok\n");
}
return 0;
}/* 卸载模块 */
static void __exit gpio_led_exit(void)
{
/* 释放对虚拟地址的占用 */
iounmap((unsigned int *)gpio_add_minor);
iounmap((unsigned int *)clk_add_minor);
/* 注销模块, 释放模块对这个设备号和名称的占用 */
unregister_chrdev(GPIO_LED_MAJOR, DEVICE_NAME);printk("gpio_led_dev_exit_ok\n");
}/* 标记加载、卸载函数 */
module_init(gpio_led_init);
module_exit(gpio_led_exit);/* 驱动描述信息 */
MODULE_AUTHOR("Alinx");
MODULE_ALIAS("gpio_led");
MODULE_DESCRIPTION("GPIO LED driver");
MODULE_VERSION("v1.0");
MODULE_LICENSE("GPL");
1.1.1.1 驱动程序中的亮/灭逻辑修改!

主要指的是控制灯亮灭的逻辑错误。

1.1.1.1.1 逻辑错误的修改

观察其中的:

if(1 == writeBuf[0])
{
*GPIO_DATA_0 &= 0xFFFFFFFE;
printk("gpio_test ON\n");
}
else if(0 == writeBuf[0])
{
*GPIO_DATA_0 |= 0x00000001;
printk("gpio_test OFF\n");
}

根据printk的提示,*GPIO_DATA_0 &= 0xFFFFFFFE;应该预期亮灯,但实际上观察GPIO_DATA_0指针指向的结果末位是0。根据《ug585-Zynq-7000-TRM.pdf》,结果应该是1。对于灭灯的控制同理,因此需要修改为如下:

if(1 == writeBuf[0])
{
*GPIO_DATA_0 |= 0x00000001;
printk("gpio_test ON\n");
}
else if(0 == writeBuf[0])
{
*GPIO_DATA_0 &= 0xFFFFFFFE;
printk("gpio_test OFF\n");
}

实验结果和预期一致。

1.1.1.1.2 多灯亮/灭

多灯的亮/灭控制其实和当初的裸机开发一致了。由于当初裸机开发使用了基于EMIO引脚的GPIO-led,所以咱肯定不能接着沿用alinx提供的驱动程序。

我先说说为什么我们不能接着用基于MIO引脚的GPIO-led,因为道理很简单,早在制作PS最小子系统的时候,led灯全被绑定到EMIO引脚的GPIO上,所以即使照着alinx的作业抄,也不会有啥效果(已经验证过了,实验结果也确实如此)!

那么,怎么改?很简单,先回到璞致提供的用户手册:

在这里插入图片描述

明明白白说了EMIO属于bank2,然后回到《ug585-Zynq-7000-TRM.pdf》。

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

所以使用0x00000284GPIO方向寄存器和0x00000288的使能寄存器,以及0x00000048的控制寄存器。关于控制寄存器/方向寄存器/使能寄存器,每一个bit都对应相应的EMIO,因此,为实现多灯亮灭控制,很显然需要从低到高依次写入数值。我们就以4个灯为例!

在方向/使能寄存器上:

/* MIO_0 时钟使能 */
*APER_CLK_CTRL |= 0x00400000;
/* MIO_0 设置成输出 */
*GPIO_DIRM_0 |= 0x0000000F;
/* MIO_0 使能 */
*GPIO_OEN_0 |= 0x0000000F;

在亮灭实现(控制寄存器)上:

if(1 == writeBuf[0])
{
*GPIO_DATA_0 |= 0x0000000F;
printk("gpio_test ON\n");
}
else if(0 == writeBuf[0])
{
*GPIO_DATA_0 &= 0xFFFFFFF0;
printk("gpio_test OFF\n");
}

因此,可以控制4个基于EMIOGPIO-led亮灭的驱动代码如下:

#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/fs.h>
#include <linux/init.h>
#include <linux/ide.h>
#include <linux/types.h>/* 驱动名称 */
#define DEVICE_NAME "gpio_leds_our"
/* 驱动主设备号 */
#define GPIO_LED_MAJOR 200/* gpio 寄存器虚拟地址 */
static unsigned int gpio_add_minor;
/* gpio 寄存器物理基地址 */
#define GPIO_BASE 0xE000A000
/* gpio 寄存器所占空间大小 */
#define GPIO_SIZE 0x1000
/* gpio 方向寄存器 */
#define GPIO_DIRM_0 (unsigned int *)(0xE000A284 - GPIO_BASE + gpio_add_minor)
/* gpio 使能寄存器 */
#define GPIO_OEN_0 (unsigned int *)(0xE000A288 - GPIO_BASE + gpio_add_minor)
/* gpio 控制寄存器 */
#define GPIO_DATA_0 (unsigned int *)(0xE000A048 - GPIO_BASE + gpio_add_minor)/* 时钟使能寄存器虚拟地址 */
static unsigned int clk_add_minor;
/* 时钟使能寄存器物理基地址 */
#define CLK_BASE 0xF8000000
/* 时钟使能寄存器所占空间大小 */
#define CLK_SIZE 0x1000
/* AMBA 外设时钟使能寄存器 */
#define APER_CLK_CTRL (unsigned int *)(0xF800012C - CLK_BASE + clk_add_minor)/* open 函数实现, 对应到 Linux 系统调用函数的 open 函数 */
static int gpio_leds_open(struct inode *inode_p, struct file *file_p)
{
/* 把需要修改的物理地址映射到虚拟地址 */
gpio_add_minor = (unsigned int)ioremap(GPIO_BASE, GPIO_SIZE);
clk_add_minor = (unsigned int)ioremap(CLK_BASE, CLK_SIZE);/* MIO_0 时钟使能 */
*APER_CLK_CTRL |= 0x00400000;
/* MIO_0 设置成输出 */
*GPIO_DIRM_0 |= 0x0000000F;
/* MIO_0 使能 */
*GPIO_OEN_0 |= 0x0000000F;printk("gpio_test module open\n");return 0;
}/* write 函数实现, 对应到 Linux 系统调用函数的 write 函数 */
static ssize_t gpio_leds_write(struct file *file_p, const char __user *buf, size_t len, loff_t *loff_t_p)
{
int rst;
char writeBuf[5] = {0};printk("gpio_test module write\n");rst = copy_from_user(writeBuf, buf, len);
if(0 != rst)
{
return -1;
}if(1 != len)
{
printk("gpio_test len err\n");
return -2;
}
if(1 == writeBuf[0])
{
*GPIO_DATA_0 |= 0x0000000F;
printk("gpio_test ON\n");
}
else if(0 == writeBuf[0])
{
*GPIO_DATA_0 &= 0xFFFFFFF0;
printk("gpio_test OFF\n");
}
else
{
printk("gpio_test para err\n");
return -3;
}return 0;
}/* release 函数实现, 对应到 Linux 系统调用函数的 close 函数 */
static int gpio_leds_release(struct inode *inode_p, struct file *file_p)
{
printk("gpio_test module release\n");
return 0;
}/* file_operations 结构体声明, 是上面 open、write 实现函数与系统调用函数对应的关键 */
static struct file_operations gpio_leds_fops = {
.owner = THIS_MODULE,
.open = gpio_leds_open,
.write = gpio_leds_write,
.release = gpio_leds_release,
};/* 模块加载时会调用的函数 */
static int __init gpio_led_init(void)
{
int ret;/* 通过模块主设备号、名称、模块带有的功能函数(及 file_operations 结构体)来注册模块 */
ret = register_chrdev(GPIO_LED_MAJOR, DEVICE_NAME, &gpio_leds_fops);
if (ret < 0)
{
printk("gpio_led_dev_init_ng\n");
return ret;
}
else
{
/* 注册成功 */
printk("gpio_led_dev_init_ok\n");
}
return 0;
}/* 卸载模块 */
static void __exit gpio_led_exit(void)
{
/* 释放对虚拟地址的占用 */
iounmap((unsigned int *)gpio_add_minor);
iounmap((unsigned int *)clk_add_minor);
/* 注销模块, 释放模块对这个设备号和名称的占用 */
unregister_chrdev(GPIO_LED_MAJOR, DEVICE_NAME);printk("gpio_led_dev_exit_ok\n");
}/* 标记加载、卸载函数 */
module_init(gpio_led_init);
module_exit(gpio_led_exit);/* 驱动描述信息 */
MODULE_AUTHOR("Alinx");
MODULE_ALIAS("gpio_led");
MODULE_DESCRIPTION("GPIO LED driver");
MODULE_VERSION("v1.0");
MODULE_LICENSE("GPL");
1.1.1.2 驱动程序中引脚的问题以及与裸机开发的区别(重要)

关于引脚问题,见1.1.1.1。注意,alinx采用的是基于MIOGPIO引脚,因此没法儿直接用。我还是参照1.1.1.1中的流程修改!

不难看出来,裸机开发的流程中,得益于xparameters.h的存在,避免了自己去找文档,只需要关注EMIO的起始序号和范围即可。然而,驱动开发需要自己确认某些寄存器的引脚以实现正常功能。

所以,相比之下,从这一方面来看,驱动开发的流程更为复杂。

1.1.1.3 “AMBA外设时钟使能寄存器”是怎么回事儿?

alinx的教程提到这个名词的时候,我不禁愣了一下,因为这个在裸机开发中压根儿不存在。

但还是去花了时间去确认这是个啥!回到《ug585-Zynq-7000-TRM.pdf》。

在这里插入图片描述
在这里插入图片描述
可以看到这里有个APER_CLK_CTRL寄存器,详细看下该寄存器:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
所以,这个寄存器的各个bit用于控制AMBA时钟,第23bit用于控制GPIO相关的时钟。那好像也不奇怪了!

1.1.2 全部流程

假设启动镜像已经制作结束,那么就从驱动开发开始!

1.1.2.1 编辑和编译驱动

首先使用petalinux-create -t modules --name ax-led-drv创建驱动模板文件,如下:

dention@ubuntu:~/petalinux_proj/test_peta/proj_peta$ petalinux-create -t modules --name ax-led-drv
INFO: Create modules: ax-led-drv
INFO: New modules successfully created in /home/dention/petalinux_proj/test_peta/proj_peta/project-spec/meta-user/recipes-modules/ax-led-drv

修改路径为/home/dention/petalinux_proj/test_peta/proj_peta/project-spec/meta-user/recipes-modules/ax-led-drv/files/下的驱动模板文件ax-led-drv.c1.1.1.1.2中的驱动程序。

随后petalinux-config -c rootfs选中驱动模块,如下:

dention@ubuntu:~/petalinux_proj/test_peta/proj_peta$ petalinux-config -c rootfs
[INFO] sourcing bitbake
[INFO] generating plnxtool conf
[INFO] generating meta-plnx-generated layer
[INFO] generating user layers
[INFO] generating machine configuration
[INFO] configuring: rootfs
[INFO] generating kconfig for Rootfs
[INFO] menuconfig rootfs*** End of the configuration.
*** Execute 'make' to start the build or try 'make help'.[INFO] generating petalinux-user-image.bb
[INFO] successfully configured rootfs

在这里插入图片描述

选中之后,使用petalinux-build编译得到.ko驱动文件,如下:

dention@ubuntu:~/petalinux_proj/test_peta/proj_peta$ petalinux-build 
[INFO] building project
[INFO] sourcing bitbake
[INFO] generating user layers
INFO: bitbake petalinux-user-image
Loading cache: 100% |########################################################################################################################| Time: 0:00:02
Loaded 3811 entries from dependency cache.
Parsing recipes: 100% |######################################################################################################################| Time: 0:00:08
Parsing of 2778 .bb files complete (2774 cached, 4 parsed). 3813 targets, 163 skipped, 0 masked, 0 errors.
NOTE: Resolving any missing task queue dependencies
Initialising tasks: 100% |###################################################################################################################| Time: 0:00:07
Checking sstate mirror object availability: 100% |###########################################################################################| Time: 0:00:22
Sstate summary: Wanted 134 Found 20 Missed 228 Current 753 (14% match, 87% complete)
NOTE: Executing SetScene Tasks
NOTE: Executing RunQueue Tasks
NOTE: Tasks Summary: Attempted 3199 tasks of which 2926 didn't need to be rerun and all succeeded.
INFO: Copying Images from deploy to images
NOTE: Failed to copy built images to tftp dir:  /tftpboot
[INFO] successfully built project

可以找一下.ko文件:

dention@ubuntu:~/petalinux_proj/test_peta/proj_peta$ find ./ -name "ax-led-drv.ko"
./build/tmp/sysroots-components/plnx_zynq7/ax-led-drv/lib/modules/4.19.0-xilinx-v2019.1/extra/ax-led-drv.ko

到此为止,驱动开发部分结束!接下来编辑和编译测试程序!

1.1.2.2 编辑和编译测试程序

按照下述存放文件:

dention@ubuntu:~/qt_proj$ tree
.
├── axleddev_test
│   └── main.c
└── build-axleddev_test-ZYNQ-Debug└── Makefile2 directories, 2 files

为什么是这么放的,可以参考嵌入式系统内核镜像相关(九)。

其中main.c是:

#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>int main(int argc, char **argv)
{
int fd;
char buf;if(3 != argc)
{
printf("none para\n");
return -1;
}fd = open(argv[1], O_RDWR);
if(fd < 0)
{
printf("Can't open file %s\r\n", argv[1]);
return -1;
}if(!strcmp("on",argv[2]))
{
printf("ps_led1 on\n");
buf = 1;
write(fd, &buf, 1);
}
else if(!strcmp("off",argv[2]))
{
printf("ps_led1 off\n");
buf = 0;
write(fd, &buf, 1);
}
else
{
printf("wrong para\n");
return -2;
}close(fd);
return 0;
}

其中Makefile是:

CC = arm-linux-gnueabihf-gcc
CFLAGS = -Wall -gall: axleddev_testaxleddev_test: main.o$(CC) $(CFLAGS) -o axleddev_test main.omain.o: ../axleddev_test/main.c$(CC) $(CFLAGS) -c ../axleddev_test/main.cclean:rm -f axleddev_test main.o

然后make all即可得到驱动模块测试可执行文件。

1.1.2.3 测试结果

参照嵌入式系统内核镜像相关(八)将驱动模块文件和测试的可执行文件放到开发板侧!

参考下述运行:

root@proj_peta:~# ls
ax-led-drv.ko  axleddev_test
root@proj_peta:~# chmod 777 -R axleddev_test
root@proj_peta:~# insmod ax-led-drv.ko
ax_led_drv: loading out-of-tree module taints kernel.
gpio_led_dev_init_ok
root@proj_peta:~# mknod /dev/alinx-led c 200 0
root@proj_peta:~# ls /dev/
alinx-led           mtab                ram6                tty27               tty55
block               mtd0                ram7                tty28               tty56
char                mtd0ro              ram8                tty29               tty57
console             mtd1                ram9                tty3                tty58
cpu_dma_latency     mtd1ro              random              tty30               tty59
disk                mtd2                shm                 tty31               tty6
fd                  mtd2ro              snd                 tty32               tty60
full                mtd3                stderr              tty33               tty61
gpiochip0           mtd3ro              stdin               tty34               tty62
iio:device0         mtdblock0           stdout              tty35               tty63
initctl             mtdblock1           tty                 tty36               tty7
kmsg                mtdblock2           tty0                tty37               tty8
log                 mtdblock3           tty1                tty38               tty9
loop-control        network_latency     tty10               tty39               ttyPS0
loop0               network_throughput  tty11               tty4                ttyPS1
loop1               null                tty12               tty40               udev_network_queue
loop2               port                tty13               tty41               urandom
loop3               ptmx                tty14               tty42               vcs
loop4               pts                 tty15               tty43               vcs1
loop5               ram0                tty16               tty44               vcsa
loop6               ram1                tty17               tty45               vcsa1
loop7               ram10               tty18               tty46               vcsu
mem                 ram11               tty19               tty47               vcsu1
memory_bandwidth    ram12               tty2                tty48               vga_arbiter
mmcblk0             ram13               tty20               tty49               watchdog
mmcblk0p1           ram14               tty21               tty5                watchdog0
mmcblk0p2           ram15               tty22               tty50               zero
mmcblk1             ram2                tty23               tty51
mmcblk1boot0        ram3                tty24               tty52
mmcblk1boot1        ram4                tty25               tty53
mmcblk1rpmb         ram5                tty26               tty54
root@proj_peta:~# ls
ax-led-drv.ko  axleddev_test
root@proj_peta:~# ./axleddev_test /dev/alinx-led on
gpio_test module open
ps_led1 on
gpio_test module write
gpio_test ON
gpio_test module release
root@proj_peta:~# ./axleddev_test /dev/alinx-led off
gpio_test module open
ps_led1 off
gpio_test module write
gpio_test OFF
gpio_test module release

初始情况如下:

在这里插入图片描述

其中亮灯的时候,如下:

在这里插入图片描述

灭灯的时候,如下:

在这里插入图片描述
到此为止!

1.2 设备树和驱动程序的优先级与延申思考

现在我把之前嵌入式系统内核镜像相关(二)里面的设备树替换掉本文一开始提到的设备树!

注意设备树中的compatiblegpio-leds,而驱动中的设备名称是gpio_leds_our

1.2.1 insmod驱动以后cat /proc/devices显示什么(回答优先级的问题)?

显示结果如下:

root@proj_peta:~# chmod 777 -R axleddev_test
root@proj_peta:~# insmod ax-led-drv.ko
ax_led_drv: loading out-of-tree module taints kernel.
gpio_led_dev_init_ok
root@proj_peta:~# cat /proc/devices
Character devices:1 mem4 /dev/vc/04 tty5 /dev/tty5 /dev/console5 /dev/ptmx7 vcs10 misc13 input21 sg29 fb81 video4linux89 i2c90 mtd
116 alsa
128 ptm
136 pts
180 usb
189 usb_device
200 gpio_leds_our
226 drm
244 rpmb
245 uio
246 watchdog
247 iio
248 ptp
249 pps
250 media
251 rtc
252 ttyPS
253 ttyPS
254 gpiochipBlock devices:1 ramdisk7 loop8 sd31 mtdblock65 sd66 sd67 sd68 sd69 sd70 sd71 sd
128 sd
129 sd
130 sd
131 sd
132 sd
133 sd
134 sd
135 sd
179 mmc
259 blkext

根据编号200,可以证明即使设备树变更了,但是驱动还是顺利加载!

但是下一步的驱动测试失败了,灯的状态是10个灯按照heartbeat模式闪烁。

但沿用嵌入式系统内核镜像相关(二)里面的内置测试可以成功!

不能排除的一点是petalinux-build将设备树的内容编译进内核,并且启用了gpio-leds的内置驱动模块。这就导致再使用insmod驱动进宏内核时,可能因为宏内核判断gpioemio引脚被占用,即使insmod驱动模块,无法通过测试。

可能的解决办法是rmmod内核自带的gpio-leds模块,或者,单独编译设备树文件并加载进入内核。但是,petalinux平台并不支持单独编译设备树文件(我确实没找到),但是存在单独编译设备树文件和设备树插件文件的方式(可以参考野火的教程)。

这个话题值得后续研究,我在博客中标记一下!

1.2.2 延申思考——4个led的控制驱动就只有1个。

现在4个led灯的控制是由1个驱动完成的!

因此,可以确认的一点是被控制外设的数量并不绝对等于驱动数量。

此外,驱动可以控制4个led灯,也就意味着可以控制10个led灯。但是控制的逻辑被限制在驱动程序里面,导致需要控制10个led灯时,不得不重新编译驱动模块,这在petalinux中还是挺浪费时间的!

怎么办?这也是后续接着研究的内容!

(很幸运的是,自己从4个led灯的例子,cover掉以往讲解驱动教程中提到为什么要发展设备驱动平台和设备树的原因!)

二、后续魔改

这一节放在下一篇文章了,本篇内容够多了!

另外后面几篇就不一定会那么详细地展开步骤,只会提及教程中需要注意的点。


总结

alinx教程中与我开发板不符的点进行详细描述,并深度思考一些从未被教程提到的问题。

此外,这次开发将Vivado最小ps子系统、Vitis SDK上的xparameters.h和驱动开发结合在一起,相互辅助判断驱动开发的bug究竟出在哪里,尽管怎么遇到bug和怎么解决bug的过程我并没有展开,但从上文我怎么改进中可窥一角。

http://www.dtcms.com/wzjs/187269.html

相关文章:

  • 做网站_没内容真人seo点击平台
  • 网站用什么框架做怎样做一个网页
  • 珠海网站建设尚古道策略软文营销实施背景
  • 增城哪家网站建设好做个网页需要多少钱?
  • 以美食为主的网站栏目怎么做seo营销课程培训
  • 石家庄做网站比较好的公司有哪些app拉新推广怎么做
  • 室内装饰设计培训机构seo手机关键词网址
  • 网站编程好学吗微信营销软件哪个好用
  • 网站建设用到的技术国际新闻最新消息10条
  • html 创意网站app开发自学教程
  • 游戏推广员如何推广引流网站优化排名提升
  • 深圳flash网站建设百度关键词收录
  • 美国专门做特卖的网站微商刚起步怎么找客源
  • 成都注册公司核名网站网站推广内容
  • 做跨境电商网站的意义seo优化培训机构
  • 网站建设一条龙百度关键词优化企业
  • wordpress_子网站重命名哈尔滨关键词优化报价
  • 合肥企业网站模板建站seo网站优化技术
  • 网站建设最新教程视频教程刷外链网站
  • 委托网络公司做的网站侵权武汉武汉最新
  • 官方做任务网站360收录提交入口
  • 长沙房产集团网站建设seo什么职位
  • wordpress链接提交seo关键词找29火星软件
  • 玻璃钢产品哪个网站做推广好西安网站seo公司
  • 东营做网站建设的公司seo优化网站
  • 天津做网站好的公司企业网站搭建
  • 怎么做消费一卡通网站网络推广外包公司
  • 网站建设选超速云建站全国疫情一览表
  • web网站开发参考文献甘肃网站推广
  • 做视频网站利润如何郑州seo技术服务