/* * ======== Timer_getExpiredCounts ======== */ UInt32 Timer_getExpiredCounts(Timer_Object *obj) { UInt key; UInt32 count1, count2; Bool countFlag; key = Hwi_disable(); count1 = Timer_getCount(obj); if (obj->id == 0) { /* SysTick Timer */ countFlag = Hwi_nvic.STCSR & 0x00010000; } else { /* CTM Timer */ /* Test corresponding Int pending flag */ countFlag = Hwi_nvic.ISPR[0] & (1 << (obj->intNum - 16)); } count2 = Timer_getCount(obj); Hwi_restore(key); if (obj->id == 0) { /* SysTick Timer */ if ((count1 > count2) && countFlag) { return (obj->period - count1 + Timer_getPeriod(obj)); } else { return (obj->period - count1); } } else { /* CTM Timer */ if (count2 < count1 && countFlag) { return (count1 + Timer_getPeriod(obj)); } else { return (count1) ; } } }
/* * ======== Timer_getExpiredCounts ======== */ UInt32 Timer_getExpiredCounts(Timer_Object *obj) { /* if timer running with RunMode_DYNAMIC ... */ if (obj->runMode == Timer_RunMode_DYNAMIC) { TimerRegs *timer; UInt32 result; UInt32 count; UInt32 thresh; UInt32 period; UInt32 prev; Bool intrFlag1; Bool intrFlag2; timer = (TimerRegs *)Timer_module->device[obj->id].baseAddr; intrFlag1 = timer->tisr & TIMER_IRQSTATUS_MAT_IT_FLAG; count = Timer_getCount(obj); intrFlag2 = timer->tisr & TIMER_IRQSTATUS_MAT_IT_FLAG; prev = obj->prevThreshold; /* was interrupt pending before read the count? */ if (intrFlag1) { thresh = timer->tmar; /* threshold for interrupt */ period = Timer_getPeriod(obj); /* period count */ /* threshold reached; no wrap thru zero yet */ if (count >= thresh) { result = (count - thresh) + period; } /* threshold reached; count has wrapped thru zero */ else { result = (0xffffffff - thresh + 1) + count + period; } } /* new interrupt now pending, when wasn't before read the count */ else if (intrFlag2) { result = Timer_getPeriod(obj); /* return period count */ } /* interrupt threshold not reached; check if wrapped thru zero */ else if (count >= prev) { result = count - prev; } /* interrupt threshold not reached; count *has* wrapped thru zero */ else { result = (0xffffffff - prev + 1) + count; } return (result); } /* else ... */ else { return (Timer_getCount(obj)); } }
/* * ======== Timer_getExpiredCounts ======== * * This API is used by the TimestampProvider as part of retrieving a timestamp * using a timer and a tick counter. It returns the expired counts since the * last serviced timer interrupt. * * This API must be called with interrupts disabled; the TimestampProvider * must disable interrupts while retrieving the tick count and calling this * API. * * The TimestampProvider uses a 32-bit timer and 32-bit tick count to track * the timestamp. The tick count either comes from the Clock module or is * stored in the TimestampProvider's module state and incremented by an ISR * when the timer expires. * * For MSP430 we have 16-bit timers, and use a timer compare feature to * trigger an interrupt upon a specific threshold count being reached. The * timer counts can rollover (going thru zero), on the way to reaching the * next threshold. We need to accommodate this rollover as part of * determining expired counts. * * We also need to handle the case where there is a large period value used * for the timer, and the timer is ticking at a fast rate (e.g., the CPU * rate, via an SMCLK selection). For this case, it is possible that * interrupts are disabled before the timer reaches threshold, and then the * timer reaches the threshold count and asserts an interrupt, and then * continues to count upwards before it is read in this routine. If the * timer rolled past zero, then we need to know that there is an interrupt * pending, otherwise we'd report a low count, versus the period plus * that low count. * * To be sure to catch the interrupt, we sample the interrupt flag, read * the count, and then sample the interrupt flag again: * * intrFlag1 * count * intrFlag2 * * If intrFlag1 is set, then we know we've reached the period count, and * need to add it to the reported counts. If intrFlag2 is set, but * intrFlag1 wasn't, we know the timer just reached threshold, and simply * report the period count. * * If neither interrupt flag is set, we can then compute the expired counts by * comparing the count to the previous interrupt threshold (saved in the * timer object). If the current count is greater than or equal to the * previous threshold value, then we know there has been no counter rollover, * and the expired counts is simply: * * result = count - prevThresh * * If the current count is less than the previous threshold, then we know a * counter rollover has occurred since the last ISR. In this case, the * expired counts has to include those between the previous threshold and * zero, plus any counts after rolling past zero: * * result = (0 - prevTresh) + count * * Similar logic to compare the current count to previous threshold can * be used for the case where we know intrFlag1 has been set, and we * need to figure the counts to be added to the period counts. * */ UInt32 Timer_getExpiredCounts(Timer_Object *obj) { ti_catalog_msp430_peripherals_timers_TimerRegs *timer; UInt32 result32; UInt32 count32; UInt32 thresh32; UInt32 period32; UInt32 prev32; Bool intrFlag1; Bool intrFlag2; timer = (ti_catalog_msp430_peripherals_timers_TimerRegs *) Timer_module->device[obj->id].baseAddr; intrFlag1 = timer->cctl_0 & TIMER_COMPARE_INTR_PENDING; count32 = Timer_getCount(obj) & 0xffff; intrFlag2 = timer->cctl_0 & TIMER_COMPARE_INTR_PENDING; prev32 = obj->prevThreshold & 0xffff; /* interrupt pending before read count? */ if (intrFlag1) { thresh32 = timer->cc_compare_0 & 0xffff; /* threshold for interrupt */ period32 = Timer_getPeriod(obj) & 0xffff; /* period count */ /* threshold reached; no wrap thru zero yet */ if (count32 >= thresh32) { result32 = (count32 - thresh32) + period32; } /* threshold reached; count has wrapped thru zero */ else { result32 = (0x10000 - thresh32) + count32 + period32; } } /* new interrupt now pending, when wasn't before read the count */ else if (intrFlag2) { result32 = Timer_getPeriod(obj) & 0xffff; /* return period count */ } /* interrupt threshold not reached; check if wrapped thru zero */ else if (count32 >= prev32) { result32 = count32 - prev32; } /* interrupt threshold not reached; count has wrapped thru zero */ else { result32 = (0x10000 - prev32) + count32; } return (result32); }
/* * ======== TimestampProvider_get32 ======== * The 32-bit timestamp can be retrieved more efficiently than the 64-bit one, * so it has a different implementation. */ Bits32 TimestampProvider_get32() { /* * If we're sharing the Clock timer, get the timestamp by using the Clock * tick count. */ if (TimestampProvider_useClockTimer) { UInt key; UInt32 timestamp; /* * Disable interrupts so that the Clock tick count doesn't change if * the timer expires while we are reading it. */ key = Hwi_disable(); /* * timestamp = (clock ticks) x (tick period) + (current timer count) * The 'getExpiredCounts' API retrieves the current Timer count and * also accounts for timer rollover. */ timestamp = Clock_getTicks() * Timer_getPeriod(MOD->timer) + Timer_getExpiredCounts(MOD->timer); Hwi_restore(key); return (timestamp); } /* If we have a dedicated timer, just read the timer count. */ else { return (Timer_getCount(MOD->timer)); } }
/* * ======== TimestampProvider_get32 ======== */ Bits32 TimestampProvider_get32() { if (TimestampProvider_useClockTimer) { UInt key; UInt32 timestamp; key = Hwi_disable(); timestamp = Clock_getTicks() * Timer_getPeriod(MOD->timer) + Timer_getExpiredCounts(MOD->timer); Hwi_restore(key); return (timestamp); } else { return (Timer_getCount(MOD->timer)); } }
/* * ======== Timer_getExpiredCounts ======== */ UInt32 Timer_getExpiredCounts(Timer_Object *obj) { UInt key; UInt32 count1, count2; Bool itrFlag; key = Hwi_disable(); count1 = Timer_getCount(obj); itrFlag = (Hwi_l1Intc.ITR & (0x1 << obj->intNum)); count2 = Timer_getCount(obj); Hwi_restore(key); if (count2 < count1 && itrFlag) { return (count1 + Timer_getPeriod(obj)); } else { return (count1) ; } }
/* * ======== TimestampProvider_get64 ======== */ Void TimestampProvider_get64(Types_Timestamp64 *result) { UInt key; UInt64 timestamp; key = Hwi_disable(); if (TimestampProvider_useClockTimer) { timestamp = Clock_getTicks() * Timer_getPeriod(MOD->timer) + Timer_getExpiredCounts(MOD->timer); } else { timestamp = ((UInt64)MOD->hi << 32) + Timer_getExpiredCounts(MOD->timer); } Hwi_restore(key); result->hi = timestamp >> 32; result->lo = timestamp; }
/* * ======== Timer_getExpiredCounts ======== */ UInt32 Timer_getExpiredCounts(Timer_Object *obj) { UInt key; UInt32 count1, count2; Bool countFlag; key = Hwi_disable(); count1 = Timer_getCount(obj); /* Test corresponding Int pending flag */ countFlag = Hwi_nvic.ISPR[0] & (1 << (obj->intNum - 16)); count2 = Timer_getCount(obj); Hwi_restore(key); if (count2 < count1 && countFlag) { return (count1 + Timer_getPeriod(obj)); } else { return (count1) ; } }
/* * ======== Timer_getExpiredCounts ======== */ UInt32 Timer_getExpiredCounts(Timer_Object *obj) { UInt key; UInt32 count1, count2; Bool countFlag; extern cregister volatile unsigned int IFR; key = Hwi_disable(); count1 = Timer_getCount(obj); /* Test corresponding Int pending flag */ countFlag = IFR & (1 << obj->intNum); count2 = Timer_getCount(obj); Hwi_restore(key); /* CTM Timer */ if (count2 < count1 && countFlag) { return (count1 + Timer_getPeriod(obj)); } else { return (count1) ; } }
/* * ======== TimestampProvider_get64 ======== * This API has different implementations based on whether we're using a * dedicated timer or sharing the Clock timer. * If we're sharing the Clock timer, we have to multiply the Clock tick count * by the Clock tick period. If we have a dedicate timer, the timer period is * 2^32, so we can just use the MOD->hi tick count as the upper 32-bits of the * timestamp. */ Void TimestampProvider_get64(Types_Timestamp64 *result) { UInt key; /* * If we're sharing the Clock timer, get the timestamp by using the Clock * tick count. */ if (TimestampProvider_useClockTimer) { UInt64 timestamp; /* * Disable interrupts so that the Clock tick count doesn't change if * the timer expires while we are reading it. */ key = Hwi_disable(); /* * timestamp = (clock ticks) x (tick period) + (current timer count) * The 'getExpiredCounts' API retrieves the current Timer count and * also accounts for timer rollover. */ timestamp = (UInt64) Clock_getTicks() * Timer_getPeriod(MOD->timer) + Timer_getExpiredCounts(MOD->timer); Hwi_restore(key); /* * Copy the value into the result structure. * * The 28x is little endian, so it stores the 16-bit words * in reverse order. For example, the value * 0xFEDCBA9876543210 * Is stored as: * Address Value * 0x0 0x3210 * 0x1 0x7654 * 0x2 0xBA98 * 0x3 0xFEDC * * To retrieve the lower 32 bits, simply cast the value as a UInt32. * To retrieve the upper 32 bits, cast the address of 'timestamp' as a * pointer to a UInt32, increment the pointer by 1, then retrieve the * value at that address. */ result->lo = (UInt32) timestamp; result->hi = *(((UInt32 *) ×tamp) + 1); } /* If we have a dedicated timer... */ else { /* Disable interrupts while reading the tick count and timer value. */ key = Hwi_disable(); /* Use the tick counter as the upper 32-bits. */ result->hi = MOD->hi; /* * Get the timer value as the lower 32-bits. This API will also take * timer rollover into account and add 1 to result->hi if necessary. */ Timer_getExpiredCounts64(MOD->timer, result); Hwi_restore(key); } }