zoukankan      html  css  js  c++  java
  • 【转】TI Z-stack协议栈学习-添加新任务

    开始学习TI的zigbee协议栈,无线龙的资料看得比较乱,在网络找到不少分析协议栈的文章,先贴上来,等自己有空了再好好原创一下吧。

    协议栈版本:ZStack-1.4.3-1.2.1

         TI Z-stack协议栈学习-添加新任务

    1.Zstack中如何实现自己的任务 http://zhenling.chen.blog.163.com/blog/static/1940851920097710392587/

    在Zstack(TI的Zigbee协议栈)中,对于每个用户自己新建立的任务通常需要两个相关的处理函数,包括:

         (1).用于初始化的函数,如:SampleApp_Init(), 这个函数是在osalInitTasks()这个osal(Zstack中自带的小操作系统)中去调用的,其目的就是把一些用户自己写的任务中的一些变量,网络模式,网络终端类型等进行初始化;

         (2).用于引起该任务状态变化的事件发生后所需要执行的事件处理函数,如:

    SampleApp_ProcessEvent(),这个函数是首先在const pTaskEventHandlerFn tasksArr[ ] 中进行设置(绑定),然后在osalInitTasks()中如果发生事件进行调用绑定的事件处理函数.

        下面分3个部分分析.

    1.用户自己设计的任务代码在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()中增加.

    void osalInitTasks( void )

    {

    uint8 taskID = 0;

    //这里很重要, 调用osal_mem_alloc()为当前OSAL中的各任务分配存储空间(实际上是一个任//务数组),并用tasksEvents指向该任务数组(任务队列).

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

    osal_memset( tasksEvents, 0, (sizeof( uint16 ) * tasksCnt)); //将taskSEvents所指向的空间清零

    macTaskInit( taskID++ );

    nwk_init( taskID++ );

    Hal_Init( taskID++ );

    #if defined( MT_TASK )

    MT_TaskInit( taskID++ );

    #endif

    APS_Init( taskID++ );

    ZDApp_Init( taskID++ );

    SampleApp_Init( taskID ); //用户自己需要添加的任务

    }

    2.任务处理调用的重要数据结构

    这里要解释一下,在Zstack里,对于同一个任务可能有多种事件发生,那么需要执行不同的事件处理,为了方便,对于每个任务的事件处理函数都统一在一个事件处理函数中实现,然后根据任务的ID号(task_id)和该任务的具体事件(events)调用某个任务的事件处理函数,进入了该任务的事件处理函数之后,再根据events再来判别是该任务的哪一种事件发生,进而执行相应的事件处理.pTaskEventHandlerFn 是一个指向函数(事件处理函数)的指针,这里实现的每一个数组元素各对应于一个任务的事件处理函数,比如SampleApp_ProcessEvent对于用户自行实现的事件处理函数uint16 SampleApp_ProcessEvent( uint8 task_id, uint16 events ),所以这里如果我们实现了一个任务,还需要把实现的该任务的事件处理函数在这里添加.

    const pTaskEventHandlerFn tasksArr[] = {

    macEventLoop,

    nwk_event_loop,

    Hal_ProcessEvent,

    #if defined( MT_TASK )    //一个MT任务命令

    MT_ProcessEvent,

    #endif

    APS_event_loop,

    ZDApp_event_loop,

    SampleApp_ProcessEvent

    };

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

    //计算出任务的数量

    const uint8 tasksCnt = sizeof( tasksArr ) / sizeof( tasksArr[0] );

    uint16 *tasksEvents;

    3. 对于不同事件发生后的任务处理函数的调用

    osal_start_system() 很重要,决定了当某个任务的事件发生后调用对应的事件处理函数

    void osal_start_system(void)

    {

    #if !defined ( ZBIT )

    for(;;) // Forever Loop

    #endif

    {

        uint8 idx = 0;

        Hal_ProcessPoll(); // This replaces MT_SerialPoll() and osal_check_timer().

    //这里是轮训任务队列,并检查是否有某个任务的事件发生

        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);

          events = tasksEvents[idx];   //处理该idx的任务事件, 是第idx个任务的事件发生了

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

          HAL_EXIT_CRITICAL_SECTION(intState);

          //对应调用第idx个任务的事件处理函数,用events说明是什么事件

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

      

          //当没有处理完,把返回的events继续放到tasksEvents[idx]当中

          HAL_ENTER_CRITICAL_SECTION(intState);

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

          HAL_EXIT_CRITICAL_SECTION(intState);

          }

    #if defined( POWER_SAVING )

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

        {

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

        }

    #endif

        }

    }

    =========================================================================

    2.Z-stack添加一个新的任务 http://www.wyouxi.com/index.php/group_thread/view/id-8583

    在osalInitTasks()和tasksArr[]添加相应的项就可以了。 1.修改osalInitTasks()void osalInitTasks( void ){……OuhsApp_Init( taskID++ ); PhotoApp_Init( taskID); } 2.修改tasksArr[]const pTaskEventHa ...

    在osalInitTasks()和tasksArr[]添加相应的项就可以了。

    1.修改osalInitTasks()

    void osalInitTasks( void )

    {

    ……

    OuhsApp_Init( taskID++ );

    PhotoApp_Init( taskID);

    }

    2.修改tasksArr[]

    const pTaskEventHandlerFn tasksArr[] = {

    ……

    OuhsApp_ProcessEvent

    PhotoApp_ProcessEvent

    };

    3.添加_Init()和_ProcessEvent()

    void PhotoApp_Init( uint8 task_id )

    {

    PhotoApp_TaskID = task_id;

    PhotoInit();

    RegisterForPhoto( PhotoApp_TaskID );

    }

    uint16 PhotoApp_ProcessEvent( uint8 task_id uint16 events )

    {

    afIncomingMSGPacket_t *MSGpkt;

    if ( events &SYS_EVENT_MSG )

    {

    MSGpkt = (afIncomingMSGPacket_t *)osal_msg_receive( PhotoApp_TaskID );

    while ( MSGpkt )

    {

    switch ( MSGpkt->hdr.event )

    {

    case PHOTO_CHANGE:

    HalLedblink( HAL_LED_1 3 30 300 );

    //P0IE = 1;

    break;

    }

    // Release the memory

    osal_msg_deallocate( (uint8 *)MSGpkt );

    // Next - if one is available

    MSGpkt = (afIncomingMSGPacket_t *)osal_msg_receive( PhotoApp_TaskID );

    }

    // return unprocessed events

    return (events ^ SYS_EVENT_MSG);

    }

    // Discard unknown events

    return 0;

    }

  • 相关阅读:
    【SSH网上商城项目实战15】线程、定时器同步首页数据(类似于CSDN博客定期更新排名)
    【SSH网上商城项目实战14】商城首页UI的设计
    Spring工具类:WebApplicationContextUtils
    多线程技术: 两个线程交替打印奇数和偶数
    常见的几种异常类型Exception
    【SSH网上商城项目实战13】Struts2实现文件上传功能
    【SSH网上商城项目实战12】添加和更新商品功能的实现
    【SSH网上商城项目实战11】查询和删除商品功能的实现
    【SSH网上商城项目实战10】商品类基本模块的搭建
    如何防止通过IP地址访问Tomcat管理页面
  • 原文地址:https://www.cnblogs.com/farbeyond/p/5204745.html
Copyright © 2011-2022 走看看