Loss Of Clock: FEE to FEI within ISR (OSC0 monitor IRQ)

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

Loss Of Clock: FEE to FEI within ISR (OSC0 monitor IRQ)

1,641 Views
alessandromorni
Contributor III

Hi,

 

I'm working on a project that requires to recover from FEE  to FEI mode in case of Loss Of Clock (LOC).

 

I'd like to perform this action within the ISR of MCG handler.

 

In a previous project, I had an external 32kHz used as external reference clock for the RTC oscillator. I have never been able to recover from FEE to FEI in case of LOC (you can read this topic for more informations K22 - can't change from FEE to FEI in case of Loss Of Clock).

 

From what I've understood, this should be a legal operation (Recovering from loss of external reference clock (LOCS0 = 1)

 

I'm using a TWR-K21D50M as proto board, w/ KSDK 2.0.

 

This is the code I'm using.

 

/*
 * Copyright (c) 2013 - 2016, Freescale Semiconductor, Inc.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without modification,
 * are permitted provided that the following conditions are met:
 *
 * o Redistributions of source code must retain the above copyright notice, this list
 *   of conditions and the following disclaimer.
 *
 * o Redistributions in binary form must reproduce the above copyright notice, this
 *   list of conditions and the following disclaimer in the documentation and/or
 *   other materials provided with the distribution.
 *
 * o Neither the name of Freescale Semiconductor, Inc. nor the names of its
 *   contributors may be used to endorse or promote products derived from this
 *   software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
 * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

/**
 * This is template for main module created by New Kinetis SDK 2.x Project Wizard. Enjoy!
 **/

#include "board.h"
#include "pin_mux.h"
#include "clock_config.h"

#include "fsl_clock.h"

void MCG_IRQHandler (void)
{
    CLOCK_SetOsc0MonitorMode (kMCG_MonitorNone);

    NVIC_DisableIRQ (MCG_IRQn);

    CLOCK_SetFeiMode (kMCG_Dmx32Default, kMCG_DrsLow, NULL);
}

/*!
 * @brief Application entry point.
 */
int main(void) {
  /* Init board hardware. */
  BOARD_InitPins();
  BOARD_BootClockRUN();
  BOARD_InitDebugConsole();

  /* Add your code here */
  osc_config_t oscConfig;

  oscConfig.freq = 8000000;
  oscConfig.capLoad = 0U;
  oscConfig.workMode = kOSC_ModeOscLowPower;
  oscConfig.oscerConfig.enableMode = kOSC_ErClkEnable;

  CLOCK_InitOsc0(&oscConfig);

  CLOCK_SetXtal0Freq(8000000);

  /* Set clock divider to safe value to switch mode */
  CLOCK_SetSimSafeDivs();

  CLOCK_SetFeeMode (0, kMCG_Dmx32Default, kMCG_DrsLow, NULL);

  CLOCK_SetOsc0MonitorMode (kMCG_MonitorInt);

  NVIC_EnableIRQ (MCG_IRQn);

  CLOCK_DeinitOsc0 ();

  for(;;) { /* Infinite loop to avoid leaving the main function */
    __asm("NOP"); /* something to use as a breakpoint stop while looping */
  }
}

 

 

 

I've got stuck within the function CLOCK_SetFeiMode (kMCG_Dmx32Default, kMCG_DrsLow, NULL): IREFST field of register MCG_S remains set to '0'.

 

 

Am I missing something?

 

I've attacched the Kinetis Design Studio I'm using for testing.

Best regards,

 

Alessandro

Original Attachment has been moved to: loc.zip

Labels (1)
0 Kudos
Reply
4 Replies

1,195 Views
isaacavila
NXP Employee
NXP Employee

Hello,

Did you tried to run it (without debugging)?

I've tested this example by using TWR-K21D50M but using the external reference clock from TWR-SER instead of 8-MHz resonator and it worked well. This is the code that I used:

int main(void) {
    /* Init board hardware. */
    BOARD_InitPins();
    //BOARD_BootClockRUN();
    BOARD_InitDebugConsole();

    /* Add your code here */
    PRINTF("Loss of Clock test!\r\n");

    /* Add your code here */
    osc_config_t oscConfig;

    oscConfig.freq = 50000000;
    oscConfig.capLoad = 0U;
    oscConfig.workMode = kOSC_ModeExt;
    oscConfig.oscerConfig.enableMode = 0;


    CLOCK_InitOsc0(&oscConfig);

    CLOCK_SetXtal0Freq(oscConfig.freq);
    PRINTF("OSC init OK\r\n");

    PRINTF("Moving to FEE.....");
    /* Set clock divider to safe value to switch mode */
    CLOCK_SetSimSafeDivs();
    CLOCK_SetFeeMode(6, kMCG_Dmx32Default, kMCG_DrsMid, NULL);
    g_bFeiModeOn = 0;
    DbgConsole_Deinit();
    BOARD_InitDebugConsole();
    PRINTF("OK\r\n");
    PRINTF("Core is running at %d Hz\r\n", CLOCK_GetCoreSysClkFreq());

    CLOCK_SetOsc0MonitorMode(kMCG_MonitorInt);

    NVIC_EnableIRQ(MCG_IRQn);
    for (;;) { /* Infinite loop to avoid leaving the main function */
        if (g_bFeiModeOn)
        {
            delay();
            g_bFeiModeOn = 0;
            CLOCK_SetFeeMode(6, kMCG_Dmx32Default, kMCG_DrsMid, NULL);
            DbgConsole_Deinit();
            BOARD_InitDebugConsole();
            CLOCK_SetOsc0MonitorMode(kMCG_MonitorInt);

            NVIC_EnableIRQ(MCG_IRQn);
            PRINTF("Core is running at %d Hz\r\n", CLOCK_GetCoreSysClkFreq());
        }
        /* something to use as a breakpoint stop while looping */
    }
}

void MCG_IRQHandler(void) {
    CLOCK_SetOsc0MonitorMode(kMCG_MonitorNone);

    NVIC_DisableIRQ(MCG_IRQn);
    PRINTF("Returning to FEI mode");
    CLOCK_SetFeiMode(kMCG_Dmx32Default, kMCG_DrsLow, NULL);
    g_bFeiModeOn = 1;
    DbgConsole_Deinit();
    BOARD_InitDebugConsole();
    PRINTF("Core is running at %d Hz\r\n", CLOCK_GetCoreSysClkFreq());
}

When I debugged the project, I also could see that IREFST field of register MCG_S remains set to '0' but when I ran and used debug console I could see that transitions where done correctly.

MCG transitions.jpg

I hope this helps!

Regards,

Isaac

0 Kudos
Reply

1,195 Views
alessandromorni
Contributor III

Hi,

I've just tried without debbugger attached but I'm still not able to recover back to FEI mode (IREFST remains '0', also w/o debbuger).

I've added some visual debug using the leds:

- green led -> ON when FEE mode is active;
- yellow led -> ON when FEI mode is active;
- orange led -> toggled in main loop;
- blue led -> ON entering / OFF exiting the LOC ISR handler (MCG_IRQHandler);

I'm disabling the external clock (CLOCK_DeinitOsc0) within the SW2 button ISR (PORTC_IRQHandler);

As soon as I press the button, the green led is turned OFF, the orange led stops toggling and the blue led is turned ON but never OFF (code is stuck in while loop checking the IREFST field).


Here's the code I'm using.

#include "fsl_clock.h"
#include "fsl_port.h"
#include "fsl_gpio.h"

void MCG_IRQHandler (void)
{
    GPIO_ClearPinsOutput (GPIOD, (1 << 7));

    CLOCK_SetOsc0MonitorMode (kMCG_MonitorNone);

    NVIC_DisableIRQ (MCG_IRQn);

    GPIO_SetPinsOutput (GPIOD, (1 << 4));

    CLOCK_SetFeiMode (kMCG_Dmx32Default, kMCG_DrsLow, NULL);

    GPIO_ClearPinsOutput (GPIOD, (1 << 5));

    GPIO_SetPinsOutput (GPIOD, (1 << 7));
}

void PORTC_IRQHandler (void)
{
    CLOCK_DeinitOsc0 ();
}

int main (void)
{
    port_pin_config_t tlButtonConfig;
    gpio_pin_config_t tlLedConfig;
    osc_config_t      tlOscConfig;
    uint32_t          u32lI;

    tlButtonConfig.pullSelect          = kPORT_PullUp;
    tlButtonConfig.slewRate            = kPORT_FastSlewRate;
    tlButtonConfig.passiveFilterEnable = kPORT_PassiveFilterDisable;
    tlButtonConfig.openDrainEnable     = kPORT_OpenDrainEnable;
    tlButtonConfig.driveStrength       = kPORT_HighDriveStrength;
    tlButtonConfig.mux                 = kPORT_MuxAsGpio;
    tlButtonConfig.lockRegister        = kPORT_UnlockRegister;

    tlLedConfig.pinDirection = kGPIO_DigitalOutput;
    tlLedConfig.outputLogic  = 1;

    tlOscConfig.freq                   = 8000000;
    tlOscConfig.capLoad                = 0U;
    tlOscConfig.workMode               = kOSC_ModeOscLowPower;
    tlOscConfig.oscerConfig.enableMode = 0;

    CLOCK_EnableClock (kCLOCK_PortC);
    CLOCK_EnableClock (kCLOCK_PortD);

    PORT_SetPinMux (PORTD, 4, kPORT_MuxAsGpio);
    PORT_SetPinMux (PORTD, 5, kPORT_MuxAsGpio);
    PORT_SetPinMux (PORTD, 6, kPORT_MuxAsGpio);
    PORT_SetPinMux (PORTD, 7, kPORT_MuxAsGpio);

    GPIO_PinInit (GPIOD, 4, &tlLedConfig); /* Green led ON -> FEE enabled.                     */
    GPIO_PinInit (GPIOD, 5, &tlLedConfig); /* Yellow led ON -> FEI enabled.                    */
    GPIO_PinInit (GPIOD, 6, &tlLedConfig); /* Orange led toggle in main loop.                  */
    GPIO_PinInit (GPIOD, 7, &tlLedConfig); /* Blue led ON entering/OFF exiting MCG_IRQHandler. */

    PORT_SetPinConfig (PORTC, 7, &tlButtonConfig);

    PORT_SetPinInterruptConfig (PORTC, 7, kPORT_InterruptFallingEdge);

    NVIC_EnableIRQ (PORTC_IRQn);
    NVIC_EnableIRQ (MCG_IRQn);

    CLOCK_InitOsc0(&tlOscConfig);

    CLOCK_SetXtal0Freq(tlOscConfig.freq);

    CLOCK_SetSimSafeDivs();

    CLOCK_SetFeeMode (0, kMCG_Dmx32Default, kMCG_DrsLow, NULL);

    GPIO_ClearPinsOutput (GPIOD, (1 << 4));

    CLOCK_SetOsc0MonitorMode (kMCG_MonitorInt);

    while (1)
    {
        for (u32lI = 0; u32lI < 100000; u32lI++)
        {
            ;
        }

        GPIO_TogglePinsOutput (GPIOD, (1 << 6));
    }
}
‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍
0 Kudos
Reply

1,195 Views
isaacavila
NXP Employee
NXP Employee

Hello Alessandro,

I also tried this use case (disabling OSC) but it failed (got stuck) waiting for Internal Reference Clock to be used for FLL. What mask are you using? is it possible to test it by using an external reference clock instead of oscillator?

Regards,
Isaac

0 Kudos
Reply

1,195 Views
alessandromorni
Contributor III

Hi Isaac,

isaacavila ha scritto:

What mask are you using?  

The mask reported on the MCU of the TWR-K21D50M is: 0N89E

isaacavila ha scritto:

is it possible to test it by using an external reference clock instead of oscillator?

Right now, it's not possible testing with an external reference clock using the TWR-K21 board.

We already tried with an external reference clock in the past, but with a different (custom) board and different MCU (K22). We tried using 32-kHz external reference clock but the result is the same (you can find more details @ K22 - can't change from FEE to FEI in case of Loss Of Clock). 

Thanks for the support.


Best regards,

Alessandro

0 Kudos
Reply