目前我们782X/781X运行操作系统都是ECOS。eCOS由Redhat推出的小型即时操作系统(Real-Time operating system)。
但是为什么我们看不到ecos的相关代码呢?这是因为Mstar在这做了一层封装,将ecos OS相关的api打包进了Mstar的函数。
关于封装OS的函数,全部在msos.h中申明。作为理解精通Mstar STB架构,必须熟悉这些函数,因为很多地方需要利用OS的特性,然后很多系统BUG都是由于没理解这些OS相关函数导致的。
本文主要解析MsOS_WaitEvent这个函数,因为这个函数就是Mstar HQ还有用错的时候,导致产生特定性质的bug。
如下是Mstar封装ECOS的实现代码。通过代码我们可以看到
typedef enum
{
E_AND, ///< Specify all of the requested events are require.
E_OR, ///< Specify any of the requested events are require.
E_AND_CLEAR, ///< Specify all of the requested events are require. If the request are successful, clear the event.
E_OR_CLEAR, ///< Specify any of the requested events are require. If the request are successful, clear the event.
} EventWaitMode;
这几种模式到底在底层是这么实现的,具体是怎么含义。
具体这个函数底层有调用到cyg_flag_wait,cyg_flag_poll,cyg_flag_timed_wait三个函数
其中
cyg_flag_wait对应blocking wait模式
cyg_flag_poll对应non-blocking模式
cyg_flag_timed_wait对应blocking wait with timeout模式
cyg_flag_wait 来等待一个或多个事件.该函数有三个参数,
第一个参数对指 定事件标志进行标识;
第二个参数是位的组合,表示对哪些事件感兴趣;
第三个参数是下列值中的 一个:
CYG_FLAG_WAITMODE_AND.函数调用者将被阻塞,直到所有指定的事件发生为止(此时 事件标志中所有对应的位为 1) .等待成功时,事件标志中的这些位不会被清除,仍保持置位的状态.
CYG_FLAG_WAITMODE_OR. 函数调用者将被阻塞, 直到所有指定的事件任一个发生为止 (此 时事件标志中所有对应的位有一个置 1) .等待成功时,事件标志中的这些位不会被清除,仍保持置位的状态.
CYG_FLAG_WAITMODE_CLR. 此标志需要与上面两个标志配合使用, 在函数成功返回时清整 个事件标志,上面的标志与此标志位相或后,兼具两者的特性.
同理其他2个函数的参数意义如上,明白了这3个参数意义,就理解了ECOS的事件机制。
//-------------------------------------------------------------------------------------------------
/// Wait for the specified event flag combination from the event group
/// @param s32EventGroupId \b IN: event group ID
/// @param u32WaitEventFlag \b IN: wait event flag value
/// @param pu32RetrievedEventFlag \b OUT: retrieved event flag value
/// @param eWaitMode \b IN: E_AND/E_OR/E_AND_CLEAR/E_OR_CLEAR
/// @param u32WaitMs \b IN: 0 ~ MSOS_WAIT_FOREVER: suspend time (ms) if the event is not ready
/// @return TRUE : succeed
/// @return FALSE : fail
//-------------------------------------------------------------------------------------------------
MS_BOOL MsOS_WaitEvent (MS_S32 s32EventGroupId,
MS_U32 u32WaitEventFlag,
MS_U32 *pu32RetrievedEventFlag,
EventWaitMode eWaitMode,
MS_U32 u32WaitMs)
{
cyg_flag_mode_t operation;
if ( (s32EventGroupId & MSOS_ID_PREFIX_MASK) != MSOS_ID_PREFIX )
{
return FALSE;
}
else
{
s32EventGroupId &= MSOS_ID_MASK;
}
ASSERT( MsOS_In_Interrupt() == FALSE );
switch(eWaitMode)
{
case E_AND:
operation = CYG_FLAG_WAITMODE_AND;
break;
case E_OR:
operation = CYG_FLAG_WAITMODE_OR;
break;
case E_AND_CLEAR:
operation = CYG_FLAG_WAITMODE_AND | CYG_FLAG_WAITMODE_CLR;
break;
case E_OR_CLEAR:
operation = CYG_FLAG_WAITMODE_OR | CYG_FLAG_WAITMODE_CLR;
break;
default:
return FALSE;
}
if (u32WaitMs==MSOS_WAIT_FOREVER) //blocking wait
{
*pu32RetrievedEventFlag = cyg_flag_wait( &_MsOS_EventGroup_Info[s32EventGroupId].stEventGroup,
u32WaitEventFlag,
operation );
}
else if (u32WaitMs==0) //non-blocking
{
*pu32RetrievedEventFlag = cyg_flag_poll( &_MsOS_EventGroup_Info[s32EventGroupId].stEventGroup,
u32WaitEventFlag,
operation );
}
else //blocking wait with timeout
{
*pu32RetrievedEventFlag = cyg_flag_timed_wait( &_MsOS_EventGroup_Info[s32EventGroupId].stEventGroup,
u32WaitEventFlag,
operation,
cyg_current_time()+u32WaitMs*TICK_PER_ONE_MS );
}
if( *pu32RetrievedEventFlag )
{
return TRUE;
}
else
{
return FALSE;
}
}
//-------------------------------------------------------------------------------------------------
/// Clear the specified event flag (bitwise XOR operation) in the specified event group
/// @param s32EventGroupId \b IN: event group ID
/// @param u32EventFlag \b IN: event flag value
/// @return TRUE : succeed
/// @return FALSE : fail
//-------------------------------------------------------------------------------------------------
MS_BOOL MsOS_ClearEvent (MS_S32 s32EventGroupId, MS_U32 u32EventFlag)
{
if ( (s32EventGroupId & MSOS_ID_PREFIX_MASK) != MSOS_ID_PREFIX )
{
return FALSE;
}
else
{
s32EventGroupId &= MSOS_ID_MASK;
}
cyg_flag_maskbits(&_MsOS_EventGroup_Info[s32EventGroupId].stEventGroup, ~u32EventFlag);
return TRUE;
}
|