Linux下GPIO驅(qū)動詳解文章_第1頁
Linux下GPIO驅(qū)動詳解文章_第2頁
Linux下GPIO驅(qū)動詳解文章_第3頁
Linux下GPIO驅(qū)動詳解文章_第4頁
Linux下GPIO驅(qū)動詳解文章_第5頁
已閱讀5頁,還剩6頁未讀, 繼續(xù)免費閱讀

下載本文檔

版權說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權,請進行舉報或認領

文檔簡介

1、打 算 跟 著 友 善 之 臂 的 mini2440 Linux 移 植 開 發(fā) 指 南 見 來做個 LED 驅(qū)動,雖然 LED 的原理簡單 得不能再簡單了,但是要把 kernel 中針對于 s3c24* 的 GPIO 的一些數(shù)據(jù)結(jié)構(gòu),還有函數(shù)搞 清楚也不是那么輕松的事,所以本文主要簡單地說明下 LED 驅(qū)動中的相關數(shù)據(jù)結(jié)構(gòu)以及函 數(shù)/宏的定義,并對驅(qū)動加以驗證*注意:在 /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)該函數(shù)直接使用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) 結(jié)束后,四個 LED 應該是 全部都是發(fā)光96 狀態(tài)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 可以看到,這里涉及到兩個函數(shù),分別是 s3c2410_gpio_cfgpin,s3c2410_gpio_setpin ,這兩個 函數(shù)分別對四個 LED 進行配置, 從函數(shù)名來看, cfgpin 對引腳寄存器狀態(tài)進行配置, 而 setpin 應該是對寄存器數(shù)據(jù)值進行配置,我們在分析函數(shù)之前先弄清楚傳入的參數(shù)到底是什么。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 是內(nèi)核配置選項,在 .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 個數(shù) +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 對應端口將要輸出的狀態(tài)列表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 */ *根據(jù)前面的分析, s3c2410 傳入了當前 GPIO 的偏移地址,以及 OUTPUT 狀態(tài)現(xiàn)在我們深入前面的兩個函數(shù):定義在 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 結(jié)構(gòu)體首指針,里面包含了該 GPIO 的各種參數(shù)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 狀態(tài)寄存器的數(shù)值為 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 是一個函數(shù)指針,由后面的分析知道,如果針對GPA, 該函數(shù)指針指向s3c_gpio_setcfg_s3c24xx_a , 如果針對 G

18、PX 應該是指向 s3c_gpio_setcfg_s3c24xx 但發(fā)現(xiàn), 如果是其 他 GPX, 根本沒有 定義 set_config! (這個問題 已經(jīng)解決,見后 文 s3c24xx_gpiolib_init 函數(shù),事實上,其余的 config 的確指向 s3c_gpio_do_setcfg 函數(shù))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 狀態(tài)是否為 (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這里涉及到了一個重要的數(shù)據(jù)結(jié)構(gòu), s3c_gpio_chip ,此數(shù)據(jù)結(jié)構(gòu)比較復雜,我貼出這個數(shù)據(jù) 結(jié)構(gòu)的結(jié)構(gòu)圖:這個重要的數(shù)據(jù)結(jié)構(gòu)中可以記錄每個 GPIO 所需要的所有數(shù)據(jù), 后面會遇到的 s3c24xx_gpios 結(jié)構(gòu)體就是該結(jié)構(gòu)體的集合, 描述了芯片中所有的 GPIO 端口, 之后我們需要時時回頭看看 這個結(jié)構(gòu)。我們先來

22、看 s3c_gpiolib_getchip ,它實現(xiàn)了返回對應 pin 值的 GPIO 結(jié)構(gòu)體首指針的功能#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;/根據(jù)偏移,計算出對應 pin 的 GPI0 結(jié)構(gòu)體指針return (pin - chip-chip.b

23、ase) chip.ngpio) ? chip : NULL;/ 這里驗證,如果 pin 偏移超過了 GPI0 的個數(shù),說明出錯了,否則就返回該 GPI0 的結(jié)構(gòu)體指針回想以下之前 s3c2410_gpio_cfgpin 中,我們傳入的參數(shù)是 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 的函數(shù)指針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. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
  • 4. 未經(jīng)權益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負責。
  • 6. 下載文件中如有侵權或不適當內(nèi)容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論