FreeRTOS的使用总结
更新时间:2023-11-07 13:49:01 阅读量: 教育文库 文档下载
FreeRTOS的使用说明
中断程序
FreeRTOS 中如果ISR中如果使用了Quene,则需要进行任务切换,需要在ISR设计时考虑
portEND_SWITCHING_ISR( ( cContextSwitchRequired ) ); 如果没有任务切换,则无需特殊处理
任务调度
调度存在几种情况:
? 自动放弃时间(SWI),yeild以及wait导致的挂起都算 ? Tick时间到(也进行调度)
VTaskSwitchContext 仅仅查找优先级最高的调度 相同的级别 占有相同的PCU时间
对于IDLE任务而言,如果用抢占式,并且执行到IDLE时,必须让出执行时间的话 a task that is sharing the idle priority (与IDLE任务有相同优先级),则会让出。
假定该任务是while(1){},并且一直处于Ready状态,没有诸如挂起等操作,则一进入IDLE任务就让出
则vApplicationIdleHook()函数基本没有时间执行。也就失去了意义
CoRoutine是一个函数,可以迅速执行完成 在vApplicationIdleHook中调用。
调度时,直接调用了CreateCorountine的任务函数
当执行完之后,IDLE任务会重新循环,检查是否有同级任务执行。
所以在IDLE层次上,有任务,但该任务执行完了还是需要释放一段时间以便让hook函数执行操作。
否则CoRoutine函数基本上没有时间执行。
QUENE操作
其中quene的发送和等待都可能进行任务切换。
当quene发送时,如果quune队列已满,则会挂起;而如果队列为空,take操作就会导致任务挂起
queen
高优先级别 发送 低优先级别 接受
发送完了,继续执行;如果不主动让出CPU的话,低优先级的无法唤醒进行队列处理 如果发送的多了的话,队列满后,高优先级挂起,然后才会让低优先级的任务进行处理 所以程序检测发送的状态,根据状态确定是否是否需要主动让出CPU时间给相同的优先级的任务
另外一个办法就是有效发送后,将任务挂起,当低优先级的任务处理后,再重新将高优先级任务挂起
如果不这样处理的话,队列总是处于满状态
低级别发送 高级别接受
发送完了后,低级别立刻被挂起,然后高级别执行, 因此队列一直为空
任务的处理 任务的原型
void vATaskFunction( void *pvParameters ); Or,
portTASK_FUNCTION_PROTO( vATaskFunction, pvParameters );
是一个死循环
空闲任务
优先级:tskIDLE_PRIORITY 该优先级可以共享
空闲的钩子函数
The Idle Task Hook,在空闲任务中处理一些事情。 如果用相同优先级,又增加一个堆栈空间
Co-routines
configMAX_CO_ROUTINE_PRIORITIES 最高的优先级 例程有以下形式:
void vACoRoutineFunction( xCoRoutineHandle xHandle, unsigned portBASE_TYPE uxIndex ) {
crSTART( xHandle );
for( ;; ) {
-- Co-routine application code here. -- }
crEND(); }
//实际经展开后如下:
switch( ( ( corCRCB * )pxCRCB )->uxState ) { case 0: ; for (;;) { } };
//延时函数的处理
#define crDELAY( xHandle, xTicksToDelay ) \\ if( xTicksToDelay > 0 ) \\ { \\ vCoRoutineAddToDelayedList( xTicksToDelay, NULL ); \\ } \\ crSET_STATE0( xHandle );
//#define crSET_STATE0( xHandle )
( ( corCRCB * )xHandle)->uxState = (__LINE__ * 2); return;
case (__LINE__ * 2):
//可见在延时函数处理过后,函数就退出了
协作例程是一个执行完了,才执行另外一个。执行完了,就意味着放弃CPU,即退出运行。
//协作例程的限制
如果需要保存数据,则需要定义成全局变量或者static变量
//block 函数只能在循环的最外层调用,不能在函数中调用,因为在函数中调用,宏已经不对了
因此也不能在switch语句中调用
void vACoRoutineFunction( xCoRoutineHandle xHandle, unsigned portBASE_TYPE uxIndex ) {
// Co-routines must start with a call to crSTART().
crSTART( xHandle );
for( ;; ) {
// It is fine to make a blocking call here, crDELAY( xHandle, 10 );
// but a blocking call cannot be made from within // vACalledFunction(). vACalledFunction(); }
// Co-routines must end with a call to crEND(). crEND(); }
void vACalledFunction( void ) {
// Cannot make a blocking call here!
}
协作例程的调度
void vApplicationIdleHook( void ) {
vCoRoutineSchedule( void ); } 或者
void vApplicationIdleHook( void ) {
for( ;; ) {
vCoRoutineSchedule( void ); } }
/////=======================展开后的程序相当怪异 /* Co-routines MUST start with a call to crSTART. */ //crSTART( xHandle ); 展开
switch( ( ( corCRCB * )xHandle )->uxState ) {
case 0:
;
//crSTART( xHandle ); 展开
for( ;; ) {
/* Post our uxIndex value onto the queue. This is used as the LED to flash. */
//crQUEUE_SEND( xHandle, xFlashQueue, ( void * crfPOSTING_BLOCK_TIME, &xResult ); 展开成如下
{
* &xResult = xQueueCRSend( xFlashQueue, ( void * ) &uxIndex, 0 ); if( * &xResult == (errQUEUE_BLOCKED ) ) {
( ( corCRCB * )xHandle)->uxState = (160 * 2); //__LINE__ return;
case (160 * 2)://__LINE__ ;
* &xResult = xQueueCRSend( xFlashQueue, ( void * ) &uxIndex, 0 ); }
if( * &xResult == ( errQUEUE_YIELD ) ) {
( ( corCRCB * )xHandle)->uxState = ((160 * 2)+1); //__LINE__ return;
case ((160 * 2)+1)://__LINE__ ;
* &xResult = ( pdPASS ); } } ;
//crQUEUE_SEND( xHandle, xFlashQueue, ( void * crfPOSTING_BLOCK_TIME, &xResult ); 展开成如上
///----------------------------正常语句--------------- if( xResult != ( pdPASS ) ) {
/* For the reasons stated at the top of the file we should always find that we can post to the queue. If we could not then an error has occurred. */
uxCoRoutineFlashStatus = ( 0 ); }
) &uxIndex,
) &uxIndex,
//crDELAY( xHandle, xFlashRates[ uxIndex ] ); ----展开 if( xFlashRates[ uxIndex ] > 0 )
{ vCoRoutineAddToDelayedList( xFlashRates[ uxIndex ], 0 ); }
( ( corCRCB * )xHandle)->uxState = (170 * 2); return;
case (170 * 2):; ;
//crDELAY( xHandle, xFlashRates[ uxIndex ] ); ----展开 }
/* Co-routines MUST end with a call to crEND. */ //crEND(); 展开 }
//crEND(); 展开 ;
quene的使用
between tasks, and between interrupts and tasks 是通过copy而不是ref进行的 xQueueCreate xQueueSend
xQueueSendToBack xQueueSendToFront xQueueReceive xQueuePeek
xQueueSendFromISR
xQueueSendToBackFromISR xQueueSendToFrontFromISR xQueueReceiveFromISR
从实现的函数看,可以在ISR和TASK之间进行传递。
查看例子,在ISR中发送后,导致调度的
void vBufferISR( void ) {
portCHAR cIn;
portBASE_TYPE xHigherPriorityTaskWoken;
/* We have not woken a task at the start of the ISR. */ xHigherPriorityTaskWoken = pdFALSE;
/* Loop until the buffer is empty. */ do {
/* Obtain a byte from the buffer. */
cIn = portINPUT_BYTE( RX_REGISTER_ADDRESS );
/* Post the byte. */
xQueueSendFromISR( xRxQueue, &cIn, &xHigherPriorityTaskWoken );
} while( portINPUT_BYTE( BUFFER_COUNT ) );
/* Now the buffer is empty we can switch context if necessary. */ if( xHigherPriorityTaskWoken ) {
/* Actual macro used here is port specific. */ taskYIELD_FROM_ISR ();//导致调度发生 } }
//如果导致切换的话
void vISR_Routine( void ) {
portBASE_TYPE xTaskWokenByReceive = pdFALSE; portCHAR cRxedChar;
while( xQueueReceiveFromISR( xQueue, ( void * ) &cRxedChar, &xTaskWokenByReceive) ) {
// A character was received. Output the character now. vOutputCharacter( cRxedChar );
// If removing the character from the queue woke the task that was // posting onto the queue xTaskWokenByReceive will have been set to // pdTRUE. No matter how many times this loop iterates only one // task will be woken. }
if( xTaskWokenByPost != pdFALSE ) {
// We should switch context so the ISR returns to a different task. // NOTE: How this is done depends on the port you are using. Check // the documentation and examples for your port. taskYIELD (); } }
//portEND_SWITCHING_ISR 参考
Note that interrupts must NOT use API functions that do not end in \
Mutex type semaphores cannot be used from within interrupt service routines. 由于存在优先级问题,所以在中断中不使用
API的选择问题: TASK有3套 ? 全特性的API ? 替代的API
? ISR中使用的轻量级的API
COROUTINE有
自己的一套,不能与TASK混用 ? xCoRoutineHandle ? xCoRoutineCreate ? crDELAY
? crQUEUE_SEND ? crQUEUE_RECEIVE
? crQUEUE_SEND_FROM_ISR ? crQUEUE_RECEIVE_FROM_ISR ? vCoRoutineSchedule
自定义:裁减
#define configUSE_PREEMPTION 1 #define configUSE_IDLE_HOOK 0 #define configUSE_TICK_HOOK 0 #define configCPU_CLOCK_HZ 58982400 #define configTICK_RATE_HZ 250 #define configMAX_PRIORITIES 5
#define configMINIMAL_STACK_SIZE 128 最小的堆栈大小 #define configTOTAL_HEAP_SIZE 10240 #define configMAX_TASK_NAME_LEN 16 #define configUSE_TRACE_FACILITY 0 #define configUSE_16_BIT_TICKS 0 #define configIDLE_SHOULD_YIELD 1 #define configUSE_MUTEXES 0 #define configUSE_RECURSIVE_MUTEXES 0 #define configUSE_COUNTING_SEMAPHORES 0 #define configUSE_ALTERNATIVE_API 0 #define configCHECK_FOR_STACK_OVERFLOW 0
#define INCLUDE_vTaskPrioritySet 1 #define INCLUDE_uxTaskPriorityGet 1
#define INCLUDE_vTaskDelete 1 #define INCLUDE_vTaskCleanUpResources 0 #define INCLUDE_vTaskSuspend 1 #define INCLUDE_vResumeFromISR 1 #define INCLUDE_vTaskDelayUntil 1 #define INCLUDE_vTaskDelay 1 #define INCLUDE_xTaskGetSchedulerState 1 #define INCLUDE_xTaskGetCurrentTaskHandle 1 #define INCLUDE_uxTaskGetStackHighWaterMark 0
#define configUSE_CO_ROUTINES 0 #define configMAX_CO_ROUTINE_PRIORITIES 1
内存管理的三种方法: ? 只分配 不回收 ? 分配佳回收
? C库函数中的分配及回收
堆栈检查功能
vApplicationStackOverflowHook 也有两种方式,检查指针大小,检查内存数据
任务创建 xTaskCreate vTaskDelete
任务控制 vTaskDelay
vTaskDelayUntil uxTaskPriorityGet vTaskPrioritySet vTaskSuspend vTaskResume
vTaskResumeFromISR
vTaskSetApplicationTag (多一个参数)
xTaskCallApplicationTaskHook 从中断中调用
内核控制
taskYIELD swi实现 taskENTER_CRITICAL taskEXIT_CRITICAL
taskDISABLE_INTERRUPTS taskENABLE_INTERRUPTS
vTaskStartScheduler vTaskEndScheduler
vTaskSuspendAll 禁止调度,但没有禁止TICK xTaskResumeAll 开始调度
任务工具
xTaskGetCurrentTaskHandle
uxTaskGetStackHighWaterMark (最高水位) xTaskGetTickCount xTaskGetSchedulerState uxTaskGetNumberOfTasks vTaskList (列出所有任务的状态,到缓冲区中) vTaskStartTrace ulTaskEndTrace
vTaskSetApplicationTag (多一个数据 多一个函数) xTaskCallApplicationTaskHook (任务钩子函数)
队列操作
uxQueueMessagesWaiting (等待的数目) vQueueDelete xQueueCreate xQueueSend
xQueueSendToBack xQueueSendToFront xQueueReceive xQueuePeek (只看 不删除) xQueueSendFromISR (需注意发送导致的任务切换操作) xQueueSendToBackFromISR xQueueSendToFrontFromISR xQueueReceiveFromISR
信号量操作
vSemaphoreCreateBinary vSemaphoreCreateCounting
xSemaphoreCreateMutex 带优先级
xSemaphoreTake (MUTEX也通过Sem的操作函数进行操作) xSemaphoreGive
xSemaphoreGiveFromISR(MUTEX的不行)
xSemaphoreCreateRecursiveMutex xSemaphoreTakeRecursive xSemaphoreGiveRecursive
MUTEX类型的不允许在中断中使用
CO ROUTINE控制 xCoRoutineHandle xCoRoutineCreate crDELAY
crQUEUE_SEND crQUEUE_RECEIVE
crQUEUE_SEND_FROM_ISR crQUEUE_RECEIVE_FROM_ISR vCoRoutineSchedule
不要使用任何形式的开关中断函数,portEXIT_CRITICAL().
而用portENTER_CRITICAL() and
正在阅读:
FreeRTOS的使用总结11-07
任课教师会议记录03-20
各种LED发光字比较07-18
我是山姆英文观后感04-02
我的房间作文想象作文300字06-24
爸爸作文400字07-15
《水浒传》读书笔记10篇03-27
第五章 Excel中的数据透视表(图)-作业4:销售数据简单分析08-05
北师大版小学四年级下册脱式计算04-30
- exercise2
- 铅锌矿详查地质设计 - 图文
- 厨余垃圾、餐厨垃圾堆肥系统设计方案
- 陈明珠开题报告
- 化工原理精选例题
- 政府形象宣传册营销案例
- 小学一至三年级语文阅读专项练习题
- 2014.民诉 期末考试 复习题
- 巅峰智业 - 做好顶层设计对建设城市的重要意义
- (三起)冀教版三年级英语上册Unit4 Lesson24练习题及答案
- 2017年实心轮胎现状及发展趋势分析(目录)
- 基于GIS的农用地定级技术研究定稿
- 2017-2022年中国医疗保健市场调查与市场前景预测报告(目录) - 图文
- 作业
- OFDM技术仿真(MATLAB代码) - 图文
- Android工程师笔试题及答案
- 生命密码联合密码
- 空间地上权若干法律问题探究
- 江苏学业水平测试《机械基础》模拟试题
- 选课走班实施方案
- FreeRTOS
- 总结
- 使用
- 形容词变副词练习
- 2017-2018学年高中英语牛津译林版选修九教师用书:Unit 4 单元尾 核心要点回扣 含答案 精品
- 操作系统(第三版)习题答案(中国铁道出版社 - 刘振鹏) 2
- 影响金属腐蚀因素习题
- 大学计算机基础重点 - 选择题100题
- 2013年公共英语二级考试(pets2)全真模拟试卷(2)-中大网校
- 70个经典面试问题及回答思路(一)
- 03-压力管道施工工艺
- 丽水学院学术期刊定级标准 - 图文
- XX电器销售工作总结范文 - 1
- 附录3 本书自编MATLAB函数的源代码及注释
- 福建省厦门市湖滨中学2018-2019学年高一下学期期中考试生物试题
- 甲级单位编制作业本项目可行性报告(立项可研+贷款+用地+2013案例)设计方案
- 高中《三角函数》全部教案
- 江苏省教师资格证教育学考试历年真题真题
- 安葬咒语
- 供电段安全大反思、大讨论总结
- 资源加工学课后习题答案
- 神农架林区各乡镇精准扶贫贫困户
- 鲁教版二年级语文上册教案《 太空生活趣事多》教学设计