一、获取源码
官网下载
二、下载完解压
三、获取需要移植的文件
点来FreeRTOS文件夹,只需要看Source
1.打开Source文件夹
include文件夹 :包含了一些我们需要移植的头文件
portable文件夹:包含一些适配不同内核的东西,我们需要用到以下框选的文件
内存管理选择移植 heap_4.c
内核管理选择移植 CM3内核的文件
2.找到 FreeRTOSConfig.h 配置文件
四、打开一个keil工程
1、创建group,添加相应的文件,添加头文件路径
2、修改相关用到的FreeRTOS的配置和中断
1)系统配置文件修改
FreeRTOSConfig.h 中添加如下3个配置:
#define xPortPendSVHandler PendSV_Handler
#define vPortSVCHandler SVC_Handler
#define INCLUDE_xTaskGetSchedulerState 1
2)修改 stm32f1xx_it.c 文件
1.引入头文件
2.注释掉2个中断函数(由于 FreeRTOS 已经实现了)
3.将 Systick_Handler 中断和 FreeRTOS关联起来
extern void xPortSysTickHandler(void);
if (xTaskGetSchedulerState() != taskSCHEDULER_NOT_STARTED)
{
xPortSysTickHandler();
}
五、移植完成
关于Systick 可能会出现的问题:系统时钟HAL和FreeRTOS共同使用systick?
void SysTick_Handler(void)
{
/* USER CODE BEGIN SysTick_IRQn 0 */
/* USER CODE END SysTick_IRQn 0 */
HAL_IncTick(); //hal库的时间函数依赖这个
/* USER CODE BEGIN SysTick_IRQn 1 */
if (xTaskGetSchedulerState() != taskSCHEDULER_NOT_STARTED)
{
xPortSysTickHandler(); //freertos依赖这个函数
}
/* USER CODE END SysTick_IRQn 1 */
}
FreeRTOS有些地方会屏蔽中断,造成 delay 不准--》出现这种情况时 可以将 Sys 配置的 Timebase Source 由原来默认的 Systick 改为其他 TIM(定时器)!!!
六、测试工程
1.main.c中简单创建两个任务
//1.包含头文件
/* FreeRTOS头文件 */
#include "FreeRTOS.h"
#include "task.h"
//2.任务相关
static TaskHandle_t AppTaskCreate_Handle;/* 创建任务句柄 */
static TaskHandle_t LED_Task_Handle; /* LED任务句柄 */
static void AppTaskCreate(void); /* 用于创建任务 */
static void LED_Task(void* pvParameters);/* LED_Task任务实现 */
int main(void)
{
HAL_Init();
BaseType_t xReturn = pdPASS;/* 定义一个创建信息返回值,默认为pdPASS */
/* 配置优先级分组为4 */
HAL_NVIC_SetPriorityGrouping( NVIC_PRIORITYGROUP_4 );
/* Configure the system clock */
SystemClock_Config();
/* Initialize all configured peripherals */
LED_GPIO_Config();
/* 创建 AppTaskCreate 任务 */
xReturn = xTaskCreate((TaskFunction_t )AppTaskCreate, /* 任务入口函数 */
(const char* )"AppTaskCreate",/* 任务名字 */
(uint16_t )128, /* 任务栈大小 */
(void* )NULL,/* 任务入口函数参数 */
(UBaseType_t )1, /* 任务的优先级 */
(TaskHandle_t* )&AppTaskCreate_Handle);/* 任务控制块指针 */
if(pdFAIL != xReturn)/* 创建成功 */
vTaskStartScheduler(); /* 启动任务,开启调度 */
while (1)
{
}
/* USER CODE END 3 */
}
2.实现两个任务
/***********************************************************************
* @ 函数名 : AppTaskCreate
* @ 功能说明: 为了方便管理,所有的任务创建函数都放在这个函数里面
* @ 参数 : 无
* @ 返回值 : 无
**********************************************************************/
static void AppTaskCreate(void)
{
BaseType_t xReturn = pdPASS;/* 定义一个创建信息返回值,默认为pdPASS */
taskENTER_CRITICAL(); //进入临界区
/* 创建LED_Task任务 */
xReturn = xTaskCreate((TaskFunction_t )LED_Task, /* 任务入口函数 */
(const char* )"LED_Task",/* 任务名字 */
(uint16_t )512, /* 任务栈大小 */
(void* )NULL, /* 任务入口函数参数 */
(UBaseType_t )2, /* 任务的优先级 */
(TaskHandle_t* )&LED_Task_Handle);/* 任务控制块指针 */
if(pdFAIL != xReturn)/* 创建成功 */
{
//...
}
vTaskDelete(AppTaskCreate_Handle); //删除AppTaskCreate任务
taskEXIT_CRITICAL(); //退出临界区
}
/**********************************************************************
* @ 函数名 : LED_Task
* @ 功能说明: LED_Task任务主体
* @ 参数 :
* @ 返回值 : 无
********************************************************************/
static void LED_Task(void* parameter)
{
while (1)
{
HAL_GPIO_WritePin(GPIOC, GPIO_PIN_13, GPIO_PIN_RESET);
vTaskDelay(500); /* 延时500个tick */
HAL_GPIO_WritePin(GPIOC, GPIO_PIN_13, GPIO_PIN_SET);
vTaskDelay(500); /* 延时500个tick */
}
}
3.编译烧入程序,可以看到 LED(PC13) 按指定的delay 闪烁!!!