参考教程:https://rtos.100ask.net/zh/FreeRTOS/DShanMCU-F103/chapter7.html
freertos学习笔记
任务管理
任务
-
创建任务
void xTaskCreate(TaskFunction_t pvTaskCode, const char * const pcName, const uint32_t usStackDepth, void * const pvParameters, UBaseType_t uxPriority, TaskHandle_t * const pvCreatedTask)
实际分配的任务栈内存大小为usStackDepth*堆栈宽度
-
删除任务
void vTaskDelete( TaskHandle_t xTaskToDelete );
-
example:
TaskHandle_t app_task1_handl; xTaskCreate((TaskFunction_t)app_task1, (const char *)"app_task1", 2048, NULL, 1, (TaskHandle_t *)&app_task1_handl); vTaskDelete(app_task1_handl);
延时
- 普通延时
void vTaskDelay( const TickType_t xTicksToDelay )
xTicksToDelay: 等待多少个tick
同步互斥与通信
能实现同步、互斥的内核方法有:任务通知(task notification)、队列(queue)、事件组(event group)、信号量(semaphoe)、互斥量(mutex)。
内核对象 | 生产者 | 消费者 | 数据/状态 | 说明 |
---|---|---|---|---|
队列 | ALL | ALL | 数据:若干个数据 谁都可以往队列里扔数据, 谁都可以从队列里读数据 | 用来传递数据, 发送者、接收者无限制, 一个数据只能唤醒一个接收者 |
事件组 | ALL | ALL | 多个位:或、与 谁都可以设置(生产)多个位, 谁都可以等待某个位、若干个位 | 用来传递事件, 可以是N个事件, 发送者、接受者无限制, 可以唤醒多个接收者:像广播 |
信号量 | ALL | ALL | 数量:0~n 谁都可以增加一个数量, 谁都可消耗一个数量 | 用来维持资源的个数, 生产者、消费者无限制, 1个资源只能唤醒1个接收者 |
任务通知 | ALL | 只有我 | 数据、状态都可以传输, 使用任务通知时, 必须指定接受者 | N对1的关系: 发送者无限制, 接收者只能是这个任务 |
互斥量 | 只能A开锁 | A上锁 | 位:0、1 我上锁:1变为0, 只能由我开锁:0变为1 | 就像一个空厕所, 谁使用谁上锁, 也只能由他开锁 |
-
队列:
- 里面可以放任意数据,可以放多个数据
- 任务、ISR都可以放入数据;任务、ISR都可以从中读出数据
-
事件组:
- 一个事件用一bit表示,1表示事件发生了,0表示事件没发生
- 可以用来表示事件、事件的组合发生了,不能传递数据
- 有广播效果:事件或事件的组合发生了,等待它的多个任务都会被唤醒
-
信号量:
- 核心是"计数值"
- 任务、ISR释放信号量时让计数值加1
- 任务、ISR获得信号量时,让计数值减1
-
任务通知:
- 核心是任务的TCB里的数值
- 会被覆盖
- 发通知给谁?必须指定接收任务
- 只能由接收任务本身获取该通知
队列
- 创建队列
QueueHandle_t xQueueCreate( uxQueueLength, uxItemSize )
- 发送队列
BaseType_t xQueueSend( xQueue, pvItemToQueue, xTicksToWait )
- 接收队列
BaseType_t xQueueReceive( QueueHandle_t xQueue, void * const pvBuffer, TickType_t xTicksToWait )
- example:
// 创建消息元素类型
typedef struct
{
uint8_t message_id;
uint8_t buf[256];
uint16_t len;
}uart_msg_rt;
// 定义消息类型
uart_msg_rt uart_rx_msg;
uart_msg_rt *pRxMsg;
// 定义消息队列
QueueHandle_t myRxQueue;
// 创建队列大小为10,消息类型为uart_msg_rt
myRxQueue = xQueueCreate(10, sizeof(uart_msg_rt *));
// 准备数据
memcpy(uart_rx_msg.buf, data, rxBytes);
uart_rx_msg.len = rxBytes;
pRxMsg = &uart_rx_msg;
// 写队列
if (xQueueSend(myRxQueue, (void *) &pRxMsg, (TickType_t)10) != pdPASS)
{
ESP_LOGE(RX_TASK_TAG, "send myRxQueue err!");
}
// 读队列
if (xQueueReceive(myRxQueue, (void *)&puart_rx_msg, portMAX_DELAY) != pdPASS)
{
printf("%s err", __func__);
}
else
{
// 读取成功
}