最近要深一步用到GPIO口控制,寫個部落格記錄下Kernel層的GPIO學習過程!
一、概念
General Purpose Input Output (通用輸入/輸出)簡稱為GPIO,或 總線擴充器。也就是晶片的引腳,當微控制器或晶片組沒有足夠的I/O端口,或當系統需要采用遠端串行通信或控制時,GPIO産品能夠提供額外的控制和監視功能。通常在ARM裡,所有I/O都是通用的,
每個GPIO端口包含8個管腳,如PA端口是PA0~PA7,而且GPIO口至少有兩個寄存器,即"通用IO控制寄存器"與"通用IO資料寄存器"。資料寄存器的各位都直接引到晶片外部,而對這種寄存器中每一位的作用,即每一位的信号流通方向,則可以通過控制寄存器中對應位獨立地加以設定。比如,可以設定某個引腳的屬性為輸入、輸出或其他特殊功能。
常用的應該是:高阻輸入、推挽輸出、開漏輸出。
通俗了解為 :
高阻輸入—— 保持高阻抗狀态,徹底斷開輸出,避免幹擾,對總線狀态不起作用,此時總線可由其他器件占用。
推挽輸出——可以輸出高,低電平,連接配接數字器件。
開漏輸出——輸出端相當于三極管的集電極. 要得到高電平狀态需要上拉電阻才行。
軟體上就是通過設定IO口的模式,然後控制IO的上拉下拉,寫入對應寄存器,通過寄存器控制電路:
上拉寄存器是控制對應端口上拉使能(DE)的。當對應位為0時,設定對應引腳上拉使能,為1時,禁止對應引腳上拉使能。如果上拉寄存器使能,無論引腳功能寄存器如何設定(輸入,輸出,資料,中斷等),對應引腳輸出高電平。
上拉是一個電阻接到一個電壓,其實就是增強IO的驅動能力,IO口是高電平。
下拉是一個電阻接到地,保證IO口是低電平。
二、kernel層調用接口實作
GPIO操作,在Kernel 2.6.32版本以上提供了gpio口管理的庫檔案/kernel/drivers/gpio/gpiolib.c,裡面就是我們需要的接口函數實作!
幾個主要的方法:
申請一個pin腳作為gpio口,命名為 * label,如果經過判斷空閑的 申請成功了做一些初始的bit位設定。
釋放這個gpio口,還原bit。
設定gpio口為輸入模式:
其中的chip->direction_input(chip, gpio)為實作!
設定gpio口為輸出模式 value為初始值 0為高電平/1為低電平:
其中的chip->direction_output(chip, gpio, value)為實作!
設定gpio口的值:
擷取gpio口的值:
對于有些挂載在I2C,SPI總線上的擴充GPIO,讀寫操作可能會導緻睡眠,是以不能在中斷函數中
使用。使用下面的函數以差別于正常的GPIO
三、gpiolib.c關聯晶片接口
以上為gpiolib.c的基本方法都是向下調用到對應晶片的gpio實作!
是以每個方法裡面的實作都是通過 struct gpio_chip*chip 這個指針調用結構體中關聯的相關接口!
下面是gplolib怎麼關聯到特定的晶片(mach-at91)的幾個主要方法:
mach-at91的/kernel/arch/arm/mach-at91/gpio.c中的
gpiolib.c中的接口與mach-at91函數接口對應關系如下:
從上面可以看到 在gpiolib.c中的方法調用晶片(mach-at91)的映射關系:
比如:gpio_direction_output() 設定gpio口為輸出模式中最終的實作調用chip->direction_output(chip, gpio, value)。
從上面可以看出來,也就是調用mach-at91的at91_gpiolib_direction_output()!
其它的類似。
gpiolib.c中的
添加到結構體:
這就儲存到了 chip 指針。
這一部分在Kernel初始化的時候調用執行!
四、晶片(mach-at91)gpio口的接口
由gpiolib.c根據映射調用對應接口
定義為輸出模式,初始設定val 上拉還是下拉 , 寫入資料寄存器。
同樣設定為輸入:
設定GPIO口的value 值 0或者1,已經設定為輸出模式下:
讀寄存器擷取該GPIO口的值:
大體流程就這樣了。