freertos官网 怎样调用adc

FreeRTOS的使用总结_百度文库
两大类热门资源免费畅读
续费一年阅读会员,立省24元!
FreeRTOS的使用总结
上传于||暂无简介
阅读已结束,如果下载本文需要使用1下载券
想免费下载本文?
定制HR最喜欢的简历
下载文档到电脑,查找使用更方便
还剩8页未读,继续阅读
定制HR最喜欢的简历
你可能喜欢403 Forbidden
403 ForbiddenFreeRTOS 使用指南 - jlicon - 博客园
转自[/article/7845]
作为一个轻量级的操作系统,FreeRTOS 提供的功能包括:任务管理、时间管理、信号量、消息队列、内存管理、记录功能等,可基本满足较小系统的需要。FreeRTOS 内核支持优先级调度算法,每个任务可根据重要程度的不同被赋予一定的优先级,CPU 总是让处于就绪态的、优先级最高的任务先运行。FreeRT0S 内核同时支持轮换调度算法,系统允许不同的任务使用相同的优先级,在没有更高优先级任务就绪的情况下,同一优先级的任务共享CPU 的使用时间。
FreeRTOS 的内核可根据用户需要设置为可剥夺型内核或不可剥夺型内核。当FreeRTOS 被设置为可剥夺型内核时,处于就绪态的高优先级任务能剥夺低优先级任务的CPU 使用权,这样可保证系统满足实时性的要求;当FreeRTOS 被设置为不可剥夺型内核时,处于就绪态的高优先级任务只有等当前运行任务主动释放CPU 的使用权后才能获得运行,这样可提高CPU 的运行效率FreeRTOS 对系统任务的数量没有限制。
一 变量类型定义#define portCHAR char#define portFLOAT float#define portDOUBLE double#define portLONG long#define portSHORT short#define portSTACK_TYPE unsigned portLONG#define portBASE_TYPE longGenerated by Foxit PDF Creator & Foxit Software&For evaluation only.
二 任务函数? 任务创建头文件:task.hportBASE_TYPE xTaskCreate (pdTASK_CODE pvTaskCode, 指向任务的实现函数的指针。效果上仅仅是函数名const portCHAR * const pcNane, 具有描述性的任务名。FreeRTOS 不会使用它。unsigned portSHORT usStackDepth, 指定任务堆栈的大小void *pvParameters, 指针用于作为一个参数传向创建的任务unsigned portBASE_TYPE uxPriority, 任务运行时的优先级xTaskHandle *pvCreatedTask 用于传递任务的句柄,可以引用从而对任务进行其他操作。)
说明:1. 这里的任务是指一个永远不会退出的C 函数,通常是一个死循环。2. pcNane 其只是单纯地用于辅助调试。应用程序可以通过定义常量config_MAX_TASK_NAME_LEN 来定义任务名的最大长度&&包括&\0&结束符。如果传入的字符串长度超过了这个最大值,字符串将会自动被截断3. usStackDepth 这个值指定的是栈空间可以保存多少个字(word),而不是多少个字节(byte)。栈空间大小为usStackDepth*4(bytes)。4. uxPriority 优先级的取值范围可以从最低优先级0 到最高优先级(configMAX_PRIORITIES&1)。
返回:1. pdPASS 表明任务创建成功,准备运行。2. errCOULD_NOT_ALLOCATE_REQUIRED_MEMORY 由于内存堆空间不足,FreeRTOS 无法分配足够的空间来保存任务结构数据和任务栈,因此无法创建任务。
? 任务删除头文件:task.hvoid vTaskDelete (xTaskHandle pxTask 处理要删除的任务。传递NULL 将删除自己)
说明:1. FreeRTOSConfig.h 中的INCLUDE_vTaskDelete=1,这个函数才能用。从RTOS 实时内核管理中移除任务。要删除的任务将从就绪,封锁,挂起,事件列表中移除。2. 任务被删除后就不复存在,也不会再进入运行态3. 空闲任务负责释放内核分配给已删除任务的内存。
使用提示:只有内核为任务分配的内存空间才会在任务被删除后由空闲任务自动回收。任务自己占用的内存或资源需要由应用程序自己显式地释放Generated by Foxit PDF Creator & Foxit Software&For evaluation only.
? 任务延时头文件:task.hvoid vTaskDelay (portTickType xTicksToDelay 时间数量,调用任务应该锁住的时间片周期)
说明:1. FreeRTOSConfig.h 中的INCLUDE_vTaskDelay=1,这个函数才能用。2. 延时任务为已知时间片,任务被锁住剩余的实际时间由时间片速率决定。portTICK_RATE_MS 常量以时间片速率来计算实际时间3. vTaskDelay()指定一个任务希望的时间段,这个时间之后任务解锁。4. vTaskDelay()不提供一个控制周期性任务频率的好方法,和其他任务和中断一样,在调用vTaskDelay()
后将影响频率提示:vTaskDelayUntil() ,这个交替的API 函数设计了执行固定的频率。它是指定的一个绝对时间(而不是一个相对时间)后,调用任务解锁。--------可以实现周期性任务执行。
? 任务延迟到指定时间头文件:task.hvoid vTaskDelayUntil (portTickType *pxPreviousWakeTime, 指定一个变量来掌握任务最后开启的时间, 第一次使用时必须使用当前时间来初始化, 在vTaskDelayUntil 中,这个变量是自动修改的portTickType xTimeIncrement 循环周期时间)
说明:1. FreeRTOSConfig.h 中的INCLUDE_vTaskDelayUntil=1,这个函数才能用。2. 延时一个任务到指定时间,这个和vTaskDelay() 不同, vTaskDelay 是延时一个相对时间,而vTaskDelayUntil 是延时一个绝对时间3. 常量 portTICK_RATE_MS 用来计算时间片频率的实时时间- 按照一个时间片周期4. 任务将在一定时间开启(*pxPreviousWakeTime + xTimeIncrement)。使用相同的xTimeIncrement 参数值来调用vTaskDelayUntil()将使任务按固定的周期执行。
注意:vTaskDelayUntil() 如果指定的苏醒时间使用完,将立即返回。因此,一个使用vTaskDelayUntil() 来周期性的执行的任务,如果执行周期因为任何原因(例如任务是临时为悬挂状态)暂停而导致任务错过一个或多个执行周期,那么需要重新计算苏醒时间。通过检查像pxPreviousWakeTime 可变的参数来组织当前时间片计数。然而在大多数使用中并不是必须的。
使用提示:如果一个任务想按固定的频率运行,如让一个LED 灯,按1KHz 频率运行,如果只有一个任务那么调用vTaskDelay 或vTaskDelayUntil 都能完成,但是如果有多个任务,vTaskDelay 就不行了,因为优先级或其它问题,它不知道什么时候再能运行,因此其不是周期执行,也就谈不上固定频率了,这时就要用vTaskDelayUntil 这个函数了
? 获得任务优先级头文件:task.hunsigned portBASE_TYPE uxTaskPriorityGet (xTaskHandle pxTask 需要处理的任务. 当传递NULL 时,将返回调用该任务的优先级)说明:FreeRTOSConfig.h 中的INCLUDE_vTaskPriorityGet=1,这个函数才能用返回:pxTask 的优先级
? 设置任务优先级头文件:task.hvoid vTaskPrioritySet (xTaskHandle pxTask , 需要设置优先级的任务。当传递NULL,将设置调用任务的优先级unsigned portBASE_TYPE uxNewPriority 任务需要设置的优先级)说明:FreeRTOSConfig.h 中的INCLUDE_vTaskPrioritySet 为1,才能使用此函数.如果设置的优先级高于当前执行任务的优先级,则上下文切换将在此函数返回前发生
? 挂起任务头文件:task.hvoid vTaskSuspend (xTaskHandle pxTaskToSuspend 处理需要挂起的任务。传递NULL 将挂起调用此函数的任务)说明:FreeRTOSConfig.h 中的INCLUDE_vTaskSuspend 为1,才能使用此函数。当挂起一个任务时,不管优先级是多少,不需要占用任何微控制器处理器时间。调用vTaskSuspend 不会累积&&即:在同一任务中调用vTaskSuspend 两次,但只需要调用一次vTaskResume()就能使挂起的任务就绪
? 唤醒挂起的任务头文件:task.hvoid vTaskResume (xTaskHandle pxTaskToResume 就绪任务的句柄)说明:FreeRTOSConfig.h 中的INCLUDE_vTaskSuspend 为1,才能使用此函数。必须是调用 vTaskSuspend() 后挂起的任务,才有可能通过调用 vTaskResume ()从新运行
? 从中断唤醒挂起的任务头文件:task.hportBase_TYPE vTaskResumeFromISR (xTaskHandle pxTaskToResum 就绪任务的句柄)说明:FreeRTOSConfig.h 中的INCLUDE_vTaskSuspendhe 和INCLUDE_xTaskResumeFromISR 都为1,才能使用此函数。vTaskResumeFromISR()不应该用于任务和中断同步,因为可能会在中断发生期间,任务已经挂起&&这样导致错过中断。使用信号量最为同步机制将避免这种偶然性。返回:pdTRUE: 如果唤醒了任务将引起上下文切换。pdFALSE:用于ISR 确定是否上下文切换
? 为任务分配标签值头文件:task.hvoid vTaskSetApplicationTaskTag (xTaskHandle xTask , 将分配给标签值的任务。传递NULL 将分配标签给调用的任务。pdTASK_HOOK_CODE pxTagValue 分配给任务的标签值 类型为 pdTASK_HOOK_CODE 允许一个函数指针赋值给标签,因此实际上任何值都可以分配)说明:FreeRTOSConfig.h 中的onfigUSE_APPLICATION_TASK_TAG 为1,这个函数才能可用。这个值仅在应用程序中使用,内核本身不使用它。? xTaskCallApplicationTaskHook
三:内核函数? 启动实时内核处理头文件:task.hvoid vTaskStartScheduler ( void );说明:当 vTaskStartScheduler() 被调用时,空闲任务自动创建。如果 vTaskStartScheduler() 成功调用,这个函数不返回,直到执行任务调用vTaskEndScheduler()。如果可供给空闲任务的RAM 不足,那么函数调用失败,并立即返回。
? 停止实时内核运行头文件:task.hvoid vTaskEndScheduler ( void );说明:所有创建的任务将自动删除,并且多任务(优先级或合作式)将停止。当vTaskStartScheduler()调用时,执行将再次开始,像vTaskStartScheduler()仅仅返回。注意:vPortEndScheduler ()导致所有由内核分配的资源释放&&但是不会释放由应用程序的任务分配的资源。
? 挂起所有活动的实时内核,同时允许中断(包括内核滴答)头文件:task.hvoid vTaskSuspendAll ( void );说明:任务在调用vTaskSuspendAll ()后,这个任务将继续执行,不会有任何被切换的危险,直到调用xTaskResumeAll ()函数重启内核。注意:API 中有可能影响影响上下文切换的函数(例如,vTaskDelayUntil(), xQueueSend()等等),一定不能在调度器挂起时被调用。
四:队列管理队列是内部通信的主要形式。它可以用于在任务和任务之间以及任务和中断之间发送消息。在大多数情况下使用线程安全 FIFO(先进先出)缓存,新数据放在队列的最后,虽然数据也可以放在前面。
队列可以包含固定大小的 '项目' - 每个项目的大小和队列可以保存项目的最大数量在创建队列时就已经定义了。
项目以复制而不是引用的方式放入队列,因此最好使放入队列项目的大小成为最小。以复制的方式放入队列可以使你的系统设计极大的简化,因为两个任务不会同时访问数据。队列帮助你管理所有的互斥问题。
如果你希望在队列中使用大的项目,可能最好用插入队列指针 - 但是这样做必须注意要确保你的系统明确定义任务和/或中断是数据的"所以者"。
队列 API 函数可以指定阻塞的时间。阻塞时间代表任务进入阻塞状态或者等待队列中数据时(当任务读取队列但是队列是空的时候)的最大'节拍'数,或者等待队列空间变为可以使用(当任务需要写数据到队列,但是队列已满时)。当一个以上任务在同一个队列中被阻塞时,高优先级的任务先解除阻塞。
? 创建一个新的队列头文件:queue. HxQueueHandle xQueueCreate (unsigned portBASE_TYPE uxQueueLength, 队列中包含最大项目数量unsigned portBASE_TYPE uxItemSize 队列中每个项目所需的字节数);说明:创建一个新的队列。为新的队列分配所需的存储内存,并返回一个队列处理。注意:项目通过复制而不是引用排队,因此,所需的字节数,将复制给每个项目。队列中每个项目必须分配同样大小。返回:如果队列成功创建,则返回一个新建队列的处理。如果不能创建队列,将返回0。
? 传递一个项目到队列头文件:queue. HportBASE_TYPE xQueueSend (xQueueHandle xQueue, 将项目传进的队列const void * pvItemToQueue, 项目的指针【源数据】portTickType xTicksToWait 等待的最大时间量【时间使用滴答周期】);说明:传递一个项目到队列。这个项目通过复制而不是通过引用排队。这个函数不能从中断服务程序调用。注意:当队列满时,肯定传递不成功,则等待xTicksToWait 个滴答周期后再传递,但如果xTicksToWait 设置为0,调用将立即返回。返回:pdTRUE:项目成功传递。否则为:errQUEUE_FULL.
? 传递项目到一个队列中的后面头文件:queue. HportBASE_TYPE xQueueSendToBack (xQueueHandle xQueue, 将项目传进的队列const void * pvItemToQueue, 项目的指针【源数据】portTickType xTicksToWait 等待的最大时间量);说明:这个与xQueueSend 是一样的,参照xQueueSend 的用法
? 从队列接收一个项目头文件:queue. HportBASE_TYPE xQueueReceive (xQueueHandle xQueue, 发送项目的队列句柄void *pvBuffer, 指向缓冲区的指针,将接收的项目被复制进去portTickType xTicksToWait 任务中断并等待队列中可用空间的最大时间);说明:这个项目通过复制接收,因此缓冲器必须提供足够大的空间。这个函数一定不能在中断服务程序中使用当队列空时,肯定复制传递不成功,则等待xTicksToWait 个滴答周期后再复制,但如果xTicksToWait 设置为0,调用将立即返回。返回:如果项目成功被队列接收为pdTRUE ,否则为 pdFALSE。
? 从中断传递一个项目到队列的后面头文件:queue. HportBASE_TYPE xQueueSendFromISR (xQueueHandle pxQueue, 将项目传进的队列const void *pvItemToQueue, 项目的指针【源数据】portBASE_TYPE *pxHigherPriorityTaskWoken 因空间数据问题被挂起的任务是否解锁);说明: 如果传进队列而导致因空间数据问题被挂起的任务解锁,并且解锁的任务的优先级高于当前运行任务,xQueueSendFromISR 将设置 *pxHigherPriorityTaskWoken 到 pdTRUE。当pxHigherPriorityTaskWoken被设置为pdTRUE 时,则在中断退出之前将请求任务切换。返回:pdTRUE:数据成功传递进队列。否则为:errQUEUE_FULL。
? 从中断传递项目到一个队列中的后面头文件:queue. HportBASE_TYPE xQueueSendToBackFromISR (xQueueHandle pxQueue,const void *pvItemToQueue,portBASE_TYPE *pxHigherPriorityTaskWoken);说明:参照xQueueSendFromISR
? 从中断传递一个项到队列的前面头文件:queue. HportBASE_TYPE xQueueSendToFrontFromISR (xQueueHandle pxQueue,const void *pvItemToQueue,portBASE_TYPE *pxHigherPriorityTaskWoken);说明:参照xQueueSendFromISR
? 中断时从队列接收一个项目头文件:queue. HportBASE_TYPE xQueueReceiveFromISR (xQueueHandle pxQueue, 发送项目的队列句柄void *pvBuffer, 指向缓冲区的指针,将接收的项目被复制进去portBASE_TYPE *pxTaskWoken 任务将锁住,等待队列中的可用空间);说明: 如果xQueueReceiveFromISR 引起一个任务解锁,*pxTaskWoken 将设置为pdTRUE,否则*pxTaskWoken保留不变返回:pdTRUE :如果项目成功从队列接收。否则为: pdFALSE
? 为队列命名,并加入队列到登记管理中头文件:queue.hvoid vQueueAddToRegistry (xQueueHandle xQueue, 将要添加登记的队列句柄signed portCHAR *pcQueueName, 为指定的队列命名。 仅仅是文本串,方便调试。);说明:队列登记有两个特点, 均与内核的相关调试有关:允许文本式名字,使队列在调试GUI 中方便定义。包含调试器需要的信息,如:定位每个已经登记的队列和信号量。队列的登记没有目的,除非使用内核相关的调试。configQUEUE_REGISTRY_SIZE 定义了队列和信号量的最大数目.仅当使用内核相关的调试时需要显示已经登记的信号量和队列。
? 从登记管理中移除队列头文件:queue.hvoid vQueueUnregisterQueue (xQueueHandle xQueue, 从登记管理处中移出的队列句柄);说明:队列登记有两个特点, 均与内核的相关调试有关:允许文本式名字,使队列在调试GUI 中方便定义。包含调试器需要的信息,如:定位每个已经登记的队列和信号量。队列的登记没有目的,除非使用内核相关的调试。configQUEUE_REGISTRY_SIZE 定义了队列和信号量的最大数目.仅当使用内核相关的调试时需要显示已经登记的信号量和队列。
五:信号量? 使用已存在的队列结构来创建计数型信号量头文件:semphr. HxSemaphoreHandle xSemaphoreCreateCounting (unsigned portBASE_TYPE uxMaxCount, 可以达到的最大计数值。unsigned portBASE_TYPE uxInitialCount 信号量创建时分配的初始值)说明:两种典型应用事件计数在这种应用的情形下,事件处理程序会在每次事件发生时发送信号量(增加信号量计数值),而任务处理程序会在每次处理事件时请求信号量(减少信号量计数值)。因此计数值为事件发生与事件处理两者间的差值,在这种情况下计数值初始化为0 是合适的。
资源管理在这种应用情形下,计数值指示出可用的资源数量。任务必须首先&请求&信号量来获得资源的控制权--减少信号量计数值。当计数值降为0 时表示没有空闲资源。任务使用完资源后&返还&信号量--增加信号量计数值。在这种情况下计数值初始化为与最大的计数值相一致是合适的,这指示出所有的空闲资源。
返回:已创建的信号量句柄,为xSemaphoreHandle 类型,如果信号量无法创建则为NULL。
? 使用已存在的队列结构来创建互斥锁信号量的宏头文件:semphr. HxSemaphoreHandle xSemaphoreCreateMutex ( void )
说明: 通过此宏创建的互斥锁可以使用xSemaphoreTake() 与 xSemaphoreGive() 宏来访问。不能使用xSemaphoreTakeRecursive()与 xSemaphoreGiveRecursive()宏
二元信号量与互斥锁十分相像,不过两者间有细微的差别:互斥锁包含一个优先级继承机制,而信号量没有。这种差别使得二元信号量更适合于实现同步(任务之间或任务与中断之间),互斥锁更适合于实现简单的互斥。
当有另外一个具有更高优先级的任务试图获取同一个互斥锁时,已经获得互斥锁的任务的优先级会被提升。已经获得互斥锁的任务将继承试图获取同一互斥锁的任务的优先级。这意味着互斥锁必须总是要返还的,否则高优先级的任务将永远也不能获取互斥锁,而低优先级的任务将不会放弃优先级的继承。
二元信号量并不需要在得到后立即释放,因此任务同步可以通过一个任务/中断持续释放信号量而另外一个持续获得信号量来实现。
互斥锁与二元信号量均赋值为xSemaphoreHandle 类型,并且可以在任何此类型参数的API 函数中使用。
返回: 已创建的信号量句柄,需要为xSemaphoreHandle 类型。
? 使用已存在的队列结构来创建递归互斥锁的宏头文件:semphr. HxSemaphoreHandle xSemaphoreCreateRecursiveMutex ( void )
说明:通过此宏创建的互斥锁可以使用xSemaphoreTakeRecursive()与 xSemaphoreGiveRecursive()宏 来访问。
不能使用xSemaphoreTake()与 xSemaphoreGive()宏
一个递归的互斥锁可以重复地被其所有者&获取&。在其所有者为每次的成功&获取&请求调用xSemaphoreGiveRecursive()前,此互斥锁不会再次可用。例如,如果一个任务成功&获取&同一个互斥锁5 次,则在其&释放&互斥锁恰好为5 次后,其他任务才可以使用此互斥锁。
这种类型的信号量使用一个优先级继承机制,因此已取得信号量的任务&必须总是&在不再需要信号量时立刻&释放&。
互斥类型的信号量不能在中断服务程序中使用。
可以参考vSemaphoreCreateBinary()来获得一个二选一运行的实现方式,可以在中断服务程序中实现纯粹的同步(一个任务或中断总是&释放&信号量,而另一个总是&获取&信号量)。
返回: 已创建的信号量句柄,需要为xSemaphoreHandle 类型。
? 获取信号量的宏 头文件:semphr. HxSemaphoreTake (xSemaphoreHandle xSemaphore, 将被获得的信号量句柄,此信号量必须已经被创建portTickType xBlockTime 等待信号量可用的时钟滴答次数)
说明:当信号量不可用时,则等待xBlockTime 个时钟滴答,再看是否可用,当是为0 时如果不可用,则立即退出,因此为0 时可以达到对信号量轮询的作用。
返回:如果成功获取信号量则返回pdTRUE,如果xBlockTime 超时而信号量还未可用则返回pdFALSE。
? 递归获得互斥锁信号量的宏头文件:semphr. HxSemaphoreTakeRecursive (xSemaphoreHandle xMutex, 将被获得的互斥锁句柄portTickType xBlockTime 等待信号量可用的时钟滴答次数)
说明:FreeRTOSConfig.h 中的configUSE_RECURSIVE_MUTEXES 必须设置为1 才可以使用此宏。一个递归型的互斥锁可以被其所有者重复地&获取&, 在其所有者为每次成功的&获取&请求调用xSemaphoreGiveRecursive()前,此互斥锁不会再次可用。
返回:如果成功获取信号量则返回pdTRUE,如果xBlockTime 超时而信号量还未可用则返回pdFALSE。
? 释放信号量的宏头文件:semphr. HxSemaphoreGive (xSemaphoreHandle xSemaphore 即将释放的信号量的句柄,在信号量创建是返回)
返回:如果信号量成功释放返回pdTRUE,如果发生错误则返回pdFALSE。信号量使用的是队列,因此如果队列没有位置用于发送消息就会发生一个错误&&说明开始时没有正确获取信号量。
? 用于递归释放,或&返还&,互斥锁信号量的宏头文件:semphr. HxSemaphoreGiveRecursive (xSemaphoreHandle xMutex 将被释放或&返还&的互斥锁的句柄)
返回:如果信号量成功释放则为pdTRUE
? 从中断释放一个信号量的宏头文件:semphr. HxSemaphoreGiveFromISR (xSemaphoreHandle xSemaphore, 将被释放的信号量的句柄portBASE_TYPE *pxHigherPriorityTaskWoken 因空间数据问题被挂起的任务是否解锁)
返回:如果信号量成功释放则返回pdTRUE,否则返回errQUEUE_FULL
六:联合函数
一个联合程序可以以下面的状态中的一种存在:
运行:当一个联合程序正在执行时它就是处于运行状态,它就占用了处理器。
就绪:就绪状态的联合程序是那些可以执行(没有被阻塞)但是还没有被执行的程序。一个联合程序可能处于就绪状态是因为另外一个相同或高优先级的联合程序正处于运行状态,或一个任务处于运行状态&&这只会在系统同时使用了任务和联合程序时发生。
阻塞:如果一个联合程序正处于暂时等待或等待外部事件,它就是处于阻塞状态。例如,联合程序调用 crDELAY()它就会被阻塞(放入到阻塞状态)直到达到延时时间 - 一个临时事件。被阻塞的联合程序不会被调度。
有效的联合程序状态转换
联合程序属性:
每个联合程序被分配一个从 0 到 ( configMAX_CO_ROUTINE_PRIORITIES - 1 ) 的优先级。
configMAX_CO_ROUTINE_PRIORITIES 在 FreeRTOSConfig.h 中定义并在基本系统中设置。
configMAX_CO_ROUTINE_PRIORITIES 的数值越大 FreeRTOS 消耗的 RAM 越多。
低优先级联合程序使用小数值。
联合程序优先级只针对其他联合程序,任务的优先级总是高于联合程序
? 创建一个新的联合程序并且将其增加到联合程序的就绪列表中头文件:croutine.hportBASE_TYPE xCoRoutineCreate (crCOROUTINE_CODE pxCoRoutineCode, 联合程序函数的指针unsigned portBASE_TYPE uxPriority, 优先级unsigned portBASE_TYPE uxIndex 当不同的联合程序使用同一个函数来运行时用于相互识别);
返回:如果联合程序成功创建并增加到就绪列表中则返回pdPASS,否则返回ProjDefs.h 中定义的错误代码
? 把一个联合程序延时一个特定的时间头文件:croutine.hvoid crDELAY (xCoRoutineHandle xHandle, 要延时的联合程序的句柄portTickType xTicksToDelay 联合程序要延时的时间片数)
? 联合程序向其他联合程序发送数据头文件:croutine.hcrQUEUE_SEND (xCoRoutineHandle xHandle, 调用的联合程序的句柄xQueueHandle pxQueue, 数据将被发送到的队列的句柄void *pvItemToQueue, 将被发送到队列的数据的指针portTickType xTicksToWait, 如果此刻队列没有可用空间,此值为联合程序用于阻塞等待队列空间可用的时间片数。portBASE_TYPE *pxResult 一个指向pxResult 变量的指针,如果数据成功发送到队列就会被设置为pdPASS,否则设置为 ProjDefs.h 中定义的错误码。)
? 联合程序接受其他联合程序发送的数据头文件:croutine.hvoid crQUEUE_RECEIVE(xCoRoutineHandle xHandle,xQueueHandle pxQueue,void *pvBuffer,portTickType xTicksToWait,portBASE_TYPE *pxResult)
说明:同上
? 中断处理程序向联合程序发送数据头文件:croutine.hportBASE_TYPE crQUEUE_SEND_FROM_ISR(xQueueHandle pxQueue, 将发送到的队列的句柄void *pvItemToQueue, 将被发送到队列的条目的指针portBASE_TYPE xCoRoutinePreviouslyWoken)
? 联合程序向中断处理程序发送数据头文件:croutine.hportBASE_TYPE crQUEUE_SEND_FROM_ISR(xQueueHandle pxQueue,void *pvBuffer,portBASE_TYPE * pxCoRoutineWoken)
? 运行一个联合程序头文件:croutine.hvoid vCoRoutineSchedule ( void );
说明:vCoRoutineSchedule() 与性具有最高优先级的就绪联合程序。此联合程序将运行,直到其阻塞,让出系统或被任务抢占。联合程序是合作式运行的,所以一个联合程序不会被另一个联合程序抢占,但是可以被任务抢占。
如果一个应用程序同时包含任务与联合程序,则vCoRoutineSchedule 应该在空闲任务中调用(在一个空闲任务钩子中)FreeRTOS系列第12篇---FreeRTOS任务应用函数
& & & 任务应用函数是一组辅助类函数,一般用于调试信息输出、获取任务句柄、获取任务状态、操作任务标签值等等。
1.获取任务系统状态
1.1函数描述
UBaseType_t uxTaskGetSystemState(
TaskStatus_t * constpxTaskStatusArray,
const UBaseType_tuxArraySize,
unsigned long * constpulTotalRunTime );
& & & 该函数向TaskStatus_t结构体填充相关信息,系统中每一个任务的信息都可以填充到TaskStatus_t结构体数组中,数组大小由uxArraySize指定。结构体TaskStatus_t定义如下:
typedef struct xTASK_STATUS
/* 任务句柄*/
TaskHandle_t xH
/* 指针,指向任务名*/
const signed char *pcTaskN
/*任务ID,是一个独一无二的数字*/
UBaseType_t xTaskN
/*填充结构体时,任务当前的状态(运行、就绪、挂起等等)*/
eTaskState eCurrentS
/*填充结构体时,任务运行(或继承)的优先级。*/
UBaseType_t uxCurrentP
/* 当任务因继承而改变优先级时,该变量保存任务最初的优先级。仅当configUSE_MUTEXES定义为1有效。*/
UBaseType_t uxBaseP
/* 分配给任务的总运行时间。仅当宏configGENERATE_RUN_TIME_STATS为1时有效。*/
unsigned long ulRunTimeC
/* 从任务创建起,堆栈剩余的最小数量,这个值越接近0,堆栈溢出的可能越大。 */
unsigned short usStackHighWaterM
}TaskStatus_t;
& & & 注意,这个函数仅用来调试用,调用此函数会挂起所有任务,直到函数最后才恢复挂起的任务,因此任务可能被挂起很长时间。在文件FreeRTOSConfig.h中,宏configUSE_TRACE_FACILITY必须设置为1,此函数才有效。
1.2参数描述
pxTaskStatusArray:指向TaskStatus_t类型的结构体数组。这个数组至少要包含1个元素。RTOS控制的任务数量可以使用API函数uxTaskGetNumberOfTasks()获取。
uxArraySize:参数pxTaskStatusArray指向的数组大小,也就是该数组的索引数目。
pulTotalRunTime:如果在文件FreeRTOSConfig.h中设置宏configGENERATE_RUN_TIME_STATS为1,则该函数将总运行时间写入*pulTotalRunTime中。pulTotalRunTime可以设置为NULL,表示忽略总运行时间。
&&&&&&&& 被填充的TaskStatus_t结构体数量。这个值应该等于通过调用API函数uxTaskGetNumberOfTasks()返回的值,但如果传递给uxArraySize参数的值太小,则返回0。
1.4用法举例
/*本例演示如是使用uxTaskGetSystemState()函数来获取运行时间信息,并将其转化为程序员更易识别的字符格式,这些转化后的字符保存到pcWriteBuffer中。*/
void vTaskGetRunTimeStats(signed char *pcWriteBuffer )
TaskStatus_t*pxTaskStatusA
volatileUBaseType_t uxArraySize,
unsignedlong ulTotalRunTime, ulStatsAsP
/* 防御性代码,确保字符串有合理的结束*/
*pcWriteBuffer = 0x00;
/* 获取任务总数目*/
uxArraySize = uxTaskGetNumberOfTasks ();
/*为每个任务的TaskStatus_t结构体分配内存,也可以静态的分配一个足够大的数组 */
pxTaskStatusArray = pvPortMalloc( uxArraySize * sizeof( TaskStatus_t ));
if(pxTaskStatusArray != NULL )
/*获取每个任务的状态信息 */
uxArraySize = uxTaskGetSystemState( pxTaskStatusArray, uxArraySize,&ulTotalRunTime );
/* 百分比计算 */
ulTotalRunTime /= 100UL;
/* 避免除零错误 */
if(ulTotalRunTime & 0 )
/* 将获得的每一个任务状态信息部分的转化为程序员容易识别的字符串格式*/
for( x = 0; x & uxArrayS x++ )
/* 计算任务运行时间与总运行时间的百分比。*/
ulStatsAsPercentage = pxTaskStatusArray[ x ].ulRunTimeCounter /ulTotalRunT
if( ulStatsAsPercentage & 0UL )
sprintf( pcWriteBuffer, &%s\t\t%lu\t\t%lu%%\r\n&,
pxTaskStatusArray[ x ].pcTaskName,
pxTaskStatusArray[ x ].ulRunTimeCounter,
ulStatsAsPercentage );
/* 任务运行时间不足总运行时间的1%*/
sprintf( pcWriteBuffer, &%s\t\t%lu\t\t&1%%\r\n&,
pxTaskStatusArray[ x ].pcTaskName,
pxTaskStatusArray[x ].ulRunTimeCounter );
pcWriteBuffer += strlen( ( char * ) pcWriteBuffer );
/* 释放之前申请的内存*/
vPortFree( pxTaskStatusArray );
2.获取当前任务句柄
2.1函数描述
& & & TaskHandle_t xTaskGetCurrentTaskHandle(void );
& & & 在文件FreeRTOSConfig.h中,宏INCLUDE_xTaskGetCurrentTaskHandle必须设置为1,此函数才有效。
& & & 返回当前任务(调用该函数的任务)的句柄。
3.获取空闲任务句柄
3.1函数描述
& & & TaskHandle_t xTaskGetIdleTaskHandle(void );
& & & 在文件FreeRTOSConfig.h中,宏INCLUDE_xTaskGetIdleTaskHandle必须设置为1,此函数才有效。
& & & 返回空闲任务句柄。空闲任务在RTOS调度器启动时自动创建。
4.获取任务堆栈最大使用深度
4.1函数描述
& & & UBaseType_t uxTaskGetStackHighWaterMark( TaskHandle_t xTask );
& & & 任务的堆栈空间会随着任务执行以及中断处理而增长或缩小。该函数可以返回任务启动后的最小剩余堆栈空间。换句话说,可以间接估算出一个任务最多需要多少堆栈空间。在文件FreeRTOSConfig.h中,宏 必须设置成1,此函数才有效。
4.2参数描述
xTask:任务句柄。NULL表示查看当前任务的堆栈使用情况。
& & & 返回最小剩余堆栈空间,以字为单位。比如一个32为架构处理器,返回值为1表示有4字节堆栈空间没有使用过。如果返回值为0,则任务很可能已经发生了堆栈溢出。
4.4用法举例
void vTask1( void * pvParameters )
UBaseType_tuxHighWaterM
/* 入口处检测一次 */
uxHighWaterMark =uxTaskGetStackHighWaterMark( NULL );
/* 正常调用函数 */
vTaskDelay( 1000 );
/* 测量堆栈使用情况 */
uxHighWaterMark =uxTaskGetStackHighWaterMark( NULL );
5.获取任务状态
5.1函数描述
& & & eTaskState eTaskGetState( TaskHandle_txTask );
& & & 返回一个枚举类型的任务状态值。在文件FreeRTOSConfig.h中,宏INCLUDE_eTaskGetState必须设置为1,此函数才有效。
5.2参数描述
xTask:任务句柄
&&&&&&&& 下表列出返回值和对应的任务状态。
6.获取任务描述内容
6.1函数描述
& & & char * pcTaskGetTaskName( TaskHandle_txTaskToQuery );
& & & 获取任务的描述内容,在文件FreeRTOSConfig.h中,宏INCLUDE_pcTaskGetTaskName必须设置成1,此函数才有效。
6.2参数描述
xTaskToQuery:任务的句柄。NULL表示获取当前任务的描述内容指针。
& & & 一个指针,指向任务描述字符串。
7.获取系统节拍次数
7.1函数描述
& & & volatile TickType_t xTaskGetTickCount(void );
& & & 这个函数不能在ISR中调用。在ISR中用xTaskGetTickCountFromISR(),原型为volatileTickType_t xTaskGetTickCountFromISR( void )。
& & & 返回从vTaskStartScheduler函数调用后的系统时钟节拍次数。
8.获取调度器状态
8.1函数描述
& & & BaseType_t xTaskGetSchedulerState( void);
& & & 获取调度器当前状态。在文件FreeRTOSConfig.h中,宏INCLUDE_xTaskGetSchedulerState或configUSE_TIMERS必须定义为1,此函数才有效。
&&&&&&返回值是以下常量之一(定义在task.h):taskSCHEDULER_NOT_STARTED(未启动)、taskSCHEDULER_RUNNING(正常运行)、taskSCHEDULER_SUSPENDED(挂起)。
9.获取任务总数
9.1函数描述
& & & UBaseType_t (void );
&&&&&&获取RTOS内核当前管理的任务总数。包含所有就绪、阻塞和挂起状态的任务。对于一个删除的任务,如果它的堆栈空间还没有被空闲任务释放掉,则这个被删除的任务也含在计数值中。
&&&&&&返回RTOS内核当前管理的任务总数。
10.获取所有任务详情
10.1函数描述
& & & void vTaskList( char *pcWriteBuffer );
&&&&&&将每个任务的状态、堆栈使用情况等以字符的形式保存到参数pcWriteBuffer指向的区域。vTaskList()函数调用usTaskGetSystemState()函数,然后将得到的信息格式化为程序员易读的字符形式。输出的内容例子如下图所示,图中State一栏中,B表示阻塞、R表示就绪、D表示删除(等待清除内存)、S表示挂起或阻塞。
&&&&&&注意,调用这个函数会挂起所有任务,这一过程可能持续较长时间,因此本函数仅在调试时使用。在文件FreeRTOSConfig.h中,宏configUSE_TRACE_FACILITY和configUSE_STATS_FORMATTING_FUNCTIONS必须定义为1,此函数才有效。
10.2参数描述
pcWriteBuffer:任务的信息会写入这个缓冲区,为ASCII表单形式。这个缓冲区要足够大,以容纳生成的报告,每个任务大约需要40个字节。
11.获取任务运行时间
11.1函数描述
& & & void vTaskGetRunTimeStats( char*pcWriteBuffer );
& & & 这个函数用于统计每个任务的运行时间。要使用这个函数必须满足一些条件,那就是必须有一个用于时间统计的定时器或计数器,这个定时器或计数器的精度要至少大于10倍的系统节拍周期。这个定时器或计数器的配置以及获取定时时间是由两个宏定义实现的,这两个宏一般在文件FreeRTOSConfig.h中定义。配置定时器或计数器的宏为portCONFIGURE_TIMER_FOR_RUN_TIME_STATS(),获取定时时间的宏为portGET_RUN_TIME_COUNTER_VALUE。实现了这两个宏定义后,还必须在文件FreeRTOSConfig.h中将宏configGENERATE_RUN_TIME_STATS和configUSE_STATS_FORMATTING_FUNCTIONS设置为1,此API函数才有效。
&&&&&&这个API函数调用usTaskGetSystemState()函数获取每个任务的状态信息,并把其中的运行时间格式化为程序员易读的字符形式,并将这些信息保存到参数pcWriteBuffer指向的区域。
&&&&&&注意,调用这个函数会挂起所有任务,这一过程可能持续较长时间,因此本函数仅在调试时使用。
11.2参数描述
pcWriteBuffer:任务的运行时间信息会写入这个缓冲区,为ASCII表单形式。这个缓冲区要足够大,以容纳生成的报告,每个任务大约需要40个字节。
11.3用法举例
&&&&&&以lpc17xx系列为控制为例,我们使用定时器0来作为统计基准时钟。
11.3.1使能函数宏
&&&&&&在文件FreeRTOSConfig.h中,设置宏configGENERATE_RUN_TIME_STATS和configUSE_STATS_FORMATTING_FUNCTIONS为1,
11.3.2定时初始化定时器代码
void vConfigureTimerForRunTimeStats( void )
/* 使能定时器0的外设电源,配置外设时钟 */
PCONP |= 0x02UL;
PCLKSEL0 = (PCLKSEL0& (~(0x3&&2))) | (0x01 && 2);
/* 复位定时器 0 */
T0TCR = 0x02;
/* 作为计数器 */
T0CTCR = 0x00;
/* 预分频,设置合适的分辨率即可 */
( configCPU_CLOCK_HZ / 10000UL ) - 1UL;
/* 启动计数器 */
T0TCR = 0x01;
11.3.3定义配置定时器和获取定时时间宏
&&&&&&在文件FreeRTOSConfig.h中,定义下列代码:
extern void vConfigureTimerForRunTimeStats( void );
#define portCONFIGURE_TIMER_FOR_RUN_TIME_STATS() vConfigureTimerForRunTimeStats()
#defineportGET_RUN_TIME_COUNTER_VALUE() T0TC
12.设置任务标签值
12.1函数描述
voidvTaskSetApplicationTaskTag( TaskHandle_t xTask,
TaskHookFunction_tpxTagValue );
&&&&&&可以给每个任务分配一个标签值。这个值一般用于应用程序,RTOS内核不会使用。在文件FreeRTOSConfig.h中,宏configUSE_APPLICATION_TASK_TAG必须设置为1,此函数才有效。
12.2参数描述
xTask:任务句柄。NULL表示当前任务。
pxTagValue:要分配给任务的标签值。这是一个TaskHookFunction_t类型的函数指针,但也可以给任务标签分配任意的值。
&&&&&&注:TaskHookFunction_t原型定义:typedef BaseType_t (*TaskHookFunction_t)(void * )
12.3用法举例
/* 在这个例子中,给任务设置一个整形标签值。例子中使用了RTOS跟踪钩子宏。*/
void vATask( void *pvParameters )
/* 为自己的标签分配一个整形值 */
vTaskSetApplicationTaskTag( NULL, ( void * ) 1 );
/* 任务主体代码 */
/*****************************************************************************/
/*在这个任务中,给任务设置一个函数标签值。首先定义一个回调函数,这个函数必须声明为TaskHookFunction_t类型。 */
static BaseType_t prvExampleTaskHook( void * pvParameter )
/* 这里为用户定义代码 –可能是记录数据、更新任务状态值等。*/
/* 将回调函数设置为任务的标签值。 */
void vAnotherTask( void *pvParameters )
/* 注册回调函数*/
vTaskSetApplicationTaskTag( NULL, prvExampleTaskHook );
/* 任务主体代码 */
/* 每当任务切换时,会调用xTaskCallApplicationTaskHook 函数(见14.)。 */
#define traceTASK_SWITCHED_OUT() xTaskCallApplicationTaskHook(pxCurrentTCB,0 )
13.获取任务标签值
13.1函数描述
& & & TaskHookFunction_txTaskGetApplicationTaskTag( TaskHandle_t xTask );
& & & 返回分配给任务的标签值。程序员定义标签值,RTOS内核通常不会访问标签值。
& & & 函数仅对高级用户使用。在文件FreeRTOSConfig.h中,宏configUSE_APPLICATION_TASK_TAG必须设置为1,此函数才有效。
13.2参数描述
xTask:任务句柄。NULL表示当前任务。
13.3返回值
& & & 返回指定任务的标签值。
14.执行任务的应用钩子函数
14.1函数描述
BaseType_txTaskCallApplicationTaskHook(
TaskHandle_txTask,
void*pvParameter );
& & & 可以为每个任务分配一个标签值,当这个值是一个TaskHookFunction_t类型函数指针时,相当于应用程序向任务注册了一个回调函数,而API函数xTaskCallApplicationTaskHook用来调用这个回调函数。
& & & 一般这个函数配合RTOS跟踪钩子宏使用,见12.设置任务标签值一节的用法举例。
14.2参数描述
xTask:任务句柄。NULL表示当前任务。
pvParameter:作为参数传递给应用钩子函数
15.设置线程本地存储指针
15.1函数描述
void vTaskSetThreadLocalStoragePointer(TaskHandle_t xTaskToSet,
BaseType_t xIndex,
void*pvValue )
& & & 此函数仅用于高级用户。
& & & 线程本地存储允许应用程序在任务的控制块中存储一些值,每个任务都有自己独立的储存空间。
& & & 比如,许多库函数都包含一个叫做errno的全局变量。某些库函数使用errno返回库函数错误信息,应用程序检查这个全局变量来确定发生了那些错误。在单线程程序中,将errno定义成全局变量是可以的,但是在多线程应用中,每个线程(任务)必须具有自己独有的errno值,否则,一个任务可能会读取到另一个任务的errno值。
& & & FreeRTOS提供了一个灵活的机制,使得应用程序可以使用线程本地存储指针来读写线程本地存储。在文件FreeRTOSConfig.h中,宏configNUM_THREAD_LOCAL_STORAGE_POINTERS指定每个任务线程本地存储指针数组的大小。API函数vTaskSetThreadLocalStoragePointer()用于向指针数组中写入值,API函数pvTaskGetThreadLocalStoragePointer()用于从指针数组中读取值。
15.2参数描述
xTaskToSet:任务句柄。NULL表示当前任务。
xIndex:写入到线程本地存储数组的索引号,线程本笃存储数组的大小由宏configNUM_THREAD_LOCAL_STORAGE_POINTERS设定,该宏在文件FreeRTOSConfig.h中。
pvValue:写入到指定索引地址的数据值
15.3用法举例
&&&&&参见16.获取线程本地存储指针一节。
16.读取线程本地存储指针
16.1函数描述
void*pvTaskGetThreadLocalStoragePointer(
TaskHandle_txTaskToQuery,
BaseType_txIndex );
& & & 此函数仅用于高级用户。从线程本地存储指针数组中读取值。更详细描述见15.设置线程本地存储指针一节。
16.2参数描写
xTaskToQuery:任务句柄。NULL表示当前任务。
xIndex:写入到线程本地存储数组的索引号,线程本笃存储数组的大小由宏configNUM_THREAD_LOCAL_STORAGE_POINTERS设定,该宏在文件FreeRTOSConfig.h中。
16.3返回值
& & & 返回一个指针,这个指针存储在线程本地存储指针数组中,数组索引由参数xIndex指定。
16.4用法举例
16.4.1存储一个整形数
uint32_tulV
/* 向当前任务的线程本地存储数组下标为1的位置写入一个指向32位常量值的指针。*/
vTaskSetThreadLocalStoragePointer(NULL, 1, ( void * ) 0x );
/*向当前任务的线程本地存储数组下标为0的位置写入一个指向32整形值的指针*/
ulVariable= ERROR_CODE;
vTaskSetThreadLocalStoragePointer(NULL, 0, ( void * ) ulVariable );
/*从当前任务的线程本地存储数组下标为5的位置读取出一个指针并赋值给32位整形变量。*/
ulVariable= ( uint32_t ) pvTaskGetThreadLocalStoragePointer( NULL, 5 );
16.4.2存储结构提
typedefstruct
uint32_t ulValue1;
uint32_t ulValue2;
}xExampleS
xExampleStruct*pxS
/*为结构体分配内存*/
pxStruct= pvPortMalloc( sizeof( xExampleStruct ) );
/*为结构体成员赋值*/
pxStruct-&ulValue1= 0;
pxStruct-&ulValue2= 1;
/*向当前任务的线程本地存储数组下标为0的位置写入一个指向结构体变量的指针*/
vTaskSetThreadLocalStoragePointer(NULL, 0, ( void * ) pxStruct );
/*从当前任务的线程本地存储数组下标为0的位置读取出一个结构体指针*/
pxStruct= ( xExampleStruct * ) pvTaskGetThreadLocalStoragePointer( NULL, 0 );
17.设置超时状态
17.1函数描述
& & & void vTaskSetTimeOutState( TimeOut_t *const pxTimeOut );
& & & 此函数仅用于高级用户,通常与API函数xTaskCheckForTimeOut()共同使用。
& & & 任务因为等待某事件而进入阻塞状态,通常情况下任务会设置一个等待超时周期。如果在等待事件超时,任务会退出阻塞状态。想象一个这样的应用,某任务等待一个事件而进入阻塞状态,但是事件迟迟不发生,超时后任务退出阻塞状态继续执行任务。假如任务等待的事件仍然没有发生,则任务又会阻塞在该事件下。只要任务等待的事件一直不发生,这个任务进入阻塞然后超时退出阻塞,再进入阻塞的循环就会一直存在。是不是可以设定一个总超时时间,只要总阻塞时间大于这个总超时时间,则可以结束这个任务或进行相应记录?freeRTOS提供了两个API函数来完成这个功能,这就是vTaskSetTimeOutState()和xTaskCheckForTimeOut()。
& & & vTaskSetTimeOutState()函数用于设置初始条件,之后调用xTaskCheckForTimeOut()函数检查任务总阻塞时间是否超过总超时时间,如果没有超过,则调整剩余的超时时间计数器。
17.2参数描述
pxTimeOut:指向一个结构体的指针,该结构体用来保存确定超时是否发生的必要信息。vTaskSetTimeOutState()函数会设置结构体的成员。
17.3用法举例
& & & 参见18.超时检测。
18.超时检测
18.1函数描述
BaseType_t xTaskCheckForTimeOut(TimeOut_t * const pxTimeOut,
TickType_t* const pxTicksToWait );
& & & 此函数仅用于高级用户,通常与API函数vTaskSetTimeOutState共同使用。
& & & 详细描述见17.设置超时状态。
18.2参数描述
pxTimeOut:指向一个结构体的指针。该结构体保存确定超时是否发生的必要信息。使用API函数vTaskSetTimeOutState初始化该结构体。
pxTicksToWait:TickType_t指针,指向的变量保存总超时时间。
18.3返回值
pdTRUE:总超时发生
pdFALSE:总超时未发生
18.4用法举例
/* 函数用于从RX缓冲区中接收uxWantedBytes字节数据,RX缓冲区由UART中断填充。如果RX缓冲区没有足够的数据,则任务进入阻塞状态,直到RX缓冲区有足够数据或者发生超时。如果超时后仍然没有足够的数据,则任务会再次进入阻塞状态,xTaskCheckForTimeOut()函数用于重新计算总超时时间以确保总阻塞状态时间不超过MAX_TIME_TO_WAIT。如果总阻塞状态时间大于了总超时时间,则不管RX缓冲区是否有充足数据,都将这些数据读出来。
size_txUART_Receive( uint8_t *pucBuffer, size_t uxWantedBytes )
size_t uxReceived = 0;
TickType_t xTicksToWait = MAX_TIME_TO_WAIT;
TimeOut_t xTimeO
/* 初始化结构体变量xTimeOut。*/
vTaskSetTimeOutState( &xTimeOut );
/* 无限循环,直到缓冲区包含足够的数据或者阻塞超时发生。*/
while( UART_bytes_in_rx_buffer(pxUARTInstance ) & uxWantedBytes )
/* RX缓冲区没有足够多的数据,表示任务已经进入过一次阻塞状态。调用API函数xTaskCheckForTimeOut检查总阻塞时间是否超过总超时时间,如果没有,则调整剩余的总超时时间。*/
if( xTaskCheckForTimeOut( &xTimeOut,&xTicksToWait ) != pdFALSE )
/* 如果总阻塞时间大于总超时时间,则退出这个循环 */
/* 在等待了xTicksToWait个系统节拍周期后,向接收中断发出通知,需要更多数据。
ulTaskNotifyTake( pdTRUE, xTicksToWait );
/*从RX缓冲区读取uxWantedBytes个字节并放到pucBuffer缓冲区。*/
uxReceived = UART_read_from_receive_buffer(pxUARTInstance,
pucBuffer,
uxWantedBytes );
return uxR
谢谢小伙伴的分享,学习了`(*∩_∩*)′
本分类共有文章20篇,更多信息详见
& 2012 - 2016 &
&All Rights Reserved. &
/*爱悠闲图+*/
var cpro_id = "u1888441";

我要回帖

更多关于 freertos stm32 的文章

 

随机推荐