文件下载的官网地址:FreeRTOS™ - FreeRTOS™
Source文件夹下7个.c文件全部移植过来
- port.c文件:里面的内容是由 FreeRTOS 官方的技术人员为 Cortex-M3 内核的处理器写的接口文件,里面核心的上下文切换代码是由汇编语言编写而成,对技术员的要求比较高,我们只是使用的话只需拷贝过来用即可。
- portmacro.h文件:port.c文件对应的头文件,主要是一些数据类型和宏定义。
如果需要其他内核的自己寻找到RVDS下对应的port.c和portmacro.h文件
MemMang 文件夹下存放的是跟内存管理相关的,总共有五个 heap 文件以及一个 readme 说明文件。一般只用heap_4c
FreeRTOSConfig.h 文件是 FreeRTOS 的工程配置文件,因为 FreeRTOS 是可以裁剪的 实时操作内核,应用于不同的处理器平台,用户可以通过修改这个 FreeRTOS 内核的配置 头文件来裁剪 FreeRTOS 的功能,我们把它拷贝一份放在FreeRTOS这个文件夹下面(路径随意,只要能添加其路径就好)。
将这些文件添加到一个文件夹下,并在VScode中添加路径(我的是FreeRTOS,方便后面快速移植)
注意:HAL本身和FreeRTOS都默认依赖SysTick,可能出现卡死的问题。
为了保险起见,可以考虑在SYS选择HAL时钟源的时候换成其他的,并且中断优先级设为较高,比如1。
在stm32f1xx_it.c中添加两个头文件
在stm32f1xx_it.c中注释两个函数void SVC_Handler(void)和void PendSV_Handler(void)
在stm32f1xx_it.c中声明并在void SysTick_Handler(void)编写滴答定时器
if (xTaskGetSchedulerState() != taskSCHEDULER_NOT_STARTED)
{
xPortSysTickHandler();
}
在FreeRTOSConfig.h文件添加三个宏
#define xPortPendSVHandler PendSV_Handler
#define vPortSVCHandler SVC_Handler
#define INCLUDE_xTaskGetSchedulerState 1
freertos_demo.c文件
/*
* @Author: random
* @Date: 2025-05-10 01:23:40
* @Last Modified by: random
* @Last Modified time: Do not Edit
*/
#include "freertos_demo.h"
/* freertos相关的头文件,必须的 */
#include "FreeRTOS.h"
#include "task.h"
/* 需要用到的其他头文件 */
#include "fun.h"
/* 启动任务的配置 */
#define START_TASK_STACK 128
#define START_TASK_PRIORITY 1
TaskHandle_t start_task_handle;
void start_task(void *pvParameters);
/* 任务1的配置 */
#define TASK1_STACK 128
#define TASK1_PRIORITY 2
TaskHandle_t task1_handle;
void task1(void *pvParameters);
/* 任务2的配置 */
#define TASK2_STACK 128
#define TASK2_PRIORITY 3
TaskHandle_t task2_handle;
void task2(void *pvParameters);
/* 任务3的配置 */
#define TASK3_STACK 128
#define TASK3_PRIORITY 4
TaskHandle_t task3_handle;
void task3(void *pvParameters);
/**
* @description: 启动FreeRTOS
* @return {*}
*/
void freertos_start(void)
{
/* 1.创建一个启动任务 */
xTaskCreate((TaskFunction_t)start_task, // 任务函数的地址
(char *)"start_task", // 任务名字符串
(configSTACK_DEPTH_TYPE)START_TASK_STACK, // 任务栈大小,默认最小128,单位4字节
(void *)NULL, // 传递给任务的参数
(UBaseType_t)START_TASK_PRIORITY, // 任务的优先级
(TaskHandle_t *)&start_task_handle); // 任务句柄的地址
/* 2.启动调度器:会自动创建空闲任务 */
vTaskStartScheduler();
}
/**
* @description: 启动任务:用来创建其他Task
* @param {void} *pvParameters
* @return {*}
*/
void start_task(void *pvParameters)
{
/* 进入临界区:保护临界区里的代码不会被打断 */
taskENTER_CRITICAL();
/* 创建3个任务 */
xTaskCreate((TaskFunction_t)task1,
(char *)"task1",
(configSTACK_DEPTH_TYPE)TASK1_STACK,
(void *)NULL,
(UBaseType_t)TASK1_PRIORITY,
(TaskHandle_t *)&task1_handle);
xTaskCreate((TaskFunction_t)task2,
(char *)"task2",
(configSTACK_DEPTH_TYPE)TASK2_STACK,
(void *)NULL,
(UBaseType_t)TASK2_PRIORITY,
(TaskHandle_t *)&task2_handle);
xTaskCreate((TaskFunction_t)task3,
(char *)"task3",
(configSTACK_DEPTH_TYPE)TASK3_STACK,
(void *)NULL,
(UBaseType_t)TASK3_PRIORITY,
(TaskHandle_t *)&task3_handle);
/* 启动任务只需要执行一次即可,用完就删除自己 */
vTaskDelete(NULL);
/* 退出临界区 */
taskEXIT_CRITICAL();
}
/**
* @description: 任务一:实现LED1每500ms闪烁一次
* @param {void} *pvParameters
* @return {*}
*/
void task1(void *pvParameters)
{
while (1)
{
printf("task1 is running\r\n");
led_n(1, 1);
vTaskDelay(500);
led_n(1, 0);
vTaskDelay(500);
}
}
/**
* @description: 任务二:实现LED2每500ms闪烁一次
* @param {void} *pvParameters
* @return {*}
*/
void task2(void *pvParameters)
{
while (1)
{
printf("task2 is running\r\n");
led_n(8, 1);
vTaskDelay(500);
led_n(8, 0);
vTaskDelay(500);
}
}
/**
* @description: 任务三:判断按键KEY1是否按下,按下则删掉task1
* @param {void} *pvParameters
* @return {*}
*/
extern volatile uint8_t j;
extern volatile uint8_t key_number;
void task3(void *pvParameters)
{
while (1)
{
printf("task3 is running\r\n");
if (key_number == 1)
{
/* 判断是否已经删过,避免重复执行删除 */
if (task1_handle != NULL)
{
/* key1按下了,删除task1 */
printf("task1 is delete\r\n");
vTaskDelete(task1_handle);
task1_handle = NULL;
}
key_number = 0;
}
vTaskDelay(500);
// HAL_Delay(500); //这种delay不会让任务进入阻塞态,不会让出cpu使用权
}
}
freertos_demo.h文件
/*
* @Author: random
* @Date: 2025-05-10 01:23:57
* @Last Modified by: random
* @Last Modified time: Do not Edit
*/
#ifndef __FREERTOS_DEMO_H
#define __FREERTOS_DEMO_H
void freertos_start(void);
#endif
main.c文件
添加头文件
#include "freertos_demo.h"
printf重定向
int fputc(int ch,FILE *f)
{
HAL_UART_Transmit(&huart1,(uint8_t *)&ch,1,HAL_MAX_DELAY);
return ch;
}
/* 开启按键定时器TIM3 */
HAL_TIM_Base_Start_IT(&htim3);
/* 启动FreeRTOS */
freertos_start();
/* 注意:在进入freertos后面的代码,没机会执行 */
我写的hal库工程原本写好了串口封装和定时器按键封装(此处就不在写了)