主页 > 软件开发  > 

驱动day2字符设备驱动LED亮灯

驱动day2字符设备驱动LED亮灯

可参考arm点灯C语言 cortex-A7核 点LED灯 (附 汇编实现、使用C语言 循环实现、使用C语言 封装函数实现【重要、常用】)-CSDN博客

1 应用程序 test.c #include <stdio.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include <unistd.h> #include <string.h> int main(int argc, char const *argv[]) { char buf[128]={0}; int fd = open("/dev/mychrdev",O_RDWR); if(fd < 0) { printf("打开设备文件失败\n"); return -1; } printf("打开设备文件成功\n"); while(1) { printf("请输入要进行的操作:0(关灯) 1(开灯) >>> "); fgets(buf,sizeof(buf),stdin);//在终端读一个字符串 buf[strlen(buf) - 1] = '\0'; write(fd, buf, sizeof(buf));//将数据传递给内核 } close(fd); return 0; } 2 头文件head.h #ifndef __HEAD_H__ #define __HEAD_H__ //GPIOE #define PHY_LED1_MODER 0X50006000 #define PHY_LED1_ODR 0x50006014 //GPIOF #define PHY_LED2_MODER 0X50007000 #define PHY_LED2_ODR 0x50007014 //RCC #define PHY_RCC 0x50000A28 #endif 3 驱动程序 demo.c #include <linux/init.h> #include <linux/module.h> #include <linux/fs.h> #include <linux/uaccess.h> #include <linux/io.h> #include "head.h" unsigned int major; char kbuf[128] = {}; //定义三个指针指向映射后的虚拟内存 unsigned int *vir_moder_E; unsigned int *vir_odr_E; unsigned int *vir_moder_F; unsigned int *vir_odr_F; unsigned int *vir_rcc; //封装操作方法 int mycdev_open(struct inode *inode, struct file *file) { printk("%s:%s:%d\n",__FILE__,__func__,__LINE__); return 0; } ssize_t mycdev_read(struct file *file, char *ubuf, size_t size,loff_t *lof) { printk("%s:%s:%d\n",__FILE__,__func__,__LINE__); int ret; ret = copy_to_user(ubuf,kbuf,size); if (ret) { printk("copy_to_user filed\n"); return -EIO; } return 0; } ssize_t mycdev_write(struct file *file, const char *ubuf, size_t size,loff_t *lof) { printk("%s:%s:%d\n",__FILE__,__func__,__LINE__); int ret; ret = copy_from_user(kbuf,ubuf,size); if (ret) { printk("copy_from_user filed\n"); return -EIO; } if(kbuf[0] == '0') //关灯 { //关灯逻辑 (*vir_odr_E) &= (~(0x1 << 10)); //LED1默认关灯 (*vir_odr_F) &= (~(0x1 << 10)); //LED2默认关灯 (*vir_odr_E) &= (~(0x1 << 8)); //LED3默认关灯 } else if(kbuf[0] == '1') //开灯 { //开灯逻辑 (*vir_odr_E) |= (0x1 << 10); //LED1 (*vir_odr_F) |= (0x1 << 10); //LED2 (*vir_odr_E) |= (0x1 << 8); //LED3 } return 0; } int mycdev_close(struct inode *inode, struct file *file) { printk("%s:%s:%d\n",__FILE__,__func__,__LINE__); return 0; } //定义操作方法结构体对象 struct file_operations fops = { .open = mycdev_open, .read = mycdev_read, .write = mycdev_write, .release = mycdev_close, }; static int __init mycdev_init(void) { //注册字符设备驱动 major = register_chrdev(0,"mychrdev",&fops); if(major < 0) { printk("字符设备驱动注册失败\n"); return major; } printk("字符设备驱动注册成功major=%d\n",major); //进行寄存器的地址映射 //GPIOE vir_moder_E = ioremap(PHY_LED1_MODER,4); if(vir_moder_E == NULL) { printk("物理内存地址映射失败%d\n",__LINE__); return -EFAULT; } vir_odr_E = ioremap(PHY_LED1_ODR,4); if(vir_odr_E == NULL) { printk("物理内存地址映射失败%d\n",__LINE__); return -EFAULT; } //GPIOF vir_moder_F = ioremap(PHY_LED2_MODER,4); if(vir_moder_F == NULL) { printk("物理内存地址映射失败%d\n",__LINE__); return -EFAULT; } vir_odr_F = ioremap(PHY_LED2_ODR,4); if(vir_odr_F == NULL) { printk("物理内存地址映射失败%d\n",__LINE__); return -EFAULT; } //RCC vir_rcc = ioremap(PHY_RCC,4); if(vir_rcc == NULL) { printk("物理内存地址映射失败%d\n",__LINE__); return -EFAULT; } printk("寄存器内存映射成功\n"); //LED1寄存器初始化 (*vir_rcc) |= (0x1 << 4); //GPIOE控制器时钟使能 (*vir_moder_E) &= (~(0x3 << 20)); //MODER[21:20]->00 (*vir_moder_E) |= (0x1 << 20); //MODER[21:20]->01 (*vir_odr_E) &= (~(0x1 << 10)); //默认关灯 //LED2寄存器初始化 (*vir_rcc) |= (0x1 << 5); //GPIOF控制器时钟使能 (*vir_moder_F) &= (~(0x3 << 20)); //MODER[21:20]->00 (*vir_moder_F) |= (0x1 << 20); //MODER[21:20]->01 (*vir_odr_F) &= (~(0x1 << 10)); //默认关灯 //LED3寄存器初始化 (*vir_rcc) |= (0x1 << 4); //GPIOE控制器时钟使能 (*vir_moder_E) &= (~(0x3 << 16)); //MODER[17:16]->00 (*vir_moder_E) |= (0x1 << 16); //MODER[17:16]->01 (*vir_odr_E) &= (~(0x1 << 8)); //默认关灯 return 0; } static void __exit mycdev_exit(void) { //取消内存映射 iounmap(vir_moder_E); iounmap(vir_odr_E); iounmap(vir_moder_F); iounmap(vir_odr_F); iounmap(vir_rcc); //注册字符设备驱动 unregister_chrdev(major,"mychrdev"); } module_init(mycdev_init); module_exit(mycdev_exit); MODULE_LICENSE("GPL");

编写好代码后,make成arm架构

make arch=arm modname=demo

使用交叉编译工具链

arm-linux-gnueabihf-gcc test.c 

将文件通过tftp传输到开发板中

cp demo.ko ~/nfs/rootfs/ cp a.out ~/nfs/rootfs/

4 效果呈现

标签:

驱动day2字符设备驱动LED亮灯由讯客互联软件开发栏目发布,感谢您对讯客互联的认可,以及对我们原创作品以及文章的青睐,非常欢迎各位朋友分享到个人网站或者朋友圈,但转载请说明文章出处“驱动day2字符设备驱动LED亮灯