ZIGBEE协议栈-OSAL系统框架专题【转载】

2023-11-22 22:38

本文主要是介绍ZIGBEE协议栈-OSAL系统框架专题【转载】,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

OSAL系统框架专题2010-4-15 2:47:00

9. TI协议栈所用系统框架探讨。
51的系统往往不是太大,但是几十K的程序,也足以让一个初学者望而却步。我们首先忽略C语言本身的难度,光是系统框架也让生手读起来很吃力,再加上这种到处是API跟"define"的程序,还没有正式学习协议部分就已经让人在丛林中“迷路”了。

在接下来的一段时间内,我会以TI所用的系统框架为主线进行学习,希望大家共同探讨。。。

在层层迷雾中摸索了两天,终于拨云见日,那个心情啊,怎一个“爽”字了得~~~

可是怎么能把这么复杂的一个问题讲得清楚呢?嗯。。。还是先上图吧


图片
注:为了便于直观,以下涉及到数据地址的地方都是由上而下,地址由高变低

第1节、各个任务是如何被调用到的?
我们还是先从main()函数开始,看看各个任务之间是如何协调工作的。
插播一句广告:在一切都看不清的时候,忽略次要,看主要因素-- by outman from Zigbeetech

我们直接进入主循环的核心部分,看一下系统中的几个主要的任务是如何被调用,并开始自己的使命的?


看一段程序的时候,往往要从它的数据结构入手。我们先看一下,主循环中的两个关键数组,*tasksEvents与*tasksArr,从图一中我们可以看出来,tasksEvents这个数组存放的是从序号为0到tasksCnt,每个任务在本次循环中是否要被运行,需要运行的任务其值非0(用橙色表示),否则为0。而tasksArr数组则存放了对应每个任务的入口地址,只有在tasksEvents中记录的需要运行的任务,在本次循环中才会被调用到。--这节讲完了。。。

又有同学举手?什么?还没明白?恩。。。好像是不能讲这么短的。。。
那好吧,把main函数贴过来,我们一点一点看
初始化过程“先不管”,我们先看主循环(dead loop)

for(;;)  // Forever Loop
{
    uint8 idx = 0;
    Hal_ProcessPoll();  
//
先不管1

    do {
      if (tasksEvents[idx])  
// 寻找最高优先级的任务来运行

      {
        break;
      }
    } while (++idx < tasksCnt);

    if (idx < tasksCnt)
    {
      uint16 events;
      halIntState_t intState;

      HAL_ENTER_CRITICAL_SECTION(intState);
      events = tasksEvents[idx];
      tasksEvents[idx] = 0;  
//
本任务运行完了,要对其清空,为后面要运行的任务让路
      HAL_EXIT_CRITICAL_SECTION(intState);

      events = (tasksArr[idx])( idx, events );
//
最关键的一句话,如图一中,运行对应的任务

      HAL_ENTER_CRITICAL_SECTION(intState);
      tasksEvents[idx] |= events;  
//
本任务可能没完全完成,如果是这样,再次设置标志位,在下一次循环中继续执行
      HAL_EXIT_CRITICAL_SECTION(intState);
      }
    }

第2节、系统时间

我们知道,每个操作系统(虽然我不认为OSAL是一个标准的操作系统,但我们先这么叫着吧)都有一个“节拍”-tick,就像每一个“活人”都有心跳一样。那么OSAL的心跳有多快呢?--1ms。当然这个速度是可以设置的,在osal_timer_activate函数中开启了系统节拍,用TICK_TIME来定义其速度
#define TICK_TIME   1000   // Timer per tick - in micro-sec
注意:这个1000是micro-sec(微秒),而不是milli-sec(毫秒)!我刚开始的时候就是误以为是1000ms而耽误了不少时间。
那这个心脏是怎么跳动起来的呢?

这得从“定时器”说起,由于本文的重点不是讲单片机基础的,如果对这个名字还陌生的同学,那还是回去先看看基础再来看这个吧。2430有4个定时/计数器,其中timer4用来做系统计时。如果认为是timer2的同学请看一下halTimerRemap这个函数。在上述osal_timer_activate函数中,开启了系统计时,并将timer4的初始设为TICK_TIME(1000),这样timer4就开始了从1000开始的减计数,减到0以后呢?寄存器TIMIF会产生一个溢出标志,那么它会立即产生中断并进入中断服务程序吗?不会的。

我们看一下第1节主函数里的“Hal_ProcessPoll();  // 先不管1”(不管的东西早晚要管的,只是时间的问题而已)  这个函数里调用了HalTimerTick,这个函数就是专门来检查是否有硬件定时器溢出的,如果有的话会调用halTimerSendCallBack这个函数,对溢出事件做处理。

回过头来说系统节拍,那timer4在计数满1000(即1ms)后做了些什么事呢,那我们看一下halTimerSendCallBack 这个函数
void halTimerSendCallBack (uint8 timerId, uint8 channel, uint8 channelMode)
{
  uint8 hwtimerid;

  hwtimerid = halTimerRemap (timerId);

  if (halTimerRecord[hwtimerid].callBackFunc)
    (halTimerRecord[hwtimerid].callBackFunc) (timerId, channel, channelMode);
}

这里面调用了“callBackFunc”函数,也就是说每个定时器溢出后都有一个callBackFunc函数,它在哪里呢,我们再看一下HalTimerConfig这个函数,它可以对每个定时器进行定义。那什么时候定义的呢?--InitBoard,即板子上电初始化的时候就做了这个定义的。我说什么来?“先不管”的东西,“后要管”的。。。

我们看到timer4的callBackFunc函数是Onboard_TimerCallBack,最终指向osalTimerUpdate,这个函数厉害了~
从上面的分析中我们知道它是每1ms被调用一次的,这样它就为应用程序提供了一个ms计时器,应用程序所用的定时往往以ms为单位足够了,这样的话就不用另外再占用硬件计时器了,毕竟只有4个嘛。。。同时这个函数还提供了一个系统时钟-osal_systemClock,看看它能计时多久吧,它是“uint32”型的,也就是2^32ms=49.7天,怎么样?你不会让这个系统时钟overflow吧:)


第3节、系统的消息处理机制

结合第1、2节中的内容,让我们一起进入到系统最核心的部分-消息处理中来吧(这个句型怎么这么耳熟~~~)

第1节中我们说了,tasksEvents数组存放了一个任务是否该被运行的序列,但是这个序列是如何产生的呢?如果了解了这个问题,那也就知道了OSAL系统的运作方式。
再插句广告:在浩如烟海的程序中搜索最重要的东西,就像大浪淘沙,其实也是蛮享受的一件事情--by outman from zigbeetech

source insight "ctr+/"
,整个项目搜索,我们发现了一个“osal_set_event”的函数是专门来设置tasksEvents的,但是似乎并不能帮到我们。继续搜!有两个很重要的地方引起了我们的注意:osalTimerUpdate和osal_msg_send这两个函数


osalTimerUpdate,这个称得上“厉害”的函数还记得吧?它会去设置tasksEvents?那不就是说,它可以让任务在主循环中被运行到?答对了,这就是它“厉害”的地方。。。那看看它运行任务的条件吧?
      // When timeout, execute the task
      if ( srchTimer->timeout == 0 )
      {
        osal_set_event( srchTimer->task_id, srchTimer->event_flag );
... ...
也就是说,计时器溢出--恩。。。不多说了,我们埋个伏笔,先介绍另一个朋友-osal_start_timerEx,先看下它的自我介绍
/*********************************************************************
* @fn      osal_start_timerEx
*
* @brief
*
*   This is called to start a timer to expire in n mSecs.
*   When the timer expires, the calling task will get the specified event.
*
* @param   byte taskID - task id to set timer for
* @param   UINT16 event_id - event to be notified with
* @param   UNINT16 timeout_value - in milliseconds.
*
* @return  ZSUCCESS, or NO_TIMER_AVAIL.
*/
byte osal_start_timerEx( byte taskID, UINT16 event_id, UINT16 timeout_value )

也就是说,它会开始一个timeout_value(ms)的计时器,当这个计时器溢出时,则会对taskID这个task,设置一个event_id,让这个任务在后面的主循环中运行到,但是是怎么实现的呢?还是要请osalTimerUpdate来帮忙。。。

那位同学说啥?复杂了,听不懂?
唉,还是上图吧
图片
还是先从数据结构说起吧,不知道啥是“数据链表”的同学,把谭老师的书拿过来再读几遍。。。
这个表就是osalTimerUpdate函数的“任务表”,上面不是说过这个函数给应用程序提供了“软计时”了吗?就是体现在这里,osal_start_timerEx通过osalAddTimer向链表里添加了“定时任务”,由osalTimerUpdate来以ms为单位对这些“软定时器”减计数,溢出时,即调用osal_set_event,实现主循环里对任务的调用。

好了,到此讲了上面提到的"set event"函数中的一个osal_start_timerEx,还有一个更厉害的还在外面呢,osal_msg_send,这就渐入佳境,进入最重要的消息处理机制了。。。

-- by outman 2010-4-14 18:00  下班啦,老婆在家等着回去一起做饭哪~~~晚上见~~~

为了更好地说明这个问题,还是拿一个具体的例子来讲比较直观。不过在这个笔记中,我尽量不涉及具体开发板,而讲一些通用的知识,因为这样会让更多的人受益。在TI官方zstack 2006中有4个例子,其中一个叫GenericApp最基本的通信的例程,如果没有安装zstack的同学可以到“本站专用下载贴”中下载。当然由于讲的是些比较通用的东西,所以手头有开发板的同学可以用自己的开发板来试验,效果更好。。。


在这样的通信例程中,一般会有一个按键触发,然后会和相邻的模块进行通信,当然由于这部分是讲OSAL的系统框架的,我们先不涉及通信的内容,只是看一下按键是如何产生的,及如何调用相应的接口程序。

按OSAL的模块定义,按键可能在哪层来?硬件服务相关的,恩。。。是不是在HAL层呢?到Hal_ProcessEvent看看?有个HalKeyPoll函数不是?恩,这就是检测按键的地方~~不过,我可不是像上面这样这么容易猜出来的,这几句话足足用了我大半个钟头呢。。。过程我不细说了,有兴趣的话我可以再补充一下。

在HalKeyPoll函数中,无论按键是ADC方式,或者是扫描IO口的方式,最后都会生成一个键值keys, 然后通过下面的语句来调用按键服务程序
  /* Invoke Callback if new keys were depressed */
  if (keys && (pHalKeyProcess))
  {
    (pHalKeyProcess) (keys, HAL_KEY_STATE_NORMAL);
  }

这里调用的服务程序,在InitBoard中被初始化为OnBoard_KeyCallback,这个函数又通过OnBoard_SendKeys运行下面语句
  {
   
// Send the address to the task
    msgPtr = (keyChange_t *)osal_msg_allocate( sizeof(keyChange_t) );
    if ( msgPtr )
    {
      msgPtr->hdr.event = KEY_CHANGE;
      msgPtr->state = state;
      msgPtr->keys = keys;

      osal_msg_send( registeredKeysTaskID, (uint8 *)msgPtr );
    }
    return ( ZSuccess );
  }

下面我们就看下osal_msg_send是如何向上级应用程序发送消息的。终于要讲消息量的数据结构了,好像绕得有点远。。。。还是先上图

图片
在理解了消息量的数据链表后,再来理解osal_msg_send里的语句就不难了
  OSAL_MSG_ID( msg_ptr ) = destination_task;//设置消息数据对应是属于哪个任务的

  // 将要发送的消息数据链接到以osal_qHead开头的数据链表中
  osal_msg_enqueue( &osal_qHead, msg_ptr );

  //
通知主循环有任务等待处理
  osal_set_event( destination_task, SYS_EVENT_MSG );

这样用户任务GenericApp_ProcessEvent就收到一个按键的处理任务,并通过GenericApp_HandleKeys来执行相应的操作。

好了,现在应该对OSAL的消息处理机制有个了解了吧?我们再来复习一下这个按键的处理过程:任务驱动层Hal_ProcessEvent负责对按键进行持续扫描,发现有按键事件后OnBoard_KeyCallback函数向应用层GenericApp_ProcessEvent发送一个有按键需要处理的消息,最终由GenericApp_HandleKeys来负责执行具体的操作。

让我们再回到最初的问题,任务处理表tasksEvents是怎么被改动的呢?初始化程序、其他任务或者本任务主要通过下面几种方式对其操作:
1、设置计时器,当其溢出时,触发事件处理
2、直接通过任务间的消息传递机制触发
3、...(等我想到了再补充)

-- by outman 2010.4.15 00:18   
该睡觉啦~~~

文章来自:http://www.zigbeetech.com/bbs/viewthread.php?tid=16&extra=page%3D1

              加速度 April 15,2010

 

说明:本文转载自http://blog.21ic.com/user1/6121/archives/2010/68309.html

这篇关于ZIGBEE协议栈-OSAL系统框架专题【转载】的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/413402

相关文章

不懂推荐算法也能设计推荐系统

本文以商业化应用推荐为例,告诉我们不懂推荐算法的产品,也能从产品侧出发, 设计出一款不错的推荐系统。 相信很多新手产品,看到算法二字,多是懵圈的。 什么排序算法、最短路径等都是相对传统的算法(注:传统是指科班出身的产品都会接触过)。但对于推荐算法,多数产品对着网上搜到的资源,都会无从下手。特别当某些推荐算法 和 “AI”扯上关系后,更是加大了理解的难度。 但,不了解推荐算法,就无法做推荐系

基于人工智能的图像分类系统

目录 引言项目背景环境准备 硬件要求软件安装与配置系统设计 系统架构关键技术代码示例 数据预处理模型训练模型预测应用场景结论 1. 引言 图像分类是计算机视觉中的一个重要任务,目标是自动识别图像中的对象类别。通过卷积神经网络(CNN)等深度学习技术,我们可以构建高效的图像分类系统,广泛应用于自动驾驶、医疗影像诊断、监控分析等领域。本文将介绍如何构建一个基于人工智能的图像分类系统,包括环境

水位雨量在线监测系统概述及应用介绍

在当今社会,随着科技的飞速发展,各种智能监测系统已成为保障公共安全、促进资源管理和环境保护的重要工具。其中,水位雨量在线监测系统作为自然灾害预警、水资源管理及水利工程运行的关键技术,其重要性不言而喻。 一、水位雨量在线监测系统的基本原理 水位雨量在线监测系统主要由数据采集单元、数据传输网络、数据处理中心及用户终端四大部分构成,形成了一个完整的闭环系统。 数据采集单元:这是系统的“眼睛”,

嵌入式QT开发:构建高效智能的嵌入式系统

摘要: 本文深入探讨了嵌入式 QT 相关的各个方面。从 QT 框架的基础架构和核心概念出发,详细阐述了其在嵌入式环境中的优势与特点。文中分析了嵌入式 QT 的开发环境搭建过程,包括交叉编译工具链的配置等关键步骤。进一步探讨了嵌入式 QT 的界面设计与开发,涵盖了从基本控件的使用到复杂界面布局的构建。同时也深入研究了信号与槽机制在嵌入式系统中的应用,以及嵌入式 QT 与硬件设备的交互,包括输入输出设

JAVA智听未来一站式有声阅读平台听书系统小程序源码

智听未来,一站式有声阅读平台听书系统 🌟&nbsp;开篇:遇见未来,从“智听”开始 在这个快节奏的时代,你是否渴望在忙碌的间隙,找到一片属于自己的宁静角落?是否梦想着能随时随地,沉浸在知识的海洋,或是故事的奇幻世界里?今天,就让我带你一起探索“智听未来”——这一站式有声阅读平台听书系统,它正悄悄改变着我们的阅读方式,让未来触手可及! 📚&nbsp;第一站:海量资源,应有尽有 走进“智听

【专题】2024飞行汽车技术全景报告合集PDF分享(附原数据表)

原文链接: https://tecdat.cn/?p=37628 6月16日,小鹏汇天旅航者X2在北京大兴国际机场临空经济区完成首飞,这也是小鹏汇天的产品在京津冀地区进行的首次飞行。小鹏汇天方面还表示,公司准备量产,并计划今年四季度开启预售小鹏汇天分体式飞行汽车,探索分体式飞行汽车城际通勤。阅读原文,获取专题报告合集全文,解锁文末271份飞行汽车相关行业研究报告。 据悉,业内人士对飞行汽车行业

【区块链 + 人才服务】可信教育区块链治理系统 | FISCO BCOS应用案例

伴随着区块链技术的不断完善,其在教育信息化中的应用也在持续发展。利用区块链数据共识、不可篡改的特性, 将与教育相关的数据要素在区块链上进行存证确权,在确保数据可信的前提下,促进教育的公平、透明、开放,为教育教学质量提升赋能,实现教育数据的安全共享、高等教育体系的智慧治理。 可信教育区块链治理系统的顶层治理架构由教育部、高校、企业、学生等多方角色共同参与建设、维护,支撑教育资源共享、教学质量评估、

软考系统规划与管理师考试证书含金量高吗?

2024年软考系统规划与管理师考试报名时间节点: 报名时间:2024年上半年软考将于3月中旬陆续开始报名 考试时间:上半年5月25日到28日,下半年11月9日到12日 分数线:所有科目成绩均须达到45分以上(包括45分)方可通过考试 成绩查询:可在“中国计算机技术职业资格网”上查询软考成绩 出成绩时间:预计在11月左右 证书领取时间:一般在考试成绩公布后3~4个月,各地领取时间有所不同

系统架构师考试学习笔记第三篇——架构设计高级知识(20)通信系统架构设计理论与实践

本章知识考点:         第20课时主要学习通信系统架构设计的理论和工作中的实践。根据新版考试大纲,本课时知识点会涉及案例分析题(25分),而在历年考试中,案例题对该部分内容的考查并不多,虽在综合知识选择题目中经常考查,但分值也不高。本课时内容侧重于对知识点的记忆和理解,按照以往的出题规律,通信系统架构设计基础知识点多来源于教材内的基础网络设备、网络架构和教材外最新时事热点技术。本课时知识

计算机毕业设计 大学志愿填报系统 Java+SpringBoot+Vue 前后端分离 文档报告 代码讲解 安装调试

🍊作者:计算机编程-吉哥 🍊简介:专业从事JavaWeb程序开发,微信小程序开发,定制化项目、 源码、代码讲解、文档撰写、ppt制作。做自己喜欢的事,生活就是快乐的。 🍊心愿:点赞 👍 收藏 ⭐评论 📝 🍅 文末获取源码联系 👇🏻 精彩专栏推荐订阅 👇🏻 不然下次找不到哟~Java毕业设计项目~热门选题推荐《1000套》 目录 1.技术选型 2.开发工具 3.功能