移植uc/OS-III最新版到小熊派開(kāi)發(fā)板(STM32L431)
一、uc/OS全家桶
1. Micrium Software
Micrium Software提供了 RTOS 解決方案系列,俗稱ucos全家桶,其中最為出名的就是 ucOS-II 和ucOS-III,于 2016 年成為 Silicon Labs 的一部分。
2. μc/OS RTOS & stacks
ucos整條產(chǎn)品線非常豐富,常用的組件都有,官方叫做 μc/OS RTOS & stacks,民間叫做ucos全家桶。
作為一個(gè)上過(guò)火星的老牌RTOS,找機(jī)會(huì)體驗(yàn)一下還是很爽的,ucos全家桶中提供了非常豐富的內(nèi)容。
目前ucos全家桶中的產(chǎn)品大多數(shù)已經(jīng)在github開(kāi)源,遵循 Apache-2.0 開(kāi)源許可,開(kāi)源地址在:
“https://github.com/SiliconLabs
”
3. ucos內(nèi)核選擇
玩全家桶之前,肯定要先把RTOS內(nèi)核玩起來(lái),關(guān)于選擇ucos-II還是ucos-III是個(gè)老生長(zhǎng)談的問(wèn)題,上圖解決:
4. uc/OS-III源碼下載
uc/OS-III系統(tǒng)分為了三個(gè)開(kāi)源倉(cāng)庫(kù),要分別拉取。
① uC-OS3:
git?clone?https://github.com/SiliconLabs/uC-OS3.git
② uC-CPU:
git?clone?https://github.com/SiliconLabs/uC-CPU.git
③ uC-LIB:
git?clone?https://github.com/SiliconLabs/uC-LIB.git
二、移植前的準(zhǔn)備
本文中使用的開(kāi)發(fā)板為小熊派IoT開(kāi)發(fā)板,主控為STM32L431RCT6:
本文使用的開(kāi)發(fā)工具是MDK 5.30版本,編譯器版本為ARMCC5。
移植之前使用STM32CubeMX生成一份裸機(jī)工程,保證可以使用printf在串口正常打印。
三、移植uc/OS-III
1. 復(fù)制ucos內(nèi)核文件到工程中
“這里我全都復(fù)制過(guò)來(lái),后續(xù)可以將未添加到MDK中的文件刪除。
”
在工程下新建 ucOS-III 文件夾,存放ucOS-III相關(guān)文件。
① 復(fù)制ucos內(nèi)核文件夾過(guò)來(lái):
② 復(fù)制uC-CPU和uC-LIB兩個(gè)文件夾過(guò)來(lái):
2.添加文件到MDK工程
① 添加 ucos-iii/ports 分組,添加 Ports\ARM-Cortex-M\ARMv7-M 目錄下的os_cpu_c.c文件,以及該目錄下ARM目錄下的os_cpu_a.asm文件和 os_cpu_c.c文件:② 添加 ucos-iii/source分組,添加Source文件夾下的所有c文件(除去__dbg_uCOS-III.c):③ 添加uC-LIB分組,添加uC-LIB文件夾下的4個(gè)c文件:④ 添加uC-CPU分組,添加uC-CPU下的相關(guān)文件,如圖:⑤ 添加 ucos-iii/config 分組,添加配置文件,如下:
-
lib_cfg.h:uC-LIB\Cfg\Template -
os_cfg.h:Cfg\Template -
cpu_cfg.h:uC-CPU\Cfg\Template
3. 添加頭文件路徑到工程中
4. 修改配置文件
① 修改 cpu_cfg.h,配置本工程所使用內(nèi)核中CPU的NVIC優(yōu)先級(jí)位數(shù):
② 修改 os_cfg.h,關(guān)閉系統(tǒng)中 APP HOOKS 功能:
5. 處理中斷
RTOS中內(nèi)核得以運(yùn)行需要兩個(gè)中斷:
-
在pendSV異常處理中進(jìn)行任務(wù)切換 -
在systick異常處理中進(jìn)行內(nèi)核時(shí)鐘處理
首先包含進(jìn)來(lái)ucos的頭文件,修改 stm32l4xx_it.c 文件,在頭文件添加:
/*?Private?includes?----------------------------------------------------------*/
/*?USER?CODE?BEGIN?Includes?*/
#include?"os.h"
/*?USER?CODE?END?Includes?*/
① 處理pendSV異常,如下:
/**
??*?@brief?This?function?handles?Pendable?request?for?system?service.
??*/
void?PendSV_Handler(void)
{
??/*?USER?CODE?BEGIN?PendSV_IRQn?0?*/
???OS_CPU_PendSVHandler();
??/*?USER?CODE?END?PendSV_IRQn?0?*/
??/*?USER?CODE?BEGIN?PendSV_IRQn?1?*/
??/*?USER?CODE?END?PendSV_IRQn?1?*/
}
② 處理Systick異常,如下:
/**
??*?@brief?This?function?handles?System?tick?timer.
??*/
void?SysTick_Handler(void)
{
?/*?USER?CODE?BEGIN?SysTick_IRQn?0?*/
?
?/*?USER?CODE?END?SysTick_IRQn?0?*/
?HAL_IncTick();
?/*?USER?CODE?BEGIN?SysTick_IRQn?1?*/
?OS_CPU_SysTickHandler();
?
?/*?USER?CODE?END?SysTick_IRQn?1?*/
}
至此,移植完成。
四、測(cè)試系統(tǒng)調(diào)度和延時(shí)
在main.c中按照如下過(guò)程編寫測(cè)試代碼。
① 引入ucos頭文件:
/*?Private?includes?----------------------------------------------------------*/
/*?USER?CODE?BEGIN?Includes?*/
#include?
#include?"os.h"
/*?USER?CODE?END?Includes?*/
② 定義任務(wù)棧、任務(wù)控制塊、任務(wù)入口函數(shù):
/*?Private?variables?---------------------------------------------------------*/
/*?USER?CODE?BEGIN?PV?*/
static??OS_TCB???Task1TCB;
static??CPU_STK??Task1Stk[512];
static?void?Task1_entry(void?*p_arg)
{
?OS_ERR??err;
????
?(void)p_arg;
????
?while(1)
?{
????????printf("task1?is?running...\r\n");
?????OSTimeDly(1000,?OS_OPT_TIME_DLY,?&err);??
?}???
}
static??OS_TCB???Task2TCB;
static??CPU_STK??Task2Stk[512];
static?void?Task2_entry(void?*p_arg)
{
?OS_ERR??err;
????
?(void)p_arg;
????
?while(1)
?{
????????printf("task2?is?running...\r\n");
?????OSTimeDly(1000,?OS_OPT_TIME_DLY,?&err);??
?}???
}
/*?USER?CODE?END?PV?*/
③ 在main函數(shù)中定義錯(cuò)誤值變量:
??/*?USER?CODE?BEGIN?1?*/
????OS_ERR??err;
??/*?USER?CODE?END?1?*/
④ 在main函數(shù)中初始化內(nèi)核、創(chuàng)建兩個(gè)任務(wù)、啟動(dòng)內(nèi)核:
/*?USER?CODE?BEGIN?2?*/
printf("uc/OS-III?Port?On?BearPi?Board?By?Mculover666\r\n");
/*?初始化?uc/OS?內(nèi)核?*/
OSInit(&err);?
/*?創(chuàng)建task1?*/
OSTaskCreate((OS_TCB???????*)&Task1TCB,?????????//任務(wù)控制塊指針???????????
?????????????(CPU_CHAR?????*)"Task?1",??????????//任務(wù)名稱
?????????????(OS_TASK_PTR???)Task1_entry,???????//任務(wù)入口函數(shù)
?????????????(void?????????*)NULL,??????????????//任務(wù)入口函數(shù)的參數(shù)
?????????????(OS_PRIO???????)2,?????????????????//任務(wù)優(yōu)先級(jí)
?????????????(CPU_STK??????*)&Task1Stk[0],??????//任務(wù)棧地址
?????????????(CPU_STK_SIZE??)512?/?10,??????????//任務(wù)棧監(jiān)測(cè)區(qū)大小
?????????????(CPU_STK_SIZE??)512,???????????????//任務(wù)棧大小
?????????????(OS_MSG_QTY????)0,?????????????????//任務(wù)支持接受的最大消息數(shù)
?????????????(OS_TICK???????)0,?????????????????//時(shí)間片?*/
?????????????(void?????????*)0,?????????????????//堆??臻g大小??
?????????????(OS_OPT????????)(OS_OPT_TASK_STK_CHK?|?OS_OPT_TASK_STK_CLR),
?/*
?OS_OPT_TASK_STK_CHK??????使能檢測(cè)任務(wù)棧,統(tǒng)計(jì)任務(wù)棧已用的和未用的
?OS_OPT_TASK_STK_CLR??????在創(chuàng)建任務(wù)時(shí),清零任務(wù)棧
?*/??
?????????????(OS_ERR???????*)&err);
/*?創(chuàng)建task2?*/
OSTaskCreate((OS_TCB???????*)&Task2TCB,???
?????????????(CPU_CHAR?????*)"Task?2",
?????????????(OS_TASK_PTR???)Task2_entry,
?????????????(void?????????*)0,
?????????????(OS_PRIO???????)3,
?????????????(CPU_STK??????*)&Task2Stk[0],
?????????????(CPU_STK_SIZE??)512?/?10,
?????????????(CPU_STK_SIZE??)512,
?????????????(OS_MSG_QTY????)0,
?????????????(OS_TICK???????)0,
?????????????(void?????????*)0,
?????????????(OS_OPT????????)(OS_OPT_TASK_STK_CHK?|?OS_OPT_TASK_STK_CLR),
?????????????(OS_ERR???????*)&err);
/*?啟動(dòng)內(nèi)核?*/
OSStart(&err);
(void)&err;
/*?USER?CODE?END?2?*/
⑤ 編譯,下載,在串口助手中查看輸出:接下來(lái)就可以愉快的去玩uc/OS-III內(nèi)核啦~還可以玩玩全家桶,go go go!
接收更多精彩文章及資源推送,歡迎訂閱我的微信公眾號(hào):『mculover666』。
免責(zé)聲明:本文內(nèi)容由21ic獲得授權(quán)后發(fā)布,版權(quán)歸原作者所有,本平臺(tái)僅提供信息存儲(chǔ)服務(wù)。文章僅代表作者個(gè)人觀點(diǎn),不代表本平臺(tái)立場(chǎng),如有問(wèn)題,請(qǐng)聯(lián)系我們,謝謝!