OSAL初始化流程_第1页
OSAL初始化流程_第2页
OSAL初始化流程_第3页
OSAL初始化流程_第4页
OSAL初始化流程_第5页
已阅读5页,还剩11页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

1、转载 OSAL初始化流程我使用的协议栈版本及例子信息:ZigBee2006Texas InstrumentsZStack-1.4.3-1.2.1ProjectszstackSamplesSampleApp首先借用前人的一个说明:用户自己添加的应用任务程序在Zstack中的调用过程是:(1).main()执行(在中)main() -> osal_init_system()(2). osal_init_system()调用osalInitTasks(), (在中)osal_init_system() -> osalInitTasks()(3). osalInitTasks()调用Sam

2、pleApp_Init() , (在中)osalInitTasks() -> SampleApp_Init()在osalInitTasks()中实现了多个任务初始化的设置,其中macTaskInit( taskID+ )到ZDApp_Init( taskID+ )的几行代码表示对于几个系统运行初始化任务的调用,而用户自己实现的SampleApp_Init()在最后,这里taskID随着任务的增加也随之递增.所以用户自己实现的任务的初始化操作应该在osalInitTasks()中增加./-1、首先来看下主函数main()ZSEG int main( void ) /主函数的功能就是完成初始

3、化任务,然后进入OSAL/ Turn off interrupts/*关闭中断*/osal_int_disable( INTS_ALL );/ Initialize HAL/*初始化硬件*/HAL_BOARD_INIT();/ Make sure supply voltage is high enough to run/*电压检测,确保芯片能正常工作的电压*/zmain_vdd_check();/ Initialize stack memory/*初始化stack存储区*/zmain_ram_init();/ Initialize board I/O/*初始化板载IO*/InitBoard(

4、OB_COLD );/ Initialze HAL drivers/*初始化硬件驱动*/HalDriverInit();/ Initialize NV System/*初始化NV系统*/osal_nv_init( NULL );/ Determine the extended address/*确定扩展地址(64位IEEE/物理地址)*/zmain_ext_addr();/ Initialize basic NV items/*初始化基本NV条目*/zgInit();/ Initialize the MAC/*初始化MAC*/ZMacInit();#ifndef NONWK/ Since th

5、e AF isn't a task, call it's initialization routineafInit();#endif#ifdef LCD_SUPPORTEDHalLcdInit();#endif/ Initialize the operating system/*初始化操作系统*/osal_init_system();/ Allow interrupts/*开启中断*/osal_int_enable( INTS_ALL );/ Final board initialization/*最终板载初始化*/InitBoard( OB_READY );/HalLcdIn

6、it();/ Display information about this device/*显示设备信息*/zmain_dev_info();/* Display the device info on the LCD */#ifdef LCD_SUPPORTEDzmain_lcd_init();#endifosal_start_system();/ No Return from here 没有返回,即进入操作系统!说明:初始化各软硬件后进入系统主循环函数。 这里重点是两个函数:系统初始化函数 osal_init_system(); 系统主循环函数 osal_start_system(); 下面

7、记录下个人个人对系统初始化流程和系统主循环流程的学习。这里先记录下系统初始化流程。/-2、系统初始化流程2.1osal_init_system()系统初始化函数byte osal_init_system( void )/ Initialize the Memory Allocation System/*初始化内存分配系统*/osal_mem_init();/ Initialize the message queue/*初始化系统消息队列*/osal_qHead = NULL;#if defined( OSAL_TOTAL_MEM )osal_msg_cnt = 0;#endif/ Initia

8、lize the timers/*初始化定时器*/osalTimerInit();/ Initialize the Power Management System/*初始化电源管理系统*/osal_pwrmgr_init();/ Initialize the system tasks./*初始化系统任务*/osalInitTasks(); /初始化系统任务/ Setup efficient search for the first free block of heap.osal_mem_kick();return ( ZSUCCESS );说明:这里重点是初始化系统任务函数:osalInitT

9、asks(); 下面进入系统任务的初始化:/- osalInitTasks(); 任务初始化函数void osalInitTasks( void )uint8 taskID = 0; /osal_mem_alloc()为当前OSAL中的各任务分配存储空间(实际上是一个任务数组),函数返回指向任务缓冲 /区的指针,因此tasksEvents指向该任务数组(任务队列).注意tasksEvents和后面谈到的tasksArr里的顺/序是一一对应的, tasksArr 中的第i个事件处理函数对应于tasksEvents中的第i个任务的事件.tasksEvents = (uint16 *)osal_me

10、m_alloc( sizeof( uint16 ) * tasksCnt); /osal_memset()把开辟的内存全部设置为0;sizeof( uint16 )是4个字节,即一个任务 /的长度(同样是uint16定义),乘以任务数量tasksCnt,即全部内存空间osal_memset( tasksEvents, 0, (sizeof( uint16 ) * tasksCnt); macTaskInit( taskID+ ); /初始化各层任务 mac_taskID=0;nwk_init( taskID+ ); /nwk_taskID=1;Hal_Init( taskID+ ); /Hal

11、_taskID=2;#if defined( MT_TASK )MT_TaskInit( taskID+ ); /MT_taskID=3;(if defined)#endifAPS_Init( taskID+ ); /APS_taskID=4;ZDApp_Init( taskID+ ); /ZDAPP_taskID=5;SampleApp_Init( taskID ); /SampleApp_taskID=6;用户创建的任务说明:任务初始化,就是为系统的各个任务分配存储空间,当然,这个空间初始化时为全0(NULL),然后为各任务分配taskID;这里的顺序要注意.系统主循环函数里tasksEv

12、ents idx和tasksArr idx的idx与这里taskID是一一对应关系。后面再分析。指针数组tasksEvents 里面最终分别指向的是各任务存储空间指针数组tasksArr 里面最终分别指向的是各任务事件处理函数这两个指针数组里面各元素的顺序要一一对应,因为后面需要相应任务调用相应事件处理函数.对这两个数组的定义请参见后面.问题:对于osal_mem_alloc()这个函数返回的是一个指向任务数组的指针,看前人分析的,我还没有去看这个函数。说明:那么这里重点是各任务的初始化,MAC层和NWK层的未开源看不到,先记录下用户自己添加的任务初始化函数SampleApp_Init( ta

13、skID ); /-2.3 SampleApp_Init( taskID ); 用户应用任务初始化函数void SampleApp_Init( uint8 task_id )SampleApp_TaskID = task_id; /osal分配的任务ID,这里为6,随着用户添加任务的增多而改变SampleApp_NwkState = DEV_INIT; /设备状态设定为ZDO层中定义的初始化状态(无连接)/*初始化应用设备的网络类型,设备类型的改变都要产生一个事件ZDO_STATE_CHANGE,从字面理解为/ZDO状态发生了改变。所以在设备初始化的时候一定要把它初始化为什么状态都没有。那么它

14、就要去检测/整个环境,看是否能重新建立或者加入存在的网络。但是有一种情况例外,就是当NV_RESTORE被设置的/时候(NV_RESTORE是把信息保存在非易失存储器中),那么当设备断电或者某种意外重启时,由于网络/状态存储在非易失存储器中,那么此时就只需要恢复其网络状态,而不需要重新建立或者加入网络了*/SampleApp_TransID = 0; /消息发送ID(多消息时有顺序之分) / Device hardware initialization can be added here or in main() (Zmain.c)./ If the hardware is applicati

15、on specific - add it here./ If the hardware is other parts of the device add it in main().#if defined ( SOFT_START ) /如果选择了SOFT编译选项,则作为协调器启动/ The "Demo" target is setup to have SOFT_START and HOLD_AUTO_START/ SOFT_START is a compile option that allows the device to start/ as a coordinator

16、if one isn't found./ We are looking at a jumper (defined in SampleAppHw.c) to be jumpered/ together - if they are - we will start up a coordinator. Otherwise,/ the device will start as a router./ if ( readCoordinatorJumper() ) zgDeviceLogicalType = ZG_DEVICETYPE_COORDINATOR; /else /zgDeviceLogic

17、alType = ZG_DEVICETYPE_ROUTER;#endif / SOFT_START#if defined ( HOLD_AUTO_START ) /如果定义了HOLD_AUTO_START选项,则调用层的ZDOInitDevice,按照默认顺 /序网络中的第一个设备作为协调器,其他的设备作为子设备 / HOLD_AUTO_START is a compile option that will surpress ZDApp/ from starting the device and wait for the application to/ start the device.ZDO

18、InitDevice(0);#endif/* 设置发送数据的方式和目的地址寻址模式*/-/周期消息,广播发送/ Setup for the periodic message's destination address 周期消息事件/ Broadcast to everyone/*广播到所有设备*/SampleApp_Periodic_DstAddr.addrMode = (afAddrMode_t)AddrBroadcast ; /发送模式(广播)SampleApp_Periodic_DstAddr.endPoint = SAMPLEAPP_ENDPOINT; /指定端点号EP20Sa

19、mpleApp_Periodic_DstAddr.addr.shortAddr = 0xFFFF; /指定目的网络地址为广播地址/*单播到一个设备*/* WXL_SampleApp_Single_DstAddr.addrMode = (afAddrMode_t)Addr16Bit; WXL_SampleApp_Single_DstAddr.endPoint = WXL_SAMPLEAPP_ENDPOINT;*/-/闪烁消息:发送到组 / Setup for the flash command's destination address - Group1 闪烁消息事件/*设置 endpo

20、int description.*/SampleApp_Flash_DstAddr.addrMode = (afAddrMode_t)afAddrGroup; /(组寻址)SampleApp_Flash_DstAddr.endPoint = SAMPLEAPP_ENDPOINT; /EP20SampleApp_Flash_DstAddr.addr.shortAddr = SAMPLEAPP_FLASH_GROUP; /组号0x0003/- / Fill out the endpoint description./*定义本设备用来通信的APS层端点描述符*/SampleApp_epDesc.en

21、dPoint = SAMPLEAPP_ENDPOINT; /SampleApp EP描述符的EP号:20SampleApp_epDesc.task_id = &SampleApp_TaskID; /SampleApp EP描述符的任务ID:0 = (SimpleDescriptionFormat_t *)&SampleApp_SimpleDesc; /SampleApp EP简单描述符SampleApp_epDesc.latencyReq = noLatencyReqs; /延时策略/ Register the endpoint description with the AF/

22、*向AF层登记EP描述符*/*登记endpoint description 到AF,要对该应用进行初始化并在AF进行登记,告诉应用层有这么一个EP已经开通可以使用,那么下层要是有关于该应用的信息或者应用要对下层做哪些操作,就自动得到下层的配合。*/afRegister( &SampleApp_epDesc );/ Register for all key events - This app will handle all key events/*登记所有的按键事件*/RegisterForKeys( SampleApp_TaskID );/ By default, all device

23、s start out in Group 1 为闪烁消息配置的组/*设定一个新的组*/SampleApp_Group.ID = 0x0003; /组号osal_memcpy( SampleApp_G, "Group 3", 7 ); /设定组名aps_AddGroup( SAMPLEAPP_ENDPOINT, &SampleApp_Group ); /把该组登记添加到APS中/*如果支持LCD,显示一串字符*/#if defined ( LCD_SUPPORTED )/HalLcdWriteString( "SampleApp"

24、, HAL_LCD_LINE_1 );Print8(HAL_LCD_LINE_2,20,"SampleApp",1);#endif说明: 在SampleAPP例子中,应用层提供了节点间两种逻辑关系:一种是周期性消息发送,另一种是Flash消息发送。我个人认为就是两个簇,比如节点1的EP20与节点2的EP20通信,(可以单播,广播,间接,组传递),这两种逻辑关系属于两节点的EP20简单描述符下簇列表元素. 且可以看到SampleApp_SendPeriodicMessage( void )与SampleApp_SendFlashMessage( )下的clusterID项分别

25、为SAMPLEAPP_PERIODIC_CLUSTERID和 SAMPLEAPP_FLASH_CLUSTERID。 用户应用任务初始化大致是:设置本应用发送数据的方式和目的地址寻址模式,登记注册本应用所用到的端点,以及配置相关发送模式所需的参数.(个人觉得就此应用来说,ZC,ZR,ZD用到的都是EP20,具体以后再作记录)/-以上为OSAL初始化大体流程,OSAL以及各软硬部件初始化完成后,就进入了系统主循环函数osal_start_system(); 系统主循环流程个人记录见下篇.OSAL系统主循环函数:void osal_start_system( void )#if !defined (

26、 ZBIT ) /不知道是什么东西for(;) / Forever Loop#endif uint8 idx = 0; Hal_ProcessPoll();/ This replaces MT_SerialPoll() and osal_check_timer(). /轮询TIMER与UART/-/执行循环语句:tasksEventsidx是一个指针变量,指向存放任务idx的存储空间,初始化时由/osal_memset()设为0,只要不为空类型NULL,/即有相对应任务事件发生,就break跳出循环体,通过下面的程序进行任务事件处理。/如果为空,执行判断语句,即idx自增,再返回轮询有无各层的

27、任务事件发生。如果/执行完循环语句都没有检测到有事件发生,idx=7,进入睡眠。(对于本例子来说,任务数组里只有七个任务,tasksEvents0tasksEvents6,tasksEvents6就是用户自已添加的任务,idx随着用户添加任务的增多而增大) do if (tasksEventsidx)/ Task is highest priority that is ready. break; while (+idx < tasksCnt); /tasksCnt=7(针对本例子,随着用户应用任务增多而增大)/- if (idx < tasksCnt) uint16 events;

28、 halIntState_t intState;/中断位状态 HAL_ENTER_CRITICAL_SECTION(intState);/中断临界状态:保存先前中断状态,然后关中断 events = tasksEventsidx;/uint16 events;对应有事件发生的任务 tasksEventsidx = 0;/ Clear the Events for this task. NULL HAL_EXIT_CRITICAL_SECTION(intState);/跳出中断临界状态:恢复先前中断状态 events = (tasksArridx)( idx, events ); /调用相对应的

29、任务事件处理函数处理,各类事件处理函 /数M(task_id,event)返回的都是这个任务未被处理的事件 HAL_ENTER_CRITICAL_SECTION(intState); tasksEventsidx |= events; / Add back unprocessed events to the current task. /把刚才返回未处理的任务事件添加加当前任务中再进行处理 /(跳出此if(idx < tasksCnt)循环再进行if (tasksEventsidx)判断并处理) HAL_EXIT_CRITICAL_SECTION(intState); #if defin

30、ed( POWER_SAVING ) else / Complete pass through all task events with no activity? osal_pwrmgr_powerconserve();/ Put the processor/system into sleep #endif 说明:(1)OSAL调用Hal_ProcessPoll(); 来轮询UART与TIMER,涉及HAL层,晚点总结.(2)HAL_ENTER_CRITICAL_SECTION(intState); 与HAL_EXIT_CRITICAL_SECTION(intState); 见1;(3)eve

31、nts = tasksEventsidx; tasksEventsidx = 0;见2;(4) events = (tasksArridx)( idx, events ); 见3;(5)tasksEventsidx |= events; 见4;/-/-1、HAL_ENTER_CRITICAL_SECTION(intState)与HAL_EXIT_CRITICAL_SECTION(intState)定义在hal_mcu.h中,如下:/* -* Interrupt Macros* -*/#define HAL_ENABLE_INTERRUPTS() st( EA = 1; ) /开中断#defin

32、e 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_SE

33、CTION(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中:* This macro is for use by other macros to form a fully valid C statement.* Without this, the if/else conditionals c

34、ould show unexpected behavior.#define st(x) do x while (_LINE_ = -1)/-/-2、events = tasksEventsidx; tasksEventsidx = 0; 个人认为,tasksEvents 是一个指针数组(但是在协议栈里对这个“数组”的定义我还没有找到,只是在OSAL_SampleApp.c下有这么一个声明:uint16 *tasksEvents;以及系统任务初始函数下对tasksEvents的定义),内部各元素都是指向uint16类型变量的指针变量(对于本例子来说内部各元素即tasksEvents0tasksE

35、vents6;tasksEvents0指向任务1的存储空间),对events的声明也是 uint16 events;。这里把有事件发生的任务idx的存储空间的地址赋给events。然后清除任务idx的事件 tasksEventsidx = 0,(指针变量值为NULL)./-/-3、events = (tasksArridx)( idx, events ); 任务idx的事件处理函数-首先看下对tasksArr 的定义:const pTaskEventHandlerFntasksArr = /数组tasksArr 有7个元素(MT defined)macEventLoop, /MAC层任务事件处

36、理函数nwk_event_loop, /NWK层任务事件处理函数Hal_ProcessEvent, /PHY层事件处理函数#if defined( MT_TASK )MT_ProcessEvent, /MT任务事件处理函数#endifAPS_event_loop, /APS层任务事件处理函数ZDApp_event_loop, /ZDO任务事件处理函数SampleApp_ProcessEvent /用户应用任务事件处理函数;-再来看下对pTaskEventHandlerFn 的定义:(OSAL_Tasks.h中)typedef unsigned short (*pTaskEventHandler

37、Fn)( unsigned char task_id, unsigned short event );/前面有个typedef,把pTaskEventHandlerFn声明成一种函数指针类型的别名/这种函数指针指向M(task_id,event)这种类型的函数(即各任务的事件处理函数)/如果用这个别名来生成一个指向函数的指针X,则当X获得函数的地址后,就可以像调用/原来函数一样来使用这个函数指针X(task_id,event),如上面的pTaskEventHandlerFn tasksArr /因此tasksArr 是一个指针数组,其内部的各元素都是指针,从OSAL_SampleApp.c中对

38、tasksArr /的定义我们可以知道macEventLoop,nwk_event_loop一直到SampleApp_ProcessEvent这些元素都是/指针变量,最终都是指向M(task_id,event)这种类型的函数,也就是各层的事件处理函数。/另外我觉得,就像 pTaskEventHandlerFn tasksArr ;之后可以通过tasksArr 直接/调用tasksArr (task_id,event),也可以通过tasksArr 里面的元素直接调用/macEventLoop(task_id,event).SampleApp_ProcessEvent(task_id,event)

39、,而这些任务事件处理/函数都是uint16类型的.因此osal_start_system()里可以events = (tasksArridx)( idx, events );events也是uint16类型的。语法上来解释我自己都一团雾水了,个人想法,不一定正确/typedef unsigned short uint16;/typedef unsigned char uint8;-这里events = (tasksArridx)( idx, events ); 是因为每一个任务的事件处理函数返回的都是这个任务没有被处理完成的事件。比如说用户应用任务的事件处理函数:SampleApp_Proce

40、ssEvent( uint8 task_id, uint16 events ),如下:每个任务都有不同的事件,因此在进行事件的处理前要进行判断,对于SampleApp大事件1_接收系统消息:(a)_按键小事件(包含了组发送flash消息事件和进组退组事件) (b)_接收数据小事件 (c)_设备网络状态变化小事件大事件2_向外发送消息:(a)_发送 periodic 消息 下面的SampleApp_ProcessEvent()就是通过上面的顺序对用户添加的应用任务进行事件的轮询:uint16 SampleApp_ProcessEvent( uint8 task_id, uint16 events

41、 )afIncomingMSGPacket_t *MSGpkt; /接收到的消息/*如果大事件是接收系统消息*/ /则接收系统消息再进行判断if ( events & SYS_EVENT_MSG ) MSGpkt = (afIncomingMSGPacket_t *)osal_msg_receive( SampleApp_TaskID ); /接收属于本应用任务SampleApp的消息(SampleApp_TaskID标记。 while ( MSGpkt ) /接收到 switch ( MSGpkt->hdr.event ) /系统消息的进一步判断 / Received when

42、 a key is pressed/*小事件:按键事件*/ 如果一个OSAL任务已经被登记注册,那么任何键盘事件都将接受一个KEY_CHANGE事件信息。 case KEY_CHANGE: /#define KEY_CHANGE 0xC0 -Key Events SampleApp_HandleKeys( (keyChange_t *)MSGpkt)->state, (keyChange_t *)MSGpkt)->keys ); break; / Received when a messages is received (OTA:over the air) for this end

43、point /*小事件:接收数据事件*/ 接收数据事件,调用函数AF_DataRequest()接收数据 case AF_INCOMING_MSG_CMD:/ #define AF_INCOMING_MSG_CMD 0x 1A -Incoming MSG type message SampleApp_MessageMSGCB( MSGpkt ); /调用回调函数对收到的数据进行处理 break; / Received whenever the device changes state in the network/*小事件:设备网络状态变化事件*/ 只要网络状态发生改变,就通过ZDO_STAT

44、E_CHANGE事件通知所有的任务,注意,是所有任务都会收到这消息。 case ZDO_STATE_CHANGE: /#define ZDO_STATE_CHANGE 0xD1 -ZDO has changed the device's network state SampleApp_NwkState = (devStates_t)(MSGpkt->hdr.status); /获取设备当前状态 if ( (SampleApp_NwkState = DEV_ZB_COORD) | (SampleApp_NwkState = DEV_ROUTER) | (SampleApp_NwkS

45、tate = DEV_END_DEVICE) ) / Start sending the periodic message in a regular interval. /*按一定间隔启动定时器*/ /这个定时器是为发送周期信息设置的,我觉得因为在这个例子中,用户自己添加的任务,只有两个事件是用于向外发送消息的,一个是发送flash闪烁消息,属于组寻址,而另一个是发送periodic周期消息,属于广播;这里是一个设备的网络状态发生了变化,必须要告诉同一网络中的其它设备,因此要进行广播通知其它设备发送的消息中应该会包括本设备的类型。不知道这样理解对不对管它的,以后会明白的/更新:这个定时器只是为发送周期信息开启的,设备启动初始化后从这里开始触发第一个周期信息的发送,然后周而复始下去. osal_start_timerEx( SampleApp_TaskID, SAMPLEAPP_SEND_PERIODIC_MSG_EVT, SAMPLEAPP_SEND_PERIODIC_MSG_TIMEOUT ); else / Device is no longer in the network break; default: break

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论