Hi, i'm having problem when re-enabling timer 1. Here's the problem:
/// This code doesn't work. TPM1C1V doesn't get updated - when i stepped through the assembly code, this register was supposed to get updated, but in the register watch window, it was not.
interrupt VectorNumber_Vtpm1ch1 void Timer_TPM1Channel1SMIrq (void)
{
TPM1C1SC &= 0x7fu; /* clear interrupt flag */
TPM1C1SC &= ~0x40; /* Disable interrupt. */
TPM1C1V = TPM1CNT + 98u; /* 6ms */
TPM1C1SC |= 0x40u; /* enable channel 1 interrupt */
PTED_PTED7 ^= 1;
}
/// When i remove the disable / enable portion, it worked:
interrupt VectorNumber_Vtpm1ch1 void Timer_TPM1Channel1SMIrq (void)
{
TPM1C1SC &= 0x7fu; /* clear interrupt flag */
TPM1C1V = TPM1CNT + 98u; /* 6ms */
PTED_PTED7 ^= 1;
}
/// The timer clock is sourced from bus clock with prescaler of 64.
/// Bus clock is from FLL output with external oscillator (32768Hz) enabled. Here's the initialization code:
SOPT1 = 0x23; // Disable COP, enable STOP,BKGD,RESET
SOPT2 = 0x90;
SPMSC1 = 0x00; // Disable LVD
SPMSC2 = 0x80;
SPMSC3 = 0x00; // Disable LVWIE, low trip points
SCGC1 = 0xE8u; /* Enable bus clock to TPM1,2,3. Bit 3 must be 1 per datasheet. */
SCGC2 = 0x32u; /* Enable bus clock to IRQ and KBI. Bit 1 must be 1 per datasheet. */
ICSC1 = 0x00; /* FLL selected */
ICSC2 = 0xCF; /* Bus frequency diver = 8 */
ICSSC = 0x00; /* DCO low range selected */
/// Here's the timer 1 initialization code:
TPM1SC = 0x00u;
TPM1C1SC = 0x00u;
TPM1C1V = 205u; /* 12.5ms */
TPM1SC = 0x0Eu; /* bus clock, prescaler = 64 */
TPM1C1SC = 0x50u; /* don't enable channel 1 interrupt first, software output compare only */
Appreciate some advice on what's wrong with re-enabling the timer. Thanks.
Solved! Go to Solution.
Hi June,
Take a look at section 16.3.5 of the QE8 RM. I think the issue is to do with register latching into a buffer. If the BDM is active the coherency mechanism is frozen but it's reset if the TPM1C1SC register is written to.
Thanks,
Ian
Hi June,
Try it like this
interrupt VectorNumber_Vtpm1ch1 void Timer_TPM1Channel1SMIrq (void)
{
volatile char tmp;
tmp = TPM1C1SC;
tmp &=~0x40;
TPM1C1SC=tmp; /* Disable interrupt. */
TPM1C1SC &= 0x7fu; /* clear interrupt flag */
TPM1C1V = TPM1CNT + 98u; /* 6ms */
TPM1C1SC |= 0x40u; /* enable channel 1 interrupt */
PTED_PTED7 ^= 1;
}
Best Regards,
Robin
Hi June,
Take a look at section 16.3.5 of the QE8 RM. I think the issue is to do with register latching into a buffer. If the BDM is active the coherency mechanism is frozen but it's reset if the TPM1C1SC register is written to.
Thanks,
Ian
Hi All,
Thanks for your replies. And thanks Ian for pointing me to the latching info.
I moved the order of re-enabling the interrupt and it worked:
interrupt VectorNumber_Vtpm1ch1 void Timer_TPM1Channel1SMIrq (void)
{
TPM1C1SC &= 0x7fu; /* clear interrupt flag */
TPM1C1SC &= ~0x40; /* Disable interrupt. */
TPM1C1SC |= 0x40u; /* enable channel 1 interrupt */
TPM1C1V = TPM1CNT + 98u; /* 6ms */
PTED_PTED7 ^= 1;
}
Hi June,
Am I right in assuming that you disabled the channel interrupt and then re-enabled it again so that you can protect the write to TPM1C1V? If so then you will have broken this mechanism with your code change.
Thanks,
Ian
Hi Ian,
The code i've included is just a simplified illustration. In actual case i'm disabling the interrupt in the ISR after it fires, and re-enabling it somewhere else in a separate state machine, depending on other conditions. Do you recommend a different approach to workaround this problem?
Thanks.
Hi June,
No I think your approach is fine as long as the line:
TPM1C1SC |= 0x40u; /* enable channel 1 interrupt */
Occurs somewhere in your state machine after the line:
TPM1C1V = TPM1CNT + 98u; /* 6ms */
Thus protecting the write to the TPM1C1V register.
Happy programming :smileyhappy:
Thanks,
Ian