OSAL初始化作业流程.docx
《OSAL初始化作业流程.docx》由会员分享,可在线阅读,更多相关《OSAL初始化作业流程.docx(21页珍藏版)》请在冰豆网上搜索。
OSAL初始化作业流程
转载OSAL初始化流程
我使用合同栈版本及例子信息:
ZigBee\Texaslnstruments\ZStack-1.4.3-1.2.1\Projects\zstack\Samples\SampleApp
一方面借用前人一种阐明:
顾客自己添加应用任务程序在Zstack中调用过程是:
(1).main()执行(在ZMain.c中)
main()•“>osal_init_system()
(2).osaljnit_system(用osallnitlasks()9(在OSAL.c中)
osal」nit_systein()…>osallnitTasksO
(3).osallnitTasksO调用SampleApp_Init()9(在OSAL_SampleApp.c中)
osallnitTasksO—>SampleApp_Init()
在osallnitTasksO^实现了各种任务初始化设立•其中niacTaskInit(taskID++倒ZDApp_Init(taskID++)几行代码表达对于几种系统运营初始化任务调用•而顾客自己实现SampleAppJnitOlS最后•这里taskll)蘆着任务增长也随之递增•因此顾客自己实现任务初始化操作应当在osallnitTasksO^增长.
//
K一方面来看下主函数main()
ZSEGintmain(void)〃主函数功能就是完毕初始化任务,然后进入OSAL
{
//Turnoffinterrupts
广关闭中断•/
osaljnt_disable(INTS_ALL);
广初始化硬件勺
HAL_BOARDJNIT();
//Makesuresupplyvoltageishighenoughtorun
广电压检测,保证芯片能正常工作电压*/zmain_vdd_check();
//Initializestackmemory
广初始化stack存储区7
zmain_ramJnit();
//InitializeboardI/O
厂初始化板载107
lnitBoard(OB_COLD);
//InitialzeHALdrivers
厂初始化酸件驱动*/
HalDriverlnitO;
//InitializeNVSystem
广初始化NV系统•/
osal_nvjnit(NULL);
//Determinetheextendedaddress
广拟定扩展地址(6他IEE曰物理地址)T
zmain_ext_addr();
//InitializebasicNVitems
/*初始化基本NV条目•/
zglnitO;
广初始化MAC-/
ZMacInitO;
#ifndefNONWK
//SincetheAFisn*tatask,callit'sinitializationroutineaflnitQ;
#endif
#ifdefLCD_SUPPORTED
HalLcdlnitO;
#endif
//Initializetheoperatingsystem
/*初始化操作系统*/
osal_init_system();
//Allowinterrupts
/*启动中断
osaljnt_enable(INTS_ALL);
//Finalboardinitialization
广最后板载初始化
lnitBoard(OB_READY);
//HalLcdlnitQ;
//Displayinformationaboutthisdevice
广显示设备信息•/
zmain_devjnfo();
rDisplaythedeviceinfoontheLCD•/#ifdefLCDSUPPORTED
zmainjcd_init();
#endif
osal_start_system();//NoReturnfromhere没有返回,即进入操作系统!
!
!
}
阐明:
初始化各软硬件后进入系统主循环函数.
这里垂点是两个函数:
系统初始化函数osal_init_system();系统主循环函数
osal_start_system();
下面记录下个人个人对系统初始化流程和系统主循环流程学习.这里先记录下系统初始化流
程.
//
2、系统初始化流程
2.1osalJniLsystem()——系统初始化函数
byteosal_init_system(void)
{
//InitializetheMemoryAllocationSystem
厂初始化内存分派系统
osaljnemJnit();
IIInitializethemessagequeue
•广初始化系统消息队列
osaLqHead=NULL;
#ifdefined(OSAL_TOTAL_MEM)
osal_msg_cnt=0;
#endif
osalTimerlnitO;
//InitializethePowerManagementSystem
广初始化电源管理系统T
osal_pwrmgrjnit();
//Initializethesystemtasks・
厂初始化系统任务
osallnitTasksO;/砌始化系统任务
IISetupefficientsearchforthefirstfreeblockofheap・
osaljnem_kick();
return(ZSUCCESS);
}
闸明:
这里重点是初始化系统任务函数:
osallnitTasksO;下面进入系统任务初始化:
II
2.2osallnitTasksO;——务初始化函数
voidosallnitTasks(void)
{
uint8taskID=0;
//osal_mem_alloc()>j当前OSAL中各任务分派存储空间(事实上是一种任务数组),函数返回指向任务缓冲
〃区指针,因而tasksEvents指向该任务数组(任务队列).注意tasksEvents和背面谈到tasksArr[]里顺
〃序是一一相应,tasksArr[冲第i个事件解决函数相应于tasksEvents中第i个任务事件.
tasksEvents=(uint16JosalmemalloMsizeof(uint16)*tasksCnt);
//osal_memset()把开辟内存所有设立为0;sizeof(uint16)是4个字节,即一种任务
〃长度(同样是uint16定义人乘以任务数fttasksCnt,即所有内存空间
osaljnemset(tasksEvents,0,(sizeof(uint16)*tasksCnt));//OSAL.c中定义
macTasklnit(tasklD++);
〃初始化各层任务macJasklD=0;
nwkjnit(tasklD++);
//nwk_tasklD=1;
Haljnit(tasklD++);
//HalJasklD=2;
#ifdefined(MT_TASK)
MT_Tasklnit(taskID卄);
〃MT_tasklD=:
3;(ifdefined)
#endif
APSJnit(taskID卄);
//APSJasklD=4;
ZDApp」nit(tasklD++)•
//ZDAPPjasklD=5;
SampleApp_lnit(taskID)•
//SampleAppJasklD=6;J®客创立任务
阐明:
任务初始化.就是为系统各个任务分派存储空间,固然,这个空间初始化时为全O(NULL),然后为各任务分派taskID;这里顺序要注意•系统主循环函数里tasksEvents[idx]和tasksArr[idxjidx与这里taskID是一一相应关系。
背面再分析。
指针数组tasksEvents[]里面最后分别指向是各任务存储空间
指针数组tasksArr[]里面最后分别指向是各任务事件解决函数
这两个指针数组里面各元責顺序要一一相应,由于背面需要相应任务调用相应事件解决函数.
对这两个数组定义请参见背面.
问题:
对于osaLmem_alloc()这个函数返回是一种指向任务数组指针,看前人分析,我还没有去看这个函数•
阐明:
那么这里重点是各任务初始化,MAC层和NWK层未开源看不到,先记录下顾客自己添加任务初始化函数SampleApp_lnit(taskID);
//
2.3SampleApp_lnit(taskID);——顾客应用任务初始化函数
voidSampleApp」nit(uint8taskjd)
SampleApp_TasklD=taskJd;//osal分派任务ID,这里为6,随着顾客添加任务增多而变化
SampleApp_NwkState=DEVJNIT;//设备状态设定为ZDO层中定义初始化状态(无连接)
广初始化应用设备网络类型,设备类型变化都要产生一种事件一ZDO_STATE_CHANGE,从字面理解为
//ZDO状态发生了变化。
因此在设备初始化时候一定要把它初始化为什么状态都没有。
那么它就要去检测”整个环境,看与否能垂新建立或者加入存在网络。
但是有一种状况例外,就是当NV_RESTORE被设立〃时候(NV_RESTORE是把信息保存在非易失存储器中),那么当设备断电或者某种意外重启时,由于网络
〃状态存储在非易失存储器中,那么此时就只需要恢复其网络状态,而不需要重新建立或者加入网络了"
SampleApp^TransID=0;//消息发送ID(多消息时有顺序之分)
//Devicehardwareinitializationcanbeaddedhereorinmain()(Zmain.c).
//Ifthehardwareisapplicationspecific-addithere・
//Ifthehardwareisotherpartsofthedeviceadditinmain()・
#ifdefined(SOFT_START)
〃如果选取了SOFT编译选项,则作为协调器启动
//TheMDemoutargetissetuptohaveSOFT_STARTandHOLD_AUTO_START
//SOFT_STARTisacompileoptionthatallowsthedevicetostart
//asacoordinatorifoneisn'tfound・
IIWearelookingatajumper(definedinSampleAppHw.c)tobejumpered
//together・iftheyare・wewillstartupacoordinator.Otherwise,
//thedevicewillstartasarouter.
//if(readCoordinatorJumperO)
zgDeviceLogicalType=ZG_DEVICETYPE_COORDINATOR;
//else
//zgDeviceLogicalType=ZG_DEVICETYPE_ROUTER;
#endif//SOFT_START
#ifdefined(HOLD_AUTO_START)
〃如果定义了HOLD_AUTO_START选项,贝!
I调用层ZDOInitDevice,按照默认顺
//序网络中第一种设备作为协调器,其她设备作为子设备
//HOLDAUTOSTARTisacompileoptionthatwillsurpressZDApp
//fromstartingthedeviceandwaitfortheapplicationto
//startthedevice・
ZDOInitDevice(O);
#endif
/*设立发送数据方式和目地址寻址模式*/
//
〃周期消息,广播发送
//Setupfortheperiodicmessage'sdestinationaddress周期消息事件
//Broadcasttoeveryone
广广播到所有设备*/
SampleApp_Periodic_DstAddr.addrMode=(afAddrModeJ)AddrBroadcast$〃发送模式(广播)
SampleApp__Periodic_DstAddr.endPoint=SAMPLEAPP_ENDPOINT;//指定端点号EP20
SampleApp_Periodic_DstAddr.addr.shortAddr=OxFFFF;//指定目网络地址为广播地址
广单播到一种设备*/
/*WXL_SampleApp_Single_DstAddr.addrMode=(afAddrModeJ)Addr16Bit;;
WXL_SampleApp_Single_DstAddr.endPoint=WXL_SAMPLEAPP_ENDPOINT;・/
//
〃闪烁消息:
发送到组
IISetupfortheflashcommand'sdestinationaddress•Groupl闪烁消息爭件
/*设立endpointdescription.*/
SampleApp_Flash_DstAddr.addrMode=(afAddrModet)afAddrGroup;II(组寻址)
SampleApp_Flash_DstAddr.endPoint=SAMPLEAPP_ENDPOINT;Z/EP20
SampleApp_Flash_DstAddr.addr.shortAddr=SAMPLEAPP_FLASH_GROUP;〃组号0x0003
II
//Fillouttheendpointdescription・
广定义本设备用来通倍APS层端点描述符*/
SampleAppepDesc.endPoint=SAMPLEAPP_ENDPOINT:
//SampleAppEP描述符EP号:
20
SampleApp_epDesc.task_id=&SampleAppTaskID;//SampleAppEP描述符任务ID:
0
SampleAppepDesc.simpleDesc
=(SimpleDescriptionFormat_t冷&SampleAppSimpleDesc;//SampleAppEP简朴描
述符
SampleAppepDesc.latencyReq=noLatencyReqs;〃延时方略
//RegistertheendpointdescriptionwiththeAF
广向AF层登记EP描述符•/
/*登记endpointdescription到AF,要对该应用进行初始化并在AF进行登记,告诉应用层有这样一种EP已
经开通可以使用,那么下层要是关于于该应用信息或者应用要对下层做哪些操作,就自动得到下层配合・*/afRegister(&SampleApp_epDesc);
//Registerforallkeyevents・Thisappwillhandleallkeyevents
广登记所有按键事件•/
RegisterForKeys(SampleApp_TasklD);
//Bydefault,alldevicesstartoutinGroup1为闪烁消息配备组
广设定一种新组
SampleAppGroup.lD=0x0003;〃组号
osal_memcpy(SampleApp^Group.name,''Group3Mf7);〃设定组名
aps_AddGroup(SAMPLEAPP_ENDPOINT,&SampleApp^Group);〃把该组登记添加到APS中广如果支持LCD,显示一串字符•/
#ifdefined(LCD_SUPPORTED)
//HalLcdWriteString(MSampleAppMfHAL_LCD_LINE_1);Print8(HAL^LCD_LINE_2,20;,SampleAppM11);
#endif
}
阐明:
在SampleAPP例子中,应用层提供了节点间两种逻辑关系:
一种是周期性消息发送,另一种是Flash消息发送。
我个人以为就是两个簇,例如节点1EP20与节点2EP20通信,何以单播,广播,间接,组传递),这两种逻辑关系屈于两节点EP20简朴描述符下簇列表元素.且可以看到SampleApp_SendPeriodicMessage(void)与SampleApp_SendFlashMessage()下clusterlD项分别为SAMPLEAPP_PERIODIC_CLUSTERID和SAMPLEAPP_FLASH_CLUSTERID.
顾客应用任务初始化大体是:
设立本应用发送数据方式和目地址寻址模式,登记注册本应用所用
到端点,以及配备有关发送模式所需参数.
(个人觉得就此应用来说,ZC,ZR,ZD用到都是EP20,详细后来再作记录)
II
以上为OSAL初始化大体流程,OSAL以及各软锁部件初始化完毕后,就进入了系统主循环函数osal_start_system();系统主循环流程个人记录见下篇.
OSAL系统主循环函数:
voidosal_start_system(void)
{
#ifIdefined(ZBIT)//不懂得是什么【工冻西
for(;;)//ForeverLoop
#endif
{
uint8idx=0;
HalProcessPollO^/ThisreplacesMT_SerialPoll()andosal_check_timer().
〃轮询TIMER与UART
//
〃执行循环语句:
tasksEvents[idx]是一种指针变此捋向存储任务idx存储空间,初始化时由
//osal_memset()设为0.只要不为空类型NULL,
〃即有相相应任务事件发生,就break跳出循环体,通过下面程序进行任务事件解决.
〃如果为空,执行判斷语句,即idx自増,再返回轮询有无各层任务事件发生。
如果
〃执行完循环语句都没有检测到有事件发生,idx=7,进入睡眠.(对于本例子来说,任务数组里只有七个
任务.tasksEvents[O]〜tasksEvents[6],tasksEvents⑹就是顾客自已添加任务・idx随着顾客添加任务增多而增大)
do{
if(tasksEvents[idx])//Taskishighestprioritythatisready.
break;
}
}while(++idx//
if(idxvtasksCnt)
{
uint16events;
hallntState_tintState”/中断位状态
HAL_ENTER_CRITICAL_SECTION(intState);//中断临界状态:
保存先前中断状态,然后关中断
events=tasksEvents[idx];//uint16events;相应有事件发生任务
tasksEvents(idx)=0;//CleartheEventsforthistask.NULL
HAL_EXIT_CRITICAL_SECTION(intState);〃跳出中断临界状态:
恢复先前中断状态
events=(tasksArr[idx])(idx,events);〃调用相相应任务事件解决函数解决,各类爭件解决
函
〃数M(task」d,event)返回都是这个任务未被解决事件
HAL_ENTER_CRITICAL_SECTION(intState);
tasksEvents[idx]|=events;//Addbackunprocessedeventstothecurrenttask・
"把刚才返回未解决任务事件添加加当前任务中再进行解决
//(跳出此if(idx(tasksEvents(idx))判斷并解决)
HAL_EXIT_CRITICAL_SECTION(intState);
#ifdefined(POWER_SAVING)
else//Completepassthroughalltaskeventswithnoactivity?
{
osal_pwrmgr_powerconserve();//Puttheprocessor/systemintosleep
}
#endif
}
}
阐明:
(DOSAL谓用HaLProcessPollO;来轮询UART与TIMER,涉及HAL层,晚点总结.
(2)HAL_ENTER_CRITICAL_SECTION(intState);与HAL_EXIT_CRITICAL_SECTION(intState);见1;
⑶events=tasksEvents[idx];tasksEvents[idx]=0;见2;
(4)events=(tasksArr[idx])(idx,events);见3;
(5)tasksEvents[idx]|=events;见4;
//
//
1.HAL_ENTER_CRITICAL_SECTION(intState)与HAL_EXIT_CRITICAL_SECTION(intState)
定义在halmcu.h中,如下:
*InterruptMacros
*
*/
#defineHAL_ENABLEJNTERRUPTS()st(EA=:
1;)〃开中断
#defineHAL_DISABLEJNTERRUPTS()st(EA=0;)〃关中断
#defineHAL_INTERRUPTS_ARE_ENABLED()(EA)
typedefunsignedcharhallntStateJ;〃中断位状态
〃中断临界状态:
把原先中断状态EA赋给X,然后关中断;以便背面可以恢复原先中断状态
#defineHAL_ENTER_CRITICAL_SECTION(x)st(x=EA;HAL_DISABLEJNTERRUPTS();)