ZigBee_CC2530_0DH_關(guān)于協(xié)議棧時(shí)鐘的一些記錄
使用CC2530的芯片,ZStack-CC2530-2.5.1a協(xié)議棧。對(duì)于任意接受到的數(shù)據(jù)包均有afIncomingMSGPacket_t::timestamp。根據(jù)對(duì)協(xié)議棧代碼的閱讀和網(wǎng)上一些資料的查詢,只知道這個(gè)afIncomingMSGPacket_t::timestamp是數(shù)據(jù)包發(fā)送者發(fā)送時(shí)的MAC的時(shí)間。
timestamp unit is based on a basic time unit called Backoff Period(BP)
a Unit Backoff Period = the transmission time of 80bits(0.32ms)
對(duì)于osal_systemClock參數(shù),通過對(duì)協(xié)議棧代碼的閱讀和網(wǎng)上一些資料的查詢,這個(gè)參數(shù)將在osalTimeUpdate()中被更新,而osalTimeUpdate()函數(shù)在osal_run_system中被調(diào)用。而對(duì)于osal_run_system()函數(shù)的功能的介紹,我發(fā)現(xiàn)這是一個(gè)任務(wù)隊(duì)列的檢測(cè)和任務(wù)事件實(shí)現(xiàn)的入口函數(shù)。
1.OSAL 1.1 osal_start_system()函數(shù)
首先,通過協(xié)議棧會(huì)調(diào)用OSAL.c文件中osal_start_system()函數(shù)啟動(dòng)系統(tǒng):
/*********************************************************************
?*?@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();
??}
}該函數(shù)在一個(gè)一直循環(huán)中調(diào)用同位于OSAL.c文件中的osal_run_system()函數(shù): 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();?????????//更新時(shí)鐘
??Hal_ProcessPoll();????????//查看硬件是否有事件發(fā)生
??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是一個(gè)事件的喚起函數(shù),通過該函數(shù)中調(diào)用的osalTimeUpdate()更新系統(tǒng)時(shí)鐘,調(diào)用Hal_ProcessPoll()處理任務(wù)事件,然后循環(huán)的查看是否需要添加任務(wù)事件。對(duì)于Hal_ProcessPoll()函數(shù)我們暫時(shí)不管?,F(xiàn)在我們看一下位置為OSAL_Clock.c文件中的osalTimeUpdate()函數(shù):
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?);
????}
??}
}該函數(shù)通過調(diào)用macMcuPrecisionCount()函數(shù)去返回自定時(shí)器2啟動(dòng)到現(xiàn)在為止的單位是320us的時(shí)間戳tmp,然后對(duì)于使用ticks320us去存儲(chǔ)新增加的時(shí)間數(shù),然后將previousMacTimerTick設(shè)置為當(dāng)前讀取的tmp,再將tmp設(shè)置為距離上次記錄時(shí)間時(shí)新增的時(shí)間和上次轉(zhuǎn)換成單位為ms時(shí)剩下的單位為us的剩余量之和,然后將tmp轉(zhuǎn)換成單位為ms的elapseMSec和小于1000us的單位為40us的remUsTicks,當(dāng)elapseMSec不為0是通過調(diào)用OSAL_Clock.c文件中的osalClockUpdate( elapseMSec )函數(shù)去修改系統(tǒng)時(shí)鐘,調(diào)用OSAL_Timers.c文件中的osalTimerUpdate( elapseMSec )函數(shù)去修改定時(shí)器系統(tǒng)時(shí)鐘。
1.4 系統(tǒng)時(shí)鐘?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參數(shù)可以通過osal_setClock()函數(shù)設(shè)置,也可以通過osal_getClock()函數(shù)讀取:
/*********************************************************************
?*?@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?)函數(shù)如下所示: 1.5 定時(shí)器?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?);
??????}
????}
??}
}通過這個(gè)函數(shù)去判斷是否有定時(shí)器事件產(chǎn)生并更新定時(shí)器事件剩余事件timeout參數(shù)。
2.MAC
2.1?macMcuPrecisionCount()
該函數(shù)位于~/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);
}
?該函數(shù)將當(dāng)前定時(shí)器2的24位溢出寄存器的值讀入?yún)?shù)overflowCount(實(shí)際最大為24bit)中,然后將overflowCount參數(shù)與積累的24位溢出計(jì)數(shù)值accumulatedOverflowCount進(jìn)行加法計(jì)數(shù),此時(shí)overflowCount為從定時(shí)器2開始到現(xiàn)在的總的單位為320us的時(shí)間值。然后通過判斷是否存在溢出計(jì)數(shù)寄存器是否溢出一次,若溢出一次則更新accumulatedOverflowCount和overFlowCount,函數(shù)macGetBackOffTimerRollover()返回的是設(shè)置的溢出周期。然后返回當(dāng)前定時(shí)器2自啟動(dòng)至現(xiàn)在的單位為320us的總的時(shí)間值。
2.2?macMcuOverflowSetCount()函數(shù)
/**************************************************************************************************
?*?@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);
}該函數(shù)作用是在不修改總的時(shí)間值的前提下設(shè)置Timer2的溢出寄存器的值。
而osal_systemClock為當(dāng)前節(jié)點(diǎn)自身晶振讀取修改的以ms為單位的時(shí)間值。





