mini6410 LED驱动程序及LED测试程序的设计

2019-07-13 05:50发布

在mini6410中,LED驱动程序是第一个操作硬件相关的驱动程序。对于以后的嵌入式linux驱动程序起到一定的引导作用
在操作所用到的mini6410的I/O口之前,就需要设置他们用到的寄存器。
在这里插入图片描述 我们需要调用一些现成的函数或者宏,在此用到的是 readl 和 writel,它们将直接对相应的寄存器执行读取和写入的操作。相关的寄存器如下 在这里插入图片描述在这里插入图片描述 除此之外,还需要调用一些和设备驱动密切相关的基本函数,如注册设备misc_register,填写驱动函数结构file_operations,以及module_init 和 module_exit 函数等。 misc为混杂设备驱动,什么是混杂设备驱动呢?
在LInux系统中,存在一类字符设备,它们共享一个人主设备号(10),但次设备号不同,我们称这类设备为混杂设备。所有的混杂设备形成一个链表,对设备访问时内核根据次设备号查找到相应的miscdevice设备。 不像2440一样,2440在操作GPIO口的时候直接调用相关封装好的函数即可进行GPIO的配置、置位,复位操作。mini6410的GPIO需要对寄存器进行配置。
相关的led驱动程序代码如下: #include #include #include //#include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #define DEVICE_NAME "leds" // static long sbc2440_leds_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) { switch(cmd) { unsigned tmp; case 0: case 1: if (arg > 4) { return -EINVAL; } //读取寄存器的值 tmp = readl(S3C64XX_GPKDAT); tmp &= ~(1 << (4 + arg)); tmp |= ( (!cmd) << (4 + arg) ); //设置寄存器的值 writel(tmp, S3C64XX_GPKDAT); //printk (DEVICE_NAME": %d %d ", arg, cmd); return 0; default: return -EINVAL; } } //文件操作设备机构体 file_operations static struct file_operations dev_fops = { .owner = THIS_MODULE, .unlocked_ioctl = sbc2440_leds_ioctl, }; //注册led驱动为MISC设备 static struct miscdevice misc = { //动态设备号 混杂设备主设备号为10 .minor = MISC_DYNAMIC_MINOR, .name = DEVICE_NAME, //设备名 .fops = &dev_fops, }; static int __init dev_init(void) //设备初始化 { int ret; { unsigned tmp; tmp = readl(S3C64XX_GPKCON); //将四个LED端口寄存器设置为输出 tmp = (tmp & ~(0xffffU<<16))|(0x1111U<<16); writel(tmp, S3C64XX_GPKCON); tmp = readl(S3C64XX_GPKDAT); //设置四个led端口寄存器设置为高电平输出,在模块加载后,四个LED不发光 tmp |= (0xF << 4); writel(tmp, S3C64XX_GPKDAT); } ret = misc_register(&misc); // 注册混杂设备,驱动加载后会在/dev目录自动生成设备文件/dev/DEVICE_NAME(混杂设备的一个特点,主设备号为10,次设备号自动动态分配) printk (DEVICE_NAME" initialized ");打印初始化信息 return ret; } //模块退出 static void __exit dev_exit(void) { misc_deregister(&misc); } module_init(dev_init); module_exit(dev_exit); MODULE_LICENSE("GPL"); MODULE_AUTHOR("silence_Z"); 以上为LED的驱动程序,如果按模块安装的话,需要编写MakeFile
MakeFile代码如下: ifneq ($(KERNELRELEASE),) obj-m := leds.o else KDIR := /home/zhangbin/mini6410/linux-2.6.38 all: make -C $(KDIR) M=$(PWD) clean: rm -f *.ko *.o *.mod.c *.symvers *.order endif 之后通过执行make nfs文件系统可以在mini6410开发板上进行模块的安装并且测试 root@xxx:inmod leds.ko root@xxx:lsmod 为了对LED驱动程序进行测试,要编写应用程序: #include #include #include #include int main(int argc,char **argv) { int on; int led_no; int fd; if(argc !=3 || sscanf(argv[1],"%d",&led_no) != 1 || sscanf(argv[2],"%d",&on) != 1 || on < 0 || on > 1 || led_no < 0 || led_no > 3) { fprintf(stderr,"Usage:leds led_no 0|1 "); exit(1); } fd = open("/dev/leds",0); if(fd < 0) { perror("open device leds"); exit(1); } ioctl(fd,on,led_no); close(fd); return 0; } 相信大家都能看懂LED应用程序,就是一些简单的open操作和判断 之后 进行交叉编译: root@xxx:arm-linux-gcc -static -o ledsapp ledapp.c 一定要加-static,不然在mini6410上无法执行 LED驱动程序的设计和LED应用程序的设计就到此结束了!!!