FreeRTOS学习笔记三

portBASE_TYPE xQueueSendToFront( xQueueHandle xQueue,  //目标队列的句柄  xQueueCreate() 创建该队列时的返回值
const void * pvItemToQueue,     //发送数据的指针。 其指向将要复制到目标队列中的数据单元
portTickType xTicksToWait );    //阻塞超时时间。 如果在发送时队列已满,这个时间即是任务处于阻塞态灯队列空间有效的最长等待时间
如果xTicksToWait 设为0 , 并且队列已满, 则
xQueueSendToFront()与xQueueSendToBack()均会立即返回。

返回值
1、pdPASS
返回pdPASS 只会有一种情况,那就是数据被成功发送到队列中。

2、errQUEUE_FULL
如果由于队列已满而无法将数据写入, 则将返回
errQUEUE_FULL。

xQueueReceive()
用于从队列中接收(读取)数据单元。接收到的单元同时会从队列
中删除。

xQueuePeek()
也是从从队列中接收数据单元,不同的是并不从队列中删出接收到
的单元。xQueuePeek()从队列首接收到数据后,不会修改队列中的数据,也不会改变
数据在队列中的存储序顺。


portBASE_TYPE xQueueReceive( xQueueHandle xQueue,
const void * pvBuffer,
portTickType xTicksToWait );

xTicksToWait    阻塞超时时间。  如果在接收时队列为空,则这个时间是任务处于阻塞状态以等待队列数据有效的最长等待时间。

uxQueueMessagesWaiting()  用于查询队列中当前有效数据单元个数。

unsigned portBASE_TYPE uxQueueMessagesWaiting( xQueueHandle xQueue );

返回值 当前队列中保存的数据单元个数。返回0 表明队列为空。


读队列是阻塞

队列会不会触发任务????

往队列中写数据的任务的优先级低于读队列的优先级。这意味着队列中永远不会保持超过一个的数据单元。因为一旦有数据被写入
队列,读队列任务立即解除阻塞,抢占写队列任务,并从队列中接收数据,同时数据从队列中删除---队列再一次为空队列。

写队列任务在每次循环中都调用taskYIELD()。taskYIELD()通知调度器立即进行任
务切换,而不必等到当前任务的时间片耗尽。某个任务调用taskYIELD()等效于其自愿
放弃运行态。由于本例中两个写队列任务具有相同的任务优先级,所以一旦其中一个任
务调用了taskYIELD(),另一个任务将会得到执行 — 调用taskYIELD()的任务转移到
就绪态,同时另一个任务进入运行态。这样就可以使得这两个任务轮翻地往队列发送数据。


使用队列传递复合数据类型

一个任务从单个队列中接收来自多个发送源的数据是经常的事。通常接收方收到数
据后,需要知道数据的来源,并根据数据的来源决定下一步如何处理。


利用队列传递结构体,结构体成员中就包含了数据信息和来源信息。
typedef struct
{
    int iValue;   //数据值
    int iMeaning;  //数据含义    
}xData;

中央控制任务用于完成主要的系统功能。其必须对队列中传来的输入和其它系统状态的改变做出响应。


typedef struct
{
    unsigned char ucValue;
    unsigned char ucSource;
} xData;


static const xData xStructsToSend[ 2 ] =
{
    { 100, mainSENDER_1 }, /* Used by Sender1. */
    { 200, mainSENDER_2 } /* Used by Sender2. */
};


2.4 工作于大型数据单元

如果队列存储的数据单元尺寸较大,那最好是利用队列来传递数据的指针而不是对
数据本身在队列上一字节一字节地拷贝进或拷贝出。传递指针无论是在处理速度上还是
内存空间利用上都更有效。但是,当你利用队列传递指针时,一定要十分小心地做到以
下两点:

1、指针指向的内存空间的所有权必须明确

当任务间通过指针共享内存时,应该从根本上保证所不会有任意两个任务同时
修改共享内存中的数据。

2、指针指向的内存空间必须有效

如果指针指向的内存空间是动态分配的,只应该有一个任务负责对其进行内存
释放。当这段内存空间被释放之后,就不应该有任何一个任务再访问这段空间。

第三章  中断管理

事件

    
3.2 延迟中断处理

采用二值信号量同步

二值信号量可以在某个特殊的中断发生时,让任务解除阻塞,相当于让任务与中断同步。

中断处理可以说被“推迟”到一个“处理(handler)”任务。

void vSemaphoreCreateBinary( xSemaphoreHandle xSemaphore );

xSemaphore  创建的信号量

需要说明的是vSemaphoreCreateBinary()在实现上是一个宏,所以
信号量变量应当直接传入,而不是传址。

xSemaphoreTake() API 函数
除互斥信号量  Recursive Semaphore

portBASE_TYPE xSemaphoreTake( xSemaphoreHandle xSemaphore, portTickType xTicksToWait );

xSemaphore  获取得到的信号量

xTicksToWait  阻塞超时时间。

xSemaphoreGiveFromISR() API 函数

除互斥信号量外, FreeRTOS 支持的其它类型的信号量都可以通过调用xSemaphoreGiveFromISR()给出。

 
。注意这里是如何使
用参数pxHigherPriorityTaskWoken 的。这个参数在调用xSemaphoreGiveFromISR()
前被设置为pdFALSE,如果在调用完成后被置为pdTRUE,则需要进行一次上下文切
换。


3.3 计数信号量

一个二值信号量最多只可以锁存一个中断事件。在锁存的事
件还未被处理之前,如果还有中断事件发生,那么后续发生的中断事件将会丢失。如果
用计数信号量代替二值信号量,那么,这种丢中断的情形将可以避免。


xSemaphoreHandle xSemaphoreCreateCounting( unsigned portBASE_TYPE uxMaxCount,
unsigned portBASE_TYPE uxInitialCount );

uxMaxCount   最大计数值。

uxInitialCount  信号量的初始计数值。


资源管理

在这种用法中,信号量的计数值用于表示可用资源的数目。一个任务要获取资源的
控制权,其必须先获得信号量——使信号量的计数值减1。当计数值减至0,则表示没
有可用资源。当任务利用资源完成工作后,将给出(归还)信号量——使信号量的计数值
加1。


3.5 中断嵌套

中断嵌套需要在FreeRTOSConfig.h 中 详细列出的一个或两个常量。

configKERNEL_INTERRUPT_PRIORITY  设置系统心跳时钟的中断优先级。

如果在移植中没有使用常量
configMAX_SYSCALL_INTERRUPT_PRIORITY,那
么需要调用中断安全版本FreeRTOS API
的中断都必须运行在此优先级上。

configMAX_SYSCALL_INTERRUPT_PRIORITY  设置中断安全版本FreeRTOS API 可以运行的最高中断优先级。

中断优先级是由微控制器架构体系所定义的。

中断优先级是硬件控制的优先级,中断服务例程的执行会与之关联。



你可能感兴趣的:(FreeRTOS)