当前位置:首页 > 芯闻号 > 充电吧
[导读]使用CC2530的芯片,ZStack-CC2530-2.5.1a协议栈。对于任意接受到的数据包均有afIncomingMSGPacket_t::timestamp。根据对协议栈代码的阅读和网上一些资料

使用CC2530的芯片,ZStack-CC2530-2.5.1a协议栈。对于任意接受到的数据包均有afIncomingMSGPacket_t::timestamp。根据对协议栈代码的阅读和网上一些资料的查询,只知道这个afIncomingMSGPacket_t::timestamp是数据包发送者发送时的MAC的时间。

timestamp unit is based on a basic time unit called Backoff Period(BP)
a Unit Backoff Period = the transmission time of 80bits(0.32ms)


对于osal_systemClock参数,通过对协议栈代码的阅读和网上一些资料的查询,这个参数将在osalTimeUpdate()中被更新,而osalTimeUpdate()函数在osal_run_system中被调用。而对于osal_run_system()函数的功能的介绍,我发现这是一个任务队列的检测和任务事件实现的入口函数。

1.OSAL 1.1 osal_start_system()函数

首先,通过协议栈会调用OSAL.c文件中osal_start_system()函数启动系统:


/*********************************************************************
 * @fn      osal_start_system
 *
 * @brief
 *
 *   This function is the main loop function of the task system (if
 *   ZBIT and UBIT are not defined). This Function doesn't return.
 *
 * @param   void
 *
 * @return  none
 */
void osal_start_system( void )
{
#if !defined ( ZBIT ) && !defined ( UBIT )
  for(;;)  // Forever Loop
#endif
  {
    osal_run_system();
  }
}

该函数在一个一直循环中调用同位于OSAL.c文件中的osal_run_system()函数: 1.2 osal_run_system()


/*********************************************************************
 * @fn      osal_run_system
 *
 * @brief
 *
 *   This function will make one pass through the OSAL taskEvents table
 *   and call the task_event_processor() function for the first task that
 *   is found with at least one event pending. If there are no pending
 *   events (all tasks), this function puts the processor into Sleep.
 *
 * @param   void
 *
 * @return  none
 */
void osal_run_system( void )
{
  uint8 idx = 0;

  osalTimeUpdate();         //更新时钟
  Hal_ProcessPoll();        //查看硬件是否有事件发生

  do {
    if (tasksEvents[idx])  // Task is highest priority that is ready.
    {
      break;
    }
  } 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 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
}

通过代码我们可以看出,osal_run_system是一个事件的唤起函数,通过该函数中调用的osalTimeUpdate()更新系统时钟,调用Hal_ProcessPoll()处理任务事件,然后循环的查看是否需要添加任务事件。对于Hal_ProcessPoll()函数我们暂时不管。现在我们看一下位置为OSAL_Clock.c文件中的osalTimeUpdate()函数:


1.3 osalTimeUpdate()


/*********************************************************************
 * @fn      osalTimeUpdate
 *
 * @brief   Uses the free running rollover count of the MAC backoff timer;
 *          this timer runs freely with a constant 320 usec interval.  The
 *          count of 320-usec ticks is converted to msecs and used to update
 *          the OSAL clock and Timers by invoking osalClockUpdate() and
 *          osalTimerUpdate().  This function is intended to be invoked
 *          from the background, not interrupt level.
 *
 * @param   None.
 *
 * @return  None.
 */
void osalTimeUpdate( void )
{
  halIntState_t intState;
  uint32 tmp;
  uint32 ticks320us;
  uint16 elapsedMSec = 0;

  HAL_ENTER_CRITICAL_SECTION(intState);
  // Get the free-running count of 320us timer ticks
  tmp = macMcuPrecisionCount();
  HAL_EXIT_CRITICAL_SECTION(intState);
  
  if ( tmp != previousMacTimerTick )
  {
    // Calculate the elapsed ticks of the free-running timer.
    ticks320us = (tmp - previousMacTimerTick) & 0xffffffffu;

    // Store the MAC Timer tick count for the next time through this function.
    previousMacTimerTick = tmp;
    
    // update converted number with remaining ticks from loop and the
    // accumulated remainder from loop
    tmp = (ticks320us * 8) + remUsTicks;

    // Convert the 320 us ticks into milliseconds and a remainder
    CONVERT_320US_TO_MS_ELAPSED_REMAINDER( tmp, elapsedMSec, remUsTicks );

    // Update OSAL Clock and Timers
    if ( elapsedMSec )
    {
      osalClockUpdate( elapsedMSec );
      osalTimerUpdate( elapsedMSec );
    }
  }
}

该函数通过调用macMcuPrecisionCount()函数去返回自定时器2启动到现在为止的单位是320us的时间戳tmp,然后对于使用ticks320us去存储新增加的时间数,然后将previousMacTimerTick设置为当前读取的tmp,再将tmp设置为距离上次记录时间时新增的时间和上次转换成单位为ms时剩下的单位为us的剩余量之和,然后将tmp转换成单位为ms的elapseMSec和小于1000us的单位为40us的remUsTicks,当elapseMSec不为0是通过调用OSAL_Clock.c文件中的osalClockUpdate( elapseMSec )函数去修改系统时钟,调用OSAL_Timers.c文件中的osalTimerUpdate( elapseMSec )函数去修改定时器系统时钟。

1.4 系统时钟 osalClockUpdate( uint16 elapsedMSec )



/*********************************************************************
 * @fn      osalClockUpdate
 *
 * @brief   Updates the OSAL Clock time with elapsed milliseconds.
 *
 * @param   elapsedMSec - elapsed milliseconds
 *
 * @return  none
 */
static void osalClockUpdate( uint16 elapsedMSec )
{
  // Add elapsed milliseconds to the saved millisecond portion of time
  timeMSec += elapsedMSec;

  // Roll up milliseconds to the number of seconds
  if ( timeMSec >= 1000 )
  {
    OSAL_timeSeconds += timeMSec / 1000;
    timeMSec = timeMSec % 1000;
  }
}

其中OSAL_timerSeconds参数可以通过osal_setClock()函数设置,也可以通过osal_getClock()函数读取:



/*********************************************************************
 * @fn      osal_setClock
 *
 * @brief   Set the new time.  This will only set the seconds portion
 *          of time and doesn't change the factional second counter.
 *
 * @param   newTime - number of seconds since 0 hrs, 0 minutes,
 *                    0 seconds, on the 1st of January 2000 UTC
 *
 * @return  none
 */
void osal_setClock( UTCTime newTime )
{
  OSAL_timeSeconds = newTime;
}

/*********************************************************************
 * @fn      osal_getClock
 *
 * @brief   Gets the current time.  This will only return the seconds
 *          portion of time and doesn't include the factional second
 *          counter.
 *
 * @param   none
 *
 * @return  number of seconds since 0 hrs, 0 minutes, 0 seconds,
 *          on the 1st of January 2000 UTC
 */
UTCTime osal_getClock( void )
{
  return ( OSAL_timeSeconds );
}

而OSAL_Timers.c文件中的osalTimerUpdate( elapseMSec )函数如下所示: 1.5 定时器 osalClockUpdate( uint16 elapsedMSec )



/*********************************************************************
 * @fn      osalTimerUpdate
 *
 * @brief   Update the timer structures for a timer tick.
 *
 * @param   none
 *
 * @return  none
 *********************************************************************/
void osalTimerUpdate( uint16 updateTime )
{
  halIntState_t intState;
  osalTimerRec_t *srchTimer;
  osalTimerRec_t *prevTimer;

  HAL_ENTER_CRITICAL_SECTION( intState );  // Hold off interrupts.
  // Update the system time
  osal_systemClock += updateTime;
  HAL_EXIT_CRITICAL_SECTION( intState );   // Re-enable interrupts.

  // Look for open timer slot
  if ( timerHead != NULL )
  {
    // Add it to the end of the timer list
    srchTimer = timerHead;
    prevTimer = (void *)NULL;

    // Look for open timer slot
    while ( srchTimer )
    {
      osalTimerRec_t *freeTimer = NULL;
     
      HAL_ENTER_CRITICAL_SECTION( intState );  // Hold off interrupts.
      
      if (srchTimer->timeout timeout = 0;
      }
      else
      {
        srchTimer->timeout = srchTimer->timeout - updateTime;
      }
      
      // Check for reloading
      if ( (srchTimer->timeout == 0) && (srchTimer->reloadTimeout) && (srchTimer->event_flag) )
      {
        // Notify the task of a timeout
        osal_set_event( srchTimer->task_id, srchTimer->event_flag );
        
        // Reload the timer timeout value
        srchTimer->timeout = srchTimer->reloadTimeout;
      }
      
      // When timeout or delete (event_flag == 0)
      if ( srchTimer->timeout == 0 || srchTimer->event_flag == 0 )
      {
        // Take out of list
        if ( prevTimer == NULL )
          timerHead = srchTimer->next;
        else
          prevTimer->next = srchTimer->next;

        // Setup to free memory
        freeTimer = srchTimer;

        // Next
        srchTimer = srchTimer->next;
      }
      else
      {
        // Get next
        prevTimer = srchTimer;
        srchTimer = srchTimer->next;
      }
      
      HAL_EXIT_CRITICAL_SECTION( intState );   // Re-enable interrupts.
      
      if ( freeTimer )
      {
        if ( freeTimer->timeout == 0 )
        {
          osal_set_event( freeTimer->task_id, freeTimer->event_flag );
        }
        osal_mem_free( freeTimer );
      }
    }
  }
}

通过这个函数去判断是否有定时器事件产生并更新定时器事件剩余事件timeout参数。


2.MAC
2.1 macMcuPrecisionCount() 该函数位于~/MAC/Low Level/System/mac_mcu.c中

/**************************************************************************************************
 * @fn          macMcuPrecisionCount
 *
 * @brief       This function is used by higher layer to read a free running counter driven by
 *              MAC timer.
 *
 * @param       none
 *
 * @return      overflowCount
 **************************************************************************************************
 */
uint32 macMcuPrecisionCount(void)
{
  uint32         overflowCount = 0;
  halIntState_t  s;

  HAL_ENTER_CRITICAL_SECTION(s);

  /* This T2 access macro allows accessing both T2MOVFx and T2Mx */
  MAC_MCU_T2_ACCESS_OVF_COUNT_VALUE();

  /* Latch the entire T2MOVFx first by reading T2M0.
   * T2M0 is discarded.
   */
  T2M0;
  ((uint8 *)&overflowCount)[UINT32_NDX0] = T2MOVF0;
  ((uint8 *)&overflowCount)[UINT32_NDX1] = T2MOVF1;
  ((uint8 *)&overflowCount)[UINT32_NDX2] = T2MOVF2;

  /* the overflowCount needs to account for the accumulated overflow count in Beacon mode.
   */
  overflowCount += accumulatedOverflowCount;
  
  /*
   * Workaround to take care of the case where a rollover just occured and the call to
   * macBackoffTimerPeriodIsr() hasn't yet occured or if one rollover occured during
   * sleep then update the accumulatedoverflowCount with the rollover
   */
   if((prevoverflowCount > overflowCount) && (prevAccumulatedOverflowCount == accumulatedOverflowCount))
  {
    accumulatedOverflowCount += macGetBackOffTimerRollover();
    overflowCount += macGetBackOffTimerRollover();
    /*don't update the rollover since it has been updated already */
    updateRolloverflag = TRUE;
  }

  /* store the current value of overflowcount and accumulatedOverflowCount */
  prevoverflowCount = overflowCount;
  prevAccumulatedOverflowCount = accumulatedOverflowCount;
  HAL_EXIT_CRITICAL_SECTION(s);

  return(overflowCount);
}



 该函数将当前定时器2的24位溢出寄存器的值读入参数overflowCount(实际最大为24bit)中,然后将overflowCount参数与积累的24位溢出计数值accumulatedOverflowCount进行加法计数,此时overflowCount为从定时器2开始到现在的总的单位为320us的时间值。然后通过判断是否存在溢出计数寄存器是否溢出一次,若溢出一次则更新accumulatedOverflowCount和overFlowCount,函数macGetBackOffTimerRollover()返回的是设置的溢出周期。然后返回当前定时器2自启动至现在的单位为320us的总的时间值。
2.2 macMcuOverflowSetCount()函数

/**************************************************************************************************
 * @fn          macMcuOverflowSetCount
 *
 * @brief       Sets the value of the hardware overflow counter.
 *
 * @param       count - new overflow count value
 *
 * @return      none
 **************************************************************************************************
 */
MAC_INTERNAL_API void macMcuOverflowSetCount(uint32 count)
{
  halIntState_t  s;

  MAC_ASSERT(! (count >> 24) );   /* illegal count value */

  /* save the current overflow count */
  accumulatedOverflowCount += macMcuOverflowCount();
  
  /* deduct the initial count */
  accumulatedOverflowCount -= count;

  HAL_ENTER_CRITICAL_SECTION(s);
  MAC_MCU_T2_ACCESS_OVF_COUNT_VALUE();

  /* for efficiency, the 32-bit value is decoded using endian abstracted indexing */
  /* T2OF2 must be written last */
  T2MOVF0 = ((uint8 *)&count)[UINT32_NDX0];    //T2MOVF0 = ((uint8 *)&count)[0];
  T2MOVF1 = ((uint8 *)&count)[UINT32_NDX1];
  T2MOVF2 = ((uint8 *)&count)[UINT32_NDX2];
  HAL_EXIT_CRITICAL_SECTION(s);
}

该函数作用是在不修改总的时间值的前提下设置Timer2的溢出寄存器的值。

而osal_systemClock为当前节点自身晶振读取修改的以ms为单位的时间值。

本站声明: 本文章由作者或相关机构授权发布,目的在于传递更多信息,并不代表本站赞同其观点,本站亦不保证或承诺内容真实性等。需要转载请联系该专栏作者,如若文章内容侵犯您的权益,请及时联系本站删除。
换一批
延伸阅读

9月2日消息,不造车的华为或将催生出更大的独角兽公司,随着阿维塔和赛力斯的入局,华为引望愈发显得引人瞩目。

关键字: 阿维塔 塞力斯 华为

加利福尼亚州圣克拉拉县2024年8月30日 /美通社/ -- 数字化转型技术解决方案公司Trianz今天宣布,该公司与Amazon Web Services (AWS)签订了...

关键字: AWS AN BSP 数字化

伦敦2024年8月29日 /美通社/ -- 英国汽车技术公司SODA.Auto推出其旗舰产品SODA V,这是全球首款涵盖汽车工程师从创意到认证的所有需求的工具,可用于创建软件定义汽车。 SODA V工具的开发耗时1.5...

关键字: 汽车 人工智能 智能驱动 BSP

北京2024年8月28日 /美通社/ -- 越来越多用户希望企业业务能7×24不间断运行,同时企业却面临越来越多业务中断的风险,如企业系统复杂性的增加,频繁的功能更新和发布等。如何确保业务连续性,提升韧性,成...

关键字: 亚马逊 解密 控制平面 BSP

8月30日消息,据媒体报道,腾讯和网易近期正在缩减他们对日本游戏市场的投资。

关键字: 腾讯 编码器 CPU

8月28日消息,今天上午,2024中国国际大数据产业博览会开幕式在贵阳举行,华为董事、质量流程IT总裁陶景文发表了演讲。

关键字: 华为 12nm EDA 半导体

8月28日消息,在2024中国国际大数据产业博览会上,华为常务董事、华为云CEO张平安发表演讲称,数字世界的话语权最终是由生态的繁荣决定的。

关键字: 华为 12nm 手机 卫星通信

要点: 有效应对环境变化,经营业绩稳中有升 落实提质增效举措,毛利润率延续升势 战略布局成效显著,战新业务引领增长 以科技创新为引领,提升企业核心竞争力 坚持高质量发展策略,塑强核心竞争优势...

关键字: 通信 BSP 电信运营商 数字经济

北京2024年8月27日 /美通社/ -- 8月21日,由中央广播电视总台与中国电影电视技术学会联合牵头组建的NVI技术创新联盟在BIRTV2024超高清全产业链发展研讨会上宣布正式成立。 活动现场 NVI技术创新联...

关键字: VI 传输协议 音频 BSP

北京2024年8月27日 /美通社/ -- 在8月23日举办的2024年长三角生态绿色一体化发展示范区联合招商会上,软通动力信息技术(集团)股份有限公司(以下简称"软通动力")与长三角投资(上海)有限...

关键字: BSP 信息技术
关闭
关闭