我都二手程式設計師好幾個禮拜了!想給我的STM32來點「中國風」,裝個華為LiteOS作業系統。
在此之前,我也試過STM32CubeMX自帶的FreeRTOS作業系統,不知是何緣故,用F103c8t6晶片時,FreeRTOS裡的一個斷言過不去。出師不利,決定換LiteOS試試,儘管移植LiteOS有些麻煩,不如STM32CubeMX生成的方便,但是,移植成功後,編譯沒有問題、執行也沒有問題,這讓我這個初學者增添了不少信心。
FreeRTOS與LiteOS孰優孰劣,我真的不知道,不過,我知道我喜歡CubeMX,Keil也算湊活,所以,想用大白話說說,如何給STM32CubeMX建立的MDK-ARM工程移植LiteOS。如果,你也想用華為LiteOS作業系統,可以繼續往下看,若是內行高手,「要是你拿正眼多看我一眼,那你就輸了」。
沒什麼特殊要求,注意以下兩點:一、SYS 時鐘源不要用SysTick。二、專案管理中Toolchain選擇MDK-ARM。
上面給的連結不是最新發行版,新版本增加了些晶片架構的支援,暫時還不會用。先來個打了標籤LiteOSV200R001C50B038
的版本。下圖中紅框標註的4個目錄是我們需要的。
LiteOS原始碼下載好了吧?我們開始給Keil工程新增LiteOS原始碼。
先在Keil工程根目錄下,建一個目錄LiteOS
,用來放置LiteOS的原始碼,(其實目錄名叫什麼不重要,看你高興)。
在新建的LiteOS目錄下,再整4個子目錄,分別叫它們Kernel
、Arch
、CMSIS
、Config
。看看它們的名字,想必您已經猜到了,我想在裡面放些什麼了,對嘍,就是圖1中那4個目錄所對應的內容。
怎麼複製原始碼呢?是不是這個姿勢...
不必這樣,按照下面的圖片複製就好。
首先,Kernel目錄:
把LiteOS原始碼中kernel
目錄下的內容全部複製到工程裡的 .\LiteOS\Kernel
目錄下,然後再把.\LiteOS\Kernel\base\mem
目錄下的兩個子目錄bestfit
、tlsf
刪除。
接下來是Arch目錄:
從LiteOS原始碼arch\arm\arm-m
中複製兩個目錄src
、include
到工程.\LiteOS\Arch
目錄下。
然後,根據你的STM32晶片的具體架構(cortex-m3或cortex-m4 ??),選擇複製arch\arm\arm-m\contex-m?\keil\los_dispatch_keil.S
到工程.\LiteOS\Arch
目錄下。下圖,我的晶片是Cortex-m3的。
複製好以後,Arch目錄長這樣。
這個目錄下是與作業系統供應商無關的抽象層,複製LiteOS原始碼osdepends\liteos\cmsis
目錄中的檔案到工程目錄.\LiteOS\CMSIS
目錄下。
這個目錄下應放置和你晶片相匹配的組態檔,咱們先去LiteOS原始碼的targets
目錄下找一個合適的,然後把它裡面OS_Config
目錄下的標頭檔案(.h 檔案),複製到工程的.\LiteOS\Config
目錄下。
複製好以後,我的Config目錄是這個樣子的。
在Keil的IDE環境中,分別新增以下4個分組:
在LiteOS/Kernel分組下,我們新增上面複製在..\LiteOS\Kernel
目錄下(包含子目錄下)的所有.c
的原始檔。
在LiteOS/Arch分組下,新增..\LiteOS\Arch
目錄下(包含子目錄下)所有.c
的原始檔,還不夠,還有那個名為los_dispatch_keil.S
的組合原始檔也得新增。
在LiteOS/CMSIS分組下,新增..\LiteOS\CMSIS
目錄下的cmsis_liteos.c
。
在LiteOS/Config分組下,新增..LiteOS\Config
目錄下的所有.h
的標頭檔案,其實,這個分組不建,程式照樣能跑,但是,為了以後修改引數方便,我們還是先安排上吧。
新增內容如下:
../LiteOS/Arch/include
../LiteOS/Kernel/include
../LiteOS/Kernel/base/include
../LiteOS/Kernel/extended/include
../LiteOS/Config
../LiteOS/CMSIS
它們倆藏在一個叫stm32f?xx_it.c
的檔案中, 註釋掉就好。
記得前面建立的Keil工程分組LiteOS/Config
分組嗎?設定引數就藏在這兒。
分組中有個叫target_config.c
檔案,你可以根據使用的晶片,在這修改一下#define BOARD_SRAM_SIZE_KB 40
引數,據說,該值應該比晶片實際的SRAM略小。
其它的引數,在實際開發過程中,慢慢研究調整吧。我讀書少,更多的內容也搞不清楚。
到這裡,LiteOS的移植工作算是差不多了,接下來,點一盞燈,驗證一下"來時的路"。
在main.c 引入標頭檔案
#include "cmsis_os.h"
在main.c 申明倆個變數
/* Private variables ---------------------------------------------------------*/
/* USER CODE BEGIN PV */
osThreadId_t default_taskHandle;
const osThreadAttr_t default_task_attributes = {
.name = "default_task",
.stack_size = 512 * 4,
.priority = (osPriority_t) osPriorityNormal,
};
/* USER CODE END PV */
在main.c 申明兩個函數
/* USER CODE BEGIN PFP */
/* LITEOS BEGIN PFP */
void StartDefaultTask(void *argument);
void LiteOS_Init(void);
/* LITEOS END PFP */
/* USER CODE END PFP */
在main.c中,實現上面的函數
/* Private user code ---------------------------------------------------------*/
/* USER CODE BEGIN 0 */
void LiteOS_Init(void)
{
osKernelInitialize();
default_taskHandle = osThreadNew(StartDefaultTask, NULL, &default_task_attributes);
}
void StartDefaultTask(void *argument)
{
while(1)
{
/* 一燈大師,請試試在這裡點一盞燈。 */
HAL_GPIO_TogglePin(GPIOB,GPIO_PIN_13);
osDelay(200);
}
}
/* USER CODE END 0 */
在main.c中, int main(void)
函數體裡呼叫
/* USER CODE BEGIN 2 */
LiteOS_Init();
osKernelStart(); //注意,這東西要在main的while之前
/* USER CODE END 2 */
/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
{
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
}
/* USER CODE END 3 */
燈亮了嗎?祝您成功!
寫到這兒,不知道我講清除了沒有。還不行的話,我準備了一個手搓移植工具,要不您也試試。
我把它放這兒了,Python實現,有原始碼,改改給Makefile工程移植應該也行。它長下面這副德行:
LiteOS移植完成後,如果再次點選STM32CubeMX中的GENERATE CODE
按鈕,會把工具註釋掉的兩個中斷處理常式恢復出來,這時需要您手工註釋掉它們。PendSV_Handler
、SysTick_Handler
他們在..\Core\Src\stm32f?xx_it.c
檔案中。或者,也可以再次點選工具中的開始移植
按鈕,也能註釋掉它們。
根據實際情況設定LiteOS的BOARD_SRAM_SIZE_KB
引數, 這個值應略小於晶片的SRAM,LiteOS組態檔位於LiteOS\Config
分組下的target_config.h
檔案中,約在283行處 #define BOARD_SRAM_SIZE_KB 40
。 本工具定義了一些晶片的SRAM設定尺寸,由於個人能力問題,它們既不全面,也不準確。(工具中關於晶片設定定義,見stm32.py中的列舉類class STM32
)