ThreadX 內核內容介紹#
[!NOTE]
本文圖片過多,未轉移自有伺服器,仍使用公共圖床,載圖可能會很慢
threadx 已捐贈給 eclipse 基金會,目前的開源代碼在這裡。
我使用的通常是 st 公司的 fork,實際上的支持並沒有好多少,该有的坑也還是有
ThreadX 內核包含三個內容:ThreadX 操作系統內核,Modules 模組、trace 調試監測。在 ThreadX 源碼中,這些內容很多是混雜在一起的。所以簡單寫一個文檔記錄一下。即是移植教程,也記錄庫結構。
本文檔所有的圖片,都在圖片相關描述文字的上方。這是 threadX 源碼的所有內容
其中顯示出了系統內核的三個版本
common
普通內核common_module
具有模組加載功能的內核,硬體驅動與軟體邏輯可完全分離common_smp
具有多核 MCU 支持的內核
內核移植目標是使用這些組件
- ThreadX 操作系統內核
- Modules 模組
- Trace 調試監控
純內核移植#
純內核是我說的 —— 相對於modules
版內核和smp
版內核,實際上與 freertos、bios 這類普通 RTOS 功能無異,只是移植 threadX 系其他組件更方便,命名也更一致,例如 NetX、usbX、FileX 都可以非常簡單加入系統。
哪些是純內核源碼?#
在 threadX 操作系統源碼中,有如圖框出的兩個文件夾,這兩個文件夾實際上就是我們移植操作系統內核需要的所有源碼了
首先關注到 common 文件夾,這些實際上都是需要的源碼,也就是我們的工程需要的文件,但仍然有一些值得注意的地方。
在 stc 文件夾下,有一些 tx_trace_xx 命名的源碼文件,這些是 trace 調試監測使用的源碼
以這個開啟監控的函數為例,如果沒有使用 TX_ENABLE_EVENT_TRACE 宏定義進行開啟監控功能,那麼這個函數是不會做任何事情的
在 inc 文件夾下,也有一個 tx_trace.h 的文件。
沒有開啟 TX_ENABLE_EVENT_TRACE 宏定義,也是幾乎不做任何事情。
回到源碼文件夾,再關注到 ports 文件夾
找到自己對應的內核
找到自己對應的編譯器,源碼和頭文件都是工程所需,另外要注意的是排除可能存在的這個文件 tx_misra.S,可能已經有 tx_misra.c 定義了
簡單介紹一下ports/內核名/編譯器名/inc
中的tx_port.h文件,這裡是調整 threadX 的唯一接口,類似TX_ENABLE_EVENT_TRACE
這樣控制操作系統的功能開啟與否的宏定義,可以寫在編譯器整體 define 處。
但是關注到第 79 行,他給了一個另外的.h 接口供我們定義。我們可以將TX_INCLUDE_USER_DEFINE_FILE
宏定義寫在編譯器整體 define 中然後通過自定義一個tx_user.h文件來控制操作系統宏定義。
這個tx_user.h文件有一個示例,在操作系統源碼common\inc
下有名為tx_user_sample.h
或類似的文件作為示例,但是tx_user.h這個文件名需要自己創建或改名他的示例文件。
在 common\src 下有這樣一個 tx_thread_initialize.c,其中有一個變量可以在運行時查看配置狀況。這個變量同時在 tx_thread.h 中被 extern 聲明,所以使用 threadX 操作系統時可以隨地查看這個變量且不可重複聲明。
應該如何開啟?#
雖然我們使用 ac6 編譯器,仍然可以先關注一下 gnu 文件夾,因為其中有一個簡單的創建任務的示例
在這裡!
簡單分析示例
- 這部分是頭文件,僅僅包含了 tx_api.h
- 這部分是 main 入口
- 這部分是一個固定需要自己定義的函數,這個函數名在_tx_initialize_kernel_enter () 開啟 thread 內核時會進行調用,實際上就是內核開啟後給我們用戶程序的接口,。
簡單分析一下這個用戶接口函數的話,其實就是將 threadX 的幾個主要 api 演示了一遍,申請內存空間,使用這片內存空間創建任務,創建消息隊列,創建消息量等等常見常用的 API,具體如何使用可以自行看源碼。
結合整個示例,我們知道使用 threadX 內核的最基本操作:
- 包含
tx_api.h
- 定義
void tx_application_define(void *first_unused_memory)
這個函數,並在這個函數調用後再創建任務 (此時 threadX 內核已經開啟) - 主程序中使用
tx_kernel_enter();
函數開啟 threadX 內核
關注到與示例同文件夾下的這個文件
其中定義了一些中斷函數,用於接管芯片的中斷處理,使 threadX 操作系統運行起來,注意修改
SYSTEM_CLOCK
和SYSTICK_CYCLES
,在如圖示例中,600000
代表芯片主頻時鐘是 6M,100代表
操作系統的時鐘基準是 10ms,也就是tx_thread_sleep(1);
實際上是釋放內核 10ms
其實這個.S 文件仍然有需要修改的地方,似乎是某些中斷沒有定義,最好是使用 stm32cubeMX 自動生成一個,然後粘到自己工程裡,如果操作系統沒有正常運行,最大的可能是這個 tx_initialize_low_level.s 有問題
編譯器整體 Define 添加這樣一條TX_INCLUDE_USER_DEFINE_FILE
帶模組管理器的內核移植#
首先確認一個概念,模組管理器和模組是什麼?
模組管理器具有 threadX 內核,具有驅動硬體的能力,可以從某些存儲介質內加載模組的可執行二進制內容(例如從片內 flash 的 0x8100000這個地址開始加載模組;模組不具有驅動硬體的能力,沒有 threadX 內核,無法單獨工作,但是作為一個單獨的工程存在,可以獨立編譯發布。
也就是模組管理器和模組是兩個工程,同時他們需要移植的源碼是不同的。
至於有什麼必要做這樣的事情,不在這裡討論。
哪些是帶模組管理器的源碼?#
可以先不管那麼多,將這兩個文件夾都粘進自己的工程再說在 threadX 操作系統源碼中,有如圖框出的三個文件夾,這三個文件夾內有移植帶模組管理器的內核的所有源碼
由於默認已經看過純內核移植的內容了,認為對基礎內核以及 trace 調試追蹤有一定了解。所以這些內容不再贅述,僅討論與純內核不同的點。
關注到common_modules
文件夾
作為模組管理器的內核,需要的是框起來的兩個源碼文件夾,而 module_lib 是給模組移植的源碼。
可以先不管那麼多,將這兩個文件夾的所有內容都包含進自己的工程再說,後續再做調整
關注到ports_modules
文件夾
找到自己對應的架構
找到自己對應的編譯器
需要的是框起來的兩個源碼文件夾,而 module_lib 是給模組移植的源碼。
不管那麼多,將這兩個文件夾的所有內容都包含進自己的工程再說,後續再做調整
然後從例程找到或者使用 stm32cubeMX 自動生成一個tx_initialize_low_level.S,由於 stm32cubeMX 不支持生成 modules 工程,事實上也不適合,能順利使用 modules 需要大量自己的適配和操作。
在如圖這個工程中,推薦從例程中尋找。
在純內核移植中已經介紹過tx_initialize_low_level.S了,不再贅述。
回到這個文件夾下,找到名為txm_module_user_sample.h的文件,複製一份改名為txm_module_user.h,當編譯器整體 define 設置有TXM_MODULE_INCLUDE_USER_DEFINE_FILE時,在模組管理器工程和模組工程中都會調用名為txm_module_user.h的頭文件 (必須是相同的),以控制操作系統功能
txm_module_user.h
中大致是這樣的內容
記得tx_user.h
也需要創建,在純內核中有說明
應該如何開啟#
實際上與純內核的開啟方法一樣。但注意這種內核使用時,標準的做法是將業務邏輯都做成模組進行加載,但是模組工程的建立以及二者的適配也挺麻煩的,目前還沒完全搞清楚,所以也沒有做成文檔。
但就把它當作普通內核使用也是沒有問題的。
此文由 Mix Space 同步更新至 xLog
原始鏈接為 https://www.yono233.cn/posts/shoot/24_7_15_%E6%9C%80%E5%85%A8%E8%AE%A4%E8%AF%81RTOS%E2%80%94%E2%80%94azure_threadX%E7%A7%BB%E6%A4%8D%E6%95%99%E7%A8%8B