KL27Z644 HIRC mode

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

KL27Z644 HIRC mode

Jump to solution
2,253 Views
radunasui
Contributor II

I have been trying to enable the HIRC MCG mode on a MKL27Z microcontroller. As far as I know, there are at least two ways to do this: to write the code using the device registers or to use KDSK device specific drivers.

For the first approach my could would look like this:

#include "fsl_device_registers.h"

void main(void)

{

  MCG_MC |= MCG_MC_HIRCEN_MASK; //enable the HIRC

  MCG_MC |= MCG_MC_HIRCLPEN_MASK;

  MCG_C1 |= MCG_C1_CLKS(0b00); //use the HIRC oscillator as the system clock

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

  {if (((MCG_S & MCG_S_CLKST_MASK) >> MCG_S_CLKST_SHIFT) == 0b00) break; // jump out early if CLKST shows HIRC CLK selected before loop finishes

  }

}

The problem with this example is that it does not enter the HIRC mode. I have tried the same approach on on enabling other modes and it works. Am I missing something?

The second approach is to use one of the functions provided in the low level HAL driver, fsl_mcglite_hal.h:

static void CLOCK_HAL_SetHircCmd (MCG_Type  *base, bool enable)

Although the latter will mean less lines of code, I cannot find any reference to what possible values I could give to base ( I could not find any reference to MCG_Type type).

Any thoughts??

Cheers

1 Solution
1,806 Views
bobpaddock
Senior Contributor III

"MCG_C1 |=" the '|' is the problem, can't have more than one clock selected in C1 at a time.

I use the code below.  Hopefully the editor here does not hose it like it typically does for me:


void clock_usb( void )
{
      /* The SOPT1 register is only reset on POR or LVD: */
      SIM_SOPT1 = (
                  // SIM_SOPT1_USBREGEN_MASK |    /* USB voltage regulator is enabled [Do we need to do this?] */
                  SIM_SOPT1_OSC32KSEL( 3U )        /* LPO 1kHz oscillator drives 32 kHz clock for RTC and LPTMR via ERCLK32K */
                  );

      SIM_SOPT2 = (
                  SIM_SOPT2_TPMSRC(    1U )    | /* 1:IRC48M/MCGPCLK, 2:OSCERCLK, 3:IRC8M/MCGIRCLK: Clock feeds the TPM clock */
                  SIM_SOPT2_LPUART0SRC( 1U )    | /* 1:IRC48M/MCGPCLK, 2:OSCERCLK, 3:IRC8M/MCGIRCLK: Clock feeds LPUART0 baud generator */
                  SIM_SOPT2_LPUART1SRC( 1U )    | /* 1:IRC48M/MCGPCLK, 2:OSCERCLK, 3:IRC8M/MCGIRCLK: Clock feeds LPUART0 baud generator */
                  SIM_SOPT2_CLKOUTSEL(  CLKOUT ) | /* 0:None, 2:Bus, 3:LPO-1kHz, 4:IRC8M/LIRC_CLK, 6:OSCERCLK, 7:IRC48M */
                  SIM_SOPT2_USBSRC_MASK            /* 0:External bypass clock (USB_CLKIN), 1:IRC48M */
                  );
      SIM_SCGC4 |= SIM_SCGC4_USBFS_MASK;            /* Enable USB module clock */
      /*
      * When power on or out of reset, Low-power Internal RC (LIRC) at 8
      * MHz is selected as the main clock source. To select other clock
      * sources, the mode must be set to HIRC before changing to an other
      * mode.
      *
      * Note that the bootloader may have changed clock configuration
      * substantially from the data sheet reset values.
      */
      MCG_MC    = MCG_MC_HIRCEN_MASK;      /* High-frequency IRC Enabled. Enables the HIRC, even when MCG_Lite is not working at HIRC mode */

      MCG_C1    = (
                  MCG_C1_CLKS( 0U )  |    /* 0:HIRC, 1:LIRC2M or LIRC8M mode, 2:External Clock */
                  MCG_C1_IRCLKEN_MASK      /* Internal Reference Clock LIRC enabled */
                  );
      /*
      * Clock Mode Status.  This field does not update immediately after
      * a write to MCG_C1[CLKS] due to domain synchronization.
      *
      * Check MCG_S[CLKST] to confirm HIRC clock source is selected
      */

      while( (0U << MCG_S_CLKST_SHIFT) != MCG_S_CLKST( 0U ) )
        {
          nop();
        }

    #if( defined( USB_VID ) && defined( MCU_MKL27Z4 ) ) /* Only the 43/27 family has USB sync the 25 family does not */
      USB0_USBTRC0            = 0x40U;      /* Attach Coldfire V1 USB peripheral to the bus */
      USB0_CLK_RECOVER_IRC_EN = (USB_CLK_RECOVER_IRC_EN_IRC_EN_MASK|USB_CLK_RECOVER_IRC_EN_REG_EN_MASK); /* Note that bit-0 is reserved and must be set to one, the data sheet does not explain why */
      USB0_CLK_RECOVER_CTRL  = (USB_CLK_RECOVER_CTRL_CLOCK_RECOVER_EN_MASK|USB_CLK_RECOVER_CTRL_RESTART_IFRTRIM_EN_MASK);

      USB0_CLK_RECOVER_INT_STATUS = USB_CLK_RECOVER_INT_STATUS_OVF_ERROR_MASK; /* Combined USB Clock Recovery interrupt status */
      USB0_CLK_RECOVER_INT_EN    = 0U;    /* Is enabled out of reset by default */
    #endif

      /*
      * The MCG_Lite module does not support switch between LIRC 2 MHz
      * and 8 MHz directly, because 2 MHz and 8 MHz clock generators
      * share circuits and logics. To switch between each other, the
      * module must be in HIRC or EXT clock mode.
      *
      * To enter LIRC8M mode from HIRC or EXT mode:
      *    1. 1. Write 0b to MCG_C2[IRCS] to select LIRC 2M.  Write 1b to MCG_C2[IRCS] to select LIRC 8M.
      *    2. Write 1b to MCG_C1[IRCLKEN] to enable LIRC clock (optional).
      *    3. Write 01b to MCG_C1[CLKS] to select LIRC clock source.
      *    4. Check MCG_S[CLKST] to confirm LIRC clock source is selected.
      */

      MCG_C2    = (
                  MCG_C2_IRCS_MASK        /* Low-frequency Internal Reference Clock Select LIRC 8 MHz */
                  );

      MCG_MC    = (MCG_MC_HIRCEN_MASK|MCG_MC_LIRC_DIV2( 1U )); /* High-frequency IRC Enabled.  LIRC/2 = 4MHz to match Bus.  Use MCGIRCLK for peripherals */
}

View solution in original post

0 Kudos
Reply
7 Replies
1,806 Views
kerryzhou
NXP TechSupport
NXP TechSupport

Hi Radu Nasui,

     You can refer to the KSDK1.3.0, KL27Z644 sample code.

     After you install the KSDK1.3.0, please refer to the SystemInit function in system_MKL27Z644.c, and define CLOCK_SETUP=1 in system_MKL27Z644.h.

  You can find the system_MKL27Z644.h and system_MKL27Z644.c in default folder: C:\Freescale\KSDK_1.3.0\platform\devices\MKL27Z644\startup

   When you configure CLOCK_SETUP=1, the systeminit is using MCG_MODE_HIRC.

#elif (CLOCK_SETUP == 1)

  #define DEFAULT_SYSTEM_CLOCK         48000000u           /* Default System clock value */

  #define CPU_INT_SLOW_CLK_HZ          8000000u            /* Value of the slow internal oscillator clock frequency in Hz  */

  #define MCG_MODE                     MCG_MODE_HIRC       /* Clock generator mode */

  /* MCG_C1: CLKS=0,IRCLKEN=0,IREFSTEN=0 */

  #define MCG_C1_VALUE                 0x00u               /* MCG_C1 */

  /* MCG_C2: RANGE0=0,HGO0=0,EREFS0=0,IRCS=1 */

  #define MCG_C2_VALUE                 0x01u               /* MCG_C2 */

  /* MCG_SC: FCRDIV=0 */

  #define MCG_SC_VALUE                 0x00u               /* MCG_SC */

  /* MCG_MC: HIRCEN=1 LIRC_DIV2=0 */

  #define MCG_MC_VALUE                 0x80u               /* MCG_MC */

  /* OSC0_CR: ERCLKEN=0,EREFSTEN=0,SC2P=0,SC4P=0,SC8P=0,SC16P=0 */

  #define OSC0_CR_VALUE                0x00u               /* OSC0_CR */

  /* SMC_PMCTRL: RUNM=0,STOPA=0,STOPM=0 */

  #define SMC_PMCTRL_VALUE             0x00u               /* SMC_PMCTRL */

  /* SIM_CLKDIV1: OUTDIV1=0,OUTDIV4=1 */

  #define SYSTEM_SIM_CLKDIV1_VALUE     0x10000u            /* SIM_CLKDIV1 */

  /* SIM_SOPT1: OSC32KSEL=0,OSC32KOUT=0 */

  #define SYSTEM_SIM_SOPT1_VALUE       0x00000000u         /* SIM_SOPT1 */

  /* SIM_SOPT2: LPUART1SRC=0,LPUART0SRC=0,TPMSRC=3,FLEXIOSRC=0,USBSRC=0,CLKOUTSEL=0,RTCCLKOUTSEL=0 */

  #define SYSTEM_SIM_SOPT2_VALUE       0x03000000U         /* SIM_SOPT2 */

Wish it helps you!

If you still have question, please let me know!

Have a great day,
Jingjing

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

1,806 Views
radunasui
Contributor II

Thanks, works this way too!

Do you know though how to find the set of values MCG_Type can take?

Cheers

0 Kudos
Reply
1,806 Views
kerryzhou
NXP TechSupport
NXP TechSupport

Hi Radu Nasui,

MCG_Type is defined like this:

typedef struct {

  __IO uint8_t C1;                                 /**< MCG Control Register 1, offset: 0x0 */

  __IO uint8_t C2;                                 /**< MCG Control Register 2, offset: 0x1 */

       uint8_t RESERVED_0[4];

  __I  uint8_t S;                                  /**< MCG Status Register, offset: 0x6 */

       uint8_t RESERVED_1[1];

  __IO uint8_t SC;                                 /**< MCG Status and Control Register, offset: 0x8 */

       uint8_t RESERVED_2[15];

  __IO uint8_t MC;                                 /**< MCG Miscellaneous Control Register, offset: 0x18 */

} MCG_Type, *MCG_MemMapPtr;

Actually, the value of MCG_Type is just the data defined in the header file system_MKL27Z644.h:

  #define MCG_C1_VALUE                 0x00u               /* MCG_C1 */

  /* MCG_C2: RANGE0=0,HGO0=0,EREFS0=0,IRCS=1 */

  #define MCG_C2_VALUE                 0x01u               /* MCG_C2 */

  /* MCG_SC: FCRDIV=0 */

  #define MCG_SC_VALUE                 0x00u               /* MCG_SC */

  /* MCG_MC: HIRCEN=1 LIRC_DIV2=0 */

  #define MCG_MC_VALUE                 0x80u               /* MCG_MC */

Because in the system_MKL27Z644.c, you will get the following code :

  MCG->SC = MCG_SC_VALUE;          /* Set SC (internal reference clock divider) */
  MCG->MC = MCG_MC_VALUE;          /* Set MC (high-frequency IRC enable, second LIRC divider) */
  MCG->C1 = MCG_C1_VALUE;          /* Set C1 (clock source selection, int. reference enable etc.) */
  MCG->C2 = MCG_C2_VALUE;          /* Set C2 (ext. and int. reference clock selection) */
  OSC0->CR = OSC0_CR_VALUE;        /* Set OSC0_CR (OSCERCLK enable, oscillator capacitor load) */

Wish it helps you!

If you still have question, please let me know!

Have a great day,
Jingjing

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

1,806 Views
radunasui
Contributor II

Thanks for the answer!

I still don't know though how should I call the following function:

               uint32_t CLOCK_HAL_GetOutClk ( MCG_Type   *base )

I was trying to do the following:

          clock = CLOCK_HAL_GetOutClk(MCG_MemMapPtr);

But I am getting an error:      expected expression before 'MCG_MemMapPtr'

How should I go about solving this one?

Thanks

0 Kudos
Reply
1,806 Views
radunasui
Contributor II

Found it.

For reference, all these information can be found in the device header file, in my case MKL27Z644.h

clock = CLOCK_HAL_GetOutClk(MCG);

Cheers

0 Kudos
Reply
1,806 Views
kerryzhou
NXP TechSupport
NXP TechSupport

Yes, actually, you can refer to the fsl_clock_MKL27Z644.c file which you can find from :C:\Freescale\KSDK_1.3.0\platform\system\src\clock\MKL27Z644

clock_manager_error_code_t CLOCK_SYS_GetFreq(clock_names_t clockName,

                                            uint32_t *frequency)

{

    clock_manager_error_code_t returnCode = kClockManagerSuccess;

    switch (clockName)

    {

    case kCoreClock:

    case kSystemClock:

        *frequency = CLOCK_SYS_GetCoreClockFreq();

        break;

    case kPlatformClock:

        *frequency = CLOCK_SYS_GetSystemClockFreq();

        break;

    case kBusClock:

        *frequency = CLOCK_SYS_GetBusClockFreq();

        break;

    case kFlashClock:

        *frequency = CLOCK_SYS_GetFlashClockFreq();

        break;

    case kOsc32kClock:

        *frequency = CLOCK_SYS_GetExternalRefClock32kFreq();

        break;

    case kOsc0ErClock:

        *frequency = CLOCK_SYS_GetOsc0ExternalRefClockFreq();

        break;

    case kIrc48mClock:

        *frequency = kMcgliteConst48M;

        break;

    case kRtcoutClock:

        *frequency = CLOCK_SYS_GetRtcOutFreq();

        break;

    case kMcgOutClock:

        *frequency = CLOCK_HAL_GetOutClk(MCG);

        break;

    case kMcgIrClock:

        *frequency = CLOCK_HAL_GetInternalRefClk(MCG);

        break;

    case kLpoClock:

        *frequency = CLOCK_SYS_GetLpoClockFreq();

        break;

        case kSystickClock:

            *frequency = CLOCK_SYS_GetSystickFreq();

            break;

    default:

        *frequency = 0U;

        returnCode = kClockManagerNoSuchClockName;

        break;

    }

    return returnCode;

}

this function gives you an example!

Wish it helps you!

If you still have question, please let me know!

Have a great day,
Jingjing

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

1,807 Views
bobpaddock
Senior Contributor III

"MCG_C1 |=" the '|' is the problem, can't have more than one clock selected in C1 at a time.

I use the code below.  Hopefully the editor here does not hose it like it typically does for me:


void clock_usb( void )
{
      /* The SOPT1 register is only reset on POR or LVD: */
      SIM_SOPT1 = (
                  // SIM_SOPT1_USBREGEN_MASK |    /* USB voltage regulator is enabled [Do we need to do this?] */
                  SIM_SOPT1_OSC32KSEL( 3U )        /* LPO 1kHz oscillator drives 32 kHz clock for RTC and LPTMR via ERCLK32K */
                  );

      SIM_SOPT2 = (
                  SIM_SOPT2_TPMSRC(    1U )    | /* 1:IRC48M/MCGPCLK, 2:OSCERCLK, 3:IRC8M/MCGIRCLK: Clock feeds the TPM clock */
                  SIM_SOPT2_LPUART0SRC( 1U )    | /* 1:IRC48M/MCGPCLK, 2:OSCERCLK, 3:IRC8M/MCGIRCLK: Clock feeds LPUART0 baud generator */
                  SIM_SOPT2_LPUART1SRC( 1U )    | /* 1:IRC48M/MCGPCLK, 2:OSCERCLK, 3:IRC8M/MCGIRCLK: Clock feeds LPUART0 baud generator */
                  SIM_SOPT2_CLKOUTSEL(  CLKOUT ) | /* 0:None, 2:Bus, 3:LPO-1kHz, 4:IRC8M/LIRC_CLK, 6:OSCERCLK, 7:IRC48M */
                  SIM_SOPT2_USBSRC_MASK            /* 0:External bypass clock (USB_CLKIN), 1:IRC48M */
                  );
      SIM_SCGC4 |= SIM_SCGC4_USBFS_MASK;            /* Enable USB module clock */
      /*
      * When power on or out of reset, Low-power Internal RC (LIRC) at 8
      * MHz is selected as the main clock source. To select other clock
      * sources, the mode must be set to HIRC before changing to an other
      * mode.
      *
      * Note that the bootloader may have changed clock configuration
      * substantially from the data sheet reset values.
      */
      MCG_MC    = MCG_MC_HIRCEN_MASK;      /* High-frequency IRC Enabled. Enables the HIRC, even when MCG_Lite is not working at HIRC mode */

      MCG_C1    = (
                  MCG_C1_CLKS( 0U )  |    /* 0:HIRC, 1:LIRC2M or LIRC8M mode, 2:External Clock */
                  MCG_C1_IRCLKEN_MASK      /* Internal Reference Clock LIRC enabled */
                  );
      /*
      * Clock Mode Status.  This field does not update immediately after
      * a write to MCG_C1[CLKS] due to domain synchronization.
      *
      * Check MCG_S[CLKST] to confirm HIRC clock source is selected
      */

      while( (0U << MCG_S_CLKST_SHIFT) != MCG_S_CLKST( 0U ) )
        {
          nop();
        }

    #if( defined( USB_VID ) && defined( MCU_MKL27Z4 ) ) /* Only the 43/27 family has USB sync the 25 family does not */
      USB0_USBTRC0            = 0x40U;      /* Attach Coldfire V1 USB peripheral to the bus */
      USB0_CLK_RECOVER_IRC_EN = (USB_CLK_RECOVER_IRC_EN_IRC_EN_MASK|USB_CLK_RECOVER_IRC_EN_REG_EN_MASK); /* Note that bit-0 is reserved and must be set to one, the data sheet does not explain why */
      USB0_CLK_RECOVER_CTRL  = (USB_CLK_RECOVER_CTRL_CLOCK_RECOVER_EN_MASK|USB_CLK_RECOVER_CTRL_RESTART_IFRTRIM_EN_MASK);

      USB0_CLK_RECOVER_INT_STATUS = USB_CLK_RECOVER_INT_STATUS_OVF_ERROR_MASK; /* Combined USB Clock Recovery interrupt status */
      USB0_CLK_RECOVER_INT_EN    = 0U;    /* Is enabled out of reset by default */
    #endif

      /*
      * The MCG_Lite module does not support switch between LIRC 2 MHz
      * and 8 MHz directly, because 2 MHz and 8 MHz clock generators
      * share circuits and logics. To switch between each other, the
      * module must be in HIRC or EXT clock mode.
      *
      * To enter LIRC8M mode from HIRC or EXT mode:
      *    1. 1. Write 0b to MCG_C2[IRCS] to select LIRC 2M.  Write 1b to MCG_C2[IRCS] to select LIRC 8M.
      *    2. Write 1b to MCG_C1[IRCLKEN] to enable LIRC clock (optional).
      *    3. Write 01b to MCG_C1[CLKS] to select LIRC clock source.
      *    4. Check MCG_S[CLKST] to confirm LIRC clock source is selected.
      */

      MCG_C2    = (
                  MCG_C2_IRCS_MASK        /* Low-frequency Internal Reference Clock Select LIRC 8 MHz */
                  );

      MCG_MC    = (MCG_MC_HIRCEN_MASK|MCG_MC_LIRC_DIV2( 1U )); /* High-frequency IRC Enabled.  LIRC/2 = 4MHz to match Bus.  Use MCGIRCLK for peripherals */
}

0 Kudos
Reply