MC9S08QE16: Problem when Timer is re-enabled

cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

MC9S08QE16: Problem when Timer is re-enabled

Jump to solution
795 Views
June
Contributor I

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.

Labels (1)
Tags (1)
0 Kudos
1 Solution
558 Views
iansmusical
Contributor V

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

View solution in original post

0 Kudos
6 Replies
558 Views
Robinwithu
Senior Contributor I

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

0 Kudos
559 Views
iansmusical
Contributor V

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

0 Kudos
558 Views
June
Contributor I

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;

}

0 Kudos
558 Views
iansmusical
Contributor V

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

0 Kudos
558 Views
June
Contributor I

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.

0 Kudos
558 Views
iansmusical
Contributor V

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

0 Kudos