完善资料让更多小伙伴认识你,还能领取20积分哦, 立即完善>
|
|
相关推荐
1个回答
|
|
最近在学习嵌入式 Linux 驱动开发,学生了解驱动的基本开发流程,本文主要针对字符设备驱动开发做一个简要介绍,也算是对这几天工作的一个小总结。
计算机系统是由软硬件各自共同作为共同完成工作的,作为专用系统的内置系统,既支持CPU、SDRAM、FLASH、IO等硬件,同时也少不了操作系统和应用软件等软件的支持,而应用与硬件的关键——驱动程序,是整个嵌入式系统开发过程中的关键驱动程序。驱动开发涉及重大,而了解主要作用机制对于整个开发的意义。 Linux 核心系统渗透60%以上是驱动程序,它支持形式以动态形式启动细胞,并且允许驱动以模块的动态加载进内核,可以诊断出内核的大小,便于调试分析。Linux 将所有的设备当作文件进行,Linux 系统的设备分为三类:字符设备、块设备和网络设备。字符设备的驱动有一个固定的模板,主要写文件_操作结构体中的成员函数,这些函数最终会在应用程序进行Linux的open()、写()、read()、ioctl()、close)等系统调用时被调用。 驱动开发作用在渗透空间,应用程序开发作用在用户空间。下面以GPIO端口驱动LED亮灭举例。 1、查看开发板原理图和芯片数据手册; 从上图开始可以完成GPF4~GPF7,分别控制D12~D9,当GPF4~GPF4~GPF4~GPF为输出模式,同时向该输出0时LED亮,输出1时LED灭灯。 从下图可以继承GPFCON控制对应的每个字节由决定输出,01时表示,所以GPF7~GPF4为0101时,所以GPFCON=0x55FF。分别对应对应,0表示01,表示输出1输出如要使D9~D12都亮,则GPFDAT=0x0F。GPFUP的八位为1时表示上拉失效,0时位上拉。同时可以是GPFCON、GPFDAT、GPFUP的物理地址分别是0x56000050、0x56000054、0x56000058。 2、在虚拟机的shell终端下,写和写驱动程序和测试程序,如下步骤; 源码如下: led。 C #include《linux/module.h》 #include《linux/kernel.h》 #include《linux/fs.h》 #include《linux/init.h》 #include《linux/delay.h》 #include《linux/ device.h》 #include《linux/types.h》 #include《linux/ioctl.h》 #include《linux/cdev.h》 #include《linux/errno.h》 #include《asm/io.h》 # include《asm/hardware.h》 #include《asm/arch/regs-gpio.h》 #include《asm/arch-s3c2410/hardware.h》 #define S3C2410_GPFCON S3C2410_GPIOREG(0x50) #define S3C2410_GPFDAT_S3C24105_GPF3C24105 S3C2410_GPFUP S3C2410_GPIOREG(0x58) #define GPFCON *(volatile unsigned int *)S3C2410_GPFCON #define GPFDAT *(volatile unsigned int *)S3C2410_GPFDAT #define GPFUP *(volatile unsigned int *)S3C2410_delay_int for(i=0;i《1000;i++) for(j=0;j《10000;j++); } #define LED1_ON() (GPFDAT &=~0x8f) #define LED2_ON() (GPFDAT &=~0x4f) #define LED3_ON() (GPFDAT &=~0x2f) #define LED4_ON() (GPFDAT &=~0x1f) #定义 LED1_OFF() (GPFDAT |=0x80) #define LED2_OFF() (GPFDAT |=0x40) #define LED3_OFF() (GPFDAT |=0x20) #define LED4_OFF() (GPFDAT |=0x10) static int LedStatus; void LedSet(int led) { LedStatus = led; if(LedStatus&1) LED1_ON(); 否则 LED1_OFF(); if(LedStatus&2) LED2_ON(); 否则 LED2_OFF(); if(LedStatus&4) LED3_ON(); 否则 LED3_OFF(); if(LedStatus&8) LED4_ON(); 否则 LED4_OFF(); } void LedDisp(void) { LedSet(0x08); 延迟_1(); LedSet(0x04); 延迟_1(); LedSet(0x02); 延迟_1(); LedSet(0x01); 延迟_1(); LedSet(0x02); 延迟_1(); LedSet(0x04); 延迟_1(); LedSet(0x08); 延迟_1(); } #define DEVICE_NAME “led” #define LED_MAJOR 220 static int led_open(struct inode *inode,struct file *file) { GPFCON=0x5500; GPFUP=0xff; printk(“LED 驱动打开调用!n”); 返回0;} static int led_release(struct inode *inode,struct file *file) { printk(“LED Driver Release Calledn”); 返回0;} static int led_ioctl(struct inode *inode,struct file *file,unsigned int cmd,unsigned long arg) { int err=0; if(cmd==1){ while(arg--) { LedDisp(); printk(“。。。。”); } printk(“n”); 返回0;返回错误;} static struct file_operations led_fops = { .owner = THIS_MODULE, .open = led_open, .release = led_release, .ioctl = led_ioctl, }; 静态 int __init led_init(void) { int result=0; 结果=register_chrdev(LED_MAJOR,DEVICE_NAME,&led_fops); if(result 《 0) { printk(“注册失败!n”); 返回结果;} printk(“注册成功n”); 返回0;} static void __exit led_exit(void) { printk(“LED 驱动模块退出n”); unregister_chrdev(LED_MAJOR,DEVICE_NAME); } 模块初始化(led_init);模块退出(led_exit);MODULE_AUTHOR(“njust_sxy”); MODULE_DESCRIPTION(“LED 驱动程序”); MODULE_LICENSE(“GPL”); Makefile obj-m :=led.o KDIR := /home/sxy/linux-2.6.8.1-zzm PWD :=$(shell pwd) CC=arm-linux-gcc 默认:$(MAKE) -C $(KDIR ) SUBDIRS=$(PWD) 模块清理:rm -rf .*.cmd *.o *.mod.c *.ko《/span》 test.c #include《stdio.h》 #include《stdlib.h》 #include《fcntl.h》 #include《errno.h》 #include《unistd.h》 #include《linux/delay.h》 #include《sys/ioctl .h》 int main(int argc, char *argv[]) { int fd; int val=-1; fd=open(“/dev/led”,0); if(fd《0) { perror(“无法打开设备”); 退出(1);} while(1){ printf(“请选择运行程序的编号n”); printf(“1:led on n2:quit ”); scanf(“%d”,&val); if(val==1) ioctl(fd,1,10); 否则 if(val==2){ close(fd); } } 返回 0; insmod的:加载模块; mknod的:创建设备节点; rmmod的:卸载模块; led.ko:导致驱动设备模块 实验查询查询结果:在终端打印出“。。。。。。“的同时,LED从D12〜D9相继亮灭(总结 :整个LED驱动开发并不算,如果有了一定的Linux基础,再加上一些Linux基础,上会更容易。了解答总之,基础还是很重要的,理论+实践才是王道。 PS:曾经尝试调用内核中的s3c2410_gpio_cfgpin()和s3c2410_gpio_setpin()两个函数来实现端口输出配置和向数据寄存器写数据,但会出现下面这个问题: s3c2410_gpio_cfgpin()和s3c2410_gpio_setpin()这两个函数在/arch/arm/mach-s3c2410/gpio.c文件中定义,最初在asm-arm/arch-s3c2410/hardware.h中extern声明,编译时警告说这两个函数是“未定义”的,后来这个我在gpio.c文件中添加EXPORT_SYMBOL(s3c2410_gpio_cfgpin);EXPORT_SYMBOL(s3c2410_gpio_setpin);导出,却出现了“无CRC”符号,警告这个问题已经折我了好几天了,求高手解答。 |
|
|
|
只有小组成员才能发言,加入小组>>
4274个成员聚集在这个小组
加入小组3275 浏览 0 评论
航顺(HK)联合电子发烧友推出“近距离体验高性能Cortex-M3,免费申请价值288元评估板
4216 浏览 1 评论
4221 浏览 0 评论
小黑屋| 手机版| Archiver| 电子发烧友 ( 湘ICP备2023018690号 )
GMT+8, 2024-11-10 21:53 , Processed in 0.338678 second(s), Total 43, Slave 38 queries .
Powered by 电子发烧友网
© 2015 bbs.elecfans.com
关注我们的微信
下载发烧友APP
电子发烧友观察
版权所有 © 湖南华秋数字科技有限公司
电子发烧友 (电路图) 湘公网安备 43011202000918 号 电信与信息服务业务经营许可证:合字B2-20210191 工商网监 湘ICP备2023018690号