你的浏览器版本过低,可能导致网站不能正常访问!
为了你能正常使用网站功能,请使用这些浏览器。

【经验分享】STM32H7 RTX5操作系统移植(MDK AC5)

[复制链接]
STMCU小助手 发布时间:2021-12-30 14:32
4.1   初学者重要提示
  当前RTX5可以移植到GCC,MDK和IAR三大平台,考虑到仅MDK平台下有RTX5的调试组件,我们这里仅提供了MDK的移植说明。
  STM32H7使用MDK RTE环境添加RTX5,需要强制运行一次STM32CubeMX,因为H7已经没有配套RTE经典添加方式,而STM32F4是支持经典方式的,所以无需运行STM32CubeMX,详情可以看我们STM32F4开发板对应的RTX5教程。
4.2   移植RXT5内核整体说明
移植之前,有必要对移植过程有个整体的认识:

  第1步,准备一个工程模板。
  第2步,移植RTX5。
  移植RTX5是采用MDK的RTE环境直接添加。当前H7芯片使用RTX5强制运行STM32CubeMX,所以需要大家提前安装好STM32CubeMX V5.4或者以上版本。
  第3步,处理HAL库时间基准,MPU配置等。
  第4步,创建应用。

总的来说,这4步就可以完成移植, 下面将STM32H7的移植步骤和注意事项为大家做个说明。

4.3   了解RTX5内核模板框架设计
移植RTX5前,我们优先了解下移植好的RTX5内核模板,方面大家后面移植:

ebf7bed4831890980f518eaeb842a943.png


框图如下:

cc3f4f5af7e41dcb23a03a25e14d8ae7.png


4.4   第1步,安装指定的MDK软件包版本
移植新版RTX5需要大家下载当前最新的MDK软件包版本(如果有最新版,推荐大家用最新版):

  CMSIS 软件包使用当前最新的:V5.7.0
  STM32H7使用当前最新的:V2.6.0
  STM32F4使用当前最新的:V2.6.0
  STM32CubeMX使用当前最新的:V6.0.x
  ARM_Compiler使用当前最新的:V1.6.1

不管以后MDK的软件包版本如何升级,当前的软件包版本和以后的新版是可以同时安装的,也就是说可以安装多个不同版本,在这里可以选择指定版本:

bbb84b8c4b3275b1026d2c95b5012294.png


4.5   第2步,准备一个工程模板
首先准备好一个简单的裸机工程模板,已经为大家做好:V7-400_Base Template,准备好的工程模板如下图所示(大家也可以制作其它任意的工程模板,不限制):

5618d5a487ef825c0a75ce19685c4821.png


4.6   第3步,添加RTX5并配置
RTX5可以方便的通过MDK的RTE环境添加进来。对于H7版本,MDK会强制运行一次CubeMX,并添加很多H7的HAL库文件,这些库文件我们可以使用,也可以不使用。教程配套的工程文件是不使用这些,因为前面的工程模板里面已经添加了。所以要将这些文件全部隔离出来。

4.6.1      添加RTX5源码

48f11b91f9fc45f3f04431047156434d.png


点击OK按钮后,弹出如下界面:

b430f5f7b2e1a16de73553adb9dd1f89.png


点击Start STM32CubeMX,这里需要大家电脑上已经安装了STM32CubeMX,并且为其安装了H7的软件包。

af4f52889e56b18313faf6baa5ed1281.png


打开后,用户仅需配置如下地方即可:

7c8a9271ba3d0ccb045c81921fd97d0f.png


然后点击右上角的GENERATE CODE:

62747d5251f02d427c05caf48fc46d77.png


然后弹出如下对话框,点击Close即可,然后关闭STM32CubeMX。

1a4404327c06b66c217f46c74bd48db2.png


重新回到MDK,会有一个对话框,点击是即可:

cdfb3b29fdf8c8b60f0d85f8aaa161ff.png


最后就可以看到RTX5源码已经添加到工程里面了:

e49f340b4464ddd3afb5bf5082de0fdd.png


4.6.2      将自动添加的库文件隔离出来
添加的所有文件中,仅RTX5和文件stm32h7xx_hal_msp.c留下,其它文件全部隔离出来,隔离方法也比较简单,比如隔离生成的main.c函数,鼠标右击此文件选择Options for file ‘main.c’

3b989ad148a2ec7c0522490cd84fcf3c.png


然后取消掉include Target Build前的对勾,点击OK:

6652eec0f1078d33b6c1508049d0c922.png


看到main.c文件上有个红色横杠,就表示已经隔离出来了:

cafbe4a03ab78632d36b9cf1b050250c.png


同样的方法,将stm32h7xx_it.c文件也隔离出来,文件stm32h7xx_it.h不用管。

Device下面的这些文件也是同样的隔离方法:

f46dbe6e1b27dd459e04cba9849d9ff9.png


只是鼠标右击弹出的界面有些不同:

aeccd1d366ee4da23ceff332ae2f84e5.png


注意stm32h7xx_hal_msp.c无需隔离,其它所有的文件全部隔离,stm32h7xx_hal_msp.c对应的隔离配置是STM32CubeMX,如果也隔离了,编译会有问题:

59f0e5e7d43f7ac7e983147c132a42ce.png


隔离后的效果如下:

573fb2c99aa8ef7ef6f577c106084913.png


4.6.3      RTX5配置
剩下就是配置RTX5,设置RTX_Config.h文件即可,移植阶段先按照如下设置配置好,后面章节会专门为大家讲解每个参数的配置含义:

576cda809f95be40653ff18b9682f906.png


4.7   第4步,MPU和Cache配置文件bsp.c
这个bsp.c文件也比较重要,移植阶段,直接将我们移植好的模板内容复制过去即可,这里把相关的内容为大家做个说明。

4.7.1      函数System_Init

系统初始化,主要是MPU,Cache和系统时钟配置,需要在RTX5初始化之前调用。

  1. /*
  2. *********************************************************************************************************
  3. *    函 数 名: System_Init
  4. *    功能说明: 系统初始化,主要是MPU,Cache和系统时钟配置
  5. *    形    参:无
  6. *    返 回 值: 无
  7. *********************************************************************************************************
  8. */
  9. void System_Init(void)
  10. {

  11.     /* 配置MPU */
  12.     MPU_Config();

  13.     /* 使能L1 Cache */
  14.     CPU_CACHE_Enable();

  15.     /*
  16.        STM32H7xx HAL 库初始化,此时系统用的还是H7自带的64MHz,HSI时钟:
  17.        - 调用函数HAL_InitTick,初始化滴答时钟中断1ms。
  18.        - 设置NVIV优先级分组为4。
  19.      */
  20.     HAL_Init();

  21.     /*
  22.        配置系统时钟到400MHz
  23.        - 切换使用HSE。
  24.        - 此函数会更新全局变量SystemCoreClock,并重新配置HAL_InitTick。
  25.     */
  26.     SystemClock_Config();

  27.     /*
  28.        Event Recorder:
  29.        - 可用于代码执行时间测量,MDK5.25及其以上版本才支持,IAR不支持。
  30.        - 默认不开启,如果要使能此选项,务必看V7开发板用户手册第8章
  31.     */   
  32. #if Enable_EventRecorder == 1  
  33.     /* 初始化EventRecorder并开启 */
  34.     EventRecorderInitialize(EventRecordAll, 1U);
  35.     EventRecorderStart();
  36. #endif

  37. }
复制代码

4.7.2      函数bsp_Init
硬件外设的初始化,这个函数在RTX5的启动任务里面调用。

  1. /*
  2. *********************************************************************************************************
  3. *    函 数 名: bsp_Init
  4. *    功能说明: 初始化所有的硬件设备。该函数配置CPU寄存器和外设的寄存器并初始化一些全局变量。只需要调用一次
  5. *    形    参: 无
  6. *    返 回 值: 无
  7. *********************************************************************************************************
  8. */
  9. void bsp_Init(void)
  10. {
  11.     bsp_InitDWT();     /* 初始化DWT时钟周期计数器 */      
  12.     bsp_InitKey();        /* 按键初始化,要放在滴答定时器之前,因为按钮检测是通过滴答定时器扫描 */
  13.     bsp_InitUart();    /* 初始化串口 */
  14.     bsp_InitExtIO();    /* 初始化FMC总线74HC574扩展IO. 必须在 bsp_InitLed()前执行 */   
  15.     bsp_InitLed();        /* 初始化LED */   
  16.     bsp_InitTimer();      /* 初始化滴答定时器 */
  17. }
复制代码

4.7.3      函数SystemClock_Config
这个函数主要是完成系统时钟配置。

  1. /*
  2. *********************************************************************************************************
  3. *    函 数 名: SystemClock_Config
  4. *    功能说明: 初始化系统时钟
  5. *                System Clock source            = PLL (HSE)
  6. *                SYSCLK(Hz)                     = 400000000 (CPU Clock)
  7. *               HCLK(Hz)                       = 200000000 (AXI and AHBs Clock)
  8. *                AHB Prescaler                  = 2
  9. *                D1 APB3 Prescaler              = 2 (APB3 Clock  100MHz)
  10. *                D2 APB1 Prescaler              = 2 (APB1 Clock  100MHz)
  11. *                D2 APB2 Prescaler              = 2 (APB2 Clock  100MHz)
  12. *                D3 APB4 Prescaler              = 2 (APB4 Clock  100MHz)
  13. *                HSE Frequency(Hz)              = 25000000
  14. *               PLL_M                          = 5
  15. *                PLL_N                          = 160
  16. *                PLL_P                          = 2
  17. *                PLL_Q                          = 4
  18. *                PLL_R                          = 2
  19. *                VDD(V)                         = 3.3
  20. *                Flash Latency(WS)              = 4
  21. *    形    参: 无
  22. *    返 回 值: 无
  23. *********************************************************************************************************
  24. */
  25. static void SystemClock_Config(void)
  26. {
  27.    省略未写

  28.    /* AXI SRAM的时钟是上电自动使能的,而D2域的SRAM1,SRAM2和SRAM3要单独使能 */   
  29. #if 1
  30.     __HAL_RCC_D2SRAM1_CLK_ENABLE();
  31.     __HAL_RCC_D2SRAM2_CLK_ENABLE();
  32.     __HAL_RCC_D2SRAM3_CLK_ENABLE();

  33.     __HAL_RCC_BKPRAM_CLKAM_ENABLE();      
  34.     __HAL_RCC_D3SRAM1_CLKAM_ENABLE();
  35. #endif
  36. }
复制代码

这里的RAM时钟初始化比较重要,这几个RAM的时钟都要单独使能。

4.7.4      函数MPU_Config
RTX5例子默认采用AXI SRAM作为主RAM空间,因为空间比较大,方便我们后制作综合例子使用:

  1. /*
  2. *********************************************************************************************************
  3. *    函 数 名: MPU_Config
  4. *    功能说明: 配置MPU
  5. *    形    参: 无
  6. *    返 回 值: 无
  7. *********************************************************************************************************
  8. */
  9. static void MPU_Config( void )
  10. {
  11.     MPU_Region_InitTypeDef MPU_InitStruct;

  12.     /* 禁止 MPU */
  13.     HAL_MPU_Disable();

  14. /* 最高性能,读Cache和写Cache都开启 */   
  15. #if 1
  16.        /* 配置AXI SRAM的MPU属性为Write back, Read allocate,Write allocate */
  17.     MPU_InitStruct.Enable           = MPU_REGION_ENABLE;
  18.     MPU_InitStruct.BaseAddress      = 0x24000000;
  19.     MPU_InitStruct.Size             = MPU_REGION_SIZE_512KB;
  20.     MPU_InitStruct.AccessPermission = MPU_REGION_FULL_ACCESS;
  21.     MPU_InitStruct.IsBufferable     = MPU_ACCESS_BUFFERABLE;
  22.     MPU_InitStruct.IsCacheable      = MPU_ACCESS_CACHEABLE;
  23.     MPU_InitStruct.IsShareable      = MPU_ACCESS_NOT_SHAREABLE;
  24.     MPU_InitStruct.Number           = MPU_REGION_NUMBER0;
  25.     MPU_InitStruct.TypeExtField     = MPU_TEX_LEVEL1;
  26.     MPU_InitStruct.SubRegionDisable = 0x00;
  27.     MPU_InitStruct.DisableExec      = MPU_INSTRUCTION_ACCESS_ENABLE;

  28.     HAL_MPU_ConfigRegion(&MPU_InitStruct);

  29. /* 最低性能,读Cache和写Cache都关闭 */
  30. #else
  31.     /* 配置AXI SRAM的MPU属性为NORMAL, NO Read allocate,NO Write allocate */
  32.     MPU_InitStruct.Enable           = MPU_REGION_ENABLE;
  33.     MPU_InitStruct.BaseAddress      = 0x24000000;
  34.     MPU_InitStruct.Size             = MPU_REGION_SIZE_512KB;
  35.     MPU_InitStruct.AccessPermission = MPU_REGION_FULL_ACCESS;
  36.     MPU_InitStruct.IsBufferable     = MPU_ACCESS_NOT_BUFFERABLE;
  37.     MPU_InitStruct.IsCacheable      = MPU_ACCESS_NOT_CACHEABLE;
  38.     MPU_InitStruct.IsShareable      = MPU_ACCESS_NOT_SHAREABLE;
  39.     MPU_InitStruct.Number           = MPU_REGION_NUMBER0;
  40.     MPU_InitStruct.TypeExtField     = MPU_TEX_LEVEL1;
  41.     MPU_InitStruct.SubRegionDisable = 0x00;
  42.     MPU_InitStruct.DisableExec      = MPU_INSTRUCTION_ACCESS_ENABLE;

  43.     HAL_MPU_ConfigRegion(&MPU_InitStruct);
  44. #endif

  45.     /* 配置FMC扩展IO的MPU属性为Device或者Strongly Ordered */
  46.     MPU_InitStruct.Enable           = MPU_REGION_ENABLE;
  47.     MPU_InitStruct.BaseAddress      = 0x60000000;
  48.     MPU_InitStruct.Size             = ARM_MPU_REGION_SIZE_64KB;   
  49.     MPU_InitStruct.AccessPermission = MPU_REGION_FULL_ACCESS;
  50.     MPU_InitStruct.IsBufferable     = MPU_ACCESS_BUFFERABLE;
  51.     MPU_InitStruct.IsCacheable      = MPU_ACCESS_NOT_CACHEABLE;   
  52.     MPU_InitStruct.IsShareable      = MPU_ACCESS_NOT_SHAREABLE;
  53.     MPU_InitStruct.Number           = MPU_REGION_NUMBER1;
  54.     MPU_InitStruct.TypeExtField     = MPU_TEX_LEVEL0;
  55.     MPU_InitStruct.SubRegionDisable = 0x00;
  56.     MPU_InitStruct.DisableExec      = MPU_INSTRUCTION_ACCESS_ENABLE;

  57.     HAL_MPU_ConfigRegion(&MPU_InitStruct);

  58.     /* 使能 MPU */
  59.     HAL_MPU_Enable(MPU_PRIVILEGED_DEFAULT);
  60. }
复制代码

4.7.5      函数bsp_RunPer10ms
这个函数里面默认有个按键扫描,如果大家移植的程序里面没有按键初始化,务必要把这个按键扫描函数注释掉。

  1. /*
  2. *********************************************************************************************************
  3. *    函 数 名: bsp_RunPer10ms
  4. *    功能说明: 该函数每隔10ms被Systick中断调用1次。详见 bsp_timer.c的定时中断服务程序。一些处理时间要求
  5. *             不严格的任务可以放在此函数。比如:按键扫描、蜂鸣器鸣叫控制等。
  6. *    形    参: 无
  7. *    返 回 值: 无
  8. *********************************************************************************************************
  9. */
  10. void bsp_RunPer10ms(void)
  11. {
  12.     bsp_KeyScan10ms();
  13. }
复制代码

4.8   第5步,更新bsp_timer.c和bsp.h文件
更新bsp_timer.c文件是因为此文件跟RTX5都要使用滴答定时器,有冲突。所以大家直接将我们工程模板里面此文件覆盖移植的这个文件即可。

bsp.h文件里面要添加一个宏定义,因为bsp_timer.c文件里面做了些条件编译:

#define  USE_RTX    1

另外,bsp.h文件将大部分头文件都添加进来了,大家可以根据需要,用到那些头文件,使能那些,用不到的,可以注释掉。当然,不注释也是没问题的:

  1. /* 通过取消注释或者添加注释的方式控制是否包含底层驱动模块 */
  2. //#include "bsp_msg.h"
  3. //#include "bsp_user_lib.h"
  4. #include "bsp_timer.h"
  5. #include "bsp_led.h"
  6. #include "bsp_key.h"
  7. #include "bsp_dwt.h"

  8. //#include "bsp_cpu_rtc.h"
  9. //#include "bsp_cpu_adc.h"
  10. //#include "bsp_cpu_dac.h"
  11. #include "bsp_uart_fifo.h"
  12. //#include "bsp_uart_gps.h"
  13. //#include "bsp_uart_esp8266.h"
  14. //#include "bsp_uart_sim800.h"

  15. //#include "bsp_spi_bus.h"
  16. //#include "bsp_spi_ad9833.h"
  17. //#include "bsp_spi_ads1256.h"
  18. //#include "bsp_spi_dac8501.h"
  19. //#include "bsp_spi_dac8562.h"
  20. //#include "bsp_spi_flash.h"
  21. //#include "bsp_spi_tm7705.h"
  22. //#include "bsp_spi_vs1053b.h"

  23. //#include "bsp_fmc_sdram.h"
  24. //#include "bsp_fmc_nand_flash.h"
  25. //#include "bsp_fmc_ad7606.h"
  26. //#include "bsp_fmc_oled.h"
  27. #include "bsp_fmc_io.h"

  28. //#include "bsp_i2c_gpio.h"
  29. //#include "bsp_i2c_bh1750.h"
  30. //#include "bsp_i2c_bmp085.h"
  31. //#include "bsp_i2c_eeprom_24xx.h"
  32. //#include "bsp_i2c_hmc5883l.h"
  33. //#include "bsp_i2c_mpu6050.h"
  34. //#include "bsp_i2c_si4730.h"
  35. //#include "bsp_i2c_wm8978.h"

  36. //#include "bsp_tft_h7.h"
  37. //#include "bsp_tft_429.h"
  38. //#include "bsp_tft_lcd.h"
  39. //#include "bsp_ts_touch.h"
  40. //#include "bsp_ts_ft5x06.h"
  41. //#include "bsp_ts_gt811.h"
  42. //#include "bsp_ts_gt911.h"
  43. //#include "bsp_ts_stmpe811.h"

  44. #include "bsp_beep.h"
  45. #include "bsp_tim_pwm.h"
  46. //#include "bsp_sdio_sd.h"
  47. //#include "bsp_dht11.h"
  48. //#include "bsp_ds18b20.h"
  49. //#include "bsp_ps2.h"
  50. //#include "bsp_ir_decode.h"
  51. //#include "bsp_camera.h"
  52. //#include "bsp_rs485_led.h"
  53. //#include "bsp_can.h"
复制代码

4.9   第6步,修改文件stm32h7xx_it.c
删除此文件里面带的如下函数,RTX5要使用,冲突了。

  1. /**
  2.   * @brief  This function handles SVCall exception.
  3.   * @param  None
  4.   * @retval None
  5.   */
  6. void SVC_Handler(void)
  7. {
  8. }

  9. /**
  10.   * @brief  This function handles PendSVC exception.
  11.   * @param  None
  12.   * @retval None
  13.   */
  14. void PendSV_Handler(void)
  15. {
  16. }
复制代码

4.10 第7步,添加头文件的汇总文件includes.h
在User文件夹下添加文件incudes.h,直接从本章节教程配套例子的User文件夹复制即可。此文件主要用于RTX5的各种头文件汇总。

63fafbc927e6b911f6f3b81c4acb6af1.png


4.11 第8步,HAL库时间基准stm32h7xx_hal_timebase_tim.c

由于RTX5和HAL库需要一个时间基准,而且默认都是用的滴答定时器,所有要有一个选用其它的时间基准。当前的处理方案是为HAL库提供一个时间基准文件stm32h7xx_hal_timbase_tim.c。此文件

里面做了两套方案,一个是使用TIM7做时间基准,另一个是使用RTX5的API做时间基准,通过条件编译做选择。默认是采用RTX5的API做时间基准。

  1. /*
  2. *********************************************************************************************************
  3. *    函 数 名: HAL_Delay
  4. *    功能说明: 重定向毫秒延迟函数。替换HAL中的函数。因为HAL中的缺省函数依赖于Systick中断,如果在USB、SD
  5. *             卡中断中有延迟函数,则会锁死。也可以通过函数HAL_NVIC_SetPriority提升Systick中断
  6. *    形    参: 无
  7. *    返 回 值: 无
  8. *********************************************************************************************************
  9. */
  10. void HAL_Delay(uint32_t Delay)
  11. {
  12.     bsp_DelayMS(Delay);
  13. }

  14. HAL_StatusTypeDef HAL_InitTick (uint32_t TickPriority)
  15. {
  16.     return HAL_OK;
  17. }

  18. uint32_t HAL_GetTick (void)
  19. {
  20.     static uint32_t ticks = 0U;
  21.     uint32_t i;

  22.     if (osKernelGetState () == osKernelRunning)
  23.     {
  24.         return ((uint32_t)osKernelGetTickCount ());
  25.     }

  26.     /* 如果RTX5还没有运行,采用下面方式 */
  27.     for (i = (SystemCoreClock >> 14U); i > 0U; i--)
  28.     {
  29.         __NOP(); __NOP(); __NOP(); __NOP(); __NOP(); __NOP();
  30.         __NOP(); __NOP(); __NOP(); __NOP(); __NOP(); __NOP();
  31.     }

  32.     return ++ticks;
  33. }
复制代码

4.12 第9步,添加BSP驱动文件bsp_dwt.c

添加bsp_dwt.c文件和bsp_dwt.h文件主要是因为第8步中的stm32h7xx_hal_timebase_tim.c文件里面的函数bsp_DelayMS要使用,此函数是基于DWT系统时钟周期计数器实现。

f0d85f2002a553fa31c8f67b30e2db76.png


4.13 第10步,创建应用任务(重要,注意启动任务)

应用程序比较简单,大家可以直接复制本章教程配置例子的main.c文件中的内容到自己工程里面测试。主要创建了如下几个任务:

AppTaskUserIF任务   : 按键消息处理。

AppTaskLED任务      : LED闪烁。

AppTaskMsgPro任务   : 消息处理,暂未使用。

AppTaskStart任务    : 启动任务,也是最高优先级任务,这里实现按键扫描。

osRtxTimerThread任务: 定时器任务,暂未使用。

任务栈大小和任务控制块定义如下:

  1. /*
  2. **********************************************************************************************************
  3.                                              变量
  4. **********************************************************************************************************
  5. */
  6. /* 任务的属性设置 */
  7. const osThreadAttr_t ThreadStart_Attr =
  8. {
  9.     /* 未使用 */
  10. //    .cb_mem = &worker_thread_tcb_1,
  11. //    .cb_size = sizeof(worker_thread_tcb_1),
  12. //    .stack_mem = &worker_thread_stk_1[0],
  13. //    .stack_size = sizeof(worker_thread_stk_1),
  14. //    .priority = osPriorityAboveNormal,
  15. //    .tz_module = 0

  16.     .name = "osRtxStartThread",
  17.     .attr_bits = osThreadDetached,
  18.     .priority = osPriorityHigh4,
  19.     .stack_size = 2048,
  20. };

  21. const osThreadAttr_t ThreadMsgPro_Attr =
  22. {
  23.     .name = "osRtxMsgProThread",
  24.     .attr_bits = osThreadDetached,
  25.     .priority = osPriorityHigh3,
  26.     .stack_size = 1024,
  27. };

  28. const osThreadAttr_t ThreadLED_Attr =
  29. {
  30.     .name = "osRtxLEDThread",
  31.     .attr_bits = osThreadDetached,
  32.     .priority = osPriorityHigh2,
  33.     .stack_size = 512,
  34. };

  35. const osThreadAttr_t ThreadUserIF_Attr =
  36. {
  37.     .name = "osRtxThreadUserIF",
  38.     .attr_bits = osThreadDetached,
  39.     .priority = osPriorityHigh1,
  40.     .stack_size = 1024,
  41. };
复制代码

任务创建:

  1. /*
  2. *********************************************************************************************************
  3. *    函 数 名: main
  4. *    功能说明: 标准c程序入口。
  5. *    形    参: 无
  6. *    返 回 值: 无
  7. *********************************************************************************************************
  8. */
  9. int main (void)
  10. {   
  11.     /* HAL库,MPU,Cache,时钟等系统初始化 */
  12.     System_Init();

  13.     /* 内核开启前关闭HAL的时间基准 */
  14.     HAL_SuspendTick();

  15.     /* 内核初始化 */
  16.     osKernelInitialize();                                 

  17.     /* 创建启动任务 */
  18.     ThreadIdStart = osThreadNew(AppTaskStart, NULL, &ThreadStart_Attr);  

  19.     /* 开启多任务 */
  20.     osKernelStart();

  21.     while(1);
  22. }

  23. /*
  24. *********************************************************************************************************
  25. *    函 数 名: AppTaskCreate
  26. *    功能说明: 创建应用任务
  27. *    形    参: 无
  28. *    返 回 值: 无
  29. *********************************************************************************************************
  30. */
  31. static void AppTaskCreate (void)
  32. {
  33.     ThreadIdTaskMsgPro = osThreadNew(AppTaskMsgPro, NULL, &ThreadMsgPro_Attr);  
  34.     ThreadIdTaskLED = osThreadNew(AppTaskLED, NULL, &ThreadLED_Attr);  
  35.     ThreadIdTaskUserIF = osThreadNew(AppTaskUserIF, NULL, &ThreadUserIF_Attr);  
  36. }
复制代码

这里我们重点看下启动任务,主要做了四个工作:

  外设初始化bsp_Init。
  任务创建AppTaskCreate。
  需要周期性处理的程序bsp_ProPer1ms,对应裸机工程调用的SysTick_ISR。这个的实现非常重要,这样之前裸机里面使用的API,就可以直接在RTX5里面直接调用。
  1. /*
  2. *********************************************************************************************************
  3. *    函 数 名: AppTaskStart
  4. *    功能说明: 启动任务,这里用作BSP驱动包处理。
  5. *    形    参: 无
  6. *    返 回 值: 无
  7. *   优 先 级: osPriorityHigh4  
  8. *********************************************************************************************************
  9. */
  10. void AppTaskStart(void *argument)
  11. {
  12.     const uint16_t usFrequency = 1; /* 延迟周期 */
  13.     uint32_t tick;

  14.     /* 初始化外设 */
  15.     HAL_ResumeTick();
  16.     bsp_Init();

  17.     /* 创建任务 */
  18.     AppTaskCreate();

  19.     /* 获取当前时间 */
  20.     tick = osKernelGetTickCount();

  21.     while(1)
  22.     {
  23.         /* 需要周期性处理的程序,对应裸机工程调用的SysTick_ISR */
  24.         bsp_ProPer1ms();

  25.         /* 相对延迟 */
  26.         tick += usFrequency;                          
  27.         osDelayUntil(tick);
  28.     }
  29. }
复制代码

4.14 常见移植错误总结

常见的移植错误主要有下面几种情况:

  编译后提示如下两种错误:
Error: L6200E: Symbol PendSV_Handler multiply defined (by irq_cm4f.o and stm32h7xx_it.o).

Error: L6200E: Symbol SVC_Handler multiply defined (by irq_cm4f.o and stm32h7xx_it.o).

解决办法:这是函数重定义了,直接将stm32h7xx_it.c文件里面的PendSV_Handler和SVC_Handler删掉。

  提示如下错误
Error: L6218E: Undefined symbol bsp_DelayMS (referred from bsp_fmc_io.o).

解决办法:打开bsp_dwt.C文件中的条件编译。

4.15 实验例程
本章节配套了如下几个例子供大家移植参考:

  V7-400_Base Template
裸机模板,方便大家添加RTX5内核源码。

  V7-401_Threadx Kernel Template

ThreadX内核模板。

MDK进入调试状态后,选择周期更新:

fdce9fac9944ad56faa0dd13307f6ebb.png


然后打开调试组件,注意和RTX4的调试组件位置不同:

9482ce7367ba4d7cf08c73a56db28f75.png


然后点击MDK的全速运行,

e3038a01781216611f96ae37d5bccb17.png


至此,就可以动态实时查看RTX5的运行状态:

797f68ea76bd699fe11ce441076df4ec.png


4.16 总结
本章节为大家讲解了RTX5 在MDK AC5上的移植方法,移植涉及到的知识点比较多,初学的话,建议实际动手操作一遍。



收藏 评论1 发布时间:2021-12-30 14:32

举报

1个回答
STMWoodData 回答时间:2021-12-30 15:31:46

好好学习

所属标签

相似分享

官网相关资源

关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
STM32N6 AI生态系统
STM32MCU,MPU高性能GUI
ST ACEPACK电源模块
意法半导体生物传感器
STM32Cube扩展软件包
关注我们
st-img 微信公众号
st-img 手机版