[N32G43x] 【N32G43XCL-STB_V1.0】+FreeRTOS移植

[复制链接]
2876|29
 楼主| qjp1988113 发表于 2021-12-31 15:39 | 显示全部楼层 |阅读模式
今天有点小空,我们来移植一下FREERTOS! FREERTOS就不要我多说了吧,免费的大家都喜欢~
我们先去网站www.freertos.org下载源码,当然也可以用旧的源码,不一定都要用新的么~
FRRRTOS.png
电脑打开GITHUB极慢,我们这了就不下载最新的了~
我们这了用的是旧版本,不知道是我哪一年下载的,不过基本上应该差别不大啊~
解压下来,去掉一些不必要的DEMO例子,及其他MCU的支持,我们简化成:
FreeRTOS.rar (272.17 KB, 下载次数: 41)
解压,添加到工程,并头文件包含:
X2.png
X3.png

我们先来编译一下,发现提升缺少文件:
X4.png
我们到之前下载的完整版的DEMO例程里面找找一样是M4F核的MCU工程里面,拷贝过来,这了我们选择STM32F407,它也是M4F核和N32G43X一样。
理论上能通用:
X6.png
复制过来,放到工程目录下,并包含~这个FreeRTOSConfig.h是用来配置和剪裁FREERTOS功能的~
再次编译,发现提示SystemCoreClock 未定义。
我们打开FreeRTOSConfig.h 将编译器支持修改成如下:
#if defined(__ICCARM__) || defined(__CC_ARM) || defined(__GNUC__)
    #include <stdint.h>
    extern uint32_t SystemCoreClock;
#endif

再次编译,提示2个中断函数重定义了:
E1.png
我们把n32g43x_it.c 里面对于的屏蔽掉
E2.png
再次编译,发现提示未定义的一些函数:
E6.png
我们把FreeRTOSConfig.h里面的对于配置设为0即可,如下图:
E7.png
再次编译,终于好了~
Z8.png
没报错,不等于能用啊~我们知道FREERTOS用Systick作为时基的~
我们屏蔽port.c里面的Systick_Handler()。并且屏蔽掉FreeRTOSConfig.h里面的
3define xPortSysTickHandler  SysTick_Handler这句话。
我们把Systick_Handler()写到delay.c里面,我们之前就是用Systick做延时的,这里面一起修改。
我们使用查询的方式来计算计时,不占用中断,不影响整个时钟节拍~
  1. #include "delay.h"
  2. #include "sys.h"

  3. #include "FreeRTOS.h"                                        //FreeRTOS使用                  
  4. #include "task.h"


  5. static u8  fac_us=0;                                                        //us延时倍乘数                          
  6. static u16 fac_ms=0;                                                        //ms延时倍乘数,在os下,代表每个节拍的ms数


  7. extern void xPortSysTickHandler(void);

  8. //systick中断服务函数,使用OS时用到
  9. void SysTick_Handler(void)
  10. {       
  11.     if(xTaskGetSchedulerState()!=taskSCHEDULER_NOT_STARTED)//系统已经运行
  12.     {
  13.         xPortSysTickHandler();       
  14.     }
  15. }
  16.                           
  17. //初始化延迟函数
  18. //SYSTICK的时钟固定为AHB时钟,基础例程里面SYSTICK时钟频率为AHB/8
  19. //这里为了兼容FreeRTOS,所以将SYSTICK的时钟频率改为AHB的频率!
  20. //SYSCLK:系统时钟频率
  21. void delay_init(u8 SYSCLK)
  22. {
  23.         u32 reload;
  24.         SysTick_CLKSourceConfig(SysTick_CLKSource_HCLK);
  25.         fac_us=SYSCLK;                                                        //不论是否使用OS,fac_us都需要使用
  26.         reload=SYSCLK;                                                        //每秒钟的计数次数 单位为M          
  27.         reload*=1000000/configTICK_RATE_HZ;                //根据delay_ostickspersec设定溢出时间
  28.                                                                                         //reload为24位寄存器,最大值:16777216,在168M下,约合0.0998s左右       
  29.         fac_ms=1000/configTICK_RATE_HZ;                        //代表OS可以延时的最少单位          
  30.         SysTick->CTRL|=SysTick_CTRL_TICKINT_Msk;//开启SYSTICK中断
  31.         SysTick->LOAD=reload;                                         //每1/configTICK_RATE_HZ断一次       
  32.         SysTick->CTRL|=SysTick_CTRL_ENABLE_Msk; //开启SYSTICK     
  33. }                                                                    

  34. //延时nus
  35. //nus:要延时的us数.       
  36. //nus:0~204522252(最大值即2^32/fac_us@fac_us=168)                                                                              
  37. void delay_us(u32 nus)
  38. {               
  39.         u32 ticks;
  40.         u32 told,tnow,tcnt=0;
  41.         u32 reload=SysTick->LOAD;                                //LOAD的值                     
  42.         ticks=nus*fac_us;                                                 //需要的节拍数
  43.         told=SysTick->VAL;                                        //刚进入时的计数器值
  44.         while(1)
  45.         {
  46.                 tnow=SysTick->VAL;       
  47.                 if(tnow!=told)
  48.                 {            
  49.                         if(tnow<told)tcnt+=told-tnow;        //这里注意一下SYSTICK是一个递减的计数器就可以了.
  50.                         else tcnt+=reload-tnow+told;            
  51.                         told=tnow;
  52.                         if(tcnt>=ticks)break;                        //时间超过/等于要延迟的时间,则退出.
  53.                 }  
  54.         };                                                                                    
  55. }  
  56. //延时nms
  57. //nms:要延时的ms数
  58. //nms:0~65535
  59. void delay_ms(u32 nms)
  60. {       
  61.         if(xTaskGetSchedulerState()!=taskSCHEDULER_NOT_STARTED)//系统已经运行
  62.         {               
  63.                 if(nms>=fac_ms)                                                //延时的时间大于OS的最少时间周期
  64.                 {
  65.                            vTaskDelay(nms/fac_ms);                         //FreeRTOS延时
  66.                 }
  67.                 nms%=fac_ms;                                                //OS已经无法提供这么小的延时了,采用普通方式延时   
  68.         }
  69.         delay_us((u32)(nms*1000));                                //普通方式延时
  70. }

  71. //延时nms,不会引起任务调度
  72. //nms:要延时的ms数
  73. void delay_xms(u32 nms)
  74. {
  75.         u32 i;
  76.         for(i=0;i<nms;i++) delay_us(1000);
  77. }


好,到这了就移植完毕了~
下面我们新建2个任务,LED闪烁及printf输出:
main.C

  1. #include "main.h"
  2. #include "sys.h"
  3. #include "delay.h"
  4. #include "debug_uart.h"

  5. #include "led.h"

  6. #include "FreeRTOS.h"
  7. #include "task.h"




  8. //任务优先级
  9. #define START_TASK_PRIO                1
  10. //任务堆栈大小       
  11. #define START_STK_SIZE                 128  
  12. //任务句柄
  13. TaskHandle_t StartTask_Handler;
  14. //任务函数
  15. void start_task(void *pvParameters);

  16. //任务优先级
  17. #define TASK1_TASK_PRIO                2
  18. //任务堆栈大小       
  19. #define TASK1_STK_SIZE                 128  
  20. //任务句柄
  21. TaskHandle_t Task1Task_Handler;
  22. //任务函数
  23. void task1_task(void *pvParameters);

  24. //任务优先级
  25. #define TASK2_TASK_PRIO                3
  26. //任务堆栈大小       
  27. #define TASK2_STK_SIZE                 128  
  28. //任务句柄
  29. TaskHandle_t Task2Task_Handler;
  30. //任务函数
  31. void task2_task(void *pvParameters);

  32. /**
  33. * [url=home.php?mod=space&uid=247401]@brief[/url]  Main program.
  34. */
  35. int main(void)
  36. {
  37.   u8 t;
  38.         u8 len;       
  39.         u16 times=0;  
  40.   /*SystemInit() function has been called by startup file startup_n32g43x.s*/
  41.         NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//设置系统中断优先级分组2
  42.         delay_init(108);                //延时初始化
  43.         DBG_UART_Init(115200);        //串口初始化波特率为115200
  44.         LED_Init();                                  //初始化与LED连接的硬件接口  
  45.   
  46.   //创建开始任务
  47.   xTaskCreate((TaskFunction_t )start_task,            //任务函数
  48.               (const char*    )"start_task",          //任务名称
  49.               (uint16_t       )START_STK_SIZE,        //任务堆栈大小
  50.               (void*          )NULL,                  //传递给任务函数的参数
  51.               (UBaseType_t    )START_TASK_PRIO,       //任务优先级
  52.               (TaskHandle_t*  )&StartTask_Handler);   //任务句柄              
  53.   vTaskStartScheduler();          //开启任务调度
  54. }



  55. //开始任务任务函数
  56. void start_task(void *pvParameters)
  57. {
  58.     taskENTER_CRITICAL();           //进入临界区
  59.     //创建TASK1任务
  60.     xTaskCreate((TaskFunction_t )task1_task,            
  61.                 (const char*    )"task1_task",           
  62.                 (uint16_t       )TASK1_STK_SIZE,        
  63.                 (void*          )NULL,                  
  64.                 (UBaseType_t    )TASK1_TASK_PRIO,        
  65.                 (TaskHandle_t*  )&Task1Task_Handler);   
  66.     //创建TASK2任务
  67.     xTaskCreate((TaskFunction_t )task2_task,     
  68.                 (const char*    )"task2_task",   
  69.                 (uint16_t       )TASK2_STK_SIZE,
  70.                 (void*          )NULL,
  71.                 (UBaseType_t    )TASK2_TASK_PRIO,
  72.                 (TaskHandle_t*  )&Task2Task_Handler);
  73.     vTaskDelete(StartTask_Handler); //删除开始任务
  74.     taskEXIT_CRITICAL();            //退出临界区
  75. }

  76. //task1任务函数
  77. void task1_task(void *pvParameters)
  78. {
  79.         u8 task1_num=0;
  80.        
  81.         while(1)
  82.         {
  83.                 task1_num++;        //任务执1行次数加1 注意task1_num1加到255的时候会清零!!
  84.                 LED1=!LED1;
  85.                 printf("任务1已经执行:%d次\r\n",task1_num);
  86.     vTaskDelay(1000);                           //延时1s,也就是1000个时钟节拍       
  87.         }
  88. }

  89. //task2任务函数
  90. void task2_task(void *pvParameters)
  91. {
  92.         u8 task2_num=0;
  93.        
  94.         while(1)
  95.         {
  96.                 task2_num++;        //任务2执行次数加1 注意task1_num2加到255的时候会清零!!
  97.     LED2=!LED2;
  98.                 printf("任务2已经执行:%d次\r\n",task2_num);
  99.     vTaskDelay(1000);                           //延时1s,也就是1000个时钟节拍       
  100.         }
  101. }
  102. /**
  103. * @}
  104. */

  105. /**
  106. * @brief Assert failed function by user.
  107. * @param file The name of the call that failed.
  108. * @param line The source line number of the call that failed.
  109. */
  110. #ifdef USE_FULL_ASSERT
  111. void assert_failed(const uint8_t* expr, const uint8_t* file, uint32_t line)
  112. {
  113.     while (1)
  114.     {
  115.     }
  116. }
  117. #endif // USE_FULL_ASSERT

编译,并运行:
串口输出:
M4.png
LED闪烁:
XX.gif
好了,FREERTOS的移植就到这来~谢谢观看~





weiwei4dk 发表于 2021-12-31 17:29 | 显示全部楼层
谢谢分享
小阁清风频顾 发表于 2022-4-24 15:35 | 显示全部楼层
你好,请问有没有455移植uCOS-ii的?
averyleigh 发表于 2022-4-27 19:48 | 显示全部楼层
FreeRTOS移植怎么样   
modesty3jonah 发表于 2022-4-27 19:57 | 显示全部楼层
如何将FreeRTOS移植  
typeof 发表于 2022-4-27 20:10 | 显示全部楼层
freertos 能移植 ucgui吗
isseed 发表于 2022-4-27 20:32 | 显示全部楼层
如何移植freertos到N32G43XCL-STB_
belindagraham 发表于 2022-4-27 20:59 | 显示全部楼层
这个兼容stm32哪个芯片呢  
minzisc 发表于 2022-4-27 21:25 | 显示全部楼层
为什么不使用rtt系统呢
suzhanhua 发表于 2022-4-27 21:53 | 显示全部楼层
freertos和ucos哪个更适合于学习
jonas222 发表于 2022-4-27 22:21 | 显示全部楼层
开发板怎么移植rtos  
mnynt121 发表于 2022-4-27 22:48 | 显示全部楼层
学习RTOS的平台。
plsbackup 发表于 2022-4-27 23:17 | 显示全部楼层
来一份移植详细过程。
lzmm 发表于 2022-4-30 19:12 | 显示全部楼层
芯片支持什么RTOS实时操作系统
lzmm 发表于 2022-4-30 22:26 | 显示全部楼层
FreeRTOS 移栽要点怎么解决
chenHaoYan 发表于 2022-8-31 11:18 | 显示全部楼层
1. FreeRTOSConfing.h 文件中的外部时钟频率引用是错误的(使用的是stm32的),应该改为:
extern uint32_t SystemClockFrequency;

2. printf() 的重定向源码最好发一下,或者参考我:
int fputo(int ch, FILE* f)
{
    USART_Data_Send( USART1, (uint8_t)ch ) ;  // 发送数据
    while ( USART_Interrupt_Status_Get( USART1, USART_FLAG_TXDE ) == RESET ) ;  // 等待发送完成
    return ch;
}
averyleigh 发表于 2022-9-3 17:50 | 显示全部楼层
FreeRTOS可以运行多少个实例
averyleigh 发表于 2022-9-3 19:33 | 显示全部楼层
怎么样定义freertos的mutex的数组
qiufengsd 发表于 2022-9-3 20:26 | 显示全部楼层
freertos任务切换需要多少个时钟周期
dspmana 发表于 2022-9-3 21:05 | 显示全部楼层
怎样精确定时调用一个task
您需要登录后才可以回帖 登录 | 注册

本版积分规则

111

主题

627

帖子

2

粉丝
快速回复 在线客服 返回列表 返回顶部