本章開(kāi)始,先新建一個(gè)基于野火STM32全系列(包含M3/4/7)開(kāi)發(fā)板的的RT-Thread的工程模板,讓RT-Thread先跑起來(lái)。以后所有的RT- Thread相關(guān)的例程我們都在此模板上修改和添加代碼,不用再反反復(fù)復(fù)地新建。
1. 獲取STM32的裸機(jī)工程模板
STM32的裸機(jī)工程模板我們直接使用野火STM32開(kāi)發(fā)板配套的固件庫(kù)例程即可。這里我們選取比較簡(jiǎn)單的例 程—“GPIO輸出—使用固件庫(kù)點(diǎn)亮LED”作為裸機(jī)工程模板。該裸機(jī)工程模板均可以在對(duì)應(yīng)板子的A盤/程序源碼 /固件庫(kù)例程的目錄下獲取到,下面以野火F103-霸道板子的光盤目錄為例,具體見(jiàn)圖 STM32裸機(jī)工程模板在光盤資料中的位置。

2. 下載RT-Thread Nano 源碼
Nano是Master的精簡(jiǎn)版,去掉了一些組件和各種開(kāi)發(fā)板的BSP,保留了OS的核心功能,但足夠我們使用。版本已經(jīng)更新到了3.0.3版本,與Master的版本號(hào)一致。
RT-Thread Master的源碼可從RT-Thread GitHub倉(cāng)庫(kù)地址:https://github.com/RT-Thread/rt-thread下載到,Nano就是從里面扣出來(lái)的。RT- Thread官方并沒(méi)有將摳出來(lái)的Nano放到他們的官方網(wǎng)站,而是作為一個(gè)Package放在了KEIL網(wǎng)站—http://www.keil.com/dd2/pack/中,供用戶下載, 具體見(jiàn)圖 RT-Thread Nano Package,目前的版本號(hào)是3.0.3,如果以后更新到更高的版本則以最新的版本為準(zhǔn)。

3. 安裝RT-Thread Package
下載下來(lái)之后是一個(gè)以exe為后綴的文件,點(diǎn)擊安裝即可,安裝目錄與你的KEIL安裝目錄一樣,安裝成功之后, 可以在KEIL的PACK目錄下找到剛剛安裝的Package的所有的文件,具體見(jiàn)圖 安裝文件。

這樣安裝成功之后,就可以在KEIL里面的軟件包管理器中將RT-Thread Nano 直接添加到工程里面, 具體見(jiàn)圖 從KEIL的軟件包管理器中選擇RT-Thread。

4. 往裸機(jī)工程添加RT-Thread源碼
4.1. 拷貝RT-Thread Package到裸機(jī)工程根目錄
使用這種方法打包的RT-Thread 工程,拷貝到一臺(tái)沒(méi)有安裝RT-Thread Package的電腦上面是使用不了的, 會(huì)提示找不到RT-Thread的源文件。鑒于RT-Thread Package容量很小,我們直接將安裝在KEIL PACK 目 錄下的整個(gè)RT-Thread文件夾拷貝到我們的STM32裸機(jī)工程里面,讓整個(gè)RT-Thread Package 跟隨我們的 工程一起發(fā)布,具體見(jiàn)圖 拷貝Package到裸機(jī)工程。

圖 拷貝Package到裸機(jī)工程 中RT-Thread文件夾下就是RT-Thread Nano 的所有東西,該文件夾下的具體內(nèi)容見(jiàn)下表。
表格 RT-dhread 文件夾內(nèi)容組成
文件夾 |
文件夾 |
描述 |
---|---|---|
rtthread/3.0.3 |
bsp |
板級(jí)支持包 |
|
components/finsh |
RT-Thread組件 |
|
include |
頭文件 |
|
include/libc |
頭文件 |
|
||
|
libcpu/arm/cortex-m3 |
與處理器相關(guān)的接口文件 |
|
libcpu/arm/cortex-m4 |
與處理器相關(guān)的接口文件 |
|
libcpu/arm/cortex-m7 |
與處理器相關(guān)的接口文件 |
|
src |
RT-Thread內(nèi)核源碼 |
4.2. 拷貝rtconfig.h文件到user文件夾
將RT-Thread/3.0.3/bsp文件夾下面的rtconfig.h配套文件拷貝到工程根目錄下面的user文件夾,等下我們需要對(duì)這個(gè)文件進(jìn)行修改。
用戶可以通過(guò)修改這個(gè)RT-Thread內(nèi)核的配置頭文件來(lái)裁剪RT-Thread的功能,所以我們把它拷貝一份放在user這個(gè)文件夾下面。user,見(jiàn)名之義我們就可以知道里面存放的文件都是用戶自己編寫的。
4.3. 拷貝board.c文件到user文件夾
將RT-Thread/3.0.3/bsp文件夾下面的board.c配套文件拷貝到工程根目錄下面的user文件夾,等下我們需要對(duì)這個(gè)board.c進(jìn)行修改。
4.4. RT-Thread文件夾內(nèi)容簡(jiǎn)介
接下來(lái)我們對(duì)RT-Thread文件夾下面的內(nèi)容做個(gè)簡(jiǎn)單的介紹,好讓我們能夠更順心地使用RT-Thread。
4.4.1. bsp文件夾簡(jiǎn)介
bsp文件夾里面存放的是板級(jí)支持包,即board support package的英文縮寫。RT-Thread為了推廣自己, 會(huì)給各種半導(dǎo)體廠商的評(píng)估板寫好驅(qū)動(dòng)程序,這些驅(qū)動(dòng)程序就放在bsp這個(gè)目錄下,我們這里用的是nano版本, 只有幾款開(kāi)發(fā)板的驅(qū)動(dòng),具體見(jiàn)圖 bsp文件夾內(nèi)容,如果是Master版本,則存放了非常多的開(kāi)發(fā)板的驅(qū)動(dòng),具體見(jiàn) 圖 Master文件夾內(nèi)容。bsp文件夾下面的board.c這是RT-Thread用來(lái)初始化開(kāi)發(fā)板硬件的相關(guān)函數(shù)。rtconfig.h是 RT-Thread功能的配置頭文件,里面定義了很多宏,通過(guò)這些宏定義,我們可以裁剪RT-Thread的功能。 用戶在使用RT-Thread的時(shí)候,用戶只需要修改board.c和rtconfig.h這兩個(gè)文件的內(nèi)容即可,其它文件 我們不需要改動(dòng)。如果為了減小工程的大小,bsp文件夾下面除了board.c和rtconfig.h這兩個(gè)文件要保 留外,其它的統(tǒng)統(tǒng)可以刪除。


4.4.2. components文件夾簡(jiǎn)介
在RT-Thread看來(lái),除了內(nèi)核,其它第三方加進(jìn)來(lái)的軟件都是組件,比如gui、fatfs、lwip和finsh等。那么這些組件就放在components這個(gè)文件夾內(nèi),目前nano版本只放了finsh,其它的都被刪除了,master版本則放了非常多的組件。finsh是RT- Thread組件里面最具特色的,它通過(guò)串口打印的方式來(lái)輸出各種信息,方便我們調(diào)試程序。
4.4.3. include文件夾簡(jiǎn)介
include目錄下面存放的是RT-Thread內(nèi)核的頭文件,是內(nèi)核不可分割的一部分。
4.4.4. libcpu文件夾簡(jiǎn)介
RT-Thread是一個(gè)軟件,單片機(jī)是一個(gè)硬件,RT- Thread要想運(yùn)行在一個(gè)單片機(jī)上面,它們就必須關(guān)聯(lián)在一起,那么怎么關(guān)聯(lián)?還是得通過(guò)寫代碼來(lái)關(guān)聯(lián),這部分 關(guān)聯(lián)的文件叫接口文件,通常由匯編和C聯(lián)合編寫。這些接口文件都是跟硬件密切相關(guān)的,不同的硬件接口文件是 不一樣的,但都大同小異。編寫這些接口文件的過(guò)程我們就叫移植,移植的過(guò)程通常由RT-Thread和mcu原廠的人 來(lái)負(fù)責(zé),移植好的這些接口文件就放在libcpu這個(gè)文件夾的目錄下。RT-Thread nano目 前在libcpu目錄下只放了cortex-m0、m3、m4和m7內(nèi)核的單片機(jī)的接口文件,只要是使用了這些內(nèi)核的mcu都可 以使用里面的接口文件。通常網(wǎng)絡(luò)上出現(xiàn)的叫“移植某某某RTOS到某某某MCU”的教程,其實(shí)準(zhǔn)確來(lái)說(shuō),不能夠叫 移植,應(yīng)該叫使用官方的移植,因?yàn)檫@些跟硬件相關(guān)的接口文件,RTOS官方都已經(jīng)寫好了,我們只是使用而已。 我們本章講的移植也是使用RT-Thread官方的移植,關(guān)于這些底層的移植文件我們已經(jīng)在第一部分“從0到1教你 寫RT-Thread內(nèi)核”有非常詳細(xì)的講解,這里我們直接使用即可。
4.4.5. src文件夾簡(jiǎn)介
src目錄下面存放的是RT-Thread內(nèi)核的源文件,是內(nèi)核的核心,我們?cè)诘谝徊糠帧皬?到1教你寫RT-Thread內(nèi)核”里面講解的就是這里面內(nèi)容。
4.5. 添加RT-Thread源碼到工程組文件夾
在上一步我們只是將RT-Thread的源碼放到了本地工程目錄下,還沒(méi)有添加到開(kāi)發(fā)環(huán)境里面的組文件夾里面。
4.5.1. 新建rtt/source和rtt/ports組
接下來(lái)我們?cè)陂_(kāi)發(fā)環(huán)境里面新建rtt/source和rtt/ports兩個(gè)組文件夾,其中rtt/source用于存放src文件夾的內(nèi)容,rtt/ports用于存放libcpu/arm/cortex-m?文件夾的內(nèi)容,“?”表示3、4或者7,具體選擇哪個(gè)得看你使用的是野火哪個(gè)型號(hào)的STM32開(kāi)發(fā)板,具體 見(jiàn)下表。
表格 野火STM32開(kāi)發(fā)板型號(hào)對(duì)應(yīng)RT-Thread的接口文件
野火STM32開(kāi)發(fā)板型號(hào) |
具體芯片型號(hào) |
RT-Thread不同內(nèi)核的接口文件 |
---|---|---|
MINI |
STM32F103RCT6 |
libcpu/arm/cortex-m3 |
指南者 |
STM32F103VET6 |
libcpu/arm/cortex-m3 |
霸道 |
STM32F103ZET6 |
libcpu/arm/cortex-m3 |
霸天虎 |
STM32F407ZGT6 |
libcpu/arm/cortex-m4 |
F429-挑戰(zhàn)者 |
STM32F429IGT6 |
libcpu/arm/cortex-m4 |
F767-挑戰(zhàn)者 |
STM32F767IGT6 |
libcpu/arm/cortex-m7 |
H743-挑戰(zhàn)者 |
STM32H743IIT6 |
libcpu/arm/cortex-m7 |
bsp里面的rtconfig.h和board.c添加到user組文件夾下,其中rtconfig.h用于配置RT-Thread的功能, board.c用于存放硬件相關(guān)的初始化函數(shù)。源碼添加完畢之后,具體見(jiàn)圖 添加RT-Thread源碼到工程組文件夾。

2.4.5.2. 指定RT-Thread頭文件的路徑
RT-Thread的源碼已經(jīng)添加到開(kāi)發(fā)環(huán)境的組文件夾下面,編譯的時(shí)候需要為這些源文件指定頭文件的路徑,不然編譯會(huì)報(bào)錯(cuò)。RT-Thread的源碼里面只有RT-Thread3.0.3componentsfinsh、RT-Thread3.0.3include和RT- Thread3.0.3includelibc這三個(gè)文件夾下面有頭文件,只需要將這三個(gè)頭文件的路徑在開(kāi)發(fā)環(huán)境里面指定即可。同時(shí)我們還將RT-Thread3.0.3bsp里面的rtconfig.h這個(gè)頭文件拷貝到了工程根目錄下的user文件夾下,所以u(píng)ser的路徑也要加到開(kāi)發(fā)環(huán)境里面。RT- Thread頭文件的路徑添加完成后的效果具體見(jiàn)圖 在開(kāi)發(fā)環(huán)境中指定RT-Thread的頭文件的路徑。

2.5. 修改rtconfig.h
rtconfig.h是直接從RT-Thread/3.0.3/bsp文件夾下面拷貝過(guò)來(lái)的,該頭文件對(duì)裁剪整個(gè)RT-Thread所需的功能的宏均做了定義,有些宏定義被使能,有些宏定義被失能,一開(kāi)始我們只需要配置最簡(jiǎn)單的功能即可。要想隨心所欲的配置RT- Thread的功能,我們必須對(duì)這些宏定義的功能有所掌握,下面我們先簡(jiǎn)單的介紹下這些宏定義的含義,然后再對(duì)這些宏定義進(jìn)行修改。
2.5.1. rtconfig.h文件內(nèi)容講解
代碼清單:移植RTT-1 (1) :頭文件RTE_Components.h是在MDK中添加RT-Thead Package時(shí)由MDK自動(dòng)生成的, 目前我們沒(méi)有使用MDK中自帶的RT-Thread的Package,所以這個(gè)頭文件不存在,如果包含了該頭文件,編譯的時(shí) 候會(huì)報(bào)錯(cuò),等下修改rtconfig.h的時(shí)候需要注釋掉該頭文件。
代碼清單:移植RTT-1 (2) : Use Configuration Wizard in Context Menu: 在上下文中使用 配置向?qū)?lái)配置rtconfig.h中的宏定義。接下來(lái)代碼中夾雜的“”、“”“”、“”和“”這些符號(hào)是MDK自帶的配置向?qū)Э刂品?hào),使用這些符號(hào)控制的代碼可以生成一個(gè)對(duì)應(yīng)的圖形界面的配置 向?qū)В瑀tconfig.h對(duì)應(yīng)的配置向?qū)Ь唧w見(jiàn)圖 rtconfig.h對(duì)應(yīng)的配置向?qū)АS嘘P(guān)配置向?qū)У恼Z(yǔ)法,可在MDK的幫助文檔里面找到, 在搜索欄輸入Configuration Wizard 即可搜索到,具體見(jiàn)圖 Configuration-Wizard。具體每一個(gè)符號(hào)的語(yǔ)法我們這里不 做細(xì)講,有興趣的可以深究下。 對(duì)于我個(gè)人,還是傾向于直接修改rtconfig.h中的源碼,而不是通過(guò)這個(gè)配置 向?qū)?lái)修改,就好比一個(gè)老煙槍抽煙的時(shí)候你要給他加個(gè)過(guò)濾嘴,那是不可能的,這輩子都是不可能的。

代碼清單:移植RTT-1 (3) :RT-Thread的基本配置,要想RT-Thread準(zhǔn)確無(wú)誤的跑起來(lái),這些基本配置必須得有且正確。
代碼清單:移植RTT-1 (3)-1 :RT_THREAD_PRIORITY_MAX這個(gè)宏表示RT-Thread支持多少個(gè)優(yōu)先級(jí), 取值范圍為8~~~256,默認(rèn)為32。
代碼清單:移植RTT-1 (3)-2:RT_TICK_PER_SECOND 表示操作系統(tǒng)每秒鐘有多少個(gè)tick,tick即是操 作系統(tǒng)的時(shí)鐘周期,默認(rèn)為1000,即操作系統(tǒng)的時(shí)鐘周期tick等于1ms。
代碼清單:移植RTT-1 (3)-3:RT_ALIGN_SIZE這個(gè)宏表示CPU處理的數(shù)據(jù)需要多少個(gè)字節(jié)對(duì)齊,默認(rèn)為4個(gè)字節(jié)。
代碼清單:移植RTT-1 (3)-4:RT_NAME_MAX這個(gè)宏表示內(nèi)核對(duì)象名字的最大長(zhǎng)度,取值范圍為2~~~16,默認(rèn)為8。
代碼清單:移植RTT-1 (3)-5:使用RT-Thread組件初始化,默認(rèn)使能。
代碼清單:移植RTT-1 (3)-6:使用用戶main函數(shù),默認(rèn)打開(kāi)。
代碼清單:移植RTT-1 (3)-7:main線程棧大小,取值范圍為1~~~4086,單位為字節(jié),默認(rèn)為512。
代碼清單:移植RTT-1 (4):調(diào)試配置。包括了內(nèi)核調(diào)試配置,組件調(diào)試配置和線程棧溢出檢測(cè),目前全部關(guān)閉。
代碼清單:移植RTT-1 (5):鉤子函數(shù)配置,目前全部關(guān)閉。
代碼清單:移植RTT-1 (6):軟件定時(shí)器配置,目前關(guān)閉,不使用軟件定時(shí)器。
代碼清單:移植RTT-1 (7):內(nèi)部通信配置,包括信號(hào)量、互斥量、事件、郵箱和消息隊(duì)列,根據(jù)需要配置。
代碼清單:移植RTT-1 (8):內(nèi)存管理配置。
代碼清單:移植RTT-1 (8)-1:RT_USING_MEMPOOL這個(gè)宏用于表示是否使用內(nèi)存池,目前關(guān)閉,不使用內(nèi)存池。
代碼清單:移植RTT-1 (8)-2:RT_USING_HEAP這個(gè)宏用于表示是否堆,目前關(guān)閉,不使用堆。
代碼清單:移植RTT-1 (8)-3:RT_USING_SMALL_MEM這個(gè)宏用于表示是否使用小內(nèi)存,目前使能。
代碼清單:移植RTT-1 (8)-4:RT_USING_TINY_SIZE這個(gè)宏用于表示是否使用極小內(nèi)存,目前關(guān)閉,不使用。
代碼清單:移植RTT-1 (9):控制臺(tái)配置。控制臺(tái)即是rt_kprintf()函數(shù)調(diào)試輸出的設(shè)備,通常使用串口。
代碼清單:移植RTT-1 (10):FINSH配置。
代碼清單:移植RTT-1 (11):設(shè)備配置。
代碼清單:移植RTT-1 (12):rtconfig.h配置結(jié)束。
2.5.2. rtconfig.h文件修改
rtconfig.h頭文件的內(nèi)容修改的不多,具體是:注釋掉頭文件RTE_Components.h、修改了 RT_THREAD_PRIORITY_MAX、RT_TICK_PER_SECOND和RT_MAIN_THREAD_STACK_SIZE這三個(gè)宏 的大小,具體見(jiàn) 代碼清單:移植RTT-2 的高亮部分。
2.6. 修改board.c
2.6.1. board.c文件內(nèi)容講解
board.c是直接從RT-Thread/3.0.3/bsp文件夾下面拷貝過(guò)來(lái)的,里面存放的是與硬件相關(guān)的初始化函數(shù), 整個(gè) board.c中的內(nèi)容具體見(jiàn) 代碼清單:移植RTT-3。
代碼清單:移植RTT-3 (1):RT-Thread相關(guān)頭文件,rthw.h是處理器相關(guān),rtthread與內(nèi)核相關(guān)。
代碼清單:移植RTT-3 (2):SysTick相關(guān)的寄存器定義和初始化函數(shù),這個(gè)是跟處理器相關(guān)的,等下我們直接 使用固件庫(kù)函數(shù),可以把這部分注釋掉,也可以保留,看個(gè)人喜好。
代碼清單:移植RTT-3 (3):RT-Thread堆配置,如果同時(shí)定義了RT_USING_USER_MAIN和 RT_USING_HEAP這兩 個(gè)宏,表示RT-Thread里面創(chuàng)建內(nèi)核對(duì)象時(shí)使用動(dòng)態(tài)內(nèi)存分配方案。堆可以是內(nèi)部的SRAM也可以是外部的SRAM或 SDRAM,目前的方法是從內(nèi)部SRAM里面分配一部分靜態(tài)內(nèi)存來(lái)作為堆空間,這里配置為4KB。rt_heap_begin_get() 和rt_heap_end_get()這兩個(gè)函數(shù)表示堆的起始地址和結(jié)束地址。這兩個(gè)函數(shù)前面的宏RT_WEAK的原型是關(guān)鍵字 __weak,表示若定義,即其它地方定義了rt_heap_begin_get()和rt_heap_end_get()這兩個(gè)函數(shù)實(shí)體, 被__weak修飾的函數(shù)就會(huì)被覆蓋。
RT_USING_USER_MAIN和RT_USING_HEAP這兩個(gè)宏在rtconfig.h中定義,RT_USING_USER_MAIN默認(rèn)使能,通過(guò)使能或者失能RT_USING_HEAP這個(gè)宏來(lái)選擇使用靜態(tài)或者動(dòng)態(tài)內(nèi)存。無(wú)論是使用靜態(tài)還是動(dòng)態(tài)內(nèi)存方案,使用的都是內(nèi)部的SRAM,區(qū)別是使用的內(nèi)存是 在程序編譯的時(shí)候分配還是在運(yùn)行的時(shí)候分配。
2.6.1.1. rt_hw_board_init()函數(shù)
代碼清單:移植RTT-3 (4):RT-Thread啟動(dòng)的時(shí)候會(huì)調(diào)用一個(gè)名為rt_hw_board_init()的函數(shù),從函數(shù)名稱 我們可以知道它是用來(lái)初始化開(kāi)發(fā)板硬件的,比如時(shí)鐘,比如串口等,具體初始化什么由用戶選擇。當(dāng)這些硬件 初始化好之后,RT-Thread才繼續(xù)往下啟動(dòng)。至于RT-Thread是哪個(gè)文件里面的哪個(gè)函數(shù)會(huì)調(diào) 用rt_hw_board_init(),我們?cè)诒菊孪炔患?xì)講,留到接下來(lái)的“RT-Thread的啟動(dòng)流程”章節(jié)再深究,這里我們 只需要知道我們用戶要自己編寫一個(gè)rt_hw_board_init()的函數(shù)供RT-Thread啟動(dòng)的時(shí)候調(diào)用即可。
代碼清單:移植RTT-3 (4)-1:更新系統(tǒng)時(shí)鐘,如果硬件已經(jīng)能夠跑起來(lái)都表示系統(tǒng)時(shí)鐘是沒(méi)有問(wèn)題的,該函數(shù)一般由固件庫(kù)提供。
代碼清單:移植RTT-3 (4)-2:初始化系統(tǒng)定時(shí)器SysTick,SysTick給操作系統(tǒng)提供時(shí)基,1個(gè)時(shí)基我們稱之 為一個(gè)tick,tick是操作系統(tǒng)最小的時(shí)間單位。RT_TICK_PER_SECOND是一個(gè)在rtconfig.h中定義的宏,用于 配置SysTick每秒中斷多少次,這里配置為1000,即1秒鐘內(nèi)SysTick會(huì)中斷1000次,即中斷周期為1ms。 這部 分功能等下我們會(huì)用固件庫(kù)函數(shù)SysTick_Config()來(lái)代替。
代碼清單:移植RTT-3 (4)-3:硬件BSP初始化統(tǒng)統(tǒng)放在這里,比如LED,串口,LCD等。目前我們暫時(shí)沒(méi)有初始化任何開(kāi)發(fā)板的硬件。
代碼清單:移植RTT-3 (4)-4:這部分是RT-Thread為開(kāi)發(fā)板組件提供的一個(gè)初始化函數(shù),該函數(shù)在 components.c里面實(shí)現(xiàn),由rtconfig.h里面的宏RT_USING_COMPONENTS_INIT決定是否調(diào)用,默認(rèn)是開(kāi)啟。
代碼清單:移植RTT-3 (4)-5:rt_console_set_device()是RT-Thread提供的一個(gè)控制臺(tái)設(shè)置函數(shù),它將指定rt_kprintf()函數(shù) 的輸出內(nèi)容具體從什么設(shè)備打印出來(lái)。該函數(shù)在kservice.c里面實(shí)現(xiàn),由rtconfig.h里面的RT_USING_CONSOLE和RT_USING_DEVICE這兩個(gè)宏決定是否調(diào)用,目前我們暫時(shí)不用。
代碼清單:移植RTT-3 (4)-6:rt_system_heap_init()是RT-Thread提供的一個(gè)內(nèi)存初始化函數(shù), 只有在使用RT-Thread提供的動(dòng)態(tài)內(nèi)存分配函數(shù)時(shí)才需要使用到。該函數(shù)在mem.c里面實(shí)現(xiàn),由rtconfig.h里面的RT_USING_HEAP和RT_USING_USER_MAIN這兩個(gè)決定是否調(diào)用,目前我們暫時(shí)不用。
2.6.1.2. SysTick_Handler()函數(shù)
代碼清單:移植RTT-3 (5):SysTick中斷服務(wù)函數(shù)是一個(gè)非常重要的函數(shù),RT-Thread所有跟時(shí)間相關(guān)的事 情都在里面處理,具體實(shí)現(xiàn)見(jiàn) 代碼清單:移植RTT-4。
代碼清單:移植RTT-4 SysTick_Handler()函數(shù)
代碼清單:移植RTT-4 (1):進(jìn)入中斷,對(duì)中斷計(jì)數(shù)器rt_interrupt_nest加1操作。
代碼清單:移植RTT-4(2):rt_tick_increase()用于更新時(shí)基,實(shí)現(xiàn)時(shí)間片,掃描系統(tǒng)定時(shí)器。
代碼清單:移植RTT-4(3) :退出中斷,對(duì)中斷計(jì)數(shù)器rt_interrupt_nest減1操作。
2.6.2. board.c文件修改
board.c文件內(nèi)容修改的并不多,具體見(jiàn)代碼清單:移植RTT-5的高亮部分。
代碼清單:移植RTT-5 修改(1):在user目錄下新建一個(gè)board.h頭文件,用來(lái)包含固件庫(kù)和BSP相關(guān)的 頭文件和存放board.c里面的函數(shù)聲明,具體見(jiàn) 代碼清單:移植RTT-6。
代碼清單:移植RTT-5 修改(2):SysTick相關(guān)的寄存器和初始化函數(shù)統(tǒng)統(tǒng)屏蔽掉,將由固件庫(kù)文件core_cm3/4/7里面的替代。
代碼清單:移植RTT-5 修改(3):SysTick初始化函數(shù)由固件庫(kù)文件core_cm3/4/7里面的SysTick_Config()函數(shù)替代。
如果使用的是HAL庫(kù)(目前野火只在STM32 M7系列中使用HAL庫(kù)),則必須添加系統(tǒng)時(shí)鐘初始化函數(shù),這個(gè)函數(shù)在 我們利用STM32CubeMX代碼生成工具配置工程時(shí)會(huì)自動(dòng)給我們生成,我們只需添加到rt_hw_board_init()函數(shù)進(jìn) 行初始化即可。
代碼清單:移植RTT-7 (2):初始化系統(tǒng)時(shí)鐘之后,需要對(duì)SysTick進(jìn)行初始化,因?yàn)橄到y(tǒng)時(shí)鐘初始化函數(shù)會(huì) 在最后將SysTick的時(shí)鐘也進(jìn)行初始化為HAL庫(kù)中默認(rèn)的時(shí)鐘,不滿足我們系統(tǒng)的要求,所以我們只能使用 HAL_SYSTICK_Config將SysTick重新初始化,根據(jù)我們的RT_TICK_PER_SECOND宏定義進(jìn)行配置。保證系統(tǒng)正常運(yùn)行。
2.7. 添加core_delay.c和core_delay.h文件
只有在使用HAL庫(kù)時(shí)才需要添加core_delay.c和core_delay.h文件。野火只在其M7系列的開(kāi)發(fā)板使用了HAL,M4和M3使用的是標(biāo)準(zhǔn)庫(kù),不需要添加。
在ST的Cortex-M7內(nèi)核系列的單片機(jī)中,就不再支持標(biāo)準(zhǔn)庫(kù)而是推出了HAL庫(kù),目前,野火只在STM32 M7系列中使用HAL庫(kù)。
HAL是意思是HardwareAbstractionLayer,即硬件抽象層。用一句話概括就是現(xiàn)在這個(gè)庫(kù)與標(biāo)準(zhǔn)庫(kù)相比,與底 層硬件的相關(guān)性大大地降低,程序可移植性大大提高,電工寫程序更easy,可以像計(jì)算機(jī)的碼農(nóng)那樣寫代碼。對(duì)于 小白來(lái)說(shuō),Coding的門檻雖然降低了,但是HAL帶來(lái)的占用內(nèi)存大,編譯慢是很多老手不喜歡的,特別是我,我就 很不喜歡,編譯一次7分鐘,簡(jiǎn)直是要了我的老命。鑒于HAL的優(yōu)缺點(diǎn),我個(gè)人觀點(diǎn)是比較適合ST Cortex-M7內(nèi)核 系列這種大內(nèi)存,高性能的MCU,雖然Cortex-M3/M4也有HAL庫(kù),但是還是使用標(biāo)準(zhǔn)庫(kù)比較好。
HAL庫(kù)驅(qū)動(dòng)中,由于某些外設(shè)的驅(qū)動(dòng)需要使用超時(shí)判斷(比如I2C、SPI、SDIO等),需要精確延時(shí)(精度為1ms), 使用的是SysTick,但是在操作系統(tǒng)里面,我們需要使用SysTick來(lái)提供系統(tǒng)時(shí)基,那么就沖突了,怎么辦?我們 采取的做法是重寫HAL庫(kù)里面延時(shí)相關(guān)的函數(shù),只有三個(gè):HAL_InitTick()、HAL_GetTick()和HAL_Delay(), 這三個(gè)函數(shù)在HAL庫(kù)中都是弱定義函數(shù)(函數(shù)開(kāi)頭帶__weak關(guān)鍵字),弱定義的意思是只要用戶重寫這三個(gè)函數(shù), 原來(lái)HAL庫(kù)里面的就會(huì)無(wú)效。
在Cortex-M內(nèi)核里面有一個(gè)外設(shè)叫DWT(Data Watchpoint and Trace), 該外設(shè)有一個(gè)32位的寄存器叫CYCCNT, 它是一個(gè)向上的計(jì)數(shù)器, 記錄的是內(nèi)核時(shí)鐘運(yùn)行的個(gè)數(shù),最長(zhǎng)能記錄的時(shí)間為: 10.74s = 2的32次方/400000000 (CYCNNT從0開(kāi)始計(jì)數(shù)到溢出,最長(zhǎng)的延時(shí)時(shí)間與內(nèi)核的頻率有關(guān),假設(shè)內(nèi)核頻率為400M,內(nèi)核時(shí)鐘跳一次的時(shí)間 大概為1/400M=2.5ns),當(dāng)CYCCNT溢出之后,會(huì)清0重新開(kāi)始向上計(jì)數(shù)。這種延時(shí)方案不僅精確,而且還不占用單 片機(jī)的外設(shè)資源,非常方便。所以HAL庫(kù)里面剛剛講到的需要重寫的三個(gè)函數(shù)我們都基于CYCCNT的方案來(lái)實(shí)現(xiàn),具 體的實(shí)現(xiàn)見(jiàn)代碼清單:移植RTT-8和代碼清單13?9的高亮部分,其中core_delay.c和core_delay.h這兩個(gè)文件我們已經(jīng) 寫好,放在user文件夾下即可,具體的使用方法看注釋。
代碼清單:移植RTT-8 (1):重寫HAL_InitTick()函數(shù)。
代碼清單:移植RTT-8 (2):重寫HAL_GetTick ()函數(shù)。
代碼清單:移植RTT-9 (3):重寫HAL_Delay ()函數(shù)。
2.8. 修改main.c
我們將原來(lái)裸機(jī)工程里面main.c的文件內(nèi)容全部刪除,新增如下內(nèi)容,具體見(jiàn) 代碼清單:移植RTT-10。
-
嵌入式
+關(guān)注
關(guān)注
5144文章
19597瀏覽量
316120 -
STM32
+關(guān)注
關(guān)注
2291文章
11022瀏覽量
363394 -
開(kāi)發(fā)板
+關(guān)注
關(guān)注
25文章
5620瀏覽量
103489 -
RT-Thread
+關(guān)注
關(guān)注
32文章
1385瀏覽量
41669
發(fā)布評(píng)論請(qǐng)先 登錄
[經(jīng)驗(yàn)] RT-Thread 潘多拉 STM32L475
如何將RT-Thread移植到NXP MCUXPressoIDE上

RT-Thread 發(fā)布 EtherKit開(kāi)源以太網(wǎng)硬件!

RT-Thread上CAN實(shí)踐

基于恩智浦FRDM-MCXA153開(kāi)發(fā)板實(shí)現(xiàn)RT-Thread的ADC驅(qū)動(dòng)

開(kāi)源共生 商業(yè)共贏 | RT-Thread 2024開(kāi)發(fā)者大會(huì)報(bào)名啟動(dòng)!

NXP FRDM-MCXC444開(kāi)發(fā)板在RT-Thread環(huán)境下的上手過(guò)程

在rt-thread bsp里esp32c3里編譯出的bin文件燒到esp32的開(kāi)發(fā)板上運(yùn)行提示chipid不對(duì),為什么?
如何在RT-thread studio的裸機(jī)例程上移植freertos?
獲獎(jiǎng)公布!2024 RT-Thread全球巡回線下培訓(xùn)火熱來(lái)襲!報(bào)名提問(wèn)有獎(jiǎng)!
【QEMU系列】不用開(kāi)發(fā)板運(yùn)行RT-Thread指南-ARM架構(gòu)

2024 RT-Thread全球巡回 線下培訓(xùn)火熱來(lái)襲!

【好書推薦】RT-Thread設(shè)備驅(qū)動(dòng)開(kāi)發(fā)指南

評(píng)論