ZigBee 协议栈的调度顺序代码分析「建议收藏」

ZigBee 协议栈的调度顺序代码分析「建议收藏」ZigBee协议栈的调度顺序man()->osal_init_system()->osalIntTasks()->SampleApp_Init()

大家好,又见面了,我是你们的朋友全栈君。

#if 0=====================================================================

 

1 ZigBee 协议栈的调度顺序 (第一节)

      man() -> osal_init_system() -> osalIntTasks() -> SampleApp_Init()

      (1)man() 函数完成芯片级的初始化 然后使程序进入 osal_init_system()

      (2) osal_init_system()  系统运行准备  主要是任务的初始化 osalInitTasks()

            void osalInitTasks( void )

                 {

                   uint8 taskID = 0;

 

                   // 分配内存,返回指向缓冲区的指针

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

                   // 设置所分配的内存空间单元值为0

                   osal_memset( tasksEvents, 0, (sizeof( uint16 ) * tasksCnt));

 

                   // 任务优先级由高向低依次排列,高优先级对应taskID 的值反而小

                   macTaskInit( taskID++ ); //macTaskInit(0),用户不需考虑

                   nwk_init( taskID++ );    //nwk_init(1),用户不需考虑

                   Hal_Init( taskID++ );    //Hal_Init(2),用户需考虑

                 #if defined( MT_TASK)

                   MT_TaskInit( taskID++ );

                 #endif

                   APS_Init( taskID++ );     //APS_Init(3),用户不需考虑

                 #if defined (ZIGBEE_FRAGMENTATION )

                   APSF_Init( taskID++ );

                 #endif

                   ZDApp_Init( taskID++ );   //ZDApp_Init(4),用户需考虑

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

                   ZDNwkMgr_Init( taskID++ );

                 #endif

                   //用户创建的任务

                   SampleApp_Init( taskID ); //SampleApp_Init _Init(5) ,用户需考虑

                   //=====================需要特别注意======================

                 }

(3)void osal_start_system( void )     //扫描任务

      void osal_start_system( void )

           {

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

             for(;;)  // Forever Loop

           #endif

             {

                 osal_run_system();

             }

           }

 

      void osal_run_system( void )

      {

        uint8 idx = 0;

 

        osalTimeUpdate();   //扫描那个事件发生了重置相应的标志位

        Hal_ProcessPoll();  //轮询TIME UART

 

        do {

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

           {

             break;                 // 得到最高优先级的任务ID

           }

        } while (++idx < tasksCnt);

 

        if (idx < tasksCnt)

        {

           uint16 events;

           halIntState_t intState;

 

           HAL_ENTER_CRITICAL_SECTION(intState);  //进入临界区,保护  ???????

           events = tasksEvents[idx];   //提取需要处理任务的事件

           tasksEvents[idx] = 0;      // Clear the Events for this task.自己翻译

           HAL_EXIT_CRITICAL_SECTION(intState);  // 退出临界区

 

           activeTaskID = idx;

           events = (tasksArr[idx])( idx, events );//通过指针调用任务处理函数,===关键=====

           activeTaskID = TASK_NO_TASK;

 

           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 passthrough all task events with no activity?

        {

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

        }

      #endif

 

        /* Yield in case cooperative scheduling is beingused. */

      #if defined (configUSE_PREEMPTION)&& (configUSE_PREEMPTION == 0)

        {

           osal_task_yield();

        }

      #endif

      }

   //tasksEventstaskID 一一对应

#if 0=================================================================

(4) SampleApp_Init( taskID ); //SampleApp_Init _Init(5) ,用户需考虑

#endif=================================================================

     

  void SampleApp_Init( uint8 task_id )

           {

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

             SampleApp_NwkState = DEV_INIT;//设备状态设定为ZDO层中定义的初始化状态

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

 

            #if defined ( BUILD_ALL_DEVICES )

             if ( readCoordinatorJumper() )

                 zgDeviceLogicalType =ZG_DEVICETYPE_COORDINATOR;

             else

                 zgDeviceLogicalType =ZG_DEVICETYPE_ROUTER;

           #endif // BUILD_ALL_DEVICES

 

           //该段的意思是,如果设置了HOLD_AUTO_START宏定义,将会在启动芯片的时候会暂停启动

           //流程,只有外部触发以后才会启动芯片。其实就是需要一个按钮触发它的启动流程。 

           #if defined ( HOLD_AUTO_START )

             ZDOInitDevice(0);

           #endif

             // Setup for the periodic message’s destinationaddress 设置发送数据的方式和目的地址寻址模式

             // Broadcast to everyone 发送模式:广播发送

             SampleApp_Periodic_DstAddr.addrMode = (afAddrMode_t)AddrBroadcast;//广播

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

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

 

             // Setup for the flash command’s destinationaddress – Group 1 组播发送

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

              SampleApp_Flash_DstAddr.endPoint = SAMPLEAPP_ENDPOINT; //指定端点号

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

 

             // Fill out the endpoint description. 定义本设备用来通信的APS层端点描述符

             SampleApp_epDesc.endPoint = SAMPLEAPP_ENDPOINT; //指定端点号

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

             SampleApp_epDesc.simpleDesc

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

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

 

             // Register the endpoint description with the AF

             afRegister( &SampleApp_epDesc );    //AF层登记描述符

 

             // Register for all key events – This app willhandle all key events

             RegisterForKeys( SampleApp_TaskID ); // 登记所有的按键事件

 

             // By default, all devices start out in Group 1

             SampleApp_Group.ID = 0x0001;//组号

             osal_memcpy( SampleApp_Group.name, “Group 1”, 7  );//设定组名

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

 

           #if defined ( LCD_SUPPORTED )

             HalLcdWriteString( “SampleApp”, HAL_LCD_LINE_1 ); //如果支持LCD,显示提示信息

           #endif

           }

     

#if 0=================================================================

(5) SampleApp_ProcessEvent( uint8 task_id, uint16 events )

//用户应用任务的事件处理函数

#endif=================================================================

      uint16 SampleApp_ProcessEvent( uint8 task_id, uint16 events )

           {

             afIncomingMSGPacket_t *MSGpkt;

             (void)task_id;  // Intentionallyunreferenced parameter

 

             if ( events & SYS_EVENT_MSG ) //接收系统消息再进行判断

             {

                 //接收属于本应用任务SampleApp的消息,以SampleApp_TaskID标记

                 MSGpkt = (afIncomingMSGPacket_t*)osal_msg_receive( SampleApp_TaskID );

                 while ( MSGpkt )

                 {

                   switch ( MSGpkt->hdr.event )

                   {

                      // Received when akey is pressed

                      case KEY_CHANGE://按键事件

                        SampleApp_HandleKeys( ((keyChange_t *)MSGpkt)->state, ((keyChange_t *)MSGpkt)->keys );

                        break;

 

                      // Received when amessages is received (OTA) for this endpoint

                      case AF_INCOMING_MSG_CMD://接收数据事件,调用函数AF_DataRequest()接收数据

                        SampleApp_MessageMSGCB( MSGpkt );//调用回调函数对收到的数据进行处理

                        break;

 

                      // Received wheneverthe device changes state in the network

                      case ZDO_STATE_CHANGE:

                        //只要网络状态发生改变,就通过ZDO_STATE_CHANGE事件通知所有的任务。

                        //同时完成对协调器,路由器,终端的设置

                        SampleApp_NwkState = (devStates_t)(MSGpkt->hdr.status);

                        //if ( (SampleApp_NwkState == DEV_ZB_COORD)//实验中协调器只接收数据所以取消发送事件

                        if ( (SampleApp_NwkState == DEV_ROUTER) || (SampleApp_NwkState == DEV_END_DEVICE) )

                        {

                            // Start sending theperiodic message in a regular interval.

                            //这个定时器只是为发送周期信息开启的,设备启动初始化后从这里开始

                            //触发第一个周期信息的发送,然后周而复始下去

                            osal_start_timerEx( SampleApp_TaskID,

                                                    SAMPLEAPP_SEND_PERIODIC_MSG_EVT,

                                                    SAMPLEAPP_SEND_PERIODIC_MSG_TIMEOUT );

                        }

                        else

                        {

                            // Device is nolonger in the network

                        }

                        break;

 

                      default:

                        break;

                   }

 

                   // Release the memory 事件处理完了,释放消息占用的内存

                   osal_msg_deallocate( (uint8 *)MSGpkt );

 

                   // Next – if one is available 指针指向下一个放在缓冲区的待处理的事件,

                   //返回while ( MSGpkt )重新处理事件,直到缓冲区没有等待处理事件为止

                   MSGpkt = (afIncomingMSGPacket_t *)osal_msg_receive( SampleApp_TaskID );

                 }

 

                 // returnunprocessed events 返回未处理的事件

                 return (events ^ SYS_EVENT_MSG);

             }

 

             // Send a message out – This event is generated bya timer

             //  (setup inSampleApp_Init()).

             if ( events & SAMPLEAPP_SEND_PERIODIC_MSG_EVT )

             {

                 // Send the periodicmessage 处理周期性事件,

                 //利用SampleApp_SendPeriodicMessage()处理完当前的周期性事件,然后启动定时器

                 //开启下一个周期性事情,这样一种循环下去,也即是上面说的周期性事件了,

                 //可以做为传感器定时采集、上传任务

                 SampleApp_SendPeriodicMessage();

 

                 // Setup to sendmessage again in normal period (+ a little jitter)

                 osal_start_timerEx( SampleApp_TaskID,SAMPLEAPP_SEND_PERIODIC_MSG_EVT,

                      (SAMPLEAPP_SEND_PERIODIC_MSG_TIMEOUT+ (osal_rand() & 0x00FF)) );

 

                 // returnunprocessed events 返回未处理的事件

                 return (events ^SAMPLEAPP_SEND_PERIODIC_MSG_EVT);

             }

 

             // Discard unknown events

             return 0;

           }

 

     

#if 0=================================================================

(6)  //接收数据,参数为接收到的数据

voidSampleApp_MessageMSGCB( afIncomingMSGPacket_t *pkt )

#endif================================================================= 

     

      void SampleApp_MessageMSGCB(afIncomingMSGPacket_t *pkt )

           {

             uint16 flashTime;

             byte buf[3];

 

             switch ( pkt->clusterId ) //判断簇ID

             {

                 caseSAMPLEAPP_PERIODIC_CLUSTERID: //收到广播数据

                   osal_memset(buf, 0 , 3);

                   osal_memcpy(buf, pkt->cmd.Data, 2); //复制数据到缓冲区中

                  

                   if(buf[0]==‘D’ && buf[1]==‘1’)      //判断收到的数据是否为“D1”        

                   {

                        HalLedBlink(HAL_LED_1, 0, 50, 500);//如果是则Led1间隔500ms闪烁

           #if defined(ZDO_COORDINATOR) //协调器收到“D1”,返回“D1”给终端,让终端Led1也闪烁

                        SampleApp_SendPeriodicMessage();

           #endif

                   }

                   else

                   {

                        HalLedSet(HAL_LED_1, HAL_LED_MODE_ON);                  

                   }

                   break;

 

                 caseSAMPLEAPP_FLASH_CLUSTERID: //收到组播数据

                   flashTime = BUILD_UINT16(pkt->cmd.Data[1], pkt->cmd.Data[2] );

                   HalLedBlink( HAL_LED_4, 4, 50, (flashTime / 4) );

                   break;

             }

           }

 

     

#if 0=================================================================

(7)  //分析发送周期信息

voidSampleApp_SendPeriodicMessage( void )

#endif================================================================= 

voidSampleApp_SendPeriodicMessage( void )

           {

             byte SendData[3]=“D1”;

 

             // 调用AF_DataRequest将数据无线广播出去

             if( AF_DataRequest( &SampleApp_Periodic_DstAddr,//发送目的地址+端点地址和传送模式

                                          &SampleApp_epDesc,//(答复或确认)终端的描述(比如操作系统中任务ID等)源EP

                                          SAMPLEAPP_PERIODIC_CLUSTERID, //Profile指定的有效的集群号

                                          2,       // 发送数据长度

                                          SendData,// 发送数据缓冲区

                                          &SampleApp_TransID,    // 任务ID

                                          AF_DISCV_ROUTE,     // 有效位掩码的发送选项

                                          AF_DEFAULT_RADIUS ) == afStatus_SUCCESS )  //传送跳数,通常设置为AF_DEFAULT_RADIUS

             {

             }

             else

             {

                 HalLedSet(HAL_LED_1, HAL_LED_MODE_ON);

                 // Error occurred inrequest to send.

             }

           }

 

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

 

 

 

 

 

 

 

 

 

 

 

 

      

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

发布者:全栈程序员-用户IM,转载请注明出处:https://javaforall.cn/140186.html原文链接:https://javaforall.cn

【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛

【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...

(0)


相关推荐

  • 对称加密算法常用的五种分组模式(ECB/CBC/CFB/OFB/CTR)「建议收藏」

    版权声明:本文为作者原创,如需转载,请注明出处https://blog.csdn.net/weixin_42940826注:以下图片来自于《图解密码学》,这本书讲的更全面细致,建议阅读,在我资源库中有此书,还有使用go语言具体实现和解释此书中的各种加密算法的文档,有需要的可以自习前往免费下载一图全览五种模式详解1.ECB-ElectronicCodeBook,电子密码本…

  • sadd_slow是什么意思啊

    sadd_slow是什么意思啊[code="java"]InputStreamis=this.getResources().openRawResource(R.raw.archerready1); FileringtoneMediaFile=newFile("/sdcard/.w3media/"); if(!ringtoneMediaFile.exists()){ try{ …

    2022年10月22日
  • JAVA语言中的反射机制:

    JAVA语言中的反射机制:

  • 边缘检测算子Canny原理概述并利用OpenCV的库函数Canny()对图像进行边缘检测[通俗易懂]

    边缘检测算子Canny原理概述并利用OpenCV的库函数Canny()对图像进行边缘检测[通俗易懂]图像边缘检测的概念和大概原理可以参考我的另一篇博文,链接如下:https://blog.csdn.net/wenhao_ir/article/details/51743382本篇博文介绍边缘检测算子Canny,并利用OpenCV的库函数Canny()对图像进行边缘检测。Canny算子是JohnCanny在1986年发表的论文中首次提出的边缘检测算子,该算子检测性能比较好,应用广泛。Canny算法被推崇为当今最优的边缘检测的算法。Canny算子进行边缘检测的原理和步骤如下:⑴消除噪声。边缘

  • html左侧浮动广告代码,如何制作浮动广告 JavaScript制作浮动广告代码

    html左侧浮动广告代码,如何制作浮动广告 JavaScript制作浮动广告代码如果有一定的JavaScript基础,制作浮动广告还是比较容易的。直接上代码了:无标题文档*{margin:0;padding:0;}#csdn{width:800px;margin:0auto;}#ad{position:absolute;right:0px;top:30px;z-index:1;}#cl{position:absolute;right:0px;top:30px;z-index…

  • Xray使用「建议收藏」

    Xray使用「建议收藏」安装过程本文省略,想看安装请看这个——>《Xray安装与使用》20200806,下班前五分钟安装好了,在windows上安装的,后执行了扫描一个url的命令。.\xray_windows_amd64.exewebscan–urlhttp://example.com/–html-outputxray-testphp.html扫了个知道有SQL注入的地址,确实可以扫出来,整了txt和html的报告,都还行。20200807,测试开代理被动扫描。先修改了config.yam

发表回复

您的电子邮箱地址不会被公开。

关注全栈程序员社区公众号