Z-Stack中OSAL定时器事件触发流程分析

2023-11-22 22:48

本文主要是介绍Z-Stack中OSAL定时器事件触发流程分析,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

写在前面:之所以会注意到定时器事件是因为在做断点调试的时候会进入osal_start_timerEx这个函数,而且这个函数之后还会涉及到hal_uartpoll有关DMA之类的函数,于是发现了这篇文章,写得很详细。

     我们先看一下osal_start_timerEx()函数,是怎么调用到最后的osal_set_event()函数,触发事件处理的。下面是osal_start_timerEx()函数的源代码,从中间我们并没有看到有关osal_set_events()函数的相关信息。当然这个函数中没有直接的调用该函数,那osal_set_events()函数,是怎么和我们的osal_start_timerEx()函数联系起来的呢?我们应该先从系统中的主循环开始查找其中的奥妙。 
byte osal_start_timerEx( byte taskID, UINT16 event_id, UINT16 timeout_value )
{
halIntState_t intState;
  osalTimerRec_t *newTimer;
 
  HAL_ENTER_CRITICAL_SECTION( intState );  // Hold off interrupts.
 
  // Add timer
  newTimer = osalAddTimer( taskID, event_id, timeout_value );
  if ( newTimer )
  {
#ifdef POWER_SAVING
    // Update timer registers
    osal_retune_timers();
    (void)timerActive;
#endif
    // Does the timer need to be started?
    if ( timerActive == FALSE )
    {
      osal_timer_activate( TRUE );
    }
  }
   先在osal_start_system( void )函数开始时调用Hal_ProcessPoll();因为Hal_ProcessPoll()函数是在一个死循环中,所以每过一定的时间就会执行到。在Z-Stack OSAL中这个时种节奏定义是1ms,由8bits HW_TIMER4来控制,这些都可以有程序员进行修改,我们先看一下Hal_ProcessPoll()函数。
void Hal_ProcessPoll ()
{
 
 
  HalTimerTick();
 
 
#if (defined HAL_UART) && (HAL_UART == TRUE)
  HalUARTPoll();
#endif
 
}
   在这是就会有一个疑问是在什么时候溢出呢?我们知道每个系统都会有一个节拍,也就是系统的时钟,在OSAL中也不例外,这个时钟就是由Timer4提供的计时的。
在void InitBoard(byte level)函数中调用下面这个函数,进行了配置
HalTimerConfig (OSAL_TIMER,                     // 8bit timer2
                  HAL_TIMER_MODE_CTC,         // Clear Timer on Compare
                  HAL_TIMER_CHANNEL_SINGLE,    // Channel 1 - default
                  HAL_TIMER_CH_MODE_OUTPUT_COMPARE,   // Output Compare mode
                  OnboardTimerIntEnable,           // Use interrupt
                  Onboard_TimerCallBack);         // Channel Mode
 
      OSAL的Timer定义好之后,就要启动Timer,在网络层初始化函数nwk_init(taskID++)执行完后,Timer启动了,也就是说在网络层的初始化函数中启动了Timer,网络层的代码是不开源的,所以也就无法看到其真正的启动代码。
   每当1ms心跳来临时,Timer4的中断标志置位,这样在OSAL的死循环中,通过一开始的Hal_ProcessPoll()函数检测到这中断标志位,在Hal_ProcessPoll ()函数中调用了  HalTimerTick();函数,这个函数是专门用来检测是否有硬件定时器溢出的。如果定时器有溢出的话,就要调用halProcessTimerX ();(X表示 1 3 4).这里假设是HalProcessTimer4(),在HalProcessTimer4()中,通过下面的一句话,调用了函数
halTimerSendCallBack (HAL_TIMER_2, 
HAL_TIMER_CHANNEL_B,
HAL_TIMER_CH_MODE_OUTPUT_COMPARE);
在halTimerSendCallBack中调用了真正的回调函数,
if (halTimerRecord[hwtimerid].callBackFunc)
    (halTimerRecord[hwtimerid].callBackFunc) (timerId, channel, channelMode);
这个回调函数通过
uint8 HalTimerConfig (uint8 timerId, uint8 opMode, uint8 channel, uint8 channelMode,bool intEnable, halTimerCBack_t cBack)
   也就是前面的那个函数。进行的配置。在InitBoard()函数中调用了函数HalTimerConfig()。
   也就是调用了Onboard_TimerCallBack()函数,在这个函数中调用了osal_update_timers();函数,这个函数又调用了osalTimerUpdate( tmr_decr_time );这个函数中又调用了osal_set_events()函数。
osalTimerUpdate( tmr_decr_time )函数会去轮询Timer事件链表,Timer事件链表是下面这样一个数据结构,next指向下一个Timer事件,timerout值表明本Timer事件还需要timerout个心跳才需要被处理,因为些处的心跳是1ms,所以也就是说还需要timerout个ms才处理。也就是检测timeout是否小于1ms,如果小于1ms,则发出event_flag这个消息到消息队列,这个消息隶属于task_id这个任务,如果不大于1ms,说明该Timer事件还不到处理的时间,则Timeout= Timeout-1,然后继续等待下一次心跳,Timer事件链表的维护是通过osal_start_timerEx()这个函数来实现的。这样就把前面的osalTimerUpdate( tmr_decr_time )函数和我们应用程序中经常调用的osal_start_timerEx()函数联系在了一起,
typedef struct
{
  void *next;
  UINT16 timeout;
  UINT16 event_flag;
  byte task_id;
} osalTimerRec_t;
   如果到达定时器的定时值,也就是说Timeout< 1ms后,就会发送一个event_flag这个消息给消息队列,这样在主循环中就可以检测到这个消息,并且检测到这个消息是属于那个任务的,然后,调用相应的消息处理函数。

这篇关于Z-Stack中OSAL定时器事件触发流程分析的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



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

相关文章

Security OAuth2 单点登录流程

单点登录(英语:Single sign-on,缩写为 SSO),又译为单一签入,一种对于许多相互关连,但是又是各自独立的软件系统,提供访问控制的属性。当拥有这项属性时,当用户登录时,就可以获取所有系统的访问权限,不用对每个单一系统都逐一登录。这项功能通常是以轻型目录访问协议(LDAP)来实现,在服务器上会将用户信息存储到LDAP数据库中。相同的,单一注销(single sign-off)就是指

Spring Security基于数据库验证流程详解

Spring Security 校验流程图 相关解释说明(认真看哦) AbstractAuthenticationProcessingFilter 抽象类 /*** 调用 #requiresAuthentication(HttpServletRequest, HttpServletResponse) 决定是否需要进行验证操作。* 如果需要验证,则会调用 #attemptAuthentica

性能分析之MySQL索引实战案例

文章目录 一、前言二、准备三、MySQL索引优化四、MySQL 索引知识回顾五、总结 一、前言 在上一讲性能工具之 JProfiler 简单登录案例分析实战中已经发现SQL没有建立索引问题,本文将一起从代码层去分析为什么没有建立索引? 开源ERP项目地址:https://gitee.com/jishenghua/JSH_ERP 二、准备 打开IDEA找到登录请求资源路径位置

禁止平板,iPad长按弹出默认菜单事件

通过监控按下抬起时间差来禁止弹出事件,把以下代码写在要禁止的页面的页面加载事件里面即可     var date;document.addEventListener('touchstart', event => {date = new Date().getTime();});document.addEventListener('touchend', event => {if (new

SWAP作物生长模型安装教程、数据制备、敏感性分析、气候变化影响、R模型敏感性分析与贝叶斯优化、Fortran源代码分析、气候数据降尺度与变化影响分析

查看原文>>>全流程SWAP农业模型数据制备、敏感性分析及气候变化影响实践技术应用 SWAP模型是由荷兰瓦赫宁根大学开发的先进农作物模型,它综合考虑了土壤-水分-大气以及植被间的相互作用;是一种描述作物生长过程的一种机理性作物生长模型。它不但运用Richard方程,使其能够精确的模拟土壤中水分的运动,而且耦合了WOFOST作物模型使作物的生长描述更为科学。 本文让更多的科研人员和农业工作者

MOLE 2.5 分析分子通道和孔隙

软件介绍 生物大分子通道和孔隙在生物学中发挥着重要作用,例如在分子识别和酶底物特异性方面。 我们介绍了一种名为 MOLE 2.5 的高级软件工具,该工具旨在分析分子通道和孔隙。 与其他可用软件工具的基准测试表明,MOLE 2.5 相比更快、更强大、功能更丰富。作为一项新功能,MOLE 2.5 可以估算已识别通道的物理化学性质。 软件下载 https://pan.quark.cn/s/57

C++——stack、queue的实现及deque的介绍

目录 1.stack与queue的实现 1.1stack的实现  1.2 queue的实现 2.重温vector、list、stack、queue的介绍 2.1 STL标准库中stack和queue的底层结构  3.deque的简单介绍 3.1为什么选择deque作为stack和queue的底层默认容器  3.2 STL中对stack与queue的模拟实现 ①stack模拟实现

衡石分析平台使用手册-单机安装及启动

单机安装及启动​ 本文讲述如何在单机环境下进行 HENGSHI SENSE 安装的操作过程。 在安装前请确认网络环境,如果是隔离环境,无法连接互联网时,请先按照 离线环境安装依赖的指导进行依赖包的安装,然后按照本文的指导继续操作。如果网络环境可以连接互联网,请直接按照本文的指导进行安装。 准备工作​ 请参考安装环境文档准备安装环境。 配置用户与安装目录。 在操作前请检查您是否有 sud

线性因子模型 - 独立分量分析(ICA)篇

序言 线性因子模型是数据分析与机器学习中的一类重要模型,它们通过引入潜变量( latent variables \text{latent variables} latent variables)来更好地表征数据。其中,独立分量分析( ICA \text{ICA} ICA)作为线性因子模型的一种,以其独特的视角和广泛的应用领域而备受关注。 ICA \text{ICA} ICA旨在将观察到的复杂信号

【软考】希尔排序算法分析

目录 1. c代码2. 运行截图3. 运行解析 1. c代码 #include <stdio.h>#include <stdlib.h> void shellSort(int data[], int n){// 划分的数组,例如8个数则为[4, 2, 1]int *delta;int k;// i控制delta的轮次int i;// 临时变量,换值int temp;in