版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
1、打 算 跟 着 友 善 之 臂 的 mini2440 Linux 移 植 开 发 指 南 见 来做个 LED 驱动,虽然 LED 的原理简单 得不能再简单了,但是要把 kernel 中针对于 s3c24* 的 GPIO 的一些数据结构,还有函数搞 清楚也不是那么轻松的事,所以本文主要简单地说明下 LED 驱动中的相关数据结构以及函 数/宏的定义,并对驱动加以验证*注意:在 /arch/arm/mach-s3c2410/include/mach/gpio-fns.h 源代码中有如下说明:16/* These functions are in the to-be-removed category
2、and it is strongly17 * encouraged not to use these in new code. They will be marked deprecated18 * very soon.19 *20 * Most of the functionality can be either replaced by the gpiocfg calls21 * for the s3c platform or by the generic GPIOlib API.22 *23 * As of 2.6.35-rc, these will be removed, with the
3、 few drivers using them24 * either replaced or given a wrapper until the calls can be removed.25*/该头文件包括:static inline void s3c2410_gpio_cfgpin(unsigned int pin, unsigned int cfg)该函数直接使用linux/arch/arm/plat-s3c/gpio-config.c 中的int s3c_gpio_cfgpin(unsigned int pin, unsigned int config)即可*首先看一下设备初始化程序:
4、85 /*86 * 设备初始化87 */88 static int _init dev_init(void)89 90 int ret;91 int i;92 for (i = 0; i 4; i+) 93 /设置 LED 对应的端口寄存器为输出 (OUTPUT)94 if (s3c_gpio_cfgpin(led_tablei, led_cfg_tablei) 结束后,四个 LED 应该是 全部都是发光96 状态97 s3c2410_gpio_setpin(led_tablei, 0);98 99 ret = misc_register(&misc); / 注册设备100 printk (D
5、EVICE_NAME/tinitialized/n); / 打印初始化信息101 return ret;102 可以看到,这里涉及到两个函数,分别是 s3c2410_gpio_cfgpin,s3c2410_gpio_setpin ,这两个 函数分别对四个 LED 进行配置, 从函数名来看, cfgpin 对引脚寄存器状态进行配置, 而 setpin 应该是对寄存器数据值进行配置,我们在分析函数之前先弄清楚传入的参数到底是什么。led_tablei28 /LED 对应的 GPIO 端口列表29 static unsigned long led_table = 30S3C2410_GPB(5),3
6、1S3C2410_GPB(6),32S3C2410_GPB(7),33S3C2410_GPB(8),34 ;这里 S3C2410_GPB 宏定义在 mach/gpio-nrs.h 中/* GPIO bank sizes */#define S3C2410_GPIO_A_NR (32)#define S3C2410_GPIO_B_NR (32)#define S3C2410_GPIO_C_NR (32)#define S3C2410_GPIO_D_NR (32)#define S3C2410_GPIO_E_NR (32)#define S3C2410_GPIO_F_NR (32)#define
7、S3C2410_GPIO_G_NR (32)#define S3C2410_GPIO_H_NR (32)#define S3C2410_GPIO_J_NR (32) /* technically 16. */ #define S3C2410_GPIO_K_NR (32) /* technically 16. */ #define S3C2410_GPIO_L_NR (32) /* technically 15. */ #define S3C2410_GPIO_M_NR (32) /* technically 2. */#if CONFIG_S3C_GPIO_SPACE != 0#error C
8、ONFIG_S3C_GPIO_SPACE cannot be zero at the moment #endif#define S3C2410_GPIO_NEXT(_gpio) /(_gpio#_START) + (_gpio#_NR) + CONFIG_S3C_GPIO_SPACE + 0)/这里的 CONFIG_S3C_GPIO_SPAC 是内核配置选项,在 .config 中可以找到,我的配置为:CONFIG_S3C_GPIO_SPACE = 0 enum s3c_gpio_number S3C2410_GPIO_A_START = 0, S3C2410_GPIO_B_START = S
9、3C2410_GPIO_NEXT(S3C2410_GPIO_A), S3C2410_GPIO_C_START = S3C2410_GPIO_NEXT(S3C2410_GPIO_B), S3C2410_GPIO_D_START = S3C2410_GPIO_NEXT(S3C2410_GPIO_C), S3C2410_GPIO_E_START = S3C2410_GPIO_NEXT(S3C2410_GPIO_D), S3C2410_GPIO_F_START = S3C2410_GPIO_NEXT(S3C2410_GPIO_E), S3C2410_GPIO_G_START = S3C2410_GPI
10、O_NEXT(S3C2410_GPIO_F), S3C2410_GPIO_H_START = S3C2410_GPIO_NEXT(S3C2410_GPIO_G), S3C2410_GPIO_J_START = S3C2410_GPIO_NEXT(S3C2410_GPIO_H), S3C2410_GPIO_K_START = S3C2410_GPIO_NEXT(S3C2410_GPIO_J), S3C2410_GPIO_L_START = S3C2410_GPIO_NEXT(S3C2410_GPIO_K), S3C2410_GPIO_M_START = S3C2410_GPIO_NEXT(S3C
11、2410_GPIO_L), ;#define S3C2410_GPB(_nr) (S3C2410_GPIO_B_START + (_nr)因此,以 S3C2410_GPB(5) 为例,其宏展开为:S3C2410_GPIO_NEXT(S3C2410_GPIO_A) +5 =(S3C2410_GPIO_A_START + S3C2410_GPIO_A_NR +CONFIG_S3C_GPIO_SPACE + 0) +5 =很显然, S3C2410_GPB(5) 就是从 GPA 的首地址 +GPA 个数 +GPB 的 offset 就是当前 GPB 的 IO 偏移量,即0+32+5=37, 同理S3C
12、2410_GPB(0) 相当于 3230S3C2410_GPB(5)相当于3731S3C2410_GPB(6)相当于3832S3C2410_GPB(7)相当于3933S3C2410_GPB(8)相当于40*led_cfg_tablei36 /LED 对应端口将要输出的状态列表37 static unsigned int led_cfg_table = 38 S3C2410_GPIO_OUTPUT,39 S3C2410_GPIO_OUTPUT,40 S3C2410_GPIO_OUTPUT,41 S3C2410_GPIO_OUTPUT,42 ;S3C2410_GPIO_OUTPUT 定义在 mac
13、h/regs-gpio.h#define S3C2410_GPIO_LEA VE (0xFFFFFFFF) / 最后两位是设置, 11 表示 RESERVE#define S3C2410_GPIO_INPUT (0xFFFFFFF0) /* not available on A */ 最后两位是(0xFFFFFFF1)设置, 00 表示 INPUT #define S3C2410_GPIO_OUTPUT/ 最后两位是设置, 01 表示 OUTPUT#define S3C2410_GPIO_IRQ (0xFFFFFFF2) /* not available for all */#define S
14、3C2410_GPIO_SFN2 (0xFFFFFFF2) /* bank A = addr/cs/nand */ #define S3C2410_GPIO_SFN3 (0xFFFFFFF3) /* not available on A */ *根据前面的分析, s3c2410 传入了当前 GPIO 的偏移地址,以及 OUTPUT 状态现在我们深入前面的两个函数:定义在 linux/arch/arm/plat-s3c/gpio-config.cint s3c_gpio_cfgpin(unsigned int pin, unsigned int config)struct s3c_gpio_ch
15、ip *chip = s3c_gpiolib_getchip(pin);/ 得到对应 GPIO 结构体首指针,里面包含了该 GPIO 的各种参数unsigned long flags;int offset;int ret;if (!chip)return -EINVAL; / 没找到的话,返回 invalidoffset = pin - chip-chip.base;/ 否则 offset 等于该 GPIO 引脚相对于 GPX( 0)的偏移量,每个偏移 1s3c_gpio_lock(chip, flags); / 自旋锁锁住该 GPIO ,通过 chip 指针指向 lock, 看下面的 def
16、ine 和图ret = s3c_gpio_do_setcfg(chip, offset, config); / 设置该 GPIO 状态寄存器的数值为 config s3c_gpio_unlock(chip, flags); / 解锁/ 自旋锁操作/* locking wrappers to deal with multiple access to the same gpio bank */ /#define s3c_gpio_lock(_oc, _fl) spin_lock_irqsave(&(_oc)-lock, _fl) /#define s3c_gpio_unlock(_oc, _fl)
17、 spin_unlock_irqrestore(&(_oc)-lock, _fl)/s3c_gpio_do_setcfg 操作static inline int s3c_gpio_do_setcfg(struct s3c_gpio_chip *chip, unsigned int off, unsigned int config)return (chip-config-set_config)(chip, off, config);/这里的 set_config 是一个函数指针,由后面的分析知道,如果针对GPA, 该函数指针指向s3c_gpio_setcfg_s3c24xx_a , 如果针对 G
18、PX 应该是指向 s3c_gpio_setcfg_s3c24xx 但发现, 如果是其 他 GPX, 根本没有 定义 set_config! (这个问题 已经解决,见后 文 s3c24xx_gpiolib_init 函数,事实上,其余的 config 的确指向 s3c_gpio_do_setcfg 函数)struct s3c_gpio_cfg s3c24xx_gpiocfg_default = .set_config = s3c_gpio_setcfg_s3c24xx,.get_config = s3c_gpio_getcfg_s3c24xx, ;int s3c_gpio_setcfg_s3c2
19、4xx_a(struct s3c_gpio_chip *chip, unsigned int off, unsigned int cfg) void _iomem *reg = chip-base;/ GPXCON 的物理基地址unsigned int shift = off; u32 con;/ 每个 GPA 对应一位if (s3c_gpio_is_cfg_special(cfg) /OUTPUT 状态是否为 (0xfffffffX) ,是,返回 1 cfg &= 0xf; / cfg = 0xX/* Map output to 0, and SFN2 to 1 */ 本实验不会运行到这cf
20、g -= 1;if (cfg 1)return -EINV AL;cfg = shift;con = _raw_readl(reg); con &= (0x1 base;unsigned int shift = off * 2;/ 每个 GPX 对应 2 位u32 con;if (s3c_gpio_is_cfg_special(cfg) cfg &= 0xf;if (cfg 3) return -EINV AL;cfg = shift; / 将 cfg 的 0,1 两位左移 offset con = _raw_readl(reg); con &= (0x3 shift); con |= cfg
21、;_raw_writel(con, reg);/ 读对应的 GPXCON 值/ 将 GPXCON (pin)的两 bits 请 0 / 设置 config 值/ 写入新的 GPXCONreturn 0; return ret; / end s3c_gpio_cfgpin这里涉及到了一个重要的数据结构, s3c_gpio_chip ,此数据结构比较复杂,我贴出这个数据 结构的结构图:这个重要的数据结构中可以记录每个 GPIO 所需要的所有数据, 后面会遇到的 s3c24xx_gpios 结构体就是该结构体的集合, 描述了芯片中所有的 GPIO 端口, 之后我们需要时时回头看看 这个结构。我们先来
22、看 s3c_gpiolib_getchip ,它实现了返回对应 pin 值的 GPIO 结构体首指针的功能#includestatic inline struct s3c_gpio_chip *s3c_gpiolib_getchip(unsigned int pin)struct s3c_gpio_chip *chip;if (pin S3C_GPI0_END)如果超过 GPJ(32)就 return NULLreturn NULL;chip = &s3c24xx_gpiospin/32;/根据偏移,计算出对应 pin 的 GPI0 结构体指针return (pin - chip-chip.b
23、ase) chip.ngpio) ? chip : NULL;/ 这里验证,如果 pin 偏移超过了 GPI0 的个数,说明出错了,否则就返回该 GPI0 的结构体指针回想以下之前 s3c2410_gpio_cfgpin 中,我们传入的参数是 led_tablei 和 led_cfg_tablei ,/* GPI0 sizes for various SoCs:* 2442* 2410 2412 2440 2443 2416* A 2322251625* B 11 11 11 11 9* C 1615161616* D 1616161616* E 1616161616* F 88888* G1
24、61616168* H 111191515* J -1316-* K -16* L -157* M -22*/ struct s3c_gpio_chip s3c24xx_gpios = 0 = .base = S3C2410_GPACON, / datasheet 上地址为 0x56000000/#define S3C2410_GPACONS3C2410_GPIOREG(0x00)#define S3C2410_GPIOREG(x) (x) + S3C24XX_V A_GPIO)#define S3C24XX_V A_GPIO (S3C24XX_PA_GPIO - S3C24XX_PA_UAR
25、T) S3C24XX_VA_UART)S3C24XX_PA_GPIO 相当于 (0x15600000)S3C24XX_PA_UART 相当于 (0x15000000)#define S3C_VA_UART S3C_ADDR(0x01000000) /* UART */#define S3C_ADDR_BASE 0xF6000000#ifndef _ASSEMBL Y_#define S3C_ADDR(x) (void _iomem _force *)S3C_ADDR_BASE + (x) #else#define S3C_ADDR(x) (S3C_ADDR_BASE + (x)#endif0x
26、15600000-15000000+F7000000 这里的 S3C2410_GPACON 应该怎么算?.pm = _gpio_pm(&s3c_gpio_pm_1bit),.config = &s3c24xx_gpiocfg_banka,/ 设置 GPIO 的函数指针static struct s3c_gpio_cfg s3c24xx_gpiocfg_banka = .set_config = s3c_gpio_setcfg_s3c24xx_a,.get_config = s3c_gpio_getcfg_s3c24xx_a,;.chip = .base = S3C2410_GPA(0), /基
27、地址,也是偏移量 .owner = THIS_MODULE,.label = GPIOA, .ngpio = 24,.direction_input = s3c24xx_gpiolib_banka_input, .direction_output = s3c24xx_gpiolib_banka_output, ,1 = .base = S3C2410_GPBCON,.pm = _gpio_pm(&s3c_gpio_pm_2bit),.chip = .base = S3C2410_GPB(0), .owner = THIS_MODULE, .label = GPIOB, .ngpio = 16,
28、 ,2 = .base = S3C2410_GPCCON,.pm = _gpio_pm(&s3c_gpio_pm_2bit),.chip = .base = S3C2410_GPC(0), .owner = THIS_MODULE, .label = GPIOC, .ngpio = 16, ,3 = .base = S3C2410_GPDCON,.pm = _gpio_pm(&s3c_gpio_pm_2bit),.chip = .base = S3C2410_GPD(0), .owner = THIS_MODULE, .label = GPIOD, .ngpio = 16, ,4 = .bas
29、e = S3C2410_GPECON,.pm = _gpio_pm(&s3c_gpio_pm_2bit),.chip = .base = S3C2410_GPE(0),.label = GPIOE, .owner = THIS_MODULE,.ngpio = 16, ,5 = .base = S3C2410_GPFCON,.pm = _gpio_pm(&s3c_gpio_pm_2bit),.chip = .base = S3C2410_GPF(0),.owner = THIS_MODULE,.label = GPIOF, .ngpio = 8, .to_irq = s3c24xx_gpiolib_bankf_toirq, ,6 = .base = S3C241
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 现代学生餐厅的照明与色彩搭配艺术
- 深度解读网络舆情的来源与影响研究报告解读分享
- 现代金融行业中的移动支付技术与教育普及
- 快手国庆节的活动方案
- 国庆假期活动方案
- 国庆节酒店涨价活动方案
- 2、3、4的乘法口诀(说课稿)-2024-2025学年二年级上册数学人教版
- Unit1 There is a horse in this photo(说课稿)-2024-2025学年外研版(三起)四年级上册001
- 17《他们那时候多有趣啊》(说课稿)-2023-2024学年统编版语文六年级下册
- 13 我能行(说课稿)-统编版(五四制)道德与法治二年级下册
- 春节后复工安全教育培训考试试题及答案
- 寄宿制学校工作总结
- 小学数学6年级应用题100道附答案(完整版)
- 2024年江苏农牧科技职业学院单招职业适应性测试题库含答案
- JT-T 1495-2024 公路水运危险性较大工程专项施工方案编制审查规程
- JT-T-390-1999突起路标行业标准
- 人教版二年级上册加减混合计算300题及答案
- 2023年四川省成都市武侯区中考物理二诊试卷(含答案)
- 《也是冬天-也是春天》
- 鲜切水果行业分析
- 第7章-无人机法律法规
评论
0/150
提交评论