/*
 * Copyright 2016 Freescale Semiconductor
 * Copyright 2016-2018 NXP
 * To be used with MCUXpresso Config Tools under its Software License Agreement.
 */

/**
 * Code generation script producing clock_config.c
 *
 */

// SDK header includes
var sdkIncludes = {
  //#include fsl_common.h moved into h file
  //fsl_common:   {code: "#include \"fsl_common.h\"",   condition: true},
  fsl_smc:      {name: "smc", code: "#include \"fsl_smc.h\"",      configurations: new Array(),   condition: false},
  fsl_rtc:      {name: "rtc", code: "#include \"fsl_rtc.h\"",      configurations: new Array(),   condition: false},
  fsl_irtc:     {name: "irtc", code: "#include \"fsl_irtc.h\"",    configurations: new Array(),   condition: false},
  fsl_port:     {name: "port", code: "#include \"fsl_port.h\"",    configurations: new Array(),   condition: false},
  clock_config: {name: "",    code: "#include \"clock_config.h\"", configuration: "",   condition: true},
}

/**
 * Writes How to setup comment block
 *
 */
function writeHowToSetupComment() {
  CWriter.writeLines([
  "/***********************************************************************************************************************",
  " * This file was generated by the MCUXpresso Config Tools. Any manual edits made to this file",
  " * will be overwritten if the respective MCUXpresso Config Tools is used to update this file.",
  " **********************************************************************************************************************/",
  "/*",
  " * How to setup clock using clock driver functions:",
  " *",
  " * 1. CLOCK_SetSimSafeDivs, to make sure core clock, bus clock, flexbus clock",
  " *    and flash clock are in allowed range during clock mode switch.",
  " *",
  " * 2. Call CLOCK_Osc0Init to setup OSC clock, if it is used in target mode.",
  " *"]);
  if (!HwAbstr.isMcgLite()) {
    CWriter.writeLines([
  " * 3. Set MCG configuration, MCG includes three parts: FLL clock, PLL clock and",
  " *    internal reference clock(MCGIRCLK). Follow the steps to setup:",
  " *",
  " *    1). Call CLOCK_BootToXxxMode to set MCG to target mode.",
  " *",
  " *    2). If target mode is FBI/BLPI/PBI mode, the MCGIRCLK has been configured",
  " *        correctly. For other modes, need to call CLOCK_SetInternalRefClkConfig",
  " *        explicitly to setup MCGIRCLK.",
  " *",
  " *    3). Don't need to configure FLL explicitly, because if target mode is FLL",
  " *        mode, then FLL has been configured by the function CLOCK_BootToXxxMode,",
  " *        if the target mode is not FLL mode, the FLL is disabled.",
  " *",
  " *    4). If target mode is PEE/PBE/PEI/PBI mode, then the related PLL has been",
  " *        setup by CLOCK_BootToXxxMode. In FBE/FBI/FEE/FBE mode, the PLL could",
  " *        be enabled independently, call CLOCK_EnablePll0 explicitly in this case.",
  " *"]);
  }
  else { // MCG lite
    CWriter.writeLines([
  " * 3. Call CLOCK_SetMcgliteConfig to set MCG_Lite configuration.",
  " *"]);
  }
  CWriter.writeLines([
  " * 4. Call CLOCK_SetSimConfig to set the clock configuration in SIM.",
  " */"]);
}


/**
 * Generates one configuration structure for a given clock configuration
 *
 * @param cfg Clock configuration object
 */
function GenerateCLKConfigStructure(cfg) {
  var configID = Gen.getConfigID(cfg);
  var mcgMode = HwAbstr.getMCGMode(cfg);
  //CWriter.line("/* " + cfg.getName() + " configuration. Core clock = " + cfg.getValueAsText("Core_clock.outFreq") + " */");
  //CWriter.line("const clock_config_t g_" + configID + " = {");
  if (mcgMode != "N/A") {
    if (!HwAbstr.isMcgLite()) {
      // set status "is extern mcg_config_t generated"
      ClockConfigH.isMcgConfigExtern[configID] = true;
      // mcg_config_t
      CWriter.line("const mcg_config_t mcgConfig_" + configID + " =");
      CWriter.line("    {");
      OutputUtils.writeStructItemInitLine(cfg, 9, "mcgConfig.mcgMode");
      OutputUtils.writeStructItemInitLine(cfg, 9, "mcgConfig.irclkEnableMode");
      OutputUtils.writeStructItemInitLine(cfg, 9, "mcgConfig.ircs");
      OutputUtils.writeStructItemInitLine(cfg, 9, "mcgConfig.fcrdiv", "", false, ["hex","unsigned"]);
      OutputUtils.writeStructItemInitLine(cfg, 9, "mcgConfig.frdiv", "", false, ["hex","unsigned"]);
      OutputUtils.writeStructItemInitLine(cfg, 9, "mcgConfig.drs");
      OutputUtils.writeStructItemInitLine(cfg, 9, "mcgConfig.dmx32");
      if (HwAbstr.clockElementExist(cfg, "mcgOscsel")) {
        OutputUtils.writeStructItemInitLine(cfg, 9, "mcgConfig.oscsel");
      }
      if (HwAbstr.clockElementExist(cfg, "mcgPll")) {
        CWriter.line("        .pll0Config =");
        CWriter.line("            {");  
        OutputUtils.writeStructItemInitLine(cfg, 17, "mcgConfig.pll0Config.enableMode");
        if (ScriptBitFields.bitFieldExist("MCG::C5", "PRDIV")) {
          OutputUtils.writeStructItemInitLine(cfg, 17, "mcgConfig.pll0Config.prdiv", "", false, ["hex","unsigned"]);
        }
        if (ScriptBitFields.bitFieldExist("MCG::C6", "VDIV")) {
          OutputUtils.writeStructItemInitLine(cfg, 17, "mcgConfig.pll0Config.vdiv", "", false, ["hex","unsigned"]);
        }
        if (HwAbstr.clockElementExist(cfg, "mcgPllRefSrc")) {
          OutputUtils.writeStructItemInitLine(cfg, 17, "mcgConfig.pll0config.refSrc", "");
        }
        if (GeneralConfig.frdivInmcg_pll_config_t) {
          OutputUtils.writeStructItemInitLine(cfg, 17, "mcgConfig.frdiv", "", false, ["hex","unsigned"]);
        }
        CWriter.line("            },");
      }  
      CWriter.line("    };");  // mcgConfig e
    }
    else { //MCG lite 
      // set status "is extern mcglite_config_t generated"
      ClockConfigH.isMcgliteConfigExtern[configID] = true;
      // mcglite_config_t
      CWriter.line("const mcglite_config_t mcgliteConfig_" + configID + " =");
      CWriter.line("    {");
      OutputUtils.writeStructItemInitLine(cfg, 9, "mcgliteConfig.outSrc");
      OutputUtils.writeStructItemInitLine(cfg, 9, "mcgliteConfig.irclkEnableMode");
      OutputUtils.writeStructItemInitLine(cfg, 9, "mcgliteConfig.ircs");
      OutputUtils.writeStructItemInitLine(cfg, 9, "mcgliteConfig.fcrdiv");
      OutputUtils.writeStructItemInitLine(cfg, 9, "mcgliteConfig.lircDiv2");
      OutputUtils.writeStructItemInitLine(cfg, 9, "mcgliteConfig.hircEnableInNotHircMode");

      CWriter.line("    };");  // mcgConfig e
    }
  } 
  // set status "is extern sim_config_t generated"
  ClockConfigH.isSimConfigExtern[configID] = true;
  // sim_clock_config_t
  CWriter.line("const sim_clock_config_t simConfig_" + configID + " =");
  CWriter.line("    {");
  if (HwAbstr.clockElementExist(cfg, "simPllFllSel")) {
    OutputUtils.writeStructItemInitLine(cfg, 9, "simConfig.pllFllSel");
  }
  if (HwAbstr.clockElementExist(cfg, "simPllFllDiv") && GeneralConfig.simPllFllFracDiv) {
    OutputUtils.writeStructItemInitLine(cfg, 9, "simConfig.pllFllDiv", "");
  }
  if (HwAbstr.clockElementExist(cfg, "simPllFllFrac") && GeneralConfig.simPllFllFracDiv) {
    OutputUtils.writeStructItemInitLine(cfg, 9, "simConfig.pllFllFrac", "");
  }
  if (HwAbstr.clockElementExist(cfg, "simEr32kSrc")) {
    OutputUtils.writeStructItemInitLine(cfg, 9, "simConfig.er32kSrc", "");
  }
  OutputUtils.writeStructItemInitLine(cfg, 9, "simConfig.clkdiv1", "", false, ["hex","unsigned"] );
  CWriter.line("    };");
  // clear status "is extern osc_config_t generated"
  ClockConfigH.isOscConfigExtern[configID] = true;
  // osc_config_t
  if (HwAbstr.clockElementExist(cfg, "osc")) {
    CWriter.line("const osc_config_t oscConfig_" + configID + " =");
    CWriter.line("    {");
    OutputUtils.writeStructItemInitLine(cfg, 9, "oscConfig.freq", "", false, ["unsigned"]);
    OutputUtils.writeStructItemInitLine(cfg, 9, "oscConfig.capLoad");
    if (ScriptBitFields.bitFieldExist("MCG::C2","HGO0")) {
      OutputUtils.writeStructItemInitLine(cfg, 9, "oscConfig.workMode");
    }
    else {
      OutputUtils.writeStructItemInitLine(cfg, 9, "oscConfig.workMode__WithoutHgo");
    }  
    CWriter.line("        .oscerConfig =");
    CWriter.line("            {");
    OutputUtils.writeStructItemInitLine(cfg, 17, "oscConfig.oscerConfig.enableMode");  
    if (HwAbstr.clockElementExist(cfg, "oscErclkDiv")) {
      OutputUtils.writeStructItemInitLine(cfg, 17, "oscConfig.oscerConfig.erclkDiv");  
    }
    CWriter.line("            }");
  }  
  CWriter.line("    };");  
  //Replaced by #define for corresponding configuration in header file 
  //OutputUtils.writeStructItemInitLine(cfg, 5, "coreClock", "", true, ["unsigned"]);  
  //CWriter.line("};");
  CWriter.line("");  
}


/**
 * Returns FllStableDelay function for all clock configuration
 *
 * return value - string lines in array 
 */
function getFllStableDelayFunction() {
  return [
  "/*FUNCTION**********************************************************************",
  " *",
  " * Function Name : CLOCK_CONFIG_FllStableDelay",
  " * Description   : This function is used to delay for FLL stable.",
  " *",
  " *END**************************************************************************/",
  "static void CLOCK_CONFIG_FllStableDelay(void)",
  "{",
  "    uint32_t i = 30000U;",
  "    while (i--)",
  "    {",
  "        __NOP();",
  "    }",
  "}",
  ];
}

/**
 * Returns InitRtc function for all clock configuration
 *
 * return value - string lines in array 
 */
function getInitRtcFunction() {
  if (HwAbstr.hasRtcOwnOscillator()) {
    var func = [
    "/*FUNCTION**********************************************************************",
    " *",
    " * Function Name : CLOCK_CONFIG_SetRtcClock",
    " * Description   : This function is used to configuring RTC clock including ",
    " * enabling RTC oscillator.",
    " * Param capLoad : RTC oscillator capacity load",
    ];
    if (HwAbstr.hasRtcOutputToPeripherals()) {
      func = func.concat([
    " * Param enableOutPeriph : Enable (1U)/Disable (0U) clock to peripherals",
      ]);
    }
    func = func.concat([
    " *",
    " *END**************************************************************************/",
    ]);
    if (HwAbstr.hasRtcOutputToPeripherals()) {
      func = func.concat([
    "static void CLOCK_CONFIG_SetRtcClock(uint32_t capLoad, uint8_t enableOutPeriph)",
      ]);
    }
    else {
      func = func.concat([
    "static void CLOCK_CONFIG_SetRtcClock(uint32_t capLoad)",
      ]);
    }
    func = func.concat([
    "{",
    "    /* RTC clock gate enable */",
    "    CLOCK_EnableClock(kCLOCK_Rtc0);",
    "    if ((RTC->CR & RTC_CR_OSCE_MASK) == 0u) { /* Only if the Rtc oscillator is not already enabled */",
    "        /* Set the specified capacitor configuration for the RTC oscillator */",
    "        RTC_SetOscCapLoad(RTC, capLoad);",
    "        /* Enable the RTC 32KHz oscillator */",
    "        RTC->CR |= RTC_CR_OSCE_MASK;",
    "    }", 
    ]);
    if (HwAbstr.hasRtcOutputToPeripherals()) {
    func = func.concat([
    "    /* Output to other peripherals */",
    "    if (enableOutPeriph) {",
    "        RTC->CR &= ~RTC_CR_CLKO_MASK;",
    "    }",
    "    else {",
    "        RTC->CR |= RTC_CR_CLKO_MASK;",
    "    }",
    ]);
    }
    func = func.concat([
    "    /* Set the XTAL32/RTC_CLKIN frequency based on board setting. */",
    "    CLOCK_SetXtal32Freq(BOARD_XTAL32K_CLK_HZ);",
    ]);
    func = func.concat([
    "    /* Set RTC_TSR if there is fault value in RTC */",
    "    if (RTC->SR & RTC_SR_TIF_MASK) {",
    "        RTC -> TSR = RTC -> TSR;", 
    "    }",
    "    /* RTC clock gate disable */",
    "    CLOCK_DisableClock(kCLOCK_Rtc0);",
    "}", 
    ]);
  }
  else { // code for RTC which does not have its own oscillator
    var func = [
    "/*FUNCTION**********************************************************************",
    " *",
    " * Function Name : CLOCK_CONFIG_SetRtcClock",
    " * Description   : This function is used to configuring RTC clock",
    " *",
    " *END**************************************************************************/",
    "static void CLOCK_CONFIG_SetRtcClock()",
    "{",
    "    /* RTC clock gate enable */",
    "    CLOCK_EnableClock(kCLOCK_Rtc0);",
    "    /* Set RTC_TSR if there is fault value in RTC */",
    "    if (RTC->SR & RTC_SR_TIF_MASK) {",
    "        RTC -> TSR = RTC -> TSR;", 
    "    }",
    "    /* RTC clock gate disable */",
    "    CLOCK_DisableClock(kCLOCK_Rtc0);",
    "}", 
    ];
  }
  return func;
}

/**
 * Returns EnableRtcOsc function for all clock configuration in order to override related bi-fields in OSC
 *
 * return value - string lines in array 
 */
function getEnableRtcOscFunction() {
  if (!HwAbstr.isIndependentRtc()) {
    var func = [
      "/*FUNCTION**********************************************************************",
      " *",
      " * Function Name : CLOCK_CONFIG_EnableRtcOsc",
      " * Description   : This function is used to enabling RTC oscillator",
      " * Param capLoad : Oscillator capacity load",
      " *",
      " *END**************************************************************************/",
      "static void CLOCK_CONFIG_EnableRtcOsc(uint32_t capLoad)",
      "{",
      "    /* RTC clock gate enable */",
      "    CLOCK_EnableClock(kCLOCK_Rtc0);",
      "    if ((RTC->CR & RTC_CR_OSCE_MASK) == 0u) { /* Only if the Rtc oscillator is not already enabled */",
      "      /* Set the specified capacitor configuration for the RTC oscillator */",
      "      RTC_SetOscCapLoad(RTC, capLoad);",
      "      /* Enable the RTC 32KHz oscillator */",
      "      RTC->CR |= RTC_CR_OSCE_MASK;",
      "    }", 
      "    /* RTC clock gate disable */",
      "    CLOCK_DisableClock(kCLOCK_Rtc0);",
      "}", 
    ];
  }
  else {
    var func = [
    "/*FUNCTION**********************************************************************",
    " *",
    " * Function Name : CLOCK_CONFIG_EnableRtcOsc",
    " * Description   : This function is used to configuring RTC oscillator ",
    " * Param capLoad : RTC oscillator capacity load",
    " *",
    " *END**************************************************************************/",
    "static void CLOCK_CONFIG_EnableRtcOsc(uint32_t capLoad)",
    "{",
    //"    /* RTC clock gate enable */",
    //"    CLOCK_EnableClock(kCLOCK_Rtc0);",
    "    if ((RTC->GP_DATA_REG & 0x01U) != 0U) { /* Only if the Rtc oscillator is not already enabled */",
    "        /* Set the specified capacitor configuration for the RTC oscillator */",
    "        IRTC_SetOscCapLoad(RTC, capLoad);",
    "        /* Enable the RTC 32KHz oscillator */",
    "        RTC->GP_DATA_REG &= ~0x01U;",
    "    }", 
    //"    /* RTC clock gate disable */",
    //"    CLOCK_DisableClock(kCLOCK_Rtc0);",
    "}", 
    ];
  }
  return func;
}


/**
 * Returns EnableIrc48MOsc function for all clock configuration
 *
 * return value - string lines in array 
 */
function getEnableIrc48MOsc() {
  return [
  "/*FUNCTION**********************************************************************",
  " *",
  " * Function Name : CLOCK_CONFIG_EnableIrc48MOsc",
  " * Description   : This function is used to enabling IRC48M oscillator for K60_1M",
  " * as workaround because there is not enabled the oscillator automatically.",
  " *",
  " *END**************************************************************************/",
  "static void CLOCK_CONFIG_EnableIrc48MOsc()",
  "{",
  "    /* USB clock gate enable */",
  "    CLOCK_EnableClock(kCLOCK_Usbfs0);",
  "    /* IRC48M oscillator enable */",
  "    USB0->CLK_RECOVER_IRC_EN = USB_CLK_RECOVER_IRC_EN_IRC_EN_MASK | USB_CLK_RECOVER_IRC_EN_REG_EN_MASK;",
  "    /* USB clock gate disable */",
  "    CLOCK_DisableClock(kCLOCK_Usbfs0);",
  "}", 
  ];
}

/**
 * Returns SetUsbSlowClock function for all clock configuration
 *
 * return value - string lines in array 
 */
function getUsbSlowClock() {
  return [
  "/*FUNCTION**********************************************************************",
  " *",
  " * Function Name : CLOCK_CONFIG_SetUsbSlowClock",
  " * Description   : Set USB slow clock source.",
  " * Param src     : The value to set USB slow clock source.",
  " *",
  " *END**************************************************************************/",
  "static void CLOCK_CONFIG_SetUsbSlowClock(uint8_t src)",
  "{",
  "    SIM->SOPT2 = ((SIM->SOPT2 & ~SIM_SOPT2_USBSLSRC_MASK) | SIM_SOPT2_USBSLSRC(src));",
  "}",
  ];
}

/**
 * Returns "extern setRtcClock()" for all clock configuration
 *
 * return value - string lines in array 
 */
function getExternSetRtcClock() {
  return [
  "/* User function which configures RTC. */",
  "extern void setRtcClock(void);",
  ];
}

/**
 * Returns "extern setUsbPhyClock()" for all clock configuration
 *
 * return value - string lines in array 
 */
function getExternSetUsbPhyClock() {
  return [
  "/* User function which configures USBPHY. */",
  "extern void setUsbPhyClock(void);",
  ];
}

/**
 * Returns "extern setI2s0MasterClock()" for all clock configuration
 *
 * return value - string lines in array 
 */
function getExternSetI2s0MasterClock() {
  return [
  "/* User function which configures I2S0 Master clock. */",
  "extern void setI2s0MasterClock(void);",
  ];
}

/**
 * Returns "extern setModemClock(void)" for all clock configuration
 *
 * return value - string lines in array 
 */
function getExternSetModemClock() {
  return [
  "/* User function which configures Modem CLK_OUT clock. */",
  "extern void setModemClock(void);",
  ];
}

/**
 * Returns EnableUsbhs0PhyPllClock function for all clock configuration
 *
 * return value - string lines in array 
 */
function getEnableUsbPhyPllClock() {
  // The following code is copied from SDK 2.x
  return [
  "/*FUNCTION**********************************************************************",
  " *",
  " * Function Name : CLOCK_CONFIG_EnableUsbhs0PhyPllClock",
  " * Description   : This function enables the internal 480MHz USB PHY PLL clock.",
  " * Param src     : USB HS PHY PLL clock source.",
  " * Param freq    : The frequency specified by src.",
  " *",
  " *END**************************************************************************/",
  "static void CLOCK_CONFIG_EnableUsbhs0PhyPllClock(uint32_t freq)",
  "{",
  "    volatile uint32_t i;", 
  "    uint32_t phyPllDiv = 0U;", 
  "",   
  "    if (24000000U == freq)", 
  "    {", 
  "        phyPllDiv = USBPHY_PLL_SIC_PLL_DIV_SEL(0U);", 
  "    }", 
  "    else if (16000000U == freq)", 
  "    {", 
  "        phyPllDiv = USBPHY_PLL_SIC_PLL_DIV_SEL(1U);", 
  "    }", 
  "    else if (12000000U == freq)", 
  "    {", 
  "        phyPllDiv = USBPHY_PLL_SIC_PLL_DIV_SEL(2U);", 
  "    }", 
  "",   
  "    SIM->SCGC3 |= SIM_SCGC3_USBHSPHY_MASK;", 
  "    SIM->SOPT2 |= SIM_SOPT2_USBREGEN_MASK;", 
  "",   
  "    i = 500000U;", 
  "    while (i--)", 
  "    {", 
  "        __NOP();", 
  "    }", 
  "",   
  "    /* Override the trim. */",
  "    USBPHY->TRIM_OVERRIDE_EN = 0x01U;", 
  "    /* release PHY from reset */",
  "    USBPHY->CTRL &= ~USBPHY_CTRL_SFTRST_MASK;", 
  "    /* power up PLL */",
  "    USBPHY->PLL_SIC |= USBPHY_PLL_SIC_PLL_POWER_MASK;", 
  "    USBPHY->PLL_SIC = (USBPHY->PLL_SIC & ~USBPHY_PLL_SIC_PLL_DIV_SEL_MASK) | phyPllDiv;", 
  "    /* Clear bypass bit */",
  "    USBPHY->PLL_SIC &= ~USBPHY_PLL_SIC_PLL_BYPASS_MASK;", 
  "    /* Clear to 0U to run clocks */",
  "    USBPHY->CTRL &= ~USBPHY_CTRL_CLKGATE_MASK;", 
  "",   
  "    /* Wait for lock. */", 
  "    while (!(USBPHY->PLL_SIC & USBPHY_PLL_SIC_PLL_LOCK_MASK))", 
  "  {", 
  "  }", 
  "}",
  "",
  ];
}

/**
 * Returns EnableUsbhs0PfdClock function for all clock configuration
 *
 * return value - string lines in array 
 */
function getEnableUsbPfdClock() {
  // The following code is copied from SDK 2.x
  return [
  "/*FUNCTION**********************************************************************",
  " *",
  " * Function Name : CLOCK_CONFIG_EnableUsbhs0PfdClock",
  " * Description   : This function enables USB HS PFD clock.",
  " * Param frac    : The value set to PFD_FRAC, it must be in the range of 18 to 35.",
  " * Param src     : Source of the USB HS PFD clock (USB1PFDCLK).",
  " *",
  " *END**************************************************************************/",
  "static void CLOCK_CONFIG_EnableUsbhs0PfdClock(uint8_t frac, uint8_t src)", 
  "{", 
  //"    assert((frac <= 35U) && (frac >= 18U));", 
  "    uint32_t fracFreq = (480000U * 18U / frac) * 1000U;", 
  "",   
  "    USBPHY->ANACTRL = (USBPHY->ANACTRL & ~(USBPHY_ANACTRL_PFD_FRAC_MASK | USBPHY_ANACTRL_PFD_CLK_SEL_MASK))", 
  "                    | (USBPHY_ANACTRL_PFD_FRAC(frac) | USBPHY_ANACTRL_PFD_CLK_SEL(src));", 
  "",   
  "    USBPHY->ANACTRL &= ~USBPHY_ANACTRL_PFD_CLKGATE_MASK;", 
  "    while (!(USBPHY->ANACTRL & USBPHY_ANACTRL_PFD_STABLE_MASK))", 
  "    {", 
  "    }", 
  "",   
  "    if (0U == src)", 
  "    {", 
  "        CLOCK_SetExtPllFreq(g_xtal0Freq);", 
  "    }", 
  "    else if (1U == src)", 
  "    {", 
  "        CLOCK_SetExtPllFreq(fracFreq / 4U);", 
  "    }", 
  "    else if (2U == src)", 
  "    {", 
  "        CLOCK_SetExtPllFreq(fracFreq / 2U);", 
  "    }", 
  "    else", 
  "    {", 
  "        CLOCK_SetExtPllFreq(fracFreq);", 
  "    }", 
  "}", 
  ];
}

/**
 * Returns SetFllExtRefDiv function for all clock configuration
 *
 * return value - string lines in array 
 */
function getSetFllExtRefDiv() {
  return [
  "/*FUNCTION**********************************************************************",
  " *",
  " * Function Name : CLOCK_CONFIG_SetFllExtRefDiv",
  " * Description   : Configure FLL external reference divider (FRDIV).",
  " * Param frdiv   : The value to set FRDIV.",
  " *",
  " *END**************************************************************************/",
  "static void CLOCK_CONFIG_SetFllExtRefDiv(uint8_t frdiv)",
  "{",
  "    MCG->C1 = ((MCG->C1 & ~MCG_C1_FRDIV_MASK) | MCG_C1_FRDIV(frdiv));",
  "}",
  ];
}

/**
 * Returns SetPllClkSel function for all clock configuration
 *
 * return value - string lines in array 
 */
function getSetPllClkSel() {
  return [
  "/*FUNCTION**********************************************************************",
  " *",
  " * Function Name : CLOCK_CONFIG_SetPllClkSel",
  " * Description   : Configure PLL clock select (PLLCS) and wait for the", 
  " * completion.",
  " * Param pllcs   : The value to set PLLCS.",
  " *",
  " *END**************************************************************************/",
  "static void CLOCK_CONFIG_SetPllClkSel(mcg_pll_clk_select_t pllcs)",
  "{",
  "    MCG->C11 = ((MCG->C11 & ~MCG_C11_PLLCS_MASK)) | MCG_C11_PLLCS(pllcs);",
  "    while (pllcs != ((MCG->S2 & MCG_S2_PLLCST_MASK) >> MCG_S2_PLLCST_SHIFT))",
  "    {",
  "    }",
  "}",
  ];
}

/**
 * Returns SetPllFllSelDivFrac function for all clock configuration
 *
 * return value - string lines in array 
 */
function getSetPllFllSelDivFracReq() {
  return [
  "/*FUNCTION**********************************************************************",
  " *",
  " * Function Name : CLOCK_CONFIG_SetPllFllSelDivFrac",
  " * Description   : Configure PLLFLLSEL divider divison and fraction in SIM", 
  " * Param div     : The value to set the divider division.",
  " * Param frac    : The value to set the divider fraction.",
  " *",
  " *END**************************************************************************/",
  "static void CLOCK_CONFIG_SetPllFllSelDivFrac(uint8_t div, uint8_t frac)",
  "{",
  "    SIM->CLKDIV3 = ((SIM->CLKDIV3 & ~(SIM_CLKDIV3_PLLFLLDIV_MASK | SIM_CLKDIV3_PLLFLLFRAC_MASK))", 
  "                   | SIM_CLKDIV3_PLLFLLDIV(div)",
  "                   | SIM_CLKDIV3_PLLFLLFRAC(frac));",
  "}",
  ];
}

/**
 * Returns SetFlexioS0Clock function for all clock configuration
 *
 * return value - string lines in array 
 */
function getSetI2s0MasterClock() {
  return [
  "/*FUNCTION**********************************************************************",
  " *",
  " * Function Name : CLOCK_CONFIG_SetI2s0MasterClock",
  " * Description   : Set SAI master clock generation.",
  " * Param source  : MCLK input clock select.",
  " * Param frac    : MCLK fraction.",
  " * Param div     : MCLK divide.",
  " * Param outputEnable : MCLK output enable. 0U-MCLK as input, 1U-MCLK as output.",
  " *",
  " *END**************************************************************************/",
  "static void CLOCK_CONFIG_SetI2s0MasterClock(uint8_t source, uint16_t frac, uint16_t div, uint8_t outputEnable)",
  "{",
  "    /* Enable the SAI clock */",
  "    CLOCK_EnableClock(kCLOCK_Sai0);",
//#if defined(FSL_FEATURE_SAI_HAS_MCR) && (FSL_FEATURE_SAI_HAS_MCR)
  "    /* Configure Master clock output enable */",
  "    I2S0->MCR = ((I2S0->MCR & ~I2S_MCR_MOE_MASK)) | I2S_MCR_MOE(outputEnable);",
  "    /* Master clock source setting */",
  "    I2S0->MCR = ((I2S0->MCR & ~I2S_MCR_MICS_MASK)) | I2S_MCR_MICS(source);",
//#endif /* FSL_FEATURE_SAI_HAS_MCR */
//#if defined(FSL_FEATURE_SAI_HAS_MCLKDIV_REGISTER) && (FSL_FEATURE_SAI_HAS_MCLKDIV_REGISTER)
  "    /* Check if master clock divider enabled, then set master clock divider */",
  "    if (I2S0->MCR & I2S_MCR_MOE_MASK)",
  "    {",
  "        /* Set fract and divider */",
  "        I2S0->MDR = ((I2S0->MDR & ~(I2S_MDR_DIVIDE_MASK | I2S_MDR_FRACT_MASK))", 
  "                    | I2S_MDR_DIVIDE(div)",
  "                    | I2S_MDR_FRACT(frac));",
  "        /* Waiting for the divider updated */",
  "        while (I2S0->MCR & I2S_MCR_DUF_MASK)",
  "        {",
  "        }",
  "    }",
//#endif /* FSL_FEATURE_SAI_HAS_MCLKDIV_REGISTER */
  "    /* Disable the SAI clock */",
  "    CLOCK_DisableClock(kCLOCK_Sai0);",
  "}",
  ];
}

/**
 * Returns SetFlexioS0Clock function for all clock configuration
 *
 * return value - string lines in array 
 */
function getSetFlexioS0Clock() {
  return [
  "/*FUNCTION**********************************************************************",
  " *",
  " * Function Name : CLOCK_CONFIG_SetFlexioS0Clock",
  " * Description   : Set FlexIOS0 clock source.",
  " * Param src     : The value to set FlexIOS0 clock source.",
  " *",
  " *END**************************************************************************/",
  "static void CLOCK_CONFIG_SetFlexioS0Clock(uint8_t src)",
  "{",
  "    SIM->MISCCTL = ((SIM->MISCCTL & ~SIM_MISCCTL_FlexIOS0_MASK) | SIM_MISCCTL_FlexIOS0(src));",
  "}",
  ];
}

/**
 * Returns SetModemClock function for all clock configuration
 *
 * return value - string lines in array 
 */
function getSetModemClock() {
  return [
  "/*FUNCTION**********************************************************************",
  " *",
  " * Function Name : CLOCK_CONFIG_SetModemClock",
  " * Description   : Set Modem clock source.",
  " * Param enableClkout : Enable (1U)/Disable (0U) Modem CLK_OUT",
  " * Param div     : The value to set Modem CLK_OUT divider.",
  " *",
  " *END**************************************************************************/",
  "static void CLOCK_CONFIG_SetModemClock(uint8_t enableClkout, uint8_t div)",
  "{",
  "    /* Modem CLK_OUT control value */",
  "    uint8_t ctrl_value = 0x80U;",
  "    if (enableClkout) {",
  "        ctrl_value |= (0x08U | div);",
  "    }",
  "    CLOCK_EnableClock(kCLOCK_PortB);",
  "    /* Modem IRQ pin initialization (MCU PTB3) */",
  "    /* Clear PTB3 interrupt status flag */",
  "    PORTB->ISFR = PORT_ISFR_ISF(0x08);",
  "    /* Set PTB3 as GPIO input with rising edge detection */",
  "    PORTB->PCR[3] = (PORT_PCR_IRQC(0x09) | PORT_PCR_MUX(0x01));",
  "    /* Modem RESET pin initialization (MCU PTB19) */",
  "    /* Set PTB19 as GPIO */",
  "    PORTB->PCR[19] = (PORT_PCR_IRQC(0x00) | PORT_PCR_MUX(0x01));",
  "    /* Set PTB19 as output */",
  "    GPIOB->PDDR |= GPIO_PDDR_PDD(0x00080000U);",
  "    /* Set PTB19 output to 1 */",
  "    GPIOB->PSOR = GPIO_PSOR_PTSO(0x00080000U);",
  "    /* Wait for modem wake-up */",
  "    while((PORTB->PCR[3] & PORT_PCR_ISF_MASK) == 0U){}",
  "    /* Clear IRQ detection flag */",
  "    PORTB->PCR[3] |= PORT_PCR_ISF_MASK;",
  "",
  "    /* ZigBee modem CLK_OUT initialization */",
  "    /* Initialize SPI1 interface for communication with modem */",
  "    /* SPI1 clock gate enable */",
  "    CLOCK_EnableClock(kCLOCK_Spi1);",
  "    /* Pin routing of modem interface */",
  "    /* Modem MOSI pin routing */",
  "    PORT_SetPinMux(PORTB, 16U, kPORT_MuxAlt2);",
  "    /* Modem MISO pin routing */",
  "    PORT_SetPinMux(PORTB, 17U, kPORT_MuxAlt2);",
  "    /* Modem SCLK pin routing */",
  "    PORT_SetPinMux(PORTB, 11U, kPORT_MuxAlt2);",
  "    /* Modem CS0 pin routing */",
  "    PORT_SetPinMux(PORTB, 10U, kPORT_MuxAlt2);",
  "    /* Configure SPI clock polarity and phase; MSB data transferred first; frame size 8 bits; baud rate set to always fulfill modem SPI limitations */",
  "    SPI1->CTAR[0] = SPI_CTAR_FMSZ(0x07) |",
  "                   SPI_CTAR_PCSSCK(0x00) |",
  "                   SPI_CTAR_PASC(0x00) |",
  "                   SPI_CTAR_PDT(0x00) |",
  "                   SPI_CTAR_PBR(0x00) |",
  "                   SPI_CTAR_CSSCK(0x00) |",
  "                   SPI_CTAR_ASC(0x00) |",
  "                   SPI_CTAR_DT(0x00) |",
  "                   SPI_CTAR_BR(0x01);",
  "    /* Configure SPI as master with inactive state of PCS0 in high */",
  "    SPI1->MCR = SPI_MCR_MSTR_MASK |",
  "               SPI_MCR_DCONF(0x00) |",
  "               SPI_MCR_PCSIS(0x01) |",
  "               SPI_MCR_SMPL_PT(0x00);",
  "    /* Send CLK_OUT_CTRL register address */",
  "    SPI1->PUSHR = SPI_PUSHR_CONT_MASK | SPI_PUSHR_PCS(0x01) | 0x3CU;",
  "    /* Wait until address is send */",
  "    while ((SPI1->SR & (SPI_SR_TFFF_MASK | SPI_SR_RFDF_MASK)) == 0U) {}",
  "    /* Clear Tx and Rx status flags */",
  "    SPI1->SR |= SPI_SR_TFFF_MASK | SPI_SR_RFDF_MASK;",
  "     /* Discard received modem status */",
  "    (void)SPI1->POPR;",
  "    /* Send CLK_OUT_CTRL register value */",
  "    SPI1->PUSHR = SPI_PUSHR_PCS(0x01) | ctrl_value;",
  "    /* Wait until value is send */",
  "    while ((SPI1->SR & (SPI_SR_TFFF_MASK | SPI_SR_RFDF_MASK)) == 0U) {}",
  "    /* Clear Tx and Rx status flags */",
  "    SPI1->SR |= SPI_SR_TFFF_MASK | SPI_SR_RFDF_MASK;",
  "    /* Discard received modem status */",
  "    (void)SPI1->POPR;",
  "    /* SPI is returned back to its initialization state */",
  "    /* Stop the SPI */",
  "    SPI1->MCR |= SPI_MCR_HALT_MASK;",
  "    /* Wait until SPI is in stop mode */",
  "    while ((SPI1->SR & SPI_SR_TXRXS_MASK) != 0U) {}",
  "    /* Disable the SPI */",
  "    SPI1->MCR |= SPI_MCR_MDIS_MASK;",
  "    /* Reset value of MCR */",
  "    SPI1->MCR = SPI_MCR_DCONF(0x00) |",
  "               SPI_MCR_PCSIS(0x00) |",
  "               SPI_MCR_MDIS_MASK |",
  "               SPI_MCR_SMPL_PT(0x00) |",
  "               SPI_MCR_HALT_MASK;",
  "    /* Reset value of CTAR0 */",
  "    SPI1->CTAR[0] = SPI_CTAR_FMSZ(0x0F) |",
  "                   SPI_CTAR_PCSSCK(0x00) |",
  "                   SPI_CTAR_PASC(0x00) |",
  "                   SPI_CTAR_PDT(0x00) |",
  "                   SPI_CTAR_PBR(0x00) |",
  "                   SPI_CTAR_CSSCK(0x00) |",
  "                   SPI_CTAR_ASC(0x00) |",
  "                   SPI_CTAR_DT(0x00) |",
  "                   SPI_CTAR_BR(0x00);",
  "    /* SPI1 clock gate disable */",
  "    CLOCK_DisableClock(kCLOCK_Spi1);",
  "}",
  ];
}

/**
 * Returns SetRtcClock function for all clock configuration
 *
 * return value - string lines in array 
 */
function getSetRtcClockSource() {
  return [
  "/*FUNCTION**********************************************************************",
  " *",
  " * Function Name : CLOCK_CONFIG_SetRtcClockSrc",
  " * Description   : Set RTC clock source.",
  " * Param src     : The value to set RTC clock source.",
  " *",
  " *END**************************************************************************/",
  "static void CLOCK_CONFIG_SetRtcClockSrc(uint8_t src)",
  "{",
  "    SIM->MISC_CTL = ((SIM->MISC_CTL & ~SIM_MISC_CTL_RTCCLKSEL_MASK) | SIM_MISC_CTL_RTCCLKSEL(src));",
  "}",
  ];
}

/**
 * Returns SetTmr0PllClock function for all clock configuration
 *
 * return value - string lines in array 
 */
function getSetTmr0PllClockSource() {
  return [
  "/*FUNCTION**********************************************************************",
  " *",
  " * Function Name : CLOCK_CONFIG_SetTmr0PllClock",
  " * Description   : Set TMR0 PLL clock source.",
  " * Param src     : The value to set TMR0 PLL clock source.",
  " *",
  " *END**************************************************************************/",
  "static void CLOCK_CONFIG_SetTmr0PllClock(uint8_t src)",
  "{",
  "    SIM->MISC_CTL = ((SIM->MISC_CTL & ~SIM_MISC_CTL_TMR0PLLSEL_MASK) | SIM_MISC_CTL_TMR0PLLSEL(src));",
  "}",
  ];
}

/**
 * Returns EnablePll0InVlpr function for all clock configuration
 *
 * return value - string lines in array 
 */
function getEnablePllForVlpr() {
  return [
  "/*FUNCTION**********************************************************************",
  " *",
  " * Function Name : CLOCK_CONFIG_EnablePll0InVlpr",
  " * Description   : Enables PLL0 for VLP modes.",
  " *",
  " *END**************************************************************************/",
  "static void CLOCK_CONFIG_EnablePll0InVlpr(mcg_pll_config_t const *config)",
  "{",
  "    /* Configure PLL 32kHz reference clock select */",
  "    MCG->C7 = (MCG->C7 & ~MCG_C7_PLL32KREFSEL_MASK) | MCG_C7_PLL32KREFSEL(config->refSrc);",
  "    /* Enable bandgap in VLPx */",
  "    PMC->REGSC |= PMC_REGSC_BGEN_MASK;",
  "    /* Enable PLL in VLP */",
  "    SIM->CTRL_REG |= SIM_CTRL_REG_PLLVLPEN_MASK;",
  "    /* FLL or PLL is not disabled */",
  "    MCG->C2 &= ~MCG_C2_LP_MASK;",
  "    /* Set enable mode. */",
  "    MCG->C5 |= ((uint32_t)kMCG_PllEnableIndependent | (uint32_t)config->enableMode);",
  "    /* Wait for PLL lock. */",
  "    while (!(MCG->S & MCG_S_LOCK0_MASK))",
  "    {",
  "    }",
  "}",
  ];
}


// get function called from BOARD_InitBootClocks() function and create BOARD_InitBootClocks() function body
function getInitBootClocksFunctions() {
  var initFunctions = new Array();
  initFunctions.push('/*******************************************************************************');
  initFunctions.push(' ************************ BOARD_InitBootClocks function ************************');
  initFunctions.push(' ******************************************************************************/');

  initFunctions.push('void BOARD_InitBootClocks(void)');
  initFunctions.push('{');

  for (var cfgIndex = 0; cfgIndex < Gen.configs.length; cfgIndex++) {
    var cfg = Gen.configs[cfgIndex];
    if (cfg.isCalledFromDefaultInit()) {
      initFunctions.push('    ' + Gen.getConfigID(cfg) + '();');
    }
  }

  initFunctions.push('}');
  initFunctions.push('');
  return initFunctions;
}

/**
 * Generate code which calls sdk function for configuration of given peripheral clock selector
 *
 * return value - string lines in array 
 */
function generateSetPeripheralClock(cfg, elementIds, bitFieldIds, functionName, comment) {
  var allElementsExist = true;
  for (elementIdIndex = 0; elementIdIndex < elementIds.length; elementIdIndex++) {
    if (!HwAbstr.clockElementExist(cfg, elementIds[elementIdIndex]) || !HwAbstr.isClockElementUsed(cfg, elementIds[elementIdIndex])) {
      allElementsExist = false;
    }
  }
  if (allElementsExist) {
      CWriter.line("    /* " + comment + " */");
      var code = "    " + functionName + "(";
      var parameters = new Array();
      for (bitFieldIdIndex = 0; bitFieldIdIndex < bitFieldIds.length; bitFieldIdIndex++) {
        parameters.push(OutputUtils.getFieldValue(cfg, bitFieldIds[bitFieldIdIndex], ""));
      }
      code += parameters.join(", ") + ");";
      CWriter.line(code);
  }
}

function getCCondition(condId) {
  var conditions = {
    "dmx32" : "FSL_CLOCK_DRIVER_VERSION >= MAKE_VERSION(2, 2, 0)",   // [KPSDK-9157] (.dmx32) - Update CLOCK_SetFeiMode/CLOCK_SetFbiMode/CLOCK_BootToFeiMode() to support set MCG_C4[DMX32]=1 in FEI/FBI modes.
  };
  if (conditions[condId] == null) {
    scriptApi.logError("[DEBUG] Unknown value for " + condId + " (see getCCondition())."); 
  }
  return conditions[condId];  
}
   
/**
 * Generates one boot function for a given clock configuration
 *
 * @param cfg Clock configuration object
 */
function GenerateBootFunction(cfg) {
  var configID = Gen.getConfigID(cfg);
  var powerMode = HwAbstr.getPowerMode(cfg);
  var mcgMode = HwAbstr.getMCGMode(cfg);
  
  CWriter.line("void " + configID + "(void)");
  CWriter.line("{");

  /* Note if frequency is not the same as default frequency */
  var theSame = HwAbstr.isSettingSameAsDefault(cfg, "MCG.FAST_IRCLK.outFreq", "fastIrclk", "asInteger");
  if (theSame != null && !theSame) {
    CWriter.writeLines(HwAbstr.getFastIrclkMsgIfDifferentFromDefault(cfg).code);
  }
  var theSame = HwAbstr.isSettingSameAsDefault(cfg, "MCG.SLOW_IRCLK.outFreq", "slowIrclk", "asInteger");
  if (theSame != null && !theSame) {
    CWriter.writeLines(HwAbstr.getSlowIrclkMsgIfDifferentFromDefault(cfg).code);
  }
  
  /* Setup HSRUN power mode */
  if (powerMode == "HSRUN") {
    CWriter.line("    /* Set HSRUN power mode */");
    CWriter.line("    SMC_SetPowerModeProtection(SMC, kSMC_AllowPowerModeAll);");
    CWriter.line("    SMC_SetPowerModeHsrun(SMC);");
    CWriter.line("    while (SMC_GetPowerModeState(SMC) != kSMC_PowerStateHsrun)"); 
    CWriter.line("    {");
    CWriter.line("    }");
    sdkIncludes["fsl_smc"]["condition"] = true;
    sdkIncludes["fsl_smc"]["configurations"].push(configID);
  }
  
  /* Set the RTC_CLKIN frequency based on board setting. */
  if (HwAbstr.clockElementExist(cfg, "rtcClkIn") && HwAbstr.isClockElementUsed(cfg, "rtcClkIn")) {
    CWriter.line("    /* Use RTC_CLKIN input clock directly. */");
    CWriter.line("    CLOCK_SetXtal32Freq(" + OutputUtils.getFieldValue(cfg, "sim.rtcClkInFreq", "") + ");");
  }
  else if (HwAbstr.clockElementExist(cfg, "rtc") && HwAbstr.isIndependentRtc() && HwAbstr.isClockElementUsed(cfg, "rtcOsc")) {
    CWriter.line("    /* Use RTC_CLKIN input clock directly. */");
    CWriter.line("    CLOCK_SetXtal32Freq(32768U);");
  }
  
  /* CLOCK_SetSimSafeDivs, to make sure core clock, bus clock, flexbus clock and flash clock are in allowed range during clock mode switch. */
  CWriter.line("    /* Set the system clock dividers in SIM to safe value. */");
  CWriter.line("    CLOCK_SetSimSafeDivs();");

  /* Initialize RTC oscillator if RTC is enabled */ 
  if (HwAbstr.clockElementExist(cfg, "rtc")) {
    if (HwAbstr.isIndependentRtc()) {
      if (HwAbstr.isClockElementUsed(cfg, "rtcOsc")) {
        CWriter.line("    /* Enable RTC oscillator. */");
        CWriter.line("    CLOCK_CONFIG_EnableRtcOsc(" + OutputUtils.getFieldValue(cfg, "rtc.oscCapLoad", "") + ");");
        /* Request for EnableRtcOsc() function generation */
        enableRtcOscFunctionReq['status'] = true;
        enableRtcOscFunctionReq['cfgs'].push(configID);
      }
    }
    else if (HwAbstr.hasRtcOwnOscillator()) {  
      if (HwAbstr.isClockElementUsed(cfg, "rtcOsc") && HwAbstr.getRtcSetting(cfg) != "no") {
        if (HwAbstr.getRtcSetting(cfg) == "yes") {
          CWriter.line("    /* Configure RTC clock including enabling RTC oscillator. */");
          CWriter.line("    CLOCK_CONFIG_SetRtcClock(" + OutputUtils.getFieldValue(cfg, "rtc.oscCapLoad", "") + ", " + OutputUtils.getFieldValue(cfg, "rtc.rtc32khzToPeripheralsInv", "") + ");");
          /* Request for SetRtcClock() function generation */
          initRtcFunctionReq['status'] = true;
          initRtcFunctionReq['cfgs'].push(configID);
        }
        else {  // user_code
          CWriter.line("    /* Call to user function which configures RTC according to user's needs."); 
          CWriter.line("       The subsequent code may be dependent on the proper configuration on RTC. */");
          CWriter.line("    setRtcClock();");
          externSetRtcClockReq = true;
          OutputUtils.getFieldValueAndCreateDefine(cfg, "rtc.oscCapLoad", configID.toUpperCase() + "_RTC_OSC_CAP_LOAD", ClockConfigH.defineBlockH[configID], ["hex","unsigned"]);
        }
      }
    }
    else {
      if (HwAbstr.clockElementExist(cfg, "osc")) {
        if (HwAbstr.isClockElementUsed(cfg, "osc")) {
          if (HwAbstr.overrideOscSettingsByRtc(cfg)) {
            CWriter.line("    /* Enable RTC oscillator. */");
            CWriter.line("    CLOCK_CONFIG_EnableRtcOsc(" + OutputUtils.getFieldValue(cfg, "rtc.oscCapLoad", "") + ");");
            /* Request for EnableRtcOsc() function generation */
            enableRtcOscFunctionReq['status'] = true;
            enableRtcOscFunctionReq['cfgs'].push(configID);
          }
        }
      }
    }
  }
  
  /* Modem CLK_OUT configuration (MKW24) */
  if (HwAbstr.clockElementExist(cfg, "ModemInitConfig")) {
    if (HwAbstr.clockElementExist(cfg, "osc")) {
      if (HwAbstr.getModemSetting(cfg) != "no") {
        if (HwAbstr.getModemSetting(cfg) != "user_code") {
          CWriter.line("    /* Configure Modem CLK_OUT clock. */");
          CWriter.line("    CLOCK_CONFIG_SetModemClock(" + OutputUtils.getFieldValue(cfg, "modem.enableClkout", "") + ", " + OutputUtils.getFieldValue(cfg, "modem.clkoutDiv", "") + ");");
          setModemClockReq = true;
          sdkIncludes["fsl_port"]["condition"] = true;
          sdkIncludes["fsl_port"]["configurations"].push(configID);
        }
        else {
          CWriter.line("    /* Call to user function which configures Modem CLK_OUT according to user's needs."); 
          CWriter.line("       The subsequent code may be dependent on the proper configuration on Modem. */");
          CWriter.line("    setModemClock();");
          externSetModemClockReq = true;
          if (HwAbstr.isClockElementUsed(cfg, "osc")) {
            OutputUtils.getFieldValueAndCreateDefine(cfg, "modem.enableClkoutBool", configID.toUpperCase() + "_MODEM_CLKOUT_ENABLE", ClockConfigH.defineBlockH[configID]);
            if (OutputUtils.getFieldValue(cfg, "modem.enableClkoutBool") == "true") {
              OutputUtils.getFieldValueAndCreateDefine(cfg, "modem.clkoutDiv", configID.toUpperCase() + "_MODEM_CLKOUT_DIV", ClockConfigH.defineBlockH[configID]);
            }
          }
        }
      }  
    }
  }
  
  /* Setup OSC oscillator */
  if (HwAbstr.clockElementExist(cfg, "osc")) {
    if (HwAbstr.isClockElementUsed(cfg, "osc")) {
      CWriter.line("    /* Initializes OSC0 according to board configuration. */");
      CWriter.line("    CLOCK_InitOsc0(&oscConfig_" + configID + ");");
      CWriter.line("    CLOCK_SetXtal0Freq(oscConfig_" + configID + ".freq);");
    }
  }

  /* IRC48 oscillator enable (workaround for K60_1M) */
  if (HwAbstr.irc48MEnableWorkaroundNecessary(Gen)) {                                                           
    if (HwAbstr.isClockElementUsed(cfg, "irc48MOsc")) {
      if (OutputUtils.getFieldValue(cfg, "mcgConfig.oscsel") == "kMCG_OscselIrc" 
          || (cfg.getValueAsText("SIM.PLLFLLSel.sel") == "IRC48M.IRC48MCLK" && (!HwAbstr.isClockElementUsed(cfg, "usbFsClock") || OutputUtils.getFieldValue(cfg, "sim.usbSrcSel") != "kCLOCK_UsbSrcIrc48M"))) {
        CWriter.line("    /* Enable IRC48M oscillator for K60_1M as workaround because there is not enabled the oscillator automatically. */");
        CWriter.line("    CLOCK_CONFIG_EnableIrc48MOsc();");
        /* Request for EnableIrc48MOsc() function generation */
        enableIrc48MOscReq = true;
      }
    }
  }

  /* Enable USBSlowClock */
  if (HwAbstr.clockElementExist(cfg, "usbSlowClock")) {
    if (HwAbstr.isClockElementUsed(cfg, "usbSlowClock")) {
      CWriter.line("    /* Set USB slow clock. */");
      CWriter.line("    CLOCK_CONFIG_SetUsbSlowClock(" + OutputUtils.getFieldValue(cfg, "sim.usbSlowSrcSel", "") + ");");
      setUsbSlowClockReq = true;
    }
  }
    
  /* Set USB PHY clock */ 
  if (HwAbstr.clockElementExist(cfg, "usbPfdClk")) {
    if (HwAbstr.getUsbPhySetting(cfg) != "no") {
      if (HwAbstr.getUsbPhySetting(cfg) == "User_PLL_PFD") {
        CWriter.line("    /* Call to user function which configures USBPHY according to user's needs."); 
        CWriter.line("       The subsequent code may be dependent on the proper configuration on USBPHY. */");
        CWriter.line("    setUsbPhyClock();");
        externSetUsbPhyClockReq = true;
        OutputUtils.getFieldValueAndCreateDefine(cfg, "usbphy.pfdFrac", configID.toUpperCase() + "_USBPHY_PFD_FRAC_DIV", ClockConfigH.defineBlockH[configID]);
        OutputUtils.getFieldValueAndCreateDefine(cfg, "usbphy.pfdClkSel", configID.toUpperCase() + "_USBPHY_PFD_CLK_SEL", ClockConfigH.defineBlockH[configID]);
      }
      else {
        if (HwAbstr.isClockElementUsed(cfg, "usbphyPll")) {  
          CWriter.line("    /* Configure USBPHY PLL. */");
          CWriter.line("    CLOCK_CONFIG_EnableUsbhs0PhyPllClock(oscConfig_" + configID + ".freq);");
          enableUsbPhyPllReq = true;
        }
        if (HwAbstr.isClockElementUsed(cfg, "usbPfdClk")) {  
          CWriter.line("    /* Configure USB PFD clock. */");
          CWriter.line("    CLOCK_CONFIG_EnableUsbhs0PfdClock(" + OutputUtils.getFieldValue(cfg, "usbphy.pfdFrac", "") + ", " + OutputUtils.getFieldValue(cfg, "usbphy.pfdClkSel", "") + ");");
          enableUsbPhyPfdClockReq = true;
        }
      }
    }
  }

  /* Configure FRDIV because of MCGFFCLK clock in MCG modes where FLL is disabled. Otherwise FRDIV is configured by CLOCK_BootToF*EMode() functions. */
  if (HwAbstr.clockElementExist(cfg, "frdiv")) {
    if (HwAbstr.frdivNotConfiguredByBootToXMode(cfg)) {
      CWriter.line("    /* Configure FLL external reference divider (FRDIV). */");
      CWriter.line("    CLOCK_CONFIG_SetFllExtRefDiv(mcgConfig_" + configID + ".frdiv);");
      setFllExtRefDivReq = true;
    }
  }
  
  /* Set MCG mode */            
  if (!HwAbstr.isMcgLite()) {
    if (mcgMode != "N/A") {
      CWriter.line("    /* Set MCG to " + mcgMode + " mode. */");
    }
    switch (mcgMode) {
      case "FEI":
        CWriter.line("#if " + getCCondition("dmx32"));
        CWriter.line("    CLOCK_BootToFeiMode(mcgConfig_" + configID + ".dmx32,");
        CWriter.line("                        mcgConfig_" + configID + ".drs,");
        CWriter.line("                        CLOCK_CONFIG_FllStableDelay);");
        CWriter.line("#else");
        CWriter.line("    CLOCK_BootToFeiMode(mcgConfig_" + configID + ".drs,");
        CWriter.line("                        CLOCK_CONFIG_FllStableDelay);");
        CWriter.line("#endif");
        fllStableDelayFunctionReq = true;
        break;
      case "FEE":
        if (HwAbstr.clockElementExist(cfg, "mcgOscsel")) {
        CWriter.line("    CLOCK_BootToFeeMode(mcgConfig_" + configID + ".oscsel,");
        }
        else {
        CWriter.line("    CLOCK_BootToFeeMode(kMCG_OscselOsc,");
        }
        CWriter.line("                        mcgConfig_" + configID + ".frdiv,");
        CWriter.line("                        mcgConfig_" + configID + ".dmx32,");
        CWriter.line("                        mcgConfig_" + configID + ".drs,");
        CWriter.line("                        CLOCK_CONFIG_FllStableDelay);");
        fllStableDelayFunctionReq = true;
        break;
      case "FBI":
        CWriter.line("    CLOCK_SetInternalRefClkConfig(mcgConfig_" + configID + ".irclkEnableMode,");
        CWriter.line("                                  mcgConfig_" + configID + ".ircs,");
        CWriter.line("                                  mcgConfig_" + configID + ".fcrdiv);");
        CWriter.line("#if " + getCCondition("dmx32"));
        CWriter.line("    CLOCK_SetFbiMode(mcgConfig_" + configID + ".dmx32,");
        CWriter.line("                     mcgConfig_" + configID + ".drs,"); 
        CWriter.line("                     CLOCK_CONFIG_FllStableDelay);");
        CWriter.line("#else");
        CWriter.line("    CLOCK_SetFbiMode(mcgConfig_" + configID + ".drs,"); 
        CWriter.line("                     CLOCK_CONFIG_FllStableDelay);");
        CWriter.line("#endif");
        fllStableDelayFunctionReq = true;
        break;
      case "PEI":
        CWriter.line("    CLOCK_SetInternalRefClkConfig(mcgConfig_" + configID + ".irclkEnableMode,");
        CWriter.line("                                  mcgConfig_" + configID + ".ircs,");
        CWriter.line("                                  mcgConfig_" + configID + ".fcrdiv);");
        CWriter.line("    CLOCK_BootToPeiMode();");
        break;
      case "PBI":
        CWriter.line("    CLOCK_SetInternalRefClkConfig(mcgConfig_" + configID + ".irclkEnableMode,");
        CWriter.line("                                  mcgConfig_" + configID + ".ircs,");
        CWriter.line("                                  mcgConfig_" + configID + ".fcrdiv);");
        CWriter.line("    CLOCK_SetPbiMode();");
        break;
      case "BLPI":
        CWriter.line("    CLOCK_BootToBlpiMode(mcgConfig_" + configID + ".fcrdiv,");
        CWriter.line("                         mcgConfig_" + configID + ".ircs,");
        CWriter.line("                         mcgConfig_" + configID + ".irclkEnableMode);");
        break;
      case "FBE":
        if (GeneralConfig.mcgModeAfterReset == "BLPI") {
          CWriter.line("    CLOCK_SetLowPowerEnable(false);");
        }
        if (HwAbstr.clockElementExist(cfg, "mcgOscsel")) {
          CWriter.line("    CLOCK_SetExternalRefClkConfig(mcgConfig_" + configID + ".oscsel);");
        }
        else {
          CWriter.line("    CLOCK_SetExternalRefClkConfig(kMCG_OscselOsc);");
        }
        if (GeneralConfig.mcgModeAfterReset == "BLPI") {
          CWriter.line("#if " + getCCondition("dmx32"));
          CWriter.line("    CLOCK_SetFbiMode(mcgConfig_" + configID + ".dmx32,");
          CWriter.line("                     mcgConfig_" + configID + ".drs,"); 
          CWriter.line("                     CLOCK_CONFIG_FllStableDelay);");
          CWriter.line("#else");
          CWriter.line("    CLOCK_SetFbiMode(mcgConfig_" + configID + ".drs,"); 
          CWriter.line("                     CLOCK_CONFIG_FllStableDelay);");
          CWriter.line("#endif");
          fllStableDelayFunctionReq = true;
        }
        CWriter.line("    CLOCK_SetFbeMode(mcgConfig_" + configID + ".frdiv,");
        CWriter.line("                     mcgConfig_" + configID + ".dmx32,");
        CWriter.line("                     mcgConfig_" + configID + ".drs,");
        CWriter.line("                     CLOCK_CONFIG_FllStableDelay);");
        fllStableDelayFunctionReq = true;
        break;
      case "BLPE":
        if (HwAbstr.clockElementExist(cfg, "mcgOscsel")) {
          CWriter.line("    CLOCK_BootToBlpeMode(mcgConfig_" + configID + ".oscsel);");
        }
        else {
          CWriter.line("    CLOCK_BootToBlpeMode(kMCG_OscselOsc);");
        }
        break;
      case "PBE":
        if (HwAbstr.clockElementExist(cfg, "mcgOscsel")) {
        CWriter.line("    CLOCK_SetExternalRefClkConfig(mcgConfig_" + configID + ".oscsel);");
        }
        else {
        CWriter.line("    CLOCK_SetExternalRefClkConfig(kMCG_OscselOsc);");
        }
        if (HwAbstr.clockElementExist(cfg, "pllcs")) {
          CWriter.line("    CLOCK_SetPbeMode(mcgConfig_" + configID + ".pllcs,");
        }
        else {
          CWriter.line("    CLOCK_SetPbeMode(kMCG_PllClkSelPll0,");
        }
        CWriter.line("                     &mcgConfig_" + configID + ".pll0Config);");
        break;
      case "PEE":
        if (HwAbstr.clockElementExist(cfg, "mcgOscsel")) {
        CWriter.line("    CLOCK_BootToPeeMode(mcgConfig_" + configID + ".oscsel,");
        }
        else {
        CWriter.line("    CLOCK_BootToPeeMode(kMCG_OscselOsc,");
        }
        if (HwAbstr.clockElementExist(cfg, "pllcs")) {
          CWriter.line("                        mcgConfig_" + configID + ".pllcs,");
        }
        else {
          CWriter.line("                        kMCG_PllClkSelPll0,");
        }
        CWriter.line("                        &mcgConfig_" + configID + ".pll0Config);");
        break;
    }
  }
  else { // MCG lite
    CWriter.line("    /* Set MCG to " + mcgMode + " mode. */");
    CWriter.line("    CLOCK_SetMcgliteConfig(&mcgliteConfig_" + configID + ");");
  }
                                                                                                            
  /* Internal reference clock config */
  if (mcgMode != "FBI" && mcgMode != "BLPI" && mcgMode != "PEI" && mcgMode != "PBI" && cfg.getValueAsText("MCG.IRCS.enable") == "true") {
    CWriter.line("    /* Configure the Internal Reference clock (MCGIRCLK). */");
    CWriter.line("    CLOCK_SetInternalRefClkConfig(mcgConfig_" + configID + ".irclkEnableMode,");
    CWriter.line("                                  mcgConfig_" + configID + ".ircs, ");
    CWriter.line("                                  mcgConfig_" + configID + ".fcrdiv);");
  }
  
  /* If Oscsel is used but MCG mode function does not initiate Oscsel */
  if ((mcgMode == "FEI" || mcgMode == "FBI" || mcgMode == "BLPI" || mcgMode == "PEI" || mcgMode == "PBI") && cfg.getValueAsText("MCG.OSCSEL.enable") == "true") {
    CWriter.line("    /* Select the MCG external reference clock. */");
    CWriter.line("    CLOCK_SetExternalRefClkConfig(mcgConfig_" + configID + ".oscsel);");
  }
    
  /* If PLL is used but MCG mode function does not initiate PLL */
  if (!ScriptBitFields.bitFieldExist("SIM::CTRL_REG", "PLLVLPEN") || cfg.getValueAsText("SIM_CTRL_REG_PLLVLPEN_CFG") != "Enabled") {
    if (mcgMode != "PBE" && mcgMode != "PEE" && mcgMode != "PEI" && mcgMode != "PBI" && cfg.getValueAsText("MCG.PLL.enable") == "true") {
      CWriter.line("    /* Enables the PLL0 in FLL mode. */");
      CWriter.line("    CLOCK_EnablePll0(&mcgConfig_" + configID + ".pll0Config);");
    }
  }
  else {
    /* Configure PLL for VLP modes */
    if (powerMode != "VLPR") {
      if (ScriptBitFields.bitFieldExist("SIM::CTRL_REG", "PLLVLPEN") && cfg.getValueAsText("SIM_CTRL_REG_PLLVLPEN_CFG") == "Enabled") {
        CWriter.line("    /* Configure PLL for VLP modes. */");
        CWriter.line("    CLOCK_CONFIG_EnablePll0InVlpr(&mcgConfig_" + configID + ".pll0Config);");
        enablePllForVlpReq = true;
      }
    }
  }

  /* Configure PLL clock select (PLLCS)*/
  //if (!ScriptBitFields.bitFieldExist("SIM::CTRL_REG", "PLLVLPEN") || cfg.getValueAsText("SIM_CTRL_REG_PLLVLPEN_CFG") != "Enabled") {
    if (HwAbstr.clockElementExist(cfg, "pllcs")) {
      if (mcgMode != "PBE" && mcgMode != "PEE" && cfg.getValueAsText("MCG.PLLCS.enable") == "true") {
        CWriter.line("    /* Set PLL clock select. */");
        CWriter.line("    CLOCK_CONFIG_SetPllClkSel(mcgConfig_" + configID + ".pllcs);");
        setPllClkSelReq = true;
      }
    }
  //}
  
  /* SIM configuration */
  CWriter.line("    /* Set the clock configuration in SIM module. */");
  CWriter.line("    CLOCK_SetSimConfig(&simConfig_" + configID + ");");
  
  if (HwAbstr.clockElementExist(cfg, "simPllFllDiv") && HwAbstr.clockElementExist(cfg, "simPllFllFrac") && !GeneralConfig.simPllFllFracDiv) {
    CWriter.line("    /* Set the PLLFLLDIV and PLLFLLFRAC in SIM module. */");
    CWriter.line("    CLOCK_CONFIG_SetPllFllSelDivFrac(" + OutputUtils.getFieldValue(cfg, "sim.pllFllDiv", "") + ", ");
    CWriter.line("                                     " + OutputUtils.getFieldValue(cfg, "sim.pllFllFrac", "") + ");");
    setPllFllSelDivFracReq = true;
  }

  /* Launch Rtc counter if RTC doesn't have its own oscillator */
  if (HwAbstr.clockElementExist(cfg, "rtc")) {
    if (!HwAbstr.hasRtcOwnOscillator()) {  
      if (HwAbstr.isClockElementUsed(cfg, "rtc1Hz") && HwAbstr.getRtcSetting(cfg) != "no") {
        if (HwAbstr.getRtcSetting(cfg) == "yes") {
          CWriter.line("    /* Configure RTC clock. */");
          CWriter.line("    CLOCK_CONFIG_SetRtcClock();");
          /* Request for SetRtcClock() function generation */
          initRtcFunctionReq['status'] = true;
          initRtcFunctionReq['cfgs'].push(configID);
        }
        else {  // user_code
          CWriter.line("    /* Call to user function which configures RTC according to user's needs."); 
          CWriter.line("       The subsequent code may be dependent on the proper configuration on RTC. */");
          CWriter.line("    setRtcClock();");
          externSetRtcClockReq = true;
        }
      }
    }
  }

  /* Set VLPR power mode */
  if (powerMode == "VLPR") {
  /* This code can be used only once after reset */
    CWriter.line("    /* Set VLPR power mode. */");
    CWriter.line("    SMC_SetPowerModeProtection(SMC, kSMC_AllowPowerModeAll);");
    CWriter.line("#if (defined(FSL_FEATURE_SMC_HAS_LPWUI) && FSL_FEATURE_SMC_HAS_LPWUI)");
    CWriter.line("    SMC_SetPowerModeVlpr(SMC, false);");
    CWriter.line("#else");
    CWriter.line("    SMC_SetPowerModeVlpr(SMC);");
    CWriter.line("#endif");
    CWriter.line("    while (SMC_GetPowerModeState(SMC) != kSMC_PowerStateVlpr)"); 
    CWriter.line("    {");
    CWriter.line("    }");
    sdkIncludes["fsl_smc"]["condition"] = true;
    sdkIncludes["fsl_smc"]["configurations"].push(configID);
  }

  /* Configure PLL for VLP modes */
  if (powerMode == "VLPR") {
    if (ScriptBitFields.bitFieldExist("SIM::CTRL_REG", "PLLVLPEN") && cfg.getValueAsText("SIM_CTRL_REG_PLLVLPEN_CFG") == "Enabled") {
      CWriter.line("    /* Configure PLL for VLP modes. */");
      CWriter.line("    CLOCK_CONFIG_EnablePll0InVlpr(&mcgConfig_" + configID + ".pll0Config);");
      enablePllForVlpReq = true;
    }
  }

  CWriter.line("    /* Set SystemCoreClock variable. */");
  CWriter.line("    SystemCoreClock = " + configID.toUpperCase() + "_CORE_CLOCK;");

  // Peripheral clock select settings
  // generateSetPeripheralClock(cfg, elementId, bitFieldIds_array_as_parameters, functionName, comment);
  // Generated code:
  //  /* <comment> */
  //  <functionName>(<bitFieldIds[0]>, <bitFieldIds[1]>);

  /* Set AFE clock source  */  
  generateSetPeripheralClock(cfg, ["afeClock"], ["sim.afeSrcSel"],                     "CLOCK_SetAfeClkSrc",       "Set AFE clock source.");
      
  /* Set RTC clock source  */  
  generateSetPeripheralClock(cfg, ["rtcClock"], ["sim.rtcSrcSel"],                     "CLOCK_CONFIG_SetRtcClockSrc", "Set RTC clock source.");
  if (HwAbstr.clockElementExist(cfg, "rtcClock")) {
    if (HwAbstr.isClockElementUsed(cfg, "rtcClock")) {
      setRtcClockSourceReq = true;
    }
  }
      
  /* Set TMR0PLL clock source  */  
  generateSetPeripheralClock(cfg, ["tmr0PllClock"], ["sim.tmr0PllSrcSel"],             "CLOCK_CONFIG_SetTmr0PllClock", "Set TMR0 PLL clock source.");
  if (HwAbstr.clockElementExist(cfg, "tmr0PllClock")) {
    if (HwAbstr.isClockElementUsed(cfg, "tmr0PllClock")) {
      setTmr0PllClockSourceReq = true;
    }
  }
      
  /* Set RTC clock out */
  if (HwAbstr.hasRtcOwnOscillator()) {
    generateSetPeripheralClock(cfg, ["rtcOutClock", "rtcOutClockSel"], ["sim.rtcClkOutSel"], "CLOCK_SetRtcClkOutClock",  "Set RTC_CLKOUT source.");
  }
  else {
    generateSetPeripheralClock(cfg, ["rtcOutClock", "rtcOutClockSel"], ["sim.rtcClkOutSel_NotOwnOsc"], "CLOCK_SetRtcClkOutClock",  "Set RTC_CLKOUT source.");
  }
    
  /* Enable USBfs0Clock */
  if (!HwAbstr.isMcgLite()) {
    generateSetPeripheralClock(cfg, ["usbFsClock"], ["sim.usbSrcSel", "sim.simUsbFreq"], "CLOCK_EnableUsbfs0Clock",  "Enable USB FS clock.");
  }
  else {
    generateSetPeripheralClock(cfg, ["usbFsClock"], ["sim.usbSrcSel_WithoutFracDiv", "sim.simUsbFreq_WithoutFracDiv"], "CLOCK_EnableUsbfs0Clock",  "Enable USB FS clock.");
  }
    
  /* Set XBAR clock out source  */  
  generateSetPeripheralClock(cfg, ["xbarClkOutClock"], ["sim.xbarClkOutSrcSel"],       "CLOCK_SetXbarClock",       "Set XBAR clock out source.");
      
  /* Set ADC trigger clock source  */  
  generateSetPeripheralClock(cfg, ["adcTrgClock"], ["sim.adcTrgSrcSel"],               "CLOCK_SetAdcTriggerClock", "Set ADC trigger clock source.");
      
  /* Set ENET 1588T clock source  */  
  generateSetPeripheralClock(cfg, ["enet1588Clock"], ["sim.enetTimerSrcSel"],          "CLOCK_SetEnetTime0Clock",  "Set enet timestamp clock source.");
      
  /* Set RMII clock source */
  generateSetPeripheralClock(cfg, ["enetRmiiClock"], ["sim.enetRmiiSrcSel"],           "CLOCK_SetRmii0Clock",      "Set RMII clock source.");

  /* Set SDHC clock source */
  generateSetPeripheralClock(cfg, ["sdhcClock"], ["sim.sdhcSrcSel"],                   "CLOCK_SetSdhc0Clock",      "Set SDHC clock source.");
    
  /* Set UART0 clock source */
  generateSetPeripheralClock(cfg, ["uart0Clock"], ["sim.uart0SrcSel"],                 "CLOCK_SetLpsci0Clock",     "Set UART0 clock source.");
    
  /* Set LPUART clock source */
  if (!GeneralConfig.useSetLpuart0ClockAlthoughLPUARTCLK) {
    generateSetPeripheralClock(cfg, ["lpuartClock"], ["sim.lpuartSrcSel"],             "CLOCK_SetLpuartClock",     "Set LPUART clock source.");
  }
  else {
    generateSetPeripheralClock(cfg, ["lpuartClock"], ["sim.lpuartSrcSel"],             "CLOCK_SetLpuart0Clock",    "Set LPUART clock source.");
  }
  
  /* Set LPUART0 clock source */
  generateSetPeripheralClock(cfg, ["lpuart0Clock"], ["sim.lpuart0SrcSel"],             "CLOCK_SetLpuart0Clock",    "Set LPUART0 clock source.");
    
  /* Set LPUART1 clock source */
  generateSetPeripheralClock(cfg, ["lpuart1Clock"], ["sim.lpuart1SrcSel"],             "CLOCK_SetLpuart1Clock",    "Set LPUART1 clock source.");
    
  /* Set LPI2C0 clock source */
  generateSetPeripheralClock(cfg, ["lpi2c0Clock"], ["sim.lpi2c0SrcSel"],               "CLOCK_SetLpi2c0Clock",     "Set LPI2C0 clock source.");
    
  /* Set LPI2C1 clock source */
  generateSetPeripheralClock(cfg, ["lpi2c1Clock"], ["sim.lpi2c1SrcSel"],               "CLOCK_SetLpi2c1Clock",     "Set LPI2C1 clock source.");
    
  
  /* Set I2S/SAI MCLK clock */
  if (HwAbstr.clockElementExist(cfg, "i2s0Mclk")) {
    if (HwAbstr.getFlexioClkSetting(cfg) == "FlexIO_I2S0") {
      CWriter.line("    /* Set I2S/SAI MCLK clock */");
      CWriter.line("    CLOCK_CONFIG_SetI2s0MasterClock(" + OutputUtils.getFieldValue(cfg, "i2s0.mclkInputSelect", "") + ", ");
      CWriter.line("                                    " + OutputUtils.getFieldValue(cfg, "i2s0.mclkFrac", "") + ", ");
      CWriter.line("                                    " + OutputUtils.getFieldValue(cfg, "i2s0.mclkDiv", "") + ", ");
      CWriter.line("                                    " + OutputUtils.getFieldValue(cfg, "i2s0.mclkOutputEnable", "") + ");");
      setI2s0MasterClockReq = true;
    }
    else if (HwAbstr.getFlexioClkSetting(cfg) == "FlexIO_user_I2S0") {
      CWriter.line("    /* Call to user function which configures I2S0 Master clock according to user's needs."); 
      CWriter.line("       The subsequent code may be dependent on the proper configuration on I2S0. */");
      CWriter.line("    setI2s0MasterClock();");
      externSetI2s0MasterClockReq = true;
      OutputUtils.getFieldValueAndCreateDefine(cfg, "i2s0.mclkInputSelectEnum", configID.toUpperCase() + "_I2S0_MCLK_SOURCE", ClockConfigH.defineBlockH[configID]);
      OutputUtils.getFieldValueAndCreateDefine(cfg, "i2s0.mclkOutputEnableBool", configID.toUpperCase() + "_I2S0_MCLK_OUTPUT_ENABLE", ClockConfigH.defineBlockH[configID]);
      OutputUtils.getFieldValueAndCreateDefine(cfg, "i2s0.mclkFreq", configID.toUpperCase() + "_I2S0_MCLK_HZ", ClockConfigH.defineBlockH[configID]);
      if (OutputUtils.getFieldValue(cfg, "i2s0.mclkOutputEnableBool") == "true") {
        OutputUtils.getFieldValueAndCreateDefine(cfg, "i2s0.mclkInClkSelectFreq", configID.toUpperCase() + "_I2S0_MCLK_SOURCE_HZ", ClockConfigH.defineBlockH[configID]);
      }
      else {
        OutputUtils.getFieldValueAndCreateDefine(cfg, "i2s0.mclkInExtFreq", configID.toUpperCase() + "_I2S0_MCLK_SOURCE_HZ", ClockConfigH.defineBlockH[configID]);
      }
    }
  }

  /* Set FLEXIOS0 clock source */
  generateSetPeripheralClock(cfg, ["flexioS0Clock"], ["sim.flexioS0SrcSel"],           "CLOCK_CONFIG_SetFlexioS0Clock",   "Set FLEXIOS0 clock source.");
  if (HwAbstr.clockElementExist(cfg, "flexioS0Clock")) {
    if (HwAbstr.isClockElementUsed(cfg, "flexioS0Clock")) {
      setFlexioS0ClockReq = true;
    }
  }

  /* Set FLEXIO clock source */
  if (!HwAbstr.isMcgLite()) {
    if (HwAbstr.clockElementExist(cfg, "flexioS0Clock") && HwAbstr.isClockElementUsed(cfg, "flexioS0Clock")) {
      generateSetPeripheralClock(cfg, ["flexioClock"], ["sim.flexioSrcSel_WithI2s0Mclk"], "CLOCK_SetFlexio0Clock",    "Set FLEXIO clock source.");
    }
    else {
      generateSetPeripheralClock(cfg, ["flexioClock"], ["sim.flexioSrcSel"],             "CLOCK_SetFlexio0Clock",    "Set FLEXIO clock source.");
    }
  }
  else {
    generateSetPeripheralClock(cfg, ["flexioClock"], ["sim.flexioSrcSel_McgLite"],     "CLOCK_SetFlexio0Clock",    "Set FLEXIO clock source.");
  }
    
  /* Set EMVSIM clock source */
  generateSetPeripheralClock(cfg, ["emvsimClock"], ["sim.emvsimSrcSel"],               "CLOCK_SetEmvsimClock",     "Set EMVSIM clock source.");
    
  /* Set TPM clock source */
  if (!HwAbstr.isMcgLite()) {
    generateSetPeripheralClock(cfg, ["tpmClock"], ["sim.tpmSrcSel"],                   "CLOCK_SetTpmClock",        "Set TPM clock source.");
  }
  else {
    generateSetPeripheralClock(cfg, ["tpmClock"], ["sim.tpmSrcSel_McgLite"],           "CLOCK_SetTpmClock",        "Set TPM clock source.");
  }
    
  /* Set CLKOUT clock source */ 
  if (!HwAbstr.isMcgLite()) {
    generateSetPeripheralClock(cfg, ["clkoutClock"], ["sim.clkoutSrcSel"],             "CLOCK_SetClkOutClock",     "Set CLKOUT source.");
  }
  else{
    generateSetPeripheralClock(cfg, ["clkoutClock"], ["sim.clkoutSrcSel_McgLite"],     "CLOCK_SetClkOutClock",     "Set CLKOUT source.");
  }
    
  /* Set Trace clock source */
  if (HwAbstr.clockElementExist(cfg, "traceDiv") && HwAbstr.clockElementExist(cfg, "traceFrac")) {
    generateSetPeripheralClock(cfg, ["traceClock"], ["sim.traceSrcSel", "sim.traceDivVal", "sim.traceFracVal"], "CLOCK_SetTraceClock", "Set debug trace clock source.");
  }
  else {
    generateSetPeripheralClock(cfg, ["traceClock"], ["sim.traceSrcSel"],                                        "CLOCK_SetTraceClock", "Set debug trace clock source.");
  }
  
  /* Set COP clock source */
  if (HwAbstr.clockElementExist(cfg, "copClock")) {
    if (HwAbstr.isClockElementUsed(cfg, "copClock")) {
      if (ScriptBitFields.bitFieldExist("SIM::COPC","COPCLKSEL")) {
        OutputUtils.getFieldValueAndCreateDefine(cfg, "sim.copSrcSel", configID.toUpperCase() + "_SIM_COP_CLK_SEL", ClockConfigH.defineBlockH[configID]);
      }
      else {
        OutputUtils.getFieldValueAndCreateDefine(cfg, "sim.copSrcSel_OneBit", configID.toUpperCase() + "_SIM_COP_CLK_SEL", ClockConfigH.defineBlockH[configID]);
      }
    }
  }

  CWriter.line("}");
  CWriter.line("");  
}

function createDependency(module, component, coreID) {
  var dependency = { 
    resourceType: "SWComponent",
    resourceId: "platform.drivers." + module,
    description: "Clocks initialization requires the " + module.toUpperCase() + " Driver in the project.",
    problem_level: 2,
    source: "Clocks:" + component,
    features:
    [{ feature_name: "enabled",
        evaluation: "equal",
        configuration: coreID,
        data: [{
          value: "true",
          unit: null,
          min:  null,
          max: null
       }]
    }]   
  }
  return dependency;
}

function pushDependency(dependencyHelper, dependency) {
  dependencyHelper.addDependency(dependency);
}
  
/////////////////// code generation  //////////////////////////////////

/*
// write header to the output
CWriter.write(CommonHeaderText());
CWriter.write("");
*/

// write How to setup comment
writeHowToSetupComment();
CWriter.write("");
// write global Yaml block
if (Gen.profile.getYaml() != null) {
  CWriter.write("/* clang-format off */");
  CWriter.write(Gen.profile.getYaml());
  CWriter.write("/* clang-format on */");
} 
CWriter.write("");
// write block of #includes
var optionalIncludesPosition = CWriter.line(null);
CWriter.write("");

// allocate place for block of #defines 
var defineBlockPosition = CWriter.line(null);
// create block instance of #defines 
var defineBlockC = new DefineBlock();
SDKMapper.setCWriterDefineContainer = defineBlockC;   
var defineBlockLinesC = OutputUtils.getDefinitionIntro();

//write common variables introduction
CWriter.writeLines(OutputUtils.getVariablesIntro());
CWriter.writeLines([
"/* System clock frequency. */",
"extern uint32_t SystemCoreClock;",
]);
CWriter.write("");
  
// allocate place for FllStableDelay, InitRtc,... functions 
var internalFunctionHeaderPosition = CWriter.line(null);
var internalFunctionPosition = CWriter.line(null);
var fllStableDelayFunctionReq = false;
var initRtcFunctionReq = {status: false, cfgs: new Array()};
var enableRtcOscFunctionReq = {status: false, cfgs: new Array()};
var enableIrc48MOscReq = false;
var externSetRtcClockReq = false;
var externSetUsbPhyClockReq = false;
var externSetI2s0MasterClockReq = false;
var externSetModemClockReq = false;
var enableUsbPhyPllReq = false;
var enableUsbPhyPfdClockReq = false;
var setUsbSlowClockReq = false;
var setFllExtRefDivReq = false;
var setPllClkSelReq = false;
var setFlexioS0ClockReq = false;
var setI2s0MasterClockReq = false;
var setPllFllSelDivFracReq = false;
var setModemClockReq = false;
var setRtcClockSourceReq = false;
var setTmr0PllClockSourceReq = false;
var enablePllForVlpReq = false;

// write clock initialization functions
CWriter.writeLines(getInitBootClocksFunctions());

for (var cfgIndex = 0; cfgIndex < Gen.configs.length; cfgIndex++) {
  var cfg = Gen.configs[cfgIndex];
  // write configuration introduction
  CWriter.writeLines(OutputUtils.getConfigurationIntro(cfg));
  // write Yaml block
  if (cfg.getYaml() != null) {
    CWriter.write("/* clang-format off */");
    CWriter.write(cfg.getYaml());
    CWriter.write("/* clang-format on */");
  }
  CWriter.line("");

  // write variables introduction
  CWriter.writeLines(OutputUtils.getVariablesIntro(cfg));
  // generate the structure variable for each configuration 
  GenerateCLKConfigStructure(cfg);

  // write code introduction
  CWriter.writeLines(OutputUtils.getCodeIntro(cfg));
  // write boot function
  GenerateBootFunction(cfg);
}

// write internal functions on position internalFunctionPosition
if (externSetRtcClockReq) {
  CWriter.writeLines(getExternSetRtcClock().concat(""), internalFunctionPosition);
}
if (externSetUsbPhyClockReq) {
  CWriter.writeLines(getExternSetUsbPhyClock().concat(""), internalFunctionPosition);
}
if (externSetI2s0MasterClockReq) {
  CWriter.writeLines(getExternSetI2s0MasterClock().concat(""), internalFunctionPosition);
}
if (externSetModemClockReq) {
  CWriter.writeLines(getExternSetModemClock().concat(""), internalFunctionPosition);
}
if (fllStableDelayFunctionReq) {
  CWriter.writeLines(getFllStableDelayFunction().concat(""), internalFunctionPosition);
}
if (initRtcFunctionReq['status']) {
  CWriter.writeLines(getInitRtcFunction().concat(""), internalFunctionPosition);
  sdkIncludes["fsl_rtc"]["condition"] = true;
  sdkIncludes["fsl_rtc"]["configurations"] = initRtcFunctionReq.cfgs;
}
if (enableRtcOscFunctionReq['status']) {
  CWriter.writeLines(getEnableRtcOscFunction().concat(""), internalFunctionPosition);
  if (HwAbstr.isIndependentRtc()) {
    sdkIncludes["fsl_irtc"]["condition"] = true;
    sdkIncludes["fsl_irtc"]["configurations"] = enableRtcOscFunctionReq.cfgs;
  }
  else {
    sdkIncludes["fsl_rtc"]["condition"] = true;
    sdkIncludes["fsl_rtc"]["configurations"] = enableRtcOscFunctionReq.cfgs;
  }
}
if (enableIrc48MOscReq) {
  CWriter.writeLines(getEnableIrc48MOsc().concat(""), internalFunctionPosition);
}
if (enableUsbPhyPllReq) {
  CWriter.writeLines(getEnableUsbPhyPllClock().concat(""), internalFunctionPosition);
}
if (enableUsbPhyPfdClockReq) {
  CWriter.writeLines(getEnableUsbPfdClock().concat(""), internalFunctionPosition);
}
if (setUsbSlowClockReq) {
  CWriter.writeLines(getUsbSlowClock().concat(""), internalFunctionPosition);
}
if (setPllFllSelDivFracReq) {
  CWriter.writeLines(getSetPllFllSelDivFracReq().concat(""), internalFunctionPosition);
}
if (enablePllForVlpReq) {
  CWriter.writeLines(getEnablePllForVlpr().concat(""), internalFunctionPosition);
}
if (setI2s0MasterClockReq) {              
  CWriter.writeLines(getSetI2s0MasterClock().concat(""), internalFunctionPosition);
}
if (setFlexioS0ClockReq) {
  CWriter.writeLines(getSetFlexioS0Clock().concat(""), internalFunctionPosition);
}
if (setFllExtRefDivReq) {
  CWriter.writeLines(getSetFllExtRefDiv().concat(""), internalFunctionPosition);
}
if (setPllClkSelReq) {
  CWriter.writeLines(getSetPllClkSel().concat(""), internalFunctionPosition);
}
if (setModemClockReq) {
  CWriter.writeLines(getSetModemClock().concat(""), internalFunctionPosition);
}
if (setRtcClockSourceReq) {
  CWriter.writeLines(getSetRtcClockSource().concat(""), internalFunctionPosition);
}
if (setTmr0PllClockSourceReq) {
  CWriter.writeLines(getSetTmr0PllClockSource().concat(""), internalFunctionPosition);
}

// write "CODE" header if an internal function is generated
if (!CWriter.isPositionEmpty(internalFunctionPosition)) {
  CWriter.writeLines(OutputUtils.getCodeIntro(), internalFunctionHeaderPosition);
}

// complete defines block and write it
defineBlockLinesC = defineBlockLinesC.concat(defineBlockC.getDefineBlock()).concat("");
CWriter.writeLines(defineBlockLinesC, defineBlockPosition);

// generate #includes and register its dependencies

var dependencyHelper = scriptApi.getDependencyHelper();
var coreListTxt = scriptApi.getProfile().getMcuInfo().getCoresList();
var coreList = JSON.parse(coreListTxt);
var coreIds = Object.keys(coreList);

for (var coreId = 0; coreId < coreIds.length; coreId++) {
  for(var configID = 0; configID < Gen.configs.length; configID++) {
    pushDependency(dependencyHelper, createDependency("common", Gen.getConfigID(Gen.configs[configID]), coreIds[coreId]));
  }
}

var sdkIncludesKeys = Object.keys(sdkIncludes);
for (includeIndex = 0; includeIndex < sdkIncludesKeys.length; includeIndex++) {
  var includeItem = sdkIncludes[sdkIncludesKeys[includeIndex]];
  if (includeItem["condition"]) {
    CWriter.write(includeItem["code"], optionalIncludesPosition);
    if (includeItem["name"] != "") {
      for (var coreId = 0; coreId < coreIds.length; coreId++) {
        for(var configID = 0; configID < includeItem["configurations"].length; configID ++) {
          pushDependency(dependencyHelper, createDependency(includeItem["name"], includeItem["configurations"][configID], coreIds[coreId]));
        }
      }
    }
  }
}  
