本篇介绍在N32F43x上移植FreeRTOS
下载FreeRTOS源码
FreeRTOS官方下载地址:https://freertos.org/a00104.html ,下载FreeRTOS 202112.00版本
解压下载源码压缩包
主要看FreeRTOS文件夹中Source文件夹,Source文件夹中文件就是FreeRTOS源码
工程移植
添加FreeRTOS源码
在工程中新建FreeRTOS文件夹,将Source文件夹中源码复制到工程FreeRTOS文件夹中
portable文件中保留Keil、MemMang、RVDS三个文件夹,RVDS文件夹中保留ARM_CM4F文件夹
添加.h头文件
添加FreeRTOS.h配置文件,打开FreeRTOS源码Demo文件夹,把同样是M4F内核的芯片例程中的FreeRTOSConfig.h文件拷贝到工程的FreeRTOS文件夹下的include文件夹中
编译代码,显示未定义SystemCoreClock
因为在FreeRTOSConfig.h中使用SystemCoreClock来标记MCU的频率,FreeRTOSConfig.h中有个条件编译,只有定义__ICCARM__下面代码才有效
需要将这个条件编译修改为#if defined(__ICCARM__) || defined(__CC_ARM) || defined(__GNUC__)
重新编译后显示SVC_Handler()、SysTick_Handler()在port.c和n32l43x.c中重复定义
将n32l43x.c中的SVC_Handler()、SysTick_Handler()注释屏蔽后重新编译显示4个Hook函数未定义,原因是在FreeRTOSConfig.h中开启了这4个函数,但未定义这些函数
将FreeRTOSConfig.h中这4个函数对应的宏定义改为0
编译通过
测试设计3个任务:start_task、led1_task、led2_task,start_task用来创建led1_task、led2_task两个任务,led1_task控制LED11秒闪烁1次,led2_task控制LED2在1秒周期内亮200ms、灭800ms,编译后显示内存溢出
在FreeRTOSConfig.h中宏定义的configTOTAL_HEAP_SIZE为75kB,已超过N32L43x的32kB
将configTOTAL_HEAP_SIZE设置为20kB,编译通过
软件代码
/** 任务优先级 */
#define START_TASK_PRIO 1
#define LED1_TASK_PRIO 2
#define LED2_TASK_PRIO 3
/** 任务堆栈大小 */
#define START_STK_SIZE 128
#define LED1_STK_SIZE 50
#define LED2_STK_SIZE 50
/** 任务句柄 */
TaskHandle_t StartTask_Handler;
TaskHandle_t LED1Task_Handler;
TaskHandle_t LED2Task_Handler;
/** 任务函数 */
void start_task(void *pvParameters);
void led1_task(void *pvParameters);
void led2_task(void *pvParameters);
/**
* [url=home.php?mod=space&uid=159083]@brief[/url] Main program.
*/
int main(void)
{
/*SystemInit() function has been called by startup file startup_n32l43x.s*/
Delay_Init();
hal_ledInit();
//创建开始任务
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(); //进入临界区
//创建LED1任务
xTaskCreate((TaskFunction_t )led1_task,
(const char* )"led1_task",
(uint16_t )LED1_STK_SIZE,
(void* )NULL,
(UBaseType_t )LED1_TASK_PRIO,
(TaskHandle_t* )&LED1Task_Handler);
//创建LED2任务
xTaskCreate((TaskFunction_t )led2_task,
(const char* )"led2_task",
(uint16_t )LED2_STK_SIZE,
(void* )NULL,
(UBaseType_t )LED2_TASK_PRIO,
(TaskHandle_t* )&LED2Task_Handler);
vTaskDelete(StartTask_Handler); //删除开始任务
taskEXIT_CRITICAL(); //退出临界区
}
//LED1任务函数
void led1_task(void *pvParameters)
{
while(1)
{
GPIO_WriteBit(LED1_PORT, LED1_PIN, (Bit_OperateType)(1 - GPIO_ReadOutputDataBit(LED1_PORT, LED1_PIN)));
vTaskDelay(500);
}
}
//LED2任务函数
void led2_task(void *pvParameters)
{
while(1)
{
GPIO_SetBits(LED2_PORT, LED2_PIN);
vTaskDelay(200);
GPIO_ResetBits(LED2_PORT, LED2_PIN);
vTaskDelay(800);
}
}
运行测试
测试代码