Other Parts Discussed in Thread: SYSCONFIG
I did setup the GPTimer1 as described in the TRM. However the tick is not 1ms. Can someone tell me what's wrong?
If i follow the values provided by the TRM, the timer is wrong..
SPRUF98M, Page 2579 (Chapter 16.2.4.2)
TPIR = 232000
TNIR = -768000
TLDR = 0xFFFF FFE0
If i increase the TLDR to 0xFFFF FFE2, it's more accurate but a little bit too fast. With 0xFFFF FFE1 it's still a little bit too slow.
But i would like to have a precise timer, not one calibrated with trial & error! What's wrong?
Example Video:
As you can see in this video, the timer drifts away about 4s within two minutes: youtube GPTimer1 demo
GPTimer1 Registers:
Sourcecode:
void TimerInterrupt::initTickTimer(){
// -------------- GPTIMER1 module intialization --------------
// enable clock
volatile OMAP_PRCM_WKUP_CM_REGS* pPrcmWkupRegs = (OMAP_PRCM_WKUP_CM_REGS*)OMAP_PRCM_WKUP_CM_REGS_PA;
// GPTIMER 1 source clock is 32,768Hz
CLRREG32(&pPrcmWkupRegs->CM_CLKSEL_WKUP, CLKSEL_GPT1);
// enable GPTIMER 1 functional clock
SETREG32(&pPrcmWkupRegs->CM_FCLKEN_WKUP, CM_CLKEN_GPT1);
// enable GPTIMER 1 interface clock
SETREG32(&pPrcmWkupRegs->CM_ICLKEN_WKUP, CM_CLKEN_GPT1);
// reset
// wait until GPTimer is ready to use
unsigned int totalWaitTimeMs = 0;
while (INREG32(&pPrcmWkupRegs->CM_IDLEST_WKUP) & CM_IDLEST_ST_GPT1) {
totalWaitTimeMs++;
}
// configure timer
volatile OMAP_GPTIMER_REGS* pTimerReg = (OMAP_GPTIMER_REGS*)OMAP_GPTIMER1_REGS_PA;
// Soft reset GPTIMER and wait until finished
SETREG32(&pTimerReg->TIOCP, SYSCONFIG_SOFTRESET);
totalWaitTimeMs = 0;
while ((INREG32(&pTimerReg->TISTAT) & GPTIMER_TISTAT_RESETDONE) == 0) {
totalWaitTimeMs++;
}
// clear interrupts
OUTREG32(&pTimerReg->TISR, 0x7);
// enable overflow interrupt
OUTREG32(&pTimerReg->TIER, GPTIMER_TIER_OVERFLOW);
// change period to 1ms with correction for 32.768 Hz clock (see 16.2.4.2)
pTimerReg->TPIR = 232000;
pTimerReg->TNIR = -768000;
pTimerReg->TLDR = 0xFFFFFFE0;
}
void TimerInterrupt::enableTickTimerInterrupt() {
// enable the GPTIMER1 as IRQ source in the interrupt controller
InterruptController::enableInterrupt(IRQ_GPTIMER1);
// ----------- counter setup -------------
// Trigger a counter reload by writing to TTGR
volatile OMAP_GPTIMER_REGS* pTimerReg = (OMAP_GPTIMER_REGS*)OMAP_GPTIMER1_REGS_PA;
OUTREG32(&pTimerReg->TTGR, 0xFFFFFFFF);
// Write pending for register GPT_TTGR
unsigned int totalWaitTimeMs = 0;
while ((INREG32(&pTimerReg->TWPS) & GPTIMER_TWPS_TTGR) == 1) {
totalWaitTimeMs++;
}
// Start the timer, set for auto reload, enable and wait until complete
OUTREG32(&pTimerReg->TCLR, GPTIMER_TCLR_ST|GPTIMER_TCLR_AR);
// Write pending for register GPT_TCLR
totalWaitTimeMs = 0;
while ((INREG32(&pTimerReg->TWPS) & GPTIMER_TWPS_TCLR) == 1) {
totalWaitTimeMs++;
}
}