一、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;
}
上一篇:QEMU模拟FriendlyArm的Mini2440开发板
下一篇:内核裁剪,arm_mini2440开发板中增删自己写的驱动
设计资源 培训 开发板 精华推荐
- ADA4637-1ARZ-R7带保护反相放大器的典型应用电路
- 【广西师大校赛】任意波形发生器
- LF25CPT-TR 2.5V 超低压降稳压器的典型应用
- L78L12AC正压稳压器Edit boost电路的典型应用
- LT8631EFE 400kHz、12V/250mA、3.3V/2.5A 双路降压转换器的典型应用电路
- AD8627ARZ-REEL单极输出精密放大器典型应用电路
- SILINKPS-EVB,用于电缆调制解调器应用的 Si3225 用户线接口的评估板
- LTC2239IUH 演示板,高速 ADC,VDD = +3.0V,80Msps,10 位 1MHz
- LT1078 的典型应用 - 微功率、双路、单电源、精密运算放大器
- OM13560: PTN3356评估板