OSAL初始化流程.docx

上传人:b****2 文档编号:16914593 上传时间:2023-04-24 格式:DOCX 页数:19 大小:27.54KB
下载 相关 举报
OSAL初始化流程.docx_第1页
第1页 / 共19页
OSAL初始化流程.docx_第2页
第2页 / 共19页
OSAL初始化流程.docx_第3页
第3页 / 共19页
OSAL初始化流程.docx_第4页
第4页 / 共19页
OSAL初始化流程.docx_第5页
第5页 / 共19页
点击查看更多>>
下载资源
资源描述

OSAL初始化流程.docx

《OSAL初始化流程.docx》由会员分享,可在线阅读,更多相关《OSAL初始化流程.docx(19页珍藏版)》请在冰豆网上搜索。

OSAL初始化流程.docx

OSAL初始化流程

转载OSAL初始化流程

我使用的协议栈版本及例子信息:

ZigBee2006\TexasInstruments\ZStack-1.4.3-1.2.1\Projects\zstack\Samples\SampleApp

首先借用前人的一个说明:

用户自己添加的应用任务程序在Zstack中的调用过程是:

(1).main()执行(在ZMain.c中)

main()--->osal_init_system()

(2).osal_init_system()调用osalInitTasks(),(在OSAL.c中)

osal_init_system()--->osalInitTasks()

(3).osalInitTasks()调用SampleApp_Init(),(在OSAL_SampleApp.c中)

osalInitTasks()--->SampleApp_Init()

在osalInitTasks()中实现了多个任务初始化的设置,其中macTaskInit(taskID++)到ZDApp_Init(taskID++)的几行代码表示对于几个系统运行初始化任务的调用,而用户自己实现的SampleApp_Init()在最后,这里taskID随着任务的增加也随之递增.所以用户自己实现的任务的初始化操作应该在osalInitTasks()中增加.

//----------------------------------------------------------------------------------------------------

1、首先来看下主函数main()

ZSEGintmain(void)//主函数的功能就是完成初始化任务,然后进入OSAL

{

//Turnoffinterrupts

/*关闭中断*/

osal_int_disable(INTS_ALL);

//InitializeHAL

/*初始化硬件*/

HAL_BOARD_INIT();

//Makesuresupplyvoltageishighenoughtorun

/*电压检测,确保芯片能正常工作的电压*/

zmain_vdd_check();

//Initializestackmemory

/*初始化stack存储区*/

zmain_ram_init();

//InitializeboardI/O

/*初始化板载IO*/

InitBoard(OB_COLD);

//InitialzeHALdrivers

/*初始化硬件驱动*/

HalDriverInit();

//InitializeNVSystem

/*初始化NV系统*/

osal_nv_init(NULL);

//Determinetheextendedaddress

/*确定扩展地址(64位IEEE/物理地址)*/

zmain_ext_addr();

//InitializebasicNVitems

/*初始化基本NV条目*/

zgInit();

//InitializetheMAC

/*初始化MAC*/

ZMacInit();

#ifndefNONWK

//SincetheAFisn'tatask,callit'sinitializationroutine

afInit();

#endif

#ifdefLCD_SUPPORTED

HalLcdInit();

#endif

//Initializetheoperatingsystem

/*初始化操作系统*/

osal_init_system();

//Allowinterrupts

/*开启中断*/

osal_int_enable(INTS_ALL);

//Finalboardinitialization

/*最终板载初始化*/

InitBoard(OB_READY);

//HalLcdInit();

//Displayinformationaboutthisdevice

/*显示设备信息*/

zmain_dev_info();

/*DisplaythedeviceinfoontheLCD*/

#ifdefLCD_SUPPORTED

zmain_lcd_init();

#endif

osal_start_system();//NoReturnfromhere没有返回,即进入操作系统!

!

!

}

说明:

初始化各软硬件后进入系统主循环函数。

这里重点是两个函数:

系统初始化函数osal_init_system();系统主循环函数osal_start_system();

下面记录下个人个人对系统初始化流程和系统主循环流程的学习。

这里先记录下系统初始化流程。

//----------------------------------------------------------------------------------------------------

2、系统初始化流程

2.1osal_init_system()——系统初始化函数

byteosal_init_system(void)

{

//InitializetheMemoryAllocationSystem

/*初始化内存分配系统*/

osal_mem_init();

//Initializethemessagequeue

/*初始化系统消息队列*/

osal_qHead=NULL;

#ifdefined(OSAL_TOTAL_MEM)

osal_msg_cnt=0;

#endif

//Initializethetimers

/*初始化定时器*/

osalTimerInit();

//InitializethePowerManagementSystem

/*初始化电源管理系统*/

osal_pwrmgr_init();

//Initializethesystemtasks.

/*初始化系统任务*/

osalInitTasks();//初始化系统任务

//Setupefficientsearchforthefirstfreeblockofheap.

osal_mem_kick();

return(ZSUCCESS);

}

说明:

这里重点是初始化系统任务函数:

osalInitTasks();下面进入系统任务的初始化:

//----------------------------------------------------------------------------------------------------

2.2osalInitTasks();——任务初始化函数

voidosalInitTasks(void)

{

uint8taskID=0;

//osal_mem_alloc()为当前OSAL中的各任务分配存储空间(实际上是一个任务数组),函数返回指向任务缓冲

//区的指针,因此tasksEvents指向该任务数组(任务队列).注意tasksEvents和后面谈到的tasksArr[]里的顺

//序是一一对应的,tasksArr[]中的第i个事件处理函数对应于tasksEvents中的第i个任务的事件.

tasksEvents=(uint16*)osal_mem_alloc(sizeof(uint16)*tasksCnt);

//osal_memset()把开辟的内存全部设置为0;sizeof(uint16)是4个字节,即一个任务

//的长度(同样是uint16定义),乘以任务数量tasksCnt,即全部内存空间

osal_memset(tasksEvents,0,(sizeof(uint16)*tasksCnt));//OSAL.c中定义

macTaskInit(taskID++);//初始化各层任务mac_taskID=0;

nwk_init(taskID++);//nwk_taskID=1;

Hal_Init(taskID++);//Hal_taskID=2;

#ifdefined(MT_TASK)

MT_TaskInit(taskID++);//MT_taskID=3;(ifdefined)

#endif

APS_Init(taskID++);//APS_taskID=4;

ZDApp_Init(taskID++);//ZDAPP_taskID=5;

SampleApp_Init(taskID);//SampleApp_taskID=6;用户创建的任务

}

说明:

任务初始化,就是为系统的各个任务分配存储空间,当然,这个空间初始化时为全0(NULL),然后为各任务分配taskID;这里的顺序要注意.系统主循环函数里tasksEvents[idx]和tasksArr[idx]的idx与这里taskID是一一对应关系。

后面再分析。

指针数组tasksEvents[]里面最终分别指向的是各任务存储空间

指针数组tasksArr[]里面最终分别指向的是各任务事件处理函数

这两个指针数组里面各元素的顺序要一一对应,因为后面需要相应任务调用相应事件处理函数.

对这两个数组的定义请参见后面.

问题:

对于osal_mem_alloc()这个函数返回的是一个指向任务数组的指针,看前人分析的,我还没有去看这个函数。

说明:

那么这里重点是各任务的初始化,MAC层和NWK层的未开源看不到,先记录下用户自己添加的任务初始化函数SampleApp_Init(taskID);

//----------------------------------------------------------------------------------------------------

2.3SampleApp_Init(taskID);——用户应用任务初始化函数

voidSampleApp_Init(uint8task_id)

{

SampleApp_TaskID=task_id;//osal分配的任务ID,这里为6,随着用户添加任务的增多而改变

SampleApp_NwkState=DEV_INIT;//设备状态设定为ZDO层中定义的初始化状态(无连接)

/*初始化应用设备的网络类型,设备类型的改变都要产生一个事件—ZDO_STATE_CHANGE,从字面理解为

//ZDO状态发生了改变。

所以在设备初始化的时候一定要把它初始化为什么状态都没有。

那么它就要去检测

//整个环境,看是否能重新建立或者加入存在的网络。

但是有一种情况例外,就是当NV_RESTORE被设置的

//时候(NV_RESTORE是把信息保存在非易失存储器中),那么当设备断电或者某种意外重启时,由于网络

//状态存储在非易失存储器中,那么此时就只需要恢复其网络状态,而不需要重新建立或者加入网络了*/

SampleApp_TransID=0;//消息发送ID(多消息时有顺序之分)

//Devicehardwareinitializationcanbeaddedhereorinmain()(Zmain.c).

//Ifthehardwareisapplicationspecific-addithere.

//Ifthehardwareisotherpartsofthedeviceadditinmain().

#ifdefined(SOFT_START)

//如果选择了SOFT编译选项,则作为协调器启动

//The"Demo"targetissetuptohaveSOFT_STARTandHOLD_AUTO_START

//SOFT_STARTisacompileoptionthatallowsthedevicetostart

//asacoordinatorifoneisn'tfound.

//Wearelookingatajumper(definedinSampleAppHw.c)tobejumpered

//together-iftheyare-wewillstartupacoordinator.Otherwise,

//thedevicewillstartasarouter.

//if(readCoordinatorJumper())

zgDeviceLogicalType=ZG_DEVICETYPE_COORDINATOR;

//else

//zgDeviceLogicalType=ZG_DEVICETYPE_ROUTER;

#endif//SOFT_START

#ifdefined(HOLD_AUTO_START)

//如果定义了HOLD_AUTO_START选项,则调用层的ZDOInitDevice,按照默认顺

//序网络中的第一个设备作为协调器,其他的设备作为子设备

//HOLD_AUTO_STARTisacompileoptionthatwillsurpressZDApp

//fromstartingthedeviceandwaitfortheapplicationto

//startthedevice.

ZDOInitDevice(0);

#endif

/*设置发送数据的方式和目的地址寻址模式*/

//---------------------------

//周期消息,广播发送

//Setupfortheperiodicmessage'sdestinationaddress周期消息事件

//Broadcasttoeveryone

/*广播到所有设备*/

SampleApp_Periodic_DstAddr.addrMode=(afAddrMode_t)AddrBroadcast;//发送模式(广播)

SampleApp_Periodic_DstAddr.endPoint=SAMPLEAPP_ENDPOINT;//指定端点号EP20

SampleApp_Periodic_DstAddr.addr.shortAddr=0xFFFF;//指定目的网络地址为广播地址

/*单播到一个设备*/

/*WXL_SampleApp_Single_DstAddr.addrMode=(afAddrMode_t)Addr16Bit;;

WXL_SampleApp_Single_DstAddr.endPoint=WXL_SAMPLEAPP_ENDPOINT;*/

//--------------------------

//闪烁消息:

发送到组

//Setupfortheflashcommand'sdestinationaddress-Group1闪烁消息事件

/*设置endpointdescription.*/

SampleApp_Flash_DstAddr.addrMode=(afAddrMode_t)afAddrGroup;//(组寻址)

SampleApp_Flash_DstAddr.endPoint=SAMPLEAPP_ENDPOINT;//EP20

SampleApp_Flash_DstAddr.addr.shortAddr=SAMPLEAPP_FLASH_GROUP;//组号0x0003

//-------------------------

//Fillouttheendpointdescription.

/*定义本设备用来通信的APS层端点描述符*/

SampleApp_epDesc.endPoint=SAMPLEAPP_ENDPOINT;//SampleAppEP描述符的EP号:

20

SampleApp_epDesc.task_id=&SampleApp_TaskID;//SampleAppEP描述符的任务ID:

0

SampleApp_epDesc.simpleDesc

=(SimpleDescriptionFormat_t*)&SampleApp_SimpleDesc;//SampleAppEP简单描述符

SampleApp_epDesc.latencyReq=noLatencyReqs;//延时策略

//RegistertheendpointdescriptionwiththeAF

/*向AF层登记EP描述符*/

/*登记endpointdescription到AF,要对该应用进行初始化并在AF进行登记,告诉应用层有这么一个EP已

经开通可以使用,那么下层要是有关于该应用的信息或者应用要对下层做哪些操作,就自动得到下层的配

合。

*/

afRegister(&SampleApp_epDesc);

//Registerforallkeyevents-Thisappwillhandleallkeyevents

/*登记所有的按键事件*/

RegisterForKeys(SampleApp_TaskID);

//Bydefault,alldevicesstartoutinGroup1为闪烁消息配置的组

/*设定一个新的组*/

SampleApp_Group.ID=0x0003;//组号

osal_memcpy(SampleApp_Group.name,"Group3",7);//设定组名

aps_AddGroup(SAMPLEAPP_ENDPOINT,&SampleApp_Group);//把该组登记添加到APS中

/*如果支持LCD,显示一串字符*/

#ifdefined(LCD_SUPPORTED)

//HalLcdWriteString("SampleApp",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项分别为SAMPLEAPP_PERIODIC_CLUSTERID和SAMPLEAPP_FLASH_CLUSTERID。

用户应用任务初始化大致是:

设置本应用发送数据的方式和目的地址寻址模式,登记注册本应用所用到的端点,以及配置相关发送模式所需的参数.

(个人觉得就此应用来说,ZC,ZR,ZD用到的都是EP20,具体以后再作记录)

//----------------------------------------------------------------------------------------------------

以上为OSAL初始化大体流程,OSAL以及各软硬部件初始化完成后,就进入了系统主循环函数osal_start_system();系统主循环流程个人记录见下篇.

OSAL系统主循环函数:

voidosal_start_system(void)

{

#if!

defined(ZBIT)//不知道是什么

东西

for(;;)//ForeverLoop

#endif

{

uint8idx=0;

Hal_ProcessPoll();//ThisreplacesMT_SerialPoll()andosal_check_timer().

//轮询TIMER与UART

//--------------------------

//执行循环语句:

tasksEvents[idx]是一个指针变量,指向存放任务idx的存储空间,初始化时由

//osal_memset()设为0,只要不为空类型NULL,

//即有相对应任务事件发生,就break跳出循环体,通过下面的程序进行任务事件处理。

//如果为空,执行判断语句,即idx自增,再返回轮询有无各层的任务事件发生。

如果

//执行完循环语句都没有检测到有事件发生,idx=7,进入睡眠。

(对于本例子来说,任务数组里只有七个任务,tasksEvents[0]~tasksEvents[6],tasksEvents[6]就是用户自已添加的任务,idx随着用户添加任务的增多而增大)

do{

if(tasksEvents[idx])//Taskishighestprioritythatisready.

{

break;

}

}while(++idx

//-------------------------

if(idx

{

uint16events;

halIntState_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_id,event)返回的都是这个任务未被处理的事件

HAL_ENTER_CRITICAL_SECTION(intState);

tasksEvents[idx]|=events;//Addbackunprocessedeventstothecurrenttask.

//把刚才返回未处理的任务事件添加加当前任务中再进行处理

//(跳出此if(idx

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > PPT模板 > 其它模板

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1