開篇分割線,再研究驅(qū)動程序之前我們先看下RTT 關(guān)于SPI應(yīng)用的代碼層級結(jié)構(gòu):
應(yīng)用層:只做應(yīng)用層開發(fā)的小伙伴是有福的,你不需要了解整個驅(qū)動是怎樣構(gòu)架的,只需要了解驅(qū)動構(gòu)架層提供的API接口函數(shù)直接調(diào)用,即可操作SPI設(shè)備。
設(shè)備驅(qū)動框架層:由RTT系統(tǒng)提供的一個重要的中間層,用于驅(qū)動層和應(yīng)用層之間聯(lián)系的建立,對應(yīng)用層開放API調(diào)用接口,對驅(qū)動層開放注冊函數(shù)和操作函數(shù),將驅(qū)動層的操作注冊到系統(tǒng)中,實(shí)現(xiàn)應(yīng)用與驅(qū)動之間的軟連接。
總線設(shè)備驅(qū)動層:該層是驅(qū)動開發(fā)工程師的主攻戰(zhàn)場,后面展開詳細(xì)講。
硬件SPI控制器層:一般情況下就是MCU自帶的控制外設(shè),這里當(dāng)然就是SPI控制器,玩過單片機(jī)的小伙伴最熟悉的部分。
外掛模塊層:最后一層就是SPI類型總線通信設(shè)備的模塊,常用的flash芯片、網(wǎng)絡(luò)控制模塊等都生活在這一層,實(shí)際電路中通過SPI通信線與MCU連接。
接下來就是看下基于STM32開發(fā)SPI的設(shè)備模型(模型即結(jié)構(gòu)體定義)了,代碼如下:
/* stm32 spi dirver class */
struct stm32_spi
{
SPI_HandleTypeDef handle;
struct stm32_spi_config *config;
struct rt_spi_configuration *cfg;
struct
{
DMA_HandleTypeDef handle_rx;
DMA_HandleTypeDef handle_tx;
} dma;
rt_uint8_t spi_dma_flag;
struct rt_spi_bus spi_bus;
};
這里需要注意的是,模型的最后一個成員spi_bus,它是由RTT系統(tǒng)提供,有了它這個模型就與系統(tǒng)之間產(chǎn)生了聯(lián)系,spi_bus是系統(tǒng)的一個SPI類型硬件設(shè)備模型。 有了模型以后,我們就是針對這個模型進(jìn)行設(shè)備的實(shí)例化,一般來講MCU會有多個SPI控制器,所以針對這一情況,我們就定義了另一個模型專門用于實(shí)例化SPI對象模型:
struct stm32_spi_config
{
SPI_TypeDef *Instance; /*SPI外設(shè)*/
char *bus_name; /*SPI總線設(shè)備名稱*/
struct dma_config *dma_rx, *dma_tx; /*DMA發(fā)送及接收配置參數(shù)*/
};
接下來需要采用預(yù)處理命令宏定義硬件外設(shè)所有的SPI設(shè)備配置項(xiàng),至于是否開啟我們可以通過rt_config.h文件是否定義該宏來決定:
#ifdef BSP_USING_SPI1
#ifndef SPI1_BUS_CONFIG
#define SPI1_BUS_CONFIG \
{ \
.Instance = SPI1, \
.bus_name = "spi1", \
}
#endif /* SPI1_BUS_CONFIG */
#endif /* BSP_USING_SPI1 */
#ifdef BSP_USING_SPI2
#ifndef SPI2_BUS_CONFIG
#define SPI2_BUS_CONFIG \
{ \
.Instance = SPI2, \
.bus_name = "spi2", \
}
#endif /* SPI2_BUS_CONFIG */
#endif /* BSP_USING_SPI2 */
有了設(shè)備配置模型,就需要定義一個真實(shí)的需要配置的設(shè)備模型數(shù)據(jù),用于實(shí)例化多個SPI控制器,實(shí)際上就一個數(shù)組搞定:
static struct stm32_spi_config spi_config[] =
{
#ifdef BSP_USING_SPI1
SPI1_BUS_CONFIG,
#endif
#ifdef BSP_USING_SPI2
SPI2_BUS_CONFIG,
#endif
};
有了設(shè)備類型模型,也有了配置模型數(shù)組,就需要定義通過模型來定義真實(shí)的設(shè)備實(shí)例,定義完并沒有進(jìn)行初始化:
/*定義SPI總線對象*/
static struct stm32_spi spi_bus_obj[sizeof(spi_config) / sizeof(spi_config[0])] = {0};
到這里,關(guān)于SPI總線對象的創(chuàng)建就完了,但是關(guān)于SPI總線對象還是一個空空如也的數(shù)組,我想你也應(yīng)該知道如何基于配置對象給總線對象進(jìn)行初始化,當(dāng)然這個我們下篇接著講。