OSAL运行、事件和消息

合集下载
  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

主函数执行以下函数由上可以看出main()函数共做了2件事:一是系统初始化,另外一件是开始执行
轮转查询式操作系统,重点就是调用了osal_init_system()和osal_start_system()。

1.屏蔽所有中断osal_int_disable( INTS_ALL );
2.初始化底板HAL_BOARD_INIT();
3.电压检测 zmain_vdd_check();
4.初始化IO InitBoard( OB_COLD );
5.初始化硬件驱动HalDriverInit();
6.初始化非易变量页面osal_nv_init( NULL );
7.初始化MAC层 ZMacInit();
10.中断使能osal_int_enable( INTS_ALL );
11.zmain_dev_info();
12.#ifdef LCD_SUPPORTED
zmain_lcd_init();
13.#ifdef WDT_IN_PM1
看门狗WatchDogEnable( WDTIMX );
14.osal_start_system();程序最终会在系统函数中无限循环下去。

1.1osal_run_system();无限的循环,
1.1.1任务轮序,跳转事件处理函数
在进入无限循环之前系统定义了三个至关重要的变量,
taskArr-----此数组的每一项都是
const pTaskEventHandlerFn tasksArr[ ] =
{- - - GenericApp_ProcessEvent }
都是一个函数指针,指向具体的函数入口地址
taskCnt-----保存了任务的总个数
const uint8 tasksCnt = sizeof( tasksArr ) / sizeof( tasksArr[0] );
taskEvent---指向事件表的首地址
uint16 *tasksEvents;
在任务初始化时osalInitTasks()做了这样一件事
tasksEvents = (uint16 *)osal_mem_alloc( sizeof( uint16 ) * tasksCnt);
osal_memset( tasksEvents, 0, (sizeof( uint16 ) * tasksCnt));//将字节清零
?那么关键的问题还没解决,事件到底是怎么被捕获的
SYS_EVENT_MSG = 0x8000 系统事件类号
case ZDO_STATE_CHANGE:不需注册网络中的设备状态发生改变时,产生的事件消息
ZDO_CB_MSG 要注册 ZDO_RegisterForZdoCB( uint8 indID, pfnZdoCb pFn );
AF_INOMING_MSG_CMD 消息进入好像不需要注册
添加这些事件前要先调用对应的Register函数
端点描述符必须要注册afRegister( &GenericApp_epDesc );
ZIGBEE事件有两类,系统定义事件和用户定义事件。

系统类事件是协议栈已定义好的,用户类事件是我们用户层面来定义的。

事件类号采用一个16bit的常量,使用独热码编码,独热码是只有一个bit为1,其他全为0的一种码制,采用独热码的优点是操作方便,可以使用简单的位操作指令实现,如:提取系统类事件用events & SYS_EVENT_MSG,清除系统类事件用events ^ SYS_EVENT_MSG;由于事件类号是16bit,也就是说zigbee事件类只有16个,系统类事件SYS_EVENT_MSG使用0x8000,故自定义事件类只有15个,可采用0x4000至0x0001。

实际上在协议栈里发现其中有几个已经用过了。

#define HAL_KEY_EVENT 0x0001
#define HAL_LED_BLINK_EVENT 0x0002
#define HAL_SLEEP_TIMER_EVENT 0x0004
#define PERIOD_RSSI_RESET_EVT 0x0008
系统类事件SYS_EVENT_MSG是协议栈里已经定义好的事件,它是一个事件集合,以下的几个事件都属于系统类事件,这些事件都是8位的二进制数,从0x00~0xcf:
①AF_INCOMINGMSG_CMD表示收到一个新的无线数据。

②ZDO_STATE_CHANGE当网络状态发生变化时,会产生该事件,如终端节点加入网络时,就可以通过判断该事件来决定何时向协调器发送数据包。

③ZDO_CB_MSG指示每一个注册的ZDO响应消息
④AF_DATA_CONFIRM_CMD调用AF_DataRequest()发送数据时,有时需要确认信息。

⑤AF_INCOMING_KVP_CMD:Incoming KVP type message收到键值对类型的消息。

⑥AF_INCOMING_GRP_KVP_CMD:Incoming Group KVP type message收到群键值对类型的消息。

⑦KEY_CHANGE:Key Events按键触发事件。

⑧ZDO_NEW_DSTADDR:ZDO has received a new DstAddr for this app ZDO终端获得新地址;匹配描述符请求(Match Descriptor Request)响应指示(例如:自动匹配);如A设备加入绑定后,A 设备触发ZDO_NEW_DSTADDR事件。

⑨ZDO_MATCH_DESC_RSP_SENT:ZDO match descriptor response was sent ZDO描述符匹配响应发送;A设备发送ZDP_MatchDescReq函数请求描述符匹配绑定,B设备收到后发送ZDP_MatchDescRsp函
数响应,B设备发送响应函数后触发ZDO_MATCH_DESC_RSP_SENT事件。


用户可以定义的事件类号还有15个从0x4000至0x0001,各个事件类下用户可定义的事件号29个从0xE0~0xFC. 事件处理函数为:app_ProcessEvent( byte task_id, UINT16 events ),可见调用此函数将传递两个参数,task_id任务号和events事件类号;事件处理函数首先根据事件类号来判断是何种类型事件,然后根据任务号得到消息指针pMsg,最后根据消息指针结构里的事件号pMsg->event 来具体处理事件,event为8bit的常量,系统event在ZComDef.h里定义。

event是如何被改变从而触发事件处理函数的呢?通过osal_set_event()这个函数。

当然一般都是通过osal_start_timerEx(),osal_msg_send() 来触发,这俩个函数都调用了osal_set_event()
脑子不够用了,速度做个总结,以后有时间会仔细的把每个函数都分析一遍。

首先,OSAL专门建立了一个任务来对硬件资源进行管理,这个任务的事件处理函数是Hal_ProcessEvent。

在这个函数中通过调用osal_start_timerEx( Hal_TaskID, HAL_KEY_EVENT, 100);这个函数使得每隔100毫秒就会执行一次HalKeyPoll()函数。

HalKeyPoll()获取当前按键的状态,并且通过调用OnBoard_KeyCallback函数向GenericApp任务发送一个按键消息,并且设置tasksEvents中GenericApp所对应的值为非零。

在osal_set_event这个函数中,有这样一个语句:tasksEvents[task_id]|=event_flag;}
下面以一个例子说明事件到底是怎样被捕获的:
#define AT_COMMEND 0x01
osal_set_event( GenericApp_TaskID, AT_COMMEND);设置了自己的事件下面来看一下这个函数是怎样设置事件的。

uint8 osal_set_event( uint8 task_id, uint16 event_flag ) 函数原型
{
if ( task_id < tasksCnt )
{
halIntState_t intState;
HAL_ENTER_CRITICAL_SECTION(intState); // Hold off interrupts
tasksEvents[task_id] |= event_flag; // Stuff the event bit(s)只将某一位置1
传到此函数的任务号就是GenericApp_TaskID用户任务号,事件就是自己定义的事件号0x01(不管是8位还是16位最好选择独热码,因为tasksEvents是双字节的数组所以如果定义的是8位事件那么高8位就会补0)。

这样tasksEvents[task_id]里面16位的某一位就会置1,这个1就是自己定义的事件。

这个事件一般只会被执行一次,在系统轮询下某个层如果有事件发生时,系统会这样处理事件
1、events= tasksEvents[task_id];取出事件号
2、tasksEvents[task_id]=0;当前任务下的事件清0
3、events=tasksArr[task_id](idx,events);处理事件
所以在下次任务轮询时如果此事件没有被再设置的话,它就不会再被执行。

HAL_EXIT_CRITICAL_SECTION(intState); // Release interrupts
return ( SUCCESS );
}
else
{
return ( INVALID_TASK );
}
}
1.3下面是系统消息(事件)
其余的是用户可以自己定义的消息。

可以称之为消息事件,用户通过定义一个消息事件然后调用函数
1.2下面是事件EVENT。

相关文档
最新文档