在STM32CubeMX生成的工程中增加并编译RTX5源码
前言:
STM32CubeMX是意法推出的基于STM32的一款强大的可视化开发软件,在常规的产品开发中,可以结合可视化的硬件配置来完成系统平台的初始化配置,选用一些中间软件包,如OS,FS等。
RTX5是Keil公司打造的一款轻量型,实时,低延迟,高可靠,安全的操作系统,MDK开发环境本身集成了RTX5软件包。但STM32CubeMX中不包含RTX5组件包,并不支持RTX5组件包,这需要在STM32CubeMXb生成的工程文件中手动添加RTX5软件包,下面详细阐述该过程,并对其中的编译错误的更正过程进行了的说明。
开发环境:
- MDK 5.25
- STM32CubeMX 4.25
- STM32CubeMX STM32F4 组件包版本为1.21.0
- RTX5 5.3.0
一. 在STM32CubeMX生成的工程中添加RTX5源码
1. 打开STM32CubeMX工程
如果中间件FreeRTOS被勾选,要勾选掉,防止两个操作系统同时存在:
2. 生成MDK工程代码
在STM32CubeMX,生成并打开MDK工程代码。
在MDK的工程Options for target ...的Output选显卡中,勾选掉默认的选项"Browse Iniormation",这样可以加快编译速度,否则编译会非常耗时。
3. 增加RTX5软件组件:
添加RTOS2-->Keil RTX5,这里为5.3.0版本(单击图片可放大):
如提示出现“Validation Output",点击信息框下面的"Resolve"。
有两种添加RTX5的方式:库和源代码。这里重点说明如何对添加的RTX5源码进行工程编译,所以这里选择"Source"。
上图 “Keil RTX5”对应的右侧栏目选择"Source",然后点击"Resolve"。
二. 工程编译错误的解决
1. "Unknown Arm Architecture!"错误
尝试工程编译,会提示如下的编译错误:
error: #35: #error directive: "Unknown Arm Architecture!"
删除工程目录Drivers\CMSIS\Include\下的cmsis_armcc.h
这样工程会使用C:\Keil_v5\ARM\PACK\ARM\CMSIS\5.3.0\CMSIS\Include\cmsis_armcc.h
后一个文件的文件头代码如下:
#if defined(__ARMCC_VERSION) && (__ARMCC_VERSION < 400677)
#error "Please use Arm Compiler Toolchain V4.0.677 or later!"
#endif
/* CMSIS compiler control architecture macros */
#if ((defined (__TARGET_ARCH_6_M ) && (__TARGET_ARCH_6_M == 1)) || \
(defined (__TARGET_ARCH_6S_M ) && (__TARGET_ARCH_6S_M == 1)) )
#define __ARM_ARCH_6M__ 1
#endif
#if (defined (__TARGET_ARCH_7_M ) && (__TARGET_ARCH_7_M == 1))
#define __ARM_ARCH_7M__ 1
#endif
#if (defined (__TARGET_ARCH_7E_M) && (__TARGET_ARCH_7E_M == 1))
#define __ARM_ARCH_7EM__ 1
#endif
/* __ARM_ARCH_8M_BASE__ not applicable */
/* __ARM_ARCH_8M_MAIN__ not applicable */
/* CMSIS compiler specific defines */
#ifndef __ASM
#define __ASM __asm
#endif
#ifndef __INLINE
#define __INLINE __inline
#endif
#ifndef __STATIC_INLINE
#define __STATIC_INLINE static __inline
#endif
#ifndef __STATIC_FORCEINLINE
#define __STATIC_FORCEINLINE static __forceinline
#endif
#ifndef __NO_RETURN
#define __NO_RETURN __declspec(noreturn)
#endif
#ifndef __USED
#define __USED __attribute__((used))
#endif
#ifndef __WEAK
#define __WEAK __attribute__((weak))
#endif
...
而在STM32CubeMX生成的Drivers\CMSIS\Include\下的cmsis_armcc.h的文件中并无这些宏定义。
特别,如下宏定义分支有效:
#if (defined (__TARGET_ARCH_7_M ) && (__TARGET_ARCH_7_M == 1))
#define __ARM_ARCH_7M__ 1
#endif
2. 代码重复冲突错误
再次编译,会出现如下错误:
error: L6235E: More than one section matches selector - cannot all be FIRST/LAST.
这是由于STM32CubeMX生成的工程所包含的启动文件"startup_stm32f439xx.s"(Application/MDK-ARM工程文件夹下,见下图)中,已经存在RESET段。这和RTX5的启动文件"startup_stm32f439xx.s"(Deviece工程文件夹下,见下图)中的代码相冲突:
将Application/MDK-ARM工程文件夹下的"startup_stm32f439xx.s"文件排除在编译之外:
右键点击Application/MDK-ARM工程文件夹下的文件"startup_stm32f439xx.s",
选中“Options for startup_stm32f439xx.s”菜单,弹出(单击图片可放大):
勾选掉“include in Target Build",如上图(“include in Target Build"未勾选掉之前)。
编译工程,会出现如下错误:
Error: L6200E: Symbol SystemCoreClock multiply defined (by system_stm32f4xx_1.o and system_stm32f4xx.o).
Error: L6200E: Symbol AHBPrescTable multiply defined (by system_stm32f4xx_1.o and system_stm32f4xx.o).
Error: L6200E: Symbol APBPrescTable multiply defined (by system_stm32f4xx_1.o and system_stm32f4xx.o).
rror: L6200E: Symbol SVC_Handler multiply defined (by stm32f4xx_it.o and irq_cm4f.o).
(单击图片可放大)
同样的,这是由于STM32CubeMX生成的工程所包含的文件"system_stm32f4xx.c"(Drivers/CMSIS工程文件夹下,见下图)中,已经存在上面编译错误中的段。这和RTX5的文件"system_stm32f4xx.c"(Deviece工程文件夹下,见下图)中的代码相冲突:
将Drivers/CMSIS工程文件夹中的"system_stm32f4xx.c"排除在编译之外。
工程编译,会提示:
Error: L6200E: Symbol SVC_Handler multiply defined (by stm32f4xx_it.o and irq_cm4f.o).
Error: L6200E: Symbol PendSV_Handler multiply defined (by stm32f4xx_it.o and irq_cm4f.o).
Error: L6200E: Symbol SysTick_Handler multiply defined (by stm32f4xx_it.o and irq_cm4f.o).
同样的,将文件"stm32f4xx_it.c"排除在编译之外。
3. RTX5示例演示
增加RTX5示例代码:
在"Application/MDK-ARM"列表上点击右键,在弹出的菜单中选中"Add New Item to Group 'Application/User'":
弹出对话框:
注意要防止这里的man.c文件存放路径和STM32CubeMX生成的main.c文件的路径相冲突。
在工程中排除掉"Application/User"下的main.c文件的编译。
最后的工程文件列表如下(红色框处的标注为排除在工程编译之外的文件):
编译工程,提示:
STM32F429_176\STM32F429_176.axf: Error: L6218E: Undefined symbol _Error_Handler (referred from tim.o).
复制"Application/User"下的main.c中的_Error_Handler函数到新增的"Application/MDK-ARM"下的main.c文件中。
在main.c中新增任务,最后的代码如下:
/*----------------------------------------------------------------------------
* Application main thread
*---------------------------------------------------------------------------*/
void task1 (void *argument)
{
// ...
for (;;){
osDelay(30);
}
}
void task2 (void *argument)
{
// ...
for (;;){
osDelay(20);
}
}
int main (void) {
// System Initialization
SystemCoreClockUpdate();
#ifdef RTE_Compiler_EventRecorder
// Initialize and start Event Recorder
EventRecorderInitialize(EventRecordError, 1U);
#endif
// ...
osKernelInitialize(); // Initialize CMSIS-RTOS
osThreadNew(task1, NULL, NULL); // Create application main thread
osThreadNew(task2, NULL, NULL); // Create application main thread
osKernelStart(); // Start thread execution
for (;;) {}
}
最后,在MDK的"Project"中,Clean Targets,再次全部编译。
注意,Clean Targets这一步是必须的,否则,调试启动时,无法跳转到最终所使用的main.c文件的main函数中。
工程示例代码:
https://pan.baidu.com/s/16_bsWqH3kbyfvMa6Bjm_Ww