http://blog.chinaunix.net/uid-20564848-id-72937.html
2007
文章来源
:http
://gliethttp.cublog.cn
[注
:以下为FreeRTOS_v4
.5
.0在at91sam7s64处理器上的task任务创建函数
(gliethtp
)]--------------------------------------------------------------------------------------portEND_SWITCHING_ISR
vPortYieldProcessor
vPortPreemptiveTick
以上3个函数会调用vTaskSwitchContext
(),将全局量pxCurrentTCB指向高优先级的task对应的TCB
,1
.portEND_SWITCHING_ISR
----在ISR中发生了Semaphore、Q或者Mutex互斥量等事件
,事件又使得比进入ISR之前的占用cpu的
当前运行线程的优先级高
,所以需要调用portEND_SWITCHING_ISR
,让更高优先级的task线程执行
, 达到RTOS的实时性
.(具体实例可见
:demo
/arm7_at91sam7s64_iar
/serial
/Serial
.c
->__arm
void vSerialISR
( void )以及
demo
/arm7_at91sam7s64_iar
/usb
/USBSample
.c
->__arm
void vUSB_ISR
( void ))2
.vPortYieldProcessor
----主动调用taskYIELD
()产生软中断
,之后软中断异常直接调用vPortYieldProcessor处理程序
, 进而调用vTaskSwitchContext
()计算已经就绪的更高优先级task对应的TCB传给全局量pxCurrentTCB
, 之后在portRESTORE_CONTEXT
()中
,顺利恢复到计算出来的就绪的最高优先级task中去执行代码
.3
.vPortPreemptiveTick
----在FreeRTOS系统滴答tick时钟里
,每1个系统滴答tick都会调用vTaskSwitchContext
(),计算下一个
需要占用cpu的新task
,这也直接导致
,同优先级的task们
,顺利进行轮转调度
,所以tick是他们能够
顺利进行轮转的直接源动力
;由此想到的
[gliethtp
]: 假设tick间隔为10ms
,那么在用户task中不做任何处理的前提下
,每10ms都会轮转到下1个同优先级的task执行
,每个task占用cpu的时间为1个系统tick滴答10ms
,如果用户task在其中夹杂了各种事件处理
,延时等待
,主动调用taskYIELD
()以及某些IRQ中触发事件
等因素之后
,就会出现多个同优先级的tasks占用cpu的时间总和为10ms的情况
,也就是taskA可能刚刚
因为同优先级的taskB主动调用了taskYIELD
()获得了cpu
,此时还没有经过2us
,系统滴答tick到来
,仅仅执行2us的taskA会在系统滴答tick到达后
,又被剥夺cpu
,通过计算
,taskB可能又获得了cpu
,最糕的情况是每个系统滴答tick都是这样
,就像物理学上讲的
"共振"一样
,那么这种情况下FreeRTOS对
taskA在分配策略上是不公平的
,taskA将一直处于饥饿状态
,虽然不至于饿死
,如果FreeRTOS修正为基于时间片的轮转调度策略
,这种问题可以得到解决
,不过实际应用中这样的巧合
可能不会出现
,但是这也直接导致我们设计的实际系统如果是关乎人类生命的
,那么不要使用轮转
调度
,因为这里边存在刚才上面提到的那样一种特殊情况
,如果某个计算需要在taskA中完成
,而taskA
又迟迟不能完成
,当缓存空间耗尽的时候
,同步机制开始起作用
,其他和计算结果相关的tasks们
因为迟迟等不到结果的到来
,而不得不放慢自己的速度甚至悬挂起自己
,让出cpu
,让taskA能够有更多的机会
获得cpu的使用时间
,整个系统的性能开始短时间下降
,又因为动态特性
,taskA的那种窘困情况并不会一直
持续
,所以我们在外边看到我们的应用系统就会出现
:一会慢、一会快
,走走停停
,慢慢悠悠
,好像我们欠它200似的
.所以在FreeRTOS实际同优先级task建立之前要考虑清楚
,否则可能因为轮转调度MLQ的原因
,出现一些不太希望的现象
,当然FreeRTOS以他优秀的架构方式
,让我们使用者可以建立优先级完全不同的多个task
,来避开轮转过程中出现的task占用cpu时间不稳定的现象
,但是每增加1个优先级
,静态空间pxReadyTasksLists就会
多出1个xList结构来维护
,扫描时间while
(listLIST_IS_EMPTY
(&(pxReadyTasksLists
[uxTopReadyPriority
])))也就多出了1个循环对应的几条汇编语句
,进而也就让cpu关闭IRQ中断的时间又多出了一些
,当然可以权衡
,使用FIQ将一些很紧要的中断进行处理
,但是因为FIQ可以抢占正在处理IRQ的context上、下文
的代码
,所以也就导致FIQ中不能出现portSAVE_CONTEXT
()等和FreeRTOS任务切换相关的代码
,所以FIQ中也不能使用事件如Q事件
,Semaphore事件等来触发任务
,因为FIQ不能再访问全局量或者局部量
,这些量值可能在IRQ或swi中
,已经被保存到了旧task中
,抑或刚刚恢复了一半
. 另一个就是FreeRTOS关闭中断的时间
,可能比较长
,从任务切换角度来看主要是由vTaskSwitchContext
()计算导致的
,void vTaskSwitchContext
( void ){ if( uxSchedulerSuspended
!= ( unsigned portBASE_TYPE
) pdFALSE
) { xMissedYield
= pdTRUE
; return; } while( listLIST_IS_EMPTY
( &( pxReadyTasksLists
[ uxTopReadyPriority
] ) ) ) { --uxTopReadyPriority
;//直接导致IRQ关闭时间可能很长[gliethttp] } listGET_OWNER_OF_NEXT_ENTRY
( pxCurrentTCB
, &( pxReadyTasksLists
[ uxTopReadyPriority
] ) ); vWriteTraceToBuffer
();} 从事件角度来看
,FreeRTOS_v4
.5
.0使用Queue机制
,间接实现了Queue队列事件机制
,Semaphore信号机制和Mutex互斥机制
3种机制
,而且进入xQueueGenericSend
()之后
,第一件事情是锁住调度器
:vTaskSuspendAll
(),将除当前task之外的
所有task不能及时获得cpu使用权
,将RTOS机制打了一个不小的折扣
,延迟到xTaskResumeAll
()才能执行任务切换
,不过还好
虽说关断时间有时可能比较长
,但是我们还能够忍受
,当然这样做的1个优势是
,vTaskSuspendAll
()期间
,cpu的IRQ中断是可以安全进行的
;进入xTaskResumeAll
()函数就会关闭
IRQ系统
,直到内部函数执行完毕才会重新使能IRQ系统
,或者在其中干脆taskYIELD
();切换到另1个task
,由另1个task完成IRQ
开启工作
(或者是当即spsr没有关中断
,进而直接打开
,或者是切换过去的task继续运行
,显示调用开中断函数
)这种方式
与ucos
-ii的任务切换和中断管理机制一致
,这种机制能够计算到IRQ系统关闭时间的最大值
;可是xTaskResumeAll
()有1个
地方可能使IRQ系统关断时间延长很多
,也是由while循环引起的
,while( ( pxTCB
= ( tskTCB
* ) listGET_OWNER_OF_HEAD_ENTRY
( ( ( xList
* ) &xPendingReadyList
) ) ) != NULL ){ //2007-09-29 gliethttp //如果调度器被锁,那么事件队列和标准队列上的指针不会调整, //所有链表摘除工作都要在这里进行 vListRemove
( &( pxTCB
->xEventListItem
) ); vListRemove
( &( pxTCB
->xGenericListItem
) ); prvAddTaskToReadyQueue
( pxTCB
); if( pxTCB
->uxPriority
>= pxCurrentTCB
->uxPriority
) { xYieldRequired
= pdTRUE
; }}因为PendingReadyList队列可能因为IRQ事件风暴
,将n多个task同时都打到上面去
,这样计算while循环体
也就要有n次
,不过还好
,他有一个上限值
,就是所有可能挂接到PendingReadyList队列上的tasks的总和
,执行while
(n
)循环体所花费的时间
. 总的来说
,每种RTOS都有它优秀的一面和不太理想的一面
,根据我们实际的工程应用场合
,来自由选择相应的RTOS
,每一种RTOS都不是万能的
,某个RTOS优秀的那一面能和我们的实际工程应用的主要因素大部分匹配
,并且不太理想的那一面也
不影响到我们什么
,那么这个RTOS就可以和我们的工程应用相匹配
,能match上一个实用的RTOS不容易
,FreeRTOS还是相当不错的
[gliethttp
]!
本站仅提供存储服务,所有内容均由用户发布,如发现有害或侵权内容,请
点击举报。