Small PIT Frequency Error in MOD5213
Posted: Wed Sep 24, 2014 5:05 pm
Hello All,
While working on a MOD5213 that uses a DMA timer, I added code to report the number of DMA timer interrupts versus seconds as computed by the OS, and found there was a small discrepancy. Since the DMA timer and PIT are both driven by the same clock, and the values I had chosen for both divide evenly into the clock frequency, it seemed wrong that I wasn't getting precisely X interrupts for Y ticks of the OS. I've tracked down the issues, and they probably don't matter in 99.9% of all cases, but I thought I would report what I found, just in case in matters to someone else.
The NB appnote for PIT on MOD5213 has the correct formula for computing PIT timeout (T) as a function of system clock frequency (S), prescaler (P), and modulus (M):
T = [P * (M+1) * 2] / S
If you want to compute the modulus (M) to get a specific PIT interrupt frequency (F = 1/T):
F = 1/T = S / [P * (M+1) * 2]
M+1 = S / (P*2) / F = (S/2) / P / F
M = [(S/2) / P / F] - 1
The first issue I found is that MOD5213\system\bsp.c does not make the "-1" correction when it computes the modulus for a given value of TICKS_PER_SECOND, so the PIT period is 1 clock longer than it should be, and the PIT frequency is ever-so-slightly lower than intended. I fixed that issue, and the error in number of interrupts became smaller, but did not go away entirely.
The second issue is trickier, and I found it on a freescale community board.
PIT interrupts are cleared by writing PIF=1 in the PCSR register:
sim.pit[0].pcsr |= 0x0004;
However, the PCSR register is a word, so the code above generates word accesses, and the result is that the upper byte of PCSR, which contains the prescaler (PRE), is also written. Any time the prescaler is written, even if it's the same value, the prescaler counter is reset. Assuming this happens early in the ISR, the effect is small, but it cause the new PIT period to "start over", and to again be slightly longer than it should be. The code below writes only the LOW byte of PCSR, and it fixes the second problem:
((BYTE*)&sim.pit[0].pcsr)[1] |= 0x04;
With these two changes, I get the exact count of DMA timer interrupts per "second" as measured by the OS, and that's true for all values of PIT prescaler.
Here's the link to the message on the Freescale community board that explains the issue with clearing PIT interrupts:
https://community.freescale.com/thread/70487
Joe
While working on a MOD5213 that uses a DMA timer, I added code to report the number of DMA timer interrupts versus seconds as computed by the OS, and found there was a small discrepancy. Since the DMA timer and PIT are both driven by the same clock, and the values I had chosen for both divide evenly into the clock frequency, it seemed wrong that I wasn't getting precisely X interrupts for Y ticks of the OS. I've tracked down the issues, and they probably don't matter in 99.9% of all cases, but I thought I would report what I found, just in case in matters to someone else.
The NB appnote for PIT on MOD5213 has the correct formula for computing PIT timeout (T) as a function of system clock frequency (S), prescaler (P), and modulus (M):
T = [P * (M+1) * 2] / S
If you want to compute the modulus (M) to get a specific PIT interrupt frequency (F = 1/T):
F = 1/T = S / [P * (M+1) * 2]
M+1 = S / (P*2) / F = (S/2) / P / F
M = [(S/2) / P / F] - 1
The first issue I found is that MOD5213\system\bsp.c does not make the "-1" correction when it computes the modulus for a given value of TICKS_PER_SECOND, so the PIT period is 1 clock longer than it should be, and the PIT frequency is ever-so-slightly lower than intended. I fixed that issue, and the error in number of interrupts became smaller, but did not go away entirely.
The second issue is trickier, and I found it on a freescale community board.
PIT interrupts are cleared by writing PIF=1 in the PCSR register:
sim.pit[0].pcsr |= 0x0004;
However, the PCSR register is a word, so the code above generates word accesses, and the result is that the upper byte of PCSR, which contains the prescaler (PRE), is also written. Any time the prescaler is written, even if it's the same value, the prescaler counter is reset. Assuming this happens early in the ISR, the effect is small, but it cause the new PIT period to "start over", and to again be slightly longer than it should be. The code below writes only the LOW byte of PCSR, and it fixes the second problem:
((BYTE*)&sim.pit[0].pcsr)[1] |= 0x04;
With these two changes, I get the exact count of DMA timer interrupts per "second" as measured by the OS, and that's true for all values of PIT prescaler.
Here's the link to the message on the Freescale community board that explains the issue with clearing PIT interrupts:
https://community.freescale.com/thread/70487
Joe