1.GPIO接口設計思想
1.1CoX.GPIO發(fā)展過程,歷史版本
typedef struct {
} COX_PIO_PI_Def;
typedef const COX_PIO_PI_Def COX_PIO_PI;
這樣的實現(xiàn),確實可以大大減小IO操作的移植,因為我們在每個廠商實現(xiàn)一套API,以新唐為例:
COX_PIO_PI pi_pio =
{
};
在使用的時候,我們僅僅需要使用pi_pio的指針就可以調(diào)用GPIO的API操作了,而且這個指針還可以被驅(qū)動嵌套使用。有興趣的可以參考NUC140-LB Board的CoOS例程,這個在www.coocox.org官網(wǎng)可以下載到。
然而,第一版有幾個明顯的不足:
1. 實現(xiàn)的功能很少,只有IO的基本配置和讀寫操作,沒有外部中斷實現(xiàn),沒有多功能配置實現(xiàn),以及一些其他特殊的功能。
2. 采用了結(jié)構(gòu)體的形式,代碼的可讀性大大降低,效率也不高。
3. CoX代碼不能搞定所有基本的事情,在使用CoX庫的使用還必須和廠商庫配套使用。
4. CoX在第一版更多的注重外設模塊的移植,而忽略了系統(tǒng)。
1.2通用強制接口
通用強制接口是提取的一套ARM Cortex M0/M3所有廠商系列MCU都具有的功能接口。本篇以新唐M051為例講解CoX.GPIO,其他系列大同小異, 提取GPIO通用接口的時候,是從以下角度出發(fā)考慮的:
u 配置一個GPIO管腳線
l 方向配置:
n 輸入
n 輸出
n 硬件功能
l 外圍功能配置:
l Pad配置:
n 驅(qū)動能力大小(電流)
n 開源/推挽
n 弱上拉/下拉電阻
u GPIO管腳數(shù)據(jù)控制
l 輸出高/低電平
l 獲取管腳輸入值
u 輸入中斷(EXTI)
l 上升沿檢測
l 下降沿檢測
l 上/下沿檢測
l 低電平檢測
l 高電平檢測
APIs分組完成以下幾大功能:
u 配置GPIO管腳線的函數(shù):
l xGPIODirModeSet
l xGPIOSPinDirModeSet
l xGPIOPinConfigure
u 讀回GPIO管腳線模式配置的函數(shù):
l xGPIODirModeGet
u 還有很方便的函數(shù),可以將GPIO配置成想要的功能:
l xGPIOSPinTypeGPIOInput
l xGPIOSPinTypeGPIOOutput
l xSPinTypeADC
l xSPinTypeI2C
l xSPinTypeSPI
l xSPinTypeTimer
l xSPinTypeUART
l xSPinTypeACMP
u 處理GPIO中斷的APIs
l xGPIOPinIntCallbackInit
l xGPIOPinIntEnable
l xGPIOSPinIntEnable
l xGPIOPinIntDisable
l xGPIOSPinIntDisable
l xGPIOPinIntStatus
l xGPIOPinIntClear
l xGPIOSPinIntClear
u 處理GPIO Pin狀態(tài)的APIs
l xGPIOPinRead
l xGPIOSPinRead
l xGPIOPinWrite
l xGPIOSPinWrite
1.3通用非強制接口
l xGPIOSPinTypeGPIOOutputO D
l xGPIOSPinTypeGPIOOutputQ B
l xSPinTypePWM
l xSPinTypeEXTINT
l xSPinTypeEBI
CoX的宏定義的參數(shù)和APIs都是以' x '開頭的, 體現(xiàn)出CoX接口的特征。比如將 GPIOA Pin0配置成輸出模式, 代碼如下:
xGPIODirModeSet(xGPIO_PORTA_BASE, xGPIO_PIN_0, xGPIO_DIR_MODE_OUT);
函數(shù)和形式參數(shù)都是x開頭。
1.4廠商庫特色接口
特色接口是包括了通用性接口,和MCU特有功能的接口。比如:
void GPIOPinDebounceEnable(unsigned long ulPort, unsigned long ulPins);并不是通用強制型或者通用非強制型,而是MCU特有的功能,就是在廠商庫特色接口這一組。
另外廠商庫接口也實現(xiàn)了MCU其他所有的功能,比如:
void GPIOPinWrite(unsigned long ulPort, unsigned long ulPins,
也實現(xiàn)了GPIO管腳線模式的配置,這個在CoX接口的xGPIOPinWrite也是這個功能。其實這個時候xGPIOPinWrite的實現(xiàn)方式如下:
#define xGPIOPinWrite(ulPort, ulPins, ucVal) \
進行了一次宏定義包裝罷了,對應的參數(shù)也是進行的一次宏定義比如:
#define xGPIO_PIN_0 GPIO_PIN_0
2.設計技巧簡介
GPIO的CoX接口創(chuàng)新性的提出了Short Pin,比如PA0 是GPIOA的Pin0腳,它的定義如下:
#define PA0 PA0
自從有了Short Pin之后,對GPIO的操作簡單多了,例如比如將GPIOA Pin0配置成輸出模式,并輸出高電平, 代碼如下:
xGPIODirModeSet(xGPIO_PORTA_BASE, xGPIO_PIN_0, xGPIO_DIR_MODE_OUT);
xGPIOPinWrite(xGPIO_PORTA_BASE, xGPIO_PIN_0, 1);
現(xiàn)在用Short Pin作為參數(shù),上面的功能可以這樣實現(xiàn):
xGPIOSPinTypeGPIOOutput(PA0);
xGPIOSPinWrite(PA0, 1);
上面的Short Pin到底是如何實現(xiàn)的呢?看起來很神奇,以xGPIOSPinWrite為例說明它的實現(xiàn)過程:
#define xGPIOSPinWrite(eShortPin, ucVal) \
#define GPIOSPinWrite(eShortPin, ucVal) \
關于##, 其實是宏定義里面的高級用法,它是一個連接符,遇到此連接符,宏會一直展開下去,直到不能展開為止。G##eShortPin其實會連接為GPA0,而GPA0同樣是個宏定義,如下:
#define GPA0 GPIO_PORTA_BASE, GPIO_PIN_0
GPIOPinWrite(GPA0, ucVal)會進一步展開為
GPIOPinWrite(GPIO_PORTA_BASE, GPIO_PIN_0, ucVal),這個函數(shù)在廠商庫里面定義了的,所以實現(xiàn)了Pin寫的功能。
另外Short Pin對GPIO管腳的外設多功能復用操作也帶來了極大的方便,比如配置PD5為I2C的clock腳功能,如下:
xSPinTypeI2C(I2C0SCK, PD5);
是不是很簡單!!!上面的實現(xiàn)如下:
#define xSPinTypeI2C(ePeripheralPin, eShortPin) \
do \
{ \
} \
while(0)
#define GPIOSPinConfigure(ePeripheralPin, eShortPin) \
#define GPIO_PD5_I2C0SCK
這個是根據(jù)多功能復用進行的編碼,視不同的芯片,這個編碼方式靈活多變。
還有一些接口完全是為了移植方便性而產(chǎn)生的,比如xGPIOSPinToPort, 這個接口是由Short Pin就可以得到這個Pin所對應的PORT Base,而在CoX.SYSCTL中有一個接口xSysCtlPeripheralEnable2是使用外設地址Base為參數(shù)使能這個外設(在SYSCTL中維護了一個外設BASE-ID-INT的表),它實現(xiàn)的時候,是進行了一個Base到外設ID的一個轉(zhuǎn)換,最終還是調(diào)用xSysCtlPeripheralEnable使能外設的。但是有了這個功能,也很利于基于CoX驅(qū)動組件的移植性,例如在AD7415溫度傳感器是通過I2C接口進行數(shù)據(jù)通信的,在這個驅(qū)動組件頭文件中, 只需要考慮一下四個元素就可以平滑的使得這個驅(qū)動組件移植到其他的MCU上(比如NUC1xx,或者STM32F1xx):
