前面我們將ThreadX成功移植到了STM32F4平臺,但這只是我們的部分應用。我們希望將ThreadX的優勢發揮到我們的更多應用中,所以在這一篇中我們就來實現將ThreadX移植到STM32H7平臺中。
1、前期準備
??在開始將ThreadX移植到STM32H7平臺之前,我們需要做一些軟硬件方面的準備。
??首先,我們需要準備STM32H7的硬件平臺。這次我們采用STM32H750VBT6為控制單元來作為目標平臺。這是一款我們在實際項目中使用的,經過驗證的,硬件能夠穩定運行的平臺。
??其次,我們需要準備相應的軟件資源,也就是ThreadX的源碼。ThreadX的源碼已經開源到Github上,其地址為:[https://github.com/azure-rtos/threadx,直接下載源碼就可以了。我們將采用目前最新的版本。下載好ThreadX的源碼后,我們將其解壓,如下圖:
??上圖中一目了然,無需做太多解釋。我們需要用到的文件主要存放在common文件夾和ports文件夾。其中common文件夾存放的是內核源碼,ports文件夾存放的是不同平臺的接口文件。我們的硬件采用的是STM32H750VBT6,軟件開發環境用的是IAR EWARM,所以我們選擇ports文件夾下cortex_m7下的IAR文件夾中的接口文件。
2、系統移植
??我們準備好軟件硬件平臺后,就可以開始系統的移植了。首先我們找到一個基礎的裸機項目,能正確實現硬件的啟動及時鐘初始化就好了。接下來的移植工作主要包括:添加源碼,修改配置等。
??第一步,我們先向項目中添加ThreadX的相關源碼文件。所以我們在項目下添加ThreadX組、并在ThreadX組下添加Source和Ports兩個組用于添加文件。并將common文件夾和ports文件夾中的文件添加到對應的分組。如下所示:
??然后要在項目屬性中為編譯器指定頭文件的引用路徑,主要是內核函數的頭文件以及接口文件的頭文件兩個路徑,在我們這個項目中配置如下:
??PROJDIRPROJDIR....\\ThreadX\\common\\inc
??PROJDIRPROJDIR....\\ThreadX\\ports\\cortex_m4\\iar\\inc
??第二步,修改stm32h7xx_it.c文件。將其中的中斷響應函數void PendSV_Handler(void)和void SysTick_Handler(void)去除。因為在ThreadX中已經實現和使用。
??第三步,修改tx_initialize_low_level.s文件。這個文件負責建立各種系統數據結構,并提供定時中斷源。這個文件應該是要針對不同的底層平臺編寫。但在微軟提供的cortex_m7下IAR的接口例程中已經提供 了一個,所以我們基于這個文件進行修改就可以了,主要根據實際應用修改的是時鐘頻率。
??SYSTEM_CLOCK EQU 480000000
??SYSTICK_CYCLES EQU ((SYSTEM_CLOCK / 1000) -1)
??第四步,修改ThreadX的配置文件。ThreadX中要求使者提供一個tx_user.h的配置文件。當然這個文件并不需要從頭編寫,在common\\inc目錄下有一個tx_user_sample.h文件,我們根據這個文件修改就可以了。
??經過上述這四步操作,我們實際上已經完成了對ThreadX內核的移植,但還沒有辦法正確使用,因為我們還沒有定義具體的任務。
3、任務實現
??我們已經完成了對ThreadX內核文件以及接口文件的移植,接下來我們就來實現具體的應用任務。ThreadX內核實現基本應用很簡單,只涉及到2個函數:tx_kernel_enter和tx_application_define,這兩個函數在頭文件“tx_api.h”中被聲明。事實上ThreadX內核所有的對外函數都在“tx_api.h”中聲明,所以凡是我們需要使用內核的地方必須引用“tx_api.h”頭文件。
??其中tx_kernel_enter實際是一個宏,真正的函數是_tx_initialize_kernel_enter,用于啟動內核,這個函數需要我們在主函數中調用。調用這個函數后,內核開始運行,多任務也將按照我們的設計循環運行。
??而tx_application_define函數只有聲明沒有實現,在_tx_initialize_kernel_enter函數中被調用,用于任務的創建。所有的任務都將在這個函數中被創建,而且不僅僅是任務在這個函數中創建,信號量、隊列、互斥量等都在這個函數中創建。
??我們將在tx_application_define函數創建任務,這就需要用到tx_thread_create函數。這個函數的參數有10個,包括任務控制塊、任務函數地址、任務棧的大小及地址、任務優先級等。這些參數都是我們需要定義或聲明的。然后我們就可以編寫tx_application_define函數:
/*tx_application_define函數實現*/
void tx_application_define(void *first_unused_memory)
{
/* 創建系統任務 */
tx_thread_create(&ThreadSystemTCB, /* 任務控制塊地址 */
"Thread System", /* 任務名 */
ThreadSystem, /* 啟動任務函數地址 */
0, /* 傳遞給任務的參數 */
&ThreadSystemStack[0], /* 堆棧基地址 */
THREAD_SYSTEM_STK_SIZE, /* 堆棧空間大小 */
THREAD_SYSTEM_PRIO, /* 任務優先級*/
THREAD_SYSTEM_PRIO, /* 任務搶占閥值 */
TX_NO_TIME_SLICE, /* 不開啟時間片 */
TX_AUTO_START); /* 創建后立即啟動 */
/* 創建模擬量處理任務 */
tx_thread_create(&ThreadAnalogTCB, /* 任務控制塊地址 */
"Thread Analog", /* 任務名 */
ThreadAnalog, /* 啟動任務函數地址 */
0, /* 傳遞給任務的參數 */
&ThreadAnalogStack[0], /* 堆棧基地址 */
THREAD_ANALOG_STK_SIZE, /* 堆棧空間大小 */
THREAD_ANALOG_PRIO, /* 任務優先級*/
THREAD_ANALOG_PRIO, /* 任務搶占閥值 */
TX_NO_TIME_SLICE, /* 不開啟時間片 */
TX_AUTO_START); /* 創建后立即啟動 */
/* 創建邏輯處理任務 */
tx_thread_create(&ThreadLogicTCB, /* 任務控制塊地址 */
"Thread Logic", /* 任務名 */
ThreadLogic, /* 啟動任務函數地址 */
0, /* 傳遞給任務的參數 */
&ThreadLogicStack[0], /* 堆棧基地址 */
THREAD_LOGIC_STK_SIZE, /* 堆棧空間大小 */
THREAD_LOGIC_PRIO, /* 任務優先級*/
THREAD_LOGIC_PRIO, /* 任務搶占閥值 */
TX_NO_TIME_SLICE, /* 不開啟時間片 */
TX_AUTO_START); /* 創建后立即啟動 */
/* 創建通訊處理任務 */
tx_thread_create(&ThreadCommTCB, /* 任務控制塊地址 */
"Thread Comm", /* 任務名 */
ThreadComm, /* 啟動任務函數地址 */
0, /* 傳遞給任務的參數 */
&ThreadCommStack[0], /* 堆棧基地址 */
THREAD_COMM_STK_SIZE, /* 堆棧空間大小 */
THREAD_COMM_PRIO, /* 任務優先級*/
THREAD_COMM_PRIO, /* 任務搶占閥值 */
TX_NO_TIME_SLICE, /* 不開啟時間片 */
TX_AUTO_START); /* 創建后立即啟動 */
/* 創建統計任務 */
tx_thread_create(&ThreadStatTCB, /* 任務控制塊地址 */
"Thread STAT", /* 任務名 */
ThreadStat, /* 啟動任務函數地址 */
0, /* 傳遞給任務的參數 */
&ThreadStatStack[0], /* 堆棧基地址 */
THREAD_IDLE_STK_SIZE, /* 堆棧空間大小 */
THREAD_STAT_PRIO, /* 任務優先級*/
THREAD_STAT_PRIO, /* 任務搶占閥值 */
TX_NO_TIME_SLICE, /* 不開啟時間片 */
TX_AUTO_START); /* 創建后立即啟動 */
/* 創建空閑任務 */
tx_thread_create(&ThreadIdleTCB, /* 任務控制塊地址 */
"Thread IDLE", /* 任務名 */
ThreadIdle, /* 啟動任務函數地址 */
0, /* 傳遞給任務的參數 */
&ThreadIdleStack[0], /* 堆棧基地址 */
THREAD_IDLE_STK_SIZE, /* 堆棧空間大小 */
THREAD_IDLE_PRIO, /* 任務優先級*/
THREAD_IDLE_PRIO, /* 任務搶占閥值 */
TX_NO_TIME_SLICE, /* 不開啟時間片 */
TX_AUTO_START); /* 創建后立即啟動 */
}
??還要在主函數中調用 tx_kernel_enter函數以達到啟動ThreadX內核的目的。
4、最后測試
??完成前述的全部內容后,我們編譯下載到目標平臺,系統能夠正常運行。添加ThreadX調試插件可以查看個任務的執行情況如下:
??經過上述測試,我們已經成功的將ThreadX一直到立刻STM32H7平臺,這樣余下的事情就是開發具體的應用了。
-
接口
+關注
關注
33文章
8691瀏覽量
151913 -
threadx
+關注
關注
0文章
15瀏覽量
13864 -
STM32
+關注
關注
2272文章
10923瀏覽量
357555 -
移植
+關注
關注
1文章
383瀏覽量
28193 -
stm32h7
+關注
關注
0文章
37瀏覽量
1753
發布評論請先 登錄
相關推薦
評論