编写LED驱动-传统
写LED驱动
首先,我们要建立一个file_operator结构体:
/* 定义自己的file_operations结构体 */ static struct file_operations led_drv = { .owner = THIS_MODULE, //主设备号 .open = led_drv_open, // driver function .read = led_drv_read, .write = led_drv_write, .release = led_drv_close, };
接下来要配置GPIO的地址:
/*指定引脚的基地址 */ static unsigned int gpio_base[] = { 0x56000000; /*GPIOA*/ 0x56000010; /*GPIOB*/ .........; } // 这里是确定GPIOE的第n个引脚 #define IMX6ULL_GPE(n) (5<<16 | n) //查找GPIO基地址:
编写相应的四个driver function:
static volatile unsigned int *gpio_con; // 将引脚配置为输出引脚
static volatile unsigned int *gpio_dat; // 设置高低电平
static int led_pin = IMX6ULL_GPE(5);
/* 3. 实现对应的open/read/write等函数,填入file_operations结构体 */ static ssize_t led_drv_read (struct file *file, char __user *buf, size_t size, loff_t *offset) { printk("%s %s line %d\n", __FILE__, __FUNCTION__, __LINE__); return 0; } /* write(fd, &val, 1); */ static ssize_t led_drv_write (struct file *file, const char __user *buf, size_t size, loff_t *offset) { int err; usigned char status;
int pin = pin_bin * 0xffff; printk("%s %s line %d\n", __FILE__, __FUNCTION__, __LINE__); err = copy_from_user(&status, buf, 1); // 将用户空间传入到值传入到kernel if(err){
return -1;
}
if(status){
/*点灯*/
*gpio_data &= ~(1<<pin);
}else{
/*灭灯*/
*gpio_data |= (1<<pin);
}
return 1; } static int led_drv_open (struct inode *node, struct file *file) {
int bank = led_pin >> 16;
int bass = gpio_bas[bank]; // 这里不太清楚宏定义的意思
int pin = led_pin & 0xFFFF;
gpio_con = ioremap(bass, 8); // 在bass基地址映射8(1024),size只映射空间的大小,这里是以page为单位,8<1024,也是一个page的大小
gpio_dat = gpio_con + 1;
*gpio_con |= (1<<pin*2); // 这里是相关寄存器配置,因为要配置GPIO5--[11:10]为output---01
return 0; } static int led_drv_close (struct inode *node, struct file *file) { printk("%s %s line %d\n", __FILE__, __FUNCTION__, __LINE__);
ioumap(gpio_con) return 0; }
注册filer_operator: 告诉CPU
static int myled_init(void) { major = register_chrdev(0, "myled", &myled_oprs); return 0; } static void myled_exit(void) { unregister_chrdev(major, "myled"); }
module_init(myled_init); //这里是为了告诉内核,入口函数是什么
module_exit(myled_exit);
退出
[Ctrl+Enter快捷键提交]
· 记一次 Visual Studio 2022 卡死分析
· 异常体系与项目实践
· .NET 通过源码深究依赖注入原理
· [趣话计算机底层技术]一个故事看懂各种锁
· 记一次 .NET 某医院门诊软件 卡死分析
· 为什么有了 HTTP 还要 RPC
· 【源码解读】asp.net core源码启动流程精细解读
· 我写了本开源书:《3D编程模式》
· 游戏前端工作流程总结
· IntelliJ IDEA一站式配置【全】(提高开发效率)