free RTOS的API典型例子分析.pdf

上传人:海阔****涯 文档编号:95341254 上传时间:2023-08-20 格式:PDF 页数:43 大小:403.64KB
返回 下载 相关 举报
free RTOS的API典型例子分析.pdf_第1页
第1页 / 共43页
free RTOS的API典型例子分析.pdf_第2页
第2页 / 共43页
点击查看更多>>
资源描述

《free RTOS的API典型例子分析.pdf》由会员分享,可在线阅读,更多相关《free RTOS的API典型例子分析.pdf(43页珍藏版)》请在得力文库 - 分享文档赚钱的网站上搜索。

1、目录目录一、任务创建.1二、任务控制.4三、内核控制.1011.vTaskStartScheduler.1012.vTaskEndSchedule.1113.vTaskSuspendAll.11四、队列管理.12五、信号量.26六、联合程序.33一、任务创建1.xTaskCreatetask.hportBASE_TYPE xTaskCreate(pdTASK_CODE pvTaskCode,const portCHAR*const pcName,unsigned portSHORT usStackDepth,void*pvParameters,unsigned portBASE_TYPE ux

2、Priority,xTaskHandle*pvCreatedTask);创建新的任务并添加到任务队列中,准备运行Parameters:pvTaskCode指向任务的入口函数.任务必须执行并且永不返回(即:无限循环).pcName描述任务的名字。主要便于调试。最大长度由 configMAX_TASK_NAME_LEN.定义usStackDepth指定任务堆栈的大小,堆栈能保护变量的数目-不是字节数.例如,如果堆栈为 16 位宽度,usStackDepth 定义为 100,200 字节,这些将分配给堆栈。堆栈嵌套深度(堆栈宽度)不能超多最大值包含了 size_t 类型的变量pvParameters

3、指针用于作为一个参数传向创建的任务uxPriority任务运行时的优先级pvCreatedTask 用于传递一个处理引用创建的任务返回:pdPASS 是如果任务成功创建并且添加到就绪列中,另外错误代码在 projdefs.H 文件定义2.vTaskDeletetask.hvoid vTaskDelete(xTaskHandle pxTask);INCLUDE_vTaskDelete 必须定义为 1,这个函数才能可用。查看配置部分获得更多信息。从 RTOS 实时内核管理中移除任务。要删除的任务将从就绪,封锁,挂起,事件列表中移除。注意:空闲任务负责释放内核分配给已删除任务的内存。因此,如果应用程

4、序调用了 vTaskDelete(),微控制器执行时间,空闲任务不假死是很重要的。内存分配给任务的代码不会自动释放,应该在任务删除之前。参数:pxTask处理要删除的任务。传递 NULL 将引起调用任务删除二、任务控制3.vTaskDelaytask.hvoid vTaskDelay(portTickType xTicksToDelay);INCLUDE_vTaskDelay 必须设置为 1,这个函数才为可用。参考配置获得更多信息。延时任务为已知时间片。任务被锁住剩余的实际时间由时间片率决定。portTICK_RATE_MS 常量用来用来从时间片速率(一片周期代表着分辨率)来计算实际时间。vT

5、askDelay()指定一个任务希望的时间段,这个时间之后(调用 vTaskDelay())任务解锁。例如,指定周期段为 100 时间片,将使任务在调用 vTaskDelay()100 个时间片之后解锁。vTaskDelay()不提供一个控制周期性任务频率的好方法,像通过代码采取的路径,和其他任务和中断一样,在调用 vTaskDelay()后 影响频率,因此任务所需的时间下一次执行。参考 vTaskDelayUntil(),这个交替的 API 函数设计了执行固定的频率。它是指定的一个绝对时间(而不是一个相对时间)后,调用任务解锁。参数:xTicksToDelay时间数量,调用任务应该锁住的时间

6、片周期4.vTaskDelayUntiltask.hvoid vTaskDelayUntil(portTickType*pxPreviousWakeTime,portTickTypexTimeIncrement);INCLUDE_vTaskDelayUntil 必须定义为 1,此函数才能用。参考配置获得更多信息。延时一个任务到指定时间。这个函数用在循环任务以确保一定频率执行。这个函数在一个重要方面上不同于 vTaskDelay(),vTaskDelay()指定的这个时间(任务希望开启)是与 vTaskDelay()有关,而 vTaskDelayUntil()指定是一个绝对时间(任务希望开启)v

7、TaskDelay()中断任务从调用这个函数开始到指定时间。很难使用 vTaskDelay()自身来产生一个固定的执行频率,因为:随着调用 vTaskDelay()一个任务开启的时间和任务下一次调用 vTaskDelay()的时间,这两者之间可能不是固定的【任务可能采取不同方式,可能通过调用,可能来自中断,或者优先取得每次任务执行的时间】。而 vTaskDelay()指定的时间与调用这个函数相关,vTaskDelayUntil()指定的是绝对时间(任务希望开启的)。应该注意:vTaskDelayUntil()如果指定的苏醒时间使用完,将立即返回。因此,一个使用vTaskDelayUntil()

8、来周期性的执行的任务,如果执行周期因为任何原因(例如任务是临时为悬挂状态)暂停而导致任务错过一个或多个执行周期,那么需要重新计算苏醒时间。通过检查像pxPreviousWakeTime 可变的参数来组织当前时间片计数。然而在大多数使用中并不是必须的。产量 portTICK_RATE_MS 用来计算时间片频率的实时时间-按照一个时间片周期。参数:pxPreviousWakeTime 指定一个变量来掌握任务最后开启的时间。这个变量在第一次使用中(参考下面的例子)必须使用当前时间来初始化。在 vTaskDelayUntil()中,这个变量是自动修改的xTimeIncrement循环周期时间。任务将在

9、一定时间开启(*pxPreviousWakeTime+xTimeIncrement)。使用相同的xTimeIncrement 参数值,来调用 vTaskDelayUntil()将使任务按固定的周期执行。5.uxTaskPriorityGettask.hunsigned portBASE_TYPE uxTaskPriorityGet(xTaskHandle pxTask);设置 INCLUDE_vTaskPriorityGet 为 1,此函数才能用。参考配置以获得更多信息。获得任务的优先级。参数:pxTask需要处理的任务.当传递 NULL 时,将返回所调用任务的优先级Returns:pxTas

10、k 的优先级6.vTaskPrioritySettask.hvoid vTaskPrioritySet(xTaskHandle pxTask,unsigned portBASE_TYPE uxNewPriority);设置 INCLUDE_vTaskPrioritySet 为 1,才能使用此函数。参考配置获得更多信息。设置任务的优先级。如果设置的优先级高于当前执行任务的优先级,则上下文切换将在此函数返回之前发生。参数:pxTask需要设置优先级的任务。当传递 NULL,将设置调用任务的优先级uxNewPriority任务需要设置的优先级7.vTaskSuspendtask.hvoid vTas

11、kSuspend(xTaskHandle pxTaskToSuspend);设置 INCLUDE_vTaskSuspend 为 1,此函数才能使用。参考配置获得更多信息。挂起任务,当挂起一个任务时,不管优先级是多少,不需要占用任何微控制器处理器时间。调用vTaskSuspend 不会累积即:在统一任务中调用 vTaskSuspend 两次,但只需调用一次vTaskResume()来是挂起的任务就绪。参数:pxTaskToSuspend处理需要挂起的任务。传递 NULL 将挂起调用此函数的任务。8.vTaskResumetask.hvoid vTaskResume(xTaskHandle pxT

12、askToResume);设置 INCLUDE_vTaskSuspend 为 1,此函数才能使用。参考配置获得更多信息。唤醒挂起的任务。必须是调用 vTaskSuspend()后挂起的任务,才有可能通过调用vTaskResume()重新运行。Parameters:pxTaskToResume就绪的任务的句柄9.vTaskResumeFromISRtask.hportBASE_TYPE vTaskResumeFromISR(xTaskHandle pxTaskToResume);设置 INCLUDE_vTaskSuspend 和 INCLUDE_xTaskResumeFromISR 都为 1,才

13、能使用此函数。参考配置获得更过信息。从 ISR 中唤醒挂起的任务。可能通过多个 调用 vTaskSuspend()挂起的任务,可以通过调用 xTaskResumeFromISR()再次运行。vTaskResumeFromISR()不应该用于任务和中断同步,因为可能会在中断发生期间,任务已经挂起这样导致错过中断。使用信号量最为同步机制将避免这种偶然性。参数:pxTaskToResume就绪任务的句柄Returns:pdTRUE:如果唤醒了任务将,引起上下文切换。pdFALSE.:用于 ISR 确定是否上下文切换10.vTaskSetApplicationTaskTagtask.hvoid vTa

14、skSetApplicationTaskTag(xTaskHandle xTask,pdTASK_HOOK_CODEpxTagValue);onfigUSE_APPLICATION_TASK_TAG 必须定义为 1,这个函数才能可用。参考配置获得更多信息。能为每个任务分配标签值。这个值仅在应用程序中使用,内核本身不使用它。RTOS tracemacros 文档提供了一个很好的例子应用程序如何利用这个特点。参数:xTask将分配给标签值的任务。传递 NULL 将分配标签给调用的任务。pxTagValue 分配给任务的标签值 类型为 pdTASK_HOOK_CODE,允许一个函数指针赋值给标签。因

15、此实际上任何值都可以分配。参考下面的例子。xTaskCallApplicationTaskHooktask.H#define traceTASK_SWITCHED_OUT()xTaskCallApplicationTaskHook(pxCurrentTCB,0)portBASE_TYPE xTaskCallApplicationTaskHook(xTaskHandle xTask,void*pvParameter);configUSE_APPLICATION_TASK_TAG 必须设置为 1,这个函数才能使用。参考配置获得更多信息。每个任务可以分配一个标签值。正常情况下,这个值仅用于应用程序,

16、内核并不存储。然而,可以使用标签赋值给钩子(或回调)函数给任务钩子函数将通过调用xTaskCallApplicationTaskHook()执行。每个任务定义自己的返回值,或者仅仅定义一个返回值。尽管可以使用第一个函数参数来调用任务中的钩子函数,最常见的使用是任务钩子函数描述钩子宏,像每个如下的例子。任务钩子函数必须使用 pdTASK_HOOK_CODE 类型,传递 void*参数,和返回 portBASE_TYPE 类型的值。Void*参数用来传递给钩子函数的任何信息。参数:xTask处理将被调用钩子函数的任务。xTask 当作 NULL 传递,将调用钩子函数赋值给当前执行的任务pvPara

17、meter 传递给钩子函数的值。可以是指向结构或数值的指针三、内核控制11.vTaskStartSchedulertask.hvoid vTaskStartScheduler(void);启动实时内核处理。在调用之后,内核已经控制执行的任务。当 vTaskStartScheduler()被调用时,空闲任务自动创建。如果 vTaskStartScheduler()成功调用,这个函数不返回,直到执行任务调用 vTaskEndScheduler()。如果可供给空闲任务的 RAM 不足,那么函数调用失败,并立即返回。12.vTaskEndScheduletask.hvoid vTaskEndSched

18、uler(void);停止实时内核运行。所有创建的任务将自动删除,并且多任务(优先级或合作式)将停止。当vTaskStartScheduler()调用时,执行将再次开始,像 vTaskStartScheduler()仅仅返回。在演示或 PC 路径的例子中,参考演示应用程序文件 main.c,例子中使用 vTaskEndScheduler()。vTaskEndScheduler()需要在便携层定义出口函数(参考在 port.c 提供 PC 接口的vPortEndScheduler())。执行硬件指定操作如停止内核执行。vPortEndScheduler()导致所有由内核分配的资源释放但是不会释放

19、由应用程序的任务分配的资源。13.vTaskSuspendAlltask.hvoid vTaskSuspendAll(void);挂起所有活动的实时内核,同时允许中断(包括内核滴答)。任务在调用 vTaskSuspendAll()后,这个任务将继续执行,不会有任何被切换的危险,直到调用 xTaskResumeAll()函数。API中有可能影响影响上下文切换的函数(例如,vTaskDelayUntil(),xQueueSend()等等),一定不能再调度器挂起时被调用。四、队列管理14.xQueueCreate队列管理queue.hxQueueHandle xQueueCreate(unsigne

20、d portBASE_TYPE uxQueueLength,unsigned portBASE_TYPE uxItemSize);创建一个新的队列。为新的队列分配所需的存储内存,并返回一个队列处理。Parameters:uxQueueLength 队列中包含最大项目数量。uxItemSize队列中每个项目所需的字节数。项目通过复制而不是引用排队,因为,所需的字节数,将复制给每个项目。队列中每个项目必须分配同样大小。Returns:如果队列成功创建,并返回一个新建队列的处理。如果不能创建队列,将返回 0。15.xQueueSend队列管理queue.hportBASE_TYPE xQueueSe

21、nd(xQueueHandle xQueue,const void*pvItemToQueue,portTickType xTicksToWait);是一个调用 xQueueGenericSend()的宏。能向后兼容 FreeRTOS.org(没有包括xQueueSendToFront()和xQueueSendToBack()宏的)版本。与 xQueueSendToBack()等效。传递一个项目到队列。这个项目通过复制而不是通过引用排队。这个函数不能从中断服务程序调用。参考xQueueSendFromISR(),在 ISR 中交错使用。xQueueSend()是全特点任务间通信 API 接口。

22、xQueueSend()等效于交叉 API。版本不要同样的参数和同样的返回值。Parameters:xQueue处理将项目传递给队列pvItemToQueue 指向队列中放置的项目的指针。项目的大小,由队列创建时定义,因为许多字节可以从 pvItemToQueue 复制到队列的储存区域xTicksToWait最大时间量(任务应该锁住,等待队列中的可用空间)应该已经满了。如果设置为 0,调用将立即返回。时间使用滴答周期来定义,因此如果需要,常量 portTICK_RATE_MS 应该用来转换实时时间Returns:pdTRUE:项目成功传递。否则为:errQUEUE_FULL.16.xQueue

23、SendToBack队列管理Only available from FreeRTOS.org V4.5.0 onwards.queue.hportBASE_TYPE xQueueSendToBack(xQueueHandle xQueue,const void*pvItemToQueue,portTickType xTicksToWait);是一个调用 xQueueGenericSend()的宏。相当于 xQueueSend()。传递项目到一个队列中的后面。这个项是复制队列,不是引用。这个函数不能被中断服务函数调用。参考xQueueSendToBackFromISR(),可以在 ISR 中交替

24、使用。xQueueSendToBack()是全功能任务间通信 API 接口。xQueueAltSendToBack()相当于 API 其中之一。版本需要相同的参数和相同的返回值。参数:xQueue将要传进的队列句柄pvItemToQueue 指向将要放进队列的项目。项目的大小由队列定义(队列创建时),许多字节从 pvItemToQueue 复制到队列存储区域xTicksToWait任务中断并等待队列中可用空间的最大时间,应该是满的。如果设置为 0,调用将立刻返回。时间在片区间中定义,如果需要,portTICK_RATE_MS 常量用来转换为实际时间。如果 INCLUDE_vTaskSuspen

25、d 定义为 1,指定的中断时间(portMAX_DELAY)将导致任务无限期中断(没有时间溢出)。Returns:pdTRUE 如果任务成功传递。否则为 errQUEUE_FULL.17.xQueueSendToFront队列管理仅适用于 FreeRTOS.org V4.5.0 以前版本queue.hportBASE_TYPE xQueueSendToToFront(xQueueHandle xQueue,const void*pvItemToQueue,portTickType xTicksToWait);是一个调用 xQueueGenericSend()的宏。传递项目到一个队列中的前面。这

26、个项是复制队列,不是引用。这个函数不能被中断服务函数调用。参考 xQueueSendToBackFromISR(),可以在ISR 中交替使用。xQueueSendToFront()是全功能任务间通信 API 接口。xQueueAltSendToFront()相当于 API 其中之一。版本需要相同的参数和相同的返回值。Parameters:xQueue将要传进的队列句柄pvItemToQueue 指向将要放进队列的项目。项目的大小由队列定义(队列创建时),许多字节从 pvItemToQueue 复制到队列存储区域xTicksToWait任务中断并等待队列中可用空间的最大时间,应该是满的。如果设置

27、为 0,调用将立刻返回。时间在片区间中定义,如果需要,portTICK_RATE_MS 常量用来转换为实际时间。如果 INCLUDE_vTaskSuspend 定义为 1,指定的中断时间(portMAX_DELAY)将导致任务无限期中断(没有时间溢出)。Returns:pdTRUE 如果任务成功传递。否则为 errQUEUE_FULL.18.xQueueReceive队列管理queue.hportBASE_TYPE xQueueReceive(xQueueHandle xQueue,void*pvBuffer,portTickType xTicksToWait);一个调用 xQueueGene

28、ricReceive()函数的宏。从队列接收一个项目。这个项目通过复制接收,因此缓冲器必须提供足够大的空间。复制进缓冲器的字节数,在队列创建时已经定义。这个函数一定不能在中断服务程序中使用。参考 xQueueReceiveFromISR 获得能够的选择。xQueueReceive()是全功能任务间通信 API 接口。xQueueAltReceive()相当于 API 其中之一。版本需要相同的参数和相同的返回值。参数:pxQueue将要接收项目的队列句柄pvBuffer指向将要复制接收项目的缓冲器的指针。xTicksToWait 任务中断并等待队列中可用空间的最大时间,应该是满的。如果设置为 0

29、,调用将立刻返回。时间在片区间中定义,如果需要,portTICK_RATE_MS 常量用来转换为实际时间。如果 INCLUDE_vTaskSuspend 定义为 1,指定的中断时间(portMAX_DELAY)将导致任务无限期中断(没有时间溢出)。Returns:如果项目成功被队列接收为 pdTRUE。否则为 pdFALSE.19.xQueuePeek队列管理Only available from FreeRTOS.org V4.5.0 onwards.queue.hportBASE_TYPE xQueuePeek(xQueueHandle xQueue,void*pvBuffer,portT

30、ickType xTicksToWait);一个调用 xQueueGenericReceive()函数的宏。从队列接收一个项目并从队列中移除该项目。这个项目通过复制接收,因此缓冲器必须提供足够大的空间。复制进缓冲器的字节数,在队列创建时已经定义。成功接收的项目在队列中保留,再下次调用时将再次返回,或者调用xQueueReceive()这个函数一定不能在中断服务程序中使用。xQueuePeek()是全功能任务间通信 API 接口。xQueueAltPeek()相当于 API 其中之一。版本需要相同的参数和相同的返回值。参数:xQueue将要接收项目的队列的句柄pvBuffer指向将要复制接收项目

31、的缓冲器的指针。项目的大小由队列定义(队列创建时),许多字节从 pvItemToQueue 复制到队列存储区域xTicksToWait 任务中断并等待队列中可用空间的最大时间,应该是满的。如果设置为 0,调用将立刻返回。时间在片区间中定义,如果需要,portTICK_RATE_MS 常量用来转换为实际时间。如果 INCLUDE_vTaskSuspend 定义为 1,指定的中断时间(portMAX_DELAY)将导致任务无限期中断(没有时间溢出)。返回值:pdTRUE 如果项目成功被队列接收。否则为 pdFALSE.20.xQueueSendFromISR队列管理queue.hportBASE_

32、TYPE xQueueSendFromISR(xQueueHandle pxQueue,const void*pvItemToQueue,portBASE_TYPE*pxHigherPriorityTaskWoken);这是一个调用xQueueGenericSendFromISR()的宏。是为了兼容FreeRTOS.org以后的版本(没有包含 xQueueSendToBackFromISR()和 xQueueSendToFrontFromISR()宏)传递一个项到队列的后面。在终端服务程序中可以安全使用。项在队列中是复制而不是引用,排列小项目更加灵活,特别是当从 ISR 调用时。在大多数情况下

33、,使用一个指向项目的指针传进队列更加灵活参数:xQueue将项目传进的队列pvItemToQueue一个指向将在队列中放置的项目的指针。项目的大小,队列在创建时已经定义了,将从 pvItemToQueue 复制许多字节到队列的存储区域pxHigherPriorityTaskWoken 如果传进队列而导致任务解锁,并且解锁的任务的优先级高于当前运行任务的优先级 xQueueSendFromISR 将设置*pxHigherPriorityTaskWoken 到 pdTRUE。如果xQueueSendFromISR()设置这个值到 pdTRUE,在中断推出之前将请求任务切换。Returns:pdTR

34、UE:数据成功传递进队列。否则为:errQUEUE_FULL。使用范例是缓冲 IO(每次调用 ISR 能够更多的值)21.xQueueSendToBackFromISR队列管理queue.hportBASE_TYPE xQueueSendToBackFromISR(xQueueHandle pxQueue,const void*pvItemToQueue,portBASE_TYPE*pxHigherPriorityTaskWoken);这是一个调用 xQueueGenericSendFromISR()的宏。是为了兼容 FreeRTOS.org 以后的版本(没有包含 xQueueSendToBa

35、ckFromISR()和 xQueueSendToFrontFromISR()宏)传递一个项到队列的后面。在终端服务程序中可以安全使用。项在队列中是复制而不是引用,排列小项目更加灵活,特别是当从 ISR 调用时。在大多数情况下,使用一个指向项目的指针传进队列更加灵活。参数:xQueue将项目传进的队列pvItemToQueue一个指向将在队列中放置的项目的指针。项目的大小,队列在创建时已经定义了,将从 pvItemToQueue 复制许多字节到队列的存储区域xTaskPreviouslyWoken 如果传进队列而导致任务解锁,并且解锁的任务的优先级高于当前运行任务的优先级 xQueueSend

36、FromISR 将设置*pxHigherPriorityTaskWoken 到 pdTRUE。如果xQueueSendFromISR()设置这个值到 pdTRUE,在中断推出之前将请求任务切换。Returns:pdTRUE:数据成功传递进队列。否则为:errQUEUE_FULL。使用范例是缓冲 IO(每次调用 ISR 能够更多的值)22.xQueueSendToFrontFromISR队列管理queue.hportBASE_TYPE xQueueSendToFrontFromISR(xQueueHandle pxQueue,const void*pvItemToQueue,portBASE_T

37、YPE*pxHigherPriorityTaskWoken);是一个调用 xQueueGenericSendFromISR().的宏。传递一个项到队列的后面。在终端服务程序中可以安全使用。项在队列中是复制而不是引用,排列小项目更加灵活,特别是当从 ISR 调用时。参数:xQueue将项目传进的队列pvItemToQueue一个指向将在队列中放置的项目的指针。项目的大小,队列在创建时已经定义了,将从 pvItemToQueue 复制许多字节到队列的存储区域xTaskPreviouslyWoken 如果传进队列而导致任务解锁,并且解锁的任务的优先级高于当前运行任务的优先级 xQueueSendTo

38、backFromISR()将设置*pxHigherPriorityTaskWoken 到 pdTRUE。如果xQueueSendToBackFromISR()设置这个值到 pdTRUE,在中断推出之前将请求任务切换。Returns:pdTRUE:数据成功传递进队列。否则为:errQUEUE_FULL。使用范例是缓冲 IO(每次调用 ISR能够更多的值)23.xQueueReceiveFromISR队列管理queue.hportBASE_TYPE xQueueReceiveFromISR(xQueueHandle pxQueue,void*pvBuffer,portBASE_TYPE*pxTas

39、kWoken);从队列接收一个项目。在中断程序中使用此函数是安全的。Parameters:pxQueue发送项目的队列句柄pvBuffer指向缓冲区的指针,将接收的项目被复制进去。pxTaskWoken 任务将锁住,等待队列中的可用空间。如果 xQueueReceiveFromISR 引起一个任务解锁,*pxTaskWoken 将设置为 pdTRUE,否则*pxTaskWoken 保留不变Returns:pdTRUE:如果项目成功从队列接收。否则为:pdFALSE24.vQueueAddToRegistry队列管理queue.hvoid vQueueAddToRegistry(xQueueHa

40、ndle xQueue,signed portCHAR*pcQueueName,);为队列命名,并加入队列到登记管理中Parameters:xQueue将要添加登记的队列句柄pcQueueName为指定的队列命名。仅仅是文本串,方便调试。队列登记有两个特点,均与内核的相关调试有关:允许文本式名字,使队列在调试 GUI 中方便定义。包含调试器需要的信息,如:定位每个已经登记的队列和信号量。队列的登记没有目的,除非使用内核相关的调试。configQUEUE_REGISTRY_SIZE 定义了队列和信号量的最大数目.仅当使用内核相关的调试时需要显示已经登记的信号量和队列。25.vQueueUnreg

41、isterQueue队列管理queue.hvoid vQueueUnregisterQueue(xQueueHandle xQueue,);从登记管理中移除队列。Parameters:xQueue从登记管理处中移出的队列句柄队列登记有两个特点,均与内核的相关调试有关:允许文本式名字,使队列在调试 GUI 中方便定义。包含调试器需要的信息,如:定位每个已经登记的队列和信号量。队列的登记没有目的,除非使用内核相关的调试。configQUEUE_REGISTRY_SIZE 定义了队列和信号量的最大数目.仅当使用内核相关的调试时需要显示已经登记的信号量和队列。五、信号量26.xSemaphoreCre

42、ateCounting信号量semphr.hxSemaphoreHandle xSemaphoreCreateCounting(unsigned portBASE_TYPEuxMaxCount,unsigned portBASE_TYPE uxInitialCount)使用已存在的队列结构来创建计数型信号量。计数型信号量有下面两种典型应用:1 事件计数在这种应用的情形下,事件处理程序会在每次事件发生时发送信号量(增加信号量计数值),而任务处理程序会在每次处理事件时请求信号量(减少信号量计数值)。因此计数值为事件发生与事件处理两者间的差值,在这种情况下计数值初始化为 0 是合适的。2 资源管理在

43、这种应用情形下,计数值指示出可用的资源数量。任务必须首先“请求”信号量来获得资源的控制权-减少信号量计数值。当计数值降为 0 时表示没有空闲资源。任务使用完资源后“返还”信号量-增加信号量计数值。在这种情况下计数值初始化为与最大的计数值相一致是合适的,这指示出所有的空闲资源。参数:uxMaxCount可以达到的最大计数值。当信号量达到此值后将不能被“返还”。uxInitialCount信号量创建时分配的初始值。返回:已创建的信号量句柄,为 xSemaphoreHandle 类型,如果信号量无法创建则为 NULL。27.xSemaphoreCreateMutex信号量只在 FreeRTOS.or

44、g V4.5.0 以后的版本中可用。semphr.hxSemaphoreHandle xSemaphoreCreateMutex(void)使用已存在的队列结构来创建互斥锁信号量的宏。通过此宏创建的互斥锁可以使用xSemaphoreTake()与 xSemaphoreGive()宏来访问。不能使用 xSemaphoreTakeRecursive()与 xSemaphoreGiveRecursive()宏。二元信号量与互斥锁十分相像,不过两者间有细微的差别:互斥锁包含一个优先级继承机制,而信号量没有。这种差别使得二元信号量更适合于实现同步(任务之间或任务与中断之间),互斥锁更适合于实现简单的互斥

45、。当有另外一个具有更高优先级的任务试图获取同一个互斥锁时,已经获得互斥锁的任务的优先级会被提升。已经获得互斥锁的任务将继承试图获取同一互斥锁的任务的优先级。这意味着互斥锁必须总是要返还的,否则高优先级的任务将永远也不能获取互斥锁,而低优先级的任务将不会放弃优先级的继承。xSemaphoreTake()页中提供了互斥锁用于互斥的范例。二元信号量并不需要在得到后立即释放,因此任务同步可以通过一个任务/中断持续释放信号量而另外一个持续获得信号量来实现。xSemaphoreGiveFromISR()页中有此种方式的实现范例。互斥锁与二元信号量均赋值为 xSemaphoreHandle 类型,并且可以在

46、任何此类型参数的 API函数中使用。Return:已创建的信号量句柄,需要为 xSemaphoreHandle 类型.28.xSemaphoreCreateRecursiveMutex信号量semphr.hxSemaphoreHandle xSemaphoreCreateRecursiveMutex(void)使用已存在的队列结构来创建递归互斥锁的宏。通过此宏创建的互斥锁可以使用xSemaphoreTakeRecursive()与 xSemaphoreGiveRecursive()宏 来访问。不能使用xSemaphoreTake()与 xSemaphoreGive()宏。一个递归的互斥锁可以重

47、复地被其所有者“获取”。在其所有者为每次的成功“获取”请求调用 xSemaphoreGiveRecursive()前,此互斥锁不会再次可用。例如,如果一个任务成功“获取”同一个互斥锁 5 次,则在其“释放”互斥锁恰好为 5 次后,其他任务才可以使用此互斥锁。这种类型的信号量使用一个优先级继承机制,因此已取得信号量的任务“必须总是”在不再需要信号量时立刻“释放”。互斥类型的信号量不能在中断服务程序中使用。可以参考 vSemaphoreCreateBinary()来获得一个二选一运行的实现方式,可以在中断服务程序中实现纯粹的同步(一个任务或中断总是“释放”信号量,而另一个总是“获取”信号量)。返回

48、:已创建的互斥锁信号量句柄,需要为 xSemaphoreHandle 类型.29.xSemaphoreTake信号量semphr.hxSemaphoreTake(xSemaphoreHandle xSemaphore,portTickType xBlockTime)用于获取信号量的宏。信号量必须已经通过调用 vSemaphoreCreateBinary(),xSemaphoreCreateMutex()或 xSemaphoreCreateCounting()来创建。这个宏不能在服务中断程序中调用。如果有必要,可以调用 xQueueReceiveFromISR()来在中断服务程序中获取信号量,虽

49、然这并不是一种正规的操作。xSemaphoreTake()是一个全功能任务间通讯 API,xSemaphoreAltTake()是其等价的替代 API。这两个版本均需要同样的参数并返回同样的值。Parameters:xSemaphore 将被获得的信号量句柄,此信号量必须已经被创建xBlockTime等待信号量可用的时钟滴答次数,可以使用 portTICK_RATE_MS 宏来转换为实际的时间。当为 0 时可以用于 对信号量进行轮询(poll the semaphore)如果 INCLUDE_vTaskSuspend 置位“1”,则指定 xBlockTime为 portMAX_DELAY 会导

50、致任务阻塞时间不确定(不会超时)返回:如果成功获取信号量则返回 pdTRUE,如果 xBlockTime 超时而信号量还未可用则返回 pdFALSE。30.xSemaphoreTakeRecursive信号量semphr.hxSemaphoreTakeRecursive(xSemaphoreHandle xMutex,portTickType xBlockTime)用于递归获得互斥锁信号量的宏。此互斥锁必须已经通过调用xSemaphoreCreateRecursiveMutex()来创建。FreeRTOSConfig.h 中的configUSE_RECURSIVE_MUTEXES 必须设置为

展开阅读全文
相关资源
相关搜索

当前位置:首页 > 技术资料 > 技术方案

本站为文档C TO C交易模式,本站只提供存储空间、用户上传的文档直接被用户下载,本站只是中间服务平台,本站所有文档下载所得的收益归上传人(含作者)所有。本站仅对用户上传内容的表现方式做保护处理,对上载内容本身不做任何修改或编辑。若文档所含内容侵犯了您的版权或隐私,请立即通知得利文库网,我们立即给予删除!客服QQ:136780468 微信:18945177775 电话:18904686070

工信部备案号:黑ICP备15003705号-8 |  经营许可证:黑B2-20190332号 |   黑公网安备:91230400333293403D

© 2020-2023 www.deliwenku.com 得利文库. All Rights Reserved 黑龙江转换宝科技有限公司 

黑龙江省互联网违法和不良信息举报
举报电话:0468-3380021 邮箱:hgswwxb@163.com