打印
[N32G43x]

【N32G43XCL-STB_V1.0】+FreeRTOS移植

[复制链接]
1932|28
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
今天有点小空,我们来移植一下FREERTOS! FREERTOS就不要我多说了吧,免费的大家都喜欢~
我们先去网站www.freertos.org下载源码,当然也可以用旧的源码,不一定都要用新的么~

电脑打开GITHUB极慢,我们这了就不下载最新的了~
我们这了用的是旧版本,不知道是我哪一年下载的,不过基本上应该差别不大啊~
解压下来,去掉一些不必要的DEMO例子,及其他MCU的支持,我们简化成:
FreeRTOS.rar (272.17 KB)
解压,添加到工程,并头文件包含:



我们先来编译一下,发现提升缺少文件:

我们到之前下载的完整版的DEMO例程里面找找一样是M4F核的MCU工程里面,拷贝过来,这了我们选择STM32F407,它也是M4F核和N32G43X一样。
理论上能通用:

复制过来,放到工程目录下,并包含~这个FreeRTOSConfig.h是用来配置和剪裁FREERTOS功能的~
再次编译,发现提示SystemCoreClock 未定义。
我们打开FreeRTOSConfig.h 将编译器支持修改成如下:
#if defined(__ICCARM__) || defined(__CC_ARM) || defined(__GNUC__)
    #include <stdint.h>
    extern uint32_t SystemCoreClock;
#endif

再次编译,提示2个中断函数重定义了:

我们把n32g43x_it.c 里面对于的屏蔽掉

再次编译,发现提示未定义的一些函数:

我们把FreeRTOSConfig.h里面的对于配置设为0即可,如下图:

再次编译,终于好了~

没报错,不等于能用啊~我们知道FREERTOS用Systick作为时基的~
我们屏蔽port.c里面的Systick_Handler()。并且屏蔽掉FreeRTOSConfig.h里面的
3define xPortSysTickHandler  SysTick_Handler这句话。
我们把Systick_Handler()写到delay.c里面,我们之前就是用Systick做延时的,这里面一起修改。
我们使用查询的方式来计算计时,不占用中断,不影响整个时钟节拍~
#include "delay.h"
#include "sys.h"

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


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


extern void xPortSysTickHandler(void);

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

//延时nus
//nus:要延时的us数.       
//nus:0~204522252(最大值即2^32/fac_us@fac_us=168)                                                                              
void delay_us(u32 nus)
{               
        u32 ticks;
        u32 told,tnow,tcnt=0;
        u32 reload=SysTick->LOAD;                                //LOAD的值                     
        ticks=nus*fac_us;                                                 //需要的节拍数
        told=SysTick->VAL;                                        //刚进入时的计数器值
        while(1)
        {
                tnow=SysTick->VAL;       
                if(tnow!=told)
                {            
                        if(tnow<told)tcnt+=told-tnow;        //这里注意一下SYSTICK是一个递减的计数器就可以了.
                        else tcnt+=reload-tnow+told;            
                        told=tnow;
                        if(tcnt>=ticks)break;                        //时间超过/等于要延迟的时间,则退出.
                }  
        };                                                                                    
}  
//延时nms
//nms:要延时的ms数
//nms:0~65535
void delay_ms(u32 nms)
{       
        if(xTaskGetSchedulerState()!=taskSCHEDULER_NOT_STARTED)//系统已经运行
        {               
                if(nms>=fac_ms)                                                //延时的时间大于OS的最少时间周期
                {
                           vTaskDelay(nms/fac_ms);                         //FreeRTOS延时
                }
                nms%=fac_ms;                                                //OS已经无法提供这么小的延时了,采用普通方式延时   
        }
        delay_us((u32)(nms*1000));                                //普通方式延时
}

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


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

#include "main.h"
#include "sys.h"
#include "delay.h"
#include "debug_uart.h"

#include "led.h"

#include "FreeRTOS.h"
#include "task.h"




//任务优先级
#define START_TASK_PRIO                1
//任务堆栈大小       
#define START_STK_SIZE                 128  
//任务句柄
TaskHandle_t StartTask_Handler;
//任务函数
void start_task(void *pvParameters);

//任务优先级
#define TASK1_TASK_PRIO                2
//任务堆栈大小       
#define TASK1_STK_SIZE                 128  
//任务句柄
TaskHandle_t Task1Task_Handler;
//任务函数
void task1_task(void *pvParameters);

//任务优先级
#define TASK2_TASK_PRIO                3
//任务堆栈大小       
#define TASK2_STK_SIZE                 128  
//任务句柄
TaskHandle_t Task2Task_Handler;
//任务函数
void task2_task(void *pvParameters);

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



//开始任务任务函数
void start_task(void *pvParameters)
{
    taskENTER_CRITICAL();           //进入临界区
    //创建TASK1任务
    xTaskCreate((TaskFunction_t )task1_task,            
                (const char*    )"task1_task",           
                (uint16_t       )TASK1_STK_SIZE,        
                (void*          )NULL,                  
                (UBaseType_t    )TASK1_TASK_PRIO,        
                (TaskHandle_t*  )&Task1Task_Handler);   
    //创建TASK2任务
    xTaskCreate((TaskFunction_t )task2_task,     
                (const char*    )"task2_task",   
                (uint16_t       )TASK2_STK_SIZE,
                (void*          )NULL,
                (UBaseType_t    )TASK2_TASK_PRIO,
                (TaskHandle_t*  )&Task2Task_Handler);
    vTaskDelete(StartTask_Handler); //删除开始任务
    taskEXIT_CRITICAL();            //退出临界区
}

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

//task2任务函数
void task2_task(void *pvParameters)
{
        u8 task2_num=0;
       
        while(1)
        {
                task2_num++;        //任务2执行次数加1 注意task1_num2加到255的时候会清零!!
    LED2=!LED2;
                printf("任务2已经执行:%d次\r\n",task2_num);
    vTaskDelay(1000);                           //延时1s,也就是1000个时钟节拍       
        }
}
/**
* @}
*/

/**
* @brief Assert failed function by user.
* @param file The name of the call that failed.
* @param line The source line number of the call that failed.
*/
#ifdef USE_FULL_ASSERT
void assert_failed(const uint8_t* expr, const uint8_t* file, uint32_t line)
{
    while (1)
    {
    }
}
#endif // USE_FULL_ASSERT

编译,并运行:
串口输出:

LED闪烁:

好了,FREERTOS的移植就到这来~谢谢观看~





使用特权

评论回复
沙发
weiwei4dk| | 2021-12-31 17:29 | 只看该作者
谢谢分享

使用特权

评论回复
板凳
小阁清风频顾| | 2022-4-24 15:35 | 只看该作者
你好,请问有没有455移植uCOS-ii的?

使用特权

评论回复
地板
averyleigh| | 2022-4-27 19:48 | 只看该作者
FreeRTOS移植怎么样   

使用特权

评论回复
5
modesty3jonah| | 2022-4-27 19:57 | 只看该作者
如何将FreeRTOS移植  

使用特权

评论回复
6
typeof| | 2022-4-27 20:10 | 只看该作者
freertos 能移植 ucgui吗

使用特权

评论回复
7
isseed| | 2022-4-27 20:32 | 只看该作者
如何移植freertos到N32G43XCL-STB_

使用特权

评论回复
8
belindagraham| | 2022-4-27 20:59 | 只看该作者
这个兼容stm32哪个芯片呢  

使用特权

评论回复
9
minzisc| | 2022-4-27 21:25 | 只看该作者
为什么不使用rtt系统呢

使用特权

评论回复
10
suzhanhua| | 2022-4-27 21:53 | 只看该作者
freertos和ucos哪个更适合于学习

使用特权

评论回复
11
jonas222| | 2022-4-27 22:21 | 只看该作者
开发板怎么移植rtos  

使用特权

评论回复
12
mnynt121| | 2022-4-27 22:48 | 只看该作者
学习RTOS的平台。

使用特权

评论回复
13
plsbackup| | 2022-4-27 23:17 | 只看该作者
来一份移植详细过程。

使用特权

评论回复
14
lzmm| | 2022-4-30 19:12 | 只看该作者
芯片支持什么RTOS实时操作系统

使用特权

评论回复
15
lzmm| | 2022-4-30 22:26 | 只看该作者
FreeRTOS 移栽要点怎么解决

使用特权

评论回复
16
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;
}

使用特权

评论回复
17
averyleigh| | 2022-9-3 17:50 | 只看该作者
FreeRTOS可以运行多少个实例

使用特权

评论回复
18
averyleigh| | 2022-9-3 19:33 | 只看该作者
怎么样定义freertos的mutex的数组

使用特权

评论回复
19
qiufengsd| | 2022-9-3 20:26 | 只看该作者
freertos任务切换需要多少个时钟周期

使用特权

评论回复
20
dspmana| | 2022-9-3 21:05 | 只看该作者
怎样精确定时调用一个task

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

111

主题

627

帖子

2

粉丝