9、LED驱动
创始人
2024-11-12 02:38:25

编写步骤:

1、确定LED是哪个GPIO,通过看原理图确认

2、配置GPIO的寄存器(复用关系、方向、数据寄存器)

        找到相关寄存器的地址 例如设置复用功能的寄存器设置:       

Linux系统 可以使用 io 命令查看寄存器的值 :

io -r -4 0xfdc2000c

3、驱动代码里使用ioremap 获取寄存器的虚拟地址

例程

#include  #include   #include  #include  #include   #include  #include  #include  #include  #include  #include       #define LED_GPIO_DIR_REG   0xfd000000  #define LED_GPIO_DATA_REG  0xfd00000C     struct led_device={       dev_t dev_num;      int major;     int minor;         struct cdev cdev_test;      struct class *class;     struct device *device;     char kbuf[32]; 	unsigened int  *vir_gpio_dir;     }     struct led_device  led1;         static  int led_open(struct inode *node, struct file *file) {     file->private_data=&led1;        printk("cdev_test_open \n");      return 0; }   static int cdev_test_release(struct inode *node, struct file *file) {        printk("cdev_test_release \n");      return 0;   }   static ssize_t cdev_test_read (struct file *file, char __user *buf, size_t size, loff_t *off) {     struct led_device *test_dev=(struct led_device *) file->private_data;       char kbuf[64]="123456hello";          copy_to_user(buf,test_dev ->kbuf,strlen(test_dev ->kbuf));        printk("cdev_test_read \n");     }     static ssize_t cdev_test_write (struct file *file, const char __user *buf, size_t size, loff_t *off) {      struct led_device *test_dev=(struct led_device *) file->private_data;      char kbuf[64];      copy_from_user(test_dev -> kbuf,buf,size);      printk("write buf[%s]\n",test_dev ->kbuf);      printk("cdev_test_write\n");   }     struct file_operations cdev_test_ops={       .owner=THIS_MODULE,     .open=cdev_test_open,     .release=cdev_test_release,     .read=cdev_test_read,     .write=cdev_test_write,     .ioctl=cdev_test_ioctl };     static int cdv_init(void) {     int ret;    	//动态申请 	ret=alloc_chrdev_region(&led1.dev_num,0,1,"led_num"); 	if( ret <0 ) 	{ 		printk("alloc_chrdev_regionerr %d\n",ret); 		goto err_alloc_chrdev_region; 	} 	printk("dev_num=%d \n",led1.dev_num); 	led1.major = MAJOR(led1.dev_num); 	led1.minor = MINOR(led1.dev_num); 	printk("input major=%d minor=%d \n",led1.major,led1.minor);           led1.cdev_test.owner= THIS_MODULE;     cdev_init(&led1.cdev_test,&cdev_test_ops);       ret = cdev_add(&led1.cdev_test,led1.dev_num,1);  	if( ret <0 ) 	{ 		printk("alloc_chrdev_regionerr %d\n",ret); 		goto err_cdev_add; 	}     led1.class = class_create(THIS_MODULE,"led1");	     if(IS_ERR(led1.class  ))     {         ret=PTR_ERR( led1.class );         goto err_device_create ;     }  	     led1.device = device_create(led1.class,NULL,led1.dev_num,NULL,"/dev/led1");          if(IS_ERR(led1.device ))     {         ret=PTR_ERR( led1.device );         goto err_device_create ;     } 	 	 	 	//内核中不能直接操作虚拟地址,需要将物理地址转换成虚拟地址 	led1.vir_gpio_dir= ioremap(LED_GPIO_DIR_REG,4);        	 	     printk("cdv init\n");     return 0; 	 	 err_device_create:     device_destroy(led1.class,led1.dev_num); err_class_create:     classs_destroy(led1.class); err_cdev_add:     cdev_del(&led1.cdev_test);	 err_alloc_chrdev_region :     unregister_chrdev_region(led1.dev_num,1);  	 }   static void cdv_exit(void) { 	iounmap(led1.vir_gpio_dir); 	     device_destroy(led1.class,led1.dev_num);     classs_destroy(led1.class);         cdev_del(&led1.cdev_test);	     //释放设备号     unregister_chrdev_region(led1.dev_num,1); 	     printk("cdv exit\n");     return 0; }     module_init(cdv_init); module_exit(cdv_exit);   MODULE_LICENSE("GPL"); MODULE_AUTHOR("SONG"); MODULE_VERSION("v1.0");

相关内容

热门资讯

裸辞做“一人公司”,我后悔了 去年这个时候,一位以色列程序员正在东南亚旅行。他顺手把一个在脑子里转了很久的想法做成了产品,一个让任...
南京建成国内首个Pre-6G试... 4月21日,2026全球6G技术与产业生态大会在南京开幕。全息互动技术展台前,一名远在北京的工作人员...
超梵求职受邀参加“2025抖音... 超梵求职受邀参加“2025抖音巨量引擎成人教育行业生态大会”,探讨分享优质内容传播,服务万千学员。 ...
摩托罗拉Razr 2026(R... IT之家 4 月 22 日消息,摩托罗拉宣布新一代 Razr 折叠手机将于 4 月 29 日在美国发...
库克卸任,特纳斯领航:苹果新纪... 苹果首席执行官蒂姆·库克将卸任,硬件工程主管约翰·特纳斯将接任,苹果公司今天宣布此事。 库克将在夏季...