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

发布者:会飞的笨鱼最新更新时间:2020-05-22 来源: eefocus关键字:mini2440  驱动程序  LED驱动  Linux-2  6 手机看文章 扫描二维码
随时随地手机看文章

一、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;

}

关键字:mini2440  驱动程序  LED驱动  Linux-2  6 引用地址:【重温经典】mini2440驱动程序之LED驱动(基于Linux-2.6.32.2)

上一篇:QEMU模拟FriendlyArm的Mini2440开发板
下一篇:内核裁剪,arm_mini2440开发板中增删自己写的驱动

小广播
设计资源 培训 开发板 精华推荐

最新单片机文章
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

换一换 更多 相关热搜器件
更多往期活动

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved