前言

提示:这里可以添加本文要记录的大概内容:

本文档主要介绍 N32G43x_L40x_L43x 系列芯片(以下简称 N32G43x)移植 FreeRTOS 的示例,以及提供相应例程。

硬件平台:N32L43XM-STB 开发板
软件平台:MDK5.29FreeRTOSv202012.00

提示:以下是本篇文章正文内容,下面案例可供参考

一、FreeRTOS 源码获取

移植前需要上 FreeRTOS 的官网去获取相应源码:www.freertos.org。这里用的版本是 FreeRTOSv202012.00。

二、工程移植

先准备一个基础工程,然后在基础工程中添加相应文件

1.添加 FreeRTOS 源码

1、在基础工程中新建一个 FreeRTOS 的文件夹,然后将 Source 文件夹下的源码文件拷贝到这个文件夹中

2、将 portable 文件夹中多余的子文件夹去掉,如下: 

3、打开基础工程,新建 RTOS 分组:FreeRTOS_CODE FreeRTOS_PORTABLE,然后在这两个分组中
添加文件,如下:

关于 MemMang 文件中的几个 heap.c 文件,分别是 5 种不同的内存管理方式,这 5 个文件都可以用来作为 FreeRTOS 的内存管理文件,只是它们实现的原理不同,各有利弊。有兴趣的可以自行学习它们的区别, 这里我们选择 heap_4.c,这也是 FreeRTOS 比较常用的方式。

4、添加相应的头文件路径

2.3.2 修改 FreeRTOS 源码 

我们先按照以上的步骤添加之后,进行编译,会报如下错误:

错误说明:缺少 FreeRTOSConfig.h 头文件。

顾名思义这个头文件是 FreeRTOS 的配置文件,一般的操作系统都有裁剪、配置功能,而这些裁剪及配置都是通过一个文件来完成的,基本都是通过宏定义来完成对系统的配置和裁剪。
这时候我们可以打开源码中的 Demo 文件夹,把一个相似的工程中的 FreeRTOSConfig.h 拷贝过来,这里 我们参考 CORTEX_M4F_STM32F407ZG-SK 工程中的 FreeRTOSConfig.h 配置文件,因为 N32G43X/N32L4XX也是 M4F 的,与这个工程比较相近。
这里是将 FreeRTOSConfig.h 配置文件放到 include 文件夹下,与 FreeRTOS 的头文件放在一起。
之后再编译,如下:

 

错误说明:SystemCoreClock 未定义
这是因为在 FreeRTOSConfig.h 中使用到了 SystemCoreClock 来标记 MCU 的频率

 

可以看到这里有个编译工具链的条件编译:#ifdef __ICCARM__
只有定义了__ICCARM__,之后的代码才会生效,这里稍作修改,添加多几个编译工具链的宏定义
#if defined(__ICCARM__) || defined(__CC_ARM) || defined(__GNUC__) 
#include <stdint.h> 
extern uint32_t SystemCoreClock; 
#endif
修改之后再次编译,如下: 
报错说明:port.cn32g43x_it.c 这两个文件中有重复定义的函数:SysTick_Handler()SVC_Handler()
这里屏蔽掉 n32g43x_it.c 中的函数。
再编译,如下:
报错说明:内存溢出
N32G43X/N32L4XX 最大有 128Kb FLASH 32Kb RAMFLASH 溢出不大可能,应该是 RAM 溢出。
heap_4 的内存管理方式是通过事先为系统资源分配一个堆(数组),如下:

 

其中 configTOTAL_HEAP_SIZE 的大小是在 FreeRTOSConfig.h 中定义的,如下: 

这里定义的 75Kb 远远超出了 RAM 的范围,所以需要根据自身实际情况修改,这里我们是将该值修改为 20,如下:

 

再编译

 

报错说明:未定义函数
这些个未定义函数都是以 Hook 结尾的,有个共同的名称:钩子函数。这是因为在 FreeRTOSConfig.h 中开启了这些钩子函数,但是却没有定义导致的。在 FreeRTOSConfig.h 中关闭这些钩子函数即可,即将相应的宏 定义改为 0,如下:

 再编译,至此编译通过。如仍有错误,可自行根据错误类型查找并修改。

2.3.3 修改 NZ_delay.c

该文件函数涉及到 FreeRTOS 的系统时钟,因为 FreeRTOS 的心跳就是由滴答定时器产生的,根据 FreeRTOS 的系统始终节拍设置好滴答定时器的周期,这样就会周期触发滴答定时器中断了。在滴答定时器中 段服务函数中调用 FreeRTOS API 函数 xPortSysTickHandler();
1.   extern void xPortSysTickHandler(void);
2.   void SysTick_Handler(void)
3.   {
4.            if(xTaskGetSchedulerState()!=taskSCHEDULER_NOT_STARTED)// 系统已经运行
5.      {
6.  xPortSysTickHandler();
7.         }
8.   }

既然 FreeRTOS 的系统时钟是由滴答定时器提供的,那么肯定是要根据 FreeRTOS 的系统时钟节拍来初始
化滴答定时器的了。FreeRTOS 的系统时钟节拍由宏定义 configTICK_RATE_HZ 来设置,这个值可以自由设
置,一旦设置好之后就要根据这个值来初始化滴答定时器(就是滴答定时器的中断周期)
函数如下:
1.    /**
2.   * @brief 初始化延迟函数
3.   * @note SYSTICK 的时钟固定为 HCLK 时钟
4.   */
5.  static u32 fac_us = 0; //us 延时倍乘数
6. static u32 fac_ms = 0; //ms 延时倍乘数
7. void NZ_Delay_init(void)
8.    {
9.       u32 reload;
10.
11.      SysTick_CLKSourceConfig(SysTick_CLKSource_HCLK);// 选择外部时钟 HCLK
12.     fac_us = (SystemCoreClock / (1000000)); // 为系统时钟
13.
14.    reload = (SystemCoreClock / 1000000); // 每秒钟的计数次数 单位为 M
15.   reload *= (1000000 / configTICK_RATE_HZ); //根据 configTICK_RATE_HZ 设定溢出时间
16.    fac_ms = (1000 / configTICK_RATE_HZ); // 代表 OS 可以延时的最少单位
17.
18.   SysTick->CTRL|=SysTick_CTRL_TICKINT_Msk; // 开启 SYSTICK 中断
19.   SysTick->LOAD=reload; // 每 1/configTICK_RATE_HZ 断一次
20.   SysTick->CTRL|=SysTick_CTRL_ENABLE_Msk; // 开启 SYSTICK
21.    }
1.         /**
2.         * @brief us 级别延时函数
3.     * @param nus:需要延时的微秒数
4.     * @note 如果延时的时间到了毫秒级别,则用 NZ_Delay_xms 实现
5.     */
6.        void NZ_Delay_us(u32 nus)
7.              {
8.     u32 ticks;
9.    u32 told,tnow,tcnt = 0;
10.   u32 reload = SysTick->LOAD; //LOAD 的值
11.      ticks = nus*fac_us; // 需要的节拍数
12.      told = SysTick->VAL; // 刚进入时的计数器值
13.   while(1)
14.                     {
15.    tnow = SysTick->VAL;
16.     if(tnow != told)
17.      {13
18.      if(tnow<told) // 这里注意一下 SYSTICK 是一个递减的计数器就可以了
19.    tcnt += told-tnow;
20.  else
21.    tcnt += reload-tnow+told;
22.
23.   told = tnow;
24.     if(tcnt>= ticks) // 时间超过 / 等于要延迟的时间, 则退出
25.             break;
26.   }
27.      };
28.  }
1. void NZ_Delay_ms(u32 nms)
2. {
3.    if(xTaskGetSchedulerState() != taskSCHEDULER_NOT_STARTED) // 系统已经运行
4.        {
5.        if(nms>= fac_ms)
//延时的时间大于 OS 的最少时间周期
6.        {
7.        vTaskDelay(nms / fac_ms); //FreeRTOS 延时
8.       }
9.
10. nms %= fac_ms;
//OS 已经无法提供这么小的延时了, 采用普通方式延时
11.         }
12.
NZ_Delay_us((u32)(nms*1000)); // 普通方式延时
13. }
14.
15. /**
16. * @brief ms 级别延时函数
17. * @param nms:需要延时的微秒数
18. */
19. void NZ_Delay_xms(u32 nms)
20. {
21.
u32 i;
22.
for(i=0;i<nms;i++) NZ_Delay_us(1000);
23. }
再编译,如下:

 

报错说明:重复定义函数 SysTick_Handler()
很明显 NZ_Delay.c 中的要保留下来,所以需要关闭 FreeRTOS 中的定义,屏蔽掉即可。如下:

 


总结

以上就是工程移植的指导内容,后续还需要工程验证,更详细的内容可与我们联络获得资料。

Logo

DAMO开发者矩阵,由阿里巴巴达摩院和中国互联网协会联合发起,致力于探讨最前沿的技术趋势与应用成果,搭建高质量的交流与分享平台,推动技术创新与产业应用链接,围绕“人工智能与新型计算”构建开放共享的开发者生态。

更多推荐