Openwrt开发指南 第19章 驱动开发之LED驱动程序

开发环境:
主机:ubuntu12.04
开发板:rt5350
openwrt:openwrt15.05
1 硬件原理
图1
由于发光二级管单向导电特性,即只有在正向电压(二极管的正极接正,负极接负)下才能导通发光。如图所示,如果 gpio 输出高电平,led 就会被点亮,如果 gpio 输出低电平,led 就会熄灭。对于我们的驱动开发,无论是单片机、还是 arm、或者是我们的 mips,核心思想,都是读写某个地址,即操作某个寄存器。
2 寄存器介绍rt5350 一共有 28 个 gpio 管脚,这 28 个 gpio,除了 gpio0,其他全部是与其他功能引脚复用的。
表1
gpio1、gpio2 与 i2c 复用。
表2
gpio3~6 与 spi 复用。
表3
gpio7~14,与 uartf 即串口 2 复用。
这些复用关系,都可以通过查阅 rt5350 的芯片手册得到。
而这些复用功能, 我们可以通过 gpiomode 寄存器来进行选择, 通过查手册得知,gpiomode寄存器的地址为 0x10000060。
表4
gpiomode 寄存器 bit0 位用于选择 gpio1、gpio2 对应的引脚是用于 iic 总线,还是用于gpio。
gpiomode 寄存器 bit1 位用于选择 gpio3~6 对应的引脚用于 spi 总线,还是用于 gpio。
gpiomode 寄存器 bit2~4 位用于选择 uartf 对应的引脚工作于哪个模块,具体定义如下。
表5
从该表格可以看出,uartf 对应的引脚,可以工作于 uartf、pcm、i2s、gpio 四种模式,将 gpiomode 寄存器 bit24 位设置为相应的值,就能让这些引脚工作于相应的模式,比如将gpiomode 寄存器 bit24 位的值设置为 7,则让相应的引脚工于 gpio 模式。
当将相应的引脚设置为 gpio 以后,我们接下来就需要操作该 gpio 了,操作 gpio 不外乎就是设置 gpio 是输入还是输出、让其输出高电平还是低电平、读取其电平状态。不管是哪种操作,都有对应的寄存器。
表6
gpio21_00_dir 寄存器,用于设置 gpio0~21 的方向,当相应的位被设置为 1,则表示相应的 gpio 管脚被设置为了输出,如果被设置为了 0,则相应的 gpio 引脚就被设置为了输入。
表7
当相应 gpio 引脚被设置为输出时,设置 gpio21_00_data 寄存器的相应位为 1,则让该gpio 引脚输出了高电平,如果设置 gpio21_00_data 寄存器的相应位为 0,则让该 gpio 引脚输出了低电平。
当相应 gpio 引脚被设置为输入时,则通过读取 gpio21_00_data 寄存器时,就能读取相应的 gpio 引脚的状态。
关于更多的 gpio 操作的寄存器介绍,请自行查阅手册。
3 编写驱动程序我们通过前面章节的学习,掌握了驱动程序的框架,接下来我们就来写一个驱动程序,实现操作 gpio25、gpio26 两个 gpio 引脚。具体驱动实现如下。
#include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #define myleds_led1_on 0#define myleds_led1_off 1#define myleds_led2_on 2#define myleds_led2_off 3volatile unsigned long *gpiomode;volatile unsigned long *gpio27_22_dir;volatile unsigned long *gpio27_22_data;static struct class *myleds_class;static int myleds_open(struct inode *inode, struct file *file){/* 让 gpio#25、gpio#26 输出高电平,同时熄灭 led1、led2 */*gpio27_22_data &= ~((1< <3)|(1< <4));return 0;}static long myleds_unlocked_ioctl(struct file *file, unsigned int cmd, unsigned long arg){switch(cmd){case myleds_led1_on:// 点亮 led1*gpio27_22_data |= (1< <3);break;case myleds_led1_off: // 熄灭 led1*gpio27_22_data &= ~(1< <3);break;case myleds_led2_on:// 点亮 led2*gpio27_22_data |= (1< <4);break;case myleds_led2_off: // 熄灭 led2*gpio27_22_data &= ~(1< <4);break;default:break;}return 0;}/* 1.分配、设置一个 file_operations 结构体 */static struct file_operations myleds_fops = {.owner = this_module, /* 这是一个宏,推向编译模块时自动创建的__this_module 变量 */.open = myleds_open,.unlocked_ioctl = myleds_unlocked_ioctl,};int major;static int __init myleds_init(void){/* 2.注册 */major = register_chrdev(0, myleds, &myleds_fops);/* 3.自动创建设备节点 *//* 创建类 */myleds_class = class_create(this_module, myleds);/* 类下面创建设备节点 */device_create(myleds_class, null, mkdev(major, 0), null, myleds); ///dev/myleds/* 4.硬件相关的操作 *//* 映射寄存器的地址 */gpiomode = (volatile unsigned long *)ioremap(0x10000060, 4);gpio27_22_dir = (volatile unsigned long *)ioremap(0x10000674, 4);gpio27_22_data = (volatile unsigned long *)ioremap(0x10000670, 4);/* 设置相应管脚用于 gpio *//*** led1 ---- gpio#25** led2 ---- gpio#26*/*gpiomode |= (0x1< <14);/* 将 gpio#25、gpio#26 设置为输出 */*gpio27_22_dir = (1< <3)|(1< other modules --- > kmod-myleds
图2
然后我们就能看到我们的驱动程序的选项了 kmod-myleds,将它配置成m,也可以便已进入内核。最后,退出保存。然后再执行编译命令。
make v=99编译完成以后,就能在源码目录下的bin/ramips/packages/base目录下看到我们的内核模块驱动程序的软件包 kmod-myleds_3.18.109-1_ramips_24kec.ipk。
19.6 动态的加载和卸载内核驱动模块软件包通过前面的努力,我们终于得到了我们自己的内核驱动模块软件包了。接下来就来使用它。首先将 kmod-myleds_3.18.109-1_ramips_24kec.ipk 软件包传到开发板上面。然后使用 opkg install 命令来安装软件包。
opkg install kmod-myleds_3.18.109-1_ramips_24kec.ipk
使用 opkg list 命令来查看已经安装了哪些软件包。这里是否执行该命令都无所谓。接下来进入我们的/lib/modules/3.18.109目录,就能看到我们的驱动程序模块了。
cd lib/modules/3.18.109/
接下来就通过 insmod 命令来装载驱动模块。
insmod myleds.ko驱动安装成功以后,我们就能看到 gpio 驱动对应的设备节点了。


独立变量分析与高光谱植被指数模型监测水稻中砷污染
焊接材料对焊点有什么基本要求?
如何通过ApiFox来构建 API 场景测试
PLC案例三相异步电动机顺序启动逆序停止控制
4路电话光端机的作用与性能特点介绍
Openwrt开发指南 第19章 驱动开发之LED驱动程序
VR的成长速度远比我们想象中的要快——LUCI immers头戴测评
光伏系统运维—组件的除尘除雪
【EsDA 应用】Modbus RTU Master 转 UDP Client
共同探讨AI+技术将带来怎样的发展,对数据发展产生怎样的推动力
详解负载电阻的原理和应用
ad620的放大倍数是怎么计算的
XSX外接存储方案的各种移动硬盘的游戏加载速度测试
业界第一颗 Versal ACAP 到达 Xilinx 之后发生了什么?
中国首次利用VR技术返回案发现场 可视化系统体现四效
电子镇流器中的电磁干扰抑制措施解析
电动化和可再生能源的利用将成为低碳交通的未来发展方向
红米Note4X首开箱:能把骁龙625打造成最具性能的只有它
ETAP无功补偿(4)如何在ETAP中进行最佳电容器位置分析
【工程师开发板使用测评】爱普特 APT32F110 ev board 试用测评连载05