嵌入式軟件就是某一項目的源碼文件集合,源碼文件的數(shù)量,根據(jù)項目復(fù)雜程度的不同而有規(guī)模和層次的差別。
就拿簡單的一個芯片廠商提供的demo來說,代碼也會被細分到寄存器操作(Drv層)、板級支持包接口(Bsp層)、功能模塊驗證(App層)等各層,但是這里的“分層”很多時候都不太明顯,因為它僅僅是個demo,所謂的“分層”更多的還是人為給它做的定義。
真正意義的分層,是從代碼的編碼規(guī)范、程序的執(zhí)行邏輯來體現(xiàn)的。
關(guān)于分層設(shè)計的意義在這暫不做太多的探討,只是做個引子,來講講SPI接口的設(shè)計過程,如何設(shè)計一套擁有自己規(guī)范和方便移植的SPI接口。
SPI在分層架構(gòu)中的設(shè)計思路
剛剛提到分層設(shè)計的思路,那么SPI作為一個通信接口,如果按照分層設(shè)計的思路,如何把接口設(shè)計得更合理,更方便?
此處需要設(shè)計的SPI是介于“應(yīng)用”和“驅(qū)動”之間的,“應(yīng)用”就是項目業(yè)務(wù)需求的功能模塊將數(shù)據(jù)、數(shù)據(jù)包等傳給SPI接口,而“驅(qū)動”是SPI接口拿到數(shù)據(jù)包后,把數(shù)據(jù)轉(zhuǎn)變?yōu)镾PI的時序發(fā)送出去。
當我們拿到一款芯片,大多數(shù)情況下官方提供的demo程序已經(jīng)給我們實現(xiàn)好了很多的驅(qū)動(或者自己從網(wǎng)絡(luò)資源中Download),各個接口的驅(qū)動,已經(jīng)被封裝成函數(shù)或者庫供我們直接調(diào)用。
想象一下我們的項目工程,如果需要操作芯片硬件接口的時候,直接調(diào)用官方提供的接口函數(shù),雖然能實現(xiàn)功能,但是在需要更換芯片平臺的時候,就需要在繁雜的、與業(yè)務(wù)需求相關(guān)的應(yīng)用層里找和去修改為目標驅(qū)動接口。
這里就牽扯到了分層設(shè)計的優(yōu)勢所在:由于平臺的更換,驅(qū)動接口已經(jīng)變了樣,那么對代碼的移植就會變得非常費力,不僅是腦力活,更是體力活(即使可以批量替換,你也需要仔細核對接口,更要解決接口的差異性)。
而此時如果是分層設(shè)計的,在應(yīng)用和驅(qū)動中間有個BSP層,應(yīng)用層調(diào)用的只是BSP層,完全不涉及驅(qū)動、寄存器,不涉及與芯片平臺相關(guān)的接口,那么即使平臺怎么更換、驅(qū)動怎么改變,你只需要改變BSP層的具體實現(xiàn),相對就輕松很多了。
從上一篇《嵌入式硬件通信接口協(xié)議-SPI(一)協(xié)議基礎(chǔ)》對SPI協(xié)議的介紹,設(shè)計BSP層的時候,根據(jù)SPI可配置項來設(shè)計接口功能。設(shè)計BSP層的SPI功能函數(shù)時考慮接口模式、數(shù)據(jù)寬度、時鐘極性與相位、時鐘速率、數(shù)據(jù)bit位大小端選擇、管腳定義。
設(shè)計BSP層時,首先想到的是接口初始化和數(shù)據(jù)收發(fā)。設(shè)計初始化,把SPI可配置項放在函數(shù)接口,作參數(shù)傳遞;設(shè)計數(shù)據(jù)收發(fā),傳數(shù)據(jù)的同時也把SPI端口號作為參數(shù)之一,因為我們都知道MCU可能會有多個SPI接口,將SPI端口號作為參數(shù)也是比較必要。
SPI接口本身就是可以實現(xiàn)1對N的串行總線,為什么在使用過程中有時要分別使用不同的SPI端口來接不同的外圍器件呢?
主要原因是SPI的可配置項的不一致,有些外圍器件對SPI時鐘信號SCLK的極性要求為高、低不一樣,時鐘相位不一樣,并且通信數(shù)據(jù)bit位大小端選擇的不一樣,這些接口配置項的差異,導(dǎo)致了有些場景下操作不同器件時需要使用不同的SPI端口。
SPI時序使用IO引腳模擬
從零開始設(shè)計自有的一套SPI板級支持包(BSP)接口,那就從初始化開始。這里設(shè)計的是模擬SPI,所以會調(diào)用GPIO設(shè)置的接口。
當前使用的芯片平臺是STM32F103系列,雖然此時已經(jīng)完全可以調(diào)用官方的StdPeriphDrivers V3.5.0版本的標準外設(shè)庫。調(diào)用接口庫不是目的,成為“調(diào)庫俠”其實很簡單。此處重新寫的模擬實現(xiàn)方式,旨在說明在BSP層,實現(xiàn)自有系統(tǒng)的軟件架構(gòu),為系統(tǒng)集成提供底層接口。同時也是在深入學(xué)習(xí)和了解SPI接口的時序特性。
初始化函數(shù)接口里暫時做了SPI端口號、數(shù)據(jù)寬度、接口時鐘模式、數(shù)據(jù)位優(yōu)先模式這四個參數(shù),基本上這四個參數(shù)已經(jīng)可以完成對大部分應(yīng)用需求。在編碼初期先不急于填入過多的配置項,首先按照最簡單的默認方式編碼,保證程序邏輯可以跑通。
其中用到的管腳定義,是在完成原理圖或者完成原型機驗證時,基本就確定了管腳的使用,因此管腳的定義一般的都是放在BSP層的頭文件中。這樣更便于移植和開發(fā)。
數(shù)據(jù)發(fā)送時,先寫發(fā)送一個字節(jié)的數(shù)據(jù),數(shù)據(jù)是“踩”著SPI接口時鐘信號SCLK的“節(jié)拍”逐個bit位發(fā)送出去,因此在發(fā)送數(shù)據(jù)的時候也是需要主機操作時鐘信號SCLK和數(shù)據(jù)信號MOSI:
SPI的數(shù)據(jù)發(fā)送接口dcbsp_spi_sendbyte函數(shù)實現(xiàn)了將1個字節(jié)的數(shù)據(jù)通過GPIO輸出,實現(xiàn)了SPI接口的時序,其中關(guān)鍵的是SCLK信號輸出、1字節(jié)數(shù)據(jù)的移位輸出、SCLK信號做延時輸出脈沖。
而發(fā)送多數(shù)據(jù)的接口就可以采用dcbsp_spi_sendbyte函數(shù)來逐字節(jié)發(fā)送完成。
另外接收數(shù)據(jù)的接口,同樣參考著字節(jié)發(fā)送接口的思路,數(shù)據(jù)的接收過程也是“踩”著SPI接口時鐘信號SCLK的“節(jié)拍”逐個bit位傳輸,這個過程主機繼續(xù)提供SCLK,然后讀取MISO信號的電平,再將讀到的電平逐bit緩存在一個變量里:
就這樣,利用GPIO進行電平的輸出的讀取,實現(xiàn)了SPI接口的部分時序。這些接口的內(nèi)部實現(xiàn)過程,因人而異、因平臺變化而微調(diào),但是對外接口不動,對上層應(yīng)用來說,這就是同一個接口同一個東西,上層的應(yīng)用層程序改動就很小了。
對于每次移植,BSP層提供了一定架構(gòu)接口,層次清晰改動小,所以對于一個嵌入式開發(fā)者而言,寫好BSP層也很重要。
總結(jié),本文主要想分享的是設(shè)計嵌入式軟件時,分出BSP層,作為應(yīng)用和驅(qū)動的中間層,以便于在項目移植過程中,應(yīng)用的完美匹配。文中的代碼未完,關(guān)于驅(qū)動類的代碼,其執(zhí)行結(jié)果必須在示波器等儀器下觀測,仍需確認執(zhí)行的效率和時序的實現(xiàn)效果!
-
嵌入式
+關(guān)注
關(guān)注
5152文章
19670瀏覽量
317509
發(fā)布評論請先 登錄
嵌入式常見的通信接口/協(xié)議有哪些?
嵌入式分層架構(gòu)的相關(guān)資料分享
為何要進行嵌入式軟件架構(gòu)設(shè)計?如何設(shè)計?
對嵌入式系統(tǒng)中的架構(gòu)設(shè)計的理解
嵌入式系統(tǒng)串口通信分層結(jié)構(gòu)設(shè)計與實現(xiàn)
嵌入式硬件通信接口協(xié)議中的串行通信接口-SPI

嵌入式常見的通信接口/協(xié)議

嵌入式分層概括總結(jié)

嵌入式硬件通信接口協(xié)議-SPI(一)協(xié)議基礎(chǔ)

評論