ZigBee学习——浅析协议栈

✨记录学习过程

文章目录

  • 一、初识OSAL
    • 1.1 Z-Stack和Zigbee的OSAL是什么关系?
    • 1.2 OSAL可以解决Z-stack在不同厂商的芯片上的使用吗?
  • 二、协议栈运行机制
    • 2.1 初始化涉及内容
    • 2.2 初始化过程

一、初识OSAL

  OSAL,全称是操作系统抽象层(Operating System Abstraction Layer),是一种在操作系统上建立的软件架构。OSAL就是基于事件的轮询查询系统,它提供了一种方法,使得应用程序可以在多种操作系统上运行,而不需要修改代码。在一个典型的OSAL实现中,你会在应用程序代码和特定操作系统代码之间看到一个OSAL。
  在Zigbee中,OSAL被用来解决在不同芯片、不同操作系统上运行Zigbee Stack的问题。无论是基于RTOS的单片机,还是复杂的嵌入式Linux系统,只要实现了相应的OSAL,Zigbee Stack就可以在上面快速移植。
  基于OSAL的设计,软件在从一个操作系统移植到另一个操作系统时,开发者不需要修改每个操作系统的底层设备驱动,而只需要关注OSAL提供的、对外统一的接口就可以了。
以Silicon Labs的Zigbee协议栈为例,它的OSAL提供了一套用于实现任务控制、内存管理、定时器控制、消息队列、中断管理等功能的API,开发者可以使用这些API来实现对Zigbee应用的开发,而无需关心具体硬件和操作系统的差异。这就使得在不同的硬件平台和操作系统上复用Zigbee应用代码变得可能。
  总的来说,OSAL在Zigbee中的作用主要是提供了一种抽象的软件接口,使得Zigbee应用能在不同的硬件平台和操作系统上运行,而无需做大量的修改工作。

1.1 Z-Stack和Zigbee的OSAL是什么关系?

  Z-Stack是Texas Instruments(TI)开发的一款Zigbee协议栈,它允许开发者在TI的微处理器上开发和应用Zigbee的解决方案。Z-Stack在设计之初,就特意采用了操作系统抽象层(OSAL)的结构来组织软件构成。
  所以,简单来说,Z-Stack是Zigbee的一个实现,而OSAL则是Z-Stack中的一部分。在搭建过程中,OSAL扮演的是一个抽象层的角色,为Z-Stack上的应用提供了一套统一的API接口,让开发者无需关心底层硬件和操作系统的具体实现。通过OSAL,Z-Stack可以在TI的多款微处理器上运行。
  同时,OSAL也容许Z-Stack具有更好的跨平台和可移植性。根据OSAL提供的API,可以在不同的硬件设备和操作系统上复用应用代码,极大地提高了代码的复用性和开发效率。
  简单概括一下,Z-Stack是TI的一款Zigbee协议栈实现,而Zigbee的OSAL则是构成Z-Stack的重要组件,提供了一套统一的API接口,使得应用能兼容并在不同的硬件平台和操作系统上运行。

1.2 OSAL可以解决Z-stack在不同厂商的芯片上的使用吗?

答案是不能
  操作系统抽象层(OSAL)的主要目标是为上层应用提供一个标准的API集合,使得应用开发者无需关心特定的硬件和操作系统实现。然而,尽管OSAL能够提供一种机制使得应用代码变得更加可移植,但是这并不意味着Zigbee的实现可以轻易地在不同厂商的芯片上运行。
  当我们谈到Zigbee和其他类似的无线通信技术时,它们所涉及到的通信协议和硬件要求通常比操作系统接口更为复杂和特定。无论是RF模块还是微处理器本身,都需要特定的驱动程序和底层固件才能正常工作。这些驱动和固件通常由芯片制造商提供,且它们的实现除了需要考虑硬件的特性,也需要满足Zigbee协议的要求。
  因此,即使使用了OSAL,我们也无法直接将一个为特定芯片设计的Zigbee实现移植到另一款芯片上。这通常需要芯片制造商参与,为他们的设备提供特定的Zigbee实现,或者提供足够的底层访问权以便其他厂商或开发者自行实现。
  所以,简而言之,OSAL可以提高Zigbee实现的代码可移植性,但并不能解决所有的移植问题。要在不同的芯片上运行Zigbee,仍然需要对特定的硬件和Zigbee协议有深入的理解,同时也需要有适当的驱动和固件支持。

二、协议栈运行机制

2.1 初始化涉及内容

  操作系统抽象层(OSAL):OSAL是Z-Stack的核心部分,它为使用不同操作系统的应用提供了通用的API接口。这些API包括任务调度、内存管理、计时器管理、中断管理等。
  硬件抽象层(HAL):HAL提供了硬件驱动的抽象,使Z-Stack可以运行在不同的TI芯片上,并且无需修改上层应用代码。
  Z-Stack服务:Z-Stack包含一套底层服务,例如网络管理、设备管理、安全管理等。这些服务负责实现Zigbee协议栈的核心功能。
  应用框架:Z-Stack也为用户提供了一个应用框架,用户可以在这个框架下开发自己的Zigbee应用。应用框架处于OSAL之上,可以直接使用OSAL提供的API。

2.2 初始化过程

Z-Stack协议栈的运行可以分为以下三个步骤:

  1. 初始化:Z-Stack启动时,它首先会执行硬件初始化,包括初始化微控制器、RF模块等硬件设备,然后加载并初始化Zigbee协议栈的软件服务。如下图(未截全):
    在这里插入图片描述

  2. 循环处理:一旦初始化完成,Z-Stack会进入主循环。在主循环中,它会通过OSAL管理并调度不同的任务运行,包括接收和处理来自硬件的中断,执行网络管理、设备管理等各种服务,处理来自上层应用的请求,以及通过RF模块发送和接收数据等。
    在这里插入图片描述

  3. 事件处理:除了主循环处理,Z-Stack还通过OSAL的事件队列机制处理任务之间的通信。每个任务都可以生成事件并发送到其他任务的事件队列中,接收任务在主循环中周期性地查看和处理自己的事件队列。
    在这里插入图片描述
    在这里插入图片描述

OSAL系统的两个关键词:任务与事件
三个关键参数:

  1. TaskCnt:任务个数
  2. taskEvents:指向事件表首地址的指针
  3. taskArray:数组,数组中的每一个元素都是指向事件处理函数的指针
void osal_run_system( void )
{
  uint8 idx = 0;

#ifdef USE_ICALL
  uint32 next_timeout_prior = osal_next_timeout();
#else /* USE_ICALL */
#ifndef HAL_BOARD_CC2538
  osalTimeUpdate();
#endif
  Hal_ProcessPoll();	// 查看硬件方面是否有事件发生,例如是否有按键按下、串口是否收到数据等等
#endif /* USE_ICALL */

#ifdef USE_ICALL
  {
    /* Update osal timers to the latest before running any OSAL processes
     * regardless of wakeup callback from ICall because OSAL timers are added
     * relative to the current time. */
    unsigned long newtimestamp = ICall_getTicks();
    uint32 milliseconds;

    if (osal_tickperiod == 1000)
    {
      milliseconds = newtimestamp - osal_last_timestamp;
      osal_last_timestamp = newtimestamp;
    }
    else
    {
      unsigned long long delta = (unsigned long long)
        ((newtimestamp - osal_last_timestamp) & 0xfffffffful);
      delta *= osal_tickperiod;
      delta /= 1000;
      milliseconds = (uint32) delta;
      osal_last_timestamp += (uint32) (delta * 1000 / osal_tickperiod);
    }
    osalAdjustTimer(milliseconds);
    /* Set a value that will never match osal_next_timeout()
     * return value so that the next time can be scheduled.
     */
    next_timeout_prior = 0xfffffffful;
  }
  if (osal_eventloop_hook)
  {
    osal_eventloop_hook();
  }

  for (;;)
  {
    void *msg;
    ICall_EntityID src, dst;
    osal_msg_hdr_t *hdr;
    uint8 dest_id;

    if (ICall_fetchMsg(&src, &dst, &msg) != ICALL_ERRNO_SUCCESS)
    {
      break;
    }
    hdr = (osal_msg_hdr_t *) msg - 1;
    dest_id = osal_dispatch2id(dst);
    if (dest_id == TASK_NO_TASK)
    {
      /* Something wrong */
      ICall_abort();
    }
    else
    {
      /* Message towards one of the tasks */
      /* Create a proxy task ID if necessary and
       * queue the message to the OSAL internal queue.
       */
      uint8 proxyid = osal_alien2proxy(hdr->srcentity);

      if (hdr->format == ICALL_MSG_FORMAT_1ST_CHAR_TASK_ID)
      {
        uint8 *bytes = msg;
        *bytes = proxyid;
      }
      else if (hdr->format == ICALL_MSG_FORMAT_3RD_CHAR_TASK_ID)
      {
        uint8 *bytes = msg;
        bytes[2] = proxyid;
      }
      /* now queue the message to the OSAL queue */
      osal_msg_send(dest_id, msg);
    }
  }
#endif /* USE_ICALL */

  do {
    if (tasksEvents[idx])  // 判断是否有事件发生,当事件发生时,对应的元素会被置1,此时idx表示的就是哪一个事件被触发
    {
      break;	// 跳出do...while
    }
  } while (++idx < tasksCnt);

  if (idx < tasksCnt)		// idx检查合法性
  {
    uint16 events;
    halIntState_t intState;

    HAL_ENTER_CRITICAL_SECTION(intState);	// 进入临界区,这是操作系统的常规操作,避免由于中断影响程序的正常运行
    events = tasksEvents[idx];
    tasksEvents[idx] = 0;  // 置0,表示处理器接下来会去处理该事件对应的任务。
    HAL_EXIT_CRITICAL_SECTION(intState);	//退出临界区

    activeTaskID = idx;
    events = (tasksArr[idx])( idx, events );	// taskArr的每个元素都指向对应事件的处理函数,括号就是处理函数的形参
    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 ) && !defined(USE_ICALL)
  else  // Complete pass through all task events with no activity?
  {
    osal_pwrmgr_powerconserve();  // Put the processor/system into sleep
  }
#endif

  /* Yield in case cooperative scheduling is being used. */
#if defined (configUSE_PREEMPTION) && (configUSE_PREEMPTION == 0)
  {
    osal_task_yield();
  }
#endif

#if defined USE_ICALL
  /* Note that scheduling wakeup at this point instead of
   * scheduling it upon ever OSAL start timer request,
   * would only work if OSAL start timer call is made
   * from OSAL tasks, but not from either ISR or
   * non-OSAL application thread.
   * In case, OSAL start timer is called from non-OSAL
   * task, the scheduling should be part of OSAL_Timers
   * module.
   * Such a change to OSAL_Timers module was not made
   * in order not to diverge the OSAL implementations
   * too drastically between pure OSAL solution vs.
   * OSAL upon service dispatcher (RTOS).
   * TODO: reconsider the above statement.
   */
  {
    halIntState_t intState;

    uint32 next_timeout_post = osal_next_timeout();
    if (next_timeout_post != next_timeout_prior)
    {
      /* Next wakeup time has to be scheduled */
      if (next_timeout_post == 0)
      {
        /* No timer. Set time to the max */
        next_timeout_post = OSAL_TIMERS_MAX_TIMEOUT;
      }
      if (next_timeout_post > osal_max_msecs)
      {
        next_timeout_post = osal_max_msecs;
      }
      /* Restart timer */
      HAL_ENTER_CRITICAL_SECTION(intState);
      ICall_stopTimer(osal_timerid_msec_timer);
      ICall_setTimerMSecs(next_timeout_post, osal_msec_timer_cback,
                          (void *) (++osal_msec_timer_seq),
                          &osal_timerid_msec_timer);
      HAL_EXIT_CRITICAL_SECTION(intState);
    }
  }
#endif /* USE_ICALL */
}

Z-Stack的这种设计,使得应用代码可以在不同的TI微控制器系列产品上运行,而无需做任何修改。同时,通过服务和事件的设计,使得任务间的通信更加简洁高效。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/345992.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

详解Mockito

详解Mockito 1. Mockito简介 在我们的编程世界中&#xff0c;测试是一个非常重要的环节&#xff0c;它能帮助我们确保代码的质量和稳定性。而在众多的测试方法中&#xff0c;Mock测试是一种非常有效的手段。 1.1 什么是 Mock 测试 Mock测试&#xff0c;顾名思义&#xff0c;…

DS:顺序表的实现(超详细!!)

创作不易&#xff0c;友友们给个三连呗&#xff01; 本文为博主在DS学习阶段的第一篇博客&#xff0c;所以会介绍一下数据结构&#xff0c;并在最后学习对顺序表的实现&#xff0c;在友友们学习数据结构之前&#xff0c;一定要对三个部分的知识——指针、结构体、动态内存管理的…

spring eureka集群相关问题

一、集群节点信息如何更新&#xff1f; EurekaServer节点启动的时候&#xff0c;DefaultEurekaServerContext.init()方法调用PeerEurekaNodes.start()方法&#xff0c;start方法中resolvePeerUrls()会从配置文件读取serviceUrl属性值获得集群最新节点信息&#xff0c;通过upda…

微软 AD 介绍 | 安全建议 | 防护

介绍&#xff1a; 什么是Active Directory&#xff08;AD&#xff09;&#xff1f; Active Directory 是由 微软开发的目录服务&#xff0c;用于存储和管理网络中的资源&#xff0c;如计算机、用户、组和其他网络对象。允许组织管理员轻松地管理和验证网络中的用户和计算机。 …

天津大数据培训班推荐,数据分析过程的常见错误

大数据”是近年来IT行业的热词&#xff0c;目前已经广泛应用在各个行业。大数据&#xff0c;又称海量信息&#xff0c;特点是数据量大、种类多、实时性强、数据蕴藏的价值大。大数据是对大量、动态、能持续的数据&#xff0c;通过运用分析、挖掘和整理&#xff0c;实现数据信息…

项目一:踏上Java开发之旅

文章目录 一、实战概述二、实战步骤任务1&#xff1a;安装配置JDK并开发第一个Java程序步骤一&#xff1a;安装JDK步骤二&#xff1a;配置JDK环境变量步骤三&#xff1a;开发第一个Java程序 课堂练习任务1、打印个人信息任务2、打印直角三角形任务3、打印一颗爱心任务4、打印史…

【jetson笔记】解决vscode远程调试qt.qpa.xcb: could not connect to display报错

配置x11转发 jetson远程安装x11转发 安装Xming Xming下载 安装完成后打开安装目录C:\Program Files (x86)\Xming 用记事本打开X0.hosts文件&#xff0c;添加jetson IP地址 后续IP改变需要重新修改配置文件 localhost 192.168.107.57打开Xlaunch Win菜单搜索Xlaundch打开 一…

论文阅读:Vary-toy论文阅读笔记

目录 引言整体结构图方法介绍训练vision vocabulary阶段PDF数据目标检测数据 训练Vary-toy阶段Vary-toy结构数据集情况 引言 论文&#xff1a;Small Language Model Meets with Reinforced Vision Vocabulary Paper | Github | Demo 说来也巧&#xff0c;之前在写论文阅读&…

Linux启动级别和密码问题文件

1、linux启动级别 如果安装的linux默认带的图形化界面&#xff0c;默认的运行级别为5 graphical.target 因为图形化太耗费资源了&#xff0c;想每次启动的时候&#xff0c;更改它的默认允许级别为命令行&#xff08;文本&#xff09; cat /etc/inittab 修改为命令行 多用户…

Springboot项目启动报错:Command line is too long问题解决

启动项目报错:Error running ‘xxxxxxxx’: Command line is too long. Shorten command line for ‘xxxxxxxx’ or also for Application default configuration 方法一 点击提示中的&#xff1a;default&#xff1a;然后在弹出窗口中选择&#xff1a;JAR xxxx xxx&#xff0…

Django、Flask 与 Javascirpt 之间传值与数据转换

常见问题&#xff1a;JavaScript 如何处理Django、Flask传递的数据库数据 Django 、Flask从数据库读出的数据通常保存为&#xff1a;对象列表、字典列表&#xff0c;或 tuple列表形式 # 用object_list 对象列表表示数据库记录 [<Article: id1,title星际穿越影评,body作为一…

Docker安装常用软件集合

大家好&#xff0c;我是豆豆&#xff0c;今天为大家带来了docker安装常用软件&#xff0c;全是干货&#xff0c;没有多余废话&#xff0c;大家点赞收藏吧&#xff0c;以防备用。 1.linux安装docker 环境安装&#xff1a; yum -y install gcc-c 第一步&#xff1a;安装必要的…

Linux命令大全(超详细版)

一 ~ 四章 【点击此处查看】 五、shell 编程 5.1、shell 概述 5.1.1 shell 是什么 Shell是一个命令行解释器&#xff0c;它为用户提供了一个向Linux内核发送请求以便运行程序的界面系统级程序&#xff0c;用户可以用Shell来启动、挂起、停止甚至是编写一些程序。 Shell还是…

使用Python的pygame库实现迷宫游戏

使用Python的pygame库实现迷宫游戏 关于Python中pygame游戏模块的安装使用可见 https://blog.csdn.net/cnds123/article/details/119514520 先给出效果图&#xff1a; 这个游戏能自动生成迷宫布局。 在这个游戏中&#xff0c;玩家将使用键盘箭头键来移动&#xff0c;并且目标…

Sourcetree 更新git账号密码 |Sourcetree 删除git账号密码 |Sourcetree 添加git账号密码

使用Sourcetree 第一次提交代码到git或者从git拉取代码&#xff0c;有可能因为账号的问题不成功。如果提示无法连接等问题&#xff0c;大概率是账号的问题&#xff0c;这时候你就要检查Sourcetree 上的账号密码是否正确。 1.打开Sourcetree&#xff0c;打开设置&#xff0c; …

【小呆的力学笔记】弹塑性力学的初步认知三:广义胡克定律

文章目录 1.7* 广义胡克定律1.8* 广义胡克定律几种形式 1.7* 广义胡克定律 当材料处于弹性状态时&#xff0c;材料的应变和应力呈现线性关系。比如一根杆受拉伸力F作用&#xff0c;轴向会有伸长&#xff0c;同时横向会缩小&#xff0c;如下图所示。 那么有 σ x F A , ε x…

flask_apscheduler源码分析

前言 遵循flask框架的标准的库&#xff0c;称为flask扩展&#xff0c;flask_apscheduler模块就是一个flask扩展&#xff0c;它使用了flask编程上下文&#xff0c;同时内部完全依赖apscheduler。 我近期使用flask_apscheduler遇到了一个所有job全部死亡的bug。现象&#xff1a;j…

编译PCL Qt程序

使用PCL的qt程序时&#xff0c;提示不是用QVTK编译的&#xff0c;所以需要在编译VTK时打开Qt的编译选项&#xff08;由于CMakeList比较复杂&#xff0c;使用CMakeGui进行配置&#xff0c;PCL同理&#xff09;&#xff0c;编译VTK完成后&#xff0c;编译PCL也需要配置Qt支持&…

数字图像处理(实践篇)二十八 使用OpenCV Python中的K-means对图像进行颜色量化处理

目录 1 颜色量化 2 实践 在某些时候,不可避免的某些设备只能生成有限数量的颜色。因此需要执行颜色量化。选择使用cv2.kmeans()函数对颜色量化应用k-means聚类。 1 颜色量化 使用K-means聚类在图像中实现颜色量化的步骤如下: ① 导入依赖库

css文本溢出处理

<!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8" /><meta name"viewport" content"widthdevice-width, initial-scale1.0" /><title>文本溢出处理</title><style>.sing-…