大纲
目前学习RTOS的好处:使代码不断交替任务执行,防止流水式代码带来的响应速度慢。
RTOS总结:创建多个任务代码;不同代码之间通信;资源管理。
一、创建代码
动态创建
BaseType_t xTaskCreate( TaskFunction_t pxTaskCode, // 函数指针, 任务函数
const char * const pcName, // 任务的名字
const configSTACK_DEPTH_TYPE usStackDepth, // 栈大小,单位为word,10表示40字节
void * const pvParameters, // 调用任务函数时传入的参数
UBaseType_t uxPriority, // 优先级
TaskHandle_t * const pxCreatedTask ); // 任务句柄, 以后使用它来操作这个任务
静态创建
TaskHandle_t xTaskCreateStatic( TaskFunction_t pxTaskCode,
const char * const pcName, /*lint !e971 Unqualified har types are allowed for strings and single characters only. */
const uint32_t ulStackDepth,
void * const pvParameters,
UBaseType_t uxPriority,
StackType_t * const puxStackBuffer,
StaticTask_t * const pxTaskBuffer )
其他函数
任务删除函数
void vTaskDelete( TaskHandle_t xTaskToDelete );
/*
自杀: vTaskDelete(NULL)
被杀:别的任务执行 vTaskDelete(pvTaskCode) ,pvTaskCode是自己的句柄
杀人:执行 vTaskDelete(pvTaskCode) ,pvTaskCode是别的任务的句柄
*/
延时函数
/*
vTaskDelay:至少等待指定个数的Tick Interrupt才能变为就绪状态
vTaskDelayUntil:等待到指定的绝对时刻,才能变为就绪态。
*/
void vTaskDelay( const TickType_t xTicksToDelay ); /* xTicksToDelay: 等待多少给
Tick */
/* pxPreviousWakeTime: 上一次被唤醒的时间
* xTimeIncrement: 要阻塞到(pxPreviousWakeTime + xTimeIncrement)
* 单位都是Tick Count
*/
BaseType_t xTaskDelayUntil( TickType_t * const pxPreviousWakeTime,
const TickType_t xTimeIncrement );
空闲任务
vTaskStartScheduler() ;//这个函数运行时,会创建空闲任务
二、不同代码之间通信
内核对象 | 生产者 | 消费者 | 数据/状态 | 说明 |
队列 | ALL | ALL | 数据:若干个数据 谁都可以从队列里读数据 | 用来传递数据, 一个数据只能唤醒─个接收者 |
事件组 | ALL | ALL | 多个位:或、与 谁都可以等待某个位、若干个位 | 用来传递事件, 可以是N个事件, 可以唤醒多个接收者:像广播 |
信号量 | ALL | ALL | 数量:0~n 谁都可消耗一个数量 | 用来维持资源的个数, 生产者、消费者无限制, 1个资源只能唤醒1个接收者 |
任务通知 | ALL | 只有我 | 数据、状态都可以传输, 使用任务通知时, | N对1的关系: 发送者无限制, |
互斥量 | 只能A上锁 | ALL | 位:0、1 | 就像个空厕所, 谁使用谁上锁, 也只能由他开锁 |
1.队列
动态分配内存
/*
uxQueueLength 队列长度,最多能存放多少个数据(item)
uxItemSize 每个数据(item)的大小:以字节为单位
返回值 非0:成功,返回句柄,以后使用句柄来操作队列
NULL:失败,因为内存不足
*/
QueueHandle_t xQueueCreate( UBaseType_t uxQueueLength, UBaseType_t uxItemSize );
静态分配内存
/*
uxQueueLength:队列长度,最多能存放多少个数据(item)
uxItemSize:每个数据(item)的大小:以字节为单位
pucQueueStorageBuffer:如果uxItemSize非0,pucQueueStorageBuffer必须指向一个uint8_t数组,此数组大小至少为"uxQueueLength*uxItemSize"
pxQueueBuffer:必须执行一个StaticQueue_t结构体,用来保存队列的数据结构
返回值:非0:成功,返回句柄,以后使用句柄来操作队列 NULL:失败,因为pxQueueBuffer为NULL
*/
QueueHandle_t xQueueCreateStatic(
UBaseType_t uxQueueLength,
UBaseType_t uxItemSize,
uint8_t *pucQueueStorageBuffer,
StaticQueue_t *pxQueueBuffer
);
复位
/* pxQueue : 复位哪个队列;
* 返回值: pdPASS(必定成功)
*/
BaseType_t xQueueReset( QueueHandle_t pxQueue);
删除
void vQueueDelete( QueueHandle_t xQueue );
写队列
/* 等同于xQueueSendToBack
* 往队列尾部写入数据,如果没有空间,阻塞时间为xTicksToWait
*/
BaseType_t xQueueSend(
QueueHandle_t xQueue,
const void *pvItemToQueue,这些函数用到的参数是类似的,统一说明如下:
TickType_t xTicksToWait
);
/*
* 往队列尾部写入数据,如果没有空间,阻塞时间为xTicksToWait
*/
BaseType_t xQueueSendToBack(
QueueHandle_t xQueue,
const void *pvItemToQueue,
TickType_t xTicksToWait
);
/*
* 往队列尾部写入数据,此函数可以在中断函数中使用,不可阻塞
*/
BaseType_t xQueueSendToBackFromISR(
QueueHandle_t xQueue,
const void *pvItemToQueue,
BaseType_t *pxHigherPriorityTaskWoken
);
/*
* 往队列头部写入数据,如果没有空间,阻塞时间为xTicksToWait
*/
BaseType_t xQueueSendToFront(
QueueHandle_t xQueue,
const void *pvItemToQueue,
TickType_t xTicksToWait
);
/*
* 往队列头部写入数据,此函数可以在中断函数中使用,不可阻塞
*/
BaseType_t xQueueSendToFrontFromISR(
QueueHandle_t xQueue,
const void *pvItemToQueue,
BaseType_t *pxHigherPriorityTaskWoken
);
读队列
BaseType_t xQueueReceive( QueueHandle_t xQueue,
void * const pvBuffer,
TickType_t xTicksToWait );
BaseType_t xQueueReceiveFromISR(
QueueHandle_t xQueue,
void *pvBuffer,
BaseType_t *pxTaskWoken
);