-
FreeRTOS
的使用说明
中断程序
FreeRTOS
中如果
ISR
p>
中如果使用了
Quene
,则需要进行任务
切换,需要在
ISR
设计时考虑
portEND_SWITCHING_ISR( (
cContextSwitchRequired ) );
如果没有任务切换,则无需特殊处理
任务调度
调度存在几种情况:
?
自动放弃时间(
< br>SWI
)
,
yeild
以及
wait
导致的挂起都算
< br>
?
Tick
时间到(也进行调度)
VTaskSwitchContext
仅仅查找优先级最高的调度
相同的级别
占有相同的
PCU
时间
对于
IDLE
任务而言,如果用抢占式,并且执行
到
IDLE
时,必须让出执行时间的话
a task that is sharing the idle
priority
(与
IDLE
任务
有相同优先级)
,则会让出。
p>
假定该任务是
while
(
1
)
{}
,并且一直处于
p>
Ready
状态,没有诸如挂起等操作,则一进入
< br>IDLE
任务就让出
则
vApplicationIdleHook
()函数基本没有时间执行。也就失去了意义
CoRoutine
是一个函数,可以迅速执行完成
在
vApplicationIdleHook
中调用。
调度时,直接调用了
< br>CreateCorountine
的任务函数
当执行完之后,
IDLE
任务会重新循环,检
查是否有同级任务执行。
所以在<
/p>
IDLE
层次上,有任务,但该任务执行完了还是需要释放一段时
间以便让
hook
函数
执行操作。
p>
否则
CoRoutine
函数基本上没有时间执行。
QUENE
操作
其中
quene
的发送和等待都可能进行
< br>任务切换
。
当
quene
发送时,如果
q
uune
队列已满,则会
挂起
;而如果
队列为空,
take
操作就会导致任
务
挂起
queen
高优先级别
发送
低优先级别
接受
发送
完了,继续执行;如果不主动让出
CPU
的话,低优先级的无法
唤醒进行队列处理
如果发送的多了的话,队列满后,高优先级
挂起,然后才会让低优先级的任务进行处理
所以程序检测发送
的状态,根据状态确定是否是否需要主动让出
CPU
时间给
p>
相同的优先级
的任务
另外一个办法就是有效发送后,
将任务挂起,
当低优先级的
任务处理后,
再重新将高优先级
任务挂起
如果不这样处理的话,队列总是处于满状态
低级别发送
高级别接受
发送完了后,低级别立刻被挂起,然后高级别执行,
因此队列一直为空
任务的处理
任务的原型
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
< br>变量
//block
p>
函数只能在循环的最外层调用,不能在函数中调用,因为在函数中调用,宏已经不
对了
因此也不能在
sw
itch
语句中调用
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,
-
-
-
-
-
-
-
-
-
上一篇:keil c51常见错误警告提示
下一篇:电路原理复习试卷