立即学习:https://edu.csdn.net/course/play/9511/202394?utm_source=blogtoedu
- 传统方式:驱动框架+硬件操作函数驱动框架:static struct file_operations myled_oprs ;static int myled_init(void);static void myled_exit(void);module_init(myled_init);module_exit(myled_exit);MODULE_LICENSE("GPL");硬件操作(在led_open里把对应的引脚设置成输出引脚,在led_write里根据应用层传入的数据来点灯让该引脚输出低电平或高电平):static int led_open (struct inode *node, struct file *filp);static ssize_t led_write (struct file *filp, const char __user *buf, size_t size, loff_t *off);static int led_release (struct inode *node, struct file *filp);
- GPACON:控制寄存器
- 在linux驱动程序里,不能直接操纵物理地址,要把基地址映射为虚拟地址。
- gpio_con用来把引脚配置成输出引脚;gpio_dat用来设置引脚为高电还是低电。
- 映射:gpio_con = ioremap(base, 8);gpio_dat = gpio_con + 1;
- 物理地址相差4,虚拟地址也相差4
- 设置为输出引脚:*gpio_con &= ~(3<<(pin * 2));
*gpio_con |= (1<<(pin * 2)); - copy_from_user(&val, buf, 1);这个函数是用来把用户空间传来buf里面的值拷贝到内核状态
- 点灯(输出低电平):*gpio_dat &= ~(1<<pin);gpio_dat清上某一位左移多少
- 注册驱动程序之后,我们想要让系统自动的创建设备节点,static struct class *led_class;并且在上边创建一个设备,class和设备都是一些虚拟的概念。
有了这些信息之后,可以通过open /dev/led 来设置这些灯led_class = class_create(THIS_MODULE, "myled"); device_create(led_class, NULL, MKDEV(major, 0), NULL, "led"); /* /dev/led */