zigbee2007中工程执行流程(初始化部分) 小记
来源:互联网 发布:斗鱼手游直播软件下载 编辑:程序博客网 时间:2024/06/06 17:01
废话什么的就不罗嗦了,直接开说
首先找到工程的主文件,即整个工程的入口
ZMain\ZMain.c
进入主函数 int main() 如下
int main( void ){ // Turn off interrupts osal_int_disable( INTS_ALL ); // Initialization for board related stuff such as LEDs HAL_BOARD_INIT(); // Make sure supply voltage is high enough to run zmain_vdd_check(); // Initialize stack memory zmain_ram_init(); // Initialize board I/O InitBoard( OB_COLD ); // Initialze HAL drivers HalDriverInit(); // Initialize NV System osal_nv_init( NULL ); // Initialize basic NV items zgInit(); // Initialize the MAC ZMacInit(); // Determine the extended address zmain_ext_addr();#ifndef NONWK // Since the AF isn't a task, call it's initialization routine afInit();#endif // Initialize the operating system osal_init_system(); // Allow interrupts osal_int_enable( INTS_ALL ); // Final board initialization InitBoard( OB_READY ); // Display information about this device zmain_dev_info(); /* Display the device info on the LCD */#ifdef LCD_SUPPORTED zmain_lcd_init();#endif#ifdef WDT_IN_PM1 /* If WDT is used, this is a good place to enable it. */ WatchDogEnable( WDTIMX );#endif osal_start_system(); // No Return from here // Shouldn't get here return ( 0 );}
整理上面的程序,容易知道,进入main后,首先是各种检测和初始化,之后是 这里我们比较感兴趣的
osal_init_system(); 以及最后的 osal_start_system()
先说系统初试化
(附 osalInitTasks()位于 OSAL.c 中)
uint8 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 // Initialize 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 ( SUCCESS );}
照例,先是系统级的初始化,这里我们直接看工程对应的
osalInitTasks(); (位于 OSAL_SerialApp.c)
跟踪并打开如下
void osalInitTasks( void ){ uint8 taskID = 0; tasksEvents = (uint16 *)osal_mem_alloc( sizeof( uint16 ) * tasksCnt); //osal_mem_alloc()为当前OSAL中的各任务分配存储空间(实际上是一个任务数组),函数返回指向任务缓冲 //区的指针,因此tasksEvents指向该任务数组(任务队列).注意tasksEvents和后面谈到的tasksArr[]里的顺 //序是一一对应的, tasksArr[ ]中的第i个事件处理函数对应于tasksEvents中的第i个任务的事件. osal_memset( tasksEvents, 0, (sizeof( uint16 ) * tasksCnt)); //申请内存空间,大小为 sizeof( uint16 )乘tasksCnt //sizeof( uint16 )是4个字节,即一个任务的长度(同样是uint16定义) //乘以任务数量tasksCnt macTaskInit( taskID++ ); nwk_init( taskID++ ); Hal_Init( taskID++ );#if defined( MT_TASK ) MT_TaskInit( taskID++ );#endif APS_Init( taskID++ );#if defined ( ZIGBEE_FRAGMENTATION ) APSF_Init( taskID++ );#endif ZDApp_Init( taskID++ );#if defined ( ZIGBEE_FREQ_AGILITY ) || defined(ZIGBEE_PANID_CONFLICT ) ZDNwkMgr_Init( taskID++ );#endif SerialApp_Init( taskID );}
在这部分中
1、主要任务就是对各个系统内的层次进行初始化,其中核心的 SerialApp_Init( taskID ) 处在最后
2、注意此处的taskID,表示任务的优先级,在 ZDProfile.c 中有其定义,如下
typedef struct{ void *next; uint8 taskID; uint16 clusterID;} ZDO_MsgCB_t;
注意结构体 ZDO_MsgCB_t 后面还会提到,可见这个结构体中包含了 任务ID 和 簇ID
3、现在回头看第一句
uint8 taskID = 0; tasksEvents = (uint16 *)osal_mem_alloc( sizeof( uint16 ) * tasksCnt);//此步骤的关键作用在于 osal_memset( tasksEvents, 0, (sizeof( uint16 ) * tasksCnt));
- 首先令id=0
- (uint16 *) 是强制转换,不说,关键在于后面
osal_mem_alloc( sizeof( uint16 ) * tasksCnt),来看函数的原文描述,如下
@fn osal_mem_alloc @brief Implementation of the allocator functionality. @param size - number of bytes to allocate from the heap. @return void * - pointer to the heap allocation; NULL if error or failure.
也就是说,该函数负责 执行分配功能 ,osal_mem_alloc( uint16 size ),其中size就是要分配的字节大小,sizeof( uint16 )是4个字节,即一个任务的长度(同样是uint16定义),乘以任务数量tasksCnt,即全部内存空间。
这里看一下 tsaksCnt,跟踪可知
const uint8 tasksCnt = sizeof( tasksArr ) / sizeof( tasksArr[0] ); uint16 *tasksEvents;
sizeof 表示返回一个对象或者类型所占的内存字节数。 也就是,通过这样 tasksCnt 就可以得到总共的任务个数,tasksArr是任务列表,稍后说。
接上面说,osal_mem_alloc 的返回 :如果成功执行则返回指向一个缓存的指针,一个无类型指针指向被分配的新的缓存区。
- 之后将上面返回的空指针(指向被分配的缓存区)赋给tasksEvents
- 之后第三句 osal_memset( tasksEvents, 0, (sizeof( uint16 ) * tasksCnt))
* @fn osal_memset * @brief Set memory buffer to value. * * @param dest - pointer to buffer * @param value - what to set each uint8 of the message * @param size - how big * @return value of next widget, 0 if no widget found void *osal_memset( void *dest, uint8 value, int len ) { return memset( dest, value, len ); }
该函数的作用是给内存设定指定地址、指定内容、指定大小的,话说怎么感觉那么像三归 哈~
osal_memset()把开辟的内存全部设置为0;sizeof( uint16 )是4个字节,即一个任务的长度(同样是uint16定义),乘以任务数量tasksCnt,即全部内存空间
以上,总结一下第3点:
首先令taskID=0,期间通过 tasksCnt的定义 顺带计算osal中总的任务数量 (任务队列数组的总字节数 除以 每个任务的字节数 unit16都是4)
然后tasksEvents = (uint16 )osal_mem_alloc( sizeof( uint16 ) tasksCnt)进行内存空间的分配,成功后将结果 也就是指向 heap allocation 的空指针 赋给 tasksEvents
然后通过 osal_memset()把开辟的内存(tasksEvents指向的区域)全部设置对应的值value为0,大小就是
sizeof( uint16 )是4个字节,即一个任务的长度(同样是uint16定义),乘以任务数量tasksCnt, 即全部内存空间。
=========================================================================================
4、下面开始说 osalInitTasks( void ) 中的 SerialApp_Init( taskID ),跟踪打开如下
void SerialApp_Init( uint8 task_id ){ halUARTCfg_t uartConfig; P0SEL &= 0xDf; //设置P0.5口为普通IO P0DIR |= 0x20; //设置P0.5为输出 LAMP_PIN = 1; //高电平继电器断开;低电平继电器吸合 P0SEL &= ~0x40; //设置P0.6为普通IO口 P0DIR &= ~0x40; //设置P0.6为输入口 P0SEL &= 0x7f; //P0_7配置成通用io SerialApp_TaskID = task_id; //SerialApp_RxSeq = 0xC3; afRegister( (endPointDesc_t *)&SerialApp_epDesc ); RegisterForKeys( task_id ); uartConfig.configured = TRUE; // 2x30 don't care - see uart driver. uartConfig.baudRate = SERIAL_APP_BAUD; uartConfig.flowControl = FALSE; uartConfig.flowControlThreshold = SERIAL_APP_THRESH; // 2x30 don't care - see uart driver. uartConfig.rx.maxBufSize = SERIAL_APP_RX_SZ; // 2x30 don't care - see uart driver. uartConfig.tx.maxBufSize = SERIAL_APP_TX_SZ; // 2x30 don't care - see uart driver. uartConfig.idleTimeout = SERIAL_APP_IDLE; // 2x30 don't care - see uart driver. uartConfig.intEnable = TRUE; // 2x30 don't care - see uart driver. uartConfig.callBackFunc = SerialApp_CallBack; HalUARTOpen (UART0, &uartConfig);#if defined ( LCD_SUPPORTED ) HalLcdWriteString( "SerialApp", HAL_LCD_LINE_2 );#endif //HalUARTWrite(UART0, "Init", 4); //ZDO_RegisterForZDOMsg( SerialApp_TaskID, End_Device_Bind_rsp ); //ZDO_RegisterForZDOMsg( SerialApp_TaskID, Match_Desc_rsp );}
此为 串口app任务 的初始化 ,下面进行相关语句分析,没提到的不另做说明
4.1 afRegister( (endPointDesc_t *)&SerialApp_epDesc );
作用:Register an Application’s EndPoint description ,注册一个应用的端点描述符
* @fn afRegister* @brief Register an Application's EndPoint description.* @param epDesc - pointer to the Application's endpoint descriptor.* @return afStatus_SUCCESS - Registered* afStatus_MEM_FAIL - not enough memory to add descriptor* afStatus_INVALID_PARAMETER - duplicate endpointafStatus_t afRegister( endPointDesc_t *epDesc ){ epList_t *ep; // Look for duplicate endpoint if ( afFindEndPointDescList( epDesc->endPoint ) ) return ( afStatus_INVALID_PARAMETER ); ep = afRegisterExtended( epDesc, NULL ); return ((ep == NULL) ? afStatus_MEM_FAIL : afStatus_SUCCESS);}
函数类型为 afStatus_t , 跟踪可知 typedef ZStatus_t afStatus_t;又 typedef Status_t ZStatus_t;又 typedef uint8 Status_t;
函数参数为 epDesc - pointer to the Application’s endpoint descriptor,即一个 endPointDesc_t 类型的指针
在 afRegister( (endPointDesc_t *)&SerialApp_epDesc ) 中 可见,该注册函数指向了 SerialApp_epDesc 对应的指针
下面具体看一下这个指针类型
typedef struct{ byte endPoint; byte *task_id; // Pointer to location of the Application task ID. SimpleDescriptionFormat_t *simpleDesc; afNetworkLatencyReq_t latencyReq;} endPointDesc_t;
这个也就是 端点描述符的定义,这里展看结构体中的 SimpleDescriptionFormat_t 看一下
typedef struct{ //关于此冒号的用法,见 byte EndPoint; uint16 AppProfId; uint16 AppDeviceId; //app设备ID byte AppDevVer:4; //app版本号,冒号4,此处冒号用法为 “定义变量:占位符”表明定义的变量的需要位数 byte Reserved:4; //保留,具体是什么可以自己看着办,比如下面的实例中用来表示 程序的版本标识 // AF_V1_SUPPORT uses for AppFlags:4. byte AppNumInClusters; cId_t *pAppInClusterList; byte AppNumOutClusters; cId_t *pAppOutClusterList;} SimpleDescriptionFormat_t;
上面这两个定义,均在 AF.h 中
下面 对照程序中的 SerialApp_epDesc 看一下,下面的函数定位于 SerialApp.c 中
const endPointDesc_t SerialApp_epDesc ={ SERIALAPP_ENDPOINT, &SerialApp_TaskID, (SimpleDescriptionFormat_t *)&SerialApp_SimpleDesc, noLatencyReqs};
又其中 SerialApp_SimpleDesc 可得 `
const SimpleDescriptionFormat_t SerialApp_SimpleDesc =
{
SERIALAPP_ENDPOINT, // int Endpoint;
SERIALAPP_PROFID, // uint16 AppProfId[2];
SERIALAPP_DEVICEID, // uint16 AppDeviceId[2];
SERIALAPP_DEVICE_VERSION, // int AppDevVer:4;
SERIALAPP_FLAGS, // int AppFlags:4;
SERIALAPP_MAX_CLUSTERS, // byte AppNumInClusters;
(cId_t *)SerialApp_ClusterList, // byte *pAppInClusterList;
SERIALAPP_MAX_CLUSTERS, // byte AppNumOutClusters;
(cId_t *)SerialApp_ClusterList // byte *pAppOutClusterList;
};
- zigbee2007中工程执行流程(初始化部分) 小记
- zigbee2007中工程执行流程(初始化部分) 小记
- hadoop中mapreduce部分执行流程
- hadoop中mapreduce部分执行流程
- hadoop中mapreduce部分执行流程
- 部分初始化流程
- mtk初始化和执行流程
- Tor源码分析三 -- 客户端执行流程(初始化)
- GPRS模块初始化流程(不断完善中)
- GPRS模块初始化流程(不断完善中)
- BLE-NRF51822教程2-工程初始化流程
- BLE-NRF51822教程2-工程初始化流程
- BLE-NRF51822教程2-工程初始化流程
- BLE-NRF51822教程2-工程初始化流程
- BLE-NRF51822教程2-工程初始化流程
- WPF中窗口初始化部分控件ContextMenu使用Command默认不能执行
- Java工程中使用Log4j小记
- 20. OP-TEE中TA与CA执行流程-------CA部分的代码篇
- Npp ChangeLog
- expdp 报错:ora-22923 amount of data specified in streaming LOB write is 0
- C++笔记1
- C++中虚析构函数的作用
- java获取项目访问路径的方法
- zigbee2007中工程执行流程(初始化部分) 小记
- WebRTC的google官方入门教程
- 修饰符final与static的认识 java
- 社説 20150327 プロ野球開幕 ファン層をさらに広げよう
- request请求获取参数(post和get两种方式)
- 社説 20150327 統一地方選 地域再生の処方箋を論じたい
- [省选前题目整理][BZOJ 3140][HNOI 2013]消毒(二分图最大匹配)
- NSFileManager文件操作
- myeclipse上传文件案例的struts.xml配置文件