目录
目的
为方便裸机HAL库程序手动移植FreeRTOS,加快移植效率。本文在第一章基础上进行移植(详见:https://blog.csdn.net/Huan_Xiang_Yu/article/details/127561357)。
一、FreeRTOS官网下载内核文件
二、内核移植
将下载的FreeRTOS内核包解压,打开FreeRTOS文件夹。
1.文件拷贝
拷贝路径FreeRTOS->Source下文件到需要移植的工程下;
删除FreeRTOS->Source->portable下多余文件夹,保留 Keil,MemMang,RVDS 3个文件夹;
删除FreeRTOS->Source->portable->MemMang文件夹下多余的文件,保留“heap_4.c”;
删除FreeRTOS->Source->portable->RVDS文件夹下多余的文件夹,保留“ARM_CM3”文件夹;
拷贝FreeRTOS->Demo->CORTEX STM32F103 Keil文件夹下FreeRTOSConfig.h到工程文件夹下(根据芯片型号选择对应系列文件夹下的FreeRTOSConfig.h)。
文件拷贝后工程下FreeRTOS包含文件及文件夹如下:
2.工程配置
打开需移植的Keil工程,将FreeRTOS相关文件添加到项目工程中;
打开选项卡,配置FreeRTOS相关头文件路径。
3.移植工程代码修改
编译工程,提示报错信息(Error: L6218E: Undefined symbol xTaskGetCurrentTaskHandle (referred from stream_buffer.o).),查找发现“INCLUDE_xTaskGetCurrentTaskHandle”未定义;
在FreeRTOSConfig.h文件下,添加INCLUDE_xTaskGetCurrentTaskHandle定义。再添加FreeRTOS系统相关的3个中断处理函数如下:
#define INCLUDE_xTaskGetCurrentTaskHandle 1
#define xPortPendSVHandler PendSV_Handler
#define xPortSysTickHandler SysTick_Handler
#define vPortSVCHandler SVC_Handler
删除或屏蔽原工程的3个中断处理函数,以免重复重复定义。
三、移植验证
在main.c文件下直接复制正点原子任务函数进行快速验证:
/*FreeRTOS*********************************************************************************************/
#include "FreeRTOS.h"
#include "task.h"
/* TASK1 任务 配置
* 包括: 任务句柄 任务优先级 堆栈大小 创建任务
*/
#define TASK1_PRIO 2 /* 任务优先级 */
#define TASK1_STK_SIZE 128 /* 任务堆栈大小 */
TaskHandle_t Task1Task_Handler; /* 任务句柄 */
void task1(void *pvParameters); /* 任务函数 */
/* TASK2 任务 配置
* 包括: 任务句柄 任务优先级 堆栈大小 创建任务
*/
#define TASK2_PRIO 2 /* 任务优先级 */
#define TASK2_STK_SIZE 128 /* 任务堆栈大小 */
TaskHandle_t Task2Task_Handler; /* 任务句柄 */
void task2(void *pvParameters); /* 任务函数 */
/**
* @brief task1
* @param pvParameters : 传入参数(未用到)
* @retval 无
*/
void task1(void *pvParameters)
{
while (1)
{
User_Task();
}
}
/**
* @brief task2
* @param pvParameters : 传入参数(未用到)
* @retval 无
*/
void task2(void *pvParameters)
{
while (1)
{
TogglePinOP(Y7); //翻转LED灯
// vTaskDelay(500);
HAL_Delay(1000);
}
}
/**
* @brief The application entry point.
* @retval int
*/
int main(void)
{
/* USER CODE BEGIN 1 */
/* USER CODE END 1 */
/* MCU Configuration--------------------------------------------------------*/
/* Reset of all peripherals, Initializes the Flash interface and the Systick. */
HAL_Init();
/* USER CODE BEGIN Init */
/* USER CODE END Init */
/* Configure the system clock */
SystemClock_Config();
/* USER CODE BEGIN SysInit */
/* USER CODE END SysInit */
/* Initialize all configured peripherals */
MX_GPIO_Init();
MX_DMA_Init();
PVD_Init();
MX_ADC1_Init();
MX_USART1_UART_Init();
MX_USART3_UART_Init();
MX_IWDG_Init();
MX_TIM2_Init();
MX_TIM3_Init();
/* USER CODE BEGIN 2 */
User_Init();
/* USER CODE END 2 */
/* 创建任务1 */
xTaskCreate((TaskFunction_t )task1, /* 任务函数 */
(const char* )"task1", /* 任务名称 */
(uint16_t )TASK1_STK_SIZE, /* 任务堆栈大小 */
(void* )NULL, /* 传入给任务函数的参数 */
(UBaseType_t )TASK1_PRIO, /* 任务优先级 */
(TaskHandle_t* )&Task1Task_Handler); /* 任务句柄 */
/* 创建任务2 */
xTaskCreate((TaskFunction_t )task2, /* 任务函数 */
(const char* )"task2", /* 任务名称 */
(uint16_t )TASK2_STK_SIZE, /* 任务堆栈大小 */
(void* )NULL, /* 传入给任务函数的参数 */
(UBaseType_t )TASK2_PRIO, /* 任务优先级 */
(TaskHandle_t* )&Task2Task_Handler); /* 任务句柄 */
vTaskStartScheduler();
/* USER CODE END 3 */
}