如需要绘制PCB,设计电路可以和我联系。sunhenu@163.com.
分类: 嵌入式
2013-04-19 17:26:00
void osal_start_system( void )
{
#if !defined ( ZBIT ) //不知道是什么东西
for(;;) // Forever Loop
#endif
{
uint8 idx = 0;
Hal_ProcessPoll();
// This replaces MT_SerialPoll() and osal_check_timer().
//轮询TIMER与UART
轮询UART与TIMER,涉及HAL层,晚点总结,添加串口相关代码就是在这里。
初始化时由osal_memset()设为0,只要不为空类型NULL,即有相对应任务事件发生,就break跳出循环体,通过下面的程序进行任务事件处理。如果为空,执行判断语句,即idx自增,再返回轮询有无各层的任务事件发生。如果执行完循环语句都没有检测到有事件发生,idx=7,进入睡眠。(对于本例子来说,任务数组里只有七个任务,tasksEvents[0]~tasksEvents[6],tasksEvents[6]就是用户自已添加的任务,idx随着用户添加任务的增多而增大)
do {
if (tasksEvents[idx]) // Task is highest priority that is ready.
{
break;
}
} while (++idx < tasksCnt); //tasksCnt=7
(针对本例子,随着用户应用任务增多而增大)
if (idx < tasksCnt)
{
uint16 events;
halIntState_t intState; //中断位状态
HAL_ENTER_CRITICAL_SECTION(intState);
//中断临界状态:保存先前中断状态,然后关中断
events = tasksEvents[idx];
//uint16 events;对应有事件发生的任务的数组
tasksEvents[idx] = 0;
// Clear the Events for this task. NULL
HAL_EXIT_CRITICAL_SECTION(intState);
//跳出中断临界状态:恢复先前中断状态
/***********************************************************************************************/
#define HAL_ENABLE_INTERRUPTS() st( EA = 1; ) //开中断
#define HAL_DISABLE_INTERRUPTS() st( EA = 0; ) //关中断
#define HAL_INTERRUPTS_ARE_ENABLED() (EA)
typedef unsigned char halIntState_t; //中断位状态
//中断临界状态:把原先中断状态EA赋给X,然后关中断;以便后面可以恢复原先的中断状态
#define HAL_ENTER_CRITICAL_SECTION(x) st( x = EA; HAL_DISABLE_INTERRUPTS(); )
//跳出上面的中断临界状态,恢复先前的中断状态
#define HAL_EXIT_CRITICAL_SECTION(x) st( EA =
x; )
//中断临界状态以及跳出临界状态的全过程:
#define HAL_CRITICAL_STATEMENT(x) st( halIntState_t s; HAL_ENTER_CRITICAL_SECTION(s); x;HAL_EXIT_CRITICAL_SECTION(s); )
st()函数,定义在hal_defs.h中:
#define st(x) do { x } while (__LINE__ == -1)
临界状态是操作系统为了防止数据发生竞争而采取的一种保护策略。具体的原理在linux
kernel里面有详细介绍
/***********************************************************************************************/
events = (tasksArr[idx])( idx, events );
//调用相对应的任务事件处理函数处理,各类事件处理函数M(task_id,event),返回的都是这个任务未被处理的事件。
HAL_ENTER_CRITICAL_SECTION(intState);
tasksEvents[idx] |= events;
// Add back unprocessed events to the current task.
//把刚才返回未处理的任务事件添加加当前任务中再进行处理,跳出此if(idx < tasksCnt)循环再进行if (tasksEvents[idx])判断并处理)
HAL_EXIT_CRITICAL_SECTION(intState);
}
#if defined( POWER_SAVING )
else // Complete pass through all task events with no activity?
{
osal_pwrmgr_powerconserve(); // Put the processor/system into sleep
}
#endif
}
}
/***********************************************************************************************/
接下来就是事件和任务处理函数,涉及到指针数组和函数指针的问题,最好先看看C语言教程。
//typedef unsigned short uint16;
//typedef unsigned char uint8;
tasksEvents[ ]是一个事件数组,其元素对应着事件值(uint16类型的),也即是事件。但是在OSAL_SampleApp.c下有这么一个声明:uint16*tasksEvents;所以很多人将其误认为事件指针的数组。从程序后面来看,这里虽然定义了tasksEvents为指针,但是在实际使用过程中将其作为一个uint16类型的数组来使用的(tasksEvents[idx])。例如:uint16
a[],是定义了uint16类型的a数组。如果我定义了uint16
*a;然后利用a[0],a[1]来赋值使用,这样a就变成了一个uint16类型的数组,但是a本身还是一个指针,指向a[]的首地址,也指向a[0]的地址,a=&a[0],a++就是&a[1],但是a[idx](也就是*(a+idx))就是一个地道的uint16数值了,也就是事件本身了。关于这点如果不明白,可以参考一下谭浩强的指针和数组之间的关系。
(对于本例子来说内部各元素即tasksEvents[0]~tasksEvents[6];tasksEvents[idx]是就是事件)。
/***********************************************************************************************/
events = (tasksArr[idx])( idx, events );任务idx的事件处理函数
首先看下对tasksArr[ ]的定义:
const pTaskEventHandlerFn tasksArr[ ] =
//数组tasksArr[ ]有7个元素(MT defined)
{
macEventLoop, //MAC层任务事件处理函数
nwk_event_loop, //NWK层任务事件处理函数
Hal_ProcessEvent, //PHY层事件处理函数
#if defined( MT_TASK )
MT_ProcessEvent, //MT任务事件处理函数
#endif
APS_event_loop, //APS层任务事件处理函数
ZDApp_event_loop, //ZDO任务事件处理函数
SampleApp_ProcessEvent //用户应用任务事件处理函数
};
再来看下对 pTaskEventHandlerFn的定义:(OSAL_Tasks.h中)
/***********************************************************************************************/
typedef unsigned short (*pTaskEventHandlerFn)( unsigned char task_id, unsigned short event );
typedef,把pTaskEventHandlerFn声明成一种函数指针类型的别名,这种函数指针指向M(task_id,event)这种类型的函数,
即各任务的事件处理函数。其实我们正常定义的函数,其函数名就是一种指针,所以tasksArr[
]就是一个指针数组,数组里面的元素就是函数指针(pTaskEventHandlerFn类型的),或者说就是函数名称,这样tasksArr[
]就是一个按照idx顺序排列的函数数组了。
如果调用相对应的函数,直接使用 tasksArr[idx](task_id,event)就行了,也即是调用相应的函数。
这里如果不明白,请看看可以找到谭浩强的那本C语言书籍,具体看看。
从OSAL_SampleApp.c中对tasksArr[ ]的定义我们可以知道macEventLoop,nwk_event_loop……SampleApp_ProcessEvent这些元素都是函数名称,也即是函数指针变量,最终都是指向M(task_id,event)这种类型的函数,也就是各层的事件处理函数。
/***********************************************************************************************/
参考文章为 http://wjf88223.blog.163.com。