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í)不管。現(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í)間值。