历史上的今天
返回首页

历史上的今天

今天是:2025年10月12日(星期日)

正在发生

2022年10月12日 | mini2440驱动分析之LED

2022-10-12 来源:csdn

看LDD3有一段时间了,里面的例程也大部分实践了一下。现在进入真正的驱动程序学习。从友善之臂mini2440提供的驱动程序开始,把一些基本的驱动程序都分析一遍,以提高自己对驱动程序的认识,提高自己的编程能力。下面开始分析友善之臂mini2440提供的led驱动程序,对应文件mini2440_leds.c,内核版本号为2.6.32.2。


1. 模块注册函数

驱动程序作为内核模块出现,首先要做的就是注册自己,也就是在模块初始化中调用一些初始化以及注册函数,下面分析led驱动的模块初始化函数    

static int __init dev_init(void)

{

int ret;


int i;

for (i = 0; i < 4; i++) {

s3c2410_gpio_cfgpin(led_table[i], led_cfg_table[i]);

s3c2410_gpio_setpin(led_table[i], 0);

}


ret = misc_register(&misc);


printk (DEVICE_NAME"tinitializedn");


return ret;

}


这个函数主要调用了三个函数来完成初始化以及注册。首先循环四次调用s3c2410_gpio_cfgpin和s3c2410_gpio_setpin,前一个函数用来配置引脚的功能,后一个函数用来设置引脚的值,这两个函数后面会详细分析。最后调用misc_register注册一个杂项设备,然后输出调试信息。这个misc_register函数是led驱动程序的关键,在后面的杂项设备中再进行分析。当你insmod的时候这个函数被调用,模块就被注册到内核中了。


2. 模块卸载函数

static void __exit dev_exit(void)

{

misc_deregister(&misc);

}


3.功能实现

一个驱动程序要能使硬件正常工作,无非是实现一些read,write,ioctl等一些系统调用方法.当应用程序操作设备文件的时候,调用驱动程序中的这些方法,以实现具体的功能。


下面分析led驱动程序的系统调用方法也就是文件操作。可以看出mini2440的led驱动除了ioctl方法外,其他的方法都没有,就连open都没有。为什么连open这个最基本的必须的系统调用都没有实现,这个和杂项设备有关,因为杂项设备实现了open方法,以后会详细分析。我们看看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);

return 0;

default:

return -EINVAL;

}

}


这个ioctl的实现和我们在ldd3中看到有所不一样,因为没有什么幻数什么的,命令只是简单的0,1。标准的ioctl命令号的确是像ldd3中说的那样要幻数,序数等的,以防止与其他ioctl命令号冲突。这里是为了简单,就用0,1代替了。这里也调用了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);

}


这个函数在arch/arm/plat-s3c24xx/gpio.c中定义,实现了设置引脚值的功能, S3C24XX_GPIO_BASE(pin)这个宏得到具体引脚基地址,S3C2410_GPIO_OFFSET(pin)得到相应引脚的偏移,这个两个宏的实现与s3c2440的寄存器表示以及操作实现有关系,后面再详细分析。


函数有两个参数,一个是引脚,一个是值,引脚传进来的一般是宏像S3C2410_GPB(5)这样的。可以看出操作寄存器的时候采用了读修改写的方式,

__raw_readl(base + 0x04);读取GPIOnDAT的值,这个函数是io内存的底层操作组件,个人认为应该用ldd3中推荐的ioread系列函数

__raw_writel(dat, base + 0x04);将修改的值写入GPIOnDAT,完成修改。


综上所述,led驱动程序的ioctl实现的主要功能,就是根据命令设置led引脚的值,0 熄灭led,1点亮led


5 数据结构

static unsigned long led_table [] = {

S3C2410_GPB(5),

S3C2410_GPB(6),

S3C2410_GPB(7),

S3C2410_GPB(8),

};

        这个是led引脚数组

static unsigned int led_cfg_table [] = {

S3C2410_GPIO_OUTPUT,

S3C2410_GPIO_OUTPUT,

S3C2410_GPIO_OUTPUT,

S3C2410_GPIO_OUTPUT,

};

这个是引脚功能数组,四个引脚都为输出


6. S3C2440  GPIO寄存器表示与操作

(1)S3C24XX_GPIO_BASE(pin)分析  

在reg-gpio.h中,有它的定义

    #define S3C24XX_GPIO_BASE(pin) S3C2410_GPIO_BASE(x)

    #define S3C2410_GPIO_BASE(pin) ((((pin) & ~31) >> 1) + S3C24XX_VA_GPIO)

    pin 是  S3C2410_GPn(_nr)  形式的宏                                                          

    以pin = S3C2410_GPB(5)来分析 S3C2410_GPB(_nr)宏 有如下的定义

    #define S3C2410_GPB(_nr) (S3C2410_GPIO_B_START + (_nr))

    而  S3C2410_GPIO_B_START = S3C2410_GPIO_NEXT(S3C2410_GPIO_A)

    S3C2410_GPIO_NEXT()宏有如下定义

    #define S3C2410_GPIO_NEXT(__gpio) ((__gpio##_START) + (__gpio##_NR) +CONFIG_S3C_GPIO_SPACE + 0)  

    因为      S3C2410_GPIO_A_START=0               

                 S3C2410_GPIO_A_NR=32                

                  CONFIG_S3C_GPIO_SPACE=0

    所以 S3C2410_GPIO_B_START = 32 以此类推S3C2410_GPIO_C_START = 64 。。。

    所以 S3C2410_GPB(_nr) = 32 + _nr 即S3C2410_GPB(5) = 37

    所以 S3C2410_GPIO_BASE(pin) =  (((32+pin) & ~31) >>1) + S3C24XX_VA_GPIO  

    而不管pin是多少,(((32+pin) & ~31) >>1)  算出来的都是16 正好是GPB的控制寄存器的地址偏移量

    S3C24XX_VA_GPIO为GPIO的虚拟基地址

    所以得出结论S3C24XX_GPIO_BASE(pin)得到相关GPIO寄存器的基地址

    所以S3C24XX_GPIO_BASE(S3C2410_GPB(5)) = S3C24XX_VA_GPIO +16  

(2) S3C2410_GPIO_OFFSET(pin)分析

    #define S3C2410_GPIO_OFFSET(pin) ((pin) & 31)

        得出来的就是 pin - 32


        所以   S3C2410_GPIO_OFFSET(S3C2410_GPB(5)) = 37- 32 = 5

(3)s3c2410_gpio_cfgpin分析


这个函数和s3c2410_gpio_setpin 实现方式差不多,只是GPIOA设置引脚功能只有一位,与其他的不同,所以要单独考虑。


7. 总结

刚开始看真正的驱动程序的时候,一些函数的调用总是不习惯,总是想着找的调用的原型,感觉不懂的东西太多了。但是分析了一段时间,慢慢感觉其实也不用那么钻牛角尖,只要明白函数是做什么的就行了,会使用就好,省着自己写函数了。led驱动程序就算最简单的驱动程序了吧,但是真正搞懂还需要杂项设备的知识。接下来学习杂项设备的实现方法。


推荐阅读

史海拾趣

Fractus公司的发展小趣事

为了加速技术的商业化进程,Fractus积极寻求与全球领先企业的合作。自2000年以来,公司陆续与多家知名手机厂商、电信运营商以及设备制造商建立了战略合作关系。这些合作不仅为Fractus带来了稳定的收入来源,也促进了其技术的广泛应用和持续改进。同时,Fractus还通过签订全球许可协议和建立战略伙伴关系,进一步拓展了其业务范围和市场影响力。

CAROLCABLE公司的发展小趣事

在激烈的市场竞争中,CAROLCABLE公司深知技术创新是企业发展的核心动力。因此,公司不断加大研发投入,引进先进的生产设备和技术人才,推动技术创新和产业升级。经过多年的努力,CAROLCABLE成功研发出了一系列具有自主知识产权的高性能线缆产品,这些产品在传输速度、稳定性和耐用性等方面均达到了行业领先水平。

随着产品技术的不断升级,CAROLCABLE开始积极拓展国内外市场。公司参加了多个国际电子线缆展会,与全球同行交流学习,寻找合作机会。同时,CAROLCABLE还加强与国内大型电子企业的合作,为其提供定制化的线缆解决方案。这些举措不仅为公司带来了更多的商机,也进一步巩固了CAROLCABLE在电子线缆行业的领先地位。

这两个故事仅是对CAROLCABLE公司发展起来的简要描述,实际上,公司的成长历程中还有许多值得探讨的细节和里程碑事件。如需了解更多关于CAROLCABLE公司的故事,建议查阅相关新闻报道或公司官方资料。

HCH Co公司的发展小趣事

背景:随着全球经济一体化的加速推进,HCH Co公司意识到必须加快全球化步伐以拓展更广阔的市场空间。公司制定了详细的全球化战略,包括在海外设立研发中心、生产基地和销售网络等。

发展:通过全球化战略的实施,HCH Co公司成功进入了多个国际市场,并与当地的企业和机构建立了紧密的合作关系。公司的品牌影响力不断提升,产品销量也实现了快速增长。同时,全球化战略还为公司带来了更多的技术、人才和市场资源,为公司的长期发展奠定了坚实基础。

昭华(CHA)公司的发展小趣事

为了满足市场的不断增长的需求,昭华公司在2016年成立了昭华智硕东莞工厂。这座工厂拥有先进的生产设备和完善的生产流程,能够大幅提高公司的生产效率和产品质量。同时,昭华公司还不断优化供应链管理,加强与供应商的合作,确保原材料的稳定供应。这些举措不仅提高了公司的产能,还降低了生产成本,增强了公司的市场竞争力。

AMRI Enterprise Co Ltd公司的发展小趣事

面对国内市场的饱和竞争,AMRI Enterprise Co Ltd积极实施国际化战略,拓展海外市场。公司通过参加国际电子展会、建立海外销售渠道等方式,不断提升品牌知名度和产品影响力。同时,AMRI还针对不同国家和地区的市场需求,调整产品策略,提供定制化的解决方案。这一战略的实施,使得AMRI的产品成功打入多个国际市场,实现了业务的快速增长。

Baneasa SA公司的发展小趣事

随着国内市场的逐渐饱和,Baneasa SA开始将目光投向海外市场。公司制定了国际化的发展战略,通过在欧美等发达国家设立分支机构、参加国际展会等方式积极开拓国际市场。这些努力使得Baneasa SA的产品逐渐在国际市场上占据了一席之地,公司的业务范围也得到了进一步扩大。

问答坊 | AI 解惑

二层交换机的实现

本章节是我写的 《嵌入式通信设备开发---基于MPC82xx 》一章的缩略版 请大家给看看 写得如何 可以联系我获取其他章节 给出意见的都有分 文档密码:ads 下载地址: http://download.eeworld.net/source/652607 …

查看全部问答>

wavecom模块短信猫收发短信在高峰期时会丢失串口数据?

如题,根据业务需求,短信猫在规定的时间点开始批量发送短信(可能上百条),各设备在收到查询短信后,会陆续将数据发送给短信猫,会出现以下情况: 1.短信猫在发送AT指令时,同时收到串口短信,这个时候就会报ERROR和设备返回来的短信,短信发送失败,需要重 ...…

查看全部问答>

学习微型计算机系统原理机应用遇到困难

书中提到的8237A 8259A 8253-PIT 8255A 8250 8251A这些片子总觉得不是很熟,不会编程,大家有什么好的建议,能让我掌握他们。有什么好的资料吗? …

查看全部问答>

做过条码采集器系统开发的请进~~~~~~~~~

casio dt900系列采集器 请问这个采集器里的盘点软件用什么开发的?? 有没有相关的开发包或开发工具什么的??? 请给点思路,谢谢先~~~~~~~~~   分不够再加!!…

查看全部问答>

汽车电子电流检测方法及分析

这里主要介绍电流的检测方法,发现设计中容易被忽略的一些因素。首先考虑两种不同的方法:基于磁场的检测方法和基于分流器的检测方法。1.基于磁场的检测方法(以电流互感器和霍尔传感器为代表)具有良好的隔离和较低的功率损耗等优点,在电源驱动技 ...…

查看全部问答>

STM32开发板例程中的Bug

连续几周参加cotex32的研讨会,收获颇多,深感其功能强大,价格低廉,市场广阔,同时也认识了不少业界的朋友。苦于买不起1980的ULINK2(俺是学生,银子少啊),而自己的ULINK又不支持M32,一直没有切身去好好体会它。这周ST巡演,便吐血购入一 ...…

查看全部问答>

在OK6410平台下运行Wince的问题

在Wince中编程程序时调用wcscpy_s函数会提示: 是什么原因啊…

查看全部问答>

ARM Architecture Reference Manual-0001

本文讲述了ARM体系结构。 第一章:CPU体系结构 第二章:存储与系统构架 第三章:浮点运算体系结构…

查看全部问答>

分享经典教程:嵌入式实时操作系统UCOS-II教程(邵贝贝译)

分享经典教程: 嵌入式实时操作系统UCOS-II教程(邵贝贝译)分享经典教程: 嵌入式实时操作系统UCOS-II教程(邵贝贝译)下载地址1:http://zhengoogle.qjwm.com/down_2900170.html下载地址2:http://www.ctdisk.com/file/6375533…

查看全部问答>

CSS初学者求指点

CSS在使用的时候需要设置什么么?一般的是怎么设置的?…

查看全部问答>