协议栈代码main()函数分析

ZMain文件->ZMain.c->main()  在这里我们重点了解osal_start_system()函数

int main( void )

{

//关闭所有终端

osal_int_disable( INTS_ALL );

//硬件板子的初始化,比如led的初始化

HAL_BOARD_INIT();

//监测电压,确保电压能使CC2530运行

zmain_vdd_check();

// 初始化板子的I/O

InitBoard( OB_COLD );

// 初始化硬件驱动

HalDriverInit();

// 初始化NV系统

osal_nv_init( NULL );

// MAC的初始化

ZMacInit();

// 扩展地址的初始化

zmain_ext_addr();

// 初始化NV条目

zgInit();

#ifndef NONWK

//AF层的初始化,在禁止NONWK的时候需要初始化AF层

afInit();

#endif

//初始化操作系统

//维护事件表的函数在这个函数里边-》osalInitTasks();

osal_init_system();

// 开中断

osal_int_enable( INTS_ALL );

// 板级终初始化

InitBoard( OB_READY );

// 设备信息显示

zmain_dev_info();

//如果定义了LCD,那么执行LCD初始化

#ifdef LCD_SUPPORTED

zmain_lcd_init();

#endif

#ifdef WDT_IN_PM1

//如果定义了看门狗,那么执行使能看门狗函数

WatchDogEnable( WDTIMX );

#endif

//系统执行的入口,注意正常情况是不会运行到此函数的下一句,

//也就是return语句的,因为进入此函数以后会一直在里面循环执行任务,并不会跳出次循环。

osal_start_system();

return 0;

} // main()

分析osal_start_system()函数,通过go  to的方式,跳转到函数中去

void osal_start_system( void )

{

#if !defined ( ZBIT ) && !defined ( UBIT )

for(;;)  // Forever Loop   //进入for死循环,相当于while(1);

#endif

{

osal_run_system();  //到这里进入我们osal系统,

}

}

OSAL的运行机制

ZigBee 协议栈仅仅是 ZigBee 协议的具体实现。OSAL 就是一种支持多任务运行的系统资源分配机制。在 ZigBee 协议栈中,OSAL 负责调度各个任务的运行,如果有事件发生了,则会调用相应的事件处理函数进行处理。

那么,事件和任务的事件处理函数是如何联系起来的呢?

ZigBee 中采用的方法是:建立一个事件表,保存各个任务的对应的事件,建立另一个函数表,保存各个任务的事件处理函数的地址,然后将这两张表建立某种对应关系,当某一事件发生时则查找函数表找到对应的事件处理函数即可。

分析osal_run_system()函数,通过go to的方式,跳转到函数中去,分析我们OSAL的运行机制。

void osal_run_system( void )

{

uint8 idx = 0;

osalTimeUpdate();

Hal_ProcessPoll();

//查询任务事件表是否有事件发生,从高优先级的任务中开始查询

// const uint8 tasksCnt = sizeof( tasksArr ) / sizeof( tasksArr[0] );  初始化任务数,并且进行初始化

do {

if (tasksEvents[idx])  // Task is highest priority that is ready.

{

break;

}

} while (++idx < tasksCnt);

if (idx < tasksCnt)

{

uint16 events;

halIntState_t intState;

HAL_ENTER_CRITICAL_SECTION(intState);  /* 进入临界区---保存EA状态然后置EA = 0 */

//将发生任务的事件取出来放到events变量中,并将tasksEvents[idx]清零

// uint16 *tasksEvents;  指向事件表的首地址,

//协议栈中的事件采用独热码的方式,

// ZigBee 协议栈使用一个 unsigned short 型的变量,因为 unsigned short 类型占两个字节,

// 即 16 个二进制位,因此,可以使用每个二进制位表示一个事件,我们来看下协议栈定义

// 的系统事件SYS_EVENT_MS G,十六进制:0x8000,二进制0b100000000000000 0。

//它用的就是高位来表示该事件:在系统初始化时,所有任务的事件初始化为 0,

events = tasksEvents[idx];

tasksEvents[idx] = 0;  // Clear the Events for this task.

HAL_EXIT_CRITICAL_SECTION(intState);   /* 退出临界区---恢复EA状态 */

activeTaskID = idx;

// 声明函数指针

// typedef unsigned short (*pTaskEventHandlerFn)( unsigned char task_id, unsigned short event );

// 函数指针数组,指向任务事件处理函数

// const pTaskEventHandlerFn tasksArr[] = {}

// 在任务事件处理函数中通过eturn (events ^ SYS_EVENT_MSG);返回任务中未处理的事件

events = (tasksArr[idx])( idx, events );

activeTaskID = TASK_NO_TASK;

HAL_ENTER_CRITICAL_SECTION(intState);  /* 进入临界区---保存EA状态然后置EA = 0 */

// 将未处理的任务中的事件重新写回到事件表中

tasksEvents[idx] |= events;  // Add back unprocessed events to the current task.

HAL_EXIT_CRITICAL_SECTION(intState);   /* 退出临界区---恢复EA状态 */

}

#if defined( POWER_SAVING )   //进入低功耗模式

else  // Complete pass through all task events with no activity?

{

osal_pwrmgr_powerconserve();  // Put the processor/system into sleep

}

#endif

}

事件表的分配空间:

查看main()函数中的系统初始化函数osal_init_system();——> 任务初始化函数osalInitTasks();

void osalInitTasks( void )

{

uint8 taskID = 0;

//给事件表分配空间通过osal_mem_alloc函数,

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

//使用osal_memset函数给事件表全部初始化为0

osal_memset( tasksEvents, 0, (sizeof( 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

SampleApp_Init( taskID );   //用户自己添加的任务初始化函数

}

任务事件处理函数分配空间:

const pTaskEventHandlerFn tasksArr[] = {

macEventLoop,

nwk_event_loop,

Hal_ProcessEvent,

#if defined( MT_TASK )

MT_ProcessEvent,

#endif

APS_event_loop,

#if defined ( ZIGBEE_FRAGMENTATION )

APSF_ProcessEvent,

#endif

ZDApp_event_loop,

#if defined ( ZIGBEE_FREQ_AGILITY ) || defined ( ZIGBEE_PANID_CONFLICT )

ZDNwkMgr_event_loop,

#endif

SampleApp_ProcessEvent    //用户自己的任务中的事件处理函数

};

注意:任务初始化函数中每个任务的初始化函数必须与任务事件处理数组中的任务事件处理函数一一对应。

在 ZigBee 协议栈中,有三个变量至关重要:

  tasksCnt—该变量保存了任务的总个数。

该变量的声明为:uint8 tasksCnt,其中 uint8 的定义为:typedef unsigned char uint8

 tasksEvents—这是一个指针,指向了事件表的首地址。

该变量的声明为:uint16 *tasksEvents,其中 uint16 的定义为:typedef unsigned short

uint16

 tasksArr—这是一个数组, 数组的每一项都是一个函数指针, 指向了事件处理函数

该数组的声明为:const pTaskEventHandlerFn tasksArr[],其中 pTaskEventHandlerFn 的

定义为:typedef unsigned short (*pTaskEventHandlerFn)( unsigned char task_id, unsigned short

event ),这是定义了一个函数指针。tasksArr 数组的每一项都是一个函数指针,指向了事件

处理函数。

事件表          任务中的事件处理函数表

OSAL消息队列

提到事件,我们就不得不提到消息。事件是驱动任务去执行某些操作的条件,当系统中产生了一个事件,OSAL 将这个事件传递给相应的任务后,任务才能执行一个相应的操作(调用事件处理函数去处理) 。

通常某些事件发生时,又伴随着一些附加信息的产生,例如:从天线接收到数据后,会产生 AF_INCOMING _MSG_CMD 消息,但是任务的事件处理函数在处理这个事件的时候,还需要得到收到的数据。

因此,这就需要将事件和数据封装成一个消息,将消息发送到消息队列,然后在事件处理函数中就可以使用 osal_msg_receive 从消息队列中得到该消息。afIncomingMSGPacket_t *MSGpkt;   //根据消息类型声明对应的接收消息的变量

MSGpkt = (afIncomingMSGPacket_t *)osal_msg_receive( SampleApp_TaskID );  //强制转化成对应的消息类型

OSAL维护了一个消息队列,每一个消息都会被放到这个消息队列中去,当任务接收到时间后,可以从消息队列中获取属于自己的消息,然后调用消息处理函数进行相应的处理即可。

OSAL中消息队列如下图所示:

每个消息都包含一个消息头osal_mag_hdr_t和用户自定义的消息,osal_msg_hdr_t结构体的定义为:

typedef struct

{

void   *next;

uint16 len;

uint8  dest_id;

} osal_msg_hdr_t;

OSAL工作机制分析的更多相关文章

  1. Java IO工作机制分析

    Java的IO类都在java.io包下,这些类大致可分为以下4种: 基于字节操作的 I/O 接口:InputStream 和 OutputStream 基于字符操作的 I/O 接口:Writer 和 ...

  2. Map/Reduce 工作机制分析 --- 错误处理机制

    前言 对于Hadoop集群来说,节点损坏是非常常见的现象. 而Hadoop一个很大的特点就是某个节点的损坏,不会影响到整个分布式任务的运行. 下面就来分析Hadoop平台是如何做到的. 硬件故障 硬件 ...

  3. Map/Reduce 工作机制分析 --- 数据的流向分析

    前言 在MapReduce程序中,待处理的数据最开始是放在HDFS上的,这点无异议. 接下来,数据被会被送往一个个Map节点中去,这也无异议. 下面问题来了:数据在被Map节点处理完后,再何去何从呢? ...

  4. Map/Reduce 工作机制分析 --- 作业的执行流程

    前言 从运行我们的 Map/Reduce 程序,到结果的提交,Hadoop 平台其实做了很多事情. 那么 Hadoop 平台到底做了什么事情,让 Map/Reduce 程序可以如此 "轻易& ...

  5. 第十一篇:Map/Reduce 工作机制分析 - 错误处理机制

    前言 对于Hadoop集群来说,节点损坏是非常常见的现象. 而Hadoop一个很大的特点就是某个节点的损坏,不会影响到整个分布式任务的运行. 下面就来分析Hadoop平台是如何做到的. 硬件故障 硬件 ...

  6. 第十篇:Map/Reduce 工作机制分析 - 数据的流向分析

    前言 在MapReduce程序中,待处理的数据最开始是放在HDFS上的,这点无异议. 接下来,数据被会被送往一个个Map节点中去,这也无异议. 下面问题来了:数据在被Map节点处理完后,再何去何从呢? ...

  7. 第九篇:Map/Reduce 工作机制分析 - 作业的执行流程

    前言 从运行我们的 Map/Reduce 程序,到结果的提交,Hadoop 平台其实做了很多事情. 那么 Hadoop 平台到底做了什么事情,让 Map/Reduce 程序可以如此 "轻易& ...

  8. hostapd源代码分析(二):hostapd的工作机制

    [转]hostapd源代码分析(二):hostapd的工作机制 原文链接:http://blog.csdn.net/qq_21949217/article/details/46004433 在我的上一 ...

  9. Linux内核分析第四周学习总结——系统调用的工作机制

    Linux内核分析第四周学习总结--系统调用的工作机制 内核态 执行级别高,可以执行特权指令,访问任意物理地址,在intel X86 CPU的权限分级为0级. 用户态 执行级别低,只能访问0x0000 ...

随机推荐

  1. eclipse中的maven build、maven clean、maven install和maven test的区别

    eclipse中的maven build.maven clean.maven install和maven test的区别 https://www.cnblogs.com/Marydon20170307 ...

  2. web前端面试经历分享

    十天前,我还在纠结这个暑假到底是呆在实验室研究技术好还是找一份实习见识世面好,而现在我已经接到offer准备工作了.这几天真是累得够呛,一方面需要拼命准备期末考试,另一方面,需要往公司里面跑接受面试. ...

  3. Codeforces.959E.Mahmoud and Ehab and the xor-MST(思路)

    题目链接 \(Description\) 有一张\(n\)个点的完全图,从\(0\)到\(n-1\)标号,每两点\(i,j\)间的边权为\(i\oplus j\).求其最小生成树边权之和. \(Sol ...

  4. bzoj 1455 可并堆+并查集

    一个堆和一个并查集对应,并且满足并查集中所有没有死的人等于堆中的人 /************************************************************** Pr ...

  5. [原创]WebScarab工具介绍

    [原创]WebScarab工具介绍 一 WebScarab介绍 WebScarab是一个用来分析使用HTTP和HTTPS协议的应用程序框架.其原理很简单,WebScarab可以记录它检测到的会话内容( ...

  6. Android SDKVersion 参数列表

    http://developer.android.com/guide/topics/manifest/uses-sdk-element.html Platform Version API Level ...

  7. oracle sql 高级

    1  时间   如果是从当前时间到前一个月的这个时候之间的记录总条数:   select count(1)   from uis_md_stcustom u  where firsttime betw ...

  8. leetcode——169 Majority Element(数组中出现次数过半的元素)

    Given an array of size n, find the majority element. The majority element is the element that appear ...

  9. ASP.NET MVC中使用Session来保持表单的状态

    本篇实践在ASP.NET MVC 4下使用Session来保持表单的状态. 本篇的源码在这里: https://github.com/darrenji/KeepFormStateUsingSessio ...

  10. Grid布局方式

    wp7中Grid布局类似HTML中的表格,但是又不太一致! 为了测试新一个3行3列的Grid 方了方便,剔除掉其它XAML代码 [c-sharp:collapse] view plaincopy   ...