300字范文,内容丰富有趣,生活中的好帮手!
300字范文 > 【重温经典】mini2440驱动程序之LED驱动(基于Linux-2.6.32.2)

【重温经典】mini2440驱动程序之LED驱动(基于Linux-2.6.32.2)

时间:2018-08-25 19:47:15

相关推荐

【重温经典】mini2440驱动程序之LED驱动(基于Linux-2.6.32.2)

版权声明:本文为博主(宽简厚重,Yuesichiu)原创文章,未经博主允许。

/yuesichiu/article/details/81459946

一、LED资源介绍

1、LED对应的GPIO(已上拉)

LED1 nLED1 GPB5

LED2 nLED2 GPB6

LED3 nLED3 GPB7

LED4 nLED4 GPB8

2、硬件电路

二、驱动代码(mini2440_leds.c)

以混杂设备注册,主要实现了ioctl接口,应用程序操作时,只需要打开这个设备文件,然后发一个ioctl的命令就会进入到内核空间,接着调用该驱动的ioctl函数来设置相应的状态。

(1)、设置GPIO为输出模式

for (i = 0; i < 4; i++) {s3c2410_gpio_cfgpin(led_table[i], led_cfg_table[i]); //配置文件输出模式s3c2410_gpio_setpin(led_table[i], 0);//输出低电平,点亮4个GPIO}

GPIO的s3c2410_gpio_cfgpin函数中的第二个参数S3C2410_GPIO_OUTPUT(值为0xFFFFFFF1,即高31:4为1,3:1为0,最低位为1),通过查看s3c2410_gpio_cfgpin得知,设置了GPIO对应的位为01,是代表输出模式,这个可以从s3c2440芯片手册上GPIO寄存器得知:

这里贴一下s3c2410_gpio_cfgpin函数的实现:

void s3c2410_gpio_cfgpin(unsigned int pin, unsigned int function){void __iomem *base = S3C24XX_GPIO_BASE(pin);unsigned long mask;unsigned long con;unsigned long flags;if (pin < S3C2410_GPIO_BANKB) {mask = 1 << S3C2410_GPIO_OFFSET(pin);} else {mask = 3 << S3C2410_GPIO_OFFSET(pin)*2;}switch (function) {case S3C2410_GPIO_LEAVE:mask = 0;function = 0;break;case S3C2410_GPIO_INPUT:case S3C2410_GPIO_OUTPUT:case S3C2410_GPIO_SFN2:case S3C2410_GPIO_SFN3:if (pin < S3C2410_GPIO_BANKB) {function -= 1;function &= 1;function <<= S3C2410_GPIO_OFFSET(pin);} else {function &= 3;function <<= S3C2410_GPIO_OFFSET(pin)*2;}}/* modify the specified register wwith IRQs off */local_irq_save(flags);con = __raw_readl(base + 0x00);con &= ~mask;con |= function;__raw_writel(con, base + 0x00);local_irq_restore(flags);}

(2)、编写ioctl接口

static int sbc2440_leds_ioctl(struct inode *inode,struct file *file,unsigned int cmd,unsigned long arg){switch(cmd) {case 0:case 1:if (arg > 4) {return -EINVAL;}s3c2410_gpio_setpin(led_table[arg], !cmd); //注意,应用程序设为on(GPIO输出高电平)状态时,即驱动程序输出低电平;应用程序设为off(GPIO输出低电平)状态时,即驱动程序输出高电平,因为该硬件电路(上拉)决定。return 0;default:return -EINVAL;}}

另外设置和读取GPIO pin的函数为s3c2410_gpio_getpin/s3c2410_gpio_setpin。

s3c2410_gpio_getpin的函数实现为:

unsigned int s3c2410_gpio_getpin(unsigned int pin){void __iomem *base = S3C24XX_GPIO_BASE(pin);unsigned long offs = S3C2410_GPIO_OFFSET(pin);return __raw_readl(base + 0x04) & (1<< offs);}

s3c2410_gpio_setpin的函数实现为:

void s3c2410_gpio_setpin(unsigned int pin, unsigned int to){void __iomem *base = S3C24XX_GPIO_BASE(pin);unsigned long offs = S3C2410_GPIO_OFFSET(pin);unsigned long flags;unsigned long dat;local_irq_save(flags);dat = __raw_readl(base + 0x04);dat &= ~(1 << offs);dat |= to << offs;__raw_writel(dat, base + 0x04);local_irq_restore(flags);}

我们注意到访问s3c2440的GPIO寄存器使用__raw_readl/__raw_writel函数,也就是直接访问GPIO寄存器。

static inline u32 __raw_readl(const volatile void __iomem *addr){return *(const volatile u32 __force *) addr;}static inline void __raw_writel(u32 b, volatile void __iomem *addr){*(volatile u32 __force *) addr = b;}

版权声明:本文为博主(宽简厚重,Yuesichiu)原创文章,未经博主允许。

/yuesichiu/article/details/81459946

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。