微软在2019年对Express Logic的收购将其ThreadX实时操作系统带入了Azure。 现在已被称为Azure RTOS(开源的主页为 https://github.com/azure-rtos) ,它是一种工业级实时操作系统。ThreadX及其所有中间件的安全认证等级,至今没有一款小型RTOS可以与其匹敌。
各种安全等级基本都达到了最高。像工业级安全认证IEC61508,ThreadX满足最高等级SIL4,而SafeRTOS,embOS,uCOS-II都只是SIL3。
ThreadX和它功能极为全面的各种中间件如下图:
ThreadX的体系结构的一个优势是,很容易移植到新的芯片体系结构。现在拿前一节准备好的并且测试正常的OLED显示工程,直接移植,以下是过程。
内核源码可以在官方的Github下载:https://github.com/azure-rtos/threadx 将源码中的common和ports文件夹复制到原工程中:
将源码文件和ports文件添加到MDK的工程项目中,添加后的效果如下:
ThreadX/Ports分组文件位置
文件tx_initialize_low_level.s在路径ThreadX\ports\cortex_m4\ac5\example_build,其它文件在路径ThreadX\ports\cortex_m4\ac5\src
ThreadX/Source分组文件位置
全部在路径ThreadX\common\src,所有文件全部添加进来,推荐使用下面的方法添加,有效防止MDK大批量添加源文件造成的卡顿问题:
添加所有相关的源码文件,然后添加好工程的头文件路径以及添加相关预定义宏
原工程默认跑8MHz时钟,现需要修改时钟配置,更改到 200MHz主频
/* Define the initial systemcore clock. */
void CLK_SwitchTo200MHz()
{
en_clk_sys_source_t enSysClkSrc;
stc_clk_sysclk_cfg_t stcSysClkCfg;
stc_clk_xtal_cfg_t stcXtalCfg;
stc_clk_mpll_cfg_t stcMpllCfg;
stc_clk_freq_t stcClkFreq;
stc_clk_output_cfg_t stcOutputClkCfg;
stc_sram_config_t stcSramConfig;
MEM_ZERO_STRUCT(enSysClkSrc);
MEM_ZERO_STRUCT(stcSysClkCfg);
MEM_ZERO_STRUCT(stcXtalCfg);
MEM_ZERO_STRUCT(stcMpllCfg);
/* Set bus clk div. */
stcSysClkCfg.enHclkDiv = ClkSysclkDiv1;
stcSysClkCfg.enExclkDiv = ClkSysclkDiv2;
stcSysClkCfg.enPclk0Div = ClkSysclkDiv1;
stcSysClkCfg.enPclk1Div = ClkSysclkDiv2;
stcSysClkCfg.enPclk2Div = ClkSysclkDiv4;
stcSysClkCfg.enPclk3Div = ClkSysclkDiv4;
stcSysClkCfg.enPclk4Div = ClkSysclkDiv2;
CLK_SysClkConfig(&stcSysClkCfg);
/* Config Xtal and Enable Xtal */
stcXtalCfg.enMode = ClkXtalModeOsc;
stcXtalCfg.enDrv = ClkXtalLowDrv;
stcXtalCfg.enFastStartup = Enable;
CLK_XtalConfig(&stcXtalCfg);
CLK_XtalCmd(Enable);
/* Switch system clock source to XTAL. */
CLK_SetSysClkSource(ClkSysSrcXTAL);
/* Use Xtal as MPLL source. */
/* MPLL config (XTAL / pllmDiv * plln / PllpDiv = 50M). */
stcMpllCfg.pllmDiv = 1ul;
stcMpllCfg.plln = 50ul;
stcMpllCfg.PllpDiv = 8ul;
stcMpllCfg.PllqDiv = 8ul;
stcMpllCfg.PllrDiv = 8ul;
CLK_SetPllSource(ClkPllSrcXTAL);
CLK_MpllConfig(&stcMpllCfg);
/* flash read wait cycle setting */
EFM_Unlock();
EFM_SetLatency(EFM_LATENCY_1);
EFM_Lock();
/* sram init include read/write wait cycle setting */
stcSramConfig.u8SramIdx = Sram12Idx | Sram3Idx | SramHsIdx | SramRetIdx;
stcSramConfig.enSramRC = SramCycle2;
stcSramConfig.enSramWC = SramCycle2;
stcSramConfig.enSramEccMode = EccMode3;
stcSramConfig.enSramEccOp = SramNmi;
stcSramConfig.enSramPyOp = SramNmi;
SRAM_Init(&stcSramConfig);
/* Enable MPLL. */
CLK_MpllCmd(Enable);
/* Wait MPLL ready. */
while (Set != CLK_GetFlagStatus(ClkFlagMPLLRdy))
{
;
}
/* Switch system clock source to MPLL. */
CLK_SetSysClkSource(CLKSysSrcMPLL);
/* Check source and frequency. */
enSysClkSrc = CLK_GetSysClkSource();
CLK_GetClockFreq(&stcClkFreq);
/* flash read wait cycle setting */
EFM_Unlock();
EFM_SetLatency(EFM_LATENCY_4);
EFM_Lock();
/* Switch driver ability */
PWC_HS2HP();
/* MPLL config (XTAL / pllmDiv * plln / PllpDiv = 200M). */
stcMpllCfg.pllmDiv = 1ul;
stcMpllCfg.plln = 50ul;
stcMpllCfg.PllpDiv = 2ul;
stcMpllCfg.PllqDiv = 2ul;
stcMpllCfg.PllrDiv = 2ul;
CLK_SetPllSource(ClkPllSrcXTAL);
CLK_MpllConfig(&stcMpllCfg);
SystemCoreClock = 200000000 ;
}
需要将startup_hc32f46x.s 中的堆栈大小加大
Stack_Size EQU 0x00001400
Heap_Size EQU 0x00000600
ThreadX为MDK AC5提供的这个文件有点欠妥,因为ThreadX通过这个文件直接接管了我们一直使用的xxxx.S启动文件。但接管的文件仅写了几个重要的中断向量表入口。这就给让移植的人非常不方便。所以我们做的例子不接管XXX.S启动文件了,方便大家移植。本周教程配套例子使用的这个文件已经做了修改,推荐大家直接复制粘贴到自己的工程即可,内容如下:
注意:下面代码中置红部分的参数需要大家配置,即芯片主频和系统时钟节拍。
SYSTEM_CLOCK EQU 200000000
SYSTICK_CYCLES EQU ((SYSTEM_CLOCK / 1000) -1)
200000000是系统时钟主频,1000对应的就是系统时钟节拍,这里1000就表示1000Hz。
其它的修改详见附件工程即可。
ThreadX内核相关的配置,已经全部整理到了这个文件中,并且做中文注释,大家可以更新需要使能宏定义。本工程中全部注释掉。
应用程序比较简单,大家可以直接复制本章教程配置例子的main.c文件中的内容到自己工程里面测试。主要在tx_application_define里面创建两个任务:
thread_0_entry :闪灯任务
thread_1_entry :OLED显示任务
本次评测内容主要介绍了移植思路,具体可以参考后续文章中的附件工程,另外需要掌握ThreadX内核框架设计,这有助于移植。
实验现象:可以看到板载的LED每秒闪烁一次,另外显示屏会有显示:
大佬大佬,跪求该工程!!!万分感谢