Linux设备驱动开发详解:基于最新的Linux4.0内核
上QQ阅读APP看书,第一时间看更新

1.6 设备驱动Hello World:LED驱动

1.6.1 无操作系统时的LED驱动

在嵌入式系统的设计中,LED一般直接由CPU的GPIO(通用可编程I/O)口控制。GPIO一般由两组寄存器控制,即一组控制寄存器和一组数据寄存器。控制寄存器可设置GPIO口的工作方式为输入或者输出。当引脚被设置为输出时,向数据寄存器的对应位写入1和0会分别在引脚上产生高电平和低电平;当引脚设置为输入时,读取数据寄存器的对应位可获得引脚上的电平为高或低。

在本例子中,我们屏蔽具体CPU的差异,假设在GPIO_REG_CTRL物理地址中控制寄存器处的第n位写入1可设置GPIO口为输出,在地址GPIO_REG_DATA物理地址中数据寄存器的第n位写入1或0可在引脚上产生高或低电平,则在无操作系统的情况下,设备驱动见代码清单1.3。

代码清单1.3 无操作系统时的LED驱动

 1 #define reg_gpio_ctrl *(volatile int *)(ToVirtual(GPIO_REG_CTRL))
 2 #define reg_gpio_data *(volatile int *)(ToVirtual(GPIO_REG_DATA))
 3 /* 初始化LED */
 4 void LightInit(void)
 5 {
 6   reg_gpio_ctrl |= (1 << n); /* 设置GPIO为输出 */
 7 }
 8
 9 /* 点亮LED */
10 void LightOn(void)
11 {
12   reg_gpio_data |= (1 << n); /* 在GPIO上输出高电平 */
13 }
14
15 /* 熄灭LED */
16 void LightOff(void)
17 {
18   reg_gpio_data &= ~(1 << n); /* 在GPIO上输出低电平 */
19 }

上述程序中的LightInit()、LightOn()、LightOff()都直接作为驱动提供给应用程序的外部接口函数。程序中ToVirtual()的作用是当系统启动了硬件MMU之后,根据物理地址和虚拟地址的映射关系,将寄存器的物理地址转化为虚拟地址。