当前位置: 首页 > news >正文

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_ICALLuint32 next_timeout_prior = osal_next_timeout();
#else /* USE_ICALL */
#ifndef HAL_BOARD_CC2538osalTimeUpdate();
#endifHal_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微控制器系列产品上运行,而无需做任何修改。同时,通过服务和事件的设计,使得任务间的通信更加简洁高效。

相关文章:

  • 网络协议与攻击模拟_08DHCP协议
  • Object.prototype.toString.call个人理解
  • Docker数据管理
  • BTC交易模式 - UXTO - 工具整理
  • 鸿蒙开发案例002
  • 数据结构笔记1
  • php 文件上传
  • Docker部署
  • 书生·浦语大模型--第五节课笔记作业--LMDeploy 大模型量化部署实践
  • 美易官方:美国国债收益率扩大跌幅
  • 解决 Git:ssh: connect to host github.com port 22: Connection timed out 问题的三种方案
  • 探索设计模式的魅力:深入理解面向对象设计的深层原则与思维
  • java获取一段音频/mp3的时长
  • 【无标题】KADB使用DBLINK连接KES验证
  • 【C++干货铺】C++11新特性——右值引用、移动构造、完美转发
  • 《深入 React 技术栈》
  • Android路由框架AnnoRouter:使用Java接口来定义路由跳转
  • ECMAScript 6 学习之路 ( 四 ) String 字符串扩展
  • Elasticsearch 参考指南(升级前重新索引)
  • Rancher-k8s加速安装文档
  • Storybook 5.0正式发布:有史以来变化最大的版本\n
  • 大整数乘法-表格法
  • 电商搜索引擎的架构设计和性能优化
  • 今年的LC3大会没了?
  • 开源SQL-on-Hadoop系统一览
  • 人脸识别最新开发经验demo
  • 使用docker-compose进行多节点部署
  • 算法系列——算法入门之递归分而治之思想的实现
  • 蚂蚁金服CTO程立:真正的技术革命才刚刚开始
  • #Lua:Lua调用C++生成的DLL库
  • #考研#计算机文化知识1(局域网及网络互联)
  • #在 README.md 中生成项目目录结构
  • (C#)Windows Shell 外壳编程系列9 - QueryInfo 扩展提示
  • (附源码)springboot学生选课系统 毕业设计 612555
  • (官网安装) 基于CentOS 7安装MangoDB和MangoDB Shell
  • (循环依赖问题)学习spring的第九天
  • .net 8 发布了,试下微软最近强推的MAUI
  • .net core开源商城系统源码,支持可视化布局小程序
  • .NET Framework .NET Core与 .NET 的区别
  • .Net Redis的秒杀Dome和异步执行
  • .Net 中的反射(动态创建类型实例) - Part.4(转自http://www.tracefact.net/CLR-and-Framework/Reflection-Part4.aspx)...
  • .NET/C# 阻止屏幕关闭,阻止系统进入睡眠状态
  • .netcore如何运行环境安装到Linux服务器
  • @Autowired和@Resource装配
  • @Service注解让spring找到你的Service bean
  • [AIGC] 使用Curl进行网络请求的常见用法
  • [android]-如何在向服务器发送request时附加已保存的cookie数据
  • [Angular 基础] - 指令(directives)
  • [BetterExplained]书写是为了更好的思考(转载)
  • [BZOJ 3282] Tree 【LCT】
  • [BZOJ3757] 苹果树
  • [Cocoa]iOS 开发者账户,联机调试,发布应用事宜
  • [codevs 2822] 爱在心中 【tarjan 算法】
  • [cogs2652]秘术「天文密葬法」
  • [FTP]pureftp部署和优化