目录
硬件平台:
- STM32F103
相关配置:
1. FreeRTOS延时函数
延时函数:
- vTaskDelay:相对延时,从延时函数调用开始,任务进入阻塞状态,直到指定延时时间完毕。
- vTaskDelayUntil:绝对延时,计算整个任务的执行时间,最后用指定延时时间减去任务当前的执行时间即为任务所需的延时。
1.1 相对延时 - vTaskDelay
函数说明:
- 注意实现: INCLUDE_vTaskDelay设置为1
- 参数1: 指定延时的时间,单位为滴答周期(STM32所一直的FreeRTOS滴答周期为1ms)
void vTaskDelay( const TickType_t xTicksToDelay );
1.2 绝对延时 - vTaskDelayUntil
函数说明:
- 注意实现: INCLUDE_vTaskDelayUntil设置为1
- 参数1: 当前滴答计数的值的指针
- 参数2: 指定延时的时间,单位为滴答周期(STM32所一直的FreeRTOS滴答周期为1ms)
void vTaskDelayUntil( TickType_t *pxPreviousWakeTime,
const TickType_t xTimeIncrement );
获取滴答计数值函数:
- 返回值: 返回当前滴答计数的值
- 注意实现: 无法从中断中获取
volatile TickType_t xTaskGetTickCount( void );
2. 相对延时与绝对延时示例
示例流程:
- 系统启动函数:创建一个启动任务
- 启动任务执行函数
- 创建任务1
- 创建任务2
- 任务1:
- 串口打印Task1
- CPU延时200ms
- 相对延时1s
- 任务2:
- 获取当前计数周期的值
- 打印Task2
- CPU延时200ms
- 绝对延时1s
2.1 系统启动函数
函数说明:
- 动态创建一个启动任务
- 启动任务调度器
/* 启动任务相关配置 */
void startTask(void *args); /* 启动任务执行函数 */
#define START_TASK_NAME "start" /* 启动任务的名称 */
#define START_TASK_STACK_DEPTH 128 /* 启动任务栈大小 = 2 * 128 字节 */
#define START_TASK_PRIORITY 4 /* 启动任务优先级 */
TaskHandle_t startTaskTCB; /* 启动任务的控制块 */
void FreeRTOS_Start(void)
{
/* 1. 创建启动任务 */
xTaskCreate(
startTask,
START_TASK_NAME,
START_TASK_STACK_DEPTH,
NULL,
START_TASK_PRIORITY,
&startTaskTCB
);
/* 2. 启动任务调度器 */
vTaskStartScheduler();
}
2.2 启动任务执行函数
函数说明:
- 创建任务1与任务2
- 回收起始任务
/* 2个子任务相关配置 */
/* --------------------Task1-------------------- */
void taskFunc1(void *args); /* 任务1执行函数 */
#define TASK_NAME_1 "task1" /* 任务1的名称 */
#define TASK1_PRIORITY 4 /* 任务1优先级 */
TaskHandle_t task1TCB; /* 任务1的控制块 */
/* --------------------Task2-------------------- */
void taskFunc2(void *args); /* 任务2执行函数 */
#define TASK_NAME_2 "task2" /* 任务2的名称 */
#define TASK2_PRIORITY 3 /* 任务2优先级 */
TaskHandle_t task2TCB; /* 任务2的控制块 */
void startTask(void *args)
{
// 1. 代码进入临界区,防止代码中断
vPortEnterCritical();
debug_printfln("执行启动任务...");
// 2. 创建3个任务
xTaskCreate( /* 任务1 */
taskFunc1,
TASK_NAME_1,
START_TASK_STACK_DEPTH,
NULL,
TASK1_PRIORITY,
&task1TCB
);
xTaskCreate( /* 任务2 */
taskFunc2,
TASK_NAME_2,
START_TASK_STACK_DEPTH,
NULL,
TASK2_PRIORITY,
&task2TCB
);
// 3. 代码退出临界区
debug_printfln("启动任务执行完毕...\n回收启动任务...");
vPortExitCritical();
// 4. 回收启动任务
vTaskDelete(NULL);
}
2.3 任务1
函数说明
- 串口打印Task1
- CPU延时200ms
- 相对延时1s
void taskFunc1(void *args) /* 任务1执行函数 */
{
while (1)
{
debug_printfln("Task1...");
Delay_ms(200);
vTaskDelay(1000);
}
}
2.4 任务2
函数说明:
- 获取当前计数周期的值
- 打印Task2
- CPU延时200ms
- 绝对延时1s
void taskFunc2(void *args) /* 任务2执行函数 */
{
TickType_t tickCount = xTaskGetTickCount();
while (1)
{
debug_printfln("Task2...");
Delay_ms(200);
vTaskDelayUntil(&tickCount, 1000);
}
}
执行效果:
- Task2进入阻塞的时间大致为1000-200
- Task1进入阻塞的时间为1000
文章声明:
本文章为作者学习FreeRTOS实时操作系统的笔记与巩固输出,欢迎同行交流与指教,文章借鉴来源小破站的某谷RTOS教程。
FreeRTOSDemo.h
#ifndef __FREERTOS_DEMO_H
#define __FREERTOS_DEMO_H
/* 任务相关 */
#include "FreeRTOS.h"
#include "task.h"
#include "Common_Debug.h"
#include "Common_Delay.h"
#include "Inf_Key.h"
/* 1. 启动操作系统 */
void FreeRTOS_Start(void);
#endif
FreeRTOSDemo.c
#include "FreeRTOS_Demo.h"
/* 启动任务相关配置 */
void startTask(void *args); /* 启动任务执行函数 */
#define START_TASK_NAME "start" /* 启动任务的名称 */
#define START_TASK_STACK_DEPTH 128 /* 启动任务栈大小 = 2 * 128 字节 */
#define START_TASK_PRIORITY 4 /* 启动任务优先级 */
TaskHandle_t startTaskTCB; /* 启动任务的控制块 */
/* 2个子任务相关配置 */
/* --------------------Task1-------------------- */
void taskFunc1(void *args); /* 任务1执行函数 */
#define TASK_NAME_1 "task1" /* 任务1的名称 */
#define TASK1_PRIORITY 4 /* 任务1优先级 */
TaskHandle_t task1TCB; /* 任务1的控制块 */
/* --------------------Task2-------------------- */
void taskFunc2(void *args); /* 任务2执行函数 */
#define TASK_NAME_2 "task2" /* 任务2的名称 */
#define TASK2_PRIORITY 3 /* 任务2优先级 */
TaskHandle_t task2TCB; /* 任务2的控制块 */
void FreeRTOS_Start(void)
{
/* 1. 创建启动任务 */
xTaskCreate(
startTask,
START_TASK_NAME,
START_TASK_STACK_DEPTH,
NULL,
START_TASK_PRIORITY,
&startTaskTCB
);
/* 2. 启动任务调度器 */
vTaskStartScheduler();
}
void startTask(void *args)
{
// 1. 代码进入临界区,防止代码中断
vPortEnterCritical();
debug_printfln("执行启动任务...");
// 2. 创建3个任务
xTaskCreate( /* 任务1 */
taskFunc1,
TASK_NAME_1,
START_TASK_STACK_DEPTH,
NULL,
TASK1_PRIORITY,
&task1TCB
);
xTaskCreate( /* 任务2 */
taskFunc2,
TASK_NAME_2,
START_TASK_STACK_DEPTH,
NULL,
TASK2_PRIORITY,
&task2TCB
);
// 3. 代码退出临界区
debug_printfln("启动任务执行完毕...\n回收启动任务...");
vPortExitCritical();
// 4. 回收启动任务
vTaskDelete(NULL);
}
void taskFunc1(void *args) /* 任务1执行函数 */
{
while (1)
{
debug_printfln("Task1...");
Delay_ms(200);
vTaskDelay(1000);
}
}
void taskFunc2(void *args) /* 任务2执行函数 */
{
TickType_t tickCount = xTaskGetTickCount();
while (1)
{
debug_printfln("Task2...");
Delay_ms(200);
vTaskDelayUntil(&tickCount, 1000);
}
}
extern void xPortSysTickHandler(void);
void SysTick_Handler(void)
{
if(xTaskGetSchedulerState() != taskSCHEDULER_NOT_STARTED)
{
xPortSysTickHandler();
}
}