在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被勾选,要勾选掉,防止两个操作系统同时存在:
在STM32CubeMX生成的工程中增加并编译RTX5源码

2. 生成MDK工程代码
在STM32CubeMX,生成并打开MDK工程代码。
在MDK的工程Options for target ...的Output选显卡中,勾选掉默认的选项"Browse Iniormation",这样可以加快编译速度,否则编译会非常耗时。

3. 增加RTX5软件组件:
在STM32CubeMX生成的工程中增加并编译RTX5源码
添加RTOS2-->Keil RTX5,这里为5.3.0版本(单击图片可放大):
在STM32CubeMX生成的工程中增加并编译RTX5源码
如提示出现“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工程文件夹下,见下图)中的代码相冲突:
在STM32CubeMX生成的工程中增加并编译RTX5源码

将Application/MDK-ARM工程文件夹下的"startup_stm32f439xx.s"文件排除在编译之外:
右键点击Application/MDK-ARM工程文件夹下的文件"startup_stm32f439xx.s",
选中“Options for startup_stm32f439xx.s”菜单,弹出(单击图片可放大):
在STM32CubeMX生成的工程中增加并编译RTX5源码
勾选掉“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生成的工程中增加并编译RTX5源码
同样的,这是由于STM32CubeMX生成的工程所包含的文件"system_stm32f4xx.c"(Drivers/CMSIS工程文件夹下,见下图)中,已经存在上面编译错误中的段。这和RTX5的文件"system_stm32f4xx.c"(Deviece工程文件夹下,见下图)中的代码相冲突:
在STM32CubeMX生成的工程中增加并编译RTX5源码
将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'":
在STM32CubeMX生成的工程中增加并编译RTX5源码
弹出对话框:
在STM32CubeMX生成的工程中增加并编译RTX5源码
注意要防止这里的man.c文件存放路径和STM32CubeMX生成的main.c文件的路径相冲突。
在工程中排除掉"Application/User"下的main.c文件的编译。
最后的工程文件列表如下(红色框处的标注为排除在工程编译之外的文件):
在STM32CubeMX生成的工程中增加并编译RTX5源码
编译工程,提示:
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