Harmony 3 System Timer and Interrupts
In the process of evaluating Harmony 3, I have converted our free-running timer code that previously accessed the MIPS Core Timer directly over to using the Harmony 3 Timer System Service instead (in Harmony 3 at core/system/time/...
). I replaced our Core Timer interrupt, which accessed the CP0 Count register, with a callback that is given to SYS_TIME_CallbackRegisterMS()
. My callback function gets the software counter using SYS_TIME_CounterGet()
(it does other things with the raw counter value), which worked okay until
I also started using other code that called that function from a non-interrupt context. What would I would see is the counter value jump by extremely large amounts.
(The eventual plan is to ditch our free-running timer and use the H3 Timer service directly--or probably through a thin C++ wrapper--but I just wanted to get something up and running for now. This let me find issues like this one!)
To cut a long story short, what was happening is I was essentially getting an underflow condition that was causing the counter to increment by (1<<32 - some_small_number). To make the story even shorter, I believe I have fixed the issue by modifying the SYS_TIME_PLIBCallback()
function to update the 64-bit counter value before
calling our callback, like so:
static void SYS_TIME_PLIBCallback(uint32_t status, uintptr_t context)
SYS_TIME_COUNTER_OBJ* counterObj = (SYS_TIME_COUNTER_OBJ *)&gSystemCounterObj;
SYS_TIME_TIMER_OBJ* tmrActive = counterObj->tmrActive;
uint32_t elapsedCount = 0;
counterObj->hwTimerCurrentValue = counterObj->timePlib->timerCounterGet();
elapsedCount = SYS_TIME_GetElapsedCount(counterObj->hwTimerCurrentValue);
SYS_TIME_Counter64Update(elapsedCount); // MOVED HERE...
if (tmrActive != NULL)
// SYS_TIME_Counter64Update(elapsedCount); // ...FROM HERE
interruptState = SYS_INT_Disable();
Looking through the other functions called here, I don't believe they are adversely affected by this modification.
On another note, am I correct in thinking that these functions should NOT be called from interrupts other than our timer callbacks we register? I ask because it looks like doing so can cause your interrupt to deadlock inside the SYS_TIME_ResourceLock()
function or return a useless value if it doesn't (this depends on what OSAL layer you're using). We probably could wrap all of our SYS_TIME calls in interrupt disables if we really needed to, but I think it'll be easier to just avoid using these in interrupts if we really shouldn't.