Problem switching clock dividers (outdiv4) if timer is used

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

Problem switching clock dividers (outdiv4) if timer is used

686 Views
carlostadeoorte
Contributor III

KDS 3.0

SDK 1.2

processor: kl03

using freedom board.

Using openSDA debugger

Hello dear freescale comunity,

In my application, I switch between 8MHz/8MHz and 48MHz/24MHz clock for the core/bus speed. It all works fine... except when I use the timer in between.  If I use the itmer then my application goes into reset vector. 

The line that seems to fail is:

      SIM_CLKDIV1 =  SIM_CLKDIV1_OUTDIV4(1);           //Divide bus/flash clock by 2

   and

      SIM_CLKDIV1 = ~SIM_CLKDIV1_OUTDIV4_MASK;                                 //Set bus speed to 8Mhz

I appreciate your help with this.

Thank you!

The full code to reproduce the problem is below:

#include "fsl_device_registers.h"

#include "fsl_port_hal.h"

#include "fsl_gpio_hal.h"

#include "fsl_tpm_driver.h"

#define TPM_INSTANCE 0

int main(void) 

{

    volatile unsigned int i,j;

    CLOCK_SYS_EnablePortClock(PORTB_IDX);

    //Set ports as GPIO

    configure_gpio();

    while(1) {

      __asm("CPSID i");                            // Disable interrupts

      MCG_MC = MCG_MC_HIRCEN_MASK;

      MCG_C1 &= ~MCG_C1_CLKS_MASK;                       // Enable Main Clock Source of the 48MHz

      while(MCG_S & MCG_S_CLKST_MASK) {  };         //Wait until 48 Mhz clock gets selected

      SIM_CLKDIV1 =  SIM_CLKDIV1_OUTDIV4(1);           //Divide bus/flash clock by 2

      __asm("CPSIE i");                            // Disable interrupts

      //Enable clock to timer

      SIM_SCGC6 |= SIM_SCGC6_TPM0_MASK;

      SIM_SOPT2 |= SIM_SOPT2_TPMSRC(kTpmClockSourceModuleHighFreq);

      ////////////// Works if I comment all the timer stuff

/*

      TPM0_C0SC = TPM_CnSC_CHF_MASK ;       //Clear ch0 flag and stop timer1, channel0

      TPM0_SC  &= ~TPM_SC_CMOD_MASK;        //Make sure TPM is disabled

      TPM0_CNT = 0;

      TPM0_MOD = 65535u;

      TPM0_C0SC = 0;                        //Count up

      TPM0_SC |= TPM_SC_TOF_MASK;           //Clear overflow flag if any

      TPM0_SC |= TPM_SC_CMOD(kTpmClockSourceModuleClk);  //Fire it up

//*/

      PTB -> PTOR|=0x1<<10;

      for(i=0;i<10;i++) { }

      ////////////// Works if I comment all the timer stuff

/*

      TPM0_SC = 0;  //Stop counter

      j  = TPM0_CNT & TPM_CNT_COUNT_MASK;

      TPM0_CNT = 0x0; //Clear count

      TPM0_MOD = 0x0; //Clear mod

*/

      __asm("CPSID i");                            // Disable interrupts

      SIM_SCGC6 &= ~SIM_SCGC6_TPM0_MASK;

      SIM_SOPT2 &= ~SIM_SOPT2_TPMSRC_MASK;

      MCG_C2 = MCG_C2_IRCS(1);

      MCG_C1 = MCG_C1_IRCLKEN(1);

      MCG_C1 = MCG_C1_CLKS(1);                         //Run at 8MHz

      while(MCG_S & MCG_S_CLKST_MASK != 0x1) { }       //Wait until clock is selected

      SIM_CLKDIV1 = ~SIM_CLKDIV1_OUTDIV4_MASK;                                 //Set bus speed to 8Mhz

      MCG_SC = MCG_SC_FCRDIV(0x0);                     //0x07 = Divide 2Mhz clock by 128=15.625kHz

      MCG_MC =0;

      __asm("CPSIE i");                                // Enable interrupts

    }

    return 0;

}

void configure_gpio(void) {

  unsigned int i;

  PORT_HAL_SetMuxMode(PORTB_BASE_PTR, 10u,kPortMuxAsGpio);    //Switch pin attached to PB0 ---not anymore

  GPIO_HAL_SetPinDir(GPIOB_BASE_PTR, 10u, kGpioDigitalOutput); //Sensing on port B0

}

////////////////////////////////////////////////////////////////////////////////

// EOF

////////////////////////////////////////////////////////////////////////////////

Labels (1)
0 Kudos
4 Replies

475 Views
carlostadeoorte
Contributor III

As a follow up.

I notice there are two errors in my code:

      MCG_C1 = MCG_C1_CLKS(1);                         //Run at 8MHz

should be

      MCG_C1 |= MCG_C1_CLKS(1);                         //Run at 8MHz

      SIM_CLKDIV1 = ~SIM_CLKDIV1_OUTDIV4_MASK;                                 //Set bus speed to 8Mhz

should be

      SIM_CLKDIV1 &= ~SIM_CLKDIV1_OUTDIV4_MASK;                                 //Set bus speed to 8Mhz

The problem remains though

0 Kudos

475 Views
Hui_Ma
NXP TechSupport
NXP TechSupport

Hi,

What kind of reset will happen if you run the timer code?

I would recommend customer to check Example code on how to configure the TPM as PWM in the FRDM-KL25 board.

Wish it helps.


Have a great day,
Ma Hui

-----------------------------------------------------------------------------------------------------------------------
Note: If this post answers your question, please click the Correct Answer button. Thank you!
-----------------------------------------------------------------------------------------------------------------------

0 Kudos

475 Views
carlostadeoorte
Contributor III

Hello,

I looked at the code. But I don't think it is very relevant. First, I use (for most of the part) bare metal code.   Secondly,  the timer works ok in count-up mode. Finally, changing the clocks work fine if I don't have the timer.

The problem arises when I mix them together.   I need to double check this, but I am pretty sure I was getting a lockup event.  i.e.:

RCM->SRS1->LOCKUP bit is on.

Thank you,

-Carlos

0 Kudos

475 Views
Hui_Ma
NXP TechSupport
NXP TechSupport

Hi Carlos,

The reason could cause Kinetis core enter into lockup status as below: 1> An incorrect Clock mode transition occurs 2> Or the clock part is over-clocked 3> Or Code executes after POR, if a part memory is not programmed 4> Broken external oscillator if using external clock as reference clock.

Please change the code order, first change the  SIM_CLKDIV1 register, then change the MCG work mode.

Such as:

      __asm("CPSID i");                            // Disable interrupts

  SIM_CLKDIV1 =  SIM_CLKDIV1_OUTDIV4(1);       //Divide bus/flash clock by 2

      MCG_MC = MCG_MC_HIRCEN_MASK;

      MCG_C1 &= ~MCG_C1_CLKS_MASK;                       // Enable Main Clock Source of the 48MHz

      while(MCG_S & MCG_S_CLKST_MASK) {  };         //Wait until 48 Mhz clock gets selected

      __asm("CPSIE i");                            // Disable interrupts

Wish it helps.


Have a great day,
Ma Hui

-----------------------------------------------------------------------------------------------------------------------
Note: If this post answers your question, please click the Correct Answer button. Thank you!
-----------------------------------------------------------------------------------------------------------------------

0 Kudos