K22 - can't change from FEE to FEI in case of Loss Of Clock

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

K22 - can't change from FEE to FEI in case of Loss Of Clock

3,032 Views
alessandromorni
Contributor III

Hello,

I'm not able to change MCG mode from FEE to FEI in case of Loss Of Clock.

I'm using a custom board mounting MK22FX512VLK12 or MK22FX512V12 (mask 3N03G). On the custom board is also mounted an external I2C RTC, which 32-kHz output is used as reference clock for the RTC oscillator.

At startup, MCU starts by default in FEI mode (using the internal 32-kHz clock). In the main, I change then the MCG mode from FEI to FEE, using the external 32-kHz as reference clock.

I also enable the external clock monitor for generating an interrupt in case of loss of clock (CME1 = 1, LOCRE1= 0).

In case of loss of lock then (removing a jumper on the board that cuts off the 32-kHz signal), within the MCG ISR I change the MCG mode from FEE to FEI, but the bit IREFST remains 0, meaning that the source of the FLL reference clock is still the external one.

Is it possible to change MCGmode from FEE to FEI in case of loss of clock without resetting the MCU? I have found no documentation about that.

Here is my very simple example code

void setFEE (void)

{

    MCG_C7 |= MCG_C7_OSCSEL_MASK;

    MCG_C1  = 0;

    MCG_C4 |= (MCG_C4_DMX32_MASK | MCG_C4_DRST_DRS(0x03));

    while ((MCG_S & MCG_S_IREFST_MASK) != 0x00U)

    {

        ;

    }

    while ((MCG_S & 0x0CU) != 0x00U)

    {

        ;

    }

    MCG_C8 = MCG_C8_CME1_MASK;

    NVICIP57   = NVIC_IP_PRI57(0x80);

    NVICISER1 |= NVIC_ISER_SETENA(0x2000000);

}

void setFEI (void)

{

    MCG_C7 |= MCG_C7_OSCSEL_MASK;

    MCG_C1 |= MCG_C1_IREFS_MASK;

    MCG_C4 |= (MCG_C4_DMX32_MASK | MCG_C4_DRST_DRS(0x03));

    MCG_C8 &= ~(MCG_C8_CME1_MASK);

    while((MCG_S & MCG_S_IREFST_MASK) == 0x00U)

    {

        /* I'm stucking here when configuring from FEE to FEI within ISR. */

        ;

    }

    while((MCG_S & 0x0CU) != 0x00U)

    {

        ;

    }

}

void lossOfLockIsr ()

{

    MCG_S = (MCG_S_LOLS_MASK | MCG_S_CLKST(0x00));

    Cpu_SetFEIMode ();

    NVICIP57 &= ~NVIC_IP_PRI57(0x80);

    NVICICER1 = NVIC_ICER_CLRENA(0x2000000);

}

void main (void)

{

    setFEE ();

    while (1)

        ;

}

If a reset request is generated instead of interrupt (LOCRE1 = 1), everything is working correctly (MCU resets and it starts in FEI mode by default, with IREFST bit set to 1).

Labels (1)
0 Kudos
Reply
10 Replies

2,368 Views
jeremyzhou
NXP Employee
NXP Employee

Hi,

It's supported to switch to the FEI from the FEE, and I've attached the code as below, please for details.

int fll_freq(int fll_ref)

{

  int fll_freq_hz;

 

  if (MCG_C4 & MCG_C4_DMX32_MASK) // if DMX32 set

  {

    switch ((MCG_C4 & MCG_C4_DRST_DRS_MASK) >> MCG_C4_DRST_DRS_SHIFT) // determine multiplier based on DRS

    {

    case 0:

      fll_freq_hz = (fll_ref * 732);

      if (fll_freq_hz < 20000000) {return 0x33;}

      else if (fll_freq_hz > 25000000) {return 0x34;}

      break;

    case 1:

      fll_freq_hz = (fll_ref * 1464);

      if (fll_freq_hz < 40000000) {return 0x35;}

      else if (fll_freq_hz > 50000000) {return 0x36;}

      break;

    case 2:

      fll_freq_hz = (fll_ref * 2197);

      if (fll_freq_hz < 60000000) {return 0x37;}

      else if (fll_freq_hz > 75000000) {return 0x38;}

      break;

    case 3:

      fll_freq_hz = (fll_ref * 2929);

      if (fll_freq_hz < 80000000) {return 0x39;}

      else if (fll_freq_hz > 100000000) {return 0x3A;}

      break;

    }

  }

  else // if DMX32 = 0

  {

    switch ((MCG_C4 & MCG_C4_DRST_DRS_MASK) >> MCG_C4_DRST_DRS_SHIFT) // determine multiplier based on DRS

    {

    case 0:

      fll_freq_hz = (fll_ref * 640);

      if (fll_freq_hz < 20000000) {return 0x33;}

      else if (fll_freq_hz > 25000000) {return 0x34;}

      break;

    case 1:

      fll_freq_hz = (fll_ref * 1280);

      if (fll_freq_hz < 40000000) {return 0x35;}

      else if (fll_freq_hz > 50000000) {return 0x36;}

      break;

    case 2:

      fll_freq_hz = (fll_ref * 1920);

      if (fll_freq_hz < 60000000) {return 0x37;}

      else if (fll_freq_hz > 75000000) {return 0x38;}

      break;

    case 3:

      fll_freq_hz = (fll_ref * 2560);

      if (fll_freq_hz < 80000000) {return 0x39;}

      else if (fll_freq_hz > 100000000) {return 0x3A;}

      break;

    }

  }   

  return fll_freq_hz;

} // fll_freq

int fee_fei(int slow_irc_freq)

{

  short i;

  int mcg_out;

// Check MCG is in FEE mode

  if (!((((MCG_S & MCG_S_CLKST_MASK) >> MCG_S_CLKST_SHIFT) == 0x0) && // check CLKS mux has selcted FLL

      (!(MCG_S & MCG_S_IREFST_MASK)) &&                             // check FLL ref is external ref clk

      (!(MCG_S & MCG_S_PLLST_MASK))))                               // check PLLS mux has selected FLL

  {

    return 0x2;                                                     // return error code

  }

     

// Check IRC frequency is within spec.

  if ((slow_irc_freq < 31250) || (slow_irc_freq > 39063))

  {

    return 0x31;

  }

  // Check resulting FLL frequency

  mcg_out = fll_freq(slow_irc_freq);

  if (mcg_out < 0x5B) {return mcg_out;} // If error code returned, return the code to calling function

 

// Ensure clock monitor is disabled before switching to FEI otherwise a loss of clock will trigger

  MCG_C6 &= ~MCG_C6_CME0_MASK;

// Change FLL reference clock from external to internal by setting IREFS bit

  MCG_C1 |= MCG_C1_IREFS_MASK; // select internal reference

 

// wait for Reference clock to switch to internal reference

  for (i = 0 ; i < 2000 ; i++)

  {

    if (MCG_S & MCG_S_IREFST_MASK) break; // jump out early if IREFST sets before loop finishes

  }

  if (!(MCG_S & MCG_S_IREFST_MASK)) return 0x12; // check bit is really set and return with error if not set 

 

// Now in FEI mode 

  return mcg_out; 

} // fee_fei


Have a great day,

Ping

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

0 Kudos
Reply

2,368 Views
alessandromorni
Contributor III

Hi,

thank you for the support.

I've just tried using your code, but I'm still not be able to change back MCG to FEI mode.

I got stuck here

if (MCG_S & MCG_S_IREFST_MASK) break; // jump out early if IREFST sets before loop finishes 

So the function returns with the code 0x12

if (!(MCG_S & MCG_S_IREFST_MASK)) return 0x12; // check bit is really set and return with error if not set

It's like that IREFST bit is never set (the same thing happens using my code).

Did you try the code? Using which board/MCU?

0 Kudos
Reply

2,368 Views
jeremyzhou
NXP Employee
NXP Employee

Hi,

This code is from the TWR-K60D100 example demo, and the K22 contains the MCG module which is as same as the K60_100.

And the code can work well on the TWR-K60D100 board.

I was wondering if you can share your project, then I can reproduce this same issue on the FRDM-K22F board.
Have a great day,
Ping

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

0 Kudos
Reply

2,368 Views
alessandromorni
Contributor III

Hi,

some updates:

the code you provided (and also mine), works well if "loss of lock" event is not triggered. I mean, as still as the external  32khz is active, I can change between FEI/FEE and viceversa without problems.

The problem occurs if external 32khz is "killed" (in my case, removing a jumper on the board). In this case, software is still running because of DCO feedback, ISR is triggered but configuring MCG back to FEI just fails.

Anyway, attached to this message you will find the KSDK project for testing it: you should be able to compile without problems regenerating PE code and (maybe) changing KSDK path.

Thank you for the support.


Alessandro

0 Kudos
Reply

2,368 Views
jeremyzhou
NXP Employee
NXP Employee

Hi,

Thanks for your reply.

I think remove the jumper to stop the external 32KHz to feed the MCU is the root accuse of the issue.

I'd like to confirm with you about when you remove the jumper on the board.

I'm looking forward to your reply.
Have a great day,
Ping

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

0 Kudos
Reply

2,368 Views
alessandromorni
Contributor III

Hi,

that's exactly what I'm trying to do.

I'd like to change from FEE to FEI whenever a "loss of clock" event occurs: for forcing such event, I'm removing the jumper in order to kill the external source clock reference and to trigger the interrupt, changing then MCG to FEI.

I'd like to understand if this operation is legal or not: in such scenario, IREFST bit is never set.

Reading the datasheet, this operation should be possible (it just says that changing from FEE to FEI and viceversa is allowed, without saying if external source clock reference must be present or not).

Thanks again for the support.

Alessandro

0 Kudos
Reply

2,368 Views
jeremyzhou
NXP Employee
NXP Employee

Hi,

I'd like to confirm the steps of forcing the "loss of clock" event.

Did you remove the jumper before you start changing the MCG mode from the FEE to FEI or not?
Have a great day,

Ping

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

0 Kudos
Reply

2,368 Views
alessandromorni
Contributor III

Hi,

I remove the jumper before changing  from FEE to FEI.

The steps I do are reported as follows:

1. power on the board (MCU starts with FEI mode by default);


2. after startup, I change MCG mode from FEI to FEE;


3. I enable the MCG interrupt in the vector table in case of loss of clock event;

/* Enable the loss of lock interrupt in MCG module. */

MCG_C8 = MCG_C8_CME1_MASK;

/* Set priority and enable interrupt. */

NVICIP57   = NVIC_IP_PRI57(0x80);

NVICISER1 |= NVIC_ISER_SETENA(0x2000000);

4. I then start my application as usual;

At some point, I remove the jumper in order to generate the "loss of clock" event. The MCG ISR is then triggered and executed.

PE_ISR(Cpu_INT_MCGInterrupt)

{

  MCG_S = (MCG_S_LOLS_MASK | MCG_S_CLKST(0x00)); /* Clear Loss of Lock status flag */

 

  /* Switch to FEI mode. */

  Cpu_SetFEIMode ();

}

When the ISR is executed, the 32-kHz external reference clock is already "dead".

0 Kudos
Reply

2,368 Views
chipweller
Contributor II

Hi,

We have a similar issue. Did you find a solution?

0 Kudos
Reply

2,368 Views
alessandromorni
Contributor III

Hi,

sorry for the delayed response.

No solution for the problem: if I cutoff the external 32khz signal, the ISR triggers but can't change mode to FEI.

Despite it, the board continues to run normally because of the 'feedback signal' named DCOOUT (on the datasheet it can be found under the Multipurpose Clock Generator (MCG) block diagram).

Our final solution was to generate a reset in case of LOC, saving a flag in the no reset ram, and configuring the FEI after the reset.

0 Kudos
Reply