GPTM down count mode capturing positive edge counts and event interrupt cycle unable to keep RPM stable during high NVIC traffic inside a pre set amount of CCP input edge match counts in the one second interrupt time intervals.
Updated Source 10-03-2016:
Oddly GPTM clock source changed from 120Mhz SYSCLK to 16Mhz PIOS. PIOS clock source reduced false RPM ramping to over 300k RPM in the one second one shot timer interrupt intervals into the edge counts. That was occurring NVIC servicing high amount of ADC/PWM interrupts and only has few hundred RPM miscalculations with PIOS. Original code was interrupting every 2 edges, with code changes below the edges counted rise much higher prior to interrupting and constrained via TnMATCHR at the Oneshot timer reload interval of 1 second.
Shouldn't the edge count timer interrupts and 1 second one shot timer occur at the same clock time if the interrupt priority never changes?
Edge count GPTM-0B = INT36 priority 0x40 and Oneshot GPTM-3A INT 51 priority 0x40.
Example of interrupt period code:
#define TIMER_TICKS_PER_HZ 0x3c //60hz
void TMCCP1TacoEdgeCountInt(void) { /* Clear the CnMIM CnMEIN/CnMCENT interrupt. * To be sure NVIC unpends INT clear twice*/ ROM_TimerIntClear(TIMER0_BASE, TIMER_CAPB_MATCH); ROM_TimerIntClear(TIMER0_BASE, TIMER_CAPB_MATCH); /* Phase lock the interrupt loop of CCP1 input edges * accumulating the frequency of captured edges from * the most recent tick update of TnTBV ISR value. */ g_ui32TimerFrequency += ui32EdgeCount; /* Average pulse times dividing the number of interrupts * incremented per-revolution this captured frequency. */ ui32NewEdgeTime = g_ui32TimerFrequency / 2; /* Update the new taco frequency derived from * the average of edge count interrupt cycles. */ g_ui32TimerFrequency = g_ui32TimerFrequency - ui32NewEdgeTime; /* Trigger GPTM3 oneshot 1 second taco ticks. * Further process the CCP1 edge counts into RPM. */ HWREG(TIMER3_BASE + TIMER_O_CTL) |= TIMER_CTL_TAEN; /* Re-enable GPTM edge counts starting a new edge * capture sequence for processing all the counted * edges in 1 second intervals of count frequency. */ HWREG(TIMER0_BASE + TIMER_O_CTL) |= TIMER_CTL_TBEN; }
/********************************************** * ISR source is 1 second OneShot timer **********************************************/
void FanSpeedTickHandler(void) { uint32_t ui32TBVEdgeCount; uint32_t ui32TBILREdgeCount; /* Clear the periodic 1Hz TIMEOUT interrupt.*/ ROM_TimerIntClear(TIMER3_BASE, TIMER_TIMA_TIMEOUT); /* In down-count mode, the current count of the input * events can be obtained by subtracting the GPTMTnR * or GPTMTnV from the value made up of the GPTMTnPR * and GPTMTnILR register combination. */ /* Get GPTMTBV free running count value. */ ui32TBVEdgeCount = HWREG(TIMER0_BASE + TIMER_O_TBV); /* Get GPTMTBILR current matching edge counts */ ui32TBILREdgeCount = HWREG(TIMER0_BASE + TIMER_O_TBILR); /* Determine the total number of counted edges up to ISR */ ui32EdgeCount = ui32TBILREdgeCount - ui32TBVEdgeCount; /* Disable GPTM-B0 to update TnMATCHR count register */ HWREG(TIMER0_BASE + TIMER_O_CTL) &= ~(TIMER_CTL_TBEN); /* Load number of counted edges 1 second later */ ROM_TimerMatchSet(TIMER0_BASE, TIMER_B, ui32EdgeCount); /* Re-enable GPTM-B0 edge counts. */ HWREG(TIMER0_BASE + TIMER_O_CTL) |= TIMER_CTL_TBEN; /* Reprogram GPTM-3 wide 32bit oneshot timer for 1 second. */ HWREG(TIMER3_BASE + TIMER_O_TAILR) = 0xF42400;; /* Set the Low pass filter taco speed update * of 96EPS in the captured edge counts */ if(ui32EdgeCount > TIMER_TICKS_PER_HZ) { /* Update the Taco RPM formula with the * frequency derived in the counted edges */ TacoSpeedUpdate(g_ui32TimerFrequency); /* Clear the edge counts & frequency */ g_ui32TimerFrequency = 0; return; } else { /* Set the fan speed to zero in the absence * of edge count interrupts, thus indicating * the fan blade has stopped moving. */ ui32FanSpeedSend = ui32FanSpeed = 0; g_ui32TimerFrequency = 0; ui32EdgeCount = 0; } }