diff --git a/drivers/fsl_clock.c b/drivers/fsl_clock.c
new file mode 100644
index 0000000..81cbe23
--- /dev/null
+++ b/drivers/fsl_clock.c
@@ -0,0 +1,2176 @@
+/*
+ * Copyright 2017 - 2020 , NXP
+ * All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include "fsl_clock.h"
+#include "fsl_power.h"
+/*******************************************************************************
+ * Definitions
+ ******************************************************************************/
+/* Component ID definition, used by tools. */
+#ifndef FSL_COMPONENT_ID
+#define FSL_COMPONENT_ID "platform.drivers.clock"
+#endif
+#define NVALMAX (0x100U)
+#define PVALMAX (0x20U)
+#define MVALMAX (0x10000U)
+
+#define PLL_MAX_N_DIV 0x100U
+
+/*--------------------------------------------------------------------------
+!!! If required these #defines can be moved to chip library file
+----------------------------------------------------------------------------*/
+
+#define PLL_SSCG1_MDEC_VAL_P (10U) /* MDEC is in bits 25 downto 10 */
+#define PLL_SSCG1_MDEC_VAL_M (0xFFFFULL << PLL_SSCG1_MDEC_VAL_P)
+#define PLL_NDEC_VAL_P (0U) /* NDEC is in bits 9:0 */
+#define PLL_NDEC_VAL_M (0xFFUL << PLL_NDEC_VAL_P)
+#define PLL_PDEC_VAL_P (0U) /*!< PDEC is in bits 6:0 */
+#define PLL_PDEC_VAL_M (0x1FUL << PLL_PDEC_VAL_P)
+
+#define PLL_MIN_CCO_FREQ_MHZ (275000000U)
+#define PLL_MAX_CCO_FREQ_MHZ (550000000U)
+#define PLL_LOWER_IN_LIMIT (2000U) /*!< Minimum PLL input rate */
+#define PLL_HIGHER_IN_LIMIT (150000000U) /*!< Maximum PLL input rate */
+#define PLL_MIN_IN_SSMODE (3000000U)
+#define PLL_MAX_IN_SSMODE \
+ (100000000U) /*!< Not find the value in UM, Just use the maximum frequency which device support */
+
+/* PLL NDEC reg */
+#define PLL_NDEC_VAL_SET(value) (((unsigned long)(value) << PLL_NDEC_VAL_P) & PLL_NDEC_VAL_M)
+/* PLL PDEC reg */
+#define PLL_PDEC_VAL_SET(value) (((unsigned long)(value) << PLL_PDEC_VAL_P) & PLL_PDEC_VAL_M)
+/* SSCG control1 */
+#define PLL_SSCG1_MDEC_VAL_SET(value) (((uint64_t)(value) << PLL_SSCG1_MDEC_VAL_P) & PLL_SSCG1_MDEC_VAL_M)
+
+/* PLL0 SSCG control1 */
+#define PLL0_SSCG_MD_FRACT_P 0U
+#define PLL0_SSCG_MD_INT_P 25U
+#define PLL0_SSCG_MD_FRACT_M (0x1FFFFFFUL << PLL0_SSCG_MD_FRACT_P)
+#define PLL0_SSCG_MD_INT_M ((uint64_t)0xFFUL << PLL0_SSCG_MD_INT_P)
+
+#define PLL0_SSCG_MD_FRACT_SET(value) (((uint64_t)(value) << PLL0_SSCG_MD_FRACT_P) & PLL0_SSCG_MD_FRACT_M)
+#define PLL0_SSCG_MD_INT_SET(value) (((uint64_t)(value) << PLL0_SSCG_MD_INT_P) & PLL0_SSCG_MD_INT_M)
+
+/* Saved value of PLL output rate, computed whenever needed to save run-time
+ computation on each call to retrive the PLL rate. */
+static uint32_t s_Pll0_Freq;
+static uint32_t s_Pll1_Freq;
+
+/** External clock rate on the CLKIN pin in Hz. If not used,
+ set this to 0. Otherwise, set it to the exact rate in Hz this pin is
+ being driven at. */
+static uint32_t s_Ext_Clk_Freq = 16000000U;
+static uint32_t s_I2S_Mclk_Freq = 0U;
+static uint32_t s_PLU_ClkIn_Freq = 0U;
+
+/*******************************************************************************
+ * Variables
+ ******************************************************************************/
+
+/*******************************************************************************
+ * Prototypes
+ ******************************************************************************/
+/* Find SELP, SELI, and SELR values for raw M value, max M = MVALMAX */
+static void pllFindSel(uint32_t M, uint32_t *pSelP, uint32_t *pSelI, uint32_t *pSelR);
+/* Get predivider (N) from PLL0 NDEC setting */
+static uint32_t findPll0PreDiv(void);
+/* Get predivider (N) from PLL1 NDEC setting */
+static uint32_t findPll1PreDiv(void);
+/* Get postdivider (P) from PLL0 PDEC setting */
+static uint32_t findPll0PostDiv(void);
+/* Get postdivider (P) from PLL1 PDEC setting. */
+static uint32_t findPll1PostDiv(void);
+/* Get multiplier (M) from PLL0 MDEC and SSCG settings */
+static float findPll0MMult(void);
+/* Get multiplier (M) from PLL1 MDEC. */
+static uint32_t findPll1MMult(void);
+/* Get the greatest common divisor */
+static uint32_t FindGreatestCommonDivisor(uint32_t m, uint32_t n);
+/* Set PLL output based on desired output rate */
+static pll_error_t CLOCK_GetPll0Config(uint32_t finHz, uint32_t foutHz, pll_setup_t *pSetup, bool useSS);
+/* Update local PLL rate variable */
+static void CLOCK_GetPLL0OutFromSetupUpdate(pll_setup_t *pSetup);
+/* Update local PLL1 rate variable */
+static void CLOCK_GetPLL1OutFromSetupUpdate(pll_setup_t *pSetup);
+
+/*******************************************************************************
+ * Code
+ ******************************************************************************/
+
+/* Clock Selection for IP */
+/**
+ * brief Configure the clock selection muxes.
+ * param connection : Clock to be configured.
+ * return Nothing
+ */
+void CLOCK_AttachClk(clock_attach_id_t connection)
+{
+ uint8_t mux;
+ uint8_t sel;
+ uint16_t item;
+ uint32_t tmp32 = (uint32_t)connection;
+ uint32_t i;
+ volatile uint32_t *pClkSel;
+
+ pClkSel = &(SYSCON->SYSTICKCLKSELX[0]);
+
+ if (kNONE_to_NONE != connection)
+ {
+ for (i = 0U; i < 2U; i++)
+ {
+ if (tmp32 == 0U)
+ {
+ break;
+ }
+ item = (uint16_t)GET_ID_ITEM(tmp32);
+ if (item != 0U)
+ {
+ mux = (uint8_t)GET_ID_ITEM_MUX(item);
+ sel = (uint8_t)GET_ID_ITEM_SEL(item);
+ if (mux == CM_RTCOSC32KCLKSEL)
+ {
+ PMC->RTCOSC32K = (PMC->RTCOSC32K & ~PMC_RTCOSC32K_SEL_MASK) | PMC_RTCOSC32K_SEL(sel);
+ }
+ else if (mux == CM_OSTIMERCLKSEL)
+ {
+ PMC->OSTIMERr = (PMC->OSTIMERr & ~PMC_OSTIMER_OSTIMERCLKSEL_MASK) | PMC_OSTIMER_OSTIMERCLKSEL(sel);
+ }
+ else
+ {
+ pClkSel[mux] = sel;
+ }
+ }
+ tmp32 = GET_ID_NEXT_ITEM(tmp32); /* pick up next descriptor */
+ }
+ }
+}
+
+/* Return the actual clock attach id */
+/**
+ * brief Get the actual clock attach id.
+ * This fuction uses the offset in input attach id, then it reads the actual source value in
+ * the register and combine the offset to obtain an actual attach id.
+ * param attachId : Clock attach id to get.
+ * return Clock source value.
+ */
+clock_attach_id_t CLOCK_GetClockAttachId(clock_attach_id_t attachId)
+{
+ uint8_t mux;
+ uint32_t actualSel;
+ uint32_t tmp32 = (uint32_t)attachId;
+ uint32_t i;
+ uint32_t actualAttachId = 0U;
+ uint32_t selector = GET_ID_SELECTOR(tmp32);
+ volatile uint32_t *pClkSel;
+
+ pClkSel = &(SYSCON->SYSTICKCLKSELX[0]);
+
+ if (kNONE_to_NONE == attachId)
+ {
+ return kNONE_to_NONE;
+ }
+
+ for (i = 0U; i < 2U; i++)
+ {
+ mux = (uint8_t)GET_ID_ITEM_MUX(tmp32);
+ if (tmp32 != 0UL)
+ {
+ if (mux == CM_RTCOSC32KCLKSEL)
+ {
+ actualSel = ((PMC->RTCOSC32K) & PMC_RTCOSC32K_SEL_MASK) >> PMC_RTCOSC32K_SEL_SHIFT;
+ }
+ else if (mux == CM_OSTIMERCLKSEL)
+ {
+ actualSel = ((PMC->OSTIMERr) & PMC_OSTIMER_OSTIMERCLKSEL_MASK) >> PMC_OSTIMER_OSTIMERCLKSEL_SHIFT;
+ }
+ else
+ {
+ actualSel = pClkSel[mux];
+ }
+
+ /* Consider the combination of two registers */
+ actualAttachId |= CLK_ATTACH_ID(mux, actualSel, i);
+ }
+ tmp32 = GET_ID_NEXT_ITEM(tmp32); /*!< pick up next descriptor */
+ }
+
+ actualAttachId |= selector;
+
+ return (clock_attach_id_t)actualAttachId;
+}
+
+/* Set IP Clock Divider */
+/**
+ * brief Setup peripheral clock dividers.
+ * param div_name : Clock divider name
+ * param divided_by_value: Value to be divided
+ * param reset : Whether to reset the divider counter.
+ * return Nothing
+ */
+void CLOCK_SetClkDiv(clock_div_name_t div_name, uint32_t divided_by_value, bool reset)
+{
+ volatile uint32_t *pClkDiv;
+
+ pClkDiv = &(SYSCON->SYSTICKCLKDIV0);
+ if ((div_name >= kCLOCK_DivFlexFrg0) && (div_name <= kCLOCK_DivFlexFrg7))
+ {
+ /*!< Flexcomm Interface function clock = (clock selected via FCCLKSEL) / (1+ MULT /DIV), DIV = 0xFF */
+ ((volatile uint32_t *)pClkDiv)[(uint8_t)div_name] =
+ SYSCON_FLEXFRG0CTRL_DIV_MASK | SYSCON_FLEXFRG0CTRL_MULT(divided_by_value);
+ }
+ else
+ {
+ if (reset)
+ {
+ ((volatile uint32_t *)pClkDiv)[(uint8_t)div_name] = 1UL << 29U;
+ }
+ if (divided_by_value == 0U) /*!< halt */
+ {
+ ((volatile uint32_t *)pClkDiv)[(uint8_t)div_name] = 1UL << 30U;
+ }
+ else
+ {
+ ((volatile uint32_t *)pClkDiv)[(uint8_t)div_name] = (divided_by_value - 1U);
+ }
+ }
+}
+
+/* Set RTC 1KHz Clock Divider */
+/**
+ * brief Setup rtc 1khz clock divider.
+ * param divided_by_value: Value to be divided
+ * return Nothing
+ */
+void CLOCK_SetRtc1khzClkDiv(uint32_t divided_by_value)
+{
+ PMC->RTCOSC32K =
+ (PMC->RTCOSC32K & ~PMC_RTCOSC32K_CLK1KHZDIV_MASK) | PMC_RTCOSC32K_CLK1KHZDIV(divided_by_value - 28U);
+}
+
+/* Set RTC 1KHz Clock Divider */
+/**
+ * brief Setup rtc 1hz clock divider.
+ * param divided_by_value: Value to be divided
+ * return Nothing
+ */
+void CLOCK_SetRtc1hzClkDiv(uint32_t divided_by_value)
+{
+ if (divided_by_value == 0U) /*!< halt */
+ {
+ PMC->RTCOSC32K |= (1UL << PMC_RTCOSC32K_CLK1HZDIVHALT_SHIFT);
+ }
+ else
+ {
+ PMC->RTCOSC32K =
+ (PMC->RTCOSC32K & ~PMC_RTCOSC32K_CLK1HZDIV_MASK) | PMC_RTCOSC32K_CLK1HZDIV(divided_by_value - 31744U);
+ }
+}
+
+/* Set FRO Clocking */
+/**
+ * brief Initialize the Core clock to given frequency (12, 48 or 96 MHz).
+ * Turns on FRO and uses default CCO, if freq is 12000000, then high speed output is off, else high speed output is
+ * enabled.
+ * param iFreq : Desired frequency (must be one of #CLK_FRO_12MHZ or #CLK_FRO_48MHZ or #CLK_FRO_96MHZ)
+ * return returns success or fail status.
+ */
+status_t CLOCK_SetupFROClocking(uint32_t iFreq)
+{
+ if ((iFreq != 12000000U) && (iFreq != 96000000U))
+ {
+ return kStatus_Fail;
+ }
+ /* Enable Analog Control module */
+ SYSCON->PRESETCTRLCLR[2] = (1UL << SYSCON_PRESETCTRL2_ANALOG_CTRL_RST_SHIFT);
+ SYSCON->AHBCLKCTRLSET[2] = SYSCON_AHBCLKCTRL2_ANALOG_CTRL_MASK;
+ /* Power up the FRO192M */
+ POWER_DisablePD(kPDRUNCFG_PD_FRO192M);
+
+ if (iFreq == 96000000U)
+ {
+ ANACTRL->FRO192M_CTRL |= ANACTRL_FRO192M_CTRL_ENA_96MHZCLK(1);
+ }
+ /* always enable
+ else if (iFreq == 48000000U)
+ {
+ ANACTRL->FRO192M_CTRL |= ANACTRL_FRO192M_CTRL_ENA_48MHZCLK(1);
+ }*/
+ else
+ {
+ ANACTRL->FRO192M_CTRL |= ANACTRL_FRO192M_CTRL_ENA_12MHZCLK(1);
+ }
+ return kStatus_Success;
+}
+
+/* Set the FLASH wait states for the passed frequency */
+/**
+ * brief Set the flash wait states for the input freuqency.
+ * param iFreq: Input frequency
+ * return Nothing
+ */
+typedef struct
+{
+ uint32_t waitstate;
+ uint32_t freqMax;
+} WaitStateInterval_t;
+
+/* clang-format off */
+/* Wait state if frequency is inferior to the one specified */
+static const WaitStateInterval_t IntervalList[] = {
+ {0, 11000000},
+ {1, 22000000},
+ {2, 33000000},
+ {3, 44000000},
+ {4, 55000000},
+ {5, 66000000},
+ {6, 84000000},
+ {7, 104000000},
+ {8, 119000000},
+ {9, 129000000},
+ {10, 144000000},
+ {11, 150000000} /* Maximum allowed frequency (150 MHz) */
+};
+/* clang-format on */
+
+void CLOCK_SetFLASHAccessCyclesForFreq(uint32_t system_freq_hz)
+{
+ /* Flash Controller & FMC internal number of Wait States (minus 1) */
+ uint32_t num_wait_states = 15UL; /* Default to the maximum number of wait states */
+
+ for (size_t cnt = 0; cnt < (sizeof(IntervalList) / sizeof(WaitStateInterval_t)); cnt++)
+ {
+ if (system_freq_hz <= IntervalList[cnt].freqMax)
+ {
+ num_wait_states = IntervalList[cnt].waitstate;
+ break;
+ }
+ }
+
+ FLASH->INT_CLR_STATUS = 0x1F; /* Clear all status flags */
+
+ FLASH->DATAW[0] = (FLASH->DATAW[0] & 0xFFFFFFF0UL) |
+ (num_wait_states & (SYSCON_FMCCR_FLASHTIM_MASK >> SYSCON_FMCCR_FLASHTIM_SHIFT));
+
+ FLASH->CMD = 0x2; /* CMD_SET_READ_MODE */
+
+ /* Wait until the cmd is completed (without error) */
+ while ((FLASH->INT_STATUS & FLASH_INT_STATUS_DONE_MASK) == 0UL)
+ {
+ }
+
+ /* Adjust FMC waiting time cycles (num_wait_states) */
+ SYSCON->FMCCR = (SYSCON->FMCCR & ~SYSCON_FMCCR_FLASHTIM_MASK) |
+ ((num_wait_states << SYSCON_FMCCR_FLASHTIM_SHIFT) & SYSCON_FMCCR_FLASHTIM_MASK);
+}
+
+/* Set EXT OSC Clk */
+/**
+ * brief Initialize the external osc clock to given frequency.
+ * Crystal oscillator with an operating frequency of 12 MHz to 32 MHz.
+ * Option for external clock input (bypass mode) for clock frequencies of up to 25 MHz.
+ * param iFreq : Desired frequency (must be equal to exact rate in Hz)
+ * return returns success or fail status.
+ */
+status_t CLOCK_SetupExtClocking(uint32_t iFreq)
+{
+ if (iFreq > 32000000U)
+ {
+ return kStatus_Fail;
+ }
+ /* Turn on power for crystal 32 MHz */
+ POWER_DisablePD(kPDRUNCFG_PD_XTAL32M);
+ POWER_DisablePD(kPDRUNCFG_PD_LDOXO32M);
+ /* Enable clock_in clock for clock module. */
+ SYSCON->CLOCK_CTRL |= SYSCON_CLOCK_CTRL_CLKIN_ENA_MASK;
+
+ s_Ext_Clk_Freq = iFreq;
+ return kStatus_Success;
+}
+
+/* Set I2S MCLK Clk */
+/**
+ * brief Initialize the I2S MCLK clock to given frequency.
+ * param iFreq : Desired frequency (must be equal to exact rate in Hz)
+ * return returns success or fail status.
+ */
+status_t CLOCK_SetupI2SMClkClocking(uint32_t iFreq)
+{
+ s_I2S_Mclk_Freq = iFreq;
+ return kStatus_Success;
+}
+
+/* Set PLU CLKIN Clk */
+/**
+ * brief Initialize the PLU CLKIN clock to given frequency.
+ * param iFreq : Desired frequency (must be equal to exact rate in Hz)
+ * return returns success or fail status.
+ */
+status_t CLOCK_SetupPLUClkInClocking(uint32_t iFreq)
+{
+ s_PLU_ClkIn_Freq = iFreq;
+ return kStatus_Success;
+}
+
+/* Get CLOCK OUT Clk */
+/*! brief Return Frequency of ClockOut
+ * return Frequency of ClockOut
+ */
+uint32_t CLOCK_GetClockOutClkFreq(void)
+{
+ uint32_t freq = 0U;
+
+ switch (SYSCON->CLKOUTSEL)
+ {
+ case 0U:
+ freq = CLOCK_GetCoreSysClkFreq();
+ break;
+
+ case 1U:
+ freq = CLOCK_GetPll0OutFreq();
+ break;
+
+ case 2U:
+ freq = CLOCK_GetExtClkFreq();
+ break;
+
+ case 3U:
+ freq = CLOCK_GetFroHfFreq();
+ break;
+
+ case 4U:
+ freq = CLOCK_GetFro1MFreq();
+ break;
+
+ case 5U:
+ freq = CLOCK_GetPll1OutFreq();
+ break;
+
+ case 6U:
+ freq = CLOCK_GetOsc32KFreq();
+ break;
+
+ case 7U:
+ freq = 0U;
+ break;
+
+ default:
+ freq = 0U;
+ break;
+ }
+ return freq / ((SYSCON->CLKOUTDIV & 0xffU) + 1U);
+}
+
+/* Get CAN Clk */
+/*! brief Return Frequency of Can Clock
+ * return Frequency of Can.
+ */
+uint32_t CLOCK_GetMCanClkFreq(void)
+{
+ uint32_t freq = 0U;
+
+ switch (SYSCON->CANCLKSEL)
+ {
+ case 0U:
+ freq = CLOCK_GetCoreSysClkFreq() / ((SYSCON->CANCLKDIV & SYSCON_CANCLKDIV_DIV_MASK) + 1U);
+ break;
+ case 1U:
+ freq = CLOCK_GetFro1MFreq();
+ break;
+ case 2U:
+ freq = CLOCK_GetOsc32KFreq();
+ break;
+ case 7U:
+ freq = 0U;
+ break;
+
+ default:
+ freq = 0U;
+ break;
+ }
+
+ return freq;
+}
+
+/* Get ADC Clk */
+/*! brief Return Frequency of Adc Clock
+ * return Frequency of Adc.
+ */
+uint32_t CLOCK_GetAdcClkFreq(void)
+{
+ uint32_t freq = 0U;
+
+ switch (SYSCON->ADCCLKSEL)
+ {
+ case 0U:
+ freq = CLOCK_GetCoreSysClkFreq();
+ break;
+ case 1U:
+ freq = CLOCK_GetPll0OutFreq();
+ break;
+ case 2U:
+ freq = CLOCK_GetFroHfFreq();
+ break;
+ case 7U:
+ freq = 0U;
+ break;
+
+ default:
+ freq = 0U;
+ break;
+ }
+
+ return freq / ((SYSCON->ADCCLKDIV & SYSCON_ADCCLKDIV_DIV_MASK) + 1U);
+}
+
+/* Get USB0 Clk */
+/*! brief Return Frequency of Usb0 Clock
+ * return Frequency of Usb0 Clock.
+ */
+uint32_t CLOCK_GetUsb0ClkFreq(void)
+{
+ uint32_t freq = 0U;
+
+ switch (SYSCON->USB0CLKSEL)
+ {
+ case 0U:
+ freq = CLOCK_GetCoreSysClkFreq();
+ break;
+ case 1U:
+ freq = CLOCK_GetPll0OutFreq();
+ break;
+ case 3U:
+ freq = CLOCK_GetFroHfFreq();
+ break;
+ case 5U:
+ freq = CLOCK_GetPll1OutFreq();
+ break;
+ case 7U:
+ freq = 0U;
+ break;
+
+ default:
+ freq = 0U;
+ break;
+ }
+
+ return freq / ((SYSCON->USB0CLKDIV & 0xffU) + 1U);
+}
+
+/* Get USB1 Clk */
+/*! brief Return Frequency of Usb1 Clock
+ * return Frequency of Usb1 Clock.
+ */
+uint32_t CLOCK_GetUsb1ClkFreq(void)
+{
+ return ((ANACTRL->XO32M_CTRL & ANACTRL_XO32M_CTRL_ENABLE_PLL_USB_OUT_MASK) != 0UL) ? s_Ext_Clk_Freq : 0U;
+}
+
+/* Get MCLK Clk */
+/*! brief Return Frequency of MClk Clock
+ * return Frequency of MClk Clock.
+ */
+uint32_t CLOCK_GetMclkClkFreq(void)
+{
+ uint32_t freq = 0U;
+
+ switch (SYSCON->MCLKCLKSEL)
+ {
+ case 0U:
+ freq = CLOCK_GetFroHfFreq();
+ break;
+ case 1U:
+ freq = CLOCK_GetPll0OutFreq();
+ break;
+ case 7U:
+ freq = 0U;
+ break;
+
+ default:
+ freq = 0U;
+ break;
+ }
+
+ return freq / ((SYSCON->MCLKDIV & 0xffU) + 1U);
+}
+
+/* Get SCTIMER Clk */
+/*! brief Return Frequency of SCTimer Clock
+ * return Frequency of SCTimer Clock.
+ */
+uint32_t CLOCK_GetSctClkFreq(void)
+{
+ uint32_t freq = 0U;
+
+ switch (SYSCON->SCTCLKSEL)
+ {
+ case 0U:
+ freq = CLOCK_GetCoreSysClkFreq();
+ break;
+ case 1U:
+ freq = CLOCK_GetPll0OutFreq();
+ break;
+ case 2U:
+ freq = CLOCK_GetExtClkFreq();
+ break;
+ case 3U:
+ freq = CLOCK_GetFroHfFreq();
+ break;
+ case 5U:
+ freq = CLOCK_GetI2SMClkFreq();
+ break;
+ case 7U:
+ freq = 0U;
+ break;
+
+ default:
+ freq = 0U;
+ break;
+ }
+
+ return freq / ((SYSCON->SCTCLKDIV & 0xffU) + 1U);
+}
+
+/* Get FRO 12M Clk */
+/*! brief Return Frequency of FRO 12MHz
+ * return Frequency of FRO 12MHz
+ */
+uint32_t CLOCK_GetFro12MFreq(void)
+{
+ return ((ANACTRL->FRO192M_CTRL & ANACTRL_FRO192M_CTRL_ENA_12MHZCLK_MASK) != 0UL) ? 12000000U : 0U;
+}
+
+/* Get FRO 1M Clk */
+/*! brief Return Frequency of FRO 1MHz
+ * return Frequency of FRO 1MHz
+ */
+uint32_t CLOCK_GetFro1MFreq(void)
+{
+ return ((SYSCON->CLOCK_CTRL & SYSCON_CLOCK_CTRL_FRO1MHZ_CLK_ENA_MASK) != 0UL) ? 1000000U : 0U;
+}
+
+/* Get EXT OSC Clk */
+/*! brief Return Frequency of External Clock
+ * return Frequency of External Clock. If no external clock is used returns 0.
+ */
+uint32_t CLOCK_GetExtClkFreq(void)
+{
+ return ((ANACTRL->XO32M_CTRL & ANACTRL_XO32M_CTRL_ENABLE_SYSTEM_CLK_OUT_MASK) != 0UL) ? s_Ext_Clk_Freq : 0U;
+}
+
+/* Get WATCH DOG Clk */
+/*! brief Return Frequency of Watchdog
+ * return Frequency of Watchdog
+ */
+uint32_t CLOCK_GetWdtClkFreq(void)
+{
+ return CLOCK_GetFro1MFreq() / ((SYSCON->WDTCLKDIV & SYSCON_WDTCLKDIV_DIV_MASK) + 1U);
+}
+
+/* Get HF FRO Clk */
+/*! brief Return Frequency of High-Freq output of FRO
+ * return Frequency of High-Freq output of FRO
+ */
+uint32_t CLOCK_GetFroHfFreq(void)
+{
+ return ((ANACTRL->FRO192M_CTRL & ANACTRL_FRO192M_CTRL_ENA_96MHZCLK_MASK) != 0UL) ? 96000000U : 0U;
+}
+
+/* Get SYSTEM PLL Clk */
+/*! brief Return Frequency of PLL
+ * return Frequency of PLL
+ */
+uint32_t CLOCK_GetPll0OutFreq(void)
+{
+ return s_Pll0_Freq;
+}
+
+/* Get USB PLL Clk */
+/*! brief Return Frequency of USB PLL
+ * return Frequency of PLL
+ */
+uint32_t CLOCK_GetPll1OutFreq(void)
+{
+ return s_Pll1_Freq;
+}
+
+/* Get RTC OSC Clk */
+/*! brief Return Frequency of 32kHz osc
+ * return Frequency of 32kHz osc
+ */
+uint32_t CLOCK_GetOsc32KFreq(void)
+{
+ return ((0UL == (PMC->PDRUNCFG0 & PMC_PDRUNCFG0_PDEN_FRO32K_MASK)) &&
+ (0UL == (PMC->RTCOSC32K & PMC_RTCOSC32K_SEL_MASK))) ?
+ CLK_RTC_32K_CLK :
+ ((0UL == (PMC->PDRUNCFG0 & PMC_PDRUNCFG0_PDEN_XTAL32K_MASK)) &&
+ ((PMC->RTCOSC32K & PMC_RTCOSC32K_SEL_MASK) != 0UL)) ?
+ CLK_RTC_32K_CLK :
+ 0UL;
+}
+
+/* Get MAIN Clk */
+/*! brief Return Frequency of Core System
+ * return Frequency of Core System
+ */
+uint32_t CLOCK_GetCoreSysClkFreq(void)
+{
+ uint32_t freq = 0U;
+
+ switch (SYSCON->MAINCLKSELB)
+ {
+ case 0U:
+ if (SYSCON->MAINCLKSELA == 0U)
+ {
+ freq = CLOCK_GetFro12MFreq();
+ }
+ else if (SYSCON->MAINCLKSELA == 1U)
+ {
+ freq = CLOCK_GetExtClkFreq();
+ }
+ else if (SYSCON->MAINCLKSELA == 2U)
+ {
+ freq = CLOCK_GetFro1MFreq();
+ }
+ else if (SYSCON->MAINCLKSELA == 3U)
+ {
+ freq = CLOCK_GetFroHfFreq();
+ }
+ else
+ {
+ /* Added comments to avoid the violation of MISRA C-2012 rule 15.7 */
+ }
+ break;
+ case 1U:
+ freq = CLOCK_GetPll0OutFreq();
+ break;
+ case 2U:
+ freq = CLOCK_GetPll1OutFreq();
+ break;
+
+ case 3U:
+ freq = CLOCK_GetOsc32KFreq();
+ break;
+
+ default:
+ freq = 0U;
+ break;
+ }
+
+ return freq;
+}
+
+/* Get I2S MCLK Clk */
+/*! brief Return Frequency of I2S MCLK Clock
+ * return Frequency of I2S MCLK Clock
+ */
+uint32_t CLOCK_GetI2SMClkFreq(void)
+{
+ return s_I2S_Mclk_Freq;
+}
+
+/* Get PLU CLKIN Clk */
+/*! brief Return Frequency of PLU CLKIN Clock
+ * return Frequency of PLU CLKIN Clock
+ */
+uint32_t CLOCK_GetPLUClkInFreq(void)
+{
+ return s_PLU_ClkIn_Freq;
+}
+
+/* Get FLEXCOMM input clock */
+/*! brief Return Frequency of flexcomm input clock
+ * param id : flexcomm instance id
+ * return Frequency value
+ */
+uint32_t CLOCK_GetFlexCommInputClock(uint32_t id)
+{
+ uint32_t freq = 0U;
+
+ switch (SYSCON->FCCLKSELX[id])
+ {
+ case 0U:
+ freq = CLOCK_GetCoreSysClkFreq();
+ break;
+ case 1U:
+ freq = CLOCK_GetPll0OutFreq() / ((SYSCON->PLL0CLKDIV & 0xffU) + 1U);
+ break;
+ case 2U:
+ freq = CLOCK_GetFro12MFreq();
+ break;
+ case 3U:
+ freq = CLOCK_GetFroHfFreq() / ((SYSCON->FROHFDIV & 0xffU) + 1U);
+ break;
+ case 4U:
+ freq = CLOCK_GetFro1MFreq();
+ break;
+ case 5U:
+ freq = CLOCK_GetI2SMClkFreq();
+ break;
+ case 6U:
+ freq = CLOCK_GetOsc32KFreq();
+ break;
+ case 7U:
+ freq = 0U;
+ break;
+
+ default:
+ freq = 0U;
+ break;
+ }
+
+ return freq;
+}
+
+/* Get FLEXCOMM Clk */
+uint32_t CLOCK_GetFlexCommClkFreq(uint32_t id)
+{
+ uint32_t freq = 0U;
+
+ freq = CLOCK_GetFlexCommInputClock(id);
+ return freq / (1UL + (SYSCON->FLEXFRGXCTRL[id] & SYSCON_FLEXFRG0CTRL_MULT_MASK) /
+ ((SYSCON->FLEXFRGXCTRL[id] & SYSCON_FLEXFRG0CTRL_DIV_MASK) + 1UL));
+}
+
+/* Get HS_LPSI Clk */
+uint32_t CLOCK_GetHsLspiClkFreq(void)
+{
+ uint32_t freq = 0U;
+
+ switch (SYSCON->HSLSPICLKSEL)
+ {
+ case 0U:
+ freq = CLOCK_GetCoreSysClkFreq();
+ break;
+ case 1U:
+ freq = CLOCK_GetPll0OutFreq() / ((SYSCON->PLL0CLKDIV & 0xffU) + 1U);
+ break;
+ case 2U:
+ freq = CLOCK_GetFro12MFreq();
+ break;
+ case 3U:
+ freq = CLOCK_GetFroHfFreq() / ((SYSCON->FROHFDIV & 0xffU) + 1U);
+ break;
+ case 4U:
+ freq = CLOCK_GetFro1MFreq();
+ break;
+ case 6U:
+ freq = CLOCK_GetOsc32KFreq();
+ break;
+ case 7U:
+ freq = 0U;
+ break;
+
+ default:
+ freq = 0U;
+ break;
+ }
+
+ return freq;
+}
+
+/* Get CTimer Clk */
+/*! brief Return Frequency of CTimer functional Clock
+ * return Frequency of CTimer functional Clock
+ */
+uint32_t CLOCK_GetCTimerClkFreq(uint32_t id)
+{
+ uint32_t freq = 0U;
+
+ switch (SYSCON->CTIMERCLKSELX[id])
+ {
+ case 0U:
+ freq = CLOCK_GetCoreSysClkFreq();
+ break;
+ case 1U:
+ freq = CLOCK_GetPll0OutFreq();
+ break;
+ case 3U:
+ freq = CLOCK_GetFroHfFreq();
+ break;
+ case 4U:
+ freq = CLOCK_GetFro1MFreq();
+ break;
+ case 5U:
+ freq = CLOCK_GetI2SMClkFreq();
+ break;
+ case 6U:
+ freq = CLOCK_GetOsc32KFreq();
+ break;
+ case 7U:
+ freq = 0U;
+ break;
+
+ default:
+ freq = 0U;
+ break;
+ }
+
+ return freq;
+}
+
+/* Get Systick Clk */
+/*! brief Return Frequency of SystickClock
+ * return Frequency of Systick Clock
+ */
+uint32_t CLOCK_GetSystickClkFreq(uint32_t id)
+{
+ uint32_t freq = 0U;
+
+ switch (SYSCON->SYSTICKCLKSELX[id])
+ {
+ case 0U:
+ /*Niobe4mini just has one SYSTICKSEL and SYSTICKDIV register, Fix coverity problem in this way temporarily
+ */
+ freq = CLOCK_GetCoreSysClkFreq() / (((SYSCON->SYSTICKCLKDIV0) & 0xffU) + 1U);
+ break;
+ case 1U:
+ freq = CLOCK_GetFro1MFreq();
+ break;
+ case 2U:
+ freq = CLOCK_GetOsc32KFreq();
+ break;
+ case 7U:
+ freq = 0U;
+ break;
+
+ default:
+ freq = 0U;
+ break;
+ }
+
+ return freq;
+}
+
+/* Set FlexComm Clock */
+/**
+ * brief Set the flexcomm output frequency.
+ * param id : flexcomm instance id
+ * freq : output frequency
+ * return 0 : the frequency range is out of range.
+ * 1 : switch successfully.
+ */
+uint32_t CLOCK_SetFlexCommClock(uint32_t id, uint32_t freq)
+{
+ uint32_t input = CLOCK_GetFlexCommClkFreq(id);
+ uint32_t mul;
+
+ if ((freq > 48000000UL) || (freq > input) || (input / freq >= 2UL))
+ {
+ /* FRG output frequency should be less than equal to 48MHz */
+ return 0UL;
+ }
+ else
+ {
+ mul = (uint32_t)((((uint64_t)input - freq) * 256ULL) / ((uint64_t)freq));
+ SYSCON->FLEXFRGXCTRL[id] = (mul << 8U) | 0xFFU;
+ return 1UL;
+ }
+}
+
+/* Get IP Clk */
+/*! brief Return Frequency of selected clock
+ * return Frequency of selected clock
+ */
+uint32_t CLOCK_GetFreq(clock_name_t clockName)
+{
+ uint32_t freq;
+ switch (clockName)
+ {
+ case kCLOCK_CoreSysClk:
+ freq = CLOCK_GetCoreSysClkFreq();
+ break;
+ case kCLOCK_BusClk:
+ freq = CLOCK_GetCoreSysClkFreq() / ((SYSCON->AHBCLKDIV & 0xffU) + 1U);
+ break;
+ case kCLOCK_ClockOut:
+ freq = CLOCK_GetClockOutClkFreq();
+ break;
+ case kCLOCK_Pll1Out:
+ freq = CLOCK_GetPll1OutFreq();
+ break;
+ case kCLOCK_Mclk:
+ freq = CLOCK_GetMclkClkFreq();
+ break;
+ case kCLOCK_FroHf:
+ freq = CLOCK_GetFroHfFreq();
+ break;
+ case kCLOCK_Fro12M:
+ freq = CLOCK_GetFro12MFreq();
+ break;
+ case kCLOCK_Fro1M:
+ freq = CLOCK_GetFro1MFreq();
+ break;
+ case kCLOCK_ExtClk:
+ freq = CLOCK_GetExtClkFreq();
+ break;
+ case kCLOCK_Pll0Out:
+ freq = CLOCK_GetPll0OutFreq();
+ break;
+ case kCLOCK_FlexI2S:
+ freq = CLOCK_GetI2SMClkFreq();
+ break;
+ default:
+ freq = 0U;
+ break;
+ }
+ return freq;
+}
+
+/* Find SELP, SELI, and SELR values for raw M value, max M = MVALMAX */
+static void pllFindSel(uint32_t M, uint32_t *pSelP, uint32_t *pSelI, uint32_t *pSelR)
+{
+ uint32_t seli, selp;
+ /* bandwidth: compute selP from Multiplier */
+ if ((SYSCON->PLL0SSCG1 & SYSCON_PLL0SSCG1_MDIV_EXT_MASK) != 0UL) /* normal mode */
+ {
+ selp = (M >> 2U) + 1U;
+ if (selp >= 31U)
+ {
+ selp = 31U;
+ }
+ *pSelP = selp;
+
+ if (M >= 8000UL)
+ {
+ seli = 1UL;
+ }
+ else if (M >= 122UL)
+ {
+ seli = (uint32_t)(8000UL / M); /*floor(8000/M) */
+ }
+ else
+ {
+ seli = 2UL * ((uint32_t)(M / 4UL)) + 3UL; /* 2*floor(M/4) + 3 */
+ }
+
+ if (seli >= 63UL)
+ {
+ seli = 63UL;
+ }
+ *pSelI = seli;
+
+ *pSelR = 0UL;
+ }
+ else
+ {
+ /* Note: If the spread spectrum mode, choose N to ensure 3 MHz < Fin/N < 5 MHz */
+ *pSelP = 3U;
+ *pSelI = 4U;
+ *pSelR = 4U;
+ }
+}
+
+/* Get predivider (N) from PLL0 NDEC setting */
+static uint32_t findPll0PreDiv(void)
+{
+ uint32_t preDiv = 1UL;
+
+ /* Direct input is not used? */
+ if ((SYSCON->PLL0CTRL & SYSCON_PLL0CTRL_BYPASSPREDIV_MASK) == 0UL)
+ {
+ preDiv = SYSCON->PLL0NDEC & SYSCON_PLL0NDEC_NDIV_MASK;
+ if (preDiv == 0UL)
+ {
+ preDiv = 1UL;
+ }
+ }
+ return preDiv;
+}
+
+/* Get predivider (N) from PLL1 NDEC setting */
+static uint32_t findPll1PreDiv(void)
+{
+ uint32_t preDiv = 1UL;
+
+ /* Direct input is not used? */
+ if ((SYSCON->PLL1CTRL & SYSCON_PLL1CTRL_BYPASSPREDIV_MASK) == 0UL)
+ {
+ preDiv = SYSCON->PLL1NDEC & SYSCON_PLL1NDEC_NDIV_MASK;
+ if (preDiv == 0UL)
+ {
+ preDiv = 1UL;
+ }
+ }
+ return preDiv;
+}
+
+/* Get postdivider (P) from PLL0 PDEC setting */
+static uint32_t findPll0PostDiv(void)
+{
+ uint32_t postDiv = 1UL;
+
+ if ((SYSCON->PLL0CTRL & SYSCON_PLL0CTRL_BYPASSPOSTDIV_MASK) == 0UL)
+ {
+ if ((SYSCON->PLL0CTRL & SYSCON_PLL0CTRL_BYPASSPOSTDIV2_MASK) != 0UL)
+ {
+ postDiv = SYSCON->PLL0PDEC & SYSCON_PLL0PDEC_PDIV_MASK;
+ }
+ else
+ {
+ postDiv = 2UL * (SYSCON->PLL0PDEC & SYSCON_PLL0PDEC_PDIV_MASK);
+ }
+ if (postDiv == 0UL)
+ {
+ postDiv = 2UL;
+ }
+ }
+ return postDiv;
+}
+
+/* Get postdivider (P) from PLL1 PDEC setting. */
+static uint32_t findPll1PostDiv(void)
+{
+ uint32_t postDiv = 1UL;
+
+ if ((SYSCON->PLL1CTRL & SYSCON_PLL1CTRL_BYPASSPOSTDIV_MASK) == 0UL)
+ {
+ if ((SYSCON->PLL1CTRL & SYSCON_PLL1CTRL_BYPASSPOSTDIV2_MASK) != 0UL)
+ {
+ postDiv = SYSCON->PLL1PDEC & SYSCON_PLL1PDEC_PDIV_MASK;
+ }
+ else
+ {
+ postDiv = 2UL * (SYSCON->PLL1PDEC & SYSCON_PLL1PDEC_PDIV_MASK);
+ }
+ if (postDiv == 0UL)
+ {
+ postDiv = 2UL;
+ }
+ }
+
+ return postDiv;
+}
+
+/* Get multiplier (M) from PLL0 SSCG and SEL_EXT settings */
+static float findPll0MMult(void)
+{
+ float mMult = 1.0F;
+ float mMult_fract;
+ uint32_t mMult_int;
+
+ if ((SYSCON->PLL0SSCG1 & SYSCON_PLL0SSCG1_SEL_EXT_MASK) != 0UL)
+ {
+ mMult =
+ (float)(uint32_t)((SYSCON->PLL0SSCG1 & SYSCON_PLL0SSCG1_MDIV_EXT_MASK) >> SYSCON_PLL0SSCG1_MDIV_EXT_SHIFT);
+ }
+ else
+ {
+ mMult_int = ((SYSCON->PLL0SSCG1 & SYSCON_PLL0SSCG1_MD_MBS_MASK) << 7U);
+ mMult_int = mMult_int | ((SYSCON->PLL0SSCG0) >> PLL0_SSCG_MD_INT_P);
+ mMult_fract = ((float)(uint32_t)((SYSCON->PLL0SSCG0) & PLL0_SSCG_MD_FRACT_M) /
+ (float)(uint32_t)(1UL << PLL0_SSCG_MD_INT_P));
+ mMult = (float)mMult_int + mMult_fract;
+ }
+ if (mMult == 0.0F)
+ {
+ mMult = 1.0F;
+ }
+ return mMult;
+}
+
+/* Get multiplier (M) from PLL1 MDEC. */
+static uint32_t findPll1MMult(void)
+{
+ uint32_t mMult = 1UL;
+
+ mMult = SYSCON->PLL1MDEC & SYSCON_PLL1MDEC_MDIV_MASK;
+
+ if (mMult == 0UL)
+ {
+ mMult = 1UL;
+ }
+
+ return mMult;
+}
+
+/* Find greatest common divisor between m and n */
+static uint32_t FindGreatestCommonDivisor(uint32_t m, uint32_t n)
+{
+ uint32_t tmp;
+
+ while (n != 0U)
+ {
+ tmp = n;
+ n = m % n;
+ m = tmp;
+ }
+
+ return m;
+}
+
+/*
+ * Set PLL0 output based on desired output rate.
+ * In this function, the it calculates the PLL0 setting for output frequency from input clock
+ * frequency. The calculation would cost a few time. So it is not recommaned to use it frequently.
+ * the "pllctrl", "pllndec", "pllpdec", "pllmdec" would updated in this function.
+ */
+static pll_error_t CLOCK_GetPll0ConfigInternal(uint32_t finHz, uint32_t foutHz, pll_setup_t *pSetup, bool useSS)
+{
+ uint32_t nDivOutHz, fccoHz;
+ uint32_t pllPreDivider, pllMultiplier, pllPostDivider;
+ uint32_t pllDirectInput, pllDirectOutput;
+ uint32_t pllSelP, pllSelI, pllSelR, uplimoff;
+
+ /* Baseline parameters (no input or output dividers) */
+ pllPreDivider = 1U; /* 1 implies pre-divider will be disabled */
+ pllPostDivider = 1U; /* 1 implies post-divider will be disabled */
+ pllDirectOutput = 1U;
+
+ /* Verify output rate parameter */
+ if (foutHz > PLL_MAX_CCO_FREQ_MHZ)
+ {
+ /* Maximum PLL output with post divider=1 cannot go above this frequency */
+ return kStatus_PLL_OutputTooHigh;
+ }
+ if (foutHz < (PLL_MIN_CCO_FREQ_MHZ / (PVALMAX << 1U)))
+ {
+ /* Minmum PLL output with maximum post divider cannot go below this frequency */
+ return kStatus_PLL_OutputTooLow;
+ }
+
+ /* If using SS mode, input clock needs to be between 3MHz and 20MHz */
+ if (useSS)
+ {
+ /* Verify input rate parameter */
+ if (finHz < PLL_MIN_IN_SSMODE)
+ {
+ /* Input clock into the PLL cannot be lower than this */
+ return kStatus_PLL_InputTooLow;
+ }
+ /* PLL input in SS mode must be under 20MHz */
+ if (finHz > (PLL_MAX_IN_SSMODE * NVALMAX))
+ {
+ return kStatus_PLL_InputTooHigh;
+ }
+ }
+ else
+ {
+ /* Verify input rate parameter */
+ if (finHz < PLL_LOWER_IN_LIMIT)
+ {
+ /* Input clock into the PLL cannot be lower than this */
+ return kStatus_PLL_InputTooLow;
+ }
+ if (finHz > PLL_HIGHER_IN_LIMIT)
+ {
+ /* Input clock into the PLL cannot be higher than this */
+ return kStatus_PLL_InputTooHigh;
+ }
+ }
+
+ /* Find the optimal CCO frequency for the output and input that
+ will keep it inside the PLL CCO range. This may require
+ tweaking the post-divider for the PLL. */
+ fccoHz = foutHz;
+ while (fccoHz < PLL_MIN_CCO_FREQ_MHZ)
+ {
+ /* CCO output is less than minimum CCO range, so the CCO output
+ needs to be bumped up and the post-divider is used to bring
+ the PLL output back down. */
+ pllPostDivider++;
+ if (pllPostDivider > PVALMAX)
+ {
+ return kStatus_PLL_OutsideIntLimit;
+ }
+
+ /* Target CCO goes up, PLL output goes down */
+ /* divide-by-2 divider in the post-divider is always work*/
+ fccoHz = foutHz * (pllPostDivider * 2U);
+ pllDirectOutput = 0U;
+ }
+
+ /* Determine if a pre-divider is needed to get the best frequency */
+ if ((finHz > PLL_LOWER_IN_LIMIT) && (fccoHz >= finHz) && (useSS == false))
+ {
+ uint32_t a = FindGreatestCommonDivisor(fccoHz, finHz);
+
+ if (a > PLL_LOWER_IN_LIMIT)
+ {
+ a = finHz / a;
+ if ((a != 0U) && (a < PLL_MAX_N_DIV))
+ {
+ pllPreDivider = a;
+ }
+ }
+ }
+
+ /* Bypass pre-divider hardware if pre-divider is 1 */
+ if (pllPreDivider > 1U)
+ {
+ pllDirectInput = 0U;
+ }
+ else
+ {
+ pllDirectInput = 1U;
+ }
+
+ /* Determine PLL multipler */
+ nDivOutHz = (finHz / pllPreDivider);
+ pllMultiplier = (fccoHz / nDivOutHz);
+
+ /* Find optimal values for filter */
+ if (useSS == false)
+ {
+ /* Will bumping up M by 1 get us closer to the desired CCO frequency? */
+ if ((nDivOutHz * ((pllMultiplier * 2U) + 1U)) < (fccoHz * 2U))
+ {
+ pllMultiplier++;
+ }
+
+ /* Setup filtering */
+ pllFindSel(pllMultiplier, &pllSelP, &pllSelI, &pllSelR);
+ uplimoff = 0U;
+
+ /* Get encoded value for M (mult) and use manual filter, disable SS mode */
+ pSetup->pllsscg[1] =
+ (uint32_t)((PLL_SSCG1_MDEC_VAL_SET(pllMultiplier)) | (1UL << SYSCON_PLL0SSCG1_SEL_EXT_SHIFT));
+ }
+ else
+ {
+ uint64_t fc;
+
+ /* Filtering will be handled by SSC */
+ pllSelR = 0UL;
+ pllSelI = 0UL;
+ pllSelP = 0UL;
+ uplimoff = 1U;
+
+ /* The PLL multiplier will get very close and slightly under the
+ desired target frequency. A small fractional component can be
+ added to fine tune the frequency upwards to the target. */
+ fc = ((uint64_t)(uint32_t)(fccoHz % nDivOutHz) << 25UL) / nDivOutHz;
+
+ /* Set multiplier */
+ pSetup->pllsscg[0] = (uint32_t)(PLL0_SSCG_MD_INT_SET(pllMultiplier) | PLL0_SSCG_MD_FRACT_SET((uint32_t)fc));
+ pSetup->pllsscg[1] = (uint32_t)(PLL0_SSCG_MD_INT_SET(pllMultiplier) >> 32U);
+ }
+
+ /* Get encoded values for N (prediv) and P (postdiv) */
+ pSetup->pllndec = PLL_NDEC_VAL_SET(pllPreDivider);
+ pSetup->pllpdec = PLL_PDEC_VAL_SET(pllPostDivider);
+
+ /* PLL control */
+ pSetup->pllctrl = (pllSelR << SYSCON_PLL0CTRL_SELR_SHIFT) | /* Filter coefficient */
+ (pllSelI << SYSCON_PLL0CTRL_SELI_SHIFT) | /* Filter coefficient */
+ (pllSelP << SYSCON_PLL0CTRL_SELP_SHIFT) | /* Filter coefficient */
+ (0UL << SYSCON_PLL0CTRL_BYPASSPLL_SHIFT) | /* PLL bypass mode disabled */
+ (uplimoff << SYSCON_PLL0CTRL_LIMUPOFF_SHIFT) | /* SS/fractional mode disabled */
+ (pllDirectInput << SYSCON_PLL0CTRL_BYPASSPREDIV_SHIFT) | /* Bypass pre-divider? */
+ (pllDirectOutput << SYSCON_PLL0CTRL_BYPASSPOSTDIV_SHIFT) | /* Bypass post-divider? */
+ (1UL << SYSCON_PLL0CTRL_CLKEN_SHIFT); /* Ensure the PLL clock output */
+
+ return kStatus_PLL_Success;
+}
+
+#if (defined(CLOCK_USR_CFG_PLL_CONFIG_CACHE_COUNT) && CLOCK_USR_CFG_PLL_CONFIG_CACHE_COUNT)
+/* Alloct the static buffer for cache. */
+static pll_setup_t s_PllSetupCacheStruct[CLOCK_USR_CFG_PLL_CONFIG_CACHE_COUNT];
+static uint32_t s_FinHzCache[CLOCK_USR_CFG_PLL_CONFIG_CACHE_COUNT] = {0};
+static uint32_t s_FoutHzCache[CLOCK_USR_CFG_PLL_CONFIG_CACHE_COUNT] = {0};
+static bool s_UseSSCache[CLOCK_USR_CFG_PLL_CONFIG_CACHE_COUNT] = {false};
+static uint32_t s_PllSetupCacheIdx = 0U;
+#endif /* CLOCK_USR_CFG_PLL_CONFIG_CACHE_COUNT */
+
+/*
+ * Calculate the PLL setting values from input clock freq to output freq.
+ */
+static pll_error_t CLOCK_GetPll0Config(uint32_t finHz, uint32_t foutHz, pll_setup_t *pSetup, bool useSS)
+{
+ pll_error_t retErr;
+#if (defined(CLOCK_USR_CFG_PLL_CONFIG_CACHE_COUNT) && CLOCK_USR_CFG_PLL_CONFIG_CACHE_COUNT)
+ uint32_t i;
+
+ for (i = 0U; i < CLOCK_USR_CFG_PLL_CONFIG_CACHE_COUNT; i++)
+ {
+ if ((finHz == s_FinHzCache[i]) && (foutHz == s_FoutHzCache[i]) && (useSS == s_UseSSCache[i]))
+ {
+ /* Hit the target in cache buffer. */
+ pSetup->pllctrl = s_PllSetupCacheStruct[i].pllctrl;
+ pSetup->pllndec = s_PllSetupCacheStruct[i].pllndec;
+ pSetup->pllpdec = s_PllSetupCacheStruct[i].pllpdec;
+ pSetup->pllsscg[0] = s_PllSetupCacheStruct[i].pllsscg[0];
+ pSetup->pllsscg[1] = s_PllSetupCacheStruct[i].pllsscg[1];
+ retErr = kStatus_PLL_Success;
+ break;
+ }
+ }
+
+ if (i < CLOCK_USR_CFG_PLL_CONFIG_CACHE_COUNT)
+ {
+ return retErr;
+ }
+#endif /* CLOCK_USR_CFG_PLL_CONFIG_CACHE_COUNT */
+
+ retErr = CLOCK_GetPll0ConfigInternal(finHz, foutHz, pSetup, useSS);
+
+#if (defined(CLOCK_USR_CFG_PLL_CONFIG_CACHE_COUNT) && CLOCK_USR_CFG_PLL_CONFIG_CACHE_COUNT)
+ /* Cache the most recent calulation result into buffer. */
+ s_FinHzCache[s_PllSetupCacheIdx] = finHz;
+ s_FoutHzCache[s_PllSetupCacheIdx] = foutHz;
+ s_UseSSCache[s_PllSetupCacheIdx] = useSS;
+
+ s_PllSetupCacheStruct[s_PllSetupCacheIdx].pllctrl = pSetup->pllctrl;
+ s_PllSetupCacheStruct[s_PllSetupCacheIdx].pllndec = pSetup->pllndec;
+ s_PllSetupCacheStruct[s_PllSetupCacheIdx].pllpdec = pSetup->pllpdec;
+ s_PllSetupCacheStruct[s_PllSetupCacheIdx].pllsscg[0] = pSetup->pllsscg[0];
+ s_PllSetupCacheStruct[s_PllSetupCacheIdx].pllsscg[1] = pSetup->pllsscg[1];
+ /* Update the index for next available buffer. */
+ s_PllSetupCacheIdx = (s_PllSetupCacheIdx + 1U) % CLOCK_USR_CFG_PLL_CONFIG_CACHE_COUNT;
+#endif /* CLOCK_USR_CFG_PLL_CONFIG_CACHE_COUNT */
+
+ return retErr;
+}
+
+/* Update local PLL rate variable */
+static void CLOCK_GetPLL0OutFromSetupUpdate(pll_setup_t *pSetup)
+{
+ s_Pll0_Freq = CLOCK_GetPLL0OutFromSetup(pSetup);
+}
+
+/* Update local PLL1 rate variable */
+static void CLOCK_GetPLL1OutFromSetupUpdate(pll_setup_t *pSetup)
+{
+ s_Pll1_Freq = CLOCK_GetPLL1OutFromSetup(pSetup);
+}
+
+/* Return System PLL input clock rate */
+/*! brief Return PLL0 input clock rate
+ * return PLL0 input clock rate
+ */
+uint32_t CLOCK_GetPLL0InClockRate(void)
+{
+ uint32_t clkRate = 0U;
+
+ switch ((SYSCON->PLL0CLKSEL & SYSCON_PLL0CLKSEL_SEL_MASK))
+ {
+ case 0x00U:
+ clkRate = CLK_FRO_12MHZ;
+ break;
+
+ case 0x01U:
+ clkRate = CLOCK_GetExtClkFreq();
+ break;
+
+ case 0x02U:
+ clkRate = CLOCK_GetFro1MFreq();
+ break;
+
+ case 0x03U:
+ clkRate = CLOCK_GetOsc32KFreq();
+ break;
+
+ default:
+ clkRate = 0U;
+ break;
+ }
+
+ return clkRate;
+}
+
+/* Return PLL1 input clock rate */
+uint32_t CLOCK_GetPLL1InClockRate(void)
+{
+ uint32_t clkRate = 0U;
+
+ switch ((SYSCON->PLL1CLKSEL & SYSCON_PLL1CLKSEL_SEL_MASK))
+ {
+ case 0x00U:
+ clkRate = CLK_FRO_12MHZ;
+ break;
+
+ case 0x01U:
+ clkRate = CLOCK_GetExtClkFreq();
+ break;
+
+ case 0x02U:
+ clkRate = CLOCK_GetFro1MFreq();
+ break;
+
+ case 0x03U:
+ clkRate = CLOCK_GetOsc32KFreq();
+ break;
+
+ default:
+ clkRate = 0U;
+ break;
+ }
+
+ return clkRate;
+}
+
+/* Return PLL0 output clock rate from setup structure */
+/*! brief Return PLL0 output clock rate from setup structure
+ * param pSetup : Pointer to a PLL setup structure
+ * return PLL0 output clock rate the setup structure will generate
+ */
+uint32_t CLOCK_GetPLL0OutFromSetup(pll_setup_t *pSetup)
+{
+ uint32_t clkRate = 0;
+ uint32_t prediv, postdiv;
+ float workRate = 0.0F;
+
+ /* Get the input clock frequency of PLL. */
+ clkRate = CLOCK_GetPLL0InClockRate();
+
+ if (((pSetup->pllctrl & SYSCON_PLL0CTRL_BYPASSPLL_MASK) == 0UL) &&
+ ((pSetup->pllctrl & SYSCON_PLL0CTRL_CLKEN_MASK) != 0UL) &&
+ ((PMC->PDRUNCFG0 & PMC_PDRUNCFG0_PDEN_PLL0_MASK) == 0UL) &&
+ ((PMC->PDRUNCFG0 & PMC_PDRUNCFG0_PDEN_PLL0_SSCG_MASK) == 0UL))
+ {
+ prediv = findPll0PreDiv();
+ postdiv = findPll0PostDiv();
+ /* Adjust input clock */
+ clkRate = clkRate / prediv;
+ /* MDEC used for rate */
+ workRate = (float)clkRate * (float)findPll0MMult();
+ workRate /= (float)postdiv;
+ }
+
+ return (uint32_t)workRate;
+}
+
+/* Return PLL1 output clock rate from setup structure */
+/*! brief Return PLL1 output clock rate from setup structure
+ * param pSetup : Pointer to a PLL setup structure
+ * return PLL0 output clock rate the setup structure will generate
+ */
+uint32_t CLOCK_GetPLL1OutFromSetup(pll_setup_t *pSetup)
+{
+ uint32_t clkRate = 0;
+ uint32_t prediv, postdiv;
+ uint32_t workRate = 0UL;
+
+ /* Get the input clock frequency of PLL. */
+ clkRate = CLOCK_GetPLL1InClockRate();
+
+ if (((pSetup->pllctrl & SYSCON_PLL1CTRL_BYPASSPLL_MASK) == 0UL) &&
+ ((pSetup->pllctrl & SYSCON_PLL1CTRL_CLKEN_MASK) != 0UL) &&
+ ((PMC->PDRUNCFG0 & PMC_PDRUNCFG0_PDEN_PLL1_MASK) == 0UL))
+ {
+ prediv = findPll1PreDiv();
+ postdiv = findPll1PostDiv();
+ /* Adjust input clock */
+ clkRate = clkRate / prediv;
+ /* MDEC used for rate */
+ workRate = clkRate * findPll1MMult();
+ workRate /= postdiv;
+ }
+
+ return workRate;
+}
+
+/* Set the current PLL0 Rate */
+/*! brief Store the current PLL rate
+ * param rate: Current rate of the PLL
+ * return Nothing
+ **/
+void CLOCK_SetStoredPLL0ClockRate(uint32_t rate)
+{
+ s_Pll0_Freq = rate;
+}
+
+/* Return PLL0 output clock rate */
+/*! brief Return PLL0 output clock rate
+ * param recompute : Forces a PLL rate recomputation if true
+ * return PLL0 output clock rate
+ * note The PLL rate is cached in the driver in a variable as
+ * the rate computation function can take some time to perform. It
+ * is recommended to use 'false' with the 'recompute' parameter.
+ */
+uint32_t CLOCK_GetPLL0OutClockRate(bool recompute)
+{
+ pll_setup_t Setup;
+ uint32_t rate;
+
+ if ((recompute) || (s_Pll0_Freq == 0U))
+ {
+ Setup.pllctrl = SYSCON->PLL0CTRL;
+ Setup.pllndec = SYSCON->PLL0NDEC;
+ Setup.pllpdec = SYSCON->PLL0PDEC;
+ Setup.pllsscg[0] = SYSCON->PLL0SSCG0;
+ Setup.pllsscg[1] = SYSCON->PLL0SSCG1;
+
+ CLOCK_GetPLL0OutFromSetupUpdate(&Setup);
+ }
+
+ rate = s_Pll0_Freq;
+
+ return rate;
+}
+
+/*! brief Return PLL1 output clock rate
+ * param recompute : Forces a PLL rate recomputation if true
+ * return PLL1 output clock rate
+ * note The PLL rate is cached in the driver in a variable as
+ * the rate computation function can take some time to perform. It
+ * is recommended to use 'false' with the 'recompute' parameter.
+ */
+uint32_t CLOCK_GetPLL1OutClockRate(bool recompute)
+{
+ pll_setup_t Setup;
+ uint32_t rate;
+
+ if ((recompute) || (s_Pll1_Freq == 0U))
+ {
+ Setup.pllctrl = SYSCON->PLL1CTRL;
+ Setup.pllndec = SYSCON->PLL1NDEC;
+ Setup.pllpdec = SYSCON->PLL1PDEC;
+ Setup.pllmdec = SYSCON->PLL1MDEC;
+ CLOCK_GetPLL1OutFromSetupUpdate(&Setup);
+ }
+
+ rate = s_Pll1_Freq;
+
+ return rate;
+}
+
+/* Set PLL0 output based on the passed PLL setup data */
+/*! brief Set PLL output based on the passed PLL setup data
+ * param pControl : Pointer to populated PLL control structure to generate setup with
+ * param pSetup : Pointer to PLL setup structure to be filled
+ * return PLL_ERROR_SUCCESS on success, or PLL setup error code
+ * note Actual frequency for setup may vary from the desired frequency based on the
+ * accuracy of input clocks, rounding, non-fractional PLL mode, etc.
+ */
+pll_error_t CLOCK_SetupPLL0Data(pll_config_t *pControl, pll_setup_t *pSetup)
+{
+ uint32_t inRate;
+ bool useSS = (bool)((pControl->flags & PLL_CONFIGFLAG_FORCENOFRACT) == 0UL);
+
+ pll_error_t pllError;
+
+ /* Determine input rate for the PLL */
+ if ((pControl->flags & PLL_CONFIGFLAG_USEINRATE) != 0UL)
+ {
+ inRate = pControl->inputRate;
+ }
+ else
+ {
+ inRate = CLOCK_GetPLL0InClockRate();
+ }
+
+ /* PLL flag options */
+ pllError = CLOCK_GetPll0Config(inRate, pControl->desiredRate, pSetup, useSS);
+ if ((useSS) && (pllError == kStatus_PLL_Success))
+ {
+ /* If using SS mode, then some tweaks are made to the generated setup */
+ pSetup->pllsscg[1] |= (uint32_t)pControl->ss_mf | (uint32_t)pControl->ss_mr | (uint32_t)pControl->ss_mc;
+ if (pControl->mfDither)
+ {
+ pSetup->pllsscg[1] |= (1UL << SYSCON_PLL0SSCG1_DITHER_SHIFT);
+ }
+ }
+
+ return pllError;
+}
+
+/* Set PLL0 output from PLL setup structure */
+/*! brief Set PLL output from PLL setup structure (precise frequency)
+ * param pSetup : Pointer to populated PLL setup structure
+ * param flagcfg : Flag configuration for PLL config structure
+ * return PLL_ERROR_SUCCESS on success, or PLL setup error code
+ * note This function will power off the PLL, setup the PLL with the
+ * new setup data, and then optionally powerup the PLL, wait for PLL lock,
+ * and adjust system voltages to the new PLL rate. The function will not
+ * alter any source clocks (ie, main systen clock) that may use the PLL,
+ * so these should be setup prior to and after exiting the function.
+ */
+pll_error_t CLOCK_SetupPLL0Prec(pll_setup_t *pSetup, uint32_t flagcfg)
+{
+ uint32_t inRate, clkRate, prediv;
+
+ /* Power off PLL during setup changes */
+ POWER_EnablePD(kPDRUNCFG_PD_PLL0);
+ POWER_EnablePD(kPDRUNCFG_PD_PLL0_SSCG);
+
+ pSetup->flags = flagcfg;
+
+ /* Write PLL setup data */
+ SYSCON->PLL0CTRL = pSetup->pllctrl;
+ SYSCON->PLL0NDEC = pSetup->pllndec;
+ SYSCON->PLL0NDEC = pSetup->pllndec | (1UL << SYSCON_PLL0NDEC_NREQ_SHIFT); /* latch */
+ SYSCON->PLL0PDEC = pSetup->pllpdec;
+ SYSCON->PLL0PDEC = pSetup->pllpdec | (1UL << SYSCON_PLL0PDEC_PREQ_SHIFT); /* latch */
+ SYSCON->PLL0SSCG0 = pSetup->pllsscg[0];
+ SYSCON->PLL0SSCG1 = pSetup->pllsscg[1];
+ SYSCON->PLL0SSCG1 =
+ pSetup->pllsscg[1] | (1UL << SYSCON_PLL0SSCG1_MREQ_SHIFT) | (1UL << SYSCON_PLL0SSCG1_MD_REQ_SHIFT); /* latch */
+
+ POWER_DisablePD(kPDRUNCFG_PD_PLL0);
+ POWER_DisablePD(kPDRUNCFG_PD_PLL0_SSCG);
+
+ if ((pSetup->flags & PLL_SETUPFLAG_WAITLOCK) != 0UL)
+ {
+ if ((SYSCON->PLL0SSCG1 & SYSCON_PLL0SSCG1_MDIV_EXT_MASK) != 0UL) /* normal mode */
+ {
+ inRate = CLOCK_GetPLL0InClockRate();
+ prediv = findPll0PreDiv();
+ /* Adjust input clock */
+ clkRate = inRate / prediv;
+ /* The lock signal is only reliable between fref[2] :100 kHz to 20 MHz. */
+ if ((clkRate >= 100000UL) && (clkRate <= 20000000UL))
+ {
+ while (CLOCK_IsPLL0Locked() == false)
+ {
+ }
+ }
+ else
+ {
+ SDK_DelayAtLeastUs(6000U,
+ SDK_DEVICE_MAXIMUM_CPU_CLOCK_FREQUENCY); /* software should use a 6 ms time interval
+ to insure the PLL will be stable */
+ }
+ }
+ else /* spread spectrum mode */
+ {
+ SDK_DelayAtLeastUs(6000U,
+ SDK_DEVICE_MAXIMUM_CPU_CLOCK_FREQUENCY); /* software should use a 6 ms time interval to
+ insure the PLL will be stable */
+ }
+ }
+
+ /* Update current programmed PLL rate var */
+ CLOCK_GetPLL0OutFromSetupUpdate(pSetup);
+
+ /* System voltage adjustment, occurs prior to setting main system clock */
+ if ((pSetup->flags & PLL_SETUPFLAG_ADGVOLT) != 0UL)
+ {
+ POWER_SetVoltageForFreq(s_Pll0_Freq);
+ }
+
+ return kStatus_PLL_Success;
+}
+
+/* Setup PLL Frequency from pre-calculated value */
+/**
+ * brief Set PLL0 output from PLL setup structure (precise frequency)
+ * param pSetup : Pointer to populated PLL setup structure
+ * return kStatus_PLL_Success on success, or PLL setup error code
+ * note This function will power off the PLL, setup the PLL with the
+ * new setup data, and then optionally powerup the PLL, wait for PLL lock,
+ * and adjust system voltages to the new PLL rate. The function will not
+ * alter any source clocks (ie, main systen clock) that may use the PLL,
+ * so these should be setup prior to and after exiting the function.
+ */
+pll_error_t CLOCK_SetPLL0Freq(const pll_setup_t *pSetup)
+{
+ uint32_t inRate, clkRate, prediv;
+ /* Power off PLL during setup changes */
+ POWER_EnablePD(kPDRUNCFG_PD_PLL0);
+ POWER_EnablePD(kPDRUNCFG_PD_PLL0_SSCG);
+
+ /* Write PLL setup data */
+ SYSCON->PLL0CTRL = pSetup->pllctrl;
+ SYSCON->PLL0NDEC = pSetup->pllndec;
+ SYSCON->PLL0NDEC = pSetup->pllndec | (1UL << SYSCON_PLL0NDEC_NREQ_SHIFT); /* latch */
+ SYSCON->PLL0PDEC = pSetup->pllpdec;
+ SYSCON->PLL0PDEC = pSetup->pllpdec | (1UL << SYSCON_PLL0PDEC_PREQ_SHIFT); /* latch */
+ SYSCON->PLL0SSCG0 = pSetup->pllsscg[0];
+ SYSCON->PLL0SSCG1 = pSetup->pllsscg[1];
+ SYSCON->PLL0SSCG1 =
+ pSetup->pllsscg[1] | (1UL << SYSCON_PLL0SSCG1_MD_REQ_SHIFT) | (1UL << SYSCON_PLL0SSCG1_MREQ_SHIFT); /* latch */
+
+ POWER_DisablePD(kPDRUNCFG_PD_PLL0);
+ POWER_DisablePD(kPDRUNCFG_PD_PLL0_SSCG);
+
+ if ((pSetup->flags & PLL_SETUPFLAG_WAITLOCK) != 0UL)
+ {
+ if ((SYSCON->PLL0SSCG1 & SYSCON_PLL0SSCG1_MDIV_EXT_MASK) != 0UL) /* normal mode */
+ {
+ inRate = CLOCK_GetPLL0InClockRate();
+ prediv = findPll0PreDiv();
+ /* Adjust input clock */
+ clkRate = inRate / prediv;
+ /* The lock signal is only reliable between fref[2] :100 kHz to 20 MHz. */
+ if ((clkRate >= 100000UL) && (clkRate <= 20000000UL))
+ {
+ while (CLOCK_IsPLL0Locked() == false)
+ {
+ }
+ }
+ else
+ {
+ SDK_DelayAtLeastUs(6000U,
+ SDK_DEVICE_MAXIMUM_CPU_CLOCK_FREQUENCY); /* software should use a 6 ms time interval
+ to insure the PLL will be stable */
+ }
+ }
+ else /* spread spectrum mode */
+ {
+ SDK_DelayAtLeastUs(6000U,
+ SDK_DEVICE_MAXIMUM_CPU_CLOCK_FREQUENCY); /* software should use a 6 ms time interval to
+ insure the PLL will be stable */
+ }
+ }
+
+ /* Update current programmed PLL rate var */
+ s_Pll0_Freq = pSetup->pllRate;
+
+ return kStatus_PLL_Success;
+}
+
+/* Setup PLL1 Frequency from pre-calculated value */
+/**
+ * brief Set PLL1 output from PLL setup structure (precise frequency)
+ * param pSetup : Pointer to populated PLL setup structure
+ * return kStatus_PLL_Success on success, or PLL setup error code
+ * note This function will power off the PLL, setup the PLL with the
+ * new setup data, and then optionally powerup the PLL, wait for PLL lock,
+ * and adjust system voltages to the new PLL rate. The function will not
+ * alter any source clocks (ie, main systen clock) that may use the PLL,
+ * so these should be setup prior to and after exiting the function.
+ */
+pll_error_t CLOCK_SetPLL1Freq(const pll_setup_t *pSetup)
+{
+ uint32_t inRate, clkRate, prediv;
+ /* Power off PLL during setup changes */
+ POWER_EnablePD(kPDRUNCFG_PD_PLL1);
+
+ /* Write PLL setup data */
+ SYSCON->PLL1CTRL = pSetup->pllctrl;
+ SYSCON->PLL1NDEC = pSetup->pllndec;
+ SYSCON->PLL1NDEC = pSetup->pllndec | (1UL << SYSCON_PLL1NDEC_NREQ_SHIFT); /* latch */
+ SYSCON->PLL1PDEC = pSetup->pllpdec;
+ SYSCON->PLL1PDEC = pSetup->pllpdec | (1UL << SYSCON_PLL1PDEC_PREQ_SHIFT); /* latch */
+ SYSCON->PLL1MDEC = pSetup->pllmdec;
+ SYSCON->PLL1MDEC = pSetup->pllmdec | (1UL << SYSCON_PLL1MDEC_MREQ_SHIFT); /* latch */
+
+ POWER_DisablePD(kPDRUNCFG_PD_PLL1);
+
+ if ((pSetup->flags & PLL_SETUPFLAG_WAITLOCK) != 0UL)
+ {
+ inRate = CLOCK_GetPLL1InClockRate();
+ prediv = findPll1PreDiv();
+ /* Adjust input clock */
+ clkRate = inRate / prediv;
+ /* The lock signal is only reliable between fref[2] :100 kHz to 20 MHz. */
+ if ((clkRate >= 100000UL) && (clkRate <= 20000000UL))
+ {
+ while (CLOCK_IsPLL1Locked() == false)
+ {
+ }
+ }
+ else
+ {
+ SDK_DelayAtLeastUs(6000U,
+ SDK_DEVICE_MAXIMUM_CPU_CLOCK_FREQUENCY); /* software should use a 6 ms time interval to
+ insure the PLL will be stable */
+ }
+ }
+
+ /* Update current programmed PLL rate var */
+ s_Pll1_Freq = pSetup->pllRate;
+
+ return kStatus_PLL_Success;
+}
+
+/* Set PLL0 clock based on the input frequency and multiplier */
+/*! brief Set PLL0 output based on the multiplier and input frequency
+ * param multiply_by : multiplier
+ * param input_freq : Clock input frequency of the PLL
+ * return Nothing
+ * note Unlike the Chip_Clock_SetupSystemPLLPrec() function, this
+ * function does not disable or enable PLL power, wait for PLL lock,
+ * or adjust system voltages. These must be done in the application.
+ * The function will not alter any source clocks (ie, main systen clock)
+ * that may use the PLL, so these should be setup prior to and after
+ * exiting the function.
+ */
+void CLOCK_SetupPLL0Mult(uint32_t multiply_by, uint32_t input_freq)
+{
+ uint32_t cco_freq = input_freq * multiply_by;
+ uint32_t pdec = 1U;
+ uint32_t selr;
+ uint32_t seli;
+ uint32_t selp;
+ uint32_t mdec, ndec;
+
+ while (cco_freq < 275000000U)
+ {
+ multiply_by <<= 1U; /* double value in each iteration */
+ pdec <<= 1U; /* correspondingly double pdec to cancel effect of double msel */
+ cco_freq = input_freq * multiply_by;
+ }
+
+ selr = 0U;
+
+ if (multiply_by >= 8000UL)
+ {
+ seli = 1UL;
+ }
+ else if (multiply_by >= 122UL)
+ {
+ seli = (uint32_t)(8000UL / multiply_by); /*floor(8000/M) */
+ }
+ else
+ {
+ seli = 2UL * ((uint32_t)(multiply_by / 4UL)) + 3UL; /* 2*floor(M/4) + 3 */
+ }
+
+ if (seli >= 63U)
+ {
+ seli = 63U;
+ }
+
+ {
+ selp = 31U;
+ }
+
+ if (pdec > 1U)
+ {
+ pdec = pdec / 2U; /* Account for minus 1 encoding */
+ /* Translate P value */
+ }
+
+ mdec = (uint32_t)PLL_SSCG1_MDEC_VAL_SET(multiply_by);
+ ndec = 0x1U; /* pre divide by 1 (hardcoded) */
+
+ SYSCON->PLL0CTRL = SYSCON_PLL0CTRL_CLKEN_MASK | SYSCON_PLL0CTRL_BYPASSPOSTDIV(0) |
+ SYSCON_PLL0CTRL_BYPASSPOSTDIV2(0) | (selr << SYSCON_PLL0CTRL_SELR_SHIFT) |
+ (seli << SYSCON_PLL0CTRL_SELI_SHIFT) | (selp << SYSCON_PLL0CTRL_SELP_SHIFT);
+ SYSCON->PLL0PDEC = pdec | (1UL << SYSCON_PLL0PDEC_PREQ_SHIFT); /* set Pdec value and assert preq */
+ SYSCON->PLL0NDEC = ndec | (1UL << SYSCON_PLL0NDEC_NREQ_SHIFT); /* set Pdec value and assert preq */
+ SYSCON->PLL0SSCG1 =
+ mdec | (1UL << SYSCON_PLL0SSCG1_MREQ_SHIFT); /* select non sscg MDEC value, assert mreq and select mdec value */
+}
+
+/* Enable USB DEVICE FULL SPEED clock */
+/*! brief Enable USB Device FS clock.
+ * param src : clock source
+ * param freq: clock frequency
+ * Enable USB Device Full Speed clock.
+ */
+bool CLOCK_EnableUsbfs0DeviceClock(clock_usbfs_src_t src, uint32_t freq)
+{
+ bool ret = true;
+
+ CLOCK_DisableClock(kCLOCK_Usbd0);
+
+ if (kCLOCK_UsbfsSrcFro == src)
+ {
+ switch (freq)
+ {
+ case 96000000U:
+ CLOCK_SetClkDiv(kCLOCK_DivUsb0Clk, 2, false); /*!< Div by 2 to get 48MHz, no divider reset */
+ break;
+
+ default:
+ ret = false;
+ break;
+ }
+ /* Turn ON FRO HF */
+ POWER_DisablePD(kPDRUNCFG_PD_FRO192M);
+ /* Enable FRO 96MHz output */
+ ANACTRL->FRO192M_CTRL =
+ ANACTRL->FRO192M_CTRL | ANACTRL_FRO192M_CTRL_ENA_96MHZCLK_MASK | ANACTRL_FRO192M_CTRL_USBCLKADJ_MASK;
+ /* Select FRO 96 or 48 MHz */
+ CLOCK_AttachClk(kFRO_HF_to_USB0_CLK);
+ }
+ else
+ {
+ /*!< Configure XTAL32M */
+ POWER_DisablePD(kPDRUNCFG_PD_XTAL32M); /* Ensure XTAL32M is powered */
+ POWER_DisablePD(kPDRUNCFG_PD_LDOXO32M); /* Ensure XTAL32M is powered */
+ (void)CLOCK_SetupExtClocking(16000000U); /* Enable clk_in clock */
+ SYSCON->CLOCK_CTRL |= SYSCON_CLOCK_CTRL_CLKIN_ENA_MASK; /* Enable clk_in from XTAL32M clock */
+ ANACTRL->XO32M_CTRL |= ANACTRL_XO32M_CTRL_ENABLE_SYSTEM_CLK_OUT_MASK; /* Enable clk_in to system */
+
+ /*!< Set up PLL1 */
+ POWER_DisablePD(kPDRUNCFG_PD_PLL1);
+ CLOCK_AttachClk(kEXT_CLK_to_PLL1); /*!< Switch PLL1CLKSEL to EXT_CLK */
+ const pll_setup_t pll1Setup = {
+ .pllctrl = SYSCON_PLL1CTRL_CLKEN_MASK | SYSCON_PLL1CTRL_SELI(19U) | SYSCON_PLL1CTRL_SELP(9U),
+ .pllndec = SYSCON_PLL1NDEC_NDIV(1U),
+ .pllpdec = SYSCON_PLL1PDEC_PDIV(5U),
+ .pllmdec = SYSCON_PLL1MDEC_MDIV(30U),
+ .pllRate = 48000000U,
+ .flags = PLL_SETUPFLAG_WAITLOCK};
+ (void)CLOCK_SetPLL1Freq(&pll1Setup);
+
+ CLOCK_SetClkDiv(kCLOCK_DivUsb0Clk, 1U, false);
+ CLOCK_AttachClk(kPLL1_to_USB0_CLK);
+ SDK_DelayAtLeastUs(50U, SDK_DEVICE_MAXIMUM_CPU_CLOCK_FREQUENCY);
+ }
+ CLOCK_EnableClock(kCLOCK_Usbd0);
+ CLOCK_EnableClock(kCLOCK_UsbRam1);
+
+ return ret;
+}
+
+/* Enable USB HOST FULL SPEED clock */
+/*! brief Enable USB HOST FS clock.
+ * param src : clock source
+ * param freq: clock frequency
+ * Enable USB HOST Full Speed clock.
+ */
+bool CLOCK_EnableUsbfs0HostClock(clock_usbfs_src_t src, uint32_t freq)
+{
+ bool ret = true;
+
+ CLOCK_DisableClock(kCLOCK_Usbhmr0);
+ CLOCK_DisableClock(kCLOCK_Usbhsl0);
+
+ if (kCLOCK_UsbfsSrcFro == src)
+ {
+ switch (freq)
+ {
+ case 96000000U:
+ CLOCK_SetClkDiv(kCLOCK_DivUsb0Clk, 2, false); /*!< Div by 2 to get 48MHz, no divider reset */
+ break;
+
+ default:
+ ret = false;
+ break;
+ }
+ /* Turn ON FRO HF */
+ POWER_DisablePD(kPDRUNCFG_PD_FRO192M);
+ /* Enable FRO 96MHz output */
+ ANACTRL->FRO192M_CTRL = ANACTRL->FRO192M_CTRL | ANACTRL_FRO192M_CTRL_ENA_96MHZCLK_MASK;
+ /* Select FRO 96 MHz */
+ CLOCK_AttachClk(kFRO_HF_to_USB0_CLK);
+ }
+ else
+ {
+ /*!< Configure XTAL32M */
+ POWER_DisablePD(kPDRUNCFG_PD_XTAL32M); /* Ensure XTAL32M is powered */
+ POWER_DisablePD(kPDRUNCFG_PD_LDOXO32M); /* Ensure XTAL32M is powered */
+ (void)CLOCK_SetupExtClocking(16000000U); /* Enable clk_in clock */
+ SYSCON->CLOCK_CTRL |= SYSCON_CLOCK_CTRL_CLKIN_ENA_MASK; /* Enable clk_in from XTAL32M clock */
+ ANACTRL->XO32M_CTRL |= ANACTRL_XO32M_CTRL_ENABLE_SYSTEM_CLK_OUT_MASK; /* Enable clk_in to system */
+
+ /*!< Set up PLL1 */
+ POWER_DisablePD(kPDRUNCFG_PD_PLL1);
+ CLOCK_AttachClk(kEXT_CLK_to_PLL1); /*!< Switch PLL1CLKSEL to EXT_CLK */
+ const pll_setup_t pll1Setup = {
+ .pllctrl = SYSCON_PLL1CTRL_CLKEN_MASK | SYSCON_PLL1CTRL_SELI(19U) | SYSCON_PLL1CTRL_SELP(9U),
+ .pllndec = SYSCON_PLL1NDEC_NDIV(1U),
+ .pllpdec = SYSCON_PLL1PDEC_PDIV(5U),
+ .pllmdec = SYSCON_PLL1MDEC_MDIV(30U),
+ .pllRate = 48000000U,
+ .flags = PLL_SETUPFLAG_WAITLOCK};
+ (void)CLOCK_SetPLL1Freq(&pll1Setup);
+
+ CLOCK_SetClkDiv(kCLOCK_DivUsb0Clk, 1U, false);
+ CLOCK_AttachClk(kPLL1_to_USB0_CLK);
+ SDK_DelayAtLeastUs(50U, SDK_DEVICE_MAXIMUM_CPU_CLOCK_FREQUENCY);
+ }
+ CLOCK_EnableClock(kCLOCK_Usbhmr0);
+ CLOCK_EnableClock(kCLOCK_Usbhsl0);
+ CLOCK_EnableClock(kCLOCK_UsbRam1);
+
+ return ret;
+}
+
+/* Enable USB PHY clock */
+bool CLOCK_EnableUsbhs0PhyPllClock(clock_usb_phy_src_t src, uint32_t freq)
+{
+ volatile uint32_t i;
+ uint32_t phyPllDiv = 0U;
+ uint16_t multiplier = 0U;
+
+ POWER_DisablePD(kPDRUNCFG_PD_XTAL32M);
+ POWER_DisablePD(kPDRUNCFG_PD_LDOXO32M);
+ POWER_DisablePD(kPDRUNCFG_PD_FRO32K); /*!< Ensure FRO32k is on */
+ POWER_DisablePD(kPDRUNCFG_PD_XTAL32K); /*!< Ensure xtal32k is on */
+ POWER_DisablePD(kPDRUNCFG_PD_USB1_PHY); /*!< Ensure xtal32k is on */
+ POWER_DisablePD(kPDRUNCFG_PD_LDOUSBHS); /*!< Ensure xtal32k is on */
+
+ /* wait to make sure PHY power is fully up */
+ i = 100000U;
+ while ((i--) != 0U)
+ {
+ __ASM("nop");
+ }
+
+ SYSCON->AHBCLKCTRLSET[2] = SYSCON_AHBCLKCTRL2_ANALOG_CTRL(1);
+ SYSCON->AHBCLKCTRLSET[2] = SYSCON_AHBCLKCTRL2_USB1_PHY(1);
+
+ USBPHY->CTRL_CLR = USBPHY_CTRL_SFTRST_MASK;
+
+ multiplier = 480000000 / freq;
+
+ switch (multiplier)
+ {
+ case 15:
+ {
+ phyPllDiv = USBPHY_PLL_SIC_PLL_DIV_SEL(0U);
+ break;
+ }
+ case 16:
+ {
+ phyPllDiv = USBPHY_PLL_SIC_PLL_DIV_SEL(1U);
+ break;
+ }
+ case 20:
+ {
+ phyPllDiv = USBPHY_PLL_SIC_PLL_DIV_SEL(2U);
+ break;
+ }
+ case 24:
+ {
+ phyPllDiv = USBPHY_PLL_SIC_PLL_DIV_SEL(4U);
+ break;
+ }
+ case 25:
+ {
+ phyPllDiv = USBPHY_PLL_SIC_PLL_DIV_SEL(5U);
+ break;
+ }
+ case 30:
+ {
+ phyPllDiv = USBPHY_PLL_SIC_PLL_DIV_SEL(6U);
+ break;
+ }
+ default:
+ {
+ return false;
+ }
+ }
+ USBPHY->PLL_SIC = (USBPHY->PLL_SIC & ~USBPHY_PLL_SIC_PLL_DIV_SEL(0x7)) | phyPllDiv;
+ USBPHY->PLL_SIC_SET = USBPHY_PLL_SIC_SET_PLL_REG_ENABLE_MASK;
+ USBPHY->PLL_SIC_CLR = (1UL << 16U); // Reserved. User must set this bit to 0x0
+ USBPHY->PLL_SIC_SET = USBPHY_PLL_SIC_SET_PLL_POWER_MASK;
+ USBPHY->PLL_SIC_SET = USBPHY_PLL_SIC_SET_PLL_EN_USB_CLKS_MASK;
+
+ USBPHY->CTRL_CLR = USBPHY_CTRL_CLR_CLKGATE_MASK;
+ USBPHY->PWD_SET = 0x0;
+
+ return true;
+}
+
+/* Enable USB DEVICE HIGH SPEED clock */
+bool CLOCK_EnableUsbhs0DeviceClock(clock_usbhs_src_t src, uint32_t freq)
+{
+ SYSCON->AHBCLKCTRLSET[2] = SYSCON_AHBCLKCTRL2_USB1_RAM(1);
+ SYSCON->AHBCLKCTRLSET[2] = SYSCON_AHBCLKCTRL2_USB1_DEV(1);
+
+ /* 16 MHz will be driven by the tb on the xtal1 pin of XTAL32M */
+ SYSCON->CLOCK_CTRL |= SYSCON_CLOCK_CTRL_CLKIN_ENA_MASK; /* Enable clock_in clock for clock module. */
+ ANACTRL->XO32M_CTRL |= ANACTRL_XO32M_CTRL_ENABLE_PLL_USB_OUT(1);
+ return true;
+}
+
+/* Enable USB HOST HIGH SPEED clock */
+bool CLOCK_EnableUsbhs0HostClock(clock_usbhs_src_t src, uint32_t freq)
+{
+ SYSCON->AHBCLKCTRLSET[2] = SYSCON_AHBCLKCTRL2_USB1_RAM(1);
+ SYSCON->AHBCLKCTRLSET[2] = SYSCON_AHBCLKCTRL2_USB1_HOST(1);
+
+ /* 16 MHz will be driven by the tb on the xtal1 pin of XTAL32M */
+ SYSCON->CLOCK_CTRL |= SYSCON_CLOCK_CTRL_CLKIN_ENA_MASK; /* Enable clock_in clock for clock module. */
+ ANACTRL->XO32M_CTRL |= ANACTRL_XO32M_CTRL_ENABLE_PLL_USB_OUT(1);
+
+ return true;
+}
+
+/*! @brief Enable the OSTIMER 32k clock.
+ * @return Nothing
+ */
+void CLOCK_EnableOstimer32kClock(void)
+{
+ PMC->OSTIMERr |= PMC_OSTIMER_CLOCKENABLE_MASK;
+}
diff --git a/drivers/fsl_clock.h b/drivers/fsl_clock.h
new file mode 100644
index 0000000..f35ff1e
--- /dev/null
+++ b/drivers/fsl_clock.h
@@ -0,0 +1,1525 @@
+/*
+ * Copyright 2017 - 2021 , NXP
+ * All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef _FSL_CLOCK_H_
+#define _FSL_CLOCK_H_
+
+#include "fsl_common.h"
+
+/*! @addtogroup clock */
+/*! @{ */
+
+/*! @file */
+
+/*******************************************************************************
+ * Definitions
+ *****************************************************************************/
+
+/*! @name Driver version */
+/*@{*/
+/*! @brief CLOCK driver version 2.3.7. */
+#define FSL_CLOCK_DRIVER_VERSION (MAKE_VERSION(2, 3, 7))
+/*@}*/
+
+/*! @brief Configure whether driver controls clock
+ *
+ * When set to 0, peripheral drivers will enable clock in initialize function
+ * and disable clock in de-initialize function. When set to 1, peripheral
+ * driver will not control the clock, application could control the clock out of
+ * the driver.
+ *
+ * @note All drivers share this feature switcher. If it is set to 1, application
+ * should handle clock enable and disable for all drivers.
+ */
+#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL))
+#define FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL 0
+#endif
+
+/*!
+ * @brief User-defined the size of cache for CLOCK_PllGetConfig() function.
+ *
+ * Once define this MACRO to be non-zero value, CLOCK_PllGetConfig() function
+ * would cache the recent calulation and accelerate the execution to get the
+ * right settings.
+ */
+#ifndef CLOCK_USR_CFG_PLL_CONFIG_CACHE_COUNT
+#define CLOCK_USR_CFG_PLL_CONFIG_CACHE_COUNT 2U
+#endif
+
+/* Definition for delay API in clock driver, users can redefine it to the real application. */
+#ifndef SDK_DEVICE_MAXIMUM_CPU_CLOCK_FREQUENCY
+#define SDK_DEVICE_MAXIMUM_CPU_CLOCK_FREQUENCY (100000000UL)
+#endif
+
+/*! @brief Clock ip name array for ROM. */
+#define ROM_CLOCKS \
+ { \
+ kCLOCK_Rom \
+ }
+/*! @brief Clock ip name array for SRAM. */
+#define SRAM_CLOCKS \
+ { \
+ kCLOCK_Sram1, kCLOCK_Sram2 \
+ }
+/*! @brief Clock ip name array for FLASH. */
+#define FLASH_CLOCKS \
+ { \
+ kCLOCK_Flash \
+ }
+/*! @brief Clock ip name array for FMC. */
+#define FMC_CLOCKS \
+ { \
+ kCLOCK_Fmc \
+ }
+/*! @brief Clock ip name array for INPUTMUX. */
+#define INPUTMUX_CLOCKS \
+ { \
+ kCLOCK_InputMux0 \
+ }
+/*! @brief Clock ip name array for IOCON. */
+#define IOCON_CLOCKS \
+ { \
+ kCLOCK_Iocon \
+ }
+/*! @brief Clock ip name array for GPIO. */
+#define GPIO_CLOCKS \
+ { \
+ kCLOCK_Gpio0, kCLOCK_Gpio1 \
+ }
+/*! @brief Clock ip name array for PINT. */
+#define PINT_CLOCKS \
+ { \
+ kCLOCK_Pint \
+ }
+/*! @brief Clock ip name array for GINT. */
+#define GINT_CLOCKS \
+ { \
+ kCLOCK_Gint, kCLOCK_Gint \
+ }
+/*! @brief Clock ip name array for DMA. */
+#define DMA_CLOCKS \
+ { \
+ kCLOCK_Dma0, kCLOCK_Dma1 \
+ }
+/*! @brief Clock ip name array for CRC. */
+#define CRC_CLOCKS \
+ { \
+ kCLOCK_Crc \
+ }
+/*! @brief Clock ip name array for WWDT. */
+#define WWDT_CLOCKS \
+ { \
+ kCLOCK_Wwdt \
+ }
+/*! @brief Clock ip name array for RTC. */
+#define RTC_CLOCKS \
+ { \
+ kCLOCK_Rtc \
+ }
+/*! @brief Clock ip name array for Mailbox. */
+#define MAILBOX_CLOCKS \
+ { \
+ kCLOCK_Mailbox \
+ }
+/*! @brief Clock ip name array for LPADC. */
+#define LPADC_CLOCKS \
+ { \
+ kCLOCK_Adc0 \
+ }
+/*! @brief Clock ip name array for MRT. */
+#define MRT_CLOCKS \
+ { \
+ kCLOCK_Mrt \
+ }
+/*! @brief Clock ip name array for OSTIMER. */
+#define OSTIMER_CLOCKS \
+ { \
+ kCLOCK_OsTimer0 \
+ }
+/*! @brief Clock ip name array for SCT0. */
+#define SCT_CLOCKS \
+ { \
+ kCLOCK_Sct0 \
+ }
+/*! @brief Clock ip name array for MCAN. */
+#define MCAN_CLOCKS \
+ { \
+ kCLOCK_Mcan \
+ }
+/*! @brief Clock ip name array for UTICK. */
+#define UTICK_CLOCKS \
+ { \
+ kCLOCK_Utick0 \
+ }
+/*! @brief Clock ip name array for FLEXCOMM. */
+#define FLEXCOMM_CLOCKS \
+ { \
+ kCLOCK_FlexComm0, kCLOCK_FlexComm1, kCLOCK_FlexComm2, kCLOCK_FlexComm3, kCLOCK_FlexComm4, kCLOCK_FlexComm5, \
+ kCLOCK_FlexComm6, kCLOCK_FlexComm7, kCLOCK_Hs_Lspi \
+ }
+/*! @brief Clock ip name array for LPUART. */
+#define LPUART_CLOCKS \
+ { \
+ kCLOCK_MinUart0, kCLOCK_MinUart1, kCLOCK_MinUart2, kCLOCK_MinUart3, kCLOCK_MinUart4, kCLOCK_MinUart5, \
+ kCLOCK_MinUart6, kCLOCK_MinUart7 \
+ }
+
+/*! @brief Clock ip name array for BI2C. */
+#define BI2C_CLOCKS \
+ { \
+ kCLOCK_BI2c0, kCLOCK_BI2c1, kCLOCK_BI2c2, kCLOCK_BI2c3, kCLOCK_BI2c4, kCLOCK_BI2c5, kCLOCK_BI2c6, kCLOCK_BI2c7 \
+ }
+/*! @brief Clock ip name array for LSPI. */
+#define LPSPI_CLOCKS \
+ { \
+ kCLOCK_LSpi0, kCLOCK_LSpi1, kCLOCK_LSpi2, kCLOCK_LSpi3, kCLOCK_LSpi4, kCLOCK_LSpi5, kCLOCK_LSpi6, kCLOCK_LSpi7 \
+ }
+/*! @brief Clock ip name array for FLEXI2S. */
+#define FLEXI2S_CLOCKS \
+ { \
+ kCLOCK_FlexI2s0, kCLOCK_FlexI2s1, kCLOCK_FlexI2s2, kCLOCK_FlexI2s3, kCLOCK_FlexI2s4, kCLOCK_FlexI2s5, \
+ kCLOCK_FlexI2s6, kCLOCK_FlexI2s7 \
+ }
+/*! @brief Clock ip name array for CTIMER. */
+#define CTIMER_CLOCKS \
+ { \
+ kCLOCK_Timer0, kCLOCK_Timer1, kCLOCK_Timer2, kCLOCK_Timer3, kCLOCK_Timer4 \
+ }
+/*! @brief Clock ip name array for EZHA */
+#define EZHA_CLOCKS \
+ { \
+ kCLOCK_Ezha \
+ }
+/*! @brief Clock ip name array for EZHB */
+#define EZHB_CLOCKS \
+ { \
+ kCLOCK_Ezhb \
+ }
+/*! @brief Clock ip name array for COMP */
+#define COMP_CLOCKS \
+ { \
+ kCLOCK_Comp \
+ }
+/*! @brief Clock ip name array for USB1CLK. */
+#define USB1CLK_CLOCKS \
+ { \
+ kCLOCK_Usb1Clk \
+ }
+/*! @brief Clock ip name array for FREQME. */
+#define FREQME_CLOCKS \
+ { \
+ kCLOCK_Freqme \
+ }
+/*! @brief Clock ip name array for USBRAM. */
+#define USBRAM_CLOCKS \
+ { \
+ kCLOCK_UsbRam1 \
+ }
+/*! @brief Clock ip name array for CDOG. */
+#define CDOG_CLOCKS \
+ { \
+ kCLOCK_Cdog \
+ }
+/*! @brief Clock ip name array for RNG. */
+#define RNG_CLOCKS \
+ { \
+ kCLOCK_Rng \
+ }
+/*! @brief Clock ip name array for USBHMR0. */
+#define USBHMR0_CLOCKS \
+ { \
+ kCLOCK_Usbhmr0 \
+ }
+/*! @brief Clock ip name array for USBHSL0. */
+#define USBHSL0_CLOCKS \
+ { \
+ kCLOCK_Usbhsl0 \
+ }
+/*! @brief Clock ip name array for HashCrypt. */
+#define HASHCRYPT_CLOCKS \
+ { \
+ kCLOCK_HashCrypt \
+ }
+/*! @brief Clock ip name array for PLULUT. */
+#define PLULUT_CLOCKS \
+ { \
+ kCLOCK_PluLut \
+ }
+/*! @brief Clock ip name array for PUF. */
+#define PUF_CLOCKS \
+ { \
+ kCLOCK_Puf \
+ }
+/*! @brief Clock ip name array for CASPER. */
+#define CASPER_CLOCKS \
+ { \
+ kCLOCK_Casper \
+ }
+/*! @brief Clock ip name array for ANALOGCTRL. */
+#define ANALOGCTRL_CLOCKS \
+ { \
+ kCLOCK_AnalogCtrl \
+ }
+/*! @brief Clock ip name array for HS_LSPI. */
+#define HS_LSPI_CLOCKS \
+ { \
+ kCLOCK_Hs_Lspi \
+ }
+/*! @brief Clock ip name array for GPIO_SEC. */
+#define GPIO_SEC_CLOCKS \
+ { \
+ kCLOCK_Gpio_Sec \
+ }
+/*! @brief Clock ip name array for GPIO_SEC_INT. */
+#define GPIO_SEC_INT_CLOCKS \
+ { \
+ kCLOCK_Gpio_Sec_Int \
+ }
+/*! @brief Clock ip name array for USBD. */
+#define USBD_CLOCKS \
+ { \
+ kCLOCK_Usbd0, kCLOCK_Usbh1, kCLOCK_Usbd1 \
+ }
+/*! @brief Clock ip name array for USBH. */
+#define USBH_CLOCKS \
+ { \
+ kCLOCK_Usbh1 \
+ }
+#define PLU_CLOCKS \
+ { \
+ kCLOCK_PluLut \
+ }
+#define SYSCTL_CLOCKS \
+ { \
+ kCLOCK_Sysctl \
+ }
+/*! @brief Clock gate name used for CLOCK_EnableClock/CLOCK_DisableClock. */
+/*------------------------------------------------------------------------------
+ clock_ip_name_t definition:
+------------------------------------------------------------------------------*/
+
+#define CLK_GATE_REG_OFFSET_SHIFT 8U
+#define CLK_GATE_REG_OFFSET_MASK 0xFFFFFF00U
+#define CLK_GATE_BIT_SHIFT_SHIFT 0U
+#define CLK_GATE_BIT_SHIFT_MASK 0x000000FFU
+
+#define CLK_GATE_DEFINE(reg_offset, bit_shift) \
+ ((((reg_offset) << CLK_GATE_REG_OFFSET_SHIFT) & CLK_GATE_REG_OFFSET_MASK) | \
+ (((bit_shift) << CLK_GATE_BIT_SHIFT_SHIFT) & CLK_GATE_BIT_SHIFT_MASK))
+
+#define CLK_GATE_ABSTRACT_REG_OFFSET(x) (((uint32_t)(x)&CLK_GATE_REG_OFFSET_MASK) >> CLK_GATE_REG_OFFSET_SHIFT)
+#define CLK_GATE_ABSTRACT_BITS_SHIFT(x) (((uint32_t)(x)&CLK_GATE_BIT_SHIFT_MASK) >> CLK_GATE_BIT_SHIFT_SHIFT)
+
+#define AHB_CLK_CTRL0 0
+#define AHB_CLK_CTRL1 1
+#define AHB_CLK_CTRL2 2
+
+/*! @brief Clock gate name used for CLOCK_EnableClock/CLOCK_DisableClock. */
+typedef enum _clock_ip_name
+{
+ kCLOCK_IpInvalid = 0U, /*!< Invalid Ip Name. */
+ kCLOCK_Rom = CLK_GATE_DEFINE(AHB_CLK_CTRL0, 1), /*!< Clock gate name: Rom. */
+
+ kCLOCK_Sram1 = CLK_GATE_DEFINE(AHB_CLK_CTRL0, 3), /*!< Clock gate name: Sram1. */
+
+ kCLOCK_Sram2 = CLK_GATE_DEFINE(AHB_CLK_CTRL0, 4), /*!< Clock gate name: Sram2. */
+
+ kCLOCK_Flash = CLK_GATE_DEFINE(AHB_CLK_CTRL0, 7), /*!< Clock gate name: Flash. */
+
+ kCLOCK_Fmc = CLK_GATE_DEFINE(AHB_CLK_CTRL0, 8), /*!< Clock gate name: Fmc. */
+
+ kCLOCK_InputMux = CLK_GATE_DEFINE(AHB_CLK_CTRL0, 11), /*!< Clock gate name: InputMux. */
+
+ kCLOCK_Iocon = CLK_GATE_DEFINE(AHB_CLK_CTRL0, 13), /*!< Clock gate name: Iocon. */
+
+ kCLOCK_Gpio0 = CLK_GATE_DEFINE(AHB_CLK_CTRL0, 14), /*!< Clock gate name: Gpio0. */
+
+ kCLOCK_Gpio1 = CLK_GATE_DEFINE(AHB_CLK_CTRL0, 15), /*!< Clock gate name: Gpio1. */
+
+ kCLOCK_Pint = CLK_GATE_DEFINE(AHB_CLK_CTRL0, 18), /*!< Clock gate name: Pint. */
+
+ kCLOCK_Gint = CLK_GATE_DEFINE(AHB_CLK_CTRL0, 19), /*!< Clock gate name: Gint. */
+
+ kCLOCK_Dma0 = CLK_GATE_DEFINE(AHB_CLK_CTRL0, 20), /*!< Clock gate name: Dma0. */
+
+ kCLOCK_Crc = CLK_GATE_DEFINE(AHB_CLK_CTRL0, 21), /*!< Clock gate name: Crc. */
+
+ kCLOCK_Wwdt = CLK_GATE_DEFINE(AHB_CLK_CTRL0, 22), /*!< Clock gate name: Wwdt. */
+
+ kCLOCK_Rtc = CLK_GATE_DEFINE(AHB_CLK_CTRL0, 23), /*!< Clock gate name: Rtc. */
+
+ kCLOCK_Mailbox = CLK_GATE_DEFINE(AHB_CLK_CTRL0, 26), /*!< Clock gate name: Mailbox. */
+
+ kCLOCK_Adc0 = CLK_GATE_DEFINE(AHB_CLK_CTRL0, 27), /*!< Clock gate name: Adc0. */
+
+ kCLOCK_Mrt = CLK_GATE_DEFINE(AHB_CLK_CTRL1, 0), /*!< Clock gate name: Mrt. */
+
+ kCLOCK_OsTimer0 = CLK_GATE_DEFINE(AHB_CLK_CTRL1, 1), /*!< Clock gate name: OsTimer0. */
+
+ kCLOCK_Sct0 = CLK_GATE_DEFINE(AHB_CLK_CTRL1, 2), /*!< Clock gate name: Sct0. */
+
+ kCLOCK_Mcan = CLK_GATE_DEFINE(AHB_CLK_CTRL1, 7), /*!< Clock gate name: Mcan. */
+
+ kCLOCK_Utick0 = CLK_GATE_DEFINE(AHB_CLK_CTRL1, 10), /*!< Clock gate name: Utick0. */
+
+ kCLOCK_FlexComm0 = CLK_GATE_DEFINE(AHB_CLK_CTRL1, 11), /*!< Clock gate name: FlexComm0. */
+
+ kCLOCK_FlexComm1 = CLK_GATE_DEFINE(AHB_CLK_CTRL1, 12), /*!< Clock gate name: FlexComm1. */
+
+ kCLOCK_FlexComm2 = CLK_GATE_DEFINE(AHB_CLK_CTRL1, 13), /*!< Clock gate name: FlexComm2. */
+
+ kCLOCK_FlexComm3 = CLK_GATE_DEFINE(AHB_CLK_CTRL1, 14), /*!< Clock gate name: FlexComm3. */
+
+ kCLOCK_FlexComm4 = CLK_GATE_DEFINE(AHB_CLK_CTRL1, 15), /*!< Clock gate name: FlexComm4. */
+
+ kCLOCK_FlexComm5 = CLK_GATE_DEFINE(AHB_CLK_CTRL1, 16), /*!< Clock gate name: FlexComm5. */
+
+ kCLOCK_FlexComm6 = CLK_GATE_DEFINE(AHB_CLK_CTRL1, 17), /*!< Clock gate name: FlexComm6. */
+
+ kCLOCK_FlexComm7 = CLK_GATE_DEFINE(AHB_CLK_CTRL1, 18), /*!< Clock gate name: FlexComm7. */
+
+ kCLOCK_MinUart0 = CLK_GATE_DEFINE(AHB_CLK_CTRL1, 11), /*!< Clock gate name: MinUart0. */
+
+ kCLOCK_MinUart1 = CLK_GATE_DEFINE(AHB_CLK_CTRL1, 12), /*!< Clock gate name: MinUart1. */
+
+ kCLOCK_MinUart2 = CLK_GATE_DEFINE(AHB_CLK_CTRL1, 13), /*!< Clock gate name: MinUart2. */
+
+ kCLOCK_MinUart3 = CLK_GATE_DEFINE(AHB_CLK_CTRL1, 14), /*!< Clock gate name: MinUart3. */
+
+ kCLOCK_MinUart4 = CLK_GATE_DEFINE(AHB_CLK_CTRL1, 15), /*!< Clock gate name: MinUart4. */
+
+ kCLOCK_MinUart5 = CLK_GATE_DEFINE(AHB_CLK_CTRL1, 16), /*!< Clock gate name: MinUart5. */
+
+ kCLOCK_MinUart6 = CLK_GATE_DEFINE(AHB_CLK_CTRL1, 17), /*!< Clock gate name: MinUart6. */
+
+ kCLOCK_MinUart7 = CLK_GATE_DEFINE(AHB_CLK_CTRL1, 18), /*!< Clock gate name: MinUart7. */
+
+ kCLOCK_LSpi0 = CLK_GATE_DEFINE(AHB_CLK_CTRL1, 11), /*!< Clock gate name: LSpi0. */
+
+ kCLOCK_LSpi1 = CLK_GATE_DEFINE(AHB_CLK_CTRL1, 12), /*!< Clock gate name: LSpi1. */
+
+ kCLOCK_LSpi2 = CLK_GATE_DEFINE(AHB_CLK_CTRL1, 13), /*!< Clock gate name: LSpi2. */
+
+ kCLOCK_LSpi3 = CLK_GATE_DEFINE(AHB_CLK_CTRL1, 14), /*!< Clock gate name: LSpi3. */
+
+ kCLOCK_LSpi4 = CLK_GATE_DEFINE(AHB_CLK_CTRL1, 15), /*!< Clock gate name: LSpi4. */
+
+ kCLOCK_LSpi5 = CLK_GATE_DEFINE(AHB_CLK_CTRL1, 16), /*!< Clock gate name: LSpi5. */
+
+ kCLOCK_LSpi6 = CLK_GATE_DEFINE(AHB_CLK_CTRL1, 17), /*!< Clock gate name: LSpi6. */
+
+ kCLOCK_LSpi7 = CLK_GATE_DEFINE(AHB_CLK_CTRL1, 18), /*!< Clock gate name: LSpi7. */
+
+ kCLOCK_BI2c0 = CLK_GATE_DEFINE(AHB_CLK_CTRL1, 11), /*!< Clock gate name: BI2c0. */
+
+ kCLOCK_BI2c1 = CLK_GATE_DEFINE(AHB_CLK_CTRL1, 12), /*!< Clock gate name: BI2c1. */
+
+ kCLOCK_BI2c2 = CLK_GATE_DEFINE(AHB_CLK_CTRL1, 13), /*!< Clock gate name: BI2c2. */
+
+ kCLOCK_BI2c3 = CLK_GATE_DEFINE(AHB_CLK_CTRL1, 14), /*!< Clock gate name: BI2c3. */
+
+ kCLOCK_BI2c4 = CLK_GATE_DEFINE(AHB_CLK_CTRL1, 15), /*!< Clock gate name: BI2c4. */
+
+ kCLOCK_BI2c5 = CLK_GATE_DEFINE(AHB_CLK_CTRL1, 16), /*!< Clock gate name: BI2c5. */
+
+ kCLOCK_BI2c6 = CLK_GATE_DEFINE(AHB_CLK_CTRL1, 17), /*!< Clock gate name: BI2c6. */
+
+ kCLOCK_BI2c7 = CLK_GATE_DEFINE(AHB_CLK_CTRL1, 18), /*!< Clock gate name: BI2c7. */
+
+ kCLOCK_FlexI2s0 = CLK_GATE_DEFINE(AHB_CLK_CTRL1, 11), /*!< Clock gate name: FlexI2s0. */
+
+ kCLOCK_FlexI2s1 = CLK_GATE_DEFINE(AHB_CLK_CTRL1, 12), /*!< Clock gate name: FlexI2s1. */
+
+ kCLOCK_FlexI2s2 = CLK_GATE_DEFINE(AHB_CLK_CTRL1, 13), /*!< Clock gate name: FlexI2s2. */
+
+ kCLOCK_FlexI2s3 = CLK_GATE_DEFINE(AHB_CLK_CTRL1, 14), /*!< Clock gate name: FlexI2s3. */
+
+ kCLOCK_FlexI2s4 = CLK_GATE_DEFINE(AHB_CLK_CTRL1, 15), /*!< Clock gate name: FlexI2s4. */
+
+ kCLOCK_FlexI2s5 = CLK_GATE_DEFINE(AHB_CLK_CTRL1, 16), /*!< Clock gate name: FlexI2s5. */
+
+ kCLOCK_FlexI2s6 = CLK_GATE_DEFINE(AHB_CLK_CTRL1, 17), /*!< Clock gate name: FlexI2s6. */
+
+ kCLOCK_FlexI2s7 = CLK_GATE_DEFINE(AHB_CLK_CTRL1, 18), /*!< Clock gate name: FlexI2s7. */
+
+ kCLOCK_Timer2 = CLK_GATE_DEFINE(AHB_CLK_CTRL1, 22), /*!< Clock gate name: Timer2. */
+
+ kCLOCK_Usbd0 = CLK_GATE_DEFINE(AHB_CLK_CTRL1, 25), /*!< Clock gate name: Usbd0. */
+
+ kCLOCK_Timer0 = CLK_GATE_DEFINE(AHB_CLK_CTRL1, 26), /*!< Clock gate name: Timer0. */
+
+ kCLOCK_Timer1 = CLK_GATE_DEFINE(AHB_CLK_CTRL1, 27), /*!< Clock gate name: Timer1. */
+
+ kCLOCK_Ezha = CLK_GATE_DEFINE(AHB_CLK_CTRL1, 30), /*!< Clock gate name: Ezha. */
+
+ kCLOCK_Ezhb = CLK_GATE_DEFINE(AHB_CLK_CTRL1, 31), /*!< Clock gate name: Ezhb. */
+
+ kCLOCK_Dma1 = CLK_GATE_DEFINE(AHB_CLK_CTRL2, 1), /*!< Clock gate name: Dma1. */
+
+ kCLOCK_Comp = CLK_GATE_DEFINE(AHB_CLK_CTRL2, 2), /*!< Clock gate name: Comp. */
+
+ kCLOCK_Usbh1 = CLK_GATE_DEFINE(AHB_CLK_CTRL2, 4), /*!< Clock gate name: Usbh1. */
+
+ kCLOCK_Usbd1 = CLK_GATE_DEFINE(AHB_CLK_CTRL2, 5), /*!< Clock gate name: Usbd1. */
+
+ kCLOCK_UsbRam1 = CLK_GATE_DEFINE(AHB_CLK_CTRL2, 6), /*!< Clock gate name: UsbRam1. */
+
+ kCLOCK_Usb1Clk = CLK_GATE_DEFINE(AHB_CLK_CTRL2, 7), /*!< Clock gate name: Usb1Clk. */
+
+ kCLOCK_Freqme = CLK_GATE_DEFINE(AHB_CLK_CTRL2, 8), /*!< Clock gate name: Freqme. */
+
+ kCLOCK_Cdog = CLK_GATE_DEFINE(AHB_CLK_CTRL2, 11), /*!< Clock gate name: Cdog. */
+
+ kCLOCK_Rng = CLK_GATE_DEFINE(AHB_CLK_CTRL2, 13), /*!< Clock gate name: Rng. */
+
+ kCLOCK_Sysctl = CLK_GATE_DEFINE(AHB_CLK_CTRL2, 15), /*!< Clock gate name: Sysctl. */
+
+ kCLOCK_Usbhmr0 = CLK_GATE_DEFINE(AHB_CLK_CTRL2, 16), /*!< Clock gate name: Usbhmr0. */
+
+ kCLOCK_Usbhsl0 = CLK_GATE_DEFINE(AHB_CLK_CTRL2, 17), /*!< Clock gate name: Usbhsl0. */
+
+ kCLOCK_HashCrypt = CLK_GATE_DEFINE(AHB_CLK_CTRL2, 18), /*!< Clock gate name: HashCrypt. */
+
+ kCLOCK_PluLut = CLK_GATE_DEFINE(AHB_CLK_CTRL2, 20), /*!< Clock gate name: PluLut. */
+
+ kCLOCK_Timer3 = CLK_GATE_DEFINE(AHB_CLK_CTRL2, 21), /*!< Clock gate name: Timer3. */
+
+ kCLOCK_Timer4 = CLK_GATE_DEFINE(AHB_CLK_CTRL2, 22), /*!< Clock gate name: Timer4. */
+
+ kCLOCK_Puf = CLK_GATE_DEFINE(AHB_CLK_CTRL2, 23), /*!< Clock gate name: Puf. */
+
+ kCLOCK_Casper = CLK_GATE_DEFINE(AHB_CLK_CTRL2, 24), /*!< Clock gate name: Casper. */
+
+ kCLOCK_AnalogCtrl = CLK_GATE_DEFINE(AHB_CLK_CTRL2, 27), /*!< Clock gate name: AnalogCtrl. */
+
+ kCLOCK_Hs_Lspi = CLK_GATE_DEFINE(AHB_CLK_CTRL2, 28), /*!< Clock gate name: Lspi. */
+
+ kCLOCK_Gpio_Sec = CLK_GATE_DEFINE(AHB_CLK_CTRL2, 29), /*!< Clock gate name: GPIO Sec. */
+
+ kCLOCK_Gpio_Sec_Int = CLK_GATE_DEFINE(AHB_CLK_CTRL2, 30) /*!< Clock gate name: GPIO SEC Int. */
+} clock_ip_name_t;
+
+/*! @brief Peripherals clock source definition. */
+#define BUS_CLK kCLOCK_BusClk
+
+#define I2C0_CLK_SRC BUS_CLK
+
+/*! @brief Clock name used to get clock frequency. */
+typedef enum _clock_name
+{
+ kCLOCK_CoreSysClk, /*!< Core/system clock (aka MAIN_CLK) */
+ kCLOCK_BusClk, /*!< Bus clock (AHB clock) */
+ kCLOCK_ClockOut, /*!< CLOCKOUT */
+ kCLOCK_FroHf, /*!< FRO48/96 */
+ kCLOCK_Pll1Out, /*!< PLL1 Output */
+ kCLOCK_Mclk, /*!< MCLK */
+ kCLOCK_Fro12M, /*!< FRO12M */
+ kCLOCK_Fro1M, /*!< FRO1M */
+ kCLOCK_ExtClk, /*!< External Clock */
+ kCLOCK_Pll0Out, /*!< PLL0 Output */
+ kCLOCK_FlexI2S, /*!< FlexI2S clock */
+
+} clock_name_t;
+
+/*! @brief Clock Mux Switches
+ * The encoding is as follows each connection identified is 32bits wide while 24bits are valuable
+ * starting from LSB upwards
+ *
+ * [4 bits for choice, 0 means invalid choice] [8 bits mux ID]*
+ *
+ */
+
+#define CLK_ATTACH_ID(mux, sel, pos) \
+ ((((uint32_t)(mux) << 0U) | (((uint32_t)(sel) + 1U) & 0xFU) << 8U) << ((uint32_t)(pos)*12U))
+#define MUX_A(mux, sel) CLK_ATTACH_ID((mux), (sel), 0U)
+#define MUX_B(mux, sel, selector) (CLK_ATTACH_ID((mux), (sel), 1U) | ((selector) << 24U))
+
+#define GET_ID_ITEM(connection) ((connection)&0xFFFU)
+#define GET_ID_NEXT_ITEM(connection) ((connection) >> 12U)
+#define GET_ID_ITEM_MUX(connection) (((uint8_t)connection) & 0xFFU)
+#define GET_ID_ITEM_SEL(connection) ((uint8_t)((((uint32_t)(connection)&0xF00U) >> 8U) - 1U))
+#define GET_ID_SELECTOR(connection) ((connection)&0xF000000U)
+
+#define CM_SYSTICKCLKSEL0 0
+#define CM_TRACECLKSEL 2
+#define CM_CTIMERCLKSEL0 3
+#define CM_CTIMERCLKSEL1 4
+#define CM_CTIMERCLKSEL2 5
+#define CM_CTIMERCLKSEL3 6
+#define CM_CTIMERCLKSEL4 7
+#define CM_MAINCLKSELA 8
+#define CM_MAINCLKSELB 9
+#define CM_CLKOUTCLKSEL 10
+#define CM_PLL0CLKSEL 12
+#define CM_PLL1CLKSEL 13
+#define CM_MCANCLKSEL 16
+#define CM_ADCASYNCCLKSEL 17
+#define CM_USB0CLKSEL 18
+#define CM_CLK32KCLKSEL 19
+#define CM_FXCOMCLKSEL0 20
+#define CM_FXCOMCLKSEL1 21
+#define CM_FXCOMCLKSEL2 22
+#define CM_FXCOMCLKSEL3 23
+#define CM_FXCOMCLKSEL4 24
+#define CM_FXCOMCLKSEL5 25
+#define CM_FXCOMCLKSEL6 26
+#define CM_FXCOMCLKSEL7 27
+#define CM_HSLSPICLKSEL 28
+#define CM_MCLKCLKSEL 32
+#define CM_SCTCLKSEL 36
+
+#define CM_OSTIMERCLKSEL (62U)
+#define CM_RTCOSC32KCLKSEL 63U
+
+/*!
+ * @brief The enumerator of clock attach Id.
+ */
+typedef enum _clock_attach_id
+{
+
+ kFRO12M_to_MAIN_CLK = MUX_A(CM_MAINCLKSELA, 0) | MUX_B(CM_MAINCLKSELB, 0, 0), /*!< Attach FRO12M to MAIN_CLK. */
+
+ kEXT_CLK_to_MAIN_CLK = MUX_A(CM_MAINCLKSELA, 1) | MUX_B(CM_MAINCLKSELB, 0, 0), /*!< Attach EXT_CLK to MAIN_CLK. */
+
+ kFRO1M_to_MAIN_CLK = MUX_A(CM_MAINCLKSELA, 2) | MUX_B(CM_MAINCLKSELB, 0, 0), /*!< Attach FRO1M to MAIN_CLK. */
+
+ kFRO_HF_to_MAIN_CLK = MUX_A(CM_MAINCLKSELA, 3) | MUX_B(CM_MAINCLKSELB, 0, 0), /*!< Attach FRO_HF to MAIN_CLK. */
+
+ kPLL0_to_MAIN_CLK = MUX_A(CM_MAINCLKSELA, 0) | MUX_B(CM_MAINCLKSELB, 1, 0), /*!< Attach PLL0 to MAIN_CLK. */
+
+ kPLL1_to_MAIN_CLK = MUX_A(CM_MAINCLKSELA, 0) | MUX_B(CM_MAINCLKSELB, 2, 0), /*!< Attach PLL1 to MAIN_CLK. */
+
+ kOSC32K_to_MAIN_CLK = MUX_A(CM_MAINCLKSELA, 0) | MUX_B(CM_MAINCLKSELB, 3, 0), /*!< Attach OSC32K to MAIN_CLK. */
+
+ kMAIN_CLK_to_CLKOUT = MUX_A(CM_CLKOUTCLKSEL, 0), /*!< Attach MAIN_CLK to CLKOUT. */
+
+ kPLL0_to_CLKOUT = MUX_A(CM_CLKOUTCLKSEL, 1), /*!< Attach PLL0 to CLKOUT. */
+
+ kEXT_CLK_to_CLKOUT = MUX_A(CM_CLKOUTCLKSEL, 2), /*!< Attach EXT_CLK to CLKOUT. */
+
+ kFRO_HF_to_CLKOUT = MUX_A(CM_CLKOUTCLKSEL, 3), /*!< Attach FRO_HF to CLKOUT. */
+
+ kFRO1M_to_CLKOUT = MUX_A(CM_CLKOUTCLKSEL, 4), /*!< Attach FRO1M to CLKOUT. */
+
+ kPLL1_to_CLKOUT = MUX_A(CM_CLKOUTCLKSEL, 5), /*!< Attach PLL1 to CLKOUT. */
+
+ kOSC32K_to_CLKOUT = MUX_A(CM_CLKOUTCLKSEL, 6), /*!< Attach OSC32K to CLKOUT. */
+
+ kNONE_to_SYS_CLKOUT = MUX_A(CM_CLKOUTCLKSEL, 7), /*!< Attach NONE to SYS_CLKOUT. */
+
+ kFRO12M_to_PLL0 = MUX_A(CM_PLL0CLKSEL, 0), /*!< Attach FRO12M to PLL0. */
+
+ kEXT_CLK_to_PLL0 = MUX_A(CM_PLL0CLKSEL, 1), /*!< Attach EXT_CLK to PLL0. */
+
+ kFRO1M_to_PLL0 = MUX_A(CM_PLL0CLKSEL, 2), /*!< Attach FRO1M to PLL0. */
+
+ kOSC32K_to_PLL0 = MUX_A(CM_PLL0CLKSEL, 3), /*!< Attach OSC32K to PLL0. */
+
+ kNONE_to_PLL0 = MUX_A(CM_PLL0CLKSEL, 7), /*!< Attach NONE to PLL0. */
+
+ kMCAN_DIV_to_MCAN = MUX_A(CM_MCANCLKSEL, 0), /*!< Attach MCAN_DIV to MCAN. */
+
+ kFRO1M_to_MCAN = MUX_A(CM_MCANCLKSEL, 1), /*!< Attach FRO1M to MCAN. */
+
+ kOSC32K_to_MCAN = MUX_A(CM_MCANCLKSEL, 2), /*!< Attach OSC32K to MCAN. */
+
+ kNONE_to_MCAN = MUX_A(CM_MCANCLKSEL, 7), /*!< Attach NONE to MCAN. */
+
+ kMAIN_CLK_to_ADC_CLK = MUX_A(CM_ADCASYNCCLKSEL, 0), /*!< Attach MAIN_CLK to ADC_CLK. */
+
+ kPLL0_to_ADC_CLK = MUX_A(CM_ADCASYNCCLKSEL, 1), /*!< Attach PLL0 to ADC_CLK. */
+
+ kFRO_HF_to_ADC_CLK = MUX_A(CM_ADCASYNCCLKSEL, 2), /*!< Attach FRO_HF to ADC_CLK. */
+
+ kEXT_CLK_to_ADC_CLK = MUX_A(CM_ADCASYNCCLKSEL, 4), /*!< Attach EXT_CLK to ADC_CLK. */
+
+ kNONE_to_ADC_CLK = MUX_A(CM_ADCASYNCCLKSEL, 7), /*!< Attach NONE to ADC_CLK. */
+
+ kMAIN_CLK_to_USB0_CLK = MUX_A(CM_USB0CLKSEL, 0), /*!< Attach MAIN_CLK to USB0_CLK. */
+
+ kPLL0_to_USB0_CLK = MUX_A(CM_USB0CLKSEL, 1), /*!< Attach PLL0 to USB0_CLK. */
+
+ kFRO_HF_to_USB0_CLK = MUX_A(CM_USB0CLKSEL, 3), /*!< Attach FRO_HF to USB0_CLK. */
+
+ kPLL1_to_USB0_CLK = MUX_A(CM_USB0CLKSEL, 5), /*!< Attach PLL1 to USB0_CLK. */
+
+ kNONE_to_USB0_CLK = MUX_A(CM_USB0CLKSEL, 7), /*!< Attach NONE to USB0_CLK. */
+
+ kOSC32K_to_CLK32K = MUX_A(CM_CLK32KCLKSEL, 0), /*!< Attach OSC32K to CLK32K. */
+
+ kFRO1MDIV_to_CLK32K = MUX_A(CM_CLK32KCLKSEL, 1), /*!< Attach FRO1MDIV to CLK32K. */
+
+ kNONE_to_CLK32K = MUX_A(CM_CLK32KCLKSEL, 7), /*!< Attach NONE to CLK32K. */
+
+ kMAIN_CLK_to_FLEXCOMM0 = MUX_A(CM_FXCOMCLKSEL0, 0), /*!< Attach MAIN_CLK to FLEXCOMM0. */
+
+ kPLL0_DIV_to_FLEXCOMM0 = MUX_A(CM_FXCOMCLKSEL0, 1), /*!< Attach PLL0_DIV to FLEXCOMM0. */
+
+ kFRO12M_to_FLEXCOMM0 = MUX_A(CM_FXCOMCLKSEL0, 2), /*!< Attach FRO12M to FLEXCOMM0. */
+
+ kFRO_HF_DIV_to_FLEXCOMM0 = MUX_A(CM_FXCOMCLKSEL0, 3), /*!< Attach FRO_HF_DIV to FLEXCOMM0. */
+
+ kFRO1M_to_FLEXCOMM0 = MUX_A(CM_FXCOMCLKSEL0, 4), /*!< Attach FRO1M to FLEXCOMM0. */
+
+ kMCLK_to_FLEXCOMM0 = MUX_A(CM_FXCOMCLKSEL0, 5), /*!< Attach MCLK to FLEXCOMM0. */
+
+ kOSC32K_to_FLEXCOMM0 = MUX_A(CM_FXCOMCLKSEL0, 6), /*!< Attach OSC32K to FLEXCOMM0. */
+
+ kNONE_to_FLEXCOMM0 = MUX_A(CM_FXCOMCLKSEL0, 7), /*!< Attach NONE to FLEXCOMM0. */
+
+ kMAIN_CLK_to_FLEXCOMM1 = MUX_A(CM_FXCOMCLKSEL1, 0), /*!< Attach MAIN_CLK to FLEXCOMM1. */
+
+ kPLL0_DIV_to_FLEXCOMM1 = MUX_A(CM_FXCOMCLKSEL1, 1), /*!< Attach PLL0_DIV to FLEXCOMM1. */
+
+ kFRO12M_to_FLEXCOMM1 = MUX_A(CM_FXCOMCLKSEL1, 2), /*!< Attach FRO12M to FLEXCOMM1. */
+
+ kFRO_HF_DIV_to_FLEXCOMM1 = MUX_A(CM_FXCOMCLKSEL1, 3), /*!< Attach FRO_HF_DIV to FLEXCOMM1. */
+
+ kFRO1M_to_FLEXCOMM1 = MUX_A(CM_FXCOMCLKSEL1, 4), /*!< Attach FRO1M to FLEXCOMM1. */
+
+ kMCLK_to_FLEXCOMM1 = MUX_A(CM_FXCOMCLKSEL1, 5), /*!< Attach MCLK to FLEXCOMM1. */
+
+ kOSC32K_to_FLEXCOMM1 = MUX_A(CM_FXCOMCLKSEL1, 6), /*!< Attach OSC32K to FLEXCOMM1. */
+
+ kNONE_to_FLEXCOMM1 = MUX_A(CM_FXCOMCLKSEL1, 7), /*!< Attach NONE to FLEXCOMM1. */
+
+ kMAIN_CLK_to_FLEXCOMM2 = MUX_A(CM_FXCOMCLKSEL2, 0), /*!< Attach MAIN_CLK to FLEXCOMM2. */
+
+ kPLL0_DIV_to_FLEXCOMM2 = MUX_A(CM_FXCOMCLKSEL2, 1), /*!< Attach PLL0_DIV to FLEXCOMM2. */
+
+ kFRO12M_to_FLEXCOMM2 = MUX_A(CM_FXCOMCLKSEL2, 2), /*!< Attach FRO12M to FLEXCOMM2. */
+
+ kFRO_HF_DIV_to_FLEXCOMM2 = MUX_A(CM_FXCOMCLKSEL2, 3), /*!< Attach FRO_HF_DIV to FLEXCOMM2. */
+
+ kFRO1M_to_FLEXCOMM2 = MUX_A(CM_FXCOMCLKSEL2, 4), /*!< Attach FRO1M to FLEXCOMM2. */
+
+ kMCLK_to_FLEXCOMM2 = MUX_A(CM_FXCOMCLKSEL2, 5), /*!< Attach MCLK to FLEXCOMM2. */
+
+ kOSC32K_to_FLEXCOMM2 = MUX_A(CM_FXCOMCLKSEL2, 6), /*!< Attach OSC32K to FLEXCOMM2. */
+
+ kNONE_to_FLEXCOMM2 = MUX_A(CM_FXCOMCLKSEL2, 7), /*!< Attach NONE to FLEXCOMM2. */
+
+ kMAIN_CLK_to_FLEXCOMM3 = MUX_A(CM_FXCOMCLKSEL3, 0), /*!< Attach MAIN_CLK to FLEXCOMM3. */
+
+ kPLL0_DIV_to_FLEXCOMM3 = MUX_A(CM_FXCOMCLKSEL3, 1), /*!< Attach PLL0_DIV to FLEXCOMM3. */
+
+ kFRO12M_to_FLEXCOMM3 = MUX_A(CM_FXCOMCLKSEL3, 2), /*!< Attach FRO12M to FLEXCOMM3. */
+
+ kFRO_HF_DIV_to_FLEXCOMM3 = MUX_A(CM_FXCOMCLKSEL3, 3), /*!< Attach FRO_HF_DIV to FLEXCOMM3. */
+
+ kFRO1M_to_FLEXCOMM3 = MUX_A(CM_FXCOMCLKSEL3, 4), /*!< Attach FRO1M to FLEXCOMM3. */
+
+ kMCLK_to_FLEXCOMM3 = MUX_A(CM_FXCOMCLKSEL3, 5), /*!< Attach MCLK to FLEXCOMM3. */
+
+ kOSC32K_to_FLEXCOMM3 = MUX_A(CM_FXCOMCLKSEL3, 6), /*!< Attach OSC32K to FLEXCOMM3. */
+
+ kNONE_to_FLEXCOMM3 = MUX_A(CM_FXCOMCLKSEL3, 7), /*!< Attach NONE to FLEXCOMM3. */
+
+ kMAIN_CLK_to_FLEXCOMM4 = MUX_A(CM_FXCOMCLKSEL4, 0), /*!< Attach MAIN_CLK to FLEXCOMM4. */
+
+ kPLL0_DIV_to_FLEXCOMM4 = MUX_A(CM_FXCOMCLKSEL4, 1), /*!< Attach PLL0_DIV to FLEXCOMM4. */
+
+ kFRO12M_to_FLEXCOMM4 = MUX_A(CM_FXCOMCLKSEL4, 2), /*!< Attach FRO12M to FLEXCOMM4. */
+
+ kFRO_HF_DIV_to_FLEXCOMM4 = MUX_A(CM_FXCOMCLKSEL4, 3), /*!< Attach FRO_HF_DIV to FLEXCOMM4. */
+
+ kFRO1M_to_FLEXCOMM4 = MUX_A(CM_FXCOMCLKSEL4, 4), /*!< Attach FRO1M to FLEXCOMM4. */
+
+ kMCLK_to_FLEXCOMM4 = MUX_A(CM_FXCOMCLKSEL4, 5), /*!< Attach MCLK to FLEXCOMM4. */
+
+ kOSC32K_to_FLEXCOMM4 = MUX_A(CM_FXCOMCLKSEL4, 6), /*!< Attach OSC32K to FLEXCOMM4. */
+
+ kNONE_to_FLEXCOMM4 = MUX_A(CM_FXCOMCLKSEL4, 7), /*!< Attach NONE to FLEXCOMM4. */
+
+ kMAIN_CLK_to_FLEXCOMM5 = MUX_A(CM_FXCOMCLKSEL5, 0), /*!< Attach MAIN_CLK to FLEXCOMM5. */
+
+ kPLL0_DIV_to_FLEXCOMM5 = MUX_A(CM_FXCOMCLKSEL5, 1), /*!< Attach PLL0_DIV to FLEXCOMM5. */
+
+ kFRO12M_to_FLEXCOMM5 = MUX_A(CM_FXCOMCLKSEL5, 2), /*!< Attach FRO12M to FLEXCOMM5. */
+
+ kFRO_HF_DIV_to_FLEXCOMM5 = MUX_A(CM_FXCOMCLKSEL5, 3), /*!< Attach FRO_HF_DIV to FLEXCOMM5. */
+
+ kFRO1M_to_FLEXCOMM5 = MUX_A(CM_FXCOMCLKSEL5, 4), /*!< Attach FRO1M to FLEXCOMM5. */
+
+ kMCLK_to_FLEXCOMM5 = MUX_A(CM_FXCOMCLKSEL5, 5), /*!< Attach MCLK to FLEXCOMM5. */
+
+ kOSC32K_to_FLEXCOMM5 = MUX_A(CM_FXCOMCLKSEL5, 6), /*!< Attach OSC32K to FLEXCOMM5. */
+
+ kNONE_to_FLEXCOMM5 = MUX_A(CM_FXCOMCLKSEL5, 7), /*!< Attach NONE to FLEXCOMM5. */
+
+ kMAIN_CLK_to_FLEXCOMM6 = MUX_A(CM_FXCOMCLKSEL6, 0), /*!< Attach MAIN_CLK to FLEXCOMM6. */
+
+ kPLL0_DIV_to_FLEXCOMM6 = MUX_A(CM_FXCOMCLKSEL6, 1), /*!< Attach PLL0_DIV to FLEXCOMM6. */
+
+ kFRO12M_to_FLEXCOMM6 = MUX_A(CM_FXCOMCLKSEL6, 2), /*!< Attach FRO12M to FLEXCOMM6. */
+
+ kFRO_HF_DIV_to_FLEXCOMM6 = MUX_A(CM_FXCOMCLKSEL6, 3), /*!< Attach FRO_HF_DIV to FLEXCOMM6. */
+
+ kFRO1M_to_FLEXCOMM6 = MUX_A(CM_FXCOMCLKSEL6, 4), /*!< Attach FRO1M to FLEXCOMM6. */
+
+ kMCLK_to_FLEXCOMM6 = MUX_A(CM_FXCOMCLKSEL6, 5), /*!< Attach MCLK to FLEXCOMM6. */
+
+ kOSC32K_to_FLEXCOMM6 = MUX_A(CM_FXCOMCLKSEL6, 6), /*!< Attach OSC32K to FLEXCOMM6. */
+
+ kNONE_to_FLEXCOMM6 = MUX_A(CM_FXCOMCLKSEL6, 7), /*!< Attach NONE to FLEXCOMM6. */
+
+ kMAIN_CLK_to_FLEXCOMM7 = MUX_A(CM_FXCOMCLKSEL7, 0), /*!< Attach MAIN_CLK to FLEXCOMM7. */
+
+ kPLL0_DIV_to_FLEXCOMM7 = MUX_A(CM_FXCOMCLKSEL7, 1), /*!< Attach PLL0_DIV to FLEXCOMM7. */
+
+ kFRO12M_to_FLEXCOMM7 = MUX_A(CM_FXCOMCLKSEL7, 2), /*!< Attach FRO12M to FLEXCOMM7. */
+
+ kFRO_HF_DIV_to_FLEXCOMM7 = MUX_A(CM_FXCOMCLKSEL7, 3), /*!< Attach FRO_HF_DIV to FLEXCOMM7. */
+
+ kFRO1M_to_FLEXCOMM7 = MUX_A(CM_FXCOMCLKSEL7, 4), /*!< Attach FRO1M to FLEXCOMM7. */
+
+ kMCLK_to_FLEXCOMM7 = MUX_A(CM_FXCOMCLKSEL7, 5), /*!< Attach MCLK to FLEXCOMM7. */
+
+ kOSC32K_to_FLEXCOMM7 = MUX_A(CM_FXCOMCLKSEL7, 6), /*!< Attach OSC32K to FLEXCOMM7. */
+
+ kNONE_to_FLEXCOMM7 = MUX_A(CM_FXCOMCLKSEL7, 7), /*!< Attach NONE to FLEXCOMM7. */
+
+ kMAIN_CLK_to_HSLSPI = MUX_A(CM_HSLSPICLKSEL, 0), /*!< Attach MAIN_CLK to HSLSPI. */
+
+ kPLL0_DIV_to_HSLSPI = MUX_A(CM_HSLSPICLKSEL, 1), /*!< Attach PLL0_DIV to HSLSPI. */
+
+ kFRO12M_to_HSLSPI = MUX_A(CM_HSLSPICLKSEL, 2), /*!< Attach FRO12M to HSLSPI. */
+
+ kFRO_HF_DIV_to_HSLSPI = MUX_A(CM_HSLSPICLKSEL, 3), /*!< Attach FRO_HF_DIV to HSLSPI. */
+
+ kFRO1M_to_HSLSPI = MUX_A(CM_HSLSPICLKSEL, 4), /*!< Attach FRO1M to HSLSPI. */
+
+ kOSC32K_to_HSLSPI = MUX_A(CM_HSLSPICLKSEL, 6), /*!< Attach OSC32K to HSLSPI. */
+
+ kNONE_to_HSLSPI = MUX_A(CM_HSLSPICLKSEL, 7), /*!< Attach NONE to HSLSPI. */
+
+ kFRO_HF_to_MCLK = MUX_A(CM_MCLKCLKSEL, 0), /*!< Attach FRO_HF to MCLK. */
+
+ kPLL0_to_MCLK = MUX_A(CM_MCLKCLKSEL, 1), /*!< Attach PLL0 to MCLK. */
+
+ kNONE_to_MCLK = MUX_A(CM_MCLKCLKSEL, 7), /*!< Attach NONE to MCLK. */
+
+ kMAIN_CLK_to_SCT_CLK = MUX_A(CM_SCTCLKSEL, 0), /*!< Attach MAIN_CLK to SCT_CLK. */
+
+ kPLL0_to_SCT_CLK = MUX_A(CM_SCTCLKSEL, 1), /*!< Attach PLL0 to SCT_CLK. */
+
+ kEXT_CLK_to_SCT_CLK = MUX_A(CM_SCTCLKSEL, 2), /*!< Attach EXT_CLK to SCT_CLK. */
+
+ kFRO_HF_to_SCT_CLK = MUX_A(CM_SCTCLKSEL, 3), /*!< Attach FRO_HF to SCT_CLK. */
+
+ kMCLK_to_SCT_CLK = MUX_A(CM_SCTCLKSEL, 5), /*!< Attach MCLK to SCT_CLK. */
+
+ kNONE_to_SCT_CLK = MUX_A(CM_SCTCLKSEL, 7), /*!< Attach NONE to SCT_CLK. */
+
+ kFRO32K_to_OSC32K = MUX_A(CM_RTCOSC32KCLKSEL, 0), /*!< Attach FRO32K to OSC32K. */
+
+ kXTAL32K_to_OSC32K = MUX_A(CM_RTCOSC32KCLKSEL, 1), /*!< Attach XTAL32K to OSC32K. */
+
+ kOSC32K_to_OSTIMER = MUX_A(CM_OSTIMERCLKSEL, 0), /*!< Attach OSC32K to OSTIMER. */
+
+ kFRO1M_to_OSTIMER = MUX_A(CM_OSTIMERCLKSEL, 1), /*!< Attach FRO1M to OSTIMER. */
+
+ kMAIN_CLK_to_OSTIMER = MUX_A(CM_OSTIMERCLKSEL, 2), /*!< Attach MAIN_CLK to OSTIMER. */
+
+ kTRACE_DIV_to_TRACE = MUX_A(CM_TRACECLKSEL, 0), /*!< Attach TRACE_DIV to TRACE. */
+
+ kFRO1M_to_TRACE = MUX_A(CM_TRACECLKSEL, 1), /*!< Attach FRO1M to TRACE. */
+
+ kOSC32K_to_TRACE = MUX_A(CM_TRACECLKSEL, 2), /*!< Attach OSC32K to TRACE. */
+
+ kNONE_to_TRACE = MUX_A(CM_TRACECLKSEL, 7), /*!< Attach NONE to TRACE. */
+
+ kSYSTICK_DIV0_to_SYSTICK0 = MUX_A(CM_SYSTICKCLKSEL0, 0), /*!< Attach SYSTICK_DIV0 to SYSTICK0. */
+
+ kFRO1M_to_SYSTICK0 = MUX_A(CM_SYSTICKCLKSEL0, 1), /*!< Attach FRO1M to SYSTICK0. */
+
+ kOSC32K_to_SYSTICK0 = MUX_A(CM_SYSTICKCLKSEL0, 2), /*!< Attach OSC32K to SYSTICK0. */
+
+ kNONE_to_SYSTICK0 = MUX_A(CM_SYSTICKCLKSEL0, 7), /*!< Attach NONE to SYSTICK0. */
+
+ kFRO12M_to_PLL1 = MUX_A(CM_PLL1CLKSEL, 0), /*!< Attach FRO12M to PLL1. */
+
+ kEXT_CLK_to_PLL1 = MUX_A(CM_PLL1CLKSEL, 1), /*!< Attach EXT_CLK to PLL1. */
+
+ kFRO1M_to_PLL1 = MUX_A(CM_PLL1CLKSEL, 2), /*!< Attach FRO1M to PLL1. */
+
+ kOSC32K_to_PLL1 = MUX_A(CM_PLL1CLKSEL, 3), /*!< Attach OSC32K to PLL1. */
+
+ kNONE_to_PLL1 = MUX_A(CM_PLL1CLKSEL, 7), /*!< Attach NONE to PLL1. */
+
+ kMAIN_CLK_to_CTIMER0 = MUX_A(CM_CTIMERCLKSEL0, 0), /*!< Attach MAIN_CLK to CTIMER0. */
+
+ kPLL0_to_CTIMER0 = MUX_A(CM_CTIMERCLKSEL0, 1), /*!< Attach PLL0 to CTIMER0. */
+
+ kFRO_HF_to_CTIMER0 = MUX_A(CM_CTIMERCLKSEL0, 3), /*!< Attach FRO_HF to CTIMER0. */
+
+ kFRO1M_to_CTIMER0 = MUX_A(CM_CTIMERCLKSEL0, 4), /*!< Attach FRO1M to CTIMER0. */
+
+ kMCLK_to_CTIMER0 = MUX_A(CM_CTIMERCLKSEL0, 5), /*!< Attach MCLK to CTIMER0. */
+
+ kOSC32K_to_CTIMER0 = MUX_A(CM_CTIMERCLKSEL0, 6), /*!< Attach OSC32K to CTIMER0. */
+
+ kNONE_to_CTIMER0 = MUX_A(CM_CTIMERCLKSEL0, 7), /*!< Attach NONE to CTIMER0. */
+
+ kMAIN_CLK_to_CTIMER1 = MUX_A(CM_CTIMERCLKSEL1, 0), /*!< Attach MAIN_CLK to CTIMER1. */
+
+ kPLL0_to_CTIMER1 = MUX_A(CM_CTIMERCLKSEL1, 1), /*!< Attach PLL0 to CTIMER1. */
+
+ kFRO_HF_to_CTIMER1 = MUX_A(CM_CTIMERCLKSEL1, 3), /*!< Attach FRO_HF to CTIMER1. */
+
+ kFRO1M_to_CTIMER1 = MUX_A(CM_CTIMERCLKSEL1, 4), /*!< Attach FRO1M to CTIMER1. */
+
+ kMCLK_to_CTIMER1 = MUX_A(CM_CTIMERCLKSEL1, 5), /*!< Attach MCLK to CTIMER1. */
+
+ kOSC32K_to_CTIMER1 = MUX_A(CM_CTIMERCLKSEL1, 6), /*!< Attach OSC32K to CTIMER1. */
+
+ kNONE_to_CTIMER1 = MUX_A(CM_CTIMERCLKSEL1, 7), /*!< Attach NONE to CTIMER1. */
+
+ kMAIN_CLK_to_CTIMER2 = MUX_A(CM_CTIMERCLKSEL2, 0), /*!< Attach MAIN_CLK to CTIMER2. */
+
+ kPLL0_to_CTIMER2 = MUX_A(CM_CTIMERCLKSEL2, 1), /*!< Attach PLL0 to CTIMER2. */
+
+ kFRO_HF_to_CTIMER2 = MUX_A(CM_CTIMERCLKSEL2, 3), /*!< Attach FRO_HF to CTIMER2. */
+
+ kFRO1M_to_CTIMER2 = MUX_A(CM_CTIMERCLKSEL2, 4), /*!< Attach FRO1M to CTIMER2. */
+
+ kMCLK_to_CTIMER2 = MUX_A(CM_CTIMERCLKSEL2, 5), /*!< Attach MCLK to CTIMER2. */
+
+ kOSC32K_to_CTIMER2 = MUX_A(CM_CTIMERCLKSEL2, 6), /*!< Attach OSC32K to CTIMER2. */
+
+ kNONE_to_CTIMER2 = MUX_A(CM_CTIMERCLKSEL2, 7), /*!< Attach NONE to CTIMER2. */
+
+ kMAIN_CLK_to_CTIMER3 = MUX_A(CM_CTIMERCLKSEL3, 0), /*!< Attach MAIN_CLK to CTIMER3. */
+
+ kPLL0_to_CTIMER3 = MUX_A(CM_CTIMERCLKSEL3, 1), /*!< Attach PLL0 to CTIMER3. */
+
+ kFRO_HF_to_CTIMER3 = MUX_A(CM_CTIMERCLKSEL3, 3), /*!< Attach FRO_HF to CTIMER3. */
+
+ kFRO1M_to_CTIMER3 = MUX_A(CM_CTIMERCLKSEL3, 4), /*!< Attach FRO1M to CTIMER3. */
+
+ kMCLK_to_CTIMER3 = MUX_A(CM_CTIMERCLKSEL3, 5), /*!< Attach MCLK to CTIMER3. */
+
+ kOSC32K_to_CTIMER3 = MUX_A(CM_CTIMERCLKSEL3, 6), /*!< Attach OSC32K to CTIMER3. */
+
+ kNONE_to_CTIMER3 = MUX_A(CM_CTIMERCLKSEL3, 7), /*!< Attach NONE to CTIMER3. */
+
+ kMAIN_CLK_to_CTIMER4 = MUX_A(CM_CTIMERCLKSEL4, 0), /*!< Attach MAIN_CLK to CTIMER4. */
+
+ kPLL0_to_CTIMER4 = MUX_A(CM_CTIMERCLKSEL4, 1), /*!< Attach PLL0 to CTIMER4. */
+
+ kFRO_HF_to_CTIMER4 = MUX_A(CM_CTIMERCLKSEL4, 3), /*!< Attach FRO_HF to CTIMER4. */
+
+ kFRO1M_to_CTIMER4 = MUX_A(CM_CTIMERCLKSEL4, 4), /*!< Attach FRO1M to CTIMER4. */
+
+ kMCLK_to_CTIMER4 = MUX_A(CM_CTIMERCLKSEL4, 5), /*!< Attach MCLK to CTIMER4. */
+
+ kOSC32K_to_CTIMER4 = MUX_A(CM_CTIMERCLKSEL4, 6), /*!< Attach OSC32K to CTIMER4. */
+
+ kNONE_to_CTIMER4 = MUX_A(CM_CTIMERCLKSEL4, 7), /*!< Attach NONE to CTIMER4. */
+
+ kNONE_to_NONE = (int)0x80000000U, /*!< Attach NONE to NONE. */
+
+} clock_attach_id_t;
+
+/*! @brief Clock dividers */
+typedef enum _clock_div_name
+{
+ kCLOCK_DivSystickClk0 = 0, /*!< Systick Clk0 Divider. */
+
+ kCLOCK_DivArmTrClkDiv = 2, /*!< Arm Tr Clk Div Divider. */
+
+ kCLOCK_DivCanClk = 3, /*!< Can Clock Divider. */
+
+ kCLOCK_DivFlexFrg0 = 8, /*!< Flex Frg0 Divider. */
+
+ kCLOCK_DivFlexFrg1 = 9, /*!< Flex Frg1 Divider. */
+
+ kCLOCK_DivFlexFrg2 = 10, /*!< Flex Frg2 Divider. */
+
+ kCLOCK_DivFlexFrg3 = 11, /*!< Flex Frg3 Divider. */
+
+ kCLOCK_DivFlexFrg4 = 12, /*!< Flex Frg4 Divider. */
+
+ kCLOCK_DivFlexFrg5 = 13, /*!< Flex Frg5 Divider. */
+
+ kCLOCK_DivFlexFrg6 = 14, /*!< Flex Frg6 Divider. */
+
+ kCLOCK_DivFlexFrg7 = 15, /*!< Flex Frg7 Divider. */
+
+ kCLOCK_DivAhbClk = 32, /*!< Ahb Clock Divider. */
+
+ kCLOCK_DivClkOut = 33, /*!< Clk Out Divider. */
+
+ kCLOCK_DivFrohfClk = 34, /*!< Frohf Clock Divider. */
+
+ kCLOCK_DivWdtClk = 35, /*!< Wdt Clock Divider. */
+
+ kCLOCK_DivAdcAsyncClk = 37, /*!< Adc Async Clock Divider. */
+
+ kCLOCK_DivUsb0Clk = 38, /*!< Usb0 Clock Divider. */
+
+ kCLOCK_DivFro1mClk = 40, /*!< Fro1m Clock Divider. */
+
+ kCLOCK_DivMClk = 43, /*!< I2S MCLK Clock Divider. */
+
+ kCLOCK_DivSctClk = 45, /*!< Sct Clock Divider. */
+
+ kCLOCK_DivPll0Clk = 49 /*!< PLL clock divider. */
+} clock_div_name_t;
+
+/*******************************************************************************
+ * API
+ ******************************************************************************/
+
+#if defined(__cplusplus)
+extern "C" {
+#endif /* __cplusplus */
+
+/**
+ * @brief Enable the clock for specific IP.
+ * @param clk : Clock to be enabled.
+ * @return Nothing
+ */
+static inline void CLOCK_EnableClock(clock_ip_name_t clk)
+{
+ uint32_t index = CLK_GATE_ABSTRACT_REG_OFFSET(clk);
+ SYSCON->AHBCLKCTRLSET[index] = (1UL << CLK_GATE_ABSTRACT_BITS_SHIFT(clk));
+}
+/**
+ * @brief Disable the clock for specific IP.
+ * @param clk : Clock to be Disabled.
+ * @return Nothing
+ */
+static inline void CLOCK_DisableClock(clock_ip_name_t clk)
+{
+ uint32_t index = CLK_GATE_ABSTRACT_REG_OFFSET(clk);
+ SYSCON->AHBCLKCTRLCLR[index] = (1UL << CLK_GATE_ABSTRACT_BITS_SHIFT(clk));
+}
+/**
+ * @brief Initialize the Core clock to given frequency (12, 48 or 96 MHz).
+ * Turns on FRO and uses default CCO, if freq is 12000000, then high speed output is off, else high speed output is
+ * enabled.
+ * @param iFreq : Desired frequency (must be one of CLK_FRO_12MHZ or CLK_FRO_48MHZ or CLK_FRO_96MHZ)
+ * @return returns success or fail status.
+ */
+status_t CLOCK_SetupFROClocking(uint32_t iFreq);
+/**
+ * @brief Set the flash wait states for the input freuqency.
+ * @param system_freq_hz : Input frequency
+ * @return Nothing
+ */
+void CLOCK_SetFLASHAccessCyclesForFreq(uint32_t system_freq_hz);
+/**
+ * @brief Initialize the external osc clock to given frequency.
+ * @param iFreq : Desired frequency (must be equal to exact rate in Hz)
+ * @return returns success or fail status.
+ */
+status_t CLOCK_SetupExtClocking(uint32_t iFreq);
+/**
+ * @brief Initialize the I2S MCLK clock to given frequency.
+ * @param iFreq : Desired frequency (must be equal to exact rate in Hz)
+ * @return returns success or fail status.
+ */
+status_t CLOCK_SetupI2SMClkClocking(uint32_t iFreq);
+/**
+ * @brief Initialize the PLU CLKIN clock to given frequency.
+ * @param iFreq : Desired frequency (must be equal to exact rate in Hz)
+ * @return returns success or fail status.
+ */
+status_t CLOCK_SetupPLUClkInClocking(uint32_t iFreq);
+/**
+ * @brief Configure the clock selection muxes.
+ * @param connection : Clock to be configured.
+ * @return Nothing
+ */
+void CLOCK_AttachClk(clock_attach_id_t connection);
+/**
+ * @brief Get the actual clock attach id.
+ * This fuction uses the offset in input attach id, then it reads the actual source value in
+ * the register and combine the offset to obtain an actual attach id.
+ * @param attachId : Clock attach id to get.
+ * @return Clock source value.
+ */
+clock_attach_id_t CLOCK_GetClockAttachId(clock_attach_id_t attachId);
+/**
+ * @brief Setup peripheral clock dividers.
+ * @param div_name : Clock divider name
+ * @param divided_by_value: Value to be divided
+ * @param reset : Whether to reset the divider counter.
+ * @return Nothing
+ */
+void CLOCK_SetClkDiv(clock_div_name_t div_name, uint32_t divided_by_value, bool reset);
+/**
+ * @brief Setup rtc 1khz clock divider.
+ * @param divided_by_value: Value to be divided
+ * @return Nothing
+ */
+void CLOCK_SetRtc1khzClkDiv(uint32_t divided_by_value);
+/**
+ * @brief Setup rtc 1hz clock divider.
+ * @param divided_by_value: Value to be divided
+ * @return Nothing
+ */
+void CLOCK_SetRtc1hzClkDiv(uint32_t divided_by_value);
+
+/**
+ * @brief Set the flexcomm output frequency.
+ * @param id : flexcomm instance id
+ * @param freq : output frequency
+ * @return 0 : the frequency range is out of range.
+ * 1 : switch successfully.
+ */
+uint32_t CLOCK_SetFlexCommClock(uint32_t id, uint32_t freq);
+
+/*! @brief Return Frequency of flexcomm input clock
+ * @param id : flexcomm instance id
+ * @return Frequency value
+ */
+uint32_t CLOCK_GetFlexCommInputClock(uint32_t id);
+
+/*! @brief Return Frequency of selected clock
+ * @return Frequency of selected clock
+ */
+uint32_t CLOCK_GetFreq(clock_name_t clockName);
+/*! @brief Return Frequency of FRO 12MHz
+ * @return Frequency of FRO 12MHz
+ */
+uint32_t CLOCK_GetFro12MFreq(void);
+/*! @brief Return Frequency of FRO 1MHz
+ * @return Frequency of FRO 1MHz
+ */
+uint32_t CLOCK_GetFro1MFreq(void);
+/*! @brief Return Frequency of ClockOut
+ * @return Frequency of ClockOut
+ */
+uint32_t CLOCK_GetClockOutClkFreq(void);
+/*! @brief Return Frequency of Can Clock
+ * @return Frequency of Can.
+ */
+uint32_t CLOCK_GetMCanClkFreq(void);
+/*! @brief Return Frequency of Adc Clock
+ * @return Frequency of Adc.
+ */
+uint32_t CLOCK_GetAdcClkFreq(void);
+/*! @brief Return Frequency of Usb0 Clock
+ * @return Frequency of Usb0 Clock.
+ */
+uint32_t CLOCK_GetUsb0ClkFreq(void);
+/*! @brief Return Frequency of Usb1 Clock
+ * @return Frequency of Usb1 Clock.
+ */
+uint32_t CLOCK_GetUsb1ClkFreq(void);
+/*! @brief Return Frequency of MClk Clock
+ * @return Frequency of MClk Clock.
+ */
+uint32_t CLOCK_GetMclkClkFreq(void);
+/*! @brief Return Frequency of SCTimer Clock
+ * @return Frequency of SCTimer Clock.
+ */
+uint32_t CLOCK_GetSctClkFreq(void);
+/*! @brief Return Frequency of External Clock
+ * @return Frequency of External Clock. If no external clock is used returns 0.
+ */
+uint32_t CLOCK_GetExtClkFreq(void);
+/*! @brief Return Frequency of Watchdog
+ * @return Frequency of Watchdog
+ */
+uint32_t CLOCK_GetWdtClkFreq(void);
+/*! @brief Return Frequency of High-Freq output of FRO
+ * @return Frequency of High-Freq output of FRO
+ */
+uint32_t CLOCK_GetFroHfFreq(void);
+/*! @brief Return Frequency of PLL
+ * @return Frequency of PLL
+ */
+uint32_t CLOCK_GetPll0OutFreq(void);
+/*! @brief Return Frequency of USB PLL
+ * @return Frequency of PLL
+ */
+uint32_t CLOCK_GetPll1OutFreq(void);
+/*! @brief Return Frequency of 32kHz osc
+ * @return Frequency of 32kHz osc
+ */
+uint32_t CLOCK_GetOsc32KFreq(void);
+/*! @brief Return Frequency of Core System
+ * @return Frequency of Core System
+ */
+uint32_t CLOCK_GetCoreSysClkFreq(void);
+/*! @brief Return Frequency of I2S MCLK Clock
+ * @return Frequency of I2S MCLK Clock
+ */
+uint32_t CLOCK_GetI2SMClkFreq(void);
+/*! @brief Return Frequency of PLU CLKIN Clock
+ * @return Frequency of PLU CLKIN Clock
+ */
+uint32_t CLOCK_GetPLUClkInFreq(void);
+/*! @brief Return Frequency of FlexComm Clock
+ * @return Frequency of FlexComm Clock
+ */
+uint32_t CLOCK_GetFlexCommClkFreq(uint32_t id);
+/*! @brief Return Frequency of High speed SPI Clock
+ * @return Frequency of High speed SPI Clock
+ */
+uint32_t CLOCK_GetHsLspiClkFreq(void);
+/*! @brief Return Frequency of CTimer functional Clock
+ * @return Frequency of CTimer functional Clock
+ */
+uint32_t CLOCK_GetCTimerClkFreq(uint32_t id);
+/*! @brief Return Frequency of SystickClock
+ * @return Frequency of Systick Clock
+ */
+uint32_t CLOCK_GetSystickClkFreq(uint32_t id);
+
+/*! @brief Return PLL0 input clock rate
+ * @return PLL0 input clock rate
+ */
+uint32_t CLOCK_GetPLL0InClockRate(void);
+
+/*! @brief Return PLL1 input clock rate
+ * @return PLL1 input clock rate
+ */
+uint32_t CLOCK_GetPLL1InClockRate(void);
+
+/*! @brief Return PLL0 output clock rate
+ * @param recompute : Forces a PLL rate recomputation if true
+ * @return PLL0 output clock rate
+ * @note The PLL rate is cached in the driver in a variable as
+ * the rate computation function can take some time to perform. It
+ * is recommended to use 'false' with the 'recompute' parameter.
+ */
+uint32_t CLOCK_GetPLL0OutClockRate(bool recompute);
+
+/*! @brief Return PLL1 output clock rate
+ * @param recompute : Forces a PLL rate recomputation if true
+ * @return PLL1 output clock rate
+ * @note The PLL rate is cached in the driver in a variable as
+ * the rate computation function can take some time to perform. It
+ * is recommended to use 'false' with the 'recompute' parameter.
+ */
+uint32_t CLOCK_GetPLL1OutClockRate(bool recompute);
+
+/*! @brief Enables and disables PLL0 bypass mode
+ * @brief bypass : true to bypass PLL0 (PLL0 output = PLL0 input, false to disable bypass
+ * @return PLL0 output clock rate
+ */
+__STATIC_INLINE void CLOCK_SetBypassPLL0(bool bypass)
+{
+ if (bypass)
+ {
+ SYSCON->PLL0CTRL |= (1UL << SYSCON_PLL0CTRL_BYPASSPLL_SHIFT);
+ }
+ else
+ {
+ SYSCON->PLL0CTRL &= ~(1UL << SYSCON_PLL0CTRL_BYPASSPLL_SHIFT);
+ }
+}
+
+/*! @brief Enables and disables PLL1 bypass mode
+ * @brief bypass : true to bypass PLL1 (PLL1 output = PLL1 input, false to disable bypass
+ * @return PLL1 output clock rate
+ */
+__STATIC_INLINE void CLOCK_SetBypassPLL1(bool bypass)
+{
+ if (bypass)
+ {
+ SYSCON->PLL1CTRL |= (1UL << SYSCON_PLL1CTRL_BYPASSPLL_SHIFT);
+ }
+ else
+ {
+ SYSCON->PLL1CTRL &= ~(1UL << SYSCON_PLL1CTRL_BYPASSPLL_SHIFT);
+ }
+}
+
+/*! @brief Check if PLL is locked or not
+ * @return true if the PLL is locked, false if not locked
+ */
+__STATIC_INLINE bool CLOCK_IsPLL0Locked(void)
+{
+ return (bool)((SYSCON->PLL0STAT & SYSCON_PLL0STAT_LOCK_MASK) != 0UL);
+}
+
+/*! @brief Check if PLL1 is locked or not
+ * @return true if the PLL1 is locked, false if not locked
+ */
+__STATIC_INLINE bool CLOCK_IsPLL1Locked(void)
+{
+ return (bool)((SYSCON->PLL1STAT & SYSCON_PLL1STAT_LOCK_MASK) != 0UL);
+}
+
+/*! @brief Store the current PLL0 rate
+ * @param rate: Current rate of the PLL0
+ * @return Nothing
+ **/
+void CLOCK_SetStoredPLL0ClockRate(uint32_t rate);
+
+/*! @brief PLL configuration structure flags for 'flags' field
+ * These flags control how the PLL configuration function sets up the PLL setup structure.
+ *
+ * When the PLL_CONFIGFLAG_USEINRATE flag is selected, the 'InputRate' field in the
+ * configuration structure must be assigned with the expected PLL frequency. If the
+ * PLL_CONFIGFLAG_USEINRATE is not used, 'InputRate' is ignored in the configuration
+ * function and the driver will determine the PLL rate from the currently selected
+ * PLL source. This flag might be used to configure the PLL input clock more accurately
+ * when using the WDT oscillator or a more dyanmic CLKIN source.
+ *
+ * When the PLL_CONFIGFLAG_FORCENOFRACT flag is selected, the PLL hardware for the
+ * automatic bandwidth selection, Spread Spectrum (SS) support, and fractional M-divider
+ * are not used.
+ */
+#define PLL_CONFIGFLAG_USEINRATE (1U << 0U) /*!< Flag to use InputRate in PLL configuration structure for setup */
+#define PLL_CONFIGFLAG_FORCENOFRACT (1U << 2U)
+/*!< Force non-fractional output mode, PLL output will not use the fractional, automatic bandwidth, or SS hardware */
+
+/*! @brief PLL Spread Spectrum (SS) Programmable modulation frequency
+ * See (MF) field in the PLL0SSCG1 register in the UM.
+ */
+typedef enum _ss_progmodfm
+{
+ kSS_MF_512 = (0 << 20), /*!< Nss = 512 (fm ? 3.9 - 7.8 kHz) */
+ kSS_MF_384 = (1 << 20), /*!< Nss ?= 384 (fm ? 5.2 - 10.4 kHz) */
+ kSS_MF_256 = (2 << 20), /*!< Nss = 256 (fm ? 7.8 - 15.6 kHz) */
+ kSS_MF_128 = (3 << 20), /*!< Nss = 128 (fm ? 15.6 - 31.3 kHz) */
+ kSS_MF_64 = (4 << 20), /*!< Nss = 64 (fm ? 32.3 - 64.5 kHz) */
+ kSS_MF_32 = (5 << 20), /*!< Nss = 32 (fm ? 62.5- 125 kHz) */
+ kSS_MF_24 = (6 << 20), /*!< Nss ?= 24 (fm ? 83.3- 166.6 kHz) */
+ kSS_MF_16 = (7 << 20) /*!< Nss = 16 (fm ? 125- 250 kHz) */
+} ss_progmodfm_t;
+
+/*! @brief PLL Spread Spectrum (SS) Programmable frequency modulation depth
+ * See (MR) field in the PLL0SSCG1 register in the UM.
+ */
+typedef enum _ss_progmoddp
+{
+ kSS_MR_K0 = (0 << 23), /*!< k = 0 (no spread spectrum) */
+ kSS_MR_K1 = (1 << 23), /*!< k = 1 */
+ kSS_MR_K1_5 = (2 << 23), /*!< k = 1.5 */
+ kSS_MR_K2 = (3 << 23), /*!< k = 2 */
+ kSS_MR_K3 = (4 << 23), /*!< k = 3 */
+ kSS_MR_K4 = (5 << 23), /*!< k = 4 */
+ kSS_MR_K6 = (6 << 23), /*!< k = 6 */
+ kSS_MR_K8 = (7 << 23) /*!< k = 8 */
+} ss_progmoddp_t;
+
+/*! @brief PLL Spread Spectrum (SS) Modulation waveform control
+ * See (MC) field in the PLL0SSCG1 register in the UM.
+ * Compensation for low pass filtering of the PLL to get a triangular
+ * modulation at the output of the PLL, giving a flat frequency spectrum.
+ */
+typedef enum _ss_modwvctrl
+{
+ kSS_MC_NOC = (0 << 26), /*!< no compensation */
+ kSS_MC_RECC = (2 << 26), /*!< recommended setting */
+ kSS_MC_MAXC = (3 << 26), /*!< max. compensation */
+} ss_modwvctrl_t;
+
+/*! @brief PLL configuration structure
+ *
+ * This structure can be used to configure the settings for a PLL
+ * setup structure. Fill in the desired configuration for the PLL
+ * and call the PLL setup function to fill in a PLL setup structure.
+ */
+typedef struct _pll_config
+{
+ uint32_t desiredRate; /*!< Desired PLL rate in Hz */
+ uint32_t inputRate; /*!< PLL input clock in Hz, only used if PLL_CONFIGFLAG_USEINRATE flag is set */
+ uint32_t flags; /*!< PLL configuration flags, Or'ed value of PLL_CONFIGFLAG_* definitions */
+ ss_progmodfm_t ss_mf; /*!< SS Programmable modulation frequency, only applicable when not using
+ PLL_CONFIGFLAG_FORCENOFRACT flag */
+ ss_progmoddp_t ss_mr; /*!< SS Programmable frequency modulation depth, only applicable when not using
+ PLL_CONFIGFLAG_FORCENOFRACT flag */
+ ss_modwvctrl_t
+ ss_mc; /*!< SS Modulation waveform control, only applicable when not using PLL_CONFIGFLAG_FORCENOFRACT flag */
+ bool mfDither; /*!< false for fixed modulation frequency or true for dithering, only applicable when not using
+ PLL_CONFIGFLAG_FORCENOFRACT flag */
+
+} pll_config_t;
+
+/*! @brief PLL setup structure flags for 'flags' field
+ * These flags control how the PLL setup function sets up the PLL
+ */
+#define PLL_SETUPFLAG_POWERUP (1U << 0U) /*!< Setup will power on the PLL after setup */
+#define PLL_SETUPFLAG_WAITLOCK (1U << 1U) /*!< Setup will wait for PLL lock, implies the PLL will be pwoered on */
+#define PLL_SETUPFLAG_ADGVOLT (1U << 2U) /*!< Optimize system voltage for the new PLL rate */
+#define PLL_SETUPFLAG_USEFEEDBACKDIV2 (1U << 3U) /*!< Use feedback divider by 2 in divider path */
+
+/*! @brief PLL0 setup structure
+ * This structure can be used to pre-build a PLL setup configuration
+ * at run-time and quickly set the PLL to the configuration. It can be
+ * populated with the PLL setup function. If powering up or waiting
+ * for PLL lock, the PLL input clock source should be configured prior
+ * to PLL setup.
+ */
+typedef struct _pll_setup
+{
+ uint32_t pllctrl; /*!< PLL control register PLL0CTRL */
+ uint32_t pllndec; /*!< PLL NDEC register PLL0NDEC */
+ uint32_t pllpdec; /*!< PLL PDEC register PLL0PDEC */
+ uint32_t pllmdec; /*!< PLL MDEC registers PLL0PDEC */
+ uint32_t pllsscg[2]; /*!< PLL SSCTL registers PLL0SSCG*/
+ uint32_t pllRate; /*!< Acutal PLL rate */
+ uint32_t flags; /*!< PLL setup flags, Or'ed value of PLL_SETUPFLAG_* definitions */
+} pll_setup_t;
+
+/*! @brief PLL status definitions
+ */
+typedef enum _pll_error
+{
+ kStatus_PLL_Success = MAKE_STATUS(kStatusGroup_Generic, 0), /*!< PLL operation was successful */
+ kStatus_PLL_OutputTooLow = MAKE_STATUS(kStatusGroup_Generic, 1), /*!< PLL output rate request was too low */
+ kStatus_PLL_OutputTooHigh = MAKE_STATUS(kStatusGroup_Generic, 2), /*!< PLL output rate request was too high */
+ kStatus_PLL_InputTooLow = MAKE_STATUS(kStatusGroup_Generic, 3), /*!< PLL input rate is too low */
+ kStatus_PLL_InputTooHigh = MAKE_STATUS(kStatusGroup_Generic, 4), /*!< PLL input rate is too high */
+ kStatus_PLL_OutsideIntLimit = MAKE_STATUS(kStatusGroup_Generic, 5), /*!< Requested output rate isn't possible */
+ kStatus_PLL_CCOTooLow = MAKE_STATUS(kStatusGroup_Generic, 6), /*!< Requested CCO rate isn't possible */
+ kStatus_PLL_CCOTooHigh = MAKE_STATUS(kStatusGroup_Generic, 7) /*!< Requested CCO rate isn't possible */
+} pll_error_t;
+
+/*! @brief USB FS clock source definition. */
+typedef enum _clock_usbfs_src
+{
+ kCLOCK_UsbfsSrcFro = (uint32_t)kCLOCK_FroHf, /*!< Use FRO 96 MHz. */
+ kCLOCK_UsbfsSrcPll0 = (uint32_t)kCLOCK_Pll0Out, /*!< Use PLL0 output. */
+ kCLOCK_UsbfsSrcMainClock = (uint32_t)kCLOCK_CoreSysClk, /*!< Use Main clock. */
+ kCLOCK_UsbfsSrcPll1 = (uint32_t)kCLOCK_Pll1Out, /*!< Use PLL1 clock. */
+
+ kCLOCK_UsbfsSrcNone =
+ SYSCON_USB0CLKSEL_SEL(7) /*! SIZE_MAX - alignbytes - sizeof(mem_align_cb_t))
+ {
+ return NULL;
+ }
+
+ alignedsize += alignbytes + sizeof(mem_align_cb_t);
+
+ union
+ {
+ void *pointer_value;
+#if (defined(__DSC__) && defined(__CW__))
+ uint32_t unsigned_value;
+#else
+ uintptr_t unsigned_value;
+#endif
+ } p_align_addr, p_addr;
+
+ p_addr.pointer_value = malloc(alignedsize);
+
+ if (p_addr.pointer_value == NULL)
+ {
+ return NULL;
+ }
+
+ p_align_addr.unsigned_value = SDK_SIZEALIGN(p_addr.unsigned_value + sizeof(mem_align_cb_t), alignbytes);
+
+ p_cb = (mem_align_cb_t *)(p_align_addr.unsigned_value - 4U);
+ p_cb->identifier = SDK_MEM_MAGIC_NUMBER;
+ p_cb->offset = (uint16_t)(p_align_addr.unsigned_value - p_addr.unsigned_value);
+
+ return p_align_addr.pointer_value;
+}
+
+void SDK_Free(void *ptr)
+{
+ union
+ {
+ void *pointer_value;
+#if (defined(__DSC__) && defined(__CW__))
+ uint32_t unsigned_value;
+#else
+ uintptr_t unsigned_value;
+#endif
+ } p_free;
+ p_free.pointer_value = ptr;
+ mem_align_cb_t *p_cb = (mem_align_cb_t *)(p_free.unsigned_value - 4U);
+
+ if (p_cb->identifier != SDK_MEM_MAGIC_NUMBER)
+ {
+ return;
+ }
+
+ p_free.unsigned_value = p_free.unsigned_value - p_cb->offset;
+
+ free(p_free.pointer_value);
+}
diff --git a/drivers/fsl_common.h b/drivers/fsl_common.h
new file mode 100644
index 0000000..ddf49d6
--- /dev/null
+++ b/drivers/fsl_common.h
@@ -0,0 +1,309 @@
+/*
+ * Copyright (c) 2015-2016, Freescale Semiconductor, Inc.
+ * Copyright 2016-2021 NXP
+ * All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef _FSL_COMMON_H_
+#define _FSL_COMMON_H_
+
+#include
+#include
+#include
+#include
+#include
+
+#if defined(__ICCARM__) || (defined(__CC_ARM) || defined(__ARMCC_VERSION)) || defined(__GNUC__)
+#include
+#endif
+
+#include "fsl_device_registers.h"
+
+/*!
+ * @addtogroup ksdk_common
+ * @{
+ */
+
+/*******************************************************************************
+ * Configurations
+ ******************************************************************************/
+
+/*! @brief Macro to use the default weak IRQ handler in drivers. */
+#ifndef FSL_DRIVER_TRANSFER_DOUBLE_WEAK_IRQ
+#define FSL_DRIVER_TRANSFER_DOUBLE_WEAK_IRQ 1
+#endif
+
+/*******************************************************************************
+ * Definitions
+ ******************************************************************************/
+
+/*! @brief Construct a status code value from a group and code number. */
+#define MAKE_STATUS(group, code) ((((group)*100L) + (code)))
+
+/*! @brief Construct the version number for drivers.
+ *
+ * The driver version is a 32-bit number, for both 32-bit platforms(such as Cortex M)
+ * and 16-bit platforms(such as DSC).
+ *
+ * @verbatim
+
+ | Unused || Major Version || Minor Version || Bug Fix |
+ 31 25 24 17 16 9 8 0
+
+ @endverbatim
+ */
+#define MAKE_VERSION(major, minor, bugfix) (((major) * 65536L) + ((minor) * 256L) + (bugfix))
+
+/*! @name Driver version */
+/*@{*/
+/*! @brief common driver version. */
+#define FSL_COMMON_DRIVER_VERSION (MAKE_VERSION(2, 3, 1))
+/*@}*/
+
+/* Debug console type definition. */
+#define DEBUG_CONSOLE_DEVICE_TYPE_NONE 0U /*!< No debug console. */
+#define DEBUG_CONSOLE_DEVICE_TYPE_UART 1U /*!< Debug console based on UART. */
+#define DEBUG_CONSOLE_DEVICE_TYPE_LPUART 2U /*!< Debug console based on LPUART. */
+#define DEBUG_CONSOLE_DEVICE_TYPE_LPSCI 3U /*!< Debug console based on LPSCI. */
+#define DEBUG_CONSOLE_DEVICE_TYPE_USBCDC 4U /*!< Debug console based on USBCDC. */
+#define DEBUG_CONSOLE_DEVICE_TYPE_FLEXCOMM 5U /*!< Debug console based on FLEXCOMM. */
+#define DEBUG_CONSOLE_DEVICE_TYPE_IUART 6U /*!< Debug console based on i.MX UART. */
+#define DEBUG_CONSOLE_DEVICE_TYPE_VUSART 7U /*!< Debug console based on LPC_VUSART. */
+#define DEBUG_CONSOLE_DEVICE_TYPE_MINI_USART 8U /*!< Debug console based on LPC_USART. */
+#define DEBUG_CONSOLE_DEVICE_TYPE_SWO 9U /*!< Debug console based on SWO. */
+#define DEBUG_CONSOLE_DEVICE_TYPE_QSCI 10U /*!< Debug console based on QSCI. */
+
+/*! @brief Status group numbers. */
+enum _status_groups
+{
+ kStatusGroup_Generic = 0, /*!< Group number for generic status codes. */
+ kStatusGroup_FLASH = 1, /*!< Group number for FLASH status codes. */
+ kStatusGroup_LPSPI = 4, /*!< Group number for LPSPI status codes. */
+ kStatusGroup_FLEXIO_SPI = 5, /*!< Group number for FLEXIO SPI status codes. */
+ kStatusGroup_DSPI = 6, /*!< Group number for DSPI status codes. */
+ kStatusGroup_FLEXIO_UART = 7, /*!< Group number for FLEXIO UART status codes. */
+ kStatusGroup_FLEXIO_I2C = 8, /*!< Group number for FLEXIO I2C status codes. */
+ kStatusGroup_LPI2C = 9, /*!< Group number for LPI2C status codes. */
+ kStatusGroup_UART = 10, /*!< Group number for UART status codes. */
+ kStatusGroup_I2C = 11, /*!< Group number for UART status codes. */
+ kStatusGroup_LPSCI = 12, /*!< Group number for LPSCI status codes. */
+ kStatusGroup_LPUART = 13, /*!< Group number for LPUART status codes. */
+ kStatusGroup_SPI = 14, /*!< Group number for SPI status code.*/
+ kStatusGroup_XRDC = 15, /*!< Group number for XRDC status code.*/
+ kStatusGroup_SEMA42 = 16, /*!< Group number for SEMA42 status code.*/
+ kStatusGroup_SDHC = 17, /*!< Group number for SDHC status code */
+ kStatusGroup_SDMMC = 18, /*!< Group number for SDMMC status code */
+ kStatusGroup_SAI = 19, /*!< Group number for SAI status code */
+ kStatusGroup_MCG = 20, /*!< Group number for MCG status codes. */
+ kStatusGroup_SCG = 21, /*!< Group number for SCG status codes. */
+ kStatusGroup_SDSPI = 22, /*!< Group number for SDSPI status codes. */
+ kStatusGroup_FLEXIO_I2S = 23, /*!< Group number for FLEXIO I2S status codes */
+ kStatusGroup_FLEXIO_MCULCD = 24, /*!< Group number for FLEXIO LCD status codes */
+ kStatusGroup_FLASHIAP = 25, /*!< Group number for FLASHIAP status codes */
+ kStatusGroup_FLEXCOMM_I2C = 26, /*!< Group number for FLEXCOMM I2C status codes */
+ kStatusGroup_I2S = 27, /*!< Group number for I2S status codes */
+ kStatusGroup_IUART = 28, /*!< Group number for IUART status codes */
+ kStatusGroup_CSI = 29, /*!< Group number for CSI status codes */
+ kStatusGroup_MIPI_DSI = 30, /*!< Group number for MIPI DSI status codes */
+ kStatusGroup_SDRAMC = 35, /*!< Group number for SDRAMC status codes. */
+ kStatusGroup_POWER = 39, /*!< Group number for POWER status codes. */
+ kStatusGroup_ENET = 40, /*!< Group number for ENET status codes. */
+ kStatusGroup_PHY = 41, /*!< Group number for PHY status codes. */
+ kStatusGroup_TRGMUX = 42, /*!< Group number for TRGMUX status codes. */
+ kStatusGroup_SMARTCARD = 43, /*!< Group number for SMARTCARD status codes. */
+ kStatusGroup_LMEM = 44, /*!< Group number for LMEM status codes. */
+ kStatusGroup_QSPI = 45, /*!< Group number for QSPI status codes. */
+ kStatusGroup_DMA = 50, /*!< Group number for DMA status codes. */
+ kStatusGroup_EDMA = 51, /*!< Group number for EDMA status codes. */
+ kStatusGroup_DMAMGR = 52, /*!< Group number for DMAMGR status codes. */
+ kStatusGroup_FLEXCAN = 53, /*!< Group number for FlexCAN status codes. */
+ kStatusGroup_LTC = 54, /*!< Group number for LTC status codes. */
+ kStatusGroup_FLEXIO_CAMERA = 55, /*!< Group number for FLEXIO CAMERA status codes. */
+ kStatusGroup_LPC_SPI = 56, /*!< Group number for LPC_SPI status codes. */
+ kStatusGroup_LPC_USART = 57, /*!< Group number for LPC_USART status codes. */
+ kStatusGroup_DMIC = 58, /*!< Group number for DMIC status codes. */
+ kStatusGroup_SDIF = 59, /*!< Group number for SDIF status codes.*/
+ kStatusGroup_SPIFI = 60, /*!< Group number for SPIFI status codes. */
+ kStatusGroup_OTP = 61, /*!< Group number for OTP status codes. */
+ kStatusGroup_MCAN = 62, /*!< Group number for MCAN status codes. */
+ kStatusGroup_CAAM = 63, /*!< Group number for CAAM status codes. */
+ kStatusGroup_ECSPI = 64, /*!< Group number for ECSPI status codes. */
+ kStatusGroup_USDHC = 65, /*!< Group number for USDHC status codes.*/
+ kStatusGroup_LPC_I2C = 66, /*!< Group number for LPC_I2C status codes.*/
+ kStatusGroup_DCP = 67, /*!< Group number for DCP status codes.*/
+ kStatusGroup_MSCAN = 68, /*!< Group number for MSCAN status codes.*/
+ kStatusGroup_ESAI = 69, /*!< Group number for ESAI status codes. */
+ kStatusGroup_FLEXSPI = 70, /*!< Group number for FLEXSPI status codes. */
+ kStatusGroup_MMDC = 71, /*!< Group number for MMDC status codes. */
+ kStatusGroup_PDM = 72, /*!< Group number for MIC status codes. */
+ kStatusGroup_SDMA = 73, /*!< Group number for SDMA status codes. */
+ kStatusGroup_ICS = 74, /*!< Group number for ICS status codes. */
+ kStatusGroup_SPDIF = 75, /*!< Group number for SPDIF status codes. */
+ kStatusGroup_LPC_MINISPI = 76, /*!< Group number for LPC_MINISPI status codes. */
+ kStatusGroup_HASHCRYPT = 77, /*!< Group number for Hashcrypt status codes */
+ kStatusGroup_LPC_SPI_SSP = 78, /*!< Group number for LPC_SPI_SSP status codes. */
+ kStatusGroup_I3C = 79, /*!< Group number for I3C status codes */
+ kStatusGroup_LPC_I2C_1 = 97, /*!< Group number for LPC_I2C_1 status codes. */
+ kStatusGroup_NOTIFIER = 98, /*!< Group number for NOTIFIER status codes. */
+ kStatusGroup_DebugConsole = 99, /*!< Group number for debug console status codes. */
+ kStatusGroup_SEMC = 100, /*!< Group number for SEMC status codes. */
+ kStatusGroup_ApplicationRangeStart = 101, /*!< Starting number for application groups. */
+ kStatusGroup_IAP = 102, /*!< Group number for IAP status codes */
+ kStatusGroup_SFA = 103, /*!< Group number for SFA status codes*/
+ kStatusGroup_SPC = 104, /*!< Group number for SPC status codes. */
+ kStatusGroup_PUF = 105, /*!< Group number for PUF status codes. */
+ kStatusGroup_TOUCH_PANEL = 106, /*!< Group number for touch panel status codes */
+
+ kStatusGroup_HAL_GPIO = 121, /*!< Group number for HAL GPIO status codes. */
+ kStatusGroup_HAL_UART = 122, /*!< Group number for HAL UART status codes. */
+ kStatusGroup_HAL_TIMER = 123, /*!< Group number for HAL TIMER status codes. */
+ kStatusGroup_HAL_SPI = 124, /*!< Group number for HAL SPI status codes. */
+ kStatusGroup_HAL_I2C = 125, /*!< Group number for HAL I2C status codes. */
+ kStatusGroup_HAL_FLASH = 126, /*!< Group number for HAL FLASH status codes. */
+ kStatusGroup_HAL_PWM = 127, /*!< Group number for HAL PWM status codes. */
+ kStatusGroup_HAL_RNG = 128, /*!< Group number for HAL RNG status codes. */
+ kStatusGroup_HAL_I2S = 129, /*!< Group number for HAL I2S status codes. */
+ kStatusGroup_TIMERMANAGER = 135, /*!< Group number for TiMER MANAGER status codes. */
+ kStatusGroup_SERIALMANAGER = 136, /*!< Group number for SERIAL MANAGER status codes. */
+ kStatusGroup_LED = 137, /*!< Group number for LED status codes. */
+ kStatusGroup_BUTTON = 138, /*!< Group number for BUTTON status codes. */
+ kStatusGroup_EXTERN_EEPROM = 139, /*!< Group number for EXTERN EEPROM status codes. */
+ kStatusGroup_SHELL = 140, /*!< Group number for SHELL status codes. */
+ kStatusGroup_MEM_MANAGER = 141, /*!< Group number for MEM MANAGER status codes. */
+ kStatusGroup_LIST = 142, /*!< Group number for List status codes. */
+ kStatusGroup_OSA = 143, /*!< Group number for OSA status codes. */
+ kStatusGroup_COMMON_TASK = 144, /*!< Group number for Common task status codes. */
+ kStatusGroup_MSG = 145, /*!< Group number for messaging status codes. */
+ kStatusGroup_SDK_OCOTP = 146, /*!< Group number for OCOTP status codes. */
+ kStatusGroup_SDK_FLEXSPINOR = 147, /*!< Group number for FLEXSPINOR status codes.*/
+ kStatusGroup_CODEC = 148, /*!< Group number for codec status codes. */
+ kStatusGroup_ASRC = 149, /*!< Group number for codec status ASRC. */
+ kStatusGroup_OTFAD = 150, /*!< Group number for codec status codes. */
+ kStatusGroup_SDIOSLV = 151, /*!< Group number for SDIOSLV status codes. */
+ kStatusGroup_MECC = 152, /*!< Group number for MECC status codes. */
+ kStatusGroup_ENET_QOS = 153, /*!< Group number for ENET_QOS status codes. */
+ kStatusGroup_LOG = 154, /*!< Group number for LOG status codes. */
+ kStatusGroup_I3CBUS = 155, /*!< Group number for I3CBUS status codes. */
+ kStatusGroup_QSCI = 156, /*!< Group number for QSCI status codes. */
+ kStatusGroup_SNT = 157, /*!< Group number for SNT status codes. */
+ kStatusGroup_QUEUEDSPI = 158, /*!< Group number for QSPI status codes. */
+ kStatusGroup_POWER_MANAGER = 159, /*!< Group number for POWER_MANAGER status codes. */
+};
+
+/*! \public
+ * @brief Generic status return codes.
+ */
+enum
+{
+ kStatus_Success = MAKE_STATUS(kStatusGroup_Generic, 0), /*!< Generic status for Success. */
+ kStatus_Fail = MAKE_STATUS(kStatusGroup_Generic, 1), /*!< Generic status for Fail. */
+ kStatus_ReadOnly = MAKE_STATUS(kStatusGroup_Generic, 2), /*!< Generic status for read only failure. */
+ kStatus_OutOfRange = MAKE_STATUS(kStatusGroup_Generic, 3), /*!< Generic status for out of range access. */
+ kStatus_InvalidArgument = MAKE_STATUS(kStatusGroup_Generic, 4), /*!< Generic status for invalid argument check. */
+ kStatus_Timeout = MAKE_STATUS(kStatusGroup_Generic, 5), /*!< Generic status for timeout. */
+ kStatus_NoTransferInProgress =
+ MAKE_STATUS(kStatusGroup_Generic, 6), /*!< Generic status for no transfer in progress. */
+ kStatus_Busy = MAKE_STATUS(kStatusGroup_Generic, 7), /*!< Generic status for module is busy. */
+ kStatus_NoData =
+ MAKE_STATUS(kStatusGroup_Generic, 8), /*!< Generic status for no data is found for the operation. */
+};
+
+/*! @brief Type used for all status and error return values. */
+typedef int32_t status_t;
+
+/*!
+ * @name Min/max macros
+ * @{
+ */
+#if !defined(MIN)
+#define MIN(a, b) (((a) < (b)) ? (a) : (b))
+#endif
+
+#if !defined(MAX)
+#define MAX(a, b) (((a) > (b)) ? (a) : (b))
+#endif
+/* @} */
+
+/*! @brief Computes the number of elements in an array. */
+#if !defined(ARRAY_SIZE)
+#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
+#endif
+
+/*! @name UINT16_MAX/UINT32_MAX value */
+/* @{ */
+#if !defined(UINT16_MAX)
+#define UINT16_MAX ((uint16_t)-1)
+#endif
+
+#if !defined(UINT32_MAX)
+#define UINT32_MAX ((uint32_t)-1)
+#endif
+/* @} */
+
+/*! @name Suppress fallthrough warning macro */
+/* For switch case code block, if case section ends without "break;" statement, there wil be
+ fallthrough warning with compiler flag -Wextra or -Wimplicit-fallthrough=n when using armgcc.
+ To suppress this warning, "SUPPRESS_FALL_THROUGH_WARNING();" need to be added at the end of each
+ case section which misses "break;"statement.
+ */
+/* @{ */
+#if defined(__GNUC__) && !defined(__ARMCC_VERSION)
+#define SUPPRESS_FALL_THROUGH_WARNING() __attribute__((fallthrough))
+#else
+#define SUPPRESS_FALL_THROUGH_WARNING()
+#endif
+/* @} */
+
+/*******************************************************************************
+ * API
+ ******************************************************************************/
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+/*!
+ * @brief Allocate memory with given alignment and aligned size.
+ *
+ * This is provided to support the dynamically allocated memory
+ * used in cache-able region.
+ * @param size The length required to malloc.
+ * @param alignbytes The alignment size.
+ * @retval The allocated memory.
+ */
+void *SDK_Malloc(size_t size, size_t alignbytes);
+
+/*!
+ * @brief Free memory.
+ *
+ * @param ptr The memory to be release.
+ */
+void SDK_Free(void *ptr);
+
+/*!
+ * @brief Delay at least for some time.
+ * Please note that, this API uses while loop for delay, different run-time environments make the time not precise,
+ * if precise delay count was needed, please implement a new delay function with hardware timer.
+ *
+ * @param delayTime_us Delay time in unit of microsecond.
+ * @param coreClock_Hz Core clock frequency with Hz.
+ */
+void SDK_DelayAtLeastUs(uint32_t delayTime_us, uint32_t coreClock_Hz);
+
+#if defined(__cplusplus)
+}
+#endif
+
+/*! @} */
+
+#if (defined(__DSC__) && defined(__CW__))
+#include "fsl_common_dsc.h"
+#elif defined(__XCC__)
+#include "fsl_common_dsp.h"
+#else
+#include "fsl_common_arm.h"
+#endif
+
+#endif /* _FSL_COMMON_H_ */
diff --git a/drivers/fsl_common_arm.c b/drivers/fsl_common_arm.c
new file mode 100644
index 0000000..67fe381
--- /dev/null
+++ b/drivers/fsl_common_arm.c
@@ -0,0 +1,233 @@
+/*
+ * Copyright (c) 2015-2016, Freescale Semiconductor, Inc.
+ * Copyright 2016-2021 NXP
+ * All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include "fsl_common.h"
+
+/* Component ID definition, used by tools. */
+#ifndef FSL_COMPONENT_ID
+#define FSL_COMPONENT_ID "platform.drivers.common_arm"
+#endif
+
+#ifndef __GIC_PRIO_BITS
+#if defined(ENABLE_RAM_VECTOR_TABLE)
+uint32_t InstallIRQHandler(IRQn_Type irq, uint32_t irqHandler)
+{
+#ifdef __VECTOR_TABLE
+#undef __VECTOR_TABLE
+#endif
+
+/* Addresses for VECTOR_TABLE and VECTOR_RAM come from the linker file */
+#if defined(__CC_ARM) || defined(__ARMCC_VERSION)
+ extern uint32_t Image$$VECTOR_ROM$$Base[];
+ extern uint32_t Image$$VECTOR_RAM$$Base[];
+ extern uint32_t Image$$RW_m_data$$Base[];
+
+#define __VECTOR_TABLE Image$$VECTOR_ROM$$Base
+#define __VECTOR_RAM Image$$VECTOR_RAM$$Base
+#define __RAM_VECTOR_TABLE_SIZE (((uint32_t)Image$$RW_m_data$$Base - (uint32_t)Image$$VECTOR_RAM$$Base))
+#elif defined(__ICCARM__)
+ extern uint32_t __RAM_VECTOR_TABLE_SIZE[];
+ extern uint32_t __VECTOR_TABLE[];
+ extern uint32_t __VECTOR_RAM[];
+#elif defined(__GNUC__)
+ extern uint32_t __VECTOR_TABLE[];
+ extern uint32_t __VECTOR_RAM[];
+ extern uint32_t __RAM_VECTOR_TABLE_SIZE_BYTES[];
+ uint32_t __RAM_VECTOR_TABLE_SIZE = (uint32_t)(__RAM_VECTOR_TABLE_SIZE_BYTES);
+#endif /* defined(__CC_ARM) || defined(__ARMCC_VERSION) */
+ uint32_t n;
+ uint32_t ret;
+ uint32_t irqMaskValue;
+
+ irqMaskValue = DisableGlobalIRQ();
+ if (SCB->VTOR != (uint32_t)__VECTOR_RAM)
+ {
+ /* Copy the vector table from ROM to RAM */
+ for (n = 0; n < ((uint32_t)__RAM_VECTOR_TABLE_SIZE) / sizeof(uint32_t); n++)
+ {
+ __VECTOR_RAM[n] = __VECTOR_TABLE[n];
+ }
+ /* Point the VTOR to the position of vector table */
+ SCB->VTOR = (uint32_t)__VECTOR_RAM;
+ }
+
+ ret = __VECTOR_RAM[(int32_t)irq + 16];
+ /* make sure the __VECTOR_RAM is noncachable */
+ __VECTOR_RAM[(int32_t)irq + 16] = irqHandler;
+
+ EnableGlobalIRQ(irqMaskValue);
+
+ return ret;
+}
+#endif /* ENABLE_RAM_VECTOR_TABLE. */
+#endif /* __GIC_PRIO_BITS. */
+
+#if (defined(FSL_FEATURE_SOC_SYSCON_COUNT) && (FSL_FEATURE_SOC_SYSCON_COUNT > 0))
+
+/*
+ * When FSL_FEATURE_POWERLIB_EXTEND is defined to non-zero value,
+ * powerlib should be used instead of these functions.
+ */
+#if !(defined(FSL_FEATURE_POWERLIB_EXTEND) && (FSL_FEATURE_POWERLIB_EXTEND != 0))
+
+/*
+ * When the SYSCON STARTER registers are discontinuous, these functions are
+ * implemented in fsl_power.c.
+ */
+#if !(defined(FSL_FEATURE_SYSCON_STARTER_DISCONTINUOUS) && FSL_FEATURE_SYSCON_STARTER_DISCONTINUOUS)
+
+void EnableDeepSleepIRQ(IRQn_Type interrupt)
+{
+ uint32_t intNumber = (uint32_t)interrupt;
+
+ uint32_t index = 0;
+
+ while (intNumber >= 32u)
+ {
+ index++;
+ intNumber -= 32u;
+ }
+
+ SYSCON->STARTERSET[index] = 1UL << intNumber;
+ (void)EnableIRQ(interrupt); /* also enable interrupt at NVIC */
+}
+
+void DisableDeepSleepIRQ(IRQn_Type interrupt)
+{
+ uint32_t intNumber = (uint32_t)interrupt;
+
+ (void)DisableIRQ(interrupt); /* also disable interrupt at NVIC */
+ uint32_t index = 0;
+
+ while (intNumber >= 32u)
+ {
+ index++;
+ intNumber -= 32u;
+ }
+
+ SYSCON->STARTERCLR[index] = 1UL << intNumber;
+}
+#endif /* FSL_FEATURE_SYSCON_STARTER_DISCONTINUOUS */
+#endif /* FSL_FEATURE_POWERLIB_EXTEND */
+#endif /* FSL_FEATURE_SOC_SYSCON_COUNT */
+
+#if defined(SDK_DELAY_USE_DWT) && defined(DWT)
+/* Use WDT. */
+static void enableCpuCycleCounter(void)
+{
+ /* Make sure the DWT trace fucntion is enabled. */
+ if (CoreDebug_DEMCR_TRCENA_Msk != (CoreDebug_DEMCR_TRCENA_Msk & CoreDebug->DEMCR))
+ {
+ CoreDebug->DEMCR |= CoreDebug_DEMCR_TRCENA_Msk;
+ }
+
+ /* CYCCNT not supported on this device. */
+ assert(DWT_CTRL_NOCYCCNT_Msk != (DWT->CTRL & DWT_CTRL_NOCYCCNT_Msk));
+
+ /* Read CYCCNT directly if CYCCENT has already been enabled, otherwise enable CYCCENT first. */
+ if (DWT_CTRL_CYCCNTENA_Msk != (DWT_CTRL_CYCCNTENA_Msk & DWT->CTRL))
+ {
+ DWT->CTRL |= DWT_CTRL_CYCCNTENA_Msk;
+ }
+}
+
+static uint32_t getCpuCycleCount(void)
+{
+ return DWT->CYCCNT;
+}
+#else /* defined(SDK_DELAY_USE_DWT) && defined(DWT) */
+/* Use software loop. */
+#if defined(__CC_ARM) /* This macro is arm v5 specific */
+/* clang-format off */
+__ASM static void DelayLoop(uint32_t count)
+{
+loop
+ SUBS R0, R0, #1
+ CMP R0, #0
+ BNE loop
+ BX LR
+}
+/* clang-format on */
+#elif defined(__ARMCC_VERSION) || defined(__ICCARM__) || defined(__GNUC__)
+/* Cortex-M0 has a smaller instruction set, SUBS isn't supported in thumb-16 mode reported from __GNUC__ compiler,
+ * use SUB and CMP here for compatibility */
+static void DelayLoop(uint32_t count)
+{
+ __ASM volatile(" MOV R0, %0" : : "r"(count));
+ __ASM volatile(
+ "loop: \n"
+#if defined(__GNUC__) && !defined(__ARMCC_VERSION)
+ " SUB R0, R0, #1 \n"
+#else
+ " SUBS R0, R0, #1 \n"
+#endif
+ " CMP R0, #0 \n"
+
+ " BNE loop \n"
+ :
+ :
+ : "r0");
+}
+#endif /* defined(__CC_ARM) */
+#endif /* defined(SDK_DELAY_USE_DWT) && defined(DWT) */
+
+/*!
+ * @brief Delay at least for some time.
+ * Please note that, if not uses DWT, this API will use while loop for delay, different run-time environments have
+ * effect on the delay time. If precise delay is needed, please enable DWT delay. The two parmeters delayTime_us and
+ * coreClock_Hz have limitation. For example, in the platform with 1GHz coreClock_Hz, the delayTime_us only supports
+ * up to 4294967 in current code. If long time delay is needed, please implement a new delay function.
+ *
+ * @param delayTime_us Delay time in unit of microsecond.
+ * @param coreClock_Hz Core clock frequency with Hz.
+ */
+void SDK_DelayAtLeastUs(uint32_t delayTime_us, uint32_t coreClock_Hz)
+{
+ uint64_t count;
+
+ if (delayTime_us > 0U)
+ {
+ count = USEC_TO_COUNT(delayTime_us, coreClock_Hz);
+
+ assert(count <= UINT32_MAX);
+
+#if defined(SDK_DELAY_USE_DWT) && defined(DWT) /* Use DWT for better accuracy */
+
+ enableCpuCycleCounter();
+ /* Calculate the count ticks. */
+ count += getCpuCycleCount();
+
+ if (count > UINT32_MAX)
+ {
+ count -= UINT32_MAX;
+ /* Wait for cyccnt overflow. */
+ while (count < getCpuCycleCount())
+ {
+ }
+ }
+
+ /* Wait for cyccnt reach count value. */
+ while (count > getCpuCycleCount())
+ {
+ }
+#else
+ /* Divide value may be different in various environment to ensure delay is precise.
+ * Every loop count includes three instructions, due to Cortex-M7 sometimes executes
+ * two instructions in one period, through test here set divide 1.5. Other M cores use
+ * divide 4. By the way, divide 1.5 or 4 could let the count lose precision, but it does
+ * not matter because other instructions outside while loop is enough to fill the time.
+ */
+#if (__CORTEX_M == 7)
+ count = count / 3U * 2U;
+#else
+ count = count / 4U;
+#endif
+ DelayLoop((uint32_t)count);
+#endif /* defined(SDK_DELAY_USE_DWT) && defined(DWT) */
+ }
+}
diff --git a/drivers/fsl_common_arm.h b/drivers/fsl_common_arm.h
new file mode 100644
index 0000000..ed7d5f4
--- /dev/null
+++ b/drivers/fsl_common_arm.h
@@ -0,0 +1,671 @@
+/*
+ * Copyright (c) 2015-2016, Freescale Semiconductor, Inc.
+ * Copyright 2016-2021 NXP
+ * All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef _FSL_COMMON_ARM_H_
+#define _FSL_COMMON_ARM_H_
+
+/*
+ * For CMSIS pack RTE.
+ * CMSIS pack RTE generates "RTC_Components.h" which contains the statements
+ * of the related element for all selected software components.
+ */
+#ifdef _RTE_
+#include "RTE_Components.h"
+#endif
+
+/*!
+ * @addtogroup ksdk_common
+ * @{
+ */
+
+/*! @name Atomic modification
+ *
+ * These macros are used for atomic access, such as read-modify-write
+ * to the peripheral registers.
+ *
+ * - SDK_ATOMIC_LOCAL_ADD
+ * - SDK_ATOMIC_LOCAL_SET
+ * - SDK_ATOMIC_LOCAL_CLEAR
+ * - SDK_ATOMIC_LOCAL_TOGGLE
+ * - SDK_ATOMIC_LOCAL_CLEAR_AND_SET
+ *
+ * Take SDK_ATOMIC_LOCAL_CLEAR_AND_SET as an example: the parameter @c addr
+ * means the address of the peripheral register or variable you want to modify
+ * atomically, the parameter @c clearBits is the bits to clear, the parameter
+ * @c setBits it the bits to set.
+ * For example, to set a 32-bit register bit1:bit0 to 0b10, use like this:
+ *
+ * @code
+ volatile uint32_t * reg = (volatile uint32_t *)REG_ADDR;
+
+ SDK_ATOMIC_LOCAL_CLEAR_AND_SET(reg, 0x03, 0x02);
+ @endcode
+ *
+ * In this example, the register bit1:bit0 are cleared and bit1 is set, as a result,
+ * register bit1:bit0 = 0b10.
+ *
+ * @note For the platforms don't support exclusive load and store, these macros
+ * disable the global interrupt to pretect the modification.
+ *
+ * @note These macros only guarantee the local processor atomic operations. For
+ * the multi-processor devices, use hardware semaphore such as SEMA42 to
+ * guarantee exclusive access if necessary.
+ *
+ * @{
+ */
+
+/* clang-format off */
+#if ((defined(__ARM_ARCH_7M__ ) && (__ARM_ARCH_7M__ == 1)) || \
+ (defined(__ARM_ARCH_7EM__ ) && (__ARM_ARCH_7EM__ == 1)) || \
+ (defined(__ARM_ARCH_8M_MAIN__) && (__ARM_ARCH_8M_MAIN__ == 1)) || \
+ (defined(__ARM_ARCH_8M_BASE__) && (__ARM_ARCH_8M_BASE__ == 1)))
+/* clang-format on */
+
+/* If the LDREX and STREX are supported, use them. */
+#define _SDK_ATOMIC_LOCAL_OPS_1BYTE(addr, val, ops) \
+ do \
+ { \
+ (val) = __LDREXB(addr); \
+ (ops); \
+ } while (0UL != __STREXB((val), (addr)))
+
+#define _SDK_ATOMIC_LOCAL_OPS_2BYTE(addr, val, ops) \
+ do \
+ { \
+ (val) = __LDREXH(addr); \
+ (ops); \
+ } while (0UL != __STREXH((val), (addr)))
+
+#define _SDK_ATOMIC_LOCAL_OPS_4BYTE(addr, val, ops) \
+ do \
+ { \
+ (val) = __LDREXW(addr); \
+ (ops); \
+ } while (0UL != __STREXW((val), (addr)))
+
+static inline void _SDK_AtomicLocalAdd1Byte(volatile uint8_t *addr, uint8_t val)
+{
+ uint8_t s_val;
+
+ _SDK_ATOMIC_LOCAL_OPS_1BYTE(addr, s_val, s_val += val);
+}
+
+static inline void _SDK_AtomicLocalAdd2Byte(volatile uint16_t *addr, uint16_t val)
+{
+ uint16_t s_val;
+
+ _SDK_ATOMIC_LOCAL_OPS_2BYTE(addr, s_val, s_val += val);
+}
+
+static inline void _SDK_AtomicLocalAdd4Byte(volatile uint32_t *addr, uint32_t val)
+{
+ uint32_t s_val;
+
+ _SDK_ATOMIC_LOCAL_OPS_4BYTE(addr, s_val, s_val += val);
+}
+
+static inline void _SDK_AtomicLocalSub1Byte(volatile uint8_t *addr, uint8_t val)
+{
+ uint8_t s_val;
+
+ _SDK_ATOMIC_LOCAL_OPS_1BYTE(addr, s_val, s_val -= val);
+}
+
+static inline void _SDK_AtomicLocalSub2Byte(volatile uint16_t *addr, uint16_t val)
+{
+ uint16_t s_val;
+
+ _SDK_ATOMIC_LOCAL_OPS_2BYTE(addr, s_val, s_val -= val);
+}
+
+static inline void _SDK_AtomicLocalSub4Byte(volatile uint32_t *addr, uint32_t val)
+{
+ uint32_t s_val;
+
+ _SDK_ATOMIC_LOCAL_OPS_4BYTE(addr, s_val, s_val -= val);
+}
+
+static inline void _SDK_AtomicLocalSet1Byte(volatile uint8_t *addr, uint8_t bits)
+{
+ uint8_t s_val;
+
+ _SDK_ATOMIC_LOCAL_OPS_1BYTE(addr, s_val, s_val |= bits);
+}
+
+static inline void _SDK_AtomicLocalSet2Byte(volatile uint16_t *addr, uint16_t bits)
+{
+ uint16_t s_val;
+
+ _SDK_ATOMIC_LOCAL_OPS_2BYTE(addr, s_val, s_val |= bits);
+}
+
+static inline void _SDK_AtomicLocalSet4Byte(volatile uint32_t *addr, uint32_t bits)
+{
+ uint32_t s_val;
+
+ _SDK_ATOMIC_LOCAL_OPS_4BYTE(addr, s_val, s_val |= bits);
+}
+
+static inline void _SDK_AtomicLocalClear1Byte(volatile uint8_t *addr, uint8_t bits)
+{
+ uint8_t s_val;
+
+ _SDK_ATOMIC_LOCAL_OPS_1BYTE(addr, s_val, s_val &= ~bits);
+}
+
+static inline void _SDK_AtomicLocalClear2Byte(volatile uint16_t *addr, uint16_t bits)
+{
+ uint16_t s_val;
+
+ _SDK_ATOMIC_LOCAL_OPS_2BYTE(addr, s_val, s_val &= ~bits);
+}
+
+static inline void _SDK_AtomicLocalClear4Byte(volatile uint32_t *addr, uint32_t bits)
+{
+ uint32_t s_val;
+
+ _SDK_ATOMIC_LOCAL_OPS_4BYTE(addr, s_val, s_val &= ~bits);
+}
+
+static inline void _SDK_AtomicLocalToggle1Byte(volatile uint8_t *addr, uint8_t bits)
+{
+ uint8_t s_val;
+
+ _SDK_ATOMIC_LOCAL_OPS_1BYTE(addr, s_val, s_val ^= bits);
+}
+
+static inline void _SDK_AtomicLocalToggle2Byte(volatile uint16_t *addr, uint16_t bits)
+{
+ uint16_t s_val;
+
+ _SDK_ATOMIC_LOCAL_OPS_2BYTE(addr, s_val, s_val ^= bits);
+}
+
+static inline void _SDK_AtomicLocalToggle4Byte(volatile uint32_t *addr, uint32_t bits)
+{
+ uint32_t s_val;
+
+ _SDK_ATOMIC_LOCAL_OPS_4BYTE(addr, s_val, s_val ^= bits);
+}
+
+static inline void _SDK_AtomicLocalClearAndSet1Byte(volatile uint8_t *addr, uint8_t clearBits, uint8_t setBits)
+{
+ uint8_t s_val;
+
+ _SDK_ATOMIC_LOCAL_OPS_1BYTE(addr, s_val, s_val = (s_val & ~clearBits) | setBits);
+}
+
+static inline void _SDK_AtomicLocalClearAndSet2Byte(volatile uint16_t *addr, uint16_t clearBits, uint16_t setBits)
+{
+ uint16_t s_val;
+
+ _SDK_ATOMIC_LOCAL_OPS_2BYTE(addr, s_val, s_val = (s_val & ~clearBits) | setBits);
+}
+
+static inline void _SDK_AtomicLocalClearAndSet4Byte(volatile uint32_t *addr, uint32_t clearBits, uint32_t setBits)
+{
+ uint32_t s_val;
+
+ _SDK_ATOMIC_LOCAL_OPS_4BYTE(addr, s_val, s_val = (s_val & ~clearBits) | setBits);
+}
+
+#define SDK_ATOMIC_LOCAL_ADD(addr, val) \
+ ((1UL == sizeof(*(addr))) ? \
+ _SDK_AtomicLocalAdd1Byte((volatile uint8_t *)(volatile void *)(addr), (uint8_t)(val)) : \
+ ((2UL == sizeof(*(addr))) ? _SDK_AtomicLocalAdd2Byte((volatile uint16_t *)(volatile void *)(addr), (uint16_t)(val)) : \
+ _SDK_AtomicLocalAdd4Byte((volatile uint32_t *)(volatile void *)(addr), (uint32_t)(val))))
+
+#define SDK_ATOMIC_LOCAL_SET(addr, bits) \
+ ((1UL == sizeof(*(addr))) ? \
+ _SDK_AtomicLocalSet1Byte((volatile uint8_t *)(volatile void *)(addr), (uint8_t)(bits)) : \
+ ((2UL == sizeof(*(addr))) ? _SDK_AtomicLocalSet2Byte((volatile uint16_t *)(volatile void *)(addr), (uint16_t)(bits)) : \
+ _SDK_AtomicLocalSet4Byte((volatile uint32_t *)(volatile void *)(addr), (uint32_t)(bits))))
+
+#define SDK_ATOMIC_LOCAL_CLEAR(addr, bits) \
+ ((1UL == sizeof(*(addr))) ? \
+ _SDK_AtomicLocalClear1Byte((volatile uint8_t *)(volatile void *)(addr), (uint8_t)(bits)) : \
+ ((2UL == sizeof(*(addr))) ? \
+ _SDK_AtomicLocalClear2Byte((volatile uint16_t *)(volatile void *)(addr), (uint16_t)(bits)) : \
+ _SDK_AtomicLocalClear4Byte((volatile uint32_t *)(volatile void *)(addr), (uint32_t)(bits))))
+
+#define SDK_ATOMIC_LOCAL_TOGGLE(addr, bits) \
+ ((1UL == sizeof(*(addr))) ? \
+ _SDK_AtomicLocalToggle1Byte((volatile uint8_t *)(volatile void *)(addr), (uint8_t)(bits)) : \
+ ((2UL == sizeof(*(addr))) ? \
+ _SDK_AtomicLocalToggle2Byte((volatile uint16_t *)(volatile void *)(addr), (uint16_t)(bits)) : \
+ _SDK_AtomicLocalToggle4Byte((volatile uint32_t *)(volatile void *)(addr), (uint32_t)(bits))))
+
+#define SDK_ATOMIC_LOCAL_CLEAR_AND_SET(addr, clearBits, setBits) \
+ ((1UL == sizeof(*(addr))) ? \
+ _SDK_AtomicLocalClearAndSet1Byte((volatile uint8_t *)(volatile void *)(addr), (uint8_t)(clearBits), (uint8_t)(setBits)) : \
+ ((2UL == sizeof(*(addr))) ? \
+ _SDK_AtomicLocalClearAndSet2Byte((volatile uint16_t *)(volatile void *)(addr), (uint16_t)(clearBits), (uint16_t)(setBits)) : \
+ _SDK_AtomicLocalClearAndSet4Byte((volatile uint32_t *)(volatile void *)(addr), (uint32_t)(clearBits), (uint32_t)(setBits))))
+#else
+
+#define SDK_ATOMIC_LOCAL_ADD(addr, val) \
+ do \
+ { \
+ uint32_t s_atomicOldInt; \
+ s_atomicOldInt = DisableGlobalIRQ(); \
+ *(addr) += (val); \
+ EnableGlobalIRQ(s_atomicOldInt); \
+ } while (0)
+
+#define SDK_ATOMIC_LOCAL_SET(addr, bits) \
+ do \
+ { \
+ uint32_t s_atomicOldInt; \
+ s_atomicOldInt = DisableGlobalIRQ(); \
+ *(addr) |= (bits); \
+ EnableGlobalIRQ(s_atomicOldInt); \
+ } while (0)
+
+#define SDK_ATOMIC_LOCAL_CLEAR(addr, bits) \
+ do \
+ { \
+ uint32_t s_atomicOldInt; \
+ s_atomicOldInt = DisableGlobalIRQ(); \
+ *(addr) &= ~(bits); \
+ EnableGlobalIRQ(s_atomicOldInt); \
+ } while (0)
+
+#define SDK_ATOMIC_LOCAL_TOGGLE(addr, bits) \
+ do \
+ { \
+ uint32_t s_atomicOldInt; \
+ s_atomicOldInt = DisableGlobalIRQ(); \
+ *(addr) ^= (bits); \
+ EnableGlobalIRQ(s_atomicOldInt); \
+ } while (0)
+
+#define SDK_ATOMIC_LOCAL_CLEAR_AND_SET(addr, clearBits, setBits) \
+ do \
+ { \
+ uint32_t s_atomicOldInt; \
+ s_atomicOldInt = DisableGlobalIRQ(); \
+ *(addr) = (*(addr) & ~(clearBits)) | (setBits); \
+ EnableGlobalIRQ(s_atomicOldInt); \
+ } while (0)
+
+#endif
+/* @} */
+
+/*! @name Timer utilities */
+/* @{ */
+/*! Macro to convert a microsecond period to raw count value */
+#define USEC_TO_COUNT(us, clockFreqInHz) (uint64_t)(((uint64_t)(us) * (clockFreqInHz)) / 1000000U)
+/*! Macro to convert a raw count value to microsecond */
+#define COUNT_TO_USEC(count, clockFreqInHz) (uint64_t)((uint64_t)(count)*1000000U / (clockFreqInHz))
+
+/*! Macro to convert a millisecond period to raw count value */
+#define MSEC_TO_COUNT(ms, clockFreqInHz) (uint64_t)((uint64_t)(ms) * (clockFreqInHz) / 1000U)
+/*! Macro to convert a raw count value to millisecond */
+#define COUNT_TO_MSEC(count, clockFreqInHz) (uint64_t)((uint64_t)(count)*1000U / (clockFreqInHz))
+/* @} */
+
+/*! @name ISR exit barrier
+ * @{
+ *
+ * ARM errata 838869, affects Cortex-M4, Cortex-M4F Store immediate overlapping
+ * exception return operation might vector to incorrect interrupt.
+ * For Cortex-M7, if core speed much faster than peripheral register write speed,
+ * the peripheral interrupt flags may be still set after exiting ISR, this results to
+ * the same error similar with errata 83869.
+ */
+#if (defined __CORTEX_M) && ((__CORTEX_M == 4U) || (__CORTEX_M == 7U))
+#define SDK_ISR_EXIT_BARRIER __DSB()
+#else
+#define SDK_ISR_EXIT_BARRIER
+#endif
+
+/* @} */
+
+/*! @name Alignment variable definition macros */
+/* @{ */
+#if (defined(__ICCARM__))
+/*
+ * Workaround to disable MISRA C message suppress warnings for IAR compiler.
+ * http:/ /supp.iar.com/Support/?note=24725
+ */
+_Pragma("diag_suppress=Pm120")
+#define SDK_PRAGMA(x) _Pragma(#x)
+ _Pragma("diag_error=Pm120")
+/*! Macro to define a variable with alignbytes alignment */
+#define SDK_ALIGN(var, alignbytes) SDK_PRAGMA(data_alignment = alignbytes) var
+#elif defined(__CC_ARM) || defined(__ARMCC_VERSION)
+/*! Macro to define a variable with alignbytes alignment */
+#define SDK_ALIGN(var, alignbytes) __attribute__((aligned(alignbytes))) var
+#elif defined(__GNUC__)
+/*! Macro to define a variable with alignbytes alignment */
+#define SDK_ALIGN(var, alignbytes) var __attribute__((aligned(alignbytes)))
+#else
+#error Toolchain not supported
+#endif
+
+/*! Macro to define a variable with L1 d-cache line size alignment */
+#if defined(FSL_FEATURE_L1DCACHE_LINESIZE_BYTE)
+#define SDK_L1DCACHE_ALIGN(var) SDK_ALIGN(var, FSL_FEATURE_L1DCACHE_LINESIZE_BYTE)
+#endif
+/*! Macro to define a variable with L2 cache line size alignment */
+#if defined(FSL_FEATURE_L2CACHE_LINESIZE_BYTE)
+#define SDK_L2CACHE_ALIGN(var) SDK_ALIGN(var, FSL_FEATURE_L2CACHE_LINESIZE_BYTE)
+#endif
+
+/*! Macro to change a value to a given size aligned value */
+#define SDK_SIZEALIGN(var, alignbytes) \
+ ((unsigned int)((var) + ((alignbytes)-1U)) & (unsigned int)(~(unsigned int)((alignbytes)-1U)))
+/* @} */
+
+/*! @name Non-cacheable region definition macros */
+/* For initialized non-zero non-cacheable variables, please using "AT_NONCACHEABLE_SECTION_INIT(var) ={xx};" or
+ * "AT_NONCACHEABLE_SECTION_ALIGN_INIT(var) ={xx};" in your projects to define them, for zero-inited non-cacheable
+ * variables, please using "AT_NONCACHEABLE_SECTION(var);" or "AT_NONCACHEABLE_SECTION_ALIGN(var);" to define them,
+ * these zero-inited variables will be initialized to zero in system startup.
+ */
+/* @{ */
+
+#if ((!(defined(FSL_FEATURE_HAS_NO_NONCACHEABLE_SECTION) && FSL_FEATURE_HAS_NO_NONCACHEABLE_SECTION)) && \
+ defined(FSL_FEATURE_L1ICACHE_LINESIZE_BYTE))
+
+#if (defined(__ICCARM__))
+#define AT_NONCACHEABLE_SECTION(var) var @"NonCacheable"
+#define AT_NONCACHEABLE_SECTION_ALIGN(var, alignbytes) SDK_PRAGMA(data_alignment = alignbytes) var @"NonCacheable"
+#define AT_NONCACHEABLE_SECTION_INIT(var) var @"NonCacheable.init"
+#define AT_NONCACHEABLE_SECTION_ALIGN_INIT(var, alignbytes) \
+ SDK_PRAGMA(data_alignment = alignbytes) var @"NonCacheable.init"
+
+#elif (defined(__CC_ARM) || defined(__ARMCC_VERSION))
+#define AT_NONCACHEABLE_SECTION_INIT(var) __attribute__((section("NonCacheable.init"))) var
+#define AT_NONCACHEABLE_SECTION_ALIGN_INIT(var, alignbytes) \
+ __attribute__((section("NonCacheable.init"))) __attribute__((aligned(alignbytes))) var
+#if (defined(__CC_ARM))
+#define AT_NONCACHEABLE_SECTION(var) __attribute__((section("NonCacheable"), zero_init)) var
+#define AT_NONCACHEABLE_SECTION_ALIGN(var, alignbytes) \
+ __attribute__((section("NonCacheable"), zero_init)) __attribute__((aligned(alignbytes))) var
+#else
+#define AT_NONCACHEABLE_SECTION(var) __attribute__((section(".bss.NonCacheable"))) var
+#define AT_NONCACHEABLE_SECTION_ALIGN(var, alignbytes) \
+ __attribute__((section(".bss.NonCacheable"))) __attribute__((aligned(alignbytes))) var
+#endif
+
+#elif (defined(__GNUC__))
+/* For GCC, when the non-cacheable section is required, please define "__STARTUP_INITIALIZE_NONCACHEDATA"
+ * in your projects to make sure the non-cacheable section variables will be initialized in system startup.
+ */
+#define AT_NONCACHEABLE_SECTION_INIT(var) __attribute__((section("NonCacheable.init"))) var
+#define AT_NONCACHEABLE_SECTION_ALIGN_INIT(var, alignbytes) \
+ __attribute__((section("NonCacheable.init"))) var __attribute__((aligned(alignbytes)))
+#define AT_NONCACHEABLE_SECTION(var) __attribute__((section("NonCacheable,\"aw\",%nobits @"))) var
+#define AT_NONCACHEABLE_SECTION_ALIGN(var, alignbytes) \
+ __attribute__((section("NonCacheable,\"aw\",%nobits @"))) var __attribute__((aligned(alignbytes)))
+#else
+#error Toolchain not supported.
+#endif
+
+#else
+
+#define AT_NONCACHEABLE_SECTION(var) var
+#define AT_NONCACHEABLE_SECTION_ALIGN(var, alignbytes) SDK_ALIGN(var, alignbytes)
+#define AT_NONCACHEABLE_SECTION_INIT(var) var
+#define AT_NONCACHEABLE_SECTION_ALIGN_INIT(var, alignbytes) SDK_ALIGN(var, alignbytes)
+
+#endif
+
+/* @} */
+
+/*!
+ * @name Time sensitive region
+ * @{
+ */
+#if (defined(__ICCARM__))
+#define AT_QUICKACCESS_SECTION_CODE(func) func @"CodeQuickAccess"
+#define AT_QUICKACCESS_SECTION_DATA(var) var @"DataQuickAccess"
+#define AT_QUICKACCESS_SECTION_DATA_ALIGN(var, alignbytes) \
+ SDK_PRAGMA(data_alignment = alignbytes) var @"DataQuickAccess"
+#elif (defined(__CC_ARM) || defined(__ARMCC_VERSION))
+#define AT_QUICKACCESS_SECTION_CODE(func) __attribute__((section("CodeQuickAccess"), __noinline__)) func
+#define AT_QUICKACCESS_SECTION_DATA(var) __attribute__((section("DataQuickAccess"))) var
+#define AT_QUICKACCESS_SECTION_DATA_ALIGN(var, alignbytes) \
+ __attribute__((section("DataQuickAccess"))) __attribute__((aligned(alignbytes))) var
+#elif (defined(__GNUC__))
+#define AT_QUICKACCESS_SECTION_CODE(func) __attribute__((section("CodeQuickAccess"), __noinline__)) func
+#define AT_QUICKACCESS_SECTION_DATA(var) __attribute__((section("DataQuickAccess"))) var
+#define AT_QUICKACCESS_SECTION_DATA_ALIGN(var, alignbytes) \
+ __attribute__((section("DataQuickAccess"))) var __attribute__((aligned(alignbytes)))
+#else
+#error Toolchain not supported.
+#endif /* defined(__ICCARM__) */
+
+/*! @name Ram Function */
+#if (defined(__ICCARM__))
+#define RAMFUNCTION_SECTION_CODE(func) func @"RamFunction"
+#elif (defined(__CC_ARM) || defined(__ARMCC_VERSION))
+#define RAMFUNCTION_SECTION_CODE(func) __attribute__((section("RamFunction"))) func
+#elif (defined(__GNUC__))
+#define RAMFUNCTION_SECTION_CODE(func) __attribute__((section("RamFunction"))) func
+#else
+#error Toolchain not supported.
+#endif /* defined(__ICCARM__) */
+/* @} */
+
+#if defined(__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050)
+ void DefaultISR(void);
+#endif
+
+/*
+ * The fsl_clock.h is included here because it needs MAKE_VERSION/MAKE_STATUS/status_t
+ * defined in previous of this file.
+ */
+#include "fsl_clock.h"
+
+/*
+ * Chip level peripheral reset API, for MCUs that implement peripheral reset control external to a peripheral
+ */
+#if ((defined(FSL_FEATURE_SOC_SYSCON_COUNT) && (FSL_FEATURE_SOC_SYSCON_COUNT > 0)) || \
+ (defined(FSL_FEATURE_SOC_ASYNC_SYSCON_COUNT) && (FSL_FEATURE_SOC_ASYNC_SYSCON_COUNT > 0)))
+#include "fsl_reset.h"
+#endif
+
+/*******************************************************************************
+ * API
+ ******************************************************************************/
+
+#if defined(__cplusplus)
+extern "C" {
+#endif /* __cplusplus*/
+
+/*!
+ * @brief Enable specific interrupt.
+ *
+ * Enable LEVEL1 interrupt. For some devices, there might be multiple interrupt
+ * levels. For example, there are NVIC and intmux. Here the interrupts connected
+ * to NVIC are the LEVEL1 interrupts, because they are routed to the core directly.
+ * The interrupts connected to intmux are the LEVEL2 interrupts, they are routed
+ * to NVIC first then routed to core.
+ *
+ * This function only enables the LEVEL1 interrupts. The number of LEVEL1 interrupts
+ * is indicated by the feature macro FSL_FEATURE_NUMBER_OF_LEVEL1_INT_VECTORS.
+ *
+ * @param interrupt The IRQ number.
+ * @retval kStatus_Success Interrupt enabled successfully
+ * @retval kStatus_Fail Failed to enable the interrupt
+ */
+static inline status_t EnableIRQ(IRQn_Type interrupt)
+{
+ status_t status = kStatus_Success;
+
+ if (NotAvail_IRQn == interrupt)
+ {
+ status = kStatus_Fail;
+ }
+
+#if defined(FSL_FEATURE_NUMBER_OF_LEVEL1_INT_VECTORS) && (FSL_FEATURE_NUMBER_OF_LEVEL1_INT_VECTORS > 0)
+ else if ((int32_t)interrupt >= (int32_t)FSL_FEATURE_NUMBER_OF_LEVEL1_INT_VECTORS)
+ {
+ status = kStatus_Fail;
+ }
+#endif
+
+ else
+ {
+#if defined(__GIC_PRIO_BITS)
+ GIC_EnableIRQ(interrupt);
+#else
+ NVIC_EnableIRQ(interrupt);
+#endif
+ }
+
+ return status;
+}
+
+/*!
+ * @brief Disable specific interrupt.
+ *
+ * Disable LEVEL1 interrupt. For some devices, there might be multiple interrupt
+ * levels. For example, there are NVIC and intmux. Here the interrupts connected
+ * to NVIC are the LEVEL1 interrupts, because they are routed to the core directly.
+ * The interrupts connected to intmux are the LEVEL2 interrupts, they are routed
+ * to NVIC first then routed to core.
+ *
+ * This function only disables the LEVEL1 interrupts. The number of LEVEL1 interrupts
+ * is indicated by the feature macro FSL_FEATURE_NUMBER_OF_LEVEL1_INT_VECTORS.
+ *
+ * @param interrupt The IRQ number.
+ * @retval kStatus_Success Interrupt disabled successfully
+ * @retval kStatus_Fail Failed to disable the interrupt
+ */
+static inline status_t DisableIRQ(IRQn_Type interrupt)
+{
+ status_t status = kStatus_Success;
+
+ if (NotAvail_IRQn == interrupt)
+ {
+ status = kStatus_Fail;
+ }
+
+#if defined(FSL_FEATURE_NUMBER_OF_LEVEL1_INT_VECTORS) && (FSL_FEATURE_NUMBER_OF_LEVEL1_INT_VECTORS > 0)
+ else if ((int32_t)interrupt >= (int32_t)FSL_FEATURE_NUMBER_OF_LEVEL1_INT_VECTORS)
+ {
+ status = kStatus_Fail;
+ }
+#endif
+
+ else
+ {
+#if defined(__GIC_PRIO_BITS)
+ GIC_DisableIRQ(interrupt);
+#else
+ NVIC_DisableIRQ(interrupt);
+#endif
+ }
+
+ return status;
+}
+
+/*!
+ * @brief Disable the global IRQ
+ *
+ * Disable the global interrupt and return the current primask register. User is required to provided the primask
+ * register for the EnableGlobalIRQ().
+ *
+ * @return Current primask value.
+ */
+static inline uint32_t DisableGlobalIRQ(void)
+{
+#if defined(CPSR_I_Msk)
+ uint32_t cpsr = __get_CPSR() & CPSR_I_Msk;
+
+ __disable_irq();
+
+ return cpsr;
+#else
+ uint32_t regPrimask = __get_PRIMASK();
+
+ __disable_irq();
+
+ return regPrimask;
+#endif
+}
+
+/*!
+ * @brief Enable the global IRQ
+ *
+ * Set the primask register with the provided primask value but not just enable the primask. The idea is for the
+ * convenience of integration of RTOS. some RTOS get its own management mechanism of primask. User is required to
+ * use the EnableGlobalIRQ() and DisableGlobalIRQ() in pair.
+ *
+ * @param primask value of primask register to be restored. The primask value is supposed to be provided by the
+ * DisableGlobalIRQ().
+ */
+static inline void EnableGlobalIRQ(uint32_t primask)
+{
+#if defined(CPSR_I_Msk)
+ __set_CPSR((__get_CPSR() & ~CPSR_I_Msk) | primask);
+#else
+ __set_PRIMASK(primask);
+#endif
+}
+
+#if defined(ENABLE_RAM_VECTOR_TABLE)
+/*!
+ * @brief install IRQ handler
+ *
+ * @param irq IRQ number
+ * @param irqHandler IRQ handler address
+ * @return The old IRQ handler address
+ */
+uint32_t InstallIRQHandler(IRQn_Type irq, uint32_t irqHandler);
+#endif /* ENABLE_RAM_VECTOR_TABLE. */
+
+#if (defined(FSL_FEATURE_SOC_SYSCON_COUNT) && (FSL_FEATURE_SOC_SYSCON_COUNT > 0))
+
+/*
+ * When FSL_FEATURE_POWERLIB_EXTEND is defined to non-zero value,
+ * powerlib should be used instead of these functions.
+ */
+#if !(defined(FSL_FEATURE_POWERLIB_EXTEND) && (FSL_FEATURE_POWERLIB_EXTEND != 0))
+/*!
+ * @brief Enable specific interrupt for wake-up from deep-sleep mode.
+ *
+ * Enable the interrupt for wake-up from deep sleep mode.
+ * Some interrupts are typically used in sleep mode only and will not occur during
+ * deep-sleep mode because relevant clocks are stopped. However, it is possible to enable
+ * those clocks (significantly increasing power consumption in the reduced power mode),
+ * making these wake-ups possible.
+ *
+ * @note This function also enables the interrupt in the NVIC (EnableIRQ() is called internaly).
+ *
+ * @param interrupt The IRQ number.
+ */
+void EnableDeepSleepIRQ(IRQn_Type interrupt);
+
+/*!
+ * @brief Disable specific interrupt for wake-up from deep-sleep mode.
+ *
+ * Disable the interrupt for wake-up from deep sleep mode.
+ * Some interrupts are typically used in sleep mode only and will not occur during
+ * deep-sleep mode because relevant clocks are stopped. However, it is possible to enable
+ * those clocks (significantly increasing power consumption in the reduced power mode),
+ * making these wake-ups possible.
+ *
+ * @note This function also disables the interrupt in the NVIC (DisableIRQ() is called internaly).
+ *
+ * @param interrupt The IRQ number.
+ */
+void DisableDeepSleepIRQ(IRQn_Type interrupt);
+#endif /* FSL_FEATURE_POWERLIB_EXTEND */
+#endif /* FSL_FEATURE_SOC_SYSCON_COUNT */
+
+#if defined(__cplusplus)
+}
+#endif /* __cplusplus*/
+
+/*! @} */
+
+#endif /* _FSL_COMMON_ARM_H_ */
diff --git a/drivers/fsl_flexcomm.c b/drivers/fsl_flexcomm.c
new file mode 100644
index 0000000..80a3c98
--- /dev/null
+++ b/drivers/fsl_flexcomm.c
@@ -0,0 +1,412 @@
+/*
+ * Copyright (c) 2016, Freescale Semiconductor, Inc.
+ * Copyright 2016-2019 NXP
+ * All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include "fsl_common.h"
+#include "fsl_flexcomm.h"
+
+/*******************************************************************************
+ * Definitions
+ ******************************************************************************/
+
+/* Component ID definition, used by tools. */
+#ifndef FSL_COMPONENT_ID
+#define FSL_COMPONENT_ID "platform.drivers.flexcomm"
+#endif
+
+/*!
+ * @brief Used for conversion between `void*` and `uint32_t`.
+ */
+typedef union pvoid_to_u32
+{
+ void *pvoid;
+ uint32_t u32;
+} pvoid_to_u32_t;
+
+/*******************************************************************************
+ * Prototypes
+ ******************************************************************************/
+/*! @brief Set the FLEXCOMM mode . */
+static status_t FLEXCOMM_SetPeriph(FLEXCOMM_Type *base, FLEXCOMM_PERIPH_T periph, int lock);
+
+/*! @brief check whether flexcomm supports peripheral type */
+static bool FLEXCOMM_PeripheralIsPresent(FLEXCOMM_Type *base, FLEXCOMM_PERIPH_T periph);
+
+/*******************************************************************************
+ * Variables
+ ******************************************************************************/
+
+/*! @brief Array to map FLEXCOMM instance number to base address. */
+static const uint32_t s_flexcommBaseAddrs[] = FLEXCOMM_BASE_ADDRS;
+
+/*! @brief Pointers to real IRQ handlers installed by drivers for each instance. */
+static flexcomm_irq_handler_t s_flexcommIrqHandler[ARRAY_SIZE(s_flexcommBaseAddrs)];
+
+/*! @brief Pointers to handles for each instance to provide context to interrupt routines */
+static void *s_flexcommHandle[ARRAY_SIZE(s_flexcommBaseAddrs)];
+
+/*! @brief Array to map FLEXCOMM instance number to IRQ number. */
+IRQn_Type const kFlexcommIrqs[] = FLEXCOMM_IRQS;
+
+#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
+/*! @brief IDs of clock for each FLEXCOMM module */
+static const clock_ip_name_t s_flexcommClocks[] = FLEXCOMM_CLOCKS;
+#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
+
+#if !(defined(FSL_FEATURE_FLEXCOMM_HAS_NO_RESET) && FSL_FEATURE_FLEXCOMM_HAS_NO_RESET)
+/*! @brief Pointers to FLEXCOMM resets for each instance. */
+static const reset_ip_name_t s_flexcommResets[] = FLEXCOMM_RSTS;
+#endif
+
+/*******************************************************************************
+ * Code
+ ******************************************************************************/
+
+/* check whether flexcomm supports peripheral type */
+static bool FLEXCOMM_PeripheralIsPresent(FLEXCOMM_Type *base, FLEXCOMM_PERIPH_T periph)
+{
+ if (periph == FLEXCOMM_PERIPH_NONE)
+ {
+ return true;
+ }
+ else if (periph <= FLEXCOMM_PERIPH_I2S_TX)
+ {
+ return (base->PSELID & (1UL << ((uint32_t)periph + 3U))) > 0UL ? true : false;
+ }
+ else if (periph == FLEXCOMM_PERIPH_I2S_RX)
+ {
+ return (base->PSELID & (1U << 7U)) > (uint32_t)0U ? true : false;
+ }
+ else
+ {
+ return false;
+ }
+}
+
+/* Get the index corresponding to the FLEXCOMM */
+/*! brief Returns instance number for FLEXCOMM module with given base address. */
+uint32_t FLEXCOMM_GetInstance(void *base)
+{
+ uint32_t i;
+ pvoid_to_u32_t BaseAddr;
+ BaseAddr.pvoid = base;
+
+ for (i = 0U; i < (uint32_t)FSL_FEATURE_SOC_FLEXCOMM_COUNT; i++)
+ {
+ if (BaseAddr.u32 == s_flexcommBaseAddrs[i])
+ {
+ break;
+ }
+ }
+
+ assert(i < (uint32_t)FSL_FEATURE_SOC_FLEXCOMM_COUNT);
+ return i;
+}
+
+/* Changes FLEXCOMM mode */
+static status_t FLEXCOMM_SetPeriph(FLEXCOMM_Type *base, FLEXCOMM_PERIPH_T periph, int lock)
+{
+ /* Check whether peripheral type is present */
+ if (!FLEXCOMM_PeripheralIsPresent(base, periph))
+ {
+ return kStatus_OutOfRange;
+ }
+
+ /* Flexcomm is locked to different peripheral type than expected */
+ if (((base->PSELID & FLEXCOMM_PSELID_LOCK_MASK) != 0U) &&
+ ((base->PSELID & FLEXCOMM_PSELID_PERSEL_MASK) != (uint32_t)periph))
+ {
+ return kStatus_Fail;
+ }
+
+ /* Check if we are asked to lock */
+ if (lock != 0)
+ {
+ base->PSELID = (uint32_t)periph | FLEXCOMM_PSELID_LOCK_MASK;
+ }
+ else
+ {
+ base->PSELID = (uint32_t)periph;
+ }
+
+ return kStatus_Success;
+}
+
+/*! brief Initializes FLEXCOMM and selects peripheral mode according to the second parameter. */
+status_t FLEXCOMM_Init(void *base, FLEXCOMM_PERIPH_T periph)
+{
+ uint32_t idx = FLEXCOMM_GetInstance(base);
+
+#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
+ /* Enable the peripheral clock */
+ CLOCK_EnableClock(s_flexcommClocks[idx]);
+#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
+
+#if !(defined(FSL_FEATURE_FLEXCOMM_HAS_NO_RESET) && FSL_FEATURE_FLEXCOMM_HAS_NO_RESET)
+ /* Reset the FLEXCOMM module */
+ RESET_PeripheralReset(s_flexcommResets[idx]);
+#endif
+
+ /* Set the FLEXCOMM to given peripheral */
+ return FLEXCOMM_SetPeriph((FLEXCOMM_Type *)base, periph, 0);
+}
+
+/*! brief Sets IRQ handler for given FLEXCOMM module. It is used by drivers register IRQ handler according to FLEXCOMM
+ * mode */
+void FLEXCOMM_SetIRQHandler(void *base, flexcomm_irq_handler_t handler, void *flexcommHandle)
+{
+ uint32_t instance;
+
+ /* Look up instance number */
+ instance = FLEXCOMM_GetInstance(base);
+
+ /* Clear handler first to avoid execution of the handler with wrong handle */
+ s_flexcommIrqHandler[instance] = NULL;
+ s_flexcommHandle[instance] = flexcommHandle;
+ s_flexcommIrqHandler[instance] = handler;
+ SDK_ISR_EXIT_BARRIER;
+}
+
+/* IRQ handler functions overloading weak symbols in the startup */
+#if defined(FLEXCOMM0)
+void FLEXCOMM0_DriverIRQHandler(void);
+void FLEXCOMM0_DriverIRQHandler(void)
+{
+ uint32_t instance;
+
+ /* Look up instance number */
+ instance = FLEXCOMM_GetInstance(FLEXCOMM0);
+ assert(s_flexcommIrqHandler[instance] != NULL);
+ s_flexcommIrqHandler[instance]((uint32_t *)s_flexcommBaseAddrs[instance], s_flexcommHandle[instance]);
+ SDK_ISR_EXIT_BARRIER;
+}
+#endif
+
+#if defined(FLEXCOMM1)
+void FLEXCOMM1_DriverIRQHandler(void);
+void FLEXCOMM1_DriverIRQHandler(void)
+{
+ uint32_t instance;
+
+ /* Look up instance number */
+ instance = FLEXCOMM_GetInstance(FLEXCOMM1);
+ assert(s_flexcommIrqHandler[instance] != NULL);
+ s_flexcommIrqHandler[instance]((uint32_t *)s_flexcommBaseAddrs[instance], s_flexcommHandle[instance]);
+ SDK_ISR_EXIT_BARRIER;
+}
+#endif
+
+#if defined(FLEXCOMM2)
+void FLEXCOMM2_DriverIRQHandler(void);
+void FLEXCOMM2_DriverIRQHandler(void)
+{
+ uint32_t instance;
+
+ /* Look up instance number */
+ instance = FLEXCOMM_GetInstance(FLEXCOMM2);
+ assert(s_flexcommIrqHandler[instance] != NULL);
+ s_flexcommIrqHandler[instance]((uint32_t *)s_flexcommBaseAddrs[instance], s_flexcommHandle[instance]);
+ SDK_ISR_EXIT_BARRIER;
+}
+#endif
+
+#if defined(FLEXCOMM3)
+void FLEXCOMM3_DriverIRQHandler(void);
+void FLEXCOMM3_DriverIRQHandler(void)
+{
+ uint32_t instance;
+
+ /* Look up instance number */
+ instance = FLEXCOMM_GetInstance(FLEXCOMM3);
+ assert(s_flexcommIrqHandler[instance] != NULL);
+ s_flexcommIrqHandler[instance]((uint32_t *)s_flexcommBaseAddrs[instance], s_flexcommHandle[instance]);
+ SDK_ISR_EXIT_BARRIER;
+}
+#endif
+
+#if defined(FLEXCOMM4)
+void FLEXCOMM4_DriverIRQHandler(void);
+void FLEXCOMM4_DriverIRQHandler(void)
+{
+ uint32_t instance;
+
+ /* Look up instance number */
+ instance = FLEXCOMM_GetInstance(FLEXCOMM4);
+ assert(s_flexcommIrqHandler[instance] != NULL);
+ s_flexcommIrqHandler[instance]((uint32_t *)s_flexcommBaseAddrs[instance], s_flexcommHandle[instance]);
+ SDK_ISR_EXIT_BARRIER;
+}
+
+#endif
+
+#if defined(FLEXCOMM5)
+void FLEXCOMM5_DriverIRQHandler(void);
+void FLEXCOMM5_DriverIRQHandler(void)
+{
+ uint32_t instance;
+
+ /* Look up instance number */
+ instance = FLEXCOMM_GetInstance(FLEXCOMM5);
+ assert(s_flexcommIrqHandler[instance] != NULL);
+ s_flexcommIrqHandler[instance]((uint32_t *)s_flexcommBaseAddrs[instance], s_flexcommHandle[instance]);
+ SDK_ISR_EXIT_BARRIER;
+}
+#endif
+
+#if defined(FLEXCOMM6)
+void FLEXCOMM6_DriverIRQHandler(void);
+void FLEXCOMM6_DriverIRQHandler(void)
+{
+ uint32_t instance;
+
+ /* Look up instance number */
+ instance = FLEXCOMM_GetInstance(FLEXCOMM6);
+ assert(s_flexcommIrqHandler[instance] != NULL);
+ s_flexcommIrqHandler[instance]((uint32_t *)s_flexcommBaseAddrs[instance], s_flexcommHandle[instance]);
+ SDK_ISR_EXIT_BARRIER;
+}
+#endif
+
+#if defined(FLEXCOMM7)
+void FLEXCOMM7_DriverIRQHandler(void);
+void FLEXCOMM7_DriverIRQHandler(void)
+{
+ uint32_t instance;
+
+ /* Look up instance number */
+ instance = FLEXCOMM_GetInstance(FLEXCOMM7);
+ assert(s_flexcommIrqHandler[instance] != NULL);
+ s_flexcommIrqHandler[instance]((uint32_t *)s_flexcommBaseAddrs[instance], s_flexcommHandle[instance]);
+ SDK_ISR_EXIT_BARRIER;
+}
+#endif
+
+#if defined(FLEXCOMM8)
+void FLEXCOMM8_DriverIRQHandler(void);
+void FLEXCOMM8_DriverIRQHandler(void)
+{
+ uint32_t instance;
+
+ /* Look up instance number */
+ instance = FLEXCOMM_GetInstance(FLEXCOMM8);
+ assert(s_flexcommIrqHandler[instance] != NULL);
+ s_flexcommIrqHandler[instance]((uint32_t *)s_flexcommBaseAddrs[instance], s_flexcommHandle[instance]);
+ SDK_ISR_EXIT_BARRIER;
+}
+#endif
+
+#if defined(FLEXCOMM9)
+void FLEXCOMM9_DriverIRQHandler(void);
+void FLEXCOMM9_DriverIRQHandler(void)
+{
+ uint32_t instance;
+
+ /* Look up instance number */
+ instance = FLEXCOMM_GetInstance(FLEXCOMM9);
+ assert(s_flexcommIrqHandler[instance] != NULL);
+ s_flexcommIrqHandler[instance]((uint32_t *)s_flexcommBaseAddrs[instance], s_flexcommHandle[instance]);
+ SDK_ISR_EXIT_BARRIER;
+}
+#endif
+
+#if defined(FLEXCOMM10)
+void FLEXCOMM10_DriverIRQHandler(void);
+void FLEXCOMM10_DriverIRQHandler(void)
+{
+ uint32_t instance;
+
+ /* Look up instance number */
+ instance = FLEXCOMM_GetInstance(FLEXCOMM10);
+ assert(s_flexcommIrqHandler[instance] != NULL);
+ s_flexcommIrqHandler[instance]((uint32_t *)s_flexcommBaseAddrs[instance], s_flexcommHandle[instance]);
+ SDK_ISR_EXIT_BARRIER;
+}
+#endif
+
+#if defined(FLEXCOMM11)
+void FLEXCOMM11_DriverIRQHandler(void);
+void FLEXCOMM11_DriverIRQHandler(void)
+{
+ uint32_t instance;
+
+ /* Look up instance number */
+ instance = FLEXCOMM_GetInstance(FLEXCOMM11);
+ assert(s_flexcommIrqHandler[instance] != NULL);
+ s_flexcommIrqHandler[instance]((uint32_t *)s_flexcommBaseAddrs[instance], s_flexcommHandle[instance]);
+ SDK_ISR_EXIT_BARRIER;
+}
+#endif
+
+#if defined(FLEXCOMM12)
+void FLEXCOMM12_DriverIRQHandler(void);
+void FLEXCOMM12_DriverIRQHandler(void)
+{
+ uint32_t instance;
+
+ /* Look up instance number */
+ instance = FLEXCOMM_GetInstance(FLEXCOMM12);
+ assert(s_flexcommIrqHandler[instance] != NULL);
+ s_flexcommIrqHandler[instance]((uint32_t *)s_flexcommBaseAddrs[instance], s_flexcommHandle[instance]);
+ SDK_ISR_EXIT_BARRIER;
+}
+#endif
+
+#if defined(FLEXCOMM13)
+void FLEXCOMM13_DriverIRQHandler(void);
+void FLEXCOMM13_DriverIRQHandler(void)
+{
+ uint32_t instance;
+
+ /* Look up instance number */
+ instance = FLEXCOMM_GetInstance(FLEXCOMM13);
+ assert(s_flexcommIrqHandler[instance] != NULL);
+ s_flexcommIrqHandler[instance]((uint32_t *)s_flexcommBaseAddrs[instance], s_flexcommHandle[instance]);
+ SDK_ISR_EXIT_BARRIER;
+}
+#endif
+
+#if defined(FLEXCOMM14)
+void FLEXCOMM14_DriverIRQHandler(void);
+void FLEXCOMM14_DriverIRQHandler(void)
+{
+ uint32_t instance;
+
+ /* Look up instance number */
+ instance = FLEXCOMM_GetInstance(FLEXCOMM14);
+ assert(s_flexcommIrqHandler[instance] != NULL);
+ s_flexcommIrqHandler[instance]((uint32_t *)s_flexcommBaseAddrs[instance], s_flexcommHandle[instance]);
+ SDK_ISR_EXIT_BARRIER;
+}
+#endif
+
+#if defined(FLEXCOMM15)
+void FLEXCOMM15_DriverIRQHandler(void);
+void FLEXCOMM15_DriverIRQHandler(void)
+{
+ uint32_t instance;
+
+ /* Look up instance number */
+ instance = FLEXCOMM_GetInstance(FLEXCOMM15);
+ assert(s_flexcommIrqHandler[instance] != NULL);
+ s_flexcommIrqHandler[instance]((uint32_t *)s_flexcommBaseAddrs[instance], s_flexcommHandle[instance]);
+ SDK_ISR_EXIT_BARRIER;
+}
+#endif
+
+#if defined(FLEXCOMM16)
+void FLEXCOMM16_DriverIRQHandler(void);
+void FLEXCOMM16_DriverIRQHandler(void)
+{
+ uint32_t instance;
+
+ /* Look up instance number */
+ instance = FLEXCOMM_GetInstance(FLEXCOMM16);
+ assert(s_flexcommIrqHandler[instance] != NULL);
+ s_flexcommIrqHandler[instance]((uint32_t *)s_flexcommBaseAddrs[instance], s_flexcommHandle[instance]);
+ SDK_ISR_EXIT_BARRIER;
+}
+#endif
diff --git a/drivers/fsl_flexcomm.h b/drivers/fsl_flexcomm.h
new file mode 100644
index 0000000..7fb652b
--- /dev/null
+++ b/drivers/fsl_flexcomm.h
@@ -0,0 +1,64 @@
+/*
+ * Copyright (c) 2016, Freescale Semiconductor, Inc.
+ * Copyright 2016-2019 NXP
+ * All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+#ifndef _FSL_FLEXCOMM_H_
+#define _FSL_FLEXCOMM_H_
+
+#include "fsl_common.h"
+
+/*!
+ * @addtogroup flexcomm_driver
+ * @{
+ */
+
+/*! @name Driver version */
+/*@{*/
+/*! @brief FlexCOMM driver version 2.0.2. */
+#define FSL_FLEXCOMM_DRIVER_VERSION (MAKE_VERSION(2, 0, 2))
+/*@}*/
+
+/*! @brief FLEXCOMM peripheral modes. */
+typedef enum
+{
+ FLEXCOMM_PERIPH_NONE, /*!< No peripheral */
+ FLEXCOMM_PERIPH_USART, /*!< USART peripheral */
+ FLEXCOMM_PERIPH_SPI, /*!< SPI Peripheral */
+ FLEXCOMM_PERIPH_I2C, /*!< I2C Peripheral */
+ FLEXCOMM_PERIPH_I2S_TX, /*!< I2S TX Peripheral */
+ FLEXCOMM_PERIPH_I2S_RX, /*!< I2S RX Peripheral */
+} FLEXCOMM_PERIPH_T;
+
+/*! @brief Typedef for interrupt handler. */
+typedef void (*flexcomm_irq_handler_t)(void *base, void *handle);
+
+/*! @brief Array with IRQ number for each FLEXCOMM module. */
+extern IRQn_Type const kFlexcommIrqs[];
+
+/*******************************************************************************
+ * API
+ ******************************************************************************/
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+/*! @brief Returns instance number for FLEXCOMM module with given base address. */
+uint32_t FLEXCOMM_GetInstance(void *base);
+
+/*! @brief Initializes FLEXCOMM and selects peripheral mode according to the second parameter. */
+status_t FLEXCOMM_Init(void *base, FLEXCOMM_PERIPH_T periph);
+
+/*! @brief Sets IRQ handler for given FLEXCOMM module. It is used by drivers register IRQ handler according to FLEXCOMM
+ * mode */
+void FLEXCOMM_SetIRQHandler(void *base, flexcomm_irq_handler_t handler, void *flexcommHandle);
+
+#if defined(__cplusplus)
+}
+#endif
+
+/*@}*/
+
+#endif /* _FSL_FLEXCOMM_H_*/
diff --git a/drivers/fsl_gpio.c b/drivers/fsl_gpio.c
new file mode 100644
index 0000000..3a0cdd3
--- /dev/null
+++ b/drivers/fsl_gpio.c
@@ -0,0 +1,317 @@
+/*
+ * Copyright (c) 2016, Freescale Semiconductor, Inc.
+ * Copyright 2016-2020 NXP
+ * All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include "fsl_gpio.h"
+
+/* Component ID definition, used by tools. */
+#ifndef FSL_COMPONENT_ID
+#define FSL_COMPONENT_ID "platform.drivers.lpc_gpio"
+#endif
+
+/*******************************************************************************
+ * Variables
+ ******************************************************************************/
+#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
+/*! @brief Array to map FGPIO instance number to clock name. */
+static const clock_ip_name_t s_gpioClockName[] = GPIO_CLOCKS;
+#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
+
+#if !(defined(FSL_FEATURE_GPIO_HAS_NO_RESET) && FSL_FEATURE_GPIO_HAS_NO_RESET)
+/*! @brief Pointers to GPIO resets for each instance. */
+static const reset_ip_name_t s_gpioResets[] = GPIO_RSTS_N;
+#endif
+/*******************************************************************************
+ * Prototypes
+ ************ ******************************************************************/
+/*!
+ * @brief Enable GPIO port clock.
+ *
+ * @param base GPIO peripheral base pointer.
+ * @param port GPIO port number.
+ */
+static void GPIO_EnablePortClock(GPIO_Type *base, uint32_t port);
+
+/*******************************************************************************
+ * Code
+ ******************************************************************************/
+static void GPIO_EnablePortClock(GPIO_Type *base, uint32_t port)
+{
+#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
+ assert(port < ARRAY_SIZE(s_gpioClockName));
+
+ /* Upgate the GPIO clock */
+ CLOCK_EnableClock(s_gpioClockName[port]);
+#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
+}
+
+/*!
+ * brief Initializes the GPIO peripheral.
+ *
+ * This function ungates the GPIO clock.
+ *
+ * param base GPIO peripheral base pointer.
+ * param port GPIO port number.
+ */
+void GPIO_PortInit(GPIO_Type *base, uint32_t port)
+{
+ GPIO_EnablePortClock(base, port);
+
+#if !(defined(FSL_FEATURE_GPIO_HAS_NO_RESET) && FSL_FEATURE_GPIO_HAS_NO_RESET)
+ /* Reset the GPIO module */
+ RESET_PeripheralReset(s_gpioResets[port]);
+#endif
+}
+
+/*!
+ * brief Initializes a GPIO pin used by the board.
+ *
+ * To initialize the GPIO, define a pin configuration, either input or output, in the user file.
+ * Then, call the GPIO_PinInit() function.
+ *
+ * This is an example to define an input pin or output pin configuration:
+ * code
+ * Define a digital input pin configuration,
+ * gpio_pin_config_t config =
+ * {
+ * kGPIO_DigitalInput,
+ * 0,
+ * }
+ * Define a digital output pin configuration,
+ * gpio_pin_config_t config =
+ * {
+ * kGPIO_DigitalOutput,
+ * 0,
+ * }
+ * endcode
+ *
+ * param base GPIO peripheral base pointer(Typically GPIO)
+ * param port GPIO port number
+ * param pin GPIO pin number
+ * param config GPIO pin configuration pointer
+ */
+void GPIO_PinInit(GPIO_Type *base, uint32_t port, uint32_t pin, const gpio_pin_config_t *config)
+{
+ GPIO_EnablePortClock(base, port);
+
+ if (config->pinDirection == kGPIO_DigitalInput)
+ {
+#if defined(FSL_FEATURE_GPIO_DIRSET_AND_DIRCLR) && (FSL_FEATURE_GPIO_DIRSET_AND_DIRCLR)
+ base->DIRCLR[port] = 1UL << pin;
+#else
+ base->DIR[port] &= ~(1UL << pin);
+#endif /*FSL_FEATURE_GPIO_DIRSET_AND_DIRCLR*/
+ }
+ else
+ {
+ /* Set default output value */
+ if (config->outputLogic == 0U)
+ {
+ base->CLR[port] = (1UL << pin);
+ }
+ else
+ {
+ base->SET[port] = (1UL << pin);
+ }
+/* Set pin direction */
+#if defined(FSL_FEATURE_GPIO_DIRSET_AND_DIRCLR) && (FSL_FEATURE_GPIO_DIRSET_AND_DIRCLR)
+ base->DIRSET[port] = 1UL << pin;
+#else
+ base->DIR[port] |= 1UL << pin;
+#endif /*FSL_FEATURE_GPIO_DIRSET_AND_DIRCLR*/
+ }
+}
+
+#if defined(FSL_FEATURE_GPIO_HAS_INTERRUPT) && FSL_FEATURE_GPIO_HAS_INTERRUPT
+/*!
+ * @brief Set the configuration of pin interrupt.
+ *
+ * @param base GPIO base pointer.
+ * @param port GPIO port number
+ * @param pin GPIO pin number.
+ * @param config GPIO pin interrupt configuration..
+ */
+void GPIO_SetPinInterruptConfig(GPIO_Type *base, uint32_t port, uint32_t pin, gpio_interrupt_config_t *config)
+{
+ base->INTEDG[port] = (base->INTEDG[port] & ~(1UL << pin)) | ((uint32_t)config->mode << pin);
+
+ base->INTPOL[port] = (base->INTPOL[port] & ~(1UL << pin)) | ((uint32_t)config->polarity << pin);
+}
+
+/*!
+ * @brief Enables multiple pins interrupt.
+ *
+ * @param base GPIO base pointer.
+ * @param port GPIO port number.
+ * @param index GPIO interrupt number.
+ * @param mask GPIO pin number macro.
+ */
+void GPIO_PortEnableInterrupts(GPIO_Type *base, uint32_t port, uint32_t index, uint32_t mask)
+{
+ if ((uint32_t)kGPIO_InterruptA == index)
+ {
+ base->INTENA[port] = base->INTENA[port] | mask;
+ }
+ else if ((uint32_t)kGPIO_InterruptB == index)
+ {
+ base->INTENB[port] = base->INTENB[port] | mask;
+ }
+ else
+ {
+ /*Should not enter here*/
+ }
+}
+
+/*!
+ * @brief Disables multiple pins interrupt.
+ *
+ * @param base GPIO base pointer.
+ * @param port GPIO port number.
+ * @param index GPIO interrupt number.
+ * @param mask GPIO pin number macro.
+ */
+void GPIO_PortDisableInterrupts(GPIO_Type *base, uint32_t port, uint32_t index, uint32_t mask)
+{
+ if ((uint32_t)kGPIO_InterruptA == index)
+ {
+ base->INTENA[port] = base->INTENA[port] & ~mask;
+ }
+ else if ((uint32_t)kGPIO_InterruptB == index)
+ {
+ base->INTENB[port] = base->INTENB[port] & ~mask;
+ }
+ else
+ {
+ /*Should not enter here*/
+ }
+}
+
+/*!
+ * @brief Clears multiple pins interrupt flag. Status flags are cleared by
+ * writing a 1 to the corresponding bit position.
+ *
+ * @param base GPIO base pointer.
+ * @param port GPIO port number.
+ * @param index GPIO interrupt number.
+ * @param mask GPIO pin number macro.
+ */
+void GPIO_PortClearInterruptFlags(GPIO_Type *base, uint32_t port, uint32_t index, uint32_t mask)
+{
+ if ((uint32_t)kGPIO_InterruptA == index)
+ {
+ base->INTSTATA[port] = mask;
+ }
+ else if ((uint32_t)kGPIO_InterruptB == index)
+ {
+ base->INTSTATB[port] = mask;
+ }
+ else
+ {
+ /*Should not enter here*/
+ }
+}
+
+/*!
+ * @ Read port interrupt status.
+ *
+ * @param base GPIO base pointer.
+ * @param port GPIO port number
+ * @param index GPIO interrupt number.
+ * @retval masked GPIO status value
+ */
+uint32_t GPIO_PortGetInterruptStatus(GPIO_Type *base, uint32_t port, uint32_t index)
+{
+ uint32_t status = 0U;
+
+ if ((uint32_t)kGPIO_InterruptA == index)
+ {
+ status = base->INTSTATA[port];
+ }
+ else if ((uint32_t)kGPIO_InterruptB == index)
+ {
+ status = base->INTSTATB[port];
+ }
+ else
+ {
+ /*Should not enter here*/
+ }
+ return status;
+}
+
+/*!
+ * @brief Enables the specific pin interrupt.
+ *
+ * @param base GPIO base pointer.
+ * @param port GPIO port number.
+ * @param pin GPIO pin number.
+ * @param index GPIO interrupt number.
+ */
+void GPIO_PinEnableInterrupt(GPIO_Type *base, uint32_t port, uint32_t pin, uint32_t index)
+{
+ if ((uint32_t)kGPIO_InterruptA == index)
+ {
+ base->INTENA[port] = base->INTENA[port] | (1UL << pin);
+ }
+ else if ((uint32_t)kGPIO_InterruptB == index)
+ {
+ base->INTENB[port] = base->INTENB[port] | (1UL << pin);
+ }
+ else
+ {
+ /*Should not enter here*/
+ }
+}
+
+/*!
+ * @brief Disables the specific pin interrupt.
+ *
+ * @param base GPIO base pointer.
+ * @param port GPIO port number.
+ * @param pin GPIO pin number.
+ * @param index GPIO interrupt number.
+ */
+void GPIO_PinDisableInterrupt(GPIO_Type *base, uint32_t port, uint32_t pin, uint32_t index)
+{
+ if ((uint32_t)kGPIO_InterruptA == index)
+ {
+ base->INTENA[port] = base->INTENA[port] & ~(1UL << pin);
+ }
+ else if ((uint32_t)kGPIO_InterruptB == index)
+ {
+ base->INTENB[port] = base->INTENB[port] & ~(1UL << pin);
+ }
+ else
+ {
+ /*Should not enter here*/
+ }
+}
+
+/*!
+ * @brief Clears the specific pin interrupt flag. Status flags are cleared by
+ * writing a 1 to the corresponding bit position.
+ *
+ * @param base GPIO base pointer.
+ * @param port GPIO port number.
+ * @param index GPIO interrupt number.
+ * @param mask GPIO pin number macro.
+ */
+void GPIO_PinClearInterruptFlag(GPIO_Type *base, uint32_t port, uint32_t pin, uint32_t index)
+{
+ if ((uint32_t)kGPIO_InterruptA == index)
+ {
+ base->INTSTATA[port] = 1UL << pin;
+ }
+ else if ((uint32_t)kGPIO_InterruptB == index)
+ {
+ base->INTSTATB[port] = 1UL << pin;
+ }
+ else
+ {
+ /*Should not enter here*/
+ }
+}
+#endif /* FSL_FEATURE_GPIO_HAS_INTERRUPT */
diff --git a/drivers/fsl_gpio.h b/drivers/fsl_gpio.h
new file mode 100644
index 0000000..f746eba
--- /dev/null
+++ b/drivers/fsl_gpio.h
@@ -0,0 +1,364 @@
+/*
+ * Copyright (c) 2016, Freescale Semiconductor, Inc.
+ * Copyright 2016-2020 NXP
+ * All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef _LPC_GPIO_H_
+#define _LPC_GPIO_H_
+
+#include "fsl_common.h"
+
+/*!
+ * @addtogroup lpc_gpio
+ * @{
+ */
+
+/*! @file */
+
+/*******************************************************************************
+ * Definitions
+ ******************************************************************************/
+
+/*! @name Driver version */
+/*@{*/
+/*! @brief LPC GPIO driver version. */
+#define FSL_GPIO_DRIVER_VERSION (MAKE_VERSION(2, 1, 7))
+/*@}*/
+
+/*! @brief LPC GPIO direction definition */
+typedef enum _gpio_pin_direction
+{
+ kGPIO_DigitalInput = 0U, /*!< Set current pin as digital input*/
+ kGPIO_DigitalOutput = 1U, /*!< Set current pin as digital output*/
+} gpio_pin_direction_t;
+
+/*!
+ * @brief The GPIO pin configuration structure.
+ *
+ * Every pin can only be configured as either output pin or input pin at a time.
+ * If configured as a input pin, then leave the outputConfig unused.
+ */
+typedef struct _gpio_pin_config
+{
+ gpio_pin_direction_t pinDirection; /*!< GPIO direction, input or output */
+ /* Output configurations, please ignore if configured as a input one */
+ uint8_t outputLogic; /*!< Set default output logic, no use in input */
+} gpio_pin_config_t;
+
+#if (defined(FSL_FEATURE_GPIO_HAS_INTERRUPT) && FSL_FEATURE_GPIO_HAS_INTERRUPT)
+#define GPIO_PIN_INT_LEVEL 0x00U
+#define GPIO_PIN_INT_EDGE 0x01U
+
+#define PINT_PIN_INT_HIGH_OR_RISE_TRIGGER 0x00U
+#define PINT_PIN_INT_LOW_OR_FALL_TRIGGER 0x01U
+
+/*! @brief GPIO Pin Interrupt enable mode */
+typedef enum _gpio_pin_enable_mode
+{
+ kGPIO_PinIntEnableLevel = GPIO_PIN_INT_LEVEL, /*!< Generate Pin Interrupt on level mode */
+ kGPIO_PinIntEnableEdge = GPIO_PIN_INT_EDGE /*!< Generate Pin Interrupt on edge mode */
+} gpio_pin_enable_mode_t;
+
+/*! @brief GPIO Pin Interrupt enable polarity */
+typedef enum _gpio_pin_enable_polarity
+{
+ kGPIO_PinIntEnableHighOrRise =
+ PINT_PIN_INT_HIGH_OR_RISE_TRIGGER, /*!< Generate Pin Interrupt on high level or rising edge */
+ kGPIO_PinIntEnableLowOrFall =
+ PINT_PIN_INT_LOW_OR_FALL_TRIGGER /*!< Generate Pin Interrupt on low level or falling edge */
+} gpio_pin_enable_polarity_t;
+
+/*! @brief LPC GPIO interrupt index definition */
+typedef enum _gpio_interrupt_index
+{
+ kGPIO_InterruptA = 0U, /*!< Set current pin as interrupt A*/
+ kGPIO_InterruptB = 1U, /*!< Set current pin as interrupt B*/
+} gpio_interrupt_index_t;
+
+/*! @brief Configures the interrupt generation condition. */
+typedef struct _gpio_interrupt_config
+{
+ uint8_t mode; /* The trigger mode of GPIO interrupts */
+ uint8_t polarity; /* The polarity of GPIO interrupts */
+} gpio_interrupt_config_t;
+#endif
+
+/*******************************************************************************
+ * API
+ ******************************************************************************/
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+/*! @name GPIO Configuration */
+/*@{*/
+
+/*!
+ * @brief Initializes the GPIO peripheral.
+ *
+ * This function ungates the GPIO clock.
+ *
+ * @param base GPIO peripheral base pointer.
+ * @param port GPIO port number.
+ */
+void GPIO_PortInit(GPIO_Type *base, uint32_t port);
+
+/*!
+ * @brief Initializes a GPIO pin used by the board.
+ *
+ * To initialize the GPIO, define a pin configuration, either input or output, in the user file.
+ * Then, call the GPIO_PinInit() function.
+ *
+ * This is an example to define an input pin or output pin configuration:
+ * @code
+ * Define a digital input pin configuration,
+ * gpio_pin_config_t config =
+ * {
+ * kGPIO_DigitalInput,
+ * 0,
+ * }
+ * Define a digital output pin configuration,
+ * gpio_pin_config_t config =
+ * {
+ * kGPIO_DigitalOutput,
+ * 0,
+ * }
+ * @endcode
+ *
+ * @param base GPIO peripheral base pointer(Typically GPIO)
+ * @param port GPIO port number
+ * @param pin GPIO pin number
+ * @param config GPIO pin configuration pointer
+ */
+void GPIO_PinInit(GPIO_Type *base, uint32_t port, uint32_t pin, const gpio_pin_config_t *config);
+
+/*@}*/
+
+/*! @name GPIO Output Operations */
+/*@{*/
+
+/*!
+ * @brief Sets the output level of the one GPIO pin to the logic 1 or 0.
+ *
+ * @param base GPIO peripheral base pointer(Typically GPIO)
+ * @param port GPIO port number
+ * @param pin GPIO pin number
+ * @param output GPIO pin output logic level.
+ * - 0: corresponding pin output low-logic level.
+ * - 1: corresponding pin output high-logic level.
+ */
+static inline void GPIO_PinWrite(GPIO_Type *base, uint32_t port, uint32_t pin, uint8_t output)
+{
+ base->B[port][pin] = output;
+}
+
+/*@}*/
+/*! @name GPIO Input Operations */
+/*@{*/
+
+/*!
+ * @brief Reads the current input value of the GPIO PIN.
+ *
+ * @param base GPIO peripheral base pointer(Typically GPIO)
+ * @param port GPIO port number
+ * @param pin GPIO pin number
+ * @retval GPIO port input value
+ * - 0: corresponding pin input low-logic level.
+ * - 1: corresponding pin input high-logic level.
+ */
+static inline uint32_t GPIO_PinRead(GPIO_Type *base, uint32_t port, uint32_t pin)
+{
+ return (uint32_t)base->B[port][pin];
+}
+
+/*@}*/
+
+/*!
+ * @brief Sets the output level of the multiple GPIO pins to the logic 1.
+ *
+ * @param base GPIO peripheral base pointer(Typically GPIO)
+ * @param port GPIO port number
+ * @param mask GPIO pin number macro
+ */
+static inline void GPIO_PortSet(GPIO_Type *base, uint32_t port, uint32_t mask)
+{
+ base->SET[port] = mask;
+}
+
+/*!
+ * @brief Sets the output level of the multiple GPIO pins to the logic 0.
+ *
+ * @param base GPIO peripheral base pointer(Typically GPIO)
+ * @param port GPIO port number
+ * @param mask GPIO pin number macro
+ */
+static inline void GPIO_PortClear(GPIO_Type *base, uint32_t port, uint32_t mask)
+{
+ base->CLR[port] = mask;
+}
+
+/*!
+ * @brief Reverses current output logic of the multiple GPIO pins.
+ *
+ * @param base GPIO peripheral base pointer(Typically GPIO)
+ * @param port GPIO port number
+ * @param mask GPIO pin number macro
+ */
+static inline void GPIO_PortToggle(GPIO_Type *base, uint32_t port, uint32_t mask)
+{
+ base->NOT[port] = mask;
+}
+
+/*@}*/
+
+/*!
+ * @brief Reads the current input value of the whole GPIO port.
+ *
+ * @param base GPIO peripheral base pointer(Typically GPIO)
+ * @param port GPIO port number
+ */
+static inline uint32_t GPIO_PortRead(GPIO_Type *base, uint32_t port)
+{
+ return (uint32_t)base->PIN[port];
+}
+
+/*@}*/
+/*! @name GPIO Mask Operations */
+/*@{*/
+
+/*!
+ * @brief Sets port mask, 0 - enable pin, 1 - disable pin.
+ *
+ * @param base GPIO peripheral base pointer(Typically GPIO)
+ * @param port GPIO port number
+ * @param mask GPIO pin number macro
+ */
+static inline void GPIO_PortMaskedSet(GPIO_Type *base, uint32_t port, uint32_t mask)
+{
+ base->MASK[port] = mask;
+}
+
+/*!
+ * @brief Sets the output level of the masked GPIO port. Only pins enabled by GPIO_SetPortMask() will be affected.
+ *
+ * @param base GPIO peripheral base pointer(Typically GPIO)
+ * @param port GPIO port number
+ * @param output GPIO port output value.
+ */
+static inline void GPIO_PortMaskedWrite(GPIO_Type *base, uint32_t port, uint32_t output)
+{
+ base->MPIN[port] = output;
+}
+
+/*!
+ * @brief Reads the current input value of the masked GPIO port. Only pins enabled by GPIO_SetPortMask() will be
+ * affected.
+ *
+ * @param base GPIO peripheral base pointer(Typically GPIO)
+ * @param port GPIO port number
+ * @retval masked GPIO port value
+ */
+static inline uint32_t GPIO_PortMaskedRead(GPIO_Type *base, uint32_t port)
+{
+ return (uint32_t)base->MPIN[port];
+}
+
+#if defined(FSL_FEATURE_GPIO_HAS_INTERRUPT) && FSL_FEATURE_GPIO_HAS_INTERRUPT
+/*!
+ * @brief Set the configuration of pin interrupt.
+ *
+ * @param base GPIO base pointer.
+ * @param port GPIO port number
+ * @param pin GPIO pin number.
+ * @param config GPIO pin interrupt configuration..
+ */
+void GPIO_SetPinInterruptConfig(GPIO_Type *base, uint32_t port, uint32_t pin, gpio_interrupt_config_t *config);
+
+/*!
+ * @brief Enables multiple pins interrupt.
+ *
+ * @param base GPIO base pointer.
+ * @param port GPIO port number.
+ * @param index GPIO interrupt number.
+ * @param mask GPIO pin number macro.
+ */
+void GPIO_PortEnableInterrupts(GPIO_Type *base, uint32_t port, uint32_t index, uint32_t mask);
+
+/*!
+ * @brief Disables multiple pins interrupt.
+ *
+ * @param base GPIO base pointer.
+ * @param port GPIO port number.
+ * @param index GPIO interrupt number.
+ * @param mask GPIO pin number macro.
+ */
+void GPIO_PortDisableInterrupts(GPIO_Type *base, uint32_t port, uint32_t index, uint32_t mask);
+
+/*!
+ * @brief Clears pin interrupt flag. Status flags are cleared by
+ * writing a 1 to the corresponding bit position.
+ *
+ * @param base GPIO base pointer.
+ * @param port GPIO port number.
+ * @param index GPIO interrupt number.
+ * @param mask GPIO pin number macro.
+ */
+void GPIO_PortClearInterruptFlags(GPIO_Type *base, uint32_t port, uint32_t index, uint32_t mask);
+
+/*!
+ * @ Read port interrupt status.
+ *
+ * @param base GPIO base pointer.
+ * @param port GPIO port number
+ * @param index GPIO interrupt number.
+ * @retval masked GPIO status value
+ */
+uint32_t GPIO_PortGetInterruptStatus(GPIO_Type *base, uint32_t port, uint32_t index);
+
+/*!
+ * @brief Enables the specific pin interrupt.
+ *
+ * @param base GPIO base pointer.
+ * @param port GPIO port number.
+ * @param pin GPIO pin number.
+ * @param index GPIO interrupt number.
+ */
+void GPIO_PinEnableInterrupt(GPIO_Type *base, uint32_t port, uint32_t pin, uint32_t index);
+
+/*!
+ * @brief Disables the specific pin interrupt.
+ *
+ * @param base GPIO base pointer.
+ * @param port GPIO port number.
+ * @param pin GPIO pin number.
+ * @param index GPIO interrupt number.
+ */
+void GPIO_PinDisableInterrupt(GPIO_Type *base, uint32_t port, uint32_t pin, uint32_t index);
+
+/*!
+ * @brief Clears the specific pin interrupt flag. Status flags are cleared by
+ * writing a 1 to the corresponding bit position.
+ *
+ * @param base GPIO base pointer.
+ * @param port GPIO port number.
+ * @param pin GPIO pin number.
+ * @param index GPIO interrupt number.
+ */
+void GPIO_PinClearInterruptFlag(GPIO_Type *base, uint32_t port, uint32_t pin, uint32_t index);
+
+#endif /* FSL_FEATURE_GPIO_HAS_INTERRUPT */
+
+/*@}*/
+
+#if defined(__cplusplus)
+}
+#endif
+
+/*!
+ * @}
+ */
+
+#endif /* _LPC_GPIO_H_*/
diff --git a/drivers/fsl_i2c.c b/drivers/fsl_i2c.c
new file mode 100644
index 0000000..9f02622
--- /dev/null
+++ b/drivers/fsl_i2c.c
@@ -0,0 +1,2085 @@
+/*
+ * Copyright (c) 2016, Freescale Semiconductor, Inc.
+ * Copyright 2016-2021 NXP
+ * All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include "fsl_i2c.h"
+#include "fsl_flexcomm.h"
+#include
+#include
+
+/*******************************************************************************
+ * Definitions
+ ******************************************************************************/
+
+/* Component ID definition, used by tools. */
+#ifndef FSL_COMPONENT_ID
+#define FSL_COMPONENT_ID "platform.drivers.flexcomm_i2c"
+#endif
+
+/*! @brief Common sets of flags used by the driver's transactional layer internally. */
+enum _i2c_flag_constants
+{
+ kI2C_MasterIrqFlags = I2C_INTSTAT_MSTPENDING_MASK | I2C_INTSTAT_MSTARBLOSS_MASK | I2C_INTSTAT_MSTSTSTPERR_MASK |
+ I2C_INTSTAT_EVENTTIMEOUT_MASK | I2C_INTSTAT_SCLTIMEOUT_MASK,
+ kI2C_SlaveIrqFlags = I2C_INTSTAT_SLVPENDING_MASK | I2C_INTSTAT_SLVDESEL_MASK,
+};
+
+/*!
+ * @brief Used for conversion from `flexcomm_irq_handler_t` to `flexcomm_i2c_master_irq_handler_t` and
+ * `flexcomm_i2c_slave_irq_handler_t`.
+ */
+typedef union i2c_to_flexcomm
+{
+ flexcomm_i2c_master_irq_handler_t i2c_master_handler;
+ flexcomm_i2c_slave_irq_handler_t i2c_slave_handler;
+ flexcomm_irq_handler_t flexcomm_handler;
+} i2c_to_flexcomm_t;
+
+/*******************************************************************************
+ * Prototypes
+ ******************************************************************************/
+/*!
+ * @brief Waits for Master Pending status bit to set and check for bus error status.
+ *
+ * @param base The I2C peripheral base address.
+ * @return Bus status.
+ */
+static status_t I2C_PendingStatusWait(I2C_Type *base);
+
+/*!
+ * @brief Prepares the transfer state machine and fills in the command buffer.
+ * @param base The I2C peripheral base address.
+ * @param handle Master nonblocking driver handle.
+ * @param xfer The I2C transfer configuration structure.
+ */
+static status_t I2C_InitTransferStateMachine(I2C_Type *base, i2c_master_handle_t *handle, i2c_master_transfer_t *xfer);
+
+/*!
+ * @brief Resets the slave hardware state machine.
+ * According to documentation, after disabling slave to rest the slave hardware state machine, the register
+ * configuration remains unchanged.
+ * @param base The I2C peripheral base address.
+ */
+static void I2C_SlaveInternalStateMachineReset(I2C_Type *base);
+
+/*!
+ * @brief Compute CLKDIV
+ *
+ * This function computes CLKDIV value according to the given bus speed and Flexcomm source clock frequency.
+ * This setting is used by hardware during slave clock stretching.
+ *
+ * @param base The I2C peripheral base address.
+ * @return status of the operation
+ */
+static status_t I2C_SlaveDivVal(uint32_t srcClock_Hz, i2c_slave_bus_speed_t busSpeed, uint32_t *divVal);
+
+/*!
+ * @brief Poll wait for the SLVPENDING flag.
+ *
+ * Wait for the pending status to be set (SLVPENDING = 1) by polling the STAT register.
+ *
+ * @param base The I2C peripheral base address.
+ * @return status register at time the SLVPENDING bit is read as set
+ */
+static uint32_t I2C_SlavePollPending(I2C_Type *base);
+
+/*!
+ * @brief Invoke event from I2C_SlaveTransferHandleIRQ().
+ *
+ * Sets the event type to transfer structure and invokes the event callback, if it has been
+ * enabled by eventMask.
+ *
+ * @param base The I2C peripheral base address.
+ * @param handle The I2C slave handle for non-blocking APIs.
+ * @param event The I2C slave event to invoke.
+ */
+static void I2C_SlaveInvokeEvent(I2C_Type *base, i2c_slave_handle_t *handle, i2c_slave_transfer_event_t event);
+
+/*!
+ * @brief Handle slave address match event.
+ *
+ * Called by Slave interrupt routine to ACK or NACK the matched address.
+ * It also determines master direction (read or write).
+ *
+ * @param base The I2C peripheral base address.
+ * @return true if the matched address is ACK'ed
+ * @return false if the matched address is NACK'ed
+ */
+static bool I2C_SlaveAddressIRQ(I2C_Type *base, i2c_slave_handle_t *handle);
+
+/*!
+ * @brief Starts accepting slave transfers.
+ *
+ * Call this API after calling I2C_SlaveInit() and I2C_SlaveTransferCreateHandle() to start processing
+ * transactions driven by an I2C master. The slave monitors the I2C bus and pass events to the
+ * callback that was passed into the call to I2C_SlaveTransferCreateHandle(). The callback is always invoked
+ * from the interrupt context.
+ *
+ * @param base The I2C peripheral base address.
+ * @param handle Pointer to #i2c_slave_handle_t structure which stores the transfer state.
+ * @param txData Data to be transmitted to master in response to master read from slave requests. NULL if slave RX only.
+ * @param txSize Size of txData buffer in bytes.
+ * @param rxData Data where received data from master will be stored in response to master write to slave requests. NULL
+ * if slave TX only.
+ * @param rxSize Size of rxData buffer in bytes.
+ * @retval #kStatus_Success Slave transfers were successfully started.
+ * @retval #kStatus_I2C_Busy Slave transfers have already been started on this handle.
+ */
+static status_t I2C_SlaveTransferNonBlockingInternal(I2C_Type *base,
+ i2c_slave_handle_t *handle,
+ const void *txData,
+ size_t txSize,
+ void *rxData,
+ size_t rxSize,
+ uint32_t eventMask);
+
+/*!
+ * @brief Execute master transfer software state machine until FIFOs are exhausted.
+ *
+ * For master transmit, the states would be kStartState->kTransmitSubaddrState->kTransmitDataState->kStopState
+ * For master receive, the states would be kStartState->kTransmitSubaddrState->kStartState->kReceiveDataState->
+ * kWaitForCompletionState
+ *
+ * @param handle Master nonblocking driver handle.
+ * @param[out] isDone Set to true if the transfer has completed.
+ * @retval #kStatus_Success
+ * @retval #kStatus_I2C_ArbitrationLost
+ * @retval #kStatus_I2C_Nak
+ */
+static status_t I2C_RunTransferStateMachine(I2C_Type *base, i2c_master_handle_t *handle, bool *isDone);
+
+/*!
+ * @brief Checks the slave response to master's start signal.
+ *
+ * @param base I2C peripheral base address.
+ * @retval kStatus_Success Successfully complete the data transmission.
+ * @retval kStatus_I2C_Timeout Transfer error, wait signal timeout.
+ * @retval kStataus_I2C_Nak Transfer error, receive NAK during addressing.
+ */
+static status_t I2C_MasterCheckStartResponse(I2C_Type *base);
+/*******************************************************************************
+ * Variables
+ ******************************************************************************/
+
+/*! @brief Array to map i2c instance number to base address. */
+static const uint32_t s_i2cBaseAddrs[FSL_FEATURE_SOC_I2C_COUNT] = I2C_BASE_ADDRS;
+
+/*! @brief IRQ name array */
+static const IRQn_Type s_i2cIRQ[] = I2C_IRQS;
+
+/*******************************************************************************
+ * Code
+ ******************************************************************************/
+
+/*!
+ * brief Returns an instance number given a base address.
+ *
+ * If an invalid base address is passed, debug builds will assert. Release builds will just return
+ * instance number 0.
+ *
+ * param base The I2C peripheral base address.
+ * return I2C instance number starting from 0.
+ */
+uint32_t I2C_GetInstance(I2C_Type *base)
+{
+ uint32_t i;
+ for (i = 0; i < (uint32_t)FSL_FEATURE_SOC_I2C_COUNT; i++)
+ {
+ if ((uint32_t)base == s_i2cBaseAddrs[i])
+ {
+ break;
+ }
+ }
+ assert(i < (uint32_t)FSL_FEATURE_SOC_I2C_COUNT);
+ return i;
+}
+
+/*!
+ * brief Provides a default configuration for the I2C master peripheral.
+ *
+ * This function provides the following default configuration for the I2C master peripheral:
+ * code
+ * masterConfig->enableMaster = true;
+ * masterConfig->baudRate_Bps = 100000U;
+ * masterConfig->enableTimeout = false;
+ * endcode
+ *
+ * After calling this function, you can override any settings in order to customize the configuration,
+ * prior to initializing the master driver with I2C_MasterInit().
+ *
+ * param[out] masterConfig User provided configuration structure for default values. Refer to #i2c_master_config_t.
+ */
+void I2C_MasterGetDefaultConfig(i2c_master_config_t *masterConfig)
+{
+ /* Initializes the configure structure to zero. */
+ (void)memset(masterConfig, 0, sizeof(*masterConfig));
+
+ masterConfig->enableMaster = true;
+ masterConfig->baudRate_Bps = 100000U;
+ masterConfig->enableTimeout = false;
+ masterConfig->timeout_Ms = 35;
+}
+
+/*!
+ * brief Initializes the I2C master peripheral.
+ *
+ * This function enables the peripheral clock and initializes the I2C master peripheral as described by the user
+ * provided configuration. A software reset is performed prior to configuration.
+ *
+ * param base The I2C peripheral base address.
+ * param masterConfig User provided peripheral configuration. Use I2C_MasterGetDefaultConfig() to get a set of
+ * defaults
+ * that you can override.
+ * param srcClock_Hz Frequency in Hertz of the I2C functional clock. Used to calculate the baud rate divisors,
+ * filter widths, and timeout periods.
+ */
+void I2C_MasterInit(I2C_Type *base, const i2c_master_config_t *masterConfig, uint32_t srcClock_Hz)
+{
+ (void)FLEXCOMM_Init(base, FLEXCOMM_PERIPH_I2C);
+ I2C_MasterEnable(base, masterConfig->enableMaster);
+ I2C_MasterSetBaudRate(base, masterConfig->baudRate_Bps, srcClock_Hz);
+ I2C_MasterSetTimeoutValue(base, masterConfig->timeout_Ms, srcClock_Hz);
+}
+
+/*!
+ * brief Deinitializes the I2C master peripheral.
+ *
+ * This function disables the I2C master peripheral and gates the clock. It also performs a software
+ * reset to restore the peripheral to reset conditions.
+ *
+ * param base The I2C peripheral base address.
+ */
+void I2C_MasterDeinit(I2C_Type *base)
+{
+ I2C_MasterEnable(base, false);
+}
+
+/*!
+ * brief Gets the I2C status flags.
+ *
+ * A bit mask with the state of all I2C status flags is returned. For each flag, the corresponding bit
+ * in the return value is set if the flag is asserted.
+ *
+ * param base The I2C peripheral base address.
+ * return State of the status flags:
+ * - 1: related status flag is set.
+ * - 0: related status flag is not set.
+ * see ref _i2c_status_flags, ref _i2c_master_status_flags and ref _i2c_slave_status_flags.
+ */
+uint32_t I2C_GetStatusFlags(I2C_Type *base)
+{
+ uint32_t statusMask = base->STAT;
+ if ((statusMask & (uint32_t)I2C_STAT_MSTSTATE_MASK) == 0UL)
+ {
+ statusMask |= (uint32_t)kI2C_MasterIdleFlag;
+ }
+ if (((statusMask & (uint32_t)I2C_STAT_MSTSTATE_MASK) >> I2C_STAT_MSTSTATE_SHIFT) == 3UL)
+ {
+ statusMask = (statusMask & ~(uint32_t)I2C_STAT_MSTSTATE_MASK) | (uint32_t)kI2C_MasterAddrNackFlag;
+ }
+ if ((statusMask & (uint32_t)I2C_STAT_SLVSTATE_MASK) == 0UL)
+ {
+ statusMask |= (uint32_t)kI2C_SlaveAddressedFlag;
+ }
+ if ((statusMask & (uint32_t)I2C_STAT_SLVIDX_MASK) == 0UL)
+ {
+ statusMask |= (uint32_t)kI2C_SlaveAddress0MatchFlag;
+ }
+ if (((statusMask & (uint32_t)I2C_STAT_SLVIDX_MASK) >> I2C_STAT_SLVIDX_SHIFT) == 3UL)
+ {
+ statusMask = (statusMask & ~(uint32_t)I2C_STAT_SLVIDX_MASK) | (uint32_t)kI2C_SlaveAddress3MatchFlag;
+ }
+ return statusMask;
+}
+
+/*!
+ * brief Sets the I2C bus frequency for master transactions.
+ *
+ * The I2C master is automatically disabled and re-enabled as necessary to configure the baud
+ * rate. Do not call this function during a transfer, or the transfer is aborted.
+ *
+ * param base The I2C peripheral base address.
+ * param srcClock_Hz I2C functional clock frequency in Hertz.
+ * param baudRate_Bps Requested bus frequency in bits per second.
+ */
+void I2C_MasterSetBaudRate(I2C_Type *base, uint32_t baudRate_Bps, uint32_t srcClock_Hz)
+{
+ uint32_t scl, divider;
+ uint32_t mindivider;
+ uint32_t err, best_err;
+ uint32_t best_scl = 0U;
+ uint32_t best_div = 0U;
+
+#if defined(FSL_FEATURE_I2C_PREPCLKFRG_8MHZ) && (FSL_FEATURE_I2C_PREPCLKFRG_8MHZ)
+ /*
+ * RFT1717/RFT1437: workaround for hardware bug when using DMA
+ * I2C peripheral clock frequency has to be fixed at 8MHz
+ * source clock is 32MHz or 48MHz so divider is a round integer value
+ */
+ best_div = srcClock_Hz / 8000000U;
+ best_scl = 8000000U / baudRate_Bps;
+
+ if ((8000000U / best_scl - baudRate_Bps) > (baudRate_Bps - (8000000U / (best_scl + 1U))))
+ {
+ best_scl = best_scl + 1U;
+ }
+
+ /*
+ * Fallback to usual baudrate computation method, when:
+ * 1.Master SCL frequency does not fit in workaround range,
+ * 2.User's setting of baudRate_Bps is 400kHz while the clock frequency after divval is larger than 2MHz
+ */
+ if ((best_scl > 18U) || ((best_scl < 4U)) || ((baudRate_Bps == 400000U) && (srcClock_Hz / best_div > 2000000U)))
+ {
+#endif /*FSL_FEATURE_I2C_PREPCLKFRG_8MHZ*/
+
+ /* Calculate the minimal divider value to make sure the clock frequency after divval is not larger than 2MHz */
+ /* This is required in RM in order to generate 400kHz baudrate */
+ mindivider = ((srcClock_Hz * 10U) / 2000000U + 5U) / 10U;
+ /* If the scl value with current mindivider is smaller than 4, which is the minimal value register can achieve,
+ update mindivider */
+ if ((srcClock_Hz / mindivider / baudRate_Bps) < 4U)
+ {
+ mindivider = srcClock_Hz / 4U / baudRate_Bps;
+ }
+ /* Calculate the ideal div and scl value*/
+ best_err = 0U;
+ for (divider = mindivider; divider <= 0x10000U; divider++)
+ {
+ /* Calculte ideal scl value, round up the value */
+ scl = ((srcClock_Hz * 10U) / (divider * baudRate_Bps) + 5U) / 10U;
+
+ /* adjust it if it is out of range */
+ scl = (scl > 18U) ? 18U : scl;
+
+ /* calculate error */
+ err = srcClock_Hz - (baudRate_Bps * scl * divider);
+ if ((err < best_err) || (best_err == 0U))
+ {
+ best_div = divider;
+ best_scl = scl;
+ best_err = err;
+ }
+
+ if ((err == 0U) || (scl <= 4U))
+ {
+ /* either exact value was found
+ or scl is at its min (it would be even smaller in the next iteration for sure) */
+ break;
+ }
+ }
+#if defined(FSL_FEATURE_I2C_PREPCLKFRG_8MHZ) && (FSL_FEATURE_I2C_PREPCLKFRG_8MHZ)
+ }
+#endif /*FSL_FEATURE_I2C_PREPCLKFRG_8MHZ*/
+ base->CLKDIV = I2C_CLKDIV_DIVVAL(best_div - 1U);
+ if (best_scl % 2U == 0U)
+ {
+ base->MSTTIME = I2C_MSTTIME_MSTSCLLOW(best_scl / 2U - 2U) | I2C_MSTTIME_MSTSCLHIGH(best_scl / 2U - 2U);
+ }
+ else
+ {
+ base->MSTTIME = I2C_MSTTIME_MSTSCLLOW(best_scl / 2U - 1U) | I2C_MSTTIME_MSTSCLHIGH(best_scl / 2U - 2U);
+ }
+}
+
+/*!
+ * brief Sets the I2C bus timeout value.
+ *
+ * If the SCL signal remains low or bus does not have event longer than the timeout value, kI2C_SclTimeoutFlag or
+ * kI2C_EventTimeoutFlag is set. This can indicete the bus is held by slave or any fault occurs to the I2C module.
+ *
+ * param base The I2C peripheral base address.
+ * param timeout_Ms Timeout value in millisecond.
+ * param srcClock_Hz I2C functional clock frequency in Hertz.
+ */
+void I2C_MasterSetTimeoutValue(I2C_Type *base, uint8_t timeout_Ms, uint32_t srcClock_Hz)
+{
+ assert((timeout_Ms != 0U) && (srcClock_Hz != 0U));
+
+ /* The low 4 bits of the timout reister TIMEOUT is hard-wired to be 1, so the the time out value is always 16 times
+ the I2C functional clock, we only need to calculate the high bits. */
+ uint32_t timeoutValue = ((uint32_t)timeout_Ms * srcClock_Hz / 16UL / 100UL + 5UL) / 10UL;
+ if (timeoutValue > 0x1000UL)
+ {
+ timeoutValue = 0x1000UL;
+ }
+ timeoutValue = ((timeoutValue - 1UL) << 4UL) | 0xFUL;
+ base->TIMEOUT = timeoutValue;
+}
+
+static status_t I2C_PendingStatusWait(I2C_Type *base)
+{
+ status_t result = kStatus_Success;
+ uint32_t status;
+
+#if I2C_RETRY_TIMES != 0U
+ uint32_t waitTimes = I2C_RETRY_TIMES;
+#endif
+
+ do
+ {
+ status = I2C_GetStatusFlags(base);
+ if ((status & (uint32_t)kI2C_EventTimeoutFlag) != 0U)
+ {
+ result = kStatus_I2C_EventTimeout;
+ }
+ if ((status & (uint32_t)kI2C_SclTimeoutFlag) != 0U)
+ {
+ result = kStatus_I2C_SclLowTimeout;
+ }
+#if defined(FSL_FEATURE_I2C_TIMEOUT_RECOVERY) && FSL_FEATURE_I2C_TIMEOUT_RECOVERY
+ if (result != kStatus_Success)
+ {
+ I2C_MasterEnable(base, false);
+ I2C_MasterEnable(base, true);
+ break;
+ }
+#endif
+#if I2C_RETRY_TIMES != 0U
+ waitTimes--;
+ } while (((status & (uint32_t)kI2C_MasterPendingFlag) == 0U) && (waitTimes != 0U));
+
+ if (waitTimes == 0U)
+ {
+#if defined(FSL_FEATURE_I2C_TIMEOUT_RECOVERY) && FSL_FEATURE_I2C_TIMEOUT_RECOVERY
+ I2C_MasterEnable(base, false);
+ I2C_MasterEnable(base, true);
+#endif
+ return kStatus_I2C_Timeout;
+ }
+#else
+ } while ((status & (uint32_t)kI2C_MasterPendingFlag) == 0U);
+#endif
+
+ if ((status & (uint32_t)kI2C_MasterArbitrationLostFlag) != 0U)
+ {
+ result = kStatus_I2C_ArbitrationLost;
+ }
+
+ if ((status & (uint32_t)kI2C_MasterStartStopErrorFlag) != 0U)
+ {
+ result = kStatus_I2C_StartStopError;
+ }
+
+ /* Clear controller state. */
+ I2C_ClearStatusFlags(
+ base, (uint32_t)kI2C_MasterAllClearFlags | (uint32_t)kI2C_EventTimeoutFlag | (uint32_t)kI2C_SclTimeoutFlag);
+
+ return result;
+}
+
+/*!
+ * brief Sends a START on the I2C bus.
+ *
+ * This function is used to initiate a new master mode transfer by sending the START signal.
+ * The slave address is sent following the I2C START signal.
+ *
+ * param base I2C peripheral base pointer
+ * param address 7-bit slave device address.
+ * param direction Master transfer directions(transmit/receive).
+ * retval kStatus_Success Successfully send the start signal.
+ * retval kStatus_I2C_Busy Current bus is busy.
+ */
+status_t I2C_MasterStart(I2C_Type *base, uint8_t address, i2c_direction_t direction)
+{
+ status_t result;
+ result = I2C_PendingStatusWait(base);
+ if (result != kStatus_Success)
+ {
+ return result;
+ }
+
+ /* Write Address and RW bit to data register */
+ base->MSTDAT = ((uint32_t)address << 1) | ((uint32_t)direction & 1U);
+ /* Start the transfer */
+ base->MSTCTL = I2C_MSTCTL_MSTSTART_MASK;
+
+ return kStatus_Success;
+}
+
+/*!
+ * brief Sends a STOP signal on the I2C bus.
+ *
+ * retval kStatus_Success Successfully send the stop signal.
+ * retval kStatus_I2C_Timeout Send stop signal failed, timeout.
+ */
+status_t I2C_MasterStop(I2C_Type *base)
+{
+ status_t result = I2C_PendingStatusWait(base);
+ if (result != kStatus_Success)
+ {
+ return result;
+ }
+
+ base->MSTCTL = I2C_MSTCTL_MSTSTOP_MASK;
+ return kStatus_Success;
+}
+
+/*!
+ * brief Performs a polling send transfer on the I2C bus.
+ *
+ * Sends up to a txSize number of bytes to the previously addressed slave device. The slave may
+ * reply with a NAK to any byte in order to terminate the transfer early. If this happens, this
+ * function returns #kStatus_I2C_Nak.
+ *
+ * param base The I2C peripheral base address.
+ * param txBuff The pointer to the data to be transferred.
+ * param txSize The length in bytes of the data to be transferred.
+ * param flags Transfer control flag to control special behavior like suppressing start or stop, for normal transfers
+ * use kI2C_TransferDefaultFlag
+ * retval kStatus_Success Data was sent successfully.
+ * retval #kStatus_I2C_Busy Another master is currently utilizing the bus.
+ * retval #kStatus_I2C_Nak The slave device sent a NAK in response to a byte.
+ * retval #kStatus_I2C_ArbitrationLost Arbitration lost error.
+ */
+status_t I2C_MasterWriteBlocking(I2C_Type *base, const void *txBuff, size_t txSize, uint32_t flags)
+{
+ uint32_t master_state;
+ status_t err;
+
+ const uint8_t *buf = (const uint8_t *)txBuff;
+
+ assert(txBuff != NULL);
+
+ err = kStatus_Success;
+ while (txSize != 0U)
+ {
+ err = I2C_PendingStatusWait(base);
+
+ if (err != kStatus_Success)
+ {
+ return err;
+ }
+
+ master_state = (base->STAT & I2C_STAT_MSTSTATE_MASK) >> I2C_STAT_MSTSTATE_SHIFT;
+ switch (master_state)
+ {
+ case I2C_STAT_MSTCODE_TXREADY:
+ /* ready to send next byte */
+ base->MSTDAT = *buf++;
+ txSize--;
+ base->MSTCTL = I2C_MSTCTL_MSTCONTINUE_MASK;
+ break;
+
+ case I2C_STAT_MSTCODE_NACKADR:
+ case I2C_STAT_MSTCODE_NACKDAT:
+ err = kStatus_I2C_Nak;
+ /* Issue nack signal when nacked by slave. */
+ (void)I2C_MasterStop(base);
+ break;
+
+ default:
+ /* unexpected state */
+ err = kStatus_I2C_UnexpectedState;
+ break;
+ }
+
+ if (err != kStatus_Success)
+ {
+ return err;
+ }
+ }
+
+ err = I2C_PendingStatusWait(base);
+
+ if (err != kStatus_Success)
+ {
+ return err;
+ }
+
+#if !I2C_MASTER_TRANSMIT_IGNORE_LAST_NACK
+ /* Check nack signal. If master is nacked by slave of the last byte, return kStatus_I2C_Nak. */
+ if (((base->STAT & I2C_STAT_MSTSTATE_MASK) >> I2C_STAT_MSTSTATE_SHIFT) == (uint32_t)I2C_STAT_MSTCODE_NACKDAT)
+ {
+ (void)I2C_MasterStop(base);
+ return kStatus_I2C_Nak;
+ }
+#endif
+
+ if (0U == (flags & (uint32_t)kI2C_TransferNoStopFlag))
+ {
+ /* Initiate stop */
+ base->MSTCTL = I2C_MSTCTL_MSTSTOP_MASK;
+ err = I2C_PendingStatusWait(base);
+ if (err != kStatus_Success)
+ {
+ return err;
+ }
+ }
+
+ return kStatus_Success;
+}
+
+/*!
+ * brief Performs a polling receive transfer on the I2C bus.
+ *
+ * param base The I2C peripheral base address.
+ * param rxBuff The pointer to the data to be transferred.
+ * param rxSize The length in bytes of the data to be transferred.
+ * param flags Transfer control flag to control special behavior like suppressing start or stop, for normal transfers
+ * use kI2C_TransferDefaultFlag
+ * retval kStatus_Success Data was received successfully.
+ * retval #kStatus_I2C_Busy Another master is currently utilizing the bus.
+ * retval #kStatus_I2C_Nak The slave device sent a NAK in response to a byte.
+ * retval #kStatus_I2C_ArbitrationLost Arbitration lost error.
+ */
+status_t I2C_MasterReadBlocking(I2C_Type *base, void *rxBuff, size_t rxSize, uint32_t flags)
+{
+ uint32_t master_state;
+ status_t err;
+
+ uint8_t *buf = (uint8_t *)(rxBuff);
+
+ assert(rxBuff != NULL);
+
+ err = kStatus_Success;
+ while (rxSize != 0U)
+ {
+ err = I2C_PendingStatusWait(base);
+
+ if (err != kStatus_Success)
+ {
+ return err;
+ }
+
+ master_state = (base->STAT & I2C_STAT_MSTSTATE_MASK) >> I2C_STAT_MSTSTATE_SHIFT;
+ switch (master_state)
+ {
+ case I2C_STAT_MSTCODE_RXREADY:
+ /* ready to send next byte */
+ *(buf++) = (uint8_t)base->MSTDAT;
+ if (--rxSize != 0U)
+ {
+ base->MSTCTL = I2C_MSTCTL_MSTCONTINUE_MASK;
+ }
+ else
+ {
+ if ((flags & (uint32_t)kI2C_TransferNoStopFlag) == 0U)
+ {
+ /* initiate NAK and stop */
+ base->MSTCTL = I2C_MSTCTL_MSTSTOP_MASK;
+ err = I2C_PendingStatusWait(base);
+ }
+ }
+ break;
+
+ case I2C_STAT_MSTCODE_NACKADR:
+ case I2C_STAT_MSTCODE_NACKDAT:
+ /* slave nacked the last byte */
+ err = kStatus_I2C_Nak;
+ break;
+
+ default:
+ /* unexpected state */
+ err = kStatus_I2C_UnexpectedState;
+ break;
+ }
+
+ if (err != kStatus_Success)
+ {
+ return err;
+ }
+ }
+
+ return kStatus_Success;
+}
+
+static status_t I2C_MasterCheckStartResponse(I2C_Type *base)
+{
+ /* Wait for start signal to be transmitted. */
+ status_t result = I2C_PendingStatusWait(base);
+
+ if (result != kStatus_Success)
+ {
+ return result;
+ }
+
+ if (((base->STAT & I2C_STAT_MSTSTATE_MASK) >> I2C_STAT_MSTSTATE_SHIFT) == I2C_STAT_MSTCODE_NACKADR)
+ {
+ (void)I2C_MasterStop(base);
+ return kStatus_I2C_Addr_Nak;
+ }
+ return kStatus_Success;
+}
+
+/*!
+ * brief Performs a master polling transfer on the I2C bus.
+ *
+ * note The API does not return until the transfer succeeds or fails due
+ * to arbitration lost or receiving a NAK.
+ *
+ * param base I2C peripheral base address.
+ * param xfer Pointer to the transfer structure.
+ * retval kStatus_Success Successfully complete the data transmission.
+ * retval kStatus_I2C_Busy Previous transmission still not finished.
+ * retval kStatus_I2C_Timeout Transfer error, wait signal timeout.
+ * retval kStatus_I2C_ArbitrationLost Transfer error, arbitration lost.
+ * retval kStataus_I2C_Nak Transfer error, receive NAK during transfer.
+ * retval kStataus_I2C_Addr_Nak Transfer error, receive NAK during addressing.
+ */
+status_t I2C_MasterTransferBlocking(I2C_Type *base, i2c_master_transfer_t *xfer)
+{
+ status_t result = kStatus_Success;
+ uint32_t subaddress;
+ uint8_t subaddrBuf[4];
+ i2c_direction_t direction;
+ int i;
+
+ assert(xfer != NULL);
+
+ /* If start signal is requested, send start signal. */
+ if (0U == (xfer->flags & (uint32_t)kI2C_TransferNoStartFlag))
+ {
+ direction = (xfer->subaddressSize != 0U) ? kI2C_Write : xfer->direction;
+ result = I2C_MasterStart(base, xfer->slaveAddress, direction);
+ if (result == kStatus_Success)
+ {
+ result = I2C_MasterCheckStartResponse(base);
+ if (result != kStatus_Success)
+ {
+ return result;
+ }
+ if ((xfer->subaddressSize) != 0U)
+ {
+ /* Prepare subaddress transmit buffer, most significant byte is stored at the lowest address */
+ subaddress = xfer->subaddress;
+ for (i = (int)xfer->subaddressSize - 1; i >= 0; i--)
+ {
+ subaddrBuf[i] = (uint8_t)subaddress & 0xffU;
+ subaddress >>= 8;
+ }
+ /* Send subaddress. */
+ result =
+ I2C_MasterWriteBlocking(base, subaddrBuf, xfer->subaddressSize, (uint32_t)kI2C_TransferNoStopFlag);
+ if (result != kStatus_Success)
+ {
+ if (result == kStatus_I2C_Nak)
+ {
+ (void)I2C_MasterStop(base);
+ return kStatus_I2C_Addr_Nak;
+ }
+ }
+ else if (xfer->direction == kI2C_Read)
+ {
+ result = I2C_MasterRepeatedStart(base, xfer->slaveAddress, xfer->direction);
+ if (result == kStatus_Success)
+ {
+ result = I2C_MasterCheckStartResponse(base);
+ if (result != kStatus_Success)
+ {
+ return result;
+ }
+ }
+ }
+ else
+ {
+ /* Empty else block to avoid MISRA 14.1 violation. */
+ }
+ }
+ }
+ }
+
+ if (result == kStatus_Success)
+ {
+ if ((xfer->direction == kI2C_Write) && (xfer->dataSize > 0U))
+ {
+ /* Transmit data. */
+ result = I2C_MasterWriteBlocking(base, xfer->data, xfer->dataSize, xfer->flags);
+ }
+ else
+ {
+ if ((xfer->direction == kI2C_Read) && (xfer->dataSize > 0U))
+ {
+ /* Receive Data. */
+ result = I2C_MasterReadBlocking(base, xfer->data, xfer->dataSize, xfer->flags);
+ }
+ }
+ }
+
+ if (result == kStatus_I2C_Nak)
+ {
+ (void)I2C_MasterStop(base);
+ }
+
+ return result;
+}
+
+/*!
+ * brief Creates a new handle for the I2C master non-blocking APIs.
+ *
+ * The creation of a handle is for use with the non-blocking APIs. Once a handle
+ * is created, there is not a corresponding destroy handle. If the user wants to
+ * terminate a transfer, the I2C_MasterTransferAbort() API shall be called.
+ *
+ * param base The I2C peripheral base address.
+ * param[out] handle Pointer to the I2C master driver handle.
+ * param callback User provided pointer to the asynchronous callback function.
+ * param userData User provided pointer to the application callback data.
+ */
+void I2C_MasterTransferCreateHandle(I2C_Type *base,
+ i2c_master_handle_t *handle,
+ i2c_master_transfer_callback_t callback,
+ void *userData)
+{
+ assert(handle != NULL);
+
+ uint32_t instance;
+ i2c_to_flexcomm_t handler;
+ handler.i2c_master_handler = I2C_MasterTransferHandleIRQ;
+
+ /* Clear out the handle. */
+ (void)memset(handle, 0, sizeof(*handle));
+
+ /* Look up instance number */
+ instance = I2C_GetInstance(base);
+
+ /* Save base and instance. */
+ handle->completionCallback = callback;
+ handle->userData = userData;
+
+ FLEXCOMM_SetIRQHandler(base, handler.flexcomm_handler, handle);
+
+ /* Clear internal IRQ enables and enable NVIC IRQ. */
+ I2C_DisableInterrupts(base, (uint32_t)kI2C_MasterIrqFlags);
+ (void)EnableIRQ(s_i2cIRQ[instance]);
+}
+
+/*!
+ * brief Performs a non-blocking transaction on the I2C bus.
+ *
+ * param base The I2C peripheral base address.
+ * param handle Pointer to the I2C master driver handle.
+ * param xfer The pointer to the transfer descriptor.
+ * retval kStatus_Success The transaction was started successfully.
+ * retval #kStatus_I2C_Busy Either another master is currently utilizing the bus, or a non-blocking
+ * transaction is already in progress.
+ */
+status_t I2C_MasterTransferNonBlocking(I2C_Type *base, i2c_master_handle_t *handle, i2c_master_transfer_t *xfer)
+{
+ status_t result;
+
+ assert(handle != NULL);
+ assert(xfer != NULL);
+ assert(xfer->subaddressSize <= sizeof(xfer->subaddress));
+
+ /* Return busy if another transaction is in progress. */
+ if (handle->state != (uint8_t)kIdleState)
+ {
+ return kStatus_I2C_Busy;
+ }
+
+ /* Disable I2C IRQ sources while we configure stuff. */
+ I2C_DisableInterrupts(base, (uint32_t)kI2C_MasterIrqFlags);
+
+ /* Prepare transfer state machine. */
+ result = I2C_InitTransferStateMachine(base, handle, xfer);
+
+ /* Clear error flags. */
+ I2C_ClearStatusFlags(base, I2C_STAT_MSTARBLOSS_MASK | I2C_STAT_MSTSTSTPERR_MASK);
+
+ /* Enable I2C internal IRQ sources. */
+ I2C_EnableInterrupts(base, (uint32_t)kI2C_MasterIrqFlags);
+
+ return result;
+}
+
+/*!
+ * brief Returns number of bytes transferred so far.
+ * param base The I2C peripheral base address.
+ * param handle Pointer to the I2C master driver handle.
+ * param[out] count Number of bytes transferred so far by the non-blocking transaction.
+ * retval kStatus_Success
+ * retval #kStatus_I2C_Busy
+ */
+status_t I2C_MasterTransferGetCount(I2C_Type *base, i2c_master_handle_t *handle, size_t *count)
+{
+ assert(handle != NULL);
+
+ if (NULL == count)
+ {
+ return kStatus_InvalidArgument;
+ }
+
+ /* Catch when there is not an active transfer. */
+ if (handle->state == (uint8_t)kIdleState)
+ {
+ *count = 0;
+ return kStatus_NoTransferInProgress;
+ }
+
+ /* There is no necessity to disable interrupts as we read a single integer value */
+ *count = handle->transferCount;
+ return kStatus_Success;
+}
+
+/*!
+ * brief Terminates a non-blocking I2C master transmission early.
+ *
+ * note It is not safe to call this function from an IRQ handler that has a higher priority than the
+ * I2C peripheral's IRQ priority.
+ *
+ * param base The I2C peripheral base address.
+ * param handle Pointer to the I2C master driver handle.
+ * retval kStatus_Success A transaction was successfully aborted.
+ * retval #kStatus_I2C_Timeout Timeout during polling for flags.
+ */
+status_t I2C_MasterTransferAbort(I2C_Type *base, i2c_master_handle_t *handle)
+{
+ status_t result = kStatus_Success;
+ uint32_t master_state;
+
+ if (handle->state != (uint8_t)kIdleState)
+ {
+ /* Disable internal IRQ enables. */
+ I2C_DisableInterrupts(base, (uint32_t)kI2C_MasterIrqFlags);
+
+ /* Wait until module is ready */
+ result = I2C_PendingStatusWait(base);
+
+ if (result != kStatus_Success)
+ {
+ handle->state = (uint8_t)kIdleState;
+ return result;
+ }
+
+ /* Get the state of the I2C module */
+ master_state = (base->STAT & I2C_STAT_MSTSTATE_MASK) >> I2C_STAT_MSTSTATE_SHIFT;
+
+ if (master_state != (uint32_t)I2C_STAT_MSTCODE_IDLE)
+ {
+ /* Send a stop command to finalize the transfer. */
+ base->MSTCTL = I2C_MSTCTL_MSTSTOP_MASK;
+
+ /* Wait until the STOP is completed */
+ result = I2C_PendingStatusWait(base);
+
+ if (result != kStatus_Success)
+ {
+ handle->state = (uint8_t)kIdleState;
+ return result;
+ }
+ }
+
+ /* Reset handle. */
+ handle->state = (uint8_t)kIdleState;
+ handle->checkAddrNack = false;
+ }
+ return kStatus_Success;
+}
+
+static status_t I2C_InitTransferStateMachine(I2C_Type *base, i2c_master_handle_t *handle, i2c_master_transfer_t *xfer)
+{
+ struct _i2c_master_transfer *transfer;
+
+ handle->transfer = *xfer;
+ transfer = &(handle->transfer);
+
+ handle->transferCount = 0;
+ handle->remainingBytes = transfer->dataSize;
+ handle->buf = (uint8_t *)transfer->data;
+ handle->remainingSubaddr = 0;
+ handle->checkAddrNack = false;
+
+ if ((transfer->flags & (uint32_t)kI2C_TransferNoStartFlag) != 0U)
+ {
+ /* Start condition shall be ommited, switch directly to next phase */
+ if (transfer->dataSize == 0U)
+ {
+ handle->state = (uint8_t)kStopState;
+ }
+ else if (handle->transfer.direction == kI2C_Write)
+ {
+ handle->state = (uint8_t)kTransmitDataState;
+ }
+ else if (handle->transfer.direction == kI2C_Read)
+ {
+ handle->state = (uint8_t)kReceiveDataBeginState;
+ }
+ else
+ {
+ return kStatus_I2C_InvalidParameter;
+ }
+ }
+ else
+ {
+ if (transfer->subaddressSize != 0U)
+ {
+ int i;
+ uint32_t subaddress;
+
+ if (transfer->subaddressSize > sizeof(handle->subaddrBuf))
+ {
+ return kStatus_I2C_InvalidParameter;
+ }
+
+ /* Prepare subaddress transmit buffer, most significant byte is stored at the lowest address */
+ subaddress = xfer->subaddress;
+ for (i = (int)xfer->subaddressSize - 1; i >= 0; i--)
+ {
+ handle->subaddrBuf[i] = (uint8_t)subaddress & 0xffU;
+ subaddress >>= 8;
+ }
+ handle->remainingSubaddr = transfer->subaddressSize;
+ }
+ handle->state = (uint8_t)kStartState;
+ handle->checkAddrNack = true;
+ }
+
+ return kStatus_Success;
+}
+
+static status_t I2C_RunTransferStateMachine(I2C_Type *base, i2c_master_handle_t *handle, bool *isDone)
+{
+ uint32_t status;
+ uint32_t master_state;
+ struct _i2c_master_transfer *transfer;
+ status_t err;
+
+ transfer = &(handle->transfer);
+ bool ignoreNak = ((handle->state == (uint8_t)kWaitForCompletionState) && (handle->remainingBytes == 0U))
+#if I2C_MASTER_TRANSMIT_IGNORE_LAST_NACK
+ /* If master is nacked by slave after the last byte during transmit, ignore the nack. */
+ || ((handle->state == (uint8_t)kStopState) && (handle->remainingBytes == 0U))
+#endif
+ ;
+
+ *isDone = false;
+
+ status = I2C_GetStatusFlags(base);
+
+ if ((status & I2C_STAT_MSTARBLOSS_MASK) != 0U)
+ {
+ I2C_ClearStatusFlags(base, I2C_STAT_MSTARBLOSS_MASK);
+ return kStatus_I2C_ArbitrationLost;
+ }
+
+ if ((status & I2C_STAT_MSTSTSTPERR_MASK) != 0U)
+ {
+ I2C_ClearStatusFlags(base, I2C_STAT_MSTSTSTPERR_MASK);
+ return kStatus_I2C_StartStopError;
+ }
+
+ /* Event timeout happens when the time since last bus event has been longer than the time specified by TIMEOUT
+ register. eg: Start signal fails to generate, no error status is set and transfer hangs if glitch on bus happens
+ before, the timeout status can be used to avoid the transfer hangs indefinitely. */
+ if ((status & (uint32_t)kI2C_EventTimeoutFlag) != 0U)
+ {
+ I2C_ClearStatusFlags(base, (uint32_t)kI2C_EventTimeoutFlag);
+ return kStatus_I2C_EventTimeout;
+ }
+
+ /* SCL timeout happens when the slave is holding the SCL line low and the time has been longer than the time
+ specified by TIMEOUT register. */
+ if ((status & (uint32_t)kI2C_SclTimeoutFlag) != 0U)
+ {
+ I2C_ClearStatusFlags(base, (uint32_t)kI2C_SclTimeoutFlag);
+ return kStatus_I2C_SclLowTimeout;
+ }
+
+ if ((status & I2C_STAT_MSTPENDING_MASK) == 0U)
+ {
+ return kStatus_I2C_Busy;
+ }
+
+ /* Get the hardware state of the I2C module */
+ master_state = (base->STAT & I2C_STAT_MSTSTATE_MASK) >> I2C_STAT_MSTSTATE_SHIFT;
+ if (((master_state == (uint32_t)I2C_STAT_MSTCODE_NACKADR) ||
+ (master_state == (uint32_t)I2C_STAT_MSTCODE_NACKDAT)) &&
+ (ignoreNak != true))
+ {
+ /* Slave NACKed last byte, issue stop and return error */
+ base->MSTCTL = I2C_MSTCTL_MSTSTOP_MASK;
+ handle->state = (uint8_t)kWaitForCompletionState;
+ /* If master is nacked during slave probe or during sending subaddress, return kStatus_I2C_ADDR_Nak. */
+ if ((master_state == (uint32_t)I2C_STAT_MSTCODE_NACKADR) || (handle->checkAddrNack))
+ {
+ return kStatus_I2C_Addr_Nak;
+ }
+ else /* Otherwise just return kStatus_I2C_Nak */
+ {
+ return kStatus_I2C_Nak;
+ }
+ }
+
+ err = kStatus_Success;
+ switch (handle->state)
+ {
+ case (uint8_t)kStartState:
+ if (handle->remainingSubaddr != 0U)
+ {
+ /* Subaddress takes precedence over the data transfer, direction is always "write" in this case */
+ base->MSTDAT = (uint32_t)transfer->slaveAddress << 1U;
+ handle->state = (uint8_t)kTransmitSubaddrState;
+ }
+ else if (transfer->direction == kI2C_Write)
+ {
+ base->MSTDAT = (uint32_t)transfer->slaveAddress << 1;
+ handle->state = (handle->remainingBytes != 0U) ? (uint8_t)kTransmitDataState : (uint8_t)kStopState;
+ }
+ else
+ {
+ base->MSTDAT = ((uint32_t)transfer->slaveAddress << 1) | 1u;
+ handle->state = (handle->remainingBytes != 0U) ? (uint8_t)kReceiveDataState : (uint8_t)kStopState;
+ }
+ /* Send start condition */
+ base->MSTCTL = I2C_MSTCTL_MSTSTART_MASK;
+ break;
+
+ case (uint8_t)kTransmitSubaddrState:
+ if (master_state != (uint32_t)I2C_STAT_MSTCODE_TXREADY)
+ {
+ return kStatus_I2C_UnexpectedState;
+ }
+ /* Most significant subaddress byte comes first */
+ base->MSTDAT = handle->subaddrBuf[handle->transfer.subaddressSize - handle->remainingSubaddr];
+ base->MSTCTL = I2C_MSTCTL_MSTCONTINUE_MASK;
+ if (--(handle->remainingSubaddr) != 0U)
+ {
+ /* There are still subaddress bytes to be transmitted */
+ break;
+ }
+ if (handle->remainingBytes != 0U)
+ {
+ /* There is data to be transferred, if there is write to read turnaround it is necessary to perform
+ * repeated start */
+ handle->state = (transfer->direction == kI2C_Read) ? (uint8_t)kStartState : (uint8_t)kTransmitDataState;
+ }
+ else
+ {
+ /* No more data, schedule stop condition */
+ handle->state = (uint8_t)kStopState;
+ }
+ break;
+
+ case (uint8_t)kTransmitDataState:
+ handle->checkAddrNack = false;
+ if (master_state != (uint32_t)I2C_STAT_MSTCODE_TXREADY)
+ {
+ return kStatus_I2C_UnexpectedState;
+ }
+ base->MSTDAT = *(handle->buf)++;
+ base->MSTCTL = I2C_MSTCTL_MSTCONTINUE_MASK;
+ if (--handle->remainingBytes == 0U)
+ {
+ /* No more data, schedule stop condition */
+ handle->state = (uint8_t)kStopState;
+ }
+ handle->transferCount++;
+ break;
+
+ case (uint8_t)kReceiveDataBeginState:
+ handle->checkAddrNack = false;
+ if (master_state != (uint32_t)I2C_STAT_MSTCODE_RXREADY)
+ {
+ return kStatus_I2C_UnexpectedState;
+ }
+ (void)base->MSTDAT;
+ base->MSTCTL = I2C_MSTCTL_MSTCONTINUE_MASK;
+ handle->state = (uint8_t)kReceiveDataState;
+ break;
+
+ case (uint8_t)kReceiveDataState:
+ handle->checkAddrNack = false;
+ if (master_state != (uint32_t)I2C_STAT_MSTCODE_RXREADY)
+ {
+ return kStatus_I2C_UnexpectedState;
+ }
+ *(handle->buf)++ = (uint8_t)base->MSTDAT;
+ if (--handle->remainingBytes != 0U)
+ {
+ base->MSTCTL = I2C_MSTCTL_MSTCONTINUE_MASK;
+ }
+ else
+ {
+ /* No more data expected, issue NACK and STOP right away */
+ if (0U == (transfer->flags & (uint32_t)kI2C_TransferNoStopFlag))
+ {
+ base->MSTCTL = I2C_MSTCTL_MSTSTOP_MASK;
+ }
+ handle->state = (uint8_t)kWaitForCompletionState;
+ }
+ handle->transferCount++;
+ break;
+
+ case (uint8_t)kStopState:
+ handle->checkAddrNack = false;
+ if ((transfer->flags & (uint32_t)kI2C_TransferNoStopFlag) != 0U)
+ {
+ /* Stop condition is omitted, we are done */
+ *isDone = true;
+ handle->state = (uint8_t)kIdleState;
+ break;
+ }
+ /* Send stop condition */
+ base->MSTCTL = I2C_MSTCTL_MSTSTOP_MASK;
+ handle->state = (uint8_t)kWaitForCompletionState;
+ break;
+
+ case (uint8_t)kWaitForCompletionState:
+ *isDone = true;
+ handle->state = (uint8_t)kIdleState;
+ break;
+
+ case (uint8_t)kIdleState:
+ default:
+ /* State machine shall not be invoked again once it enters the idle state */
+ err = kStatus_I2C_UnexpectedState;
+ break;
+ }
+
+ return err;
+}
+
+/*!
+ * brief Reusable routine to handle master interrupts.
+ * note This function does not need to be called unless you are reimplementing the
+ * nonblocking API's interrupt handler routines to add special functionality.
+ * param base The I2C peripheral base address.
+ * param handle Pointer to the I2C master driver handle.
+ */
+void I2C_MasterTransferHandleIRQ(I2C_Type *base, i2c_master_handle_t *handle)
+{
+ bool isDone;
+ status_t result;
+
+ /* Don't do anything if we don't have a valid handle. */
+ if (NULL == handle)
+ {
+ return;
+ }
+
+ result = I2C_RunTransferStateMachine(base, handle, &isDone);
+
+ if ((result != kStatus_Success) || isDone)
+ {
+ /* Restore handle to idle state. */
+ handle->state = (uint8_t)kIdleState;
+
+ /* Disable internal IRQ enables. */
+ I2C_DisableInterrupts(base, (uint32_t)kI2C_MasterIrqFlags);
+
+ /* Invoke callback. */
+ if (handle->completionCallback != NULL)
+ {
+ handle->completionCallback(base, handle, result, handle->userData);
+ }
+ }
+}
+
+static void I2C_SlaveInternalStateMachineReset(I2C_Type *base)
+{
+ I2C_SlaveEnable(base, false); /* clear SLVEN Slave enable bit */
+}
+
+static status_t I2C_SlaveDivVal(uint32_t srcClock_Hz, i2c_slave_bus_speed_t busSpeed, uint32_t *divVal)
+{
+ uint32_t dataSetupTime_ns;
+
+ switch ((uint8_t)(busSpeed))
+ {
+ case (uint8_t)kI2C_SlaveStandardMode:
+ dataSetupTime_ns = 250U;
+ break;
+
+ case (uint8_t)kI2C_SlaveFastMode:
+ dataSetupTime_ns = 100U;
+ break;
+
+ case (uint8_t)kI2C_SlaveFastModePlus:
+ dataSetupTime_ns = 50U;
+ break;
+
+ case (uint8_t)kI2C_SlaveHsMode:
+ dataSetupTime_ns = 10U;
+ break;
+
+ default:
+ dataSetupTime_ns = 0U;
+ break;
+ }
+
+ if (0U == dataSetupTime_ns)
+ {
+ return kStatus_InvalidArgument;
+ }
+
+ /* divVal = (sourceClock_Hz / 1000000) * (dataSetupTime_ns / 1000) */
+ *divVal = srcClock_Hz / 1000U;
+ *divVal = (*divVal) * dataSetupTime_ns;
+ *divVal = (*divVal) / 1000000U;
+
+ if ((*divVal) > I2C_CLKDIV_DIVVAL_MASK)
+ {
+ *divVal = I2C_CLKDIV_DIVVAL_MASK;
+ }
+
+ return kStatus_Success;
+}
+
+static uint32_t I2C_SlavePollPending(I2C_Type *base)
+{
+ uint32_t stat;
+
+#if I2C_RETRY_TIMES != 0U
+ uint32_t waitTimes = I2C_RETRY_TIMES;
+#endif
+ do
+ {
+ stat = base->STAT;
+#if I2C_RETRY_TIMES != 0U
+ waitTimes--;
+ } while ((0U == (stat & I2C_STAT_SLVPENDING_MASK)) && (waitTimes != 0U));
+
+ if (waitTimes == 0U)
+ {
+ return (uint32_t)kStatus_I2C_Timeout;
+ }
+#else
+ } while (0U == (stat & I2C_STAT_SLVPENDING_MASK));
+#endif
+
+ return stat;
+}
+
+static void I2C_SlaveInvokeEvent(I2C_Type *base, i2c_slave_handle_t *handle, i2c_slave_transfer_event_t event)
+{
+ uint32_t eventMask = handle->transfer.eventMask;
+ handle->transfer.event = event;
+ if (((handle->callback) != NULL) && ((eventMask & (uint32_t)event) != 0U))
+ {
+ handle->callback(base, &handle->transfer, handle->userData);
+
+ size_t txSize = handle->transfer.txSize;
+ size_t rxSize = handle->transfer.rxSize;
+ /* if after event callback we have data buffer (callback func has added new data), keep transfer busy */
+ if (false == handle->isBusy)
+ {
+ if (((handle->transfer.txData != NULL) && (txSize != 0U)) ||
+ ((handle->transfer.rxData != NULL) && (rxSize != 0U)))
+ {
+ handle->isBusy = true;
+ }
+ }
+
+ /* Clear the transferred count now that we have a new buffer. */
+ if ((event == kI2C_SlaveReceiveEvent) || (event == kI2C_SlaveTransmitEvent))
+ {
+ handle->transfer.transferredCount = 0;
+ }
+ }
+}
+
+static bool I2C_SlaveAddressIRQ(I2C_Type *base, i2c_slave_handle_t *handle)
+{
+ uint8_t addressByte0;
+ size_t txSize;
+ size_t rxSize;
+
+ addressByte0 = (uint8_t)base->SLVDAT;
+
+ /* store the matched address */
+ handle->transfer.receivedAddress = addressByte0;
+
+ /* R/nW */
+ if ((addressByte0 & 1U) != 0U)
+ {
+ txSize = handle->transfer.txSize;
+ /* if we have no data in this transfer, call callback to get new */
+ if ((handle->transfer.txData == NULL) || (txSize == 0U))
+ {
+ I2C_SlaveInvokeEvent(base, handle, kI2C_SlaveTransmitEvent);
+ }
+
+ txSize = handle->transfer.txSize;
+ /* NACK if we have no data in this transfer. */
+ if ((handle->transfer.txData == NULL) || (txSize == 0U))
+ {
+ base->SLVCTL = I2C_SLVCTL_SLVNACK_MASK;
+ return false;
+ }
+
+ /* master wants to read, so slave transmit is next state */
+ handle->slaveFsm = kI2C_SlaveFsmTransmit;
+ }
+ else
+ {
+ rxSize = handle->transfer.rxSize;
+ /* if we have no receive buffer in this transfer, call callback to get new */
+ if ((handle->transfer.rxData == NULL) || (rxSize == 0U))
+ {
+ I2C_SlaveInvokeEvent(base, handle, kI2C_SlaveReceiveEvent);
+ }
+
+ rxSize = handle->transfer.rxSize;
+ /* NACK if we have no data in this transfer */
+ if ((handle->transfer.rxData == NULL) || (rxSize == 0U))
+ {
+ base->SLVCTL = I2C_SLVCTL_SLVNACK_MASK;
+ return false;
+ }
+
+ /* master wants write, so slave receive is next state */
+ handle->slaveFsm = kI2C_SlaveFsmReceive;
+ }
+
+ /* continue transaction */
+ base->SLVCTL = I2C_SLVCTL_SLVCONTINUE_MASK;
+
+ return true;
+}
+
+static status_t I2C_SlaveTransferNonBlockingInternal(I2C_Type *base,
+ i2c_slave_handle_t *handle,
+ const void *txData,
+ size_t txSize,
+ void *rxData,
+ size_t rxSize,
+ uint32_t eventMask)
+{
+ assert(handle != NULL);
+
+ status_t status;
+ status = kStatus_Success;
+
+ /* Disable I2C IRQ sources while we configure stuff. */
+ I2C_DisableInterrupts(base, (uint32_t)kI2C_SlaveIrqFlags);
+
+ /* Return busy if another transaction is in progress. */
+ if (handle->isBusy)
+ {
+ status = kStatus_I2C_Busy;
+ }
+
+ /* Save transfer into handle. */
+ handle->transfer.txData = (const uint8_t *)txData;
+ handle->transfer.txSize = txSize;
+ handle->transfer.rxData = (uint8_t *)rxData;
+ handle->transfer.rxSize = rxSize;
+ handle->transfer.transferredCount = 0;
+ handle->transfer.eventMask = eventMask | (uint32_t)kI2C_SlaveTransmitEvent | (uint32_t)kI2C_SlaveReceiveEvent;
+ handle->isBusy = true;
+
+ /* Set the SLVEN bit to 1 in the CFG register. */
+ I2C_SlaveEnable(base, true);
+
+ /* Clear w1c flags. */
+ base->STAT |= 0u;
+
+ /* Enable I2C internal IRQ sources. */
+ I2C_EnableInterrupts(base, (uint32_t)kI2C_SlaveIrqFlags);
+
+ return status;
+}
+
+/*!
+ * brief Starts accepting master read from slave requests.
+ *
+ * The function can be called in response to #kI2C_SlaveTransmitEvent callback to start a new slave Tx transfer
+ * from within the transfer callback.
+ *
+ * The set of events received by the callback is customizable. To do so, set the a eventMask parameter to
+ * the OR'd combination of #i2c_slave_transfer_event_t enumerators for the events you wish to receive.
+ * The #kI2C_SlaveTransmitEvent and #kI2C_SlaveReceiveEvent events are always enabled and do not need
+ * to be included in the mask. Alternatively, you can pass 0 to get a default set of only the transmit and
+ * receive events that are always enabled. In addition, the #kI2C_SlaveAllEvents constant is provided as
+ * a convenient way to enable all events.
+ *
+ * param base The I2C peripheral base address.
+ * param transfer Pointer to #i2c_slave_transfer_t structure.
+ * param txData Pointer to data to send to master.
+ * param txSize Size of txData in bytes.
+ * param eventMask Bit mask formed by OR'ing together #i2c_slave_transfer_event_t enumerators to specify
+ * which events to send to the callback. Other accepted values are 0 to get a default set of
+ * only the transmit and receive events, and #kI2C_SlaveAllEvents to enable all events.
+ *
+ * retval kStatus_Success Slave transfers were successfully started.
+ * retval #kStatus_I2C_Busy Slave transfers have already been started on this handle.
+ */
+status_t I2C_SlaveSetSendBuffer(
+ I2C_Type *base, volatile i2c_slave_transfer_t *transfer, const void *txData, size_t txSize, uint32_t eventMask)
+{
+ return I2C_SlaveTransferNonBlockingInternal(base, transfer->handle, txData, txSize, NULL, 0u, eventMask);
+}
+
+/*!
+ * brief Starts accepting master write to slave requests.
+ *
+ * The function can be called in response to #kI2C_SlaveReceiveEvent callback to start a new slave Rx transfer
+ * from within the transfer callback.
+ *
+ * The set of events received by the callback is customizable. To do so, set the a eventMask parameter to
+ * the OR'd combination of #i2c_slave_transfer_event_t enumerators for the events you wish to receive.
+ * The #kI2C_SlaveTransmitEvent and #kI2C_SlaveReceiveEvent events are always enabled and do not need
+ * to be included in the mask. Alternatively, you can pass 0 to get a default set of only the transmit and
+ * receive events that are always enabled. In addition, the #kI2C_SlaveAllEvents constant is provided as
+ * a convenient way to enable all events.
+ *
+ * param base The I2C peripheral base address.
+ * param transfer Pointer to #i2c_slave_transfer_t structure.
+ * param rxData Pointer to data to store data from master.
+ * param rxSize Size of rxData in bytes.
+ * param eventMask Bit mask formed by OR'ing together #i2c_slave_transfer_event_t enumerators to specify
+ * which events to send to the callback. Other accepted values are 0 to get a default set of
+ * only the transmit and receive events, and #kI2C_SlaveAllEvents to enable all events.
+ *
+ * retval kStatus_Success Slave transfers were successfully started.
+ * retval #kStatus_I2C_Busy Slave transfers have already been started on this handle.
+ */
+status_t I2C_SlaveSetReceiveBuffer(
+ I2C_Type *base, volatile i2c_slave_transfer_t *transfer, void *rxData, size_t rxSize, uint32_t eventMask)
+{
+ return I2C_SlaveTransferNonBlockingInternal(base, transfer->handle, NULL, 0u, rxData, rxSize, eventMask);
+}
+
+/*!
+ * brief Configures Slave Address n register.
+ *
+ * This function writes new value to Slave Address register.
+ *
+ * param base The I2C peripheral base address.
+ * param addressRegister The module supports multiple address registers. The parameter determines which one shall be
+ * changed.
+ * param address The slave address to be stored to the address register for matching.
+ * param addressDisable Disable matching of the specified address register.
+ */
+void I2C_SlaveSetAddress(I2C_Type *base,
+ i2c_slave_address_register_t addressRegister,
+ uint8_t address,
+ bool addressDisable)
+{
+ base->SLVADR[addressRegister] = I2C_SLVADR_SLVADR(address) | I2C_SLVADR_SADISABLE(addressDisable);
+}
+
+/*!
+ * brief Provides a default configuration for the I2C slave peripheral.
+ *
+ * This function provides the following default configuration for the I2C slave peripheral:
+ * code
+ * slaveConfig->enableSlave = true;
+ * slaveConfig->address0.disable = false;
+ * slaveConfig->address0.address = 0u;
+ * slaveConfig->address1.disable = true;
+ * slaveConfig->address2.disable = true;
+ * slaveConfig->address3.disable = true;
+ * slaveConfig->busSpeed = kI2C_SlaveStandardMode;
+ * endcode
+ *
+ * After calling this function, override any settings to customize the configuration,
+ * prior to initializing the master driver with I2C_SlaveInit(). Be sure to override at least the a
+ * address0.address member of the configuration structure with the desired slave address.
+ *
+ * param[out] slaveConfig User provided configuration structure that is set to default values. Refer to
+ * #i2c_slave_config_t.
+ */
+void I2C_SlaveGetDefaultConfig(i2c_slave_config_t *slaveConfig)
+{
+ assert(slaveConfig != NULL);
+
+ i2c_slave_config_t mySlaveConfig = {0};
+
+ /* default config enables slave address 0 match to general I2C call address zero */
+ mySlaveConfig.enableSlave = true;
+ mySlaveConfig.address1.addressDisable = true;
+ mySlaveConfig.address2.addressDisable = true;
+ mySlaveConfig.address3.addressDisable = true;
+
+ *slaveConfig = mySlaveConfig;
+}
+
+/*!
+ * brief Initializes the I2C slave peripheral.
+ *
+ * This function enables the peripheral clock and initializes the I2C slave peripheral as described by the user
+ * provided configuration.
+ *
+ * param base The I2C peripheral base address.
+ * param slaveConfig User provided peripheral configuration. Use I2C_SlaveGetDefaultConfig() to get a set of defaults
+ * that you can override.
+ * param srcClock_Hz Frequency in Hertz of the I2C functional clock. Used to calculate CLKDIV value to provide
+ * enough
+ * data setup time for master when slave stretches the clock.
+ */
+status_t I2C_SlaveInit(I2C_Type *base, const i2c_slave_config_t *slaveConfig, uint32_t srcClock_Hz)
+{
+ status_t status;
+ uint32_t divVal = 0;
+
+ /* configure data setup time used when slave stretches clock */
+ status = I2C_SlaveDivVal(srcClock_Hz, slaveConfig->busSpeed, &divVal);
+ if (kStatus_Success != status)
+ {
+ return status;
+ }
+
+ (void)FLEXCOMM_Init(base, FLEXCOMM_PERIPH_I2C);
+
+ /* I2C Clock Divider register */
+ base->CLKDIV = divVal;
+
+ /* set Slave address */
+ I2C_SlaveSetAddress(base, kI2C_SlaveAddressRegister0, slaveConfig->address0.address,
+ slaveConfig->address0.addressDisable);
+ I2C_SlaveSetAddress(base, kI2C_SlaveAddressRegister1, slaveConfig->address1.address,
+ slaveConfig->address1.addressDisable);
+ I2C_SlaveSetAddress(base, kI2C_SlaveAddressRegister2, slaveConfig->address2.address,
+ slaveConfig->address2.addressDisable);
+ I2C_SlaveSetAddress(base, kI2C_SlaveAddressRegister3, slaveConfig->address3.address,
+ slaveConfig->address3.addressDisable);
+
+ /* set Slave address 0 qual */
+ base->SLVQUAL0 = I2C_SLVQUAL0_QUALMODE0(slaveConfig->qualMode) | I2C_SLVQUAL0_SLVQUAL0(slaveConfig->qualAddress);
+
+ /* set Slave enable */
+ base->CFG = I2C_CFG_SLVEN(slaveConfig->enableSlave);
+
+ return status;
+}
+
+/*!
+ * brief Deinitializes the I2C slave peripheral.
+ *
+ * This function disables the I2C slave peripheral and gates the clock. It also performs a software
+ * reset to restore the peripheral to reset conditions.
+ *
+ * param base The I2C peripheral base address.
+ */
+void I2C_SlaveDeinit(I2C_Type *base)
+{
+ I2C_SlaveEnable(base, false);
+}
+
+/*!
+ * brief Performs a polling send transfer on the I2C bus.
+ *
+ * The function executes blocking address phase and blocking data phase.
+ *
+ * param base The I2C peripheral base address.
+ * param txBuff The pointer to the data to be transferred.
+ * param txSize The length in bytes of the data to be transferred.
+ * return kStatus_Success Data has been sent.
+ * return kStatus_Fail Unexpected slave state (master data write while master read from slave is expected).
+ */
+status_t I2C_SlaveWriteBlocking(I2C_Type *base, const uint8_t *txBuff, size_t txSize)
+{
+ const uint8_t *buf = txBuff;
+ uint32_t stat;
+ bool slaveAddress;
+ bool slaveTransmit;
+
+ /* Set the SLVEN bit to 1 in the CFG register. */
+ I2C_SlaveEnable(base, true);
+
+ /* wait for SLVPENDING */
+ stat = I2C_SlavePollPending(base);
+ if (stat == (uint32_t)kStatus_I2C_Timeout)
+ {
+ return kStatus_I2C_Timeout;
+ }
+
+ /* Get slave machine state */
+ slaveAddress = (((stat & I2C_STAT_SLVSTATE_MASK) >> I2C_STAT_SLVSTATE_SHIFT) == (uint32_t)I2C_STAT_SLVST_ADDR);
+ slaveTransmit = (((stat & I2C_STAT_SLVSTATE_MASK) >> I2C_STAT_SLVSTATE_SHIFT) == (uint32_t)I2C_STAT_SLVST_TX);
+
+ /* in I2C_SlaveSend() it shall be either slaveAddress or slaveTransmit */
+ if (!(slaveAddress || slaveTransmit))
+ {
+ I2C_SlaveInternalStateMachineReset(base);
+ return kStatus_Fail;
+ }
+
+ if (slaveAddress)
+ {
+ /* Acknowledge (ack) the address by setting SLVCONTINUE = 1 in the slave control register */
+ base->SLVCTL = I2C_SLVCTL_SLVCONTINUE_MASK;
+
+ /* wait for SLVPENDING */
+ stat = I2C_SlavePollPending(base);
+ if (stat == (uint32_t)kStatus_I2C_Timeout)
+ {
+ return kStatus_I2C_Timeout;
+ }
+ }
+
+ /* send bytes up to txSize */
+ while (txSize != 0U)
+ {
+ slaveTransmit = (((stat & I2C_STAT_SLVSTATE_MASK) >> I2C_STAT_SLVSTATE_SHIFT) == (uint32_t)I2C_STAT_SLVST_TX);
+
+ if (!slaveTransmit)
+ {
+ I2C_SlaveInternalStateMachineReset(base);
+ return kStatus_Fail;
+ }
+
+ /* Write 8 bits of data to the SLVDAT register */
+ base->SLVDAT = I2C_SLVDAT_DATA(*buf);
+
+ /* continue transaction */
+ base->SLVCTL = I2C_SLVCTL_SLVCONTINUE_MASK;
+
+ /* advance counters and pointers for next data */
+ buf++;
+ txSize--;
+
+ if (txSize != 0U)
+ {
+ /* wait for SLVPENDING */
+ stat = I2C_SlavePollPending(base);
+ if (stat == (uint32_t)kStatus_I2C_Timeout)
+ {
+ return kStatus_I2C_Timeout;
+ }
+ }
+ }
+
+ return kStatus_Success;
+}
+
+/*!
+ * brief Performs a polling receive transfer on the I2C bus.
+ *
+ * The function executes blocking address phase and blocking data phase.
+ *
+ * param base The I2C peripheral base address.
+ * param rxBuff The pointer to the data to be transferred.
+ * param rxSize The length in bytes of the data to be transferred.
+ * return kStatus_Success Data has been received.
+ * return kStatus_Fail Unexpected slave state (master data read while master write to slave is expected).
+ */
+status_t I2C_SlaveReadBlocking(I2C_Type *base, uint8_t *rxBuff, size_t rxSize)
+{
+ uint8_t *buf = rxBuff;
+ uint32_t stat;
+ bool slaveAddress;
+ bool slaveReceive;
+
+ /* Set the SLVEN bit to 1 in the CFG register. */
+ I2C_SlaveEnable(base, true);
+
+ /* wait for SLVPENDING */
+ stat = I2C_SlavePollPending(base);
+ if (stat == (uint32_t)kStatus_I2C_Timeout)
+ {
+ return kStatus_I2C_Timeout;
+ }
+
+ /* Get slave machine state */
+ slaveAddress = (((stat & I2C_STAT_SLVSTATE_MASK) >> I2C_STAT_SLVSTATE_SHIFT) == (uint32_t)I2C_STAT_SLVST_ADDR);
+ slaveReceive = (((stat & I2C_STAT_SLVSTATE_MASK) >> I2C_STAT_SLVSTATE_SHIFT) == (uint32_t)I2C_STAT_SLVST_RX);
+
+ /* in I2C_SlaveReceive() it shall be either slaveAddress or slaveReceive */
+ if (!(slaveAddress || slaveReceive))
+ {
+ I2C_SlaveInternalStateMachineReset(base);
+ return kStatus_Fail;
+ }
+
+ if (slaveAddress)
+ {
+ /* Acknowledge (ack) the address by setting SLVCONTINUE = 1 in the slave control register */
+ base->SLVCTL = I2C_SLVCTL_SLVCONTINUE_MASK;
+
+ /* wait for SLVPENDING */
+ stat = I2C_SlavePollPending(base);
+ if (stat == (uint32_t)kStatus_I2C_Timeout)
+ {
+ return kStatus_I2C_Timeout;
+ }
+ }
+
+ /* receive bytes up to rxSize */
+ while (rxSize != 0U)
+ {
+ slaveReceive = (((stat & I2C_STAT_SLVSTATE_MASK) >> I2C_STAT_SLVSTATE_SHIFT) == (uint32_t)I2C_STAT_SLVST_RX);
+
+ if (!slaveReceive)
+ {
+ I2C_SlaveInternalStateMachineReset(base);
+ return kStatus_Fail;
+ }
+
+ /* Read 8 bits of data from the SLVDAT register */
+ *buf = (uint8_t)base->SLVDAT;
+
+ /* continue transaction */
+ base->SLVCTL = I2C_SLVCTL_SLVCONTINUE_MASK;
+
+ /* advance counters and pointers for next data */
+ buf++;
+ rxSize--;
+
+ if (rxSize != 0U)
+ {
+ /* wait for SLVPENDING */
+ stat = I2C_SlavePollPending(base);
+ if (stat == (uint32_t)kStatus_I2C_Timeout)
+ {
+ return kStatus_I2C_Timeout;
+ }
+ }
+ }
+
+ return kStatus_Success;
+}
+
+/*!
+ * brief Creates a new handle for the I2C slave non-blocking APIs.
+ *
+ * The creation of a handle is for use with the non-blocking APIs. Once a handle
+ * is created, there is not a corresponding destroy handle. If the user wants to
+ * terminate a transfer, the I2C_SlaveTransferAbort() API shall be called.
+ *
+ * param base The I2C peripheral base address.
+ * param[out] handle Pointer to the I2C slave driver handle.
+ * param callback User provided pointer to the asynchronous callback function.
+ * param userData User provided pointer to the application callback data.
+ */
+void I2C_SlaveTransferCreateHandle(I2C_Type *base,
+ i2c_slave_handle_t *handle,
+ i2c_slave_transfer_callback_t callback,
+ void *userData)
+{
+ assert(handle != NULL);
+
+ uint32_t instance;
+ i2c_to_flexcomm_t handler;
+ handler.i2c_slave_handler = I2C_SlaveTransferHandleIRQ;
+
+ /* Clear out the handle. */
+ (void)memset(handle, 0, sizeof(*handle));
+
+ /* Look up instance number */
+ instance = I2C_GetInstance(base);
+
+ /* Save base and instance. */
+ handle->callback = callback;
+ handle->userData = userData;
+
+ /* initialize fsm */
+ handle->slaveFsm = kI2C_SlaveFsmAddressMatch;
+
+ /* store pointer to handle into transfer struct */
+ handle->transfer.handle = handle;
+
+ FLEXCOMM_SetIRQHandler(base, handler.flexcomm_handler, handle);
+
+ /* Clear internal IRQ enables and enable NVIC IRQ. */
+ I2C_DisableInterrupts(base, (uint32_t)kI2C_SlaveIrqFlags);
+ (void)EnableIRQ(s_i2cIRQ[instance]);
+}
+
+/*!
+ * brief Starts accepting slave transfers.
+ *
+ * Call this API after calling I2C_SlaveInit() and I2C_SlaveTransferCreateHandle() to start processing
+ * transactions driven by an I2C master. The slave monitors the I2C bus and pass events to the
+ * callback that was passed into the call to I2C_SlaveTransferCreateHandle(). The callback is always invoked
+ * from the interrupt context.
+ *
+ * If no slave Tx transfer is busy, a master read from slave request invokes #kI2C_SlaveTransmitEvent callback.
+ * If no slave Rx transfer is busy, a master write to slave request invokes #kI2C_SlaveReceiveEvent callback.
+ *
+ * The set of events received by the callback is customizable. To do so, set the a eventMask parameter to
+ * the OR'd combination of #i2c_slave_transfer_event_t enumerators for the events you wish to receive.
+ * The #kI2C_SlaveTransmitEvent and #kI2C_SlaveReceiveEvent events are always enabled and do not need
+ * to be included in the mask. Alternatively, you can pass 0 to get a default set of only the transmit and
+ * receive events that are always enabled. In addition, the #kI2C_SlaveAllEvents constant is provided as
+ * a convenient way to enable all events.
+ *
+ * param base The I2C peripheral base address.
+ * param handle Pointer to i2c_slave_handle_t structure which stores the transfer state.
+ * param eventMask Bit mask formed by OR'ing together #i2c_slave_transfer_event_t enumerators to specify
+ * which events to send to the callback. Other accepted values are 0 to get a default set of
+ * only the transmit and receive events, and #kI2C_SlaveAllEvents to enable all events.
+ *
+ * retval kStatus_Success Slave transfers were successfully started.
+ * retval #kStatus_I2C_Busy Slave transfers have already been started on this handle.
+ */
+status_t I2C_SlaveTransferNonBlocking(I2C_Type *base, i2c_slave_handle_t *handle, uint32_t eventMask)
+{
+ return I2C_SlaveTransferNonBlockingInternal(base, handle, NULL, 0u, NULL, 0u, eventMask);
+}
+
+/*!
+ * brief Gets the slave transfer remaining bytes during a interrupt non-blocking transfer.
+ *
+ * param base I2C base pointer.
+ * param handle pointer to i2c_slave_handle_t structure.
+ * param count Number of bytes transferred so far by the non-blocking transaction.
+ * retval kStatus_InvalidArgument count is Invalid.
+ * retval kStatus_Success Successfully return the count.
+ */
+status_t I2C_SlaveTransferGetCount(I2C_Type *base, i2c_slave_handle_t *handle, size_t *count)
+{
+ assert(handle != NULL);
+
+ if (NULL == count)
+ {
+ return kStatus_InvalidArgument;
+ }
+
+ /* Catch when there is not an active transfer. */
+ if (!handle->isBusy)
+ {
+ *count = 0;
+ return kStatus_NoTransferInProgress;
+ }
+
+ /* For an active transfer, just return the count from the handle. */
+ *count = handle->transfer.transferredCount;
+
+ return kStatus_Success;
+}
+
+/*!
+ * brief Aborts the slave non-blocking transfers.
+ * note This API could be called at any time to stop slave for handling the bus events.
+ * param base The I2C peripheral base address.
+ * param handle Pointer to i2c_slave_handle_t structure which stores the transfer state.
+ * retval kStatus_Success
+ * retval #kStatus_I2C_Idle
+ */
+void I2C_SlaveTransferAbort(I2C_Type *base, i2c_slave_handle_t *handle)
+{
+ /* Disable I2C IRQ sources while we configure stuff. */
+ I2C_DisableInterrupts(base, (uint32_t)kI2C_SlaveIrqFlags);
+
+ /* Set the SLVEN bit to 0 in the CFG register. */
+ I2C_SlaveEnable(base, false);
+
+ handle->isBusy = false;
+ handle->transfer.txSize = 0U;
+ handle->transfer.rxSize = 0U;
+}
+
+/*!
+ * brief Reusable routine to handle slave interrupts.
+ * note This function does not need to be called unless you are reimplementing the
+ * non blocking API's interrupt handler routines to add special functionality.
+ * param base The I2C peripheral base address.
+ * param handle Pointer to i2c_slave_handle_t structure which stores the transfer state.
+ */
+void I2C_SlaveTransferHandleIRQ(I2C_Type *base, i2c_slave_handle_t *handle)
+{
+ uint32_t i2cStatus = base->STAT;
+ uint8_t tmpdata;
+ size_t txSize;
+ size_t rxSize;
+
+ if ((i2cStatus & I2C_STAT_SLVDESEL_MASK) != 0U)
+ {
+ I2C_SlaveInvokeEvent(base, handle, kI2C_SlaveDeselectedEvent);
+ I2C_SlaveClearStatusFlags(base, I2C_STAT_SLVDESEL_MASK);
+ }
+
+ /* SLVPENDING flag is cleared by writing I2C_SLVCTL_SLVCONTINUE_MASK to SLVCTL register */
+ if ((i2cStatus & I2C_STAT_SLVPENDING_MASK) != 0U)
+ {
+ bool slaveAddress =
+ (((i2cStatus & I2C_STAT_SLVSTATE_MASK) >> I2C_STAT_SLVSTATE_SHIFT) == (uint32_t)I2C_STAT_SLVST_ADDR);
+
+ if (slaveAddress)
+ {
+ I2C_SlaveInvokeEvent(base, handle, kI2C_SlaveAddressMatchEvent);
+ (void)I2C_SlaveAddressIRQ(base, handle);
+ }
+ else
+ {
+ switch (handle->slaveFsm)
+ {
+ case kI2C_SlaveFsmReceive:
+ {
+ bool slaveReceive = (((i2cStatus & I2C_STAT_SLVSTATE_MASK) >> I2C_STAT_SLVSTATE_SHIFT) ==
+ (uint32_t)I2C_STAT_SLVST_RX);
+
+ if (slaveReceive)
+ {
+ rxSize = handle->transfer.rxSize;
+ /* if we have no receive buffer in this transfer, call callback to get new */
+ if ((handle->transfer.rxData == NULL) || (rxSize == 0U))
+ {
+ I2C_SlaveInvokeEvent(base, handle, kI2C_SlaveReceiveEvent);
+ }
+
+ rxSize = handle->transfer.rxSize;
+ /* receive a byte */
+ if ((handle->transfer.rxData != NULL) && (rxSize != 0U))
+ {
+ /* continue transaction */
+ base->SLVCTL = I2C_SLVCTL_SLVCONTINUE_MASK;
+ tmpdata = (uint8_t)base->SLVDAT;
+ *(handle->transfer.rxData) = tmpdata;
+ (handle->transfer.rxSize)--;
+ (handle->transfer.rxData)++;
+ (handle->transfer.transferredCount)++;
+ }
+
+ rxSize = handle->transfer.rxSize;
+ txSize = handle->transfer.txSize;
+ /* is this last transaction for this transfer? allow next transaction */
+ if ((0U == rxSize) && (0U == txSize))
+ {
+ handle->isBusy = false;
+ I2C_SlaveInvokeEvent(base, handle, kI2C_SlaveCompletionEvent);
+ }
+ }
+ else
+ {
+ base->SLVCTL = I2C_SLVCTL_SLVNACK_MASK;
+ }
+ }
+ break;
+
+ case kI2C_SlaveFsmTransmit:
+ {
+ bool slaveTransmit = (((i2cStatus & I2C_STAT_SLVSTATE_MASK) >> I2C_STAT_SLVSTATE_SHIFT) ==
+ (uint32_t)I2C_STAT_SLVST_TX);
+
+ if (slaveTransmit)
+ {
+ txSize = handle->transfer.txSize;
+ /* if we have no data in this transfer, call callback to get new */
+ if ((handle->transfer.txData == NULL) || (txSize == 0U))
+ {
+ I2C_SlaveInvokeEvent(base, handle, kI2C_SlaveTransmitEvent);
+ }
+
+ txSize = handle->transfer.txSize;
+ /* transmit a byte */
+ if ((handle->transfer.txData != NULL) && (txSize != 0U))
+ {
+ base->SLVDAT = *(handle->transfer.txData);
+ /* continue transaction */
+ base->SLVCTL = I2C_SLVCTL_SLVCONTINUE_MASK;
+ (handle->transfer.txSize)--;
+ (handle->transfer.txData)++;
+ (handle->transfer.transferredCount)++;
+ }
+
+ rxSize = handle->transfer.rxSize;
+ txSize = handle->transfer.txSize;
+ /* is this last transaction for this transfer? allow next transaction */
+ if ((0U == rxSize) && (0U == txSize))
+ {
+ handle->isBusy = false;
+ I2C_SlaveInvokeEvent(base, handle, kI2C_SlaveCompletionEvent);
+ }
+ }
+ else
+ {
+ base->SLVCTL = I2C_SLVCTL_SLVNACK_MASK;
+ }
+ }
+ break;
+
+ default:
+ /* incorrect state, slv_abort()? */
+ break;
+ }
+ }
+ }
+}
diff --git a/drivers/fsl_i2c.h b/drivers/fsl_i2c.h
new file mode 100644
index 0000000..5e5c511
--- /dev/null
+++ b/drivers/fsl_i2c.h
@@ -0,0 +1,1148 @@
+/*
+ * Copyright (c) 2016, Freescale Semiconductor, Inc.
+ * Copyright 2016-2021 NXP
+ * All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+#ifndef _FSL_I2C_H_
+#define _FSL_I2C_H_
+
+#include
+#include "fsl_device_registers.h"
+#include "fsl_common.h"
+
+/*******************************************************************************
+ * Definitions
+ ******************************************************************************/
+
+#define I2C_CFG_MASK 0x1f
+
+/*!
+ * @addtogroup i2c_driver
+ * @{
+ */
+
+/*! @file */
+
+/*! @name Driver version */
+/*@{*/
+/*! @brief I2C driver version. */
+#define FSL_I2C_DRIVER_VERSION (MAKE_VERSION(2, 3, 0))
+/*@}*/
+
+/*! @brief Retry times for waiting flag. */
+#ifndef I2C_RETRY_TIMES
+#define I2C_RETRY_TIMES 0U /* Define to zero means keep waiting until the flag is assert/deassert. */
+#endif
+
+/*! @brief Whether to ignore the nack signal of the last byte during master transmit. */
+#ifndef I2C_MASTER_TRANSMIT_IGNORE_LAST_NACK
+#define I2C_MASTER_TRANSMIT_IGNORE_LAST_NACK \
+ 1U /* Define to one means master ignores the last byte's nack and considers the transfer successful. */
+#endif
+
+/* definitions for MSTCODE bits in I2C Status register STAT */
+#define I2C_STAT_MSTCODE_IDLE (0U) /*!< Master Idle State Code */
+#define I2C_STAT_MSTCODE_RXREADY (1U) /*!< Master Receive Ready State Code */
+#define I2C_STAT_MSTCODE_TXREADY (2U) /*!< Master Transmit Ready State Code */
+#define I2C_STAT_MSTCODE_NACKADR (3U) /*!< Master NACK by slave on address State Code */
+#define I2C_STAT_MSTCODE_NACKDAT (4U) /*!< Master NACK by slave on data State Code */
+
+/* definitions for SLVSTATE bits in I2C Status register STAT */
+#define I2C_STAT_SLVST_ADDR (0)
+#define I2C_STAT_SLVST_RX (1)
+#define I2C_STAT_SLVST_TX (2)
+
+/*! @brief I2C status return codes. */
+enum
+{
+ kStatus_I2C_Busy = MAKE_STATUS(kStatusGroup_FLEXCOMM_I2C, 0), /*!< The master is already performing a transfer. */
+ kStatus_I2C_Idle = MAKE_STATUS(kStatusGroup_FLEXCOMM_I2C, 1), /*!< The slave driver is idle. */
+ kStatus_I2C_Nak =
+ MAKE_STATUS(kStatusGroup_FLEXCOMM_I2C, 2), /*!< The slave device sent a NAK in response to a byte. */
+ kStatus_I2C_InvalidParameter =
+ MAKE_STATUS(kStatusGroup_FLEXCOMM_I2C, 3), /*!< Unable to proceed due to invalid parameter. */
+ kStatus_I2C_BitError = MAKE_STATUS(kStatusGroup_FLEXCOMM_I2C, 4), /*!< Transferred bit was not seen on the bus. */
+ kStatus_I2C_ArbitrationLost = MAKE_STATUS(kStatusGroup_FLEXCOMM_I2C, 5), /*!< Arbitration lost error. */
+ kStatus_I2C_NoTransferInProgress =
+ MAKE_STATUS(kStatusGroup_FLEXCOMM_I2C, 6), /*!< Attempt to abort a transfer when one is not in progress. */
+ kStatus_I2C_DmaRequestFail = MAKE_STATUS(kStatusGroup_FLEXCOMM_I2C, 7), /*!< DMA request failed. */
+ kStatus_I2C_StartStopError = MAKE_STATUS(kStatusGroup_FLEXCOMM_I2C, 8), /*!< Start and stop error. */
+ kStatus_I2C_UnexpectedState = MAKE_STATUS(kStatusGroup_FLEXCOMM_I2C, 9), /*!< Unexpected state. */
+ kStatus_I2C_Timeout =
+ MAKE_STATUS(kStatusGroup_FLEXCOMM_I2C,
+ 10), /*!< Timeout when waiting for I2C master/slave pending status to set to continue transfer. */
+ kStatus_I2C_Addr_Nak = MAKE_STATUS(kStatusGroup_FLEXCOMM_I2C, 11), /*!< NAK received for Address */
+ kStatus_I2C_EventTimeout = MAKE_STATUS(kStatusGroup_FLEXCOMM_I2C, 12), /*!< Timeout waiting for bus event. */
+ kStatus_I2C_SclLowTimeout = MAKE_STATUS(kStatusGroup_FLEXCOMM_I2C, 13), /*!< Timeout SCL signal remains low. */
+};
+
+/*! @} */
+
+/*!
+ * @addtogroup i2c_driver
+ * @{
+ */
+
+/*!
+ * @brief I2C status flags.
+ *
+ * @note These enums are meant to be OR'd together to form a bit mask.
+ */
+enum _i2c_status_flags
+{
+ kI2C_MasterPendingFlag = I2C_STAT_MSTPENDING_MASK, /*!< The I2C module is waiting for software interaction. bit 0 */
+ kI2C_MasterArbitrationLostFlag =
+ I2C_STAT_MSTARBLOSS_MASK, /*!< The arbitration of the bus was lost. There was collision on the bus. bit 4*/
+ kI2C_MasterStartStopErrorFlag =
+ I2C_STAT_MSTSTSTPERR_MASK, /*!< There was an error during start or stop phase of the transaction. bit 6 */
+ kI2C_MasterIdleFlag = 1UL << 5U, /*!< The I2C master idle status. bit 5 */
+ kI2C_MasterRxReadyFlag = 1UL << I2C_STAT_MSTSTATE_SHIFT, /*!< The I2C master rx ready status. bit 1 */
+ kI2C_MasterTxReadyFlag = 1UL << (I2C_STAT_MSTSTATE_SHIFT + 1U), /*!< The I2C master tx ready status. bit 2 */
+ kI2C_MasterAddrNackFlag = 1UL << 7U, /*!< The I2C master address nack status. bit 7 */
+ kI2C_MasterDataNackFlag = 1UL << (I2C_STAT_MSTSTATE_SHIFT + 2U), /*!< The I2C master data nack status. bit 3 */
+ kI2C_SlavePendingFlag = I2C_STAT_SLVPENDING_MASK, /*!< The I2C module is waiting for software interaction. bit 8 */
+ kI2C_SlaveNotStretching = I2C_STAT_SLVNOTSTR_MASK, /*!< Indicates whether the slave is currently stretching clock (0
+ = yes, 1 = no). bit 11 */
+ kI2C_SlaveSelected =
+ I2C_STAT_SLVSEL_MASK, /*!< Indicates whether the slave is selected by an address match. bit 14 */
+ kI2C_SaveDeselected = I2C_STAT_SLVDESEL_MASK, /*!< Indicates that slave was previously deselected (deselect event
+ took place, w1c). bit 15 */
+ kI2C_SlaveAddressedFlag = 1UL << 22U, /*!< One of the I2C slave's 4 addresses is matched. bit 22 */
+ kI2C_SlaveReceiveFlag = 1UL << I2C_STAT_SLVSTATE_SHIFT, /*!< Slave receive data available. bit 9 */
+ kI2C_SlaveTransmitFlag = 1UL << (I2C_STAT_SLVSTATE_SHIFT + 1U), /*!< Slave data can be transmitted. bit 10 */
+ kI2C_SlaveAddress0MatchFlag = 1UL << 20U, /*!< Slave address0 match. bit 20 */
+ kI2C_SlaveAddress1MatchFlag = 1UL << I2C_STAT_SLVIDX_SHIFT, /*!< Slave address1 match. bit 12 */
+ kI2C_SlaveAddress2MatchFlag = 1UL << (I2C_STAT_SLVIDX_SHIFT + 1U), /*!< Slave address2 match. bit 13 */
+ kI2C_SlaveAddress3MatchFlag = 1UL << 21U, /*!< Slave address3 match. bit 21 */
+ kI2C_MonitorReadyFlag = I2C_STAT_MONRDY_MASK, /*!< The I2C monitor ready interrupt. bit 16 */
+ kI2C_MonitorOverflowFlag = I2C_STAT_MONOV_MASK, /*!< The monitor data overrun interrupt. bit 17 */
+ kI2C_MonitorActiveFlag = I2C_STAT_MONACTIVE_MASK, /*!< The monitor is active. bit 18 */
+ kI2C_MonitorIdleFlag = I2C_STAT_MONIDLE_MASK, /*!< The monitor idle interrupt. bit 19 */
+ kI2C_EventTimeoutFlag = I2C_STAT_EVENTTIMEOUT_MASK, /*!< The bus event timeout interrupt. bit 24 */
+ kI2C_SclTimeoutFlag = I2C_STAT_SCLTIMEOUT_MASK, /*!< The SCL timeout interrupt. bit 25 */
+
+ /* All master flags that can be cleared by software */
+ kI2C_MasterAllClearFlags = kI2C_MasterArbitrationLostFlag | kI2C_MasterStartStopErrorFlag,
+ /* All slave flags that can be cleared by software */
+ kI2C_SlaveAllClearFlags = kI2C_SaveDeselected,
+ /* All common flags that can be cleared by software */
+ kI2C_CommonAllClearFlags =
+ kI2C_MonitorOverflowFlag | kI2C_MonitorIdleFlag | kI2C_EventTimeoutFlag | kI2C_SclTimeoutFlag,
+};
+
+/*!
+ * @brief I2C interrupt enable.
+ *
+ * @note These enums are meant to be OR'd together to form a bit mask.
+ */
+enum _i2c_interrupt_enable
+{
+ kI2C_MasterPendingInterruptEnable =
+ I2C_STAT_MSTPENDING_MASK, /*!< The I2C master communication pending interrupt. */
+ kI2C_MasterArbitrationLostInterruptEnable =
+ I2C_STAT_MSTARBLOSS_MASK, /*!< The I2C master arbitration lost interrupt. */
+ kI2C_MasterStartStopErrorInterruptEnable =
+ I2C_STAT_MSTSTSTPERR_MASK, /*!< The I2C master start/stop timing error interrupt. */
+ kI2C_SlavePendingInterruptEnable = I2C_STAT_SLVPENDING_MASK, /*!< The I2C slave communication pending interrupt. */
+ kI2C_SlaveNotStretchingInterruptEnable =
+ I2C_STAT_SLVNOTSTR_MASK, /*!< The I2C slave not streching interrupt, deep-sleep mode can be entered only when
+ this interrupt occurs. */
+ kI2C_SlaveDeselectedInterruptEnable = I2C_STAT_SLVDESEL_MASK, /*!< The I2C slave deselection interrupt. */
+ kI2C_MonitorReadyInterruptEnable = I2C_STAT_MONRDY_MASK, /*!< The I2C monitor ready interrupt. */
+ kI2C_MonitorOverflowInterruptEnable = I2C_STAT_MONOV_MASK, /*!< The monitor data overrun interrupt. */
+ kI2C_MonitorIdleInterruptEnable = I2C_STAT_MONIDLE_MASK, /*!< The monitor idle interrupt. */
+ kI2C_EventTimeoutInterruptEnable = I2C_STAT_EVENTTIMEOUT_MASK, /*!< The bus event timeout interrupt. */
+ kI2C_SclTimeoutInterruptEnable = I2C_STAT_SCLTIMEOUT_MASK, /*!< The SCL timeout interrupt. */
+
+ /* All master interrupt sources */
+ kI2C_MasterAllInterruptEnable = kI2C_MasterPendingInterruptEnable | kI2C_MasterArbitrationLostInterruptEnable |
+ kI2C_MasterStartStopErrorInterruptEnable,
+ /* All slave interrupt sources */
+ kI2C_SlaveAllInterruptEnable =
+ kI2C_SlavePendingInterruptEnable | kI2C_SlaveNotStretchingInterruptEnable | kI2C_SlaveDeselectedInterruptEnable,
+ /* All common interrupt sources */
+ kI2C_CommonAllInterruptEnable = kI2C_MonitorReadyInterruptEnable | kI2C_MonitorOverflowInterruptEnable |
+ kI2C_MonitorIdleInterruptEnable | kI2C_EventTimeoutInterruptEnable |
+ kI2C_SclTimeoutInterruptEnable,
+};
+/*! @} */
+
+/*!
+ * @addtogroup i2c_master_driver
+ * @{
+ */
+
+/*! @brief Direction of master and slave transfers. */
+typedef enum _i2c_direction
+{
+ kI2C_Write = 0U, /*!< Master transmit. */
+ kI2C_Read = 1U /*!< Master receive. */
+} i2c_direction_t;
+
+/*!
+ * @brief Structure with settings to initialize the I2C master module.
+ *
+ * This structure holds configuration settings for the I2C peripheral. To initialize this
+ * structure to reasonable defaults, call the I2C_MasterGetDefaultConfig() function and
+ * pass a pointer to your configuration structure instance.
+ *
+ * The configuration structure can be made constant so it resides in flash.
+ */
+typedef struct _i2c_master_config
+{
+ bool enableMaster; /*!< Whether to enable master mode. */
+ uint32_t baudRate_Bps; /*!< Desired baud rate in bits per second. */
+ bool enableTimeout; /*!< Enable internal timeout function. */
+ uint8_t timeout_Ms; /*!< Event timeout and SCL low timeout value. */
+} i2c_master_config_t;
+
+/* Forward declaration of the transfer descriptor and handle typedefs. */
+/*! @brief I2C master transfer typedef */
+typedef struct _i2c_master_transfer i2c_master_transfer_t;
+
+/*! @brief I2C master handle typedef */
+typedef struct _i2c_master_handle i2c_master_handle_t;
+
+/*!
+ * @brief Master completion callback function pointer type.
+ *
+ * This callback is used only for the non-blocking master transfer API. Specify the callback you wish to use
+ * in the call to I2C_MasterTransferCreateHandle().
+ *
+ * @param base The I2C peripheral base address.
+ * @param completionStatus Either kStatus_Success or an error code describing how the transfer completed.
+ * @param userData Arbitrary pointer-sized value passed from the application.
+ */
+typedef void (*i2c_master_transfer_callback_t)(I2C_Type *base,
+ i2c_master_handle_t *handle,
+ status_t completionStatus,
+ void *userData);
+
+/*!
+ * @brief Transfer option flags.
+ *
+ * @note These enumerations are intended to be OR'd together to form a bit mask of options for
+ * the #_i2c_master_transfer::flags field.
+ */
+enum _i2c_master_transfer_flags
+{
+ kI2C_TransferDefaultFlag = 0x00U, /*!< Transfer starts with a start signal, stops with a stop signal. */
+ kI2C_TransferNoStartFlag = 0x01U, /*!< Don't send a start condition, address, and sub address */
+ kI2C_TransferRepeatedStartFlag = 0x02U, /*!< Send a repeated start condition */
+ kI2C_TransferNoStopFlag = 0x04U, /*!< Don't send a stop condition. */
+};
+
+/*! @brief States for the state machine used by transactional APIs. */
+enum _i2c_transfer_states
+{
+ kIdleState = 0,
+ kTransmitSubaddrState,
+ kTransmitDataState,
+ kReceiveDataBeginState,
+ kReceiveDataState,
+ kReceiveLastDataState,
+ kStartState,
+ kStopState,
+ kWaitForCompletionState
+};
+
+/*!
+ * @brief Non-blocking transfer descriptor structure.
+ *
+ * This structure is used to pass transaction parameters to the I2C_MasterTransferNonBlocking() API.
+ */
+struct _i2c_master_transfer
+{
+ uint32_t flags; /*!< Bit mask of options for the transfer. See enumeration #_i2c_master_transfer_flags for available
+ options. Set to 0 or #kI2C_TransferDefaultFlag for normal transfers. */
+ uint8_t slaveAddress; /*!< The 7-bit slave address. */
+ i2c_direction_t direction; /*!< Either #kI2C_Read or #kI2C_Write. */
+ uint32_t subaddress; /*!< Sub address. Transferred MSB first. */
+ size_t subaddressSize; /*!< Length of sub address to send in bytes. Maximum size is 4 bytes. */
+ void *data; /*!< Pointer to data to transfer. */
+ size_t dataSize; /*!< Number of bytes to transfer. */
+};
+
+/*!
+ * @brief Driver handle for master non-blocking APIs.
+ * @note The contents of this structure are private and subject to change.
+ */
+struct _i2c_master_handle
+{
+ uint8_t state; /*!< Transfer state machine current state. */
+ uint32_t transferCount; /*!< Indicates progress of the transfer */
+ uint32_t remainingBytes; /*!< Remaining byte count in current state. */
+ uint8_t *buf; /*!< Buffer pointer for current state. */
+ uint32_t remainingSubaddr;
+ uint8_t subaddrBuf[4];
+ bool checkAddrNack; /*!< Whether to check the nack signal is detected during addressing. */
+ i2c_master_transfer_t transfer; /*!< Copy of the current transfer info. */
+ i2c_master_transfer_callback_t completionCallback; /*!< Callback function pointer. */
+ void *userData; /*!< Application data passed to callback. */
+};
+
+/*! @} */
+
+/*!
+ * @addtogroup i2c_slave_driver
+ * @{
+ */
+/*! @brief I2C slave address register. */
+typedef enum _i2c_slave_address_register
+{
+ kI2C_SlaveAddressRegister0 = 0U, /*!< Slave Address 0 register. */
+ kI2C_SlaveAddressRegister1 = 1U, /*!< Slave Address 1 register. */
+ kI2C_SlaveAddressRegister2 = 2U, /*!< Slave Address 2 register. */
+ kI2C_SlaveAddressRegister3 = 3U, /*!< Slave Address 3 register. */
+} i2c_slave_address_register_t;
+
+/*! @brief Data structure with 7-bit Slave address and Slave address disable. */
+typedef struct _i2c_slave_address
+{
+ uint8_t address; /*!< 7-bit Slave address SLVADR. */
+ bool addressDisable; /*!< Slave address disable SADISABLE. */
+} i2c_slave_address_t;
+
+/*! @brief I2C slave address match options. */
+typedef enum _i2c_slave_address_qual_mode
+{
+ kI2C_QualModeMask = 0U, /*!< The SLVQUAL0 field (qualAddress) is used as a logical mask for matching address0. */
+ kI2C_QualModeExtend =
+ 1U, /*!< The SLVQUAL0 (qualAddress) field is used to extend address 0 matching in a range of addresses. */
+} i2c_slave_address_qual_mode_t;
+
+/*! @brief I2C slave bus speed options. */
+typedef enum _i2c_slave_bus_speed
+{
+ kI2C_SlaveStandardMode = 0U,
+ kI2C_SlaveFastMode = 1U,
+ kI2C_SlaveFastModePlus = 2U,
+ kI2C_SlaveHsMode = 3U,
+} i2c_slave_bus_speed_t;
+
+/*!
+ * @brief Structure with settings to initialize the I2C slave module.
+ *
+ * This structure holds configuration settings for the I2C slave peripheral. To initialize this
+ * structure to reasonable defaults, call the I2C_SlaveGetDefaultConfig() function and
+ * pass a pointer to your configuration structure instance.
+ *
+ * The configuration structure can be made constant so it resides in flash.
+ */
+typedef struct _i2c_slave_config
+{
+ i2c_slave_address_t address0; /*!< Slave's 7-bit address and disable. */
+ i2c_slave_address_t address1; /*!< Alternate slave 7-bit address and disable. */
+ i2c_slave_address_t address2; /*!< Alternate slave 7-bit address and disable. */
+ i2c_slave_address_t address3; /*!< Alternate slave 7-bit address and disable. */
+ i2c_slave_address_qual_mode_t qualMode; /*!< Qualify mode for slave address 0. */
+ uint8_t qualAddress; /*!< Slave address qualifier for address 0. */
+ i2c_slave_bus_speed_t
+ busSpeed; /*!< Slave bus speed mode. If the slave function stretches SCL to allow for software response, it must
+ provide sufficient data setup time to the master before releasing the stretched clock.
+ This is accomplished by inserting one clock time of CLKDIV at that point.
+ The #busSpeed value is used to configure CLKDIV
+ such that one clock time is greater than the tSU;DAT value noted
+ in the I2C bus specification for the I2C mode that is being used.
+ If the #busSpeed mode is unknown at compile time, use the longest data setup time
+ kI2C_SlaveStandardMode (250 ns) */
+ bool enableSlave; /*!< Enable slave mode. */
+} i2c_slave_config_t;
+
+/*!
+ * @brief Set of events sent to the callback for non blocking slave transfers.
+ *
+ * These event enumerations are used for two related purposes. First, a bit mask created by OR'ing together
+ * events is passed to I2C_SlaveTransferNonBlocking() in order to specify which events to enable.
+ * Then, when the slave callback is invoked, it is passed the current event through its @a transfer
+ * parameter.
+ *
+ * @note These enumerations are meant to be OR'd together to form a bit mask of events.
+ */
+typedef enum _i2c_slave_transfer_event
+{
+ kI2C_SlaveAddressMatchEvent = 0x01U, /*!< Received the slave address after a start or repeated start. */
+ kI2C_SlaveTransmitEvent = 0x02U, /*!< Callback is requested to provide data to transmit
+ (slave-transmitter role). */
+ kI2C_SlaveReceiveEvent = 0x04U, /*!< Callback is requested to provide a buffer in which to place received
+ data (slave-receiver role). */
+ kI2C_SlaveCompletionEvent = 0x20U, /*!< All data in the active transfer have been consumed. */
+ kI2C_SlaveDeselectedEvent =
+ 0x40U, /*!< The slave function has become deselected (SLVSEL flag changing from 1 to 0. */
+
+ /*! Bit mask of all available events. */
+ kI2C_SlaveAllEvents = kI2C_SlaveAddressMatchEvent | kI2C_SlaveTransmitEvent | kI2C_SlaveReceiveEvent |
+ kI2C_SlaveCompletionEvent | kI2C_SlaveDeselectedEvent,
+} i2c_slave_transfer_event_t;
+
+/*! @brief I2C slave handle typedef. */
+typedef struct _i2c_slave_handle i2c_slave_handle_t;
+
+/*! @brief I2C slave transfer structure */
+typedef struct _i2c_slave_transfer
+{
+ i2c_slave_handle_t *handle; /*!< Pointer to handle that contains this transfer. */
+ i2c_slave_transfer_event_t event; /*!< Reason the callback is being invoked. */
+ uint8_t receivedAddress; /*!< Matching address send by master. 7-bits plus R/nW bit0 */
+ uint32_t eventMask; /*!< Mask of enabled events. */
+ uint8_t *rxData; /*!< Transfer buffer for receive data */
+ const uint8_t *txData; /*!< Transfer buffer for transmit data */
+ size_t txSize; /*!< Transfer size */
+ size_t rxSize; /*!< Transfer size */
+ size_t transferredCount; /*!< Number of bytes transferred during this transfer. */
+ status_t completionStatus; /*!< Success or error code describing how the transfer completed. Only applies for
+ #kI2C_SlaveCompletionEvent. */
+} i2c_slave_transfer_t;
+
+/*!
+ * @brief Slave event callback function pointer type.
+ *
+ * This callback is used only for the slave non-blocking transfer API. To install a callback,
+ * use the I2C_SlaveSetCallback() function after you have created a handle.
+ *
+ * @param base Base address for the I2C instance on which the event occurred.
+ * @param transfer Pointer to transfer descriptor containing values passed to and/or from the callback.
+ * @param userData Arbitrary pointer-sized value passed from the application.
+ */
+typedef void (*i2c_slave_transfer_callback_t)(I2C_Type *base, volatile i2c_slave_transfer_t *transfer, void *userData);
+
+/*!
+ * @brief I2C slave software finite state machine states.
+ */
+typedef enum _i2c_slave_fsm
+{
+ kI2C_SlaveFsmAddressMatch = 0u,
+ kI2C_SlaveFsmReceive = 2u,
+ kI2C_SlaveFsmTransmit = 3u,
+} i2c_slave_fsm_t;
+
+/*!
+ * @brief I2C slave handle structure.
+ * @note The contents of this structure are private and subject to change.
+ */
+struct _i2c_slave_handle
+{
+ volatile i2c_slave_transfer_t transfer; /*!< I2C slave transfer. */
+ volatile bool isBusy; /*!< Whether transfer is busy. */
+ volatile i2c_slave_fsm_t slaveFsm; /*!< slave transfer state machine. */
+ i2c_slave_transfer_callback_t callback; /*!< Callback function called at transfer event. */
+ void *userData; /*!< Callback parameter passed to callback. */
+};
+
+/*! @brief Typedef for master interrupt handler. */
+typedef void (*flexcomm_i2c_master_irq_handler_t)(I2C_Type *base, i2c_master_handle_t *handle);
+
+/*! @brief Typedef for slave interrupt handler. */
+typedef void (*flexcomm_i2c_slave_irq_handler_t)(I2C_Type *base, i2c_slave_handle_t *handle);
+/*! @} */
+
+/*******************************************************************************
+ * API
+ ******************************************************************************/
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+/*!
+ * @addtogroup i2c_master_driver
+ * @{
+ */
+
+/*! @name Initialization and deinitialization */
+/*@{*/
+
+/*!
+ * @brief Provides a default configuration for the I2C master peripheral.
+ *
+ * This function provides the following default configuration for the I2C master peripheral:
+ * @code
+ * masterConfig->enableMaster = true;
+ * masterConfig->baudRate_Bps = 100000U;
+ * masterConfig->enableTimeout = false;
+ * @endcode
+ *
+ * After calling this function, you can override any settings in order to customize the configuration,
+ * prior to initializing the master driver with I2C_MasterInit().
+ *
+ * @param[out] masterConfig User provided configuration structure for default values. Refer to #i2c_master_config_t.
+ */
+void I2C_MasterGetDefaultConfig(i2c_master_config_t *masterConfig);
+
+/*!
+ * @brief Initializes the I2C master peripheral.
+ *
+ * This function enables the peripheral clock and initializes the I2C master peripheral as described by the user
+ * provided configuration. A software reset is performed prior to configuration.
+ *
+ * @param base The I2C peripheral base address.
+ * @param masterConfig User provided peripheral configuration. Use I2C_MasterGetDefaultConfig() to get a set of
+ * defaults
+ * that you can override.
+ * @param srcClock_Hz Frequency in Hertz of the I2C functional clock. Used to calculate the baud rate divisors,
+ * filter widths, and timeout periods.
+ */
+void I2C_MasterInit(I2C_Type *base, const i2c_master_config_t *masterConfig, uint32_t srcClock_Hz);
+
+/*!
+ * @brief Deinitializes the I2C master peripheral.
+ *
+ * This function disables the I2C master peripheral and gates the clock. It also performs a software
+ * reset to restore the peripheral to reset conditions.
+ *
+ * @param base The I2C peripheral base address.
+ */
+void I2C_MasterDeinit(I2C_Type *base);
+
+/*!
+ * @brief Returns an instance number given a base address.
+ *
+ * If an invalid base address is passed, debug builds will assert. Release builds will just return
+ * instance number 0.
+ *
+ * @param base The I2C peripheral base address.
+ * @return I2C instance number starting from 0.
+ */
+uint32_t I2C_GetInstance(I2C_Type *base);
+
+/*!
+ * @brief Performs a software reset.
+ *
+ * Restores the I2C master peripheral to reset conditions.
+ *
+ * @param base The I2C peripheral base address.
+ */
+static inline void I2C_MasterReset(I2C_Type *base)
+{
+}
+
+/*!
+ * @brief Enables or disables the I2C module as master.
+ *
+ * @param base The I2C peripheral base address.
+ * @param enable Pass true to enable or false to disable the specified I2C as master.
+ */
+static inline void I2C_MasterEnable(I2C_Type *base, bool enable)
+{
+ if (enable)
+ {
+ base->CFG = (base->CFG & (uint32_t)I2C_CFG_MASK) | I2C_CFG_MSTEN_MASK;
+ }
+ else
+ {
+ base->CFG = (base->CFG & (uint32_t)I2C_CFG_MASK) & ~I2C_CFG_MSTEN_MASK;
+ }
+}
+
+/*@}*/
+
+/*! @name Status */
+/*@{*/
+/*!
+ * @brief Gets the I2C status flags.
+ *
+ * A bit mask with the state of all I2C status flags is returned. For each flag, the corresponding bit
+ * in the return value is set if the flag is asserted.
+ *
+ * @param base The I2C peripheral base address.
+ * @return State of the status flags:
+ * - 1: related status flag is set.
+ * - 0: related status flag is not set.
+ * @see @ref _i2c_status_flags.
+ */
+uint32_t I2C_GetStatusFlags(I2C_Type *base);
+
+/*!
+ * @brief Clears the I2C status flag state.
+ *
+ * Refer to kI2C_CommonAllClearStatusFlags, kI2C_MasterAllClearStatusFlags and kI2C_SlaveAllClearStatusFlags to see
+ * the clearable flags. Attempts to clear other flags has no effect.
+ *
+ * @param base The I2C peripheral base address.
+ * @param statusMask A bitmask of status flags that are to be cleared. The mask is composed of the members in
+ * kI2C_CommonAllClearStatusFlags, kI2C_MasterAllClearStatusFlags and kI2C_SlaveAllClearStatusFlags. You may pass
+ * the result of a previous call to I2C_GetStatusFlags().
+ * @see #_i2c_status_flags, _i2c_master_status_flags and _i2c_slave_status_flags.
+ */
+static inline void I2C_ClearStatusFlags(I2C_Type *base, uint32_t statusMask)
+{
+ /* Only deal with the clearable flags */
+ statusMask &=
+ ((uint32_t)kI2C_CommonAllClearFlags | (uint32_t)kI2C_MasterAllClearFlags | (uint32_t)kI2C_SlaveAllClearFlags);
+ base->STAT = statusMask;
+}
+
+/*!
+ * @brief Clears the I2C master status flag state.
+ * @deprecated Do not use this function. It has been superceded by @ref I2C_ClearStatusFlags
+ * The following status register flags can be cleared:
+ * - #kI2C_MasterArbitrationLostFlag
+ * - #kI2C_MasterStartStopErrorFlag
+ *
+ * Attempts to clear other flags has no effect.
+ *
+ * @param base The I2C peripheral base address.
+ * @param statusMask A bitmask of status flags that are to be cleared. The mask is composed of
+ * #_i2c_status_flags enumerators OR'd together. You may pass the result of a previous call to
+ * I2C_GetStatusFlags().
+ * @see _i2c_status_flags.
+ */
+static inline void I2C_MasterClearStatusFlags(I2C_Type *base, uint32_t statusMask)
+{
+ /* Allow clearing just master status flags */
+ base->STAT = statusMask & (I2C_STAT_MSTARBLOSS_MASK | I2C_STAT_MSTSTSTPERR_MASK);
+}
+
+/*@}*/
+
+/*! @name Interrupts */
+/*@{*/
+
+/*!
+ * @brief Enables the I2C interrupt requests.
+ *
+ * @param base The I2C peripheral base address.
+ * @param interruptMask Bit mask of interrupts to enable. See #_i2c_interrupt_enable for the set
+ * of constants that should be OR'd together to form the bit mask.
+ */
+static inline void I2C_EnableInterrupts(I2C_Type *base, uint32_t interruptMask)
+{
+ base->INTENSET = interruptMask;
+}
+
+/*!
+ * @brief Disables the I2C interrupt requests.
+ *
+ * @param base The I2C peripheral base address.
+ * @param interruptMask Bit mask of interrupts to disable. See #_i2c_interrupt_enable for the set
+ * of constants that should be OR'd together to form the bit mask.
+ */
+static inline void I2C_DisableInterrupts(I2C_Type *base, uint32_t interruptMask)
+{
+ base->INTENCLR = interruptMask;
+}
+
+/*!
+ * @brief Returns the set of currently enabled I2C interrupt requests.
+ *
+ * @param base The I2C peripheral base address.
+ * @return A bitmask composed of #_i2c_interrupt_enable enumerators OR'd together to indicate the
+ * set of enabled interrupts.
+ */
+static inline uint32_t I2C_GetEnabledInterrupts(I2C_Type *base)
+{
+ return base->INTSTAT;
+}
+
+/*@}*/
+
+/*! @name Bus operations */
+/*@{*/
+
+/*!
+ * @brief Sets the I2C bus frequency for master transactions.
+ *
+ * The I2C master is automatically disabled and re-enabled as necessary to configure the baud
+ * rate. Do not call this function during a transfer, or the transfer is aborted.
+ *
+ * @param base The I2C peripheral base address.
+ * @param srcClock_Hz I2C functional clock frequency in Hertz.
+ * @param baudRate_Bps Requested bus frequency in bits per second.
+ */
+void I2C_MasterSetBaudRate(I2C_Type *base, uint32_t baudRate_Bps, uint32_t srcClock_Hz);
+
+/*!
+ * @brief Sets the I2C bus timeout value.
+ *
+ * If the SCL signal remains low or bus does not have event longer than the timeout value, kI2C_SclTimeoutFlag or
+ * kI2C_EventTimeoutFlag is set. This can indicete the bus is held by slave or any fault occurs to the I2C module.
+ *
+ * @param base The I2C peripheral base address.
+ * @param timeout_Ms Timeout value in millisecond.
+ * @param srcClock_Hz I2C functional clock frequency in Hertz.
+ */
+void I2C_MasterSetTimeoutValue(I2C_Type *base, uint8_t timeout_Ms, uint32_t srcClock_Hz);
+
+/*!
+ * @brief Returns whether the bus is idle.
+ *
+ * Requires the master mode to be enabled.
+ *
+ * @param base The I2C peripheral base address.
+ * @retval true Bus is busy.
+ * @retval false Bus is idle.
+ */
+static inline bool I2C_MasterGetBusIdleState(I2C_Type *base)
+{
+ /* True if MSTPENDING flag is set and MSTSTATE is zero == idle */
+ return ((base->STAT & (I2C_STAT_MSTPENDING_MASK | I2C_STAT_MSTSTATE_MASK)) == I2C_STAT_MSTPENDING_MASK);
+}
+
+/*!
+ * @brief Sends a START on the I2C bus.
+ *
+ * This function is used to initiate a new master mode transfer by sending the START signal.
+ * The slave address is sent following the I2C START signal.
+ *
+ * @param base I2C peripheral base pointer
+ * @param address 7-bit slave device address.
+ * @param direction Master transfer directions(transmit/receive).
+ * @retval kStatus_Success Successfully send the start signal.
+ * @retval kStatus_I2C_Busy Current bus is busy.
+ */
+status_t I2C_MasterStart(I2C_Type *base, uint8_t address, i2c_direction_t direction);
+
+/*!
+ * @brief Sends a STOP signal on the I2C bus.
+ *
+ * @retval kStatus_Success Successfully send the stop signal.
+ * @retval kStatus_I2C_Timeout Send stop signal failed, timeout.
+ */
+status_t I2C_MasterStop(I2C_Type *base);
+
+/*!
+ * @brief Sends a REPEATED START on the I2C bus.
+ *
+ * @param base I2C peripheral base pointer
+ * @param address 7-bit slave device address.
+ * @param direction Master transfer directions(transmit/receive).
+ * @retval kStatus_Success Successfully send the start signal.
+ * @retval kStatus_I2C_Busy Current bus is busy but not occupied by current I2C master.
+ */
+static inline status_t I2C_MasterRepeatedStart(I2C_Type *base, uint8_t address, i2c_direction_t direction)
+{
+ return I2C_MasterStart(base, address, direction);
+}
+
+/*!
+ * @brief Performs a polling send transfer on the I2C bus.
+ *
+ * Sends up to @a txSize number of bytes to the previously addressed slave device. The slave may
+ * reply with a NAK to any byte in order to terminate the transfer early. If this happens, this
+ * function returns #kStatus_I2C_Nak.
+ *
+ * @param base The I2C peripheral base address.
+ * @param txBuff The pointer to the data to be transferred.
+ * @param txSize The length in bytes of the data to be transferred.
+ * @param flags Transfer control flag to control special behavior like suppressing start or stop, for normal transfers
+ * use kI2C_TransferDefaultFlag
+ * @retval kStatus_Success Data was sent successfully.
+ * @retval #kStatus_I2C_Busy Another master is currently utilizing the bus.
+ * @retval #kStatus_I2C_Nak The slave device sent a NAK in response to a byte.
+ * @retval #kStatus_I2C_ArbitrationLost Arbitration lost error.
+ */
+status_t I2C_MasterWriteBlocking(I2C_Type *base, const void *txBuff, size_t txSize, uint32_t flags);
+
+/*!
+ * @brief Performs a polling receive transfer on the I2C bus.
+ *
+ * @param base The I2C peripheral base address.
+ * @param rxBuff The pointer to the data to be transferred.
+ * @param rxSize The length in bytes of the data to be transferred.
+ * @param flags Transfer control flag to control special behavior like suppressing start or stop, for normal transfers
+ * use kI2C_TransferDefaultFlag
+ * @retval kStatus_Success Data was received successfully.
+ * @retval #kStatus_I2C_Busy Another master is currently utilizing the bus.
+ * @retval #kStatus_I2C_Nak The slave device sent a NAK in response to a byte.
+ * @retval #kStatus_I2C_ArbitrationLost Arbitration lost error.
+ */
+status_t I2C_MasterReadBlocking(I2C_Type *base, void *rxBuff, size_t rxSize, uint32_t flags);
+
+/*!
+ * @brief Performs a master polling transfer on the I2C bus.
+ *
+ * @note The API does not return until the transfer succeeds or fails due
+ * to arbitration lost or receiving a NAK.
+ *
+ * @param base I2C peripheral base address.
+ * @param xfer Pointer to the transfer structure.
+ * @retval kStatus_Success Successfully complete the data transmission.
+ * @retval kStatus_I2C_Busy Previous transmission still not finished.
+ * @retval kStatus_I2C_Timeout Transfer error, wait signal timeout.
+ * @retval kStatus_I2C_ArbitrationLost Transfer error, arbitration lost.
+ * @retval kStataus_I2C_Nak Transfer error, receive NAK during transfer.
+ * @retval kStataus_I2C_Addr_Nak Transfer error, receive NAK during addressing.
+ */
+status_t I2C_MasterTransferBlocking(I2C_Type *base, i2c_master_transfer_t *xfer);
+
+/*@}*/
+
+/*! @name Non-blocking */
+/*@{*/
+
+/*!
+ * @brief Creates a new handle for the I2C master non-blocking APIs.
+ *
+ * The creation of a handle is for use with the non-blocking APIs. Once a handle
+ * is created, there is not a corresponding destroy handle. If the user wants to
+ * terminate a transfer, the I2C_MasterTransferAbort() API shall be called.
+ *
+ * @param base The I2C peripheral base address.
+ * @param[out] handle Pointer to the I2C master driver handle.
+ * @param callback User provided pointer to the asynchronous callback function.
+ * @param userData User provided pointer to the application callback data.
+ */
+void I2C_MasterTransferCreateHandle(I2C_Type *base,
+ i2c_master_handle_t *handle,
+ i2c_master_transfer_callback_t callback,
+ void *userData);
+
+/*!
+ * @brief Performs a non-blocking transaction on the I2C bus.
+ *
+ * @param base The I2C peripheral base address.
+ * @param handle Pointer to the I2C master driver handle.
+ * @param xfer The pointer to the transfer descriptor.
+ * @retval kStatus_Success The transaction was started successfully.
+ * @retval #kStatus_I2C_Busy Either another master is currently utilizing the bus, or a non-blocking
+ * transaction is already in progress.
+ */
+status_t I2C_MasterTransferNonBlocking(I2C_Type *base, i2c_master_handle_t *handle, i2c_master_transfer_t *xfer);
+
+/*!
+ * @brief Returns number of bytes transferred so far.
+ * @param base The I2C peripheral base address.
+ * @param handle Pointer to the I2C master driver handle.
+ * @param[out] count Number of bytes transferred so far by the non-blocking transaction.
+ * @retval kStatus_Success
+ * @retval #kStatus_I2C_Busy
+ */
+status_t I2C_MasterTransferGetCount(I2C_Type *base, i2c_master_handle_t *handle, size_t *count);
+
+/*!
+ * @brief Terminates a non-blocking I2C master transmission early.
+ *
+ * @note It is not safe to call this function from an IRQ handler that has a higher priority than the
+ * I2C peripheral's IRQ priority.
+ *
+ * @param base The I2C peripheral base address.
+ * @param handle Pointer to the I2C master driver handle.
+ * @retval kStatus_Success A transaction was successfully aborted.
+ * @retval #kStatus_I2C_Timeout Timeout during polling for flags.
+ */
+status_t I2C_MasterTransferAbort(I2C_Type *base, i2c_master_handle_t *handle);
+
+/*@}*/
+
+/*! @name IRQ handler */
+/*@{*/
+
+/*!
+ * @brief Reusable routine to handle master interrupts.
+ * @note This function does not need to be called unless you are reimplementing the
+ * nonblocking API's interrupt handler routines to add special functionality.
+ * @param base The I2C peripheral base address.
+ * @param handle Pointer to the I2C master driver handle.
+ */
+void I2C_MasterTransferHandleIRQ(I2C_Type *base, i2c_master_handle_t *handle);
+
+/*@}*/
+
+/*! @} */ /* end of i2c_master_driver */
+
+/*!
+ * @addtogroup i2c_slave_driver
+ * @{
+ */
+
+/*! @name Slave initialization and deinitialization */
+/*@{*/
+
+/*!
+ * @brief Provides a default configuration for the I2C slave peripheral.
+ *
+ * This function provides the following default configuration for the I2C slave peripheral:
+ * @code
+ * slaveConfig->enableSlave = true;
+ * slaveConfig->address0.disable = false;
+ * slaveConfig->address0.address = 0u;
+ * slaveConfig->address1.disable = true;
+ * slaveConfig->address2.disable = true;
+ * slaveConfig->address3.disable = true;
+ * slaveConfig->busSpeed = kI2C_SlaveStandardMode;
+ * @endcode
+ *
+ * After calling this function, override any settings to customize the configuration,
+ * prior to initializing the master driver with I2C_SlaveInit(). Be sure to override at least the @a
+ * address0.address member of the configuration structure with the desired slave address.
+ *
+ * @param[out] slaveConfig User provided configuration structure that is set to default values. Refer to
+ * #i2c_slave_config_t.
+ */
+void I2C_SlaveGetDefaultConfig(i2c_slave_config_t *slaveConfig);
+
+/*!
+ * @brief Initializes the I2C slave peripheral.
+ *
+ * This function enables the peripheral clock and initializes the I2C slave peripheral as described by the user
+ * provided configuration.
+ *
+ * @param base The I2C peripheral base address.
+ * @param slaveConfig User provided peripheral configuration. Use I2C_SlaveGetDefaultConfig() to get a set of defaults
+ * that you can override.
+ * @param srcClock_Hz Frequency in Hertz of the I2C functional clock. Used to calculate CLKDIV value to provide
+ * enough
+ * data setup time for master when slave stretches the clock.
+ */
+status_t I2C_SlaveInit(I2C_Type *base, const i2c_slave_config_t *slaveConfig, uint32_t srcClock_Hz);
+
+/*!
+ * @brief Configures Slave Address n register.
+ *
+ * This function writes new value to Slave Address register.
+ *
+ * @param base The I2C peripheral base address.
+ * @param addressRegister The module supports multiple address registers. The parameter determines which one shall be
+ * changed.
+ * @param address The slave address to be stored to the address register for matching.
+ * @param addressDisable Disable matching of the specified address register.
+ */
+void I2C_SlaveSetAddress(I2C_Type *base,
+ i2c_slave_address_register_t addressRegister,
+ uint8_t address,
+ bool addressDisable);
+
+/*!
+ * @brief Deinitializes the I2C slave peripheral.
+ *
+ * This function disables the I2C slave peripheral and gates the clock. It also performs a software
+ * reset to restore the peripheral to reset conditions.
+ *
+ * @param base The I2C peripheral base address.
+ */
+void I2C_SlaveDeinit(I2C_Type *base);
+
+/*!
+ * @brief Enables or disables the I2C module as slave.
+ *
+ * @param base The I2C peripheral base address.
+ * @param enable True to enable or flase to disable.
+ */
+static inline void I2C_SlaveEnable(I2C_Type *base, bool enable)
+{
+ /* Set or clear the SLVEN bit in the CFG register. */
+ base->CFG = I2C_CFG_SLVEN(enable);
+}
+
+/*@}*/ /* end of Slave initialization and deinitialization */
+
+/*! @name Slave status */
+/*@{*/
+
+/*!
+ * @brief Clears the I2C status flag state.
+ *
+ * The following status register flags can be cleared:
+ * - slave deselected flag
+ *
+ * Attempts to clear other flags has no effect.
+ *
+ * @param base The I2C peripheral base address.
+ * @param statusMask A bitmask of status flags that are to be cleared. The mask is composed of
+ * _i2c_slave_flags enumerators OR'd together. You may pass the result of a previous call to
+ * I2C_SlaveGetStatusFlags().
+ * @see _i2c_slave_flags.
+ */
+static inline void I2C_SlaveClearStatusFlags(I2C_Type *base, uint32_t statusMask)
+{
+ /* Allow clearing just slave status flags */
+ base->STAT = statusMask & I2C_STAT_SLVDESEL_MASK;
+}
+
+/*@}*/ /* end of Slave status */
+
+/*! @name Slave bus operations */
+/*@{*/
+
+/*!
+ * @brief Performs a polling send transfer on the I2C bus.
+ *
+ * The function executes blocking address phase and blocking data phase.
+ *
+ * @param base The I2C peripheral base address.
+ * @param txBuff The pointer to the data to be transferred.
+ * @param txSize The length in bytes of the data to be transferred.
+ * @return kStatus_Success Data has been sent.
+ * @return kStatus_Fail Unexpected slave state (master data write while master read from slave is expected).
+ */
+status_t I2C_SlaveWriteBlocking(I2C_Type *base, const uint8_t *txBuff, size_t txSize);
+
+/*!
+ * @brief Performs a polling receive transfer on the I2C bus.
+ *
+ * The function executes blocking address phase and blocking data phase.
+ *
+ * @param base The I2C peripheral base address.
+ * @param rxBuff The pointer to the data to be transferred.
+ * @param rxSize The length in bytes of the data to be transferred.
+ * @return kStatus_Success Data has been received.
+ * @return kStatus_Fail Unexpected slave state (master data read while master write to slave is expected).
+ */
+status_t I2C_SlaveReadBlocking(I2C_Type *base, uint8_t *rxBuff, size_t rxSize);
+
+/*@}*/ /* end of Slave bus operations */
+
+/*! @name Slave non-blocking */
+/*@{*/
+
+/*!
+ * @brief Creates a new handle for the I2C slave non-blocking APIs.
+ *
+ * The creation of a handle is for use with the non-blocking APIs. Once a handle
+ * is created, there is not a corresponding destroy handle. If the user wants to
+ * terminate a transfer, the I2C_SlaveTransferAbort() API shall be called.
+ *
+ * @param base The I2C peripheral base address.
+ * @param[out] handle Pointer to the I2C slave driver handle.
+ * @param callback User provided pointer to the asynchronous callback function.
+ * @param userData User provided pointer to the application callback data.
+ */
+void I2C_SlaveTransferCreateHandle(I2C_Type *base,
+ i2c_slave_handle_t *handle,
+ i2c_slave_transfer_callback_t callback,
+ void *userData);
+
+/*!
+ * @brief Starts accepting slave transfers.
+ *
+ * Call this API after calling I2C_SlaveInit() and I2C_SlaveTransferCreateHandle() to start processing
+ * transactions driven by an I2C master. The slave monitors the I2C bus and pass events to the
+ * callback that was passed into the call to I2C_SlaveTransferCreateHandle(). The callback is always invoked
+ * from the interrupt context.
+ *
+ * If no slave Tx transfer is busy, a master read from slave request invokes #kI2C_SlaveTransmitEvent callback.
+ * If no slave Rx transfer is busy, a master write to slave request invokes #kI2C_SlaveReceiveEvent callback.
+ *
+ * The set of events received by the callback is customizable. To do so, set the @a eventMask parameter to
+ * the OR'd combination of #i2c_slave_transfer_event_t enumerators for the events you wish to receive.
+ * The #kI2C_SlaveTransmitEvent and #kI2C_SlaveReceiveEvent events are always enabled and do not need
+ * to be included in the mask. Alternatively, you can pass 0 to get a default set of only the transmit and
+ * receive events that are always enabled. In addition, the #kI2C_SlaveAllEvents constant is provided as
+ * a convenient way to enable all events.
+ *
+ * @param base The I2C peripheral base address.
+ * @param handle Pointer to i2c_slave_handle_t structure which stores the transfer state.
+ * @param eventMask Bit mask formed by OR'ing together #i2c_slave_transfer_event_t enumerators to specify
+ * which events to send to the callback. Other accepted values are 0 to get a default set of
+ * only the transmit and receive events, and #kI2C_SlaveAllEvents to enable all events.
+ *
+ * @retval kStatus_Success Slave transfers were successfully started.
+ * @retval #kStatus_I2C_Busy Slave transfers have already been started on this handle.
+ */
+status_t I2C_SlaveTransferNonBlocking(I2C_Type *base, i2c_slave_handle_t *handle, uint32_t eventMask);
+
+/*!
+ * @brief Starts accepting master read from slave requests.
+ *
+ * The function can be called in response to #kI2C_SlaveTransmitEvent callback to start a new slave Tx transfer
+ * from within the transfer callback.
+ *
+ * The set of events received by the callback is customizable. To do so, set the @a eventMask parameter to
+ * the OR'd combination of #i2c_slave_transfer_event_t enumerators for the events you wish to receive.
+ * The #kI2C_SlaveTransmitEvent and #kI2C_SlaveReceiveEvent events are always enabled and do not need
+ * to be included in the mask. Alternatively, you can pass 0 to get a default set of only the transmit and
+ * receive events that are always enabled. In addition, the #kI2C_SlaveAllEvents constant is provided as
+ * a convenient way to enable all events.
+ *
+ * @param base The I2C peripheral base address.
+ * @param transfer Pointer to #i2c_slave_transfer_t structure.
+ * @param txData Pointer to data to send to master.
+ * @param txSize Size of txData in bytes.
+ * @param eventMask Bit mask formed by OR'ing together #i2c_slave_transfer_event_t enumerators to specify
+ * which events to send to the callback. Other accepted values are 0 to get a default set of
+ * only the transmit and receive events, and #kI2C_SlaveAllEvents to enable all events.
+ *
+ * @retval kStatus_Success Slave transfers were successfully started.
+ * @retval #kStatus_I2C_Busy Slave transfers have already been started on this handle.
+ */
+status_t I2C_SlaveSetSendBuffer(
+ I2C_Type *base, volatile i2c_slave_transfer_t *transfer, const void *txData, size_t txSize, uint32_t eventMask);
+
+/*!
+ * @brief Starts accepting master write to slave requests.
+ *
+ * The function can be called in response to #kI2C_SlaveReceiveEvent callback to start a new slave Rx transfer
+ * from within the transfer callback.
+ *
+ * The set of events received by the callback is customizable. To do so, set the @a eventMask parameter to
+ * the OR'd combination of #i2c_slave_transfer_event_t enumerators for the events you wish to receive.
+ * The #kI2C_SlaveTransmitEvent and #kI2C_SlaveReceiveEvent events are always enabled and do not need
+ * to be included in the mask. Alternatively, you can pass 0 to get a default set of only the transmit and
+ * receive events that are always enabled. In addition, the #kI2C_SlaveAllEvents constant is provided as
+ * a convenient way to enable all events.
+ *
+ * @param base The I2C peripheral base address.
+ * @param transfer Pointer to #i2c_slave_transfer_t structure.
+ * @param rxData Pointer to data to store data from master.
+ * @param rxSize Size of rxData in bytes.
+ * @param eventMask Bit mask formed by OR'ing together #i2c_slave_transfer_event_t enumerators to specify
+ * which events to send to the callback. Other accepted values are 0 to get a default set of
+ * only the transmit and receive events, and #kI2C_SlaveAllEvents to enable all events.
+ *
+ * @retval kStatus_Success Slave transfers were successfully started.
+ * @retval #kStatus_I2C_Busy Slave transfers have already been started on this handle.
+ */
+status_t I2C_SlaveSetReceiveBuffer(
+ I2C_Type *base, volatile i2c_slave_transfer_t *transfer, void *rxData, size_t rxSize, uint32_t eventMask);
+
+/*!
+ * @brief Returns the slave address sent by the I2C master.
+ *
+ * This function should only be called from the address match event callback #kI2C_SlaveAddressMatchEvent.
+ *
+ * @param base The I2C peripheral base address.
+ * @param transfer The I2C slave transfer.
+ * @return The 8-bit address matched by the I2C slave. Bit 0 contains the R/w direction bit, and
+ * the 7-bit slave address is in the upper 7 bits.
+ */
+static inline uint32_t I2C_SlaveGetReceivedAddress(I2C_Type *base, volatile i2c_slave_transfer_t *transfer)
+{
+ return transfer->receivedAddress;
+}
+
+/*!
+ * @brief Aborts the slave non-blocking transfers.
+ * @note This API could be called at any time to stop slave for handling the bus events.
+ * @param base The I2C peripheral base address.
+ * @param handle Pointer to i2c_slave_handle_t structure which stores the transfer state.
+ * @retval kStatus_Success
+ * @retval #kStatus_I2C_Idle
+ */
+void I2C_SlaveTransferAbort(I2C_Type *base, i2c_slave_handle_t *handle);
+
+/*!
+ * @brief Gets the slave transfer remaining bytes during a interrupt non-blocking transfer.
+ *
+ * @param base I2C base pointer.
+ * @param handle pointer to i2c_slave_handle_t structure.
+ * @param count Number of bytes transferred so far by the non-blocking transaction.
+ * @retval kStatus_InvalidArgument count is Invalid.
+ * @retval kStatus_Success Successfully return the count.
+ */
+status_t I2C_SlaveTransferGetCount(I2C_Type *base, i2c_slave_handle_t *handle, size_t *count);
+
+/*@}*/ /* end of Slave non-blocking */
+
+/*! @name Slave IRQ handler */
+/*@{*/
+
+/*!
+ * @brief Reusable routine to handle slave interrupts.
+ * @note This function does not need to be called unless you are reimplementing the
+ * non blocking API's interrupt handler routines to add special functionality.
+ * @param base The I2C peripheral base address.
+ * @param handle Pointer to i2c_slave_handle_t structure which stores the transfer state.
+ */
+void I2C_SlaveTransferHandleIRQ(I2C_Type *base, i2c_slave_handle_t *handle);
+
+/*@}*/ /* end of Slave IRQ handler */
+
+/*! @} */ /* end of i2c_slave_driver */
+
+#if defined(__cplusplus)
+}
+#endif
+
+#endif /* _FSL_I2C_H_ */
diff --git a/drivers/fsl_iocon.h b/drivers/fsl_iocon.h
new file mode 100644
index 0000000..3e95508
--- /dev/null
+++ b/drivers/fsl_iocon.h
@@ -0,0 +1,215 @@
+/*
+ * Copyright (c) 2016, Freescale Semiconductor, Inc.
+ * Copyright 2016-2021 NXP
+ * All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef _FSL_IOCON_H_
+#define _FSL_IOCON_H_
+
+#include "fsl_common.h"
+
+/*!
+ * @addtogroup lpc_iocon
+ * @{
+ */
+
+/*! @file */
+
+/*******************************************************************************
+ * Definitions
+ ******************************************************************************/
+
+/* Component ID definition, used by tools. */
+#ifndef FSL_COMPONENT_ID
+#define FSL_COMPONENT_ID "platform.drivers.lpc_iocon"
+#endif
+
+/*! @name Driver version */
+/*@{*/
+/*! @brief IOCON driver version. */
+#define FSL_IOCON_DRIVER_VERSION (MAKE_VERSION(2, 2, 0))
+/*@}*/
+
+/**
+ * @brief Array of IOCON pin definitions passed to IOCON_SetPinMuxing() must be in this format
+ */
+typedef struct _iocon_group
+{
+ uint8_t port; /* Pin port */
+ uint8_t pin; /* Pin number */
+ uint8_t ionumber; /* IO number */
+ uint16_t modefunc; /* Function and mode */
+} iocon_group_t;
+
+/**
+ * @brief IOCON function and mode selection definitions
+ * @note See the User Manual for specific modes and functions supported by the various pins.
+ */
+#define IOCON_FUNC0 0x0 /*!< Selects pin function 0 */
+#define IOCON_FUNC1 0x1 /*!< Selects pin function 1 */
+#define IOCON_FUNC2 0x2 /*!< Selects pin function 2 */
+#define IOCON_FUNC3 0x3 /*!< Selects pin function 3 */
+#define IOCON_FUNC4 0x4 /*!< Selects pin function 4 */
+#define IOCON_FUNC5 0x5 /*!< Selects pin function 5 */
+#define IOCON_FUNC6 0x6 /*!< Selects pin function 6 */
+#define IOCON_FUNC7 0x7 /*!< Selects pin function 7 */
+#if defined(FSL_FEATURE_IOCON_FUNC_FIELD_WIDTH) && (FSL_FEATURE_IOCON_FUNC_FIELD_WIDTH == 4)
+#define IOCON_FUNC8 0x8 /*!< Selects pin function 8 */
+#define IOCON_FUNC9 0x9 /*!< Selects pin function 9 */
+#define IOCON_FUNC10 0xA /*!< Selects pin function 10 */
+#define IOCON_FUNC11 0xB /*!< Selects pin function 11 */
+#define IOCON_FUNC12 0xC /*!< Selects pin function 12 */
+#define IOCON_FUNC13 0xD /*!< Selects pin function 13 */
+#define IOCON_FUNC14 0xE /*!< Selects pin function 14 */
+#define IOCON_FUNC15 0xF /*!< Selects pin function 15 */
+#endif /* FSL_FEATURE_IOCON_FUNC_FIELD_WIDTH */
+
+#if defined(IOCON_PIO_MODE_SHIFT)
+#define IOCON_MODE_INACT (0x0 << IOCON_PIO_MODE_SHIFT) /*!< No addition pin function */
+#define IOCON_MODE_PULLDOWN (0x1 << IOCON_PIO_MODE_SHIFT) /*!< Selects pull-down function */
+#define IOCON_MODE_PULLUP (0x2 << IOCON_PIO_MODE_SHIFT) /*!< Selects pull-up function */
+#define IOCON_MODE_REPEATER (0x3 << IOCON_PIO_MODE_SHIFT) /*!< Selects pin repeater function */
+#endif
+
+#if defined(IOCON_PIO_I2CSLEW_SHIFT)
+#define IOCON_GPIO_MODE (0x1 << IOCON_PIO_I2CSLEW_SHIFT) /*!< GPIO Mode */
+#define IOCON_I2C_MODE (0x0 << IOCON_PIO_I2CSLEW_SHIFT) /*!< I2C Slew Rate Control */
+#define IOCON_I2C_SLEW IOCON_I2C_MODE /*!< Deprecated name for #IOCON_I2C_MODE */
+#endif
+
+#if defined(IOCON_PIO_EGP_SHIFT)
+#define IOCON_GPIO_MODE (0x1 << IOCON_PIO_EGP_SHIFT) /*!< GPIO Mode */
+#define IOCON_I2C_MODE (0x0 << IOCON_PIO_EGP_SHIFT) /*!< I2C Slew Rate Control */
+#define IOCON_I2C_SLEW IOCON_I2C_MODE /*!< Deprecated name for #IOCON_I2C_MODE */
+#endif
+
+#if defined(IOCON_PIO_SLEW_SHIFT)
+#define IOCON_SLEW_STANDARD (0x0 << IOCON_PIO_SLEW_SHIFT) /*!< Driver Slew Rate Control */
+#define IOCON_SLEW_FAST (0x1 << IOCON_PIO_SLEW_SHIFT) /*!< Driver Slew Rate Control */
+#endif
+
+#if defined(IOCON_PIO_INVERT_SHIFT)
+#define IOCON_INV_EN (0x1 << IOCON_PIO_INVERT_SHIFT) /*!< Enables invert function on input */
+#endif
+
+#if defined(IOCON_PIO_DIGIMODE_SHIFT)
+#define IOCON_ANALOG_EN (0x0 << IOCON_PIO_DIGIMODE_SHIFT) /*!< Enables analog function by setting 0 to bit 7 */
+#define IOCON_DIGITAL_EN \
+ (0x1 << IOCON_PIO_DIGIMODE_SHIFT) /*!< Enables digital function by setting 1 to bit 7(default) */
+#endif
+
+#if defined(IOCON_PIO_FILTEROFF_SHIFT)
+#define IOCON_INPFILT_OFF (0x1 << IOCON_PIO_FILTEROFF_SHIFT) /*!< Input filter Off for GPIO pins */
+#define IOCON_INPFILT_ON (0x0 << IOCON_PIO_FILTEROFF_SHIFT) /*!< Input filter On for GPIO pins */
+#endif
+
+#if defined(IOCON_PIO_I2CDRIVE_SHIFT)
+#define IOCON_I2C_LOWDRIVER (0x0 << IOCON_PIO_I2CDRIVE_SHIFT) /*!< Low drive, Output drive sink is 4 mA */
+#define IOCON_I2C_HIGHDRIVER (0x1 << IOCON_PIO_I2CDRIVE_SHIFT) /*!< High drive, Output drive sink is 20 mA */
+#endif
+
+#if defined(IOCON_PIO_OD_SHIFT)
+#define IOCON_OPENDRAIN_EN (0x1 << IOCON_PIO_OD_SHIFT) /*!< Enables open-drain function */
+#endif
+
+#if defined(IOCON_PIO_I2CFILTER_SHIFT)
+#define IOCON_I2CFILTER_OFF (0x1 << IOCON_PIO_I2CFILTER_SHIFT) /*!< I2C 50 ns glitch filter enabled */
+#define IOCON_I2CFILTER_ON (0x0 << IOCON_PIO_I2CFILTER_SHIFT) /*!< I2C 50 ns glitch filter not enabled, */
+#endif
+
+#if defined(IOCON_PIO_ASW_SHIFT)
+#define IOCON_AWS_EN (0x1 << IOCON_PIO_ASW_SHIFT) /*!< Enables analog switch function */
+#endif
+
+#if defined(IOCON_PIO_SSEL_SHIFT)
+#define IOCON_SSEL_3V3 (0x0 << IOCON_PIO_SSEL_SHIFT) /*!< 3V3 signaling in I2C mode */
+#define IOCON_SSEL_1V8 (0x1 << IOCON_PIO_SSEL_SHIFT) /*!< 1V8 signaling in I2C mode */
+#endif
+
+#if defined(IOCON_PIO_ECS_SHIFT)
+#define IOCON_ECS_OFF (0x0 << IOCON_PIO_ECS_SHIFT) /*!< IO is an open drain cell */
+#define IOCON_ECS_ON (0x1 << IOCON_PIO_ECS_SHIFT) /*!< Pull-up resistor is connected */
+#endif
+
+#if defined(IOCON_PIO_S_MODE_SHIFT)
+#define IOCON_S_MODE_0CLK (0x0 << IOCON_PIO_S_MODE_SHIFT) /*!< Bypass input filter */
+#define IOCON_S_MODE_1CLK \
+ (0x1 << IOCON_PIO_S_MODE_SHIFT) /*!< Input pulses shorter than 1 filter clock are rejected \ \ \ \ \
+ */
+#define IOCON_S_MODE_2CLK \
+ (0x2 << IOCON_PIO_S_MODE_SHIFT) /*!< Input pulses shorter than 2 filter clock2 are rejected \ \ \ \ \
+ */
+#define IOCON_S_MODE_3CLK \
+ (0x3 << IOCON_PIO_S_MODE_SHIFT) /*!< Input pulses shorter than 3 filter clock2 are rejected \ \ \ \ \
+ */
+#define IOCON_S_MODE(clks) ((clks) << IOCON_PIO_S_MODE_SHIFT) /*!< Select clocks for digital input filter mode */
+#endif
+
+#if defined(IOCON_PIO_CLK_DIV_SHIFT)
+#define IOCON_CLKDIV(div) \
+ ((div) \
+ << IOCON_PIO_CLK_DIV_SHIFT) /*!< Select peripheral clock divider for input filter sampling clock, 2^n, n=0-6 */
+#endif
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+#if (defined(FSL_FEATURE_IOCON_ONE_DIMENSION) && (FSL_FEATURE_IOCON_ONE_DIMENSION == 1))
+/**
+ * @brief Sets I/O Control pin mux
+ * @param base : The base of IOCON peripheral on the chip
+ * @param ionumber : GPIO number to mux
+ * @param modefunc : OR'ed values of type IOCON_*
+ * @return Nothing
+ */
+__STATIC_INLINE void IOCON_PinMuxSet(IOCON_Type *base, uint8_t ionumber, uint32_t modefunc)
+{
+ base->PIO[ionumber] = modefunc;
+}
+#else
+/**
+ * @brief Sets I/O Control pin mux
+ * @param base : The base of IOCON peripheral on the chip
+ * @param port : GPIO port to mux
+ * @param pin : GPIO pin to mux
+ * @param modefunc : OR'ed values of type IOCON_*
+ * @return Nothing
+ */
+__STATIC_INLINE void IOCON_PinMuxSet(IOCON_Type *base, uint8_t port, uint8_t pin, uint32_t modefunc)
+{
+ base->PIO[port][pin] = modefunc;
+}
+#endif
+
+/**
+ * @brief Set all I/O Control pin muxing
+ * @param base : The base of IOCON peripheral on the chip
+ * @param pinArray : Pointer to array of pin mux selections
+ * @param arrayLength : Number of entries in pinArray
+ * @return Nothing
+ */
+__STATIC_INLINE void IOCON_SetPinMuxing(IOCON_Type *base, const iocon_group_t *pinArray, uint32_t arrayLength)
+{
+ uint32_t i;
+
+ for (i = 0; i < arrayLength; i++)
+ {
+#if (defined(FSL_FEATURE_IOCON_ONE_DIMENSION) && (FSL_FEATURE_IOCON_ONE_DIMENSION == 1))
+ IOCON_PinMuxSet(base, pinArray[i].ionumber, pinArray[i].modefunc);
+#else
+ IOCON_PinMuxSet(base, pinArray[i].port, pinArray[i].pin, pinArray[i].modefunc);
+#endif /* FSL_FEATURE_IOCON_ONE_DIMENSION */
+ }
+}
+
+/* @} */
+
+#if defined(__cplusplus)
+}
+#endif
+
+#endif /* _FSL_IOCON_H_ */
diff --git a/drivers/fsl_power.c b/drivers/fsl_power.c
new file mode 100644
index 0000000..24e3f83
--- /dev/null
+++ b/drivers/fsl_power.c
@@ -0,0 +1,1985 @@
+/*
+ * Copyright (c) 2016, Freescale Semiconductor, Inc.
+ * Copyright 2016, NXP
+ * All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+#include "fsl_common.h"
+#include "fsl_power.h"
+
+/* Component ID definition, used by tools. */
+#ifndef FSL_COMPONENT_ID
+#define FSL_COMPONENT_ID "platform.drivers.power"
+#endif
+
+/*******************************************************************************
+ * Variables
+ ******************************************************************************/
+
+/*******************************************************************************
+ * Definitions
+ ******************************************************************************/
+/** @brief Low Power main structure */
+typedef enum
+{
+ VD_AON = 0x0, /*!< Digital Always On power domain */
+ VD_MEM = 0x1, /*!< Memories (SRAM) power domain */
+ VD_DCDC = 0x2, /*!< Core logic power domain */
+ VD_DEEPSLEEP = 0x3 /*!< Core logic power domain */
+} LPC_POWER_DOMAIN_T;
+
+/**
+ * @brief LDO_FLASH_NV & LDO_USB voltage settings
+ */
+typedef enum _v_flashnv
+{
+ V_LDOFLASHNV_1P650 = 0, /*!< 0.95 V */
+ V_LDOFLASHNV_1P700 = 1, /*!< 0.975 V */
+ V_LDOFLASHNV_1P750 = 2, /*!< 1 V */
+ V_LDOFLASHNV_0P800 = 3, /*!< 1.025 V */
+ V_LDOFLASHNV_1P850 = 4, /*!< 1.050 V */
+ V_LDOFLASHNV_1P900 = 5, /*!< 1.075 V */
+ V_LDOFLASHNV_1P950 = 6, /*!< 1.1 V */
+ V_LDOFLASHNV_2P000 = 7 /*!< 1.125 V */
+} v_flashnv_t;
+
+/** @brief Low Power main structure */
+typedef struct
+{ /* */
+ __IO uint32_t CFG; /*!< Low Power Mode Configuration, and miscallenous options */
+ __IO uint32_t PDCTRL0; /*!< Power Down control : controls power of various modules
+ in the different Low power modes, including ROM */
+ __IO uint32_t SRAMRETCTRL; /*!< Power Down control : controls power SRAM instances
+ in the different Low power modes */
+ __IO uint32_t CPURETCTRL; /*!< CPU0 retention control : controls CPU retention parameters in POWER DOWN modes */
+ __IO uint64_t VOLTAGE; /*!< Voltage control in Low Power Modes */
+ __IO uint64_t WAKEUPSRC; /*!< Wake up sources control for sleepcon */
+ __IO uint64_t WAKEUPINT; /*!< Wake up sources control for ARM */
+ __IO uint32_t HWWAKE; /*!< Interrupt that can postpone power down modes
+ in case an interrupt is pending when the processor request deepsleep */
+ __IO uint32_t WAKEUPIOSRC; /*!< Wake up I/O sources in DEEP POWER DOWN mode */
+ __IO uint32_t TIMERCFG; /*!< Wake up timers configuration */
+ __IO uint32_t TIMERCOUNT; /*!< Wake up Timer count*/
+ __IO uint32_t POWERCYCLE; /*!< Cancels entry in Low Power mode if set with 0xDEADABBA (might be used by some
+ interrupt handlers)*/
+} LPC_LOWPOWER_T;
+
+/* */
+#define LOWPOWER_POWERCYCLE_CANCELLED 0xDEADABBAUL /*!< */
+
+/**
+ * @brief SRAM Low Power Modes
+ */
+#define LOWPOWER_SRAM_LPMODE_MASK (0xFUL)
+#define LOWPOWER_SRAM_LPMODE_ACTIVE (0x6UL) /*!< SRAM functional mode */
+#define LOWPOWER_SRAM_LPMODE_SLEEP (0xFUL) /*!< SRAM Sleep mode (Data retention, fast wake up) */
+#define LOWPOWER_SRAM_LPMODE_DEEPSLEEP (0x8UL) /*!< SRAM Deep Sleep mode (Data retention, slow wake up) */
+#define LOWPOWER_SRAM_LPMODE_SHUTDOWN (0x9UL) /*!< SRAM Shut Down mode (no data retention) */
+#define LOWPOWER_SRAM_LPMODE_POWERUP (0xAUL) /*!< SRAM is powering up */
+
+/**
+ * @brief Wake up timers configuration in Low Power Modes
+ */
+#define LOWPOWER_TIMERCFG_CTRL_INDEX 0
+#define LOWPOWER_TIMERCFG_CTRL_MASK (0x1UL << LOWPOWER_TIMERCFG_CTRL_INDEX)
+#define LOWPOWER_TIMERCFG_TIMER_INDEX 1
+#define LOWPOWER_TIMERCFG_TIMER_MASK (0x7UL << LOWPOWER_TIMERCFG_TIMER_INDEX)
+#define LOWPOWER_TIMERCFG_OSC32K_INDEX 4
+#define LOWPOWER_TIMERCFG_OSC32K_MASK (0x1UL << LOWPOWER_TIMERCFG_OSC32K_INDEX)
+
+#define LOWPOWER_TIMERCFG_CTRL_DISABLE 0 /*!< Wake Timer Disable */
+#define LOWPOWER_TIMERCFG_CTRL_ENABLE 1 /*!< Wake Timer Enable */
+
+/**
+ * @brief Primary Wake up timers configuration in Low Power Modes
+ */
+#define LOWPOWER_TIMERCFG_TIMER_RTC1KHZ 0 /*!< 1 KHz Real Time Counter (RTC) used as wake up source */
+#define LOWPOWER_TIMERCFG_TIMER_RTC1HZ 1 /*!< 1 Hz Real Time Counter (RTC) used as wake up source */
+#define LOWPOWER_TIMERCFG_TIMER_OSTIMER 2 /*!< OS Event Timer used as wake up source */
+
+#define LOWPOWER_TIMERCFG_OSC32K_FRO32KHZ 0 /*!< Wake up Timers uses FRO 32 KHz as clock source */
+#define LOWPOWER_TIMERCFG_OSC32K_XTAL32KHZ 1 /*!< Wake up Timers uses Chrystal 32 KHz as clock source */
+
+//! @brief Interface for lowpower functions
+typedef struct LowpowerDriverInterface
+{
+ void (*power_cycle_cpu_and_flash)(void);
+ void (*set_lowpower_mode)(LPC_LOWPOWER_T *p_lowpower_cfg);
+} lowpower_driver_interface_t;
+
+/**< DCDC Power Profiles */
+typedef enum
+{
+ DCDC_POWER_PROFILE_LOW, /**< LOW (for CPU frequencies below DCDC_POWER_PROFILE_LOW_MAX_FREQ_HZ) */
+ DCDC_POWER_PROFILE_MEDIUM, /**< MEDIUM (for CPU frequencies between DCDC_POWER_PROFILE_LOW_MAX_FREQ_HZ and
+ DCDC_POWER_PROFILE_MEDIUM_MAX_FREQ_HZ) */
+ DCDC_POWER_PROFILE_HIGH, /**< HIGH (for CPU frequencies between DCDC_POWER_PROFILE_MEDIUM_MAX_FREQ_HZ and
+ DCDC_POWER_PROFILE_HIGH_MAX_FREQ_HZ) */
+} lowpower_dcdc_power_profile_enum;
+
+/**< Manufacturing Process Corners */
+typedef enum
+{
+ PROCESS_CORNER_SSS, /**< Slow Corner Process */
+ PROCESS_CORNER_NNN, /**< Nominal Corner Process */
+ PROCESS_CORNER_FFF, /**< Fast Corner Process */
+ PROCESS_CORNER_OTHERS, /**< SFN, SNF, NFS, Poly Res ... Corner Process */
+} lowpower_process_corner_enum;
+
+/**
+ * @brief DCDC voltage settings
+ */
+typedef enum _v_dcdc
+{
+ V_DCDC_0P950 = 0, /*!< 0.95 V */
+ V_DCDC_0P975 = 1, /*!< 0.975 V */
+ V_DCDC_1P000 = 2, /*!< 1 V */
+ V_DCDC_1P025 = 3, /*!< 1.025 V */
+ V_DCDC_1P050 = 4, /*!< 1.050 V */
+ V_DCDC_1P075 = 5, /*!< 1.075 V */
+ V_DCDC_1P100 = 6, /*!< 1.1 V */
+ V_DCDC_1P125 = 7, /*!< 1.125 V */
+ V_DCDC_1P150 = 8, /*!< 1.150 V */
+ V_DCDC_1P175 = 9, /*!< 1.175 V */
+ V_DCDC_1P200 = 10 /*!< 1.2 V */
+} v_dcdc_t;
+
+/**
+ * @brief Deep Sleep LDO voltage settings
+ */
+typedef enum _v_deepsleep
+{
+ V_DEEPSLEEP_0P900 = 0, /*!< 0.9 V */
+ V_DEEPSLEEP_0P925 = 1, /*!< 0.925 V */
+ V_DEEPSLEEP_0P950 = 2, /*!< 0.95 V */
+ V_DEEPSLEEP_0P975 = 3, /*!< 0.975 V */
+ V_DEEPSLEEP_1P000 = 4, /*!< 1.000 V */
+ V_DEEPSLEEP_1P025 = 5, /*!< 1.025 V */
+ V_DEEPSLEEP_1P050 = 6, /*!< 1.050 V */
+ V_DEEPSLEEP_1P075 = 7 /*!< 1.075 V */
+} v_deepsleep_t;
+
+/**
+ * @brief Always On and Memories LDO voltage settings
+ */
+typedef enum _v_ao
+{
+ V_AO_0P700 = 1, /*!< 0.7 V */
+ V_AO_0P725 = 2, /*!< 0.725 V */
+ V_AO_0P750 = 3, /*!< 0.75 V */
+ V_AO_0P775 = 4, /*!< 0.775 V */
+ V_AO_0P800 = 5, /*!< 0.8 V */
+ V_AO_0P825 = 6, /*!< 0.825 V */
+ V_AO_0P850 = 7, /*!< 0.85 V */
+ V_AO_0P875 = 8, /*!< 0.875 V */
+ V_AO_0P900 = 9, /*!< 0.9 V */
+ V_AO_0P960 = 10, /*!< 0.96 V */
+ V_AO_0P970 = 11, /*!< 0.97 V */
+ V_AO_0P980 = 12, /*!< 0.98 V */
+ V_AO_0P990 = 13, /*!< 0.99 V */
+ V_AO_1P000 = 14, /*!< 1 V */
+ V_AO_1P010 = 15, /*!< 1.01 V */
+ V_AO_1P020 = 16, /*!< 1.02 V */
+ V_AO_1P030 = 17, /*!< 1.03 V */
+ V_AO_1P040 = 18, /*!< 1.04 V */
+ V_AO_1P050 = 19, /*!< 1.05 V */
+ V_AO_1P060 = 20, /*!< 1.06 V */
+ V_AO_1P070 = 21, /*!< 1.07 V */
+ V_AO_1P080 = 22, /*!< 1.08 V */
+ V_AO_1P090 = 23, /*!< 1.09 V */
+ V_AO_1P100 = 24, /*!< 1.1 V */
+ V_AO_1P110 = 25, /*!< 1.11 V */
+ V_AO_1P120 = 26, /*!< 1.12 V */
+ V_AO_1P130 = 27, /*!< 1.13 V */
+ V_AO_1P140 = 28, /*!< 1.14 V */
+ V_AO_1P150 = 29, /*!< 1.15 V */
+ V_AO_1P160 = 30, /*!< 1.16 V */
+ V_AO_1P220 = 31 /*!< 1.22 V */
+} v_ao_t;
+
+/* Low Power modes */
+#define LOWPOWER_CFG_LPMODE_INDEX 0
+#define LOWPOWER_CFG_LPMODE_MASK (0x3UL << LOWPOWER_CFG_LPMODE_INDEX)
+#define LOWPOWER_CFG_SELCLOCK_INDEX 2
+#define LOWPOWER_CFG_SELCLOCK_MASK (0x1UL << LOWPOWER_CFG_SELCLOCK_INDEX)
+#define LOWPOWER_CFG_SELMEMSUPPLY_INDEX 3
+#define LOWPOWER_CFG_SELMEMSUPPLY_MASK (0x1UL << LOWPOWER_CFG_SELMEMSUPPLY_INDEX)
+#define LOWPOWER_CFG_MEMLOWPOWERMODE_INDEX 4
+#define LOWPOWER_CFG_MEMLOWPOWERMODE_MASK (0x1UL << LOWPOWER_CFG_MEMLOWPOWERMODE_INDEX)
+#define LOWPOWER_CFG_LDODEEPSLEEPREF_INDEX 5
+#define LOWPOWER_CFG_LDODEEPSLEEPREF_MASK (0x1UL << LOWPOWER_CFG_LDODEEPSLEEPREF_INDEX)
+
+#define LOWPOWER_CFG_LPMODE_ACTIVE 0 /*!< ACTIVE mode */
+#define LOWPOWER_CFG_LPMODE_DEEPSLEEP 1 /*!< DEEP SLEEP mode */
+#define LOWPOWER_CFG_LPMODE_POWERDOWN 2 /*!< POWER DOWN mode */
+#define LOWPOWER_CFG_LPMODE_DEEPPOWERDOWN 3 /*!< DEEP POWER DOWN mode */
+#define LOWPOWER_CFG_LPMODE_SLEEP 4 /*!< SLEEP mode */
+
+#define LOWPOWER_CFG_SELCLOCK_1MHZ 0 /*!< The 1 MHz clock is used during the configuration of the PMC */
+#define LOWPOWER_CFG_SELCLOCK_12MHZ \
+ 1 /*!< The 12 MHz clock is used during the configuration of the PMC (to speed up PMC configuration process)*/
+
+#define LOWPOWER_CFG_SELMEMSUPPLY_LDOMEM 0 /*!< In DEEP SLEEP power mode, the Memories are supplied by the LDO_MEM */
+#define LOWPOWER_CFG_SELMEMSUPPLY_LDODEEPSLEEP \
+ 1 /*!< In DEEP SLEEP power mode, the Memories are supplied by the LDO_DEEP_SLEEP (or DCDC) */
+
+#define LOWPOWER_CFG_MEMLOWPOWERMODE_SOURCEBIASING \
+ 0 /*!< All SRAM instances use "Source Biasing" as low power mode technic (it is recommended to set LDO_MEM as high \
+ as possible -- 1.1V typical -- during low power mode) */
+#define LOWPOWER_CFG_MEMLOWPOWERMODE_VOLTAGESCALING \
+ 1 /*!< All SRAM instances use "Voltage Scaling" as low power mode technic (it is recommended to set LDO_MEM as low \
+ as possible -- down to 0.7V -- during low power mode) */
+
+/* CPU Retention Control*/
+#define LOWPOWER_CPURETCTRL_ENA_INDEX 0
+#define LOWPOWER_CPURETCTRL_ENA_MASK (0x1UL << LOWPOWER_CPURETCTRL_ENA_INDEX)
+#define LOWPOWER_CPURETCTRL_MEMBASE_INDEX 1
+#define LOWPOWER_CPURETCTRL_MEMBASE_MASK (0x1FFFUL << LOWPOWER_CPURETCTRL_MEMBASE_INDEX)
+#define LOWPOWER_CPURETCTRL_RETDATALENGTH_INDEX 14
+#define LOWPOWER_CPURETCTRL_RETDATALENGTH_MASK (0x3FFUL << LOWPOWER_CPURETCTRL_RETDATALENGTH_INDEX)
+
+/* Voltgae setting*/
+#define DCDC_POWER_PROFILE_LOW_MAX_FREQ_HZ \
+ (72000000U) /* Maximum System Frequency allowed with DCDC Power Profile LOW */
+#define DCDC_POWER_PROFILE_MEDIUM_MAX_FREQ_HZ \
+ (100000000U) /* Maximum System Frequency allowed with DCDC Power Profile MEDIUM */
+#define DCDC_POWER_PROFILE_HIGH_MAX_FREQ_HZ \
+ (150000000U) /* Maximum System Frequency allowed with DCDC Power Profile HIGH */
+#define PROCESS_NNN_AVG_HZ (19300000U) /* Average Ring OScillator value for Nominal (NNN) Manufacturing Process */
+#define PROCESS_NNN_STD_HZ \
+ (400000U) /* Standard Deviation Ring OScillator value for Nominal (NNN) Manufacturing Process */
+#define PROCESS_NNN_LIMITS \
+ (6U) /* Nominal (NNN) Manufacturing Process Ring Oscillator values limit (with respect to the Average value) */
+#define PROCESS_NNN_MIN_HZ \
+ (PROCESS_NNN_AVG_HZ - \
+ (PROCESS_NNN_LIMITS * \
+ PROCESS_NNN_STD_HZ)) /* Minimum Ring OScillator value for Nominal (NNN) Manufacturing Process */
+#define PROCESS_NNN_MAX_HZ \
+ (PROCESS_NNN_AVG_HZ + \
+ (PROCESS_NNN_LIMITS * \
+ PROCESS_NNN_STD_HZ)) /* Maximum Ring OScillator value for Nominal (NNN) Manufacturing Process */
+#define VOLTAGE_SSS_LOW_MV (1100U) /* Voltage Settings for : Process=SSS, DCDC Power Profile=LOW */
+#define VOLTAGE_SSS_MED_MV (1150U) /* Voltage Settings for : Process=SSS, DCDC Power Profile=MEDIUM */
+#define VOLTAGE_SSS_HIG_MV (1200U) /* Voltage Settings for : Process=SSS, DCDC Power Profile=HIGH */
+#define VOLTAGE_NNN_LOW_MV (1050U) /* Voltage Settings for : Process=NNN, DCDC Power Profile=LOW */
+#define VOLTAGE_NNN_MED_MV (1075U) /* Voltage Settings for : Process=NNN, DCDC Power Profile=MEDIUM */
+#define VOLTAGE_NNN_HIG_MV (1150U) /* Voltage Settings for : Process=NNN, DCDC Power Profile=HIGH */
+#define VOLTAGE_FFF_LOW_MV (1000U) /* Voltage Settings for : Process=FFF, DCDC Power Profile=LOW */
+#define VOLTAGE_FFF_MED_MV (1025U) /* Voltage Settings for : Process=FFF, DCDC Power Profile=MEDIUM */
+#define VOLTAGE_FFF_HIG_MV (1050U) /* Voltage Settings for : Process=FFF, DCDC Power Profile=HIGH */
+
+/**
+ * @brief LDO Voltage control in Low Power Modes
+ */
+#define LOWPOWER_VOLTAGE_LDO_PMU_INDEX 0
+#define LOWPOWER_VOLTAGE_LDO_PMU_MASK (0x1FULL << LOWPOWER_VOLTAGE_LDO_PMU_INDEX)
+#define LOWPOWER_VOLTAGE_LDO_MEM_INDEX 5
+#define LOWPOWER_VOLTAGE_LDO_MEM_MASK (0x1FULL << LOWPOWER_VOLTAGE_LDO_MEM_INDEX)
+#define LOWPOWER_VOLTAGE_LDO_DEEP_SLEEP_INDEX 10
+#define LOWPOWER_VOLTAGE_LDO_DEEP_SLEEP_MASK (0x7ULL << LOWPOWER_VOLTAGE_LDO_DEEP_SLEEP_INDEX)
+#define LOWPOWER_VOLTAGE_LDO_PMU_BOOST_INDEX 19
+#define LOWPOWER_VOLTAGE_LDO_PMU_BOOST_MASK (0x1FULL << LOWPOWER_VOLTAGE_LDO_PMU_BOOST_INDEX)
+#define LOWPOWER_VOLTAGE_LDO_MEM_BOOST_INDEX 24
+#define LOWPOWER_VOLTAGE_LDO_MEM_BOOST_MASK (0x1FULL << LOWPOWER_VOLTAGE_LDO_MEM_BOOST_INDEX)
+#define LOWPOWER_VOLTAGE_DCDC_INDEX 29
+#define LOWPOWER_VOLTAGE_DCDC_MASK (0xFULL << LOWPOWER_VOLTAGE_DCDC_INDEX)
+
+/*! @brief set and clear bit MACRO's. */
+#define U32_SET_BITS(P, B) ((*(uint32_t *)P) |= (B))
+#define U32_CLR_BITS(P, B) ((*(uint32_t *)P) &= ~(B))
+/* Return values from Config (N-2) page of flash */
+#define GET_16MXO_TRIM() (*(uint32_t *)(FLASH_NMPA_BASE + 0xC8U)) // (0x3FCC8)
+#define GET_32KXO_TRIM() (*(uint32_t *)(FLASH_NMPA_BASE + 0xCCU)) // (0x3FCCC)
+
+#define CPU_RETENTION_RAMX_STORAGE_START_ADDR (0x04002000)
+
+#define XO_SLAVE_EN (1)
+/*******************************************************************************
+ * Codes
+ ******************************************************************************/
+
+/*******************************************************************************
+ * LOCAL FUNCTIONS PROTOTYPES
+ ******************************************************************************/
+static void lf_get_deepsleep_core_supply_cfg(uint32_t exclude_from_pd, uint32_t *dcdc_voltage);
+static uint32_t lf_set_ldo_ao_ldo_mem_voltage(uint32_t p_lp_mode, uint32_t p_dcdc_voltage);
+static uint32_t lf_wakeup_io_ctrl(uint32_t p_wakeup_io_ctrl);
+static uint8_t CLOCK_u8OscCapConvert(uint8_t u8OscCap, uint8_t u8CapBankDiscontinuity);
+
+static void lowpower_set_dcdc_power_profile(lowpower_dcdc_power_profile_enum dcdc_power_profile);
+static lowpower_process_corner_enum lowpower_get_part_process_corner(void);
+static void lowpower_set_voltage_for_process(lowpower_dcdc_power_profile_enum dcdc_power_profile);
+static lowpower_driver_interface_t *s_lowpowerDriver = (lowpower_driver_interface_t *)(0x130050e4);
+
+/**
+ * @brief Configures and enters in low power mode
+ * @param p_lowpower_cfg: pointer to a structure that contains all low power mode parameters
+ * @return Nothing
+ *
+ * !!! IMPORTANT NOTES :
+ * 1 - CPU Interrupt Enable registers are updated with p_lowpower_cfg->WAKEUPINT. They are NOT restored by the
+ * API.
+ * 2 - The Non Maskable Interrupt (NMI) should be disable before calling this API (otherwise, there is a risk
+ * of Dead Lock).
+ * 3 - The HARD FAULT handler should execute from SRAM. (The Hard fault handler should initiate a full chip
+ * reset)
+ */
+static void POWER_EnterLowPower(LPC_LOWPOWER_T *p_lowpower_cfg);
+
+/**
+ * @brief
+ * @param
+ * @return
+ */
+static void lf_set_dcdc_power_profile_low(void)
+{
+#define DCDC_POWER_PROFILE_LOW_0_ADDRS (FLASH_NMPA_BASE + 0xE0U) // N4M (0x3FCE0U) / N4S (0x9FCE0U)
+#define DCDC_POWER_PROFILE_LOW_1_ADDRS (FLASH_NMPA_BASE + 0xE4U) // N4M (0x3FCE4U) / N4S (0x9FCE4U)
+
+ uint32_t dcdcTrimValue0 = (*((volatile unsigned int *)(DCDC_POWER_PROFILE_LOW_0_ADDRS)));
+ uint32_t dcdcTrimValue1 = (*((volatile unsigned int *)(DCDC_POWER_PROFILE_LOW_1_ADDRS)));
+
+ if (0UL != (dcdcTrimValue0 & 0x1UL))
+ {
+ PMC->DCDC0 = dcdcTrimValue0 >> 1;
+ PMC->DCDC1 = dcdcTrimValue1;
+ }
+}
+
+/**
+ * @brief Configures and enters in low power mode
+ * @param : p_lowpower_cfg
+ * @return Nothing
+ */
+static void POWER_EnterLowPower(LPC_LOWPOWER_T *p_lowpower_cfg)
+{
+ /* PMC clk set to 12 MHZ */
+ p_lowpower_cfg->CFG |= (uint32_t)LOWPOWER_CFG_SELCLOCK_12MHZ << LOWPOWER_CFG_SELCLOCK_INDEX;
+
+ /* Enable Analog References fast wake-up in case of wake-up from a low power mode (DEEP SLEEP, POWER DOWN and DEEP
+ * POWER DOWN) and Hardware Pin reset */
+ PMC->REFFASTWKUP = (PMC->REFFASTWKUP & (~PMC_REFFASTWKUP_LPWKUP_MASK) & (~PMC_REFFASTWKUP_HWWKUP_MASK)) |
+ PMC_REFFASTWKUP_LPWKUP(1) | PMC_REFFASTWKUP_HWWKUP(1);
+
+ /* SRAM uses Voltage Scaling in all Low Power modes */
+ PMC->SRAMCTRL = (PMC->SRAMCTRL & (~PMC_SRAMCTRL_SMB_MASK)) | PMC_SRAMCTRL_SMB(3);
+
+ /* CPU Retention configuration : preserve the value of FUNCRETENTIONCTRL.RET_LENTH which is a Hardware defined
+ * parameter. */
+ p_lowpower_cfg->CPURETCTRL = (SYSCON->FUNCRETENTIONCTRL & SYSCON_FUNCRETENTIONCTRL_RET_LENTH_MASK) |
+ (p_lowpower_cfg->CPURETCTRL & (~SYSCON_FUNCRETENTIONCTRL_RET_LENTH_MASK));
+
+ /* Switch System Clock to FRO12Mhz (the configuration before calling this function will not be restored back) */
+ CLOCK_AttachClk(kFRO12M_to_MAIN_CLK); /* Switch main clock to FRO12MHz */
+ CLOCK_SetClkDiv(kCLOCK_DivAhbClk, 1U, false); /* Main clock divided by 1 */
+ SYSCON->FMCCR = (SYSCON->FMCCR & 0xFFFF0000UL) | 0x201AUL; /* Adjust FMC waiting time cycles */
+ lf_set_dcdc_power_profile_low(); /* Align DCDC Power profile with the 12 MHz clock (DCDC Power Profile LOW) */
+
+ (*(s_lowpowerDriver->set_lowpower_mode))(p_lowpower_cfg);
+
+ /* Restore the configuration of the MISCCTRL Register : LOWPWR_FLASH_BUF = 0, LDOMEMBLEEDDSLP = 0, LDOMEMHIGHZMODE =
+ * 0 */
+ PMC->MISCCTRL &= (~PMC_MISCCTRL_LOWPWR_FLASH_BUF_MASK) & (~PMC_MISCCTRL_DISABLE_BLEED_MASK) &
+ (~PMC_MISCCTRL_LDOMEMHIGHZMODE_MASK);
+}
+
+/**
+ * @brief Shut off the Flash and execute the _WFI(), then power up the Flash after wake-up event
+ * @param None
+ * @return Nothing
+ */
+void POWER_CycleCpuAndFlash(void)
+{
+ (*(s_lowpowerDriver->power_cycle_cpu_and_flash))();
+};
+
+/**
+ * brief PMC Deep Sleep function call
+ * return nothing
+ */
+void POWER_EnterDeepSleep(uint32_t exclude_from_pd,
+ uint32_t sram_retention_ctrl,
+ uint64_t wakeup_interrupts,
+ uint32_t hardware_wake_ctrl)
+{
+ LPC_LOWPOWER_T lv_low_power_mode_cfg; /* Low Power Mode configuration structure */
+ uint32_t cpu0_nmi_enable;
+ uint32_t cpu0_int_enable_0;
+ uint32_t cpu0_int_enable_1;
+ uint32_t dcdc_voltage;
+ uint32_t pmc_reset_ctrl;
+ /* Clear Low Power Mode configuration variable */
+ (void)memset(&lv_low_power_mode_cfg, 0x0, sizeof(LPC_LOWPOWER_T));
+
+ /* Configure Low Power Mode configuration variable */
+ lv_low_power_mode_cfg.CFG |= (uint32_t)LOWPOWER_CFG_LPMODE_DEEPSLEEP
+ << LOWPOWER_CFG_LPMODE_INDEX; /* DEEPSLEEP mode */
+
+ lf_get_deepsleep_core_supply_cfg(exclude_from_pd, &dcdc_voltage);
+
+ if (((exclude_from_pd & (uint32_t)kPDRUNCFG_PD_USB1_PHY) != 0UL) &&
+ ((exclude_from_pd & (uint32_t)kPDRUNCFG_PD_LDOUSBHS) != 0UL))
+ {
+ /* USB High Speed is required as wake-up source in Deep Sleep mode: make sure LDO FLASH NV stays powered during
+ * deep-sleep */
+ exclude_from_pd = exclude_from_pd | (uint32_t)kPDRUNCFG_PD_LDOFLASHNV;
+ }
+
+ /* DCDC will be always used during Deep Sleep (instead of LDO Deep Sleep); Make sure LDO MEM & Analog references
+ * will stay powered, Shut down ROM */
+ lv_low_power_mode_cfg.PDCTRL0 = (~exclude_from_pd & ~(uint32_t)kPDRUNCFG_PD_DCDC & ~(uint32_t)kPDRUNCFG_PD_LDOMEM &
+ ~(uint32_t)kPDRUNCFG_PD_BIAS) |
+ (uint32_t)kPDRUNCFG_PD_LDODEEPSLEEP | (uint32_t)kPDRUNCFG_PD_ROM;
+
+ /* Voltage control in DeepSleep Low Power Modes */
+ /* The Memories Voltage settings below are for voltage scaling */
+ lv_low_power_mode_cfg.VOLTAGE = lf_set_ldo_ao_ldo_mem_voltage(LOWPOWER_CFG_LPMODE_POWERDOWN, dcdc_voltage);
+
+ /* SRAM retention control during POWERDOWN */
+ lv_low_power_mode_cfg.SRAMRETCTRL = sram_retention_ctrl;
+
+ /* CPU Wake up & Interrupt sources control */
+ lv_low_power_mode_cfg.WAKEUPINT = wakeup_interrupts;
+ lv_low_power_mode_cfg.WAKEUPSRC = wakeup_interrupts;
+
+ /* Interrupts that allow DMA transfers with Flexcomm without waking up the Processor */
+ if (0UL != (hardware_wake_ctrl & (LOWPOWER_HWWAKE_PERIPHERALS | LOWPOWER_HWWAKE_SDMA0 | LOWPOWER_HWWAKE_SDMA1)))
+ {
+ lv_low_power_mode_cfg.HWWAKE = (hardware_wake_ctrl & ~LOWPOWER_HWWAKE_FORCED) | LOWPOWER_HWWAKE_ENABLE_FRO192M;
+ }
+
+ cpu0_nmi_enable = SYSCON->NMISRC & SYSCON_NMISRC_NMIENCPU0_MASK; /* Save the configuration of the NMI Register */
+ SYSCON->NMISRC &= ~SYSCON_NMISRC_NMIENCPU0_MASK; /* Disable NMI of CPU0 */
+
+ /* Save the configuration of the CPU interrupt enable Registers (because they are overwritten inside the low power
+ * API */
+ cpu0_int_enable_0 = NVIC->ISER[0];
+ cpu0_int_enable_1 = NVIC->ISER[1];
+
+ pmc_reset_ctrl = PMC->RESETCTRL;
+
+ if ((pmc_reset_ctrl & (PMC_RESETCTRL_BODCORERESETENA_SECURE_MASK | PMC_RESETCTRL_BODCORERESETENA_SECURE_DP_MASK)) ==
+ ((0x1UL << PMC_RESETCTRL_BODCORERESETENA_SECURE_SHIFT) |
+ (0x1UL << PMC_RESETCTRL_BODCORERESETENA_SECURE_DP_SHIFT)))
+ {
+ /* BoD CORE reset is activated, so make sure BoD Core and Biasing won't be shutdown */
+ lv_low_power_mode_cfg.PDCTRL0 &= ~(uint32_t)kPDRUNCFG_PD_BODCORE & ~(uint32_t)kPDRUNCFG_PD_BIAS;
+ }
+ if ((pmc_reset_ctrl & (PMC_RESETCTRL_BODVBATRESETENA_SECURE_MASK | PMC_RESETCTRL_BODVBATRESETENA_SECURE_DP_MASK)) ==
+ ((0x1UL << PMC_RESETCTRL_BODVBATRESETENA_SECURE_SHIFT) |
+ (0x1UL << PMC_RESETCTRL_BODVBATRESETENA_SECURE_DP_SHIFT)))
+ {
+ /* BoD VBAT reset is activated, so make sure BoD VBAT and Biasing won't be shutdown */
+ lv_low_power_mode_cfg.PDCTRL0 &= ~(uint32_t)kPDRUNCFG_PD_BODVBAT & ~(uint32_t)kPDRUNCFG_PD_BIAS;
+ }
+
+ /* Enter low power mode */
+ POWER_EnterLowPower(&lv_low_power_mode_cfg);
+
+ /* Restore the configuration of the NMI Register */
+ SYSCON->NMISRC |= cpu0_nmi_enable;
+
+ /* Restore the configuration of the CPU interrupt enable Registers (because they have been overwritten inside the
+ * low power API */
+ NVIC->ISER[0] = cpu0_int_enable_0;
+ NVIC->ISER[1] = cpu0_int_enable_1;
+}
+
+/**
+ * brief PMC power Down function call
+ * return nothing
+ */
+void POWER_EnterPowerDown(uint32_t exclude_from_pd,
+ uint32_t sram_retention_ctrl,
+ uint64_t wakeup_interrupts,
+ uint32_t cpu_retention_ctrl)
+{
+ LPC_LOWPOWER_T lv_low_power_mode_cfg; /* Low Power Mode configuration structure */
+ uint32_t cpu0_nmi_enable;
+ uint32_t cpu0_int_enable_0;
+ uint32_t cpu0_int_enable_1;
+ uint64_t wakeup_src_int;
+ uint32_t pmc_reset_ctrl;
+ uint32_t rng_entropy_save[6];
+
+ uint32_t analog_ctrl_regs[12]; /* To store Analog Controller Regristers */
+
+ /* Clear Low Power Mode configuration variable */
+ (void)memset(&lv_low_power_mode_cfg, 0x0, sizeof(LPC_LOWPOWER_T));
+
+ /* Configure Low Power Mode configuration variable */
+ lv_low_power_mode_cfg.CFG |= (uint32_t)LOWPOWER_CFG_LPMODE_POWERDOWN
+ << LOWPOWER_CFG_LPMODE_INDEX; /* POWER DOWN mode */
+
+ /* Only FRO32K, XTAL32K, COMP, BIAS and LDO_MEM can be stay powered during POWERDOWN (valid from application point
+ * of view; Hardware allows BODVBAT, LDODEEPSLEEP and FRO1M to stay powered, that's why they are excluded below) */
+ lv_low_power_mode_cfg.PDCTRL0 = (~exclude_from_pd) | (uint32_t)kPDRUNCFG_PD_BODVBAT | (uint32_t)kPDRUNCFG_PD_FRO1M |
+ (uint32_t)kPDRUNCFG_PD_LDODEEPSLEEP;
+
+ /* @TODO Guillaume: add save/restore entropy during PowerDown */
+ /* Entropy for RNG need to saved */
+ if ((exclude_from_pd & (uint32_t)kPDRUNCFG_PD_RNG) != 0UL)
+ {
+ CLOCK_EnableClock(kCLOCK_Rng);
+ RESET_ClearPeripheralReset(kRNG_RST_SHIFT_RSTn);
+ for (int i = 0; i < 6; i++)
+ {
+ rng_entropy_save[i] = RNG->RANDOM_NUMBER;
+ }
+ }
+
+ /* CPU0 retention Ctrl.
+ * For the time being, we do not allow customer to relocate the CPU retention area in SRAMX, meaning that the
+ * retention area range is [0x0400_6000 - 0x0400_6600] (beginning of RAMX2 for N4S) If required by customer,
+ * retention area range is [0x0400_2000 - 0x0400_2600] (beginning of RAMX2 for N4M) If required by customer,
+ * cpu_retention_ctrl[13:1] will be used for that to modify the default retention area
+ */
+ lv_low_power_mode_cfg.CPURETCTRL =
+ (cpu_retention_ctrl & LOWPOWER_CPURETCTRL_ENA_MASK) |
+ ((((uint32_t)CPU_RETENTION_RAMX_STORAGE_START_ADDR >> 2UL) << LOWPOWER_CPURETCTRL_MEMBASE_INDEX) &
+ LOWPOWER_CPURETCTRL_MEMBASE_MASK);
+ if (0UL != (cpu_retention_ctrl & 0x1UL))
+ {
+ /* Add RAMX2 for retention */
+ sram_retention_ctrl |= LOWPOWER_SRAMRETCTRL_RETEN_RAMX2;
+ /* CPU retention is required: store Analog Controller Registers */
+ analog_ctrl_regs[0] = ANACTRL->FRO192M_CTRL;
+ analog_ctrl_regs[1] = ANACTRL->ANALOG_CTRL_CFG;
+ analog_ctrl_regs[2] = ANACTRL->ADC_CTRL;
+ analog_ctrl_regs[3] = ANACTRL->XO32M_CTRL;
+ analog_ctrl_regs[4] = ANACTRL->BOD_DCDC_INT_CTRL;
+ analog_ctrl_regs[5] = ANACTRL->RINGO0_CTRL;
+ analog_ctrl_regs[6] = ANACTRL->RINGO1_CTRL;
+ analog_ctrl_regs[7] = ANACTRL->RINGO2_CTRL;
+ analog_ctrl_regs[8] = ANACTRL->LDO_XO32M;
+ analog_ctrl_regs[9] = ANACTRL->AUX_BIAS;
+ analog_ctrl_regs[10] = ANACTRL->USBHS_PHY_CTRL;
+ analog_ctrl_regs[11] = ANACTRL->USBHS_PHY_TRIM;
+ }
+
+ /* SRAM retention control during POWERDOWN */
+ lv_low_power_mode_cfg.SRAMRETCTRL = sram_retention_ctrl;
+
+ /* Sanity check: If retention is required for any of SRAM instances, make sure LDO MEM will stay powered */
+ if ((sram_retention_ctrl & 0x7FFFUL) != 0UL)
+ {
+ lv_low_power_mode_cfg.PDCTRL0 &= ~(uint32_t)kPDRUNCFG_PD_LDOMEM;
+ }
+
+ /* Voltage control in Low Power Modes */
+ /* The Memories Voltage settings below are for voltage scaling */
+ lv_low_power_mode_cfg.VOLTAGE = lf_set_ldo_ao_ldo_mem_voltage(LOWPOWER_CFG_LPMODE_POWERDOWN, 0);
+
+ /* CPU Wake up & Interrupt sources control : only WAKEUP_GPIO_GLOBALINT0, WAKEUP_GPIO_GLOBALINT1, WAKEUP_FLEXCOMM3,
+ * WAKEUP_ACMP_CAPT, WAKEUP_RTC_LITE_ALARM_WAKEUP, WAKEUP_OS_EVENT_TIMER, WAKEUP_ALLWAKEUPIOS */
+ wakeup_src_int = (uint64_t)(WAKEUP_GPIO_GLOBALINT0 | WAKEUP_GPIO_GLOBALINT1 | WAKEUP_FLEXCOMM3 | WAKEUP_ACMP |
+ WAKEUP_RTC_LITE_ALARM_WAKEUP | WAKEUP_OS_EVENT_TIMER | WAKEUP_ALLWAKEUPIOS);
+ lv_low_power_mode_cfg.WAKEUPINT = wakeup_interrupts & wakeup_src_int;
+ lv_low_power_mode_cfg.WAKEUPSRC = wakeup_interrupts & wakeup_src_int;
+
+ cpu0_nmi_enable = SYSCON->NMISRC & SYSCON_NMISRC_NMIENCPU0_MASK; /* Save the configuration of the NMI Register */
+ SYSCON->NMISRC &= ~SYSCON_NMISRC_NMIENCPU0_MASK; /* Disable NMI of CPU0 */
+
+ /* Save the configuration of the CPU interrupt enable Registers (because they are overwritten inside the low power
+ * API */
+ cpu0_int_enable_0 = NVIC->ISER[0];
+ cpu0_int_enable_1 = NVIC->ISER[1];
+
+ /* Disable BoD VBAT and BoD Core resets */
+ /* BOD VBAT disable reset */
+ pmc_reset_ctrl =
+ PMC->RESETCTRL & (~(PMC_RESETCTRL_BODVBATRESETENA_SECURE_MASK | PMC_RESETCTRL_BODVBATRESETENA_SECURE_DP_MASK));
+ pmc_reset_ctrl |= (0x2UL << PMC_RESETCTRL_BODVBATRESETENA_SECURE_SHIFT) |
+ (0x2UL << PMC_RESETCTRL_BODVBATRESETENA_SECURE_DP_SHIFT);
+
+ /* BOD CORE disable reset */
+ pmc_reset_ctrl &= (~(PMC_RESETCTRL_BODCORERESETENA_SECURE_MASK | PMC_RESETCTRL_BODCORERESETENA_SECURE_DP_MASK));
+ pmc_reset_ctrl |= (0x2UL << PMC_RESETCTRL_BODCORERESETENA_SECURE_SHIFT) |
+ (0x2UL << PMC_RESETCTRL_BODCORERESETENA_SECURE_DP_SHIFT);
+
+ PMC->RESETCTRL = pmc_reset_ctrl;
+
+ /* Enter low power mode */
+ POWER_EnterLowPower(&lv_low_power_mode_cfg);
+
+ /*** We'll reach this point in case of POWERDOWN with CPU retention or if the POWERDOWN has not been taken (for
+ instance because an interrupt is pending). In case of CPU retention, assumption is that the SRAM containing the
+ stack used to call this function shall be preserved during low power ***/
+
+#if defined(PUF_SRAM_CTRL_CFG_ENABLE_MASK)
+ /* Following code is to reset PUF to remove over consumption */
+ /* Enable PUF register clock to access register */
+ SYSCON->AHBCLKCTRLSET[2] = SYSCON_AHBCLKCTRL2_PUF_MASK;
+ /* Release PUF reset */
+ SYSCON->PRESETCTRLCLR[2] = SYSCON_PRESETCTRL2_PUF_RST_MASK;
+ /* Enable PUF SRAM */
+ PUF_SRAM_CTRL->CFG |= PUF_SRAM_CTRL_CFG_ENABLE_MASK | PUF_SRAM_CTRL_CFG_CKGATING_MASK;
+
+ /* Disable PUF register clock. */
+ // Delaying the line of code below until the PUF State Machine execution is completed:
+ // Shuting down the clock to early will prevent the state machine from reaching the end.
+ // => Wait for status bit in PUF Controller Registers before stop PUF clock.
+ while (0UL == (PUF_SRAM_CTRL->INT_STATUS & PUF_SRAM_CTRL_INT_STATUS_READY_MASK))
+ {
+ }
+
+ SYSCON->AHBCLKCTRLCLR[2] = SYSCON_AHBCLKCTRL2_PUF_MASK;
+#endif
+ /* Restore the configuration of the NMI Register */
+ SYSCON->NMISRC |= cpu0_nmi_enable;
+
+ /* Restore PMC RESETCTRL register */
+ PMC->RESETCTRL = pmc_reset_ctrl;
+
+ /* Restore the configuration of the CPU interrupt enable Registers (because they have been overwritten inside the
+ * low power API */
+ NVIC->ISER[0] = cpu0_int_enable_0;
+ NVIC->ISER[1] = cpu0_int_enable_1;
+
+ if ((cpu_retention_ctrl & 0x1UL) != 0UL)
+ {
+ /* Restore Analog Controller Registers */
+ ANACTRL->FRO192M_CTRL = analog_ctrl_regs[0] | ANACTRL_FRO192M_CTRL_WRTRIM_MASK;
+ ANACTRL->ANALOG_CTRL_CFG = analog_ctrl_regs[1];
+ ANACTRL->ADC_CTRL = analog_ctrl_regs[2];
+ ANACTRL->XO32M_CTRL = analog_ctrl_regs[3];
+ ANACTRL->BOD_DCDC_INT_CTRL = analog_ctrl_regs[4];
+ ANACTRL->RINGO0_CTRL = analog_ctrl_regs[5];
+ ANACTRL->RINGO1_CTRL = analog_ctrl_regs[6];
+ ANACTRL->RINGO2_CTRL = analog_ctrl_regs[7];
+ ANACTRL->LDO_XO32M = analog_ctrl_regs[8];
+ ANACTRL->AUX_BIAS = analog_ctrl_regs[9];
+ ANACTRL->USBHS_PHY_CTRL = analog_ctrl_regs[10];
+ ANACTRL->USBHS_PHY_TRIM = analog_ctrl_regs[11];
+ }
+
+ /* @TODO Guillaume: add save/restore entropy during PowerDown */
+ /* Restore Entropy for RNG */
+ if ((exclude_from_pd & (uint32_t)kPDRUNCFG_PD_RNG) != 0UL)
+ {
+ RNG->POWERDOWN &= ~RNG_POWERDOWN_POWERDOWN_MASK;
+ for (int i = 0; i < 6; i++)
+ {
+ RNG->ENTROPY_INJECT = rng_entropy_save[i];
+ }
+ }
+}
+
+/**
+ * brief PMC Deep Sleep Power Down function call
+ * return nothing
+ */
+void POWER_EnterDeepPowerDown(uint32_t exclude_from_pd,
+ uint32_t sram_retention_ctrl,
+ uint64_t wakeup_interrupts,
+ uint32_t wakeup_io_ctrl)
+{
+ LPC_LOWPOWER_T lv_low_power_mode_cfg; /* Low Power Mode configuration structure */
+ uint32_t cpu0_nmi_enable;
+ uint32_t cpu0_int_enable_0;
+ uint32_t cpu0_int_enable_1;
+ uint32_t pmc_reset_ctrl;
+
+ /* Clear Low Power Mode configuration variable */
+ (void)memset(&lv_low_power_mode_cfg, 0x0, sizeof(LPC_LOWPOWER_T));
+
+ /* Configure Low Power Mode configuration variable */
+ lv_low_power_mode_cfg.CFG |= (uint32_t)LOWPOWER_CFG_LPMODE_DEEPPOWERDOWN
+ << LOWPOWER_CFG_LPMODE_INDEX; /* DEEP POWER DOWN mode */
+
+ /* Only FRO32K, XTAL32K and LDO_MEM can be stay powered during DEEPPOWERDOWN (valid from application point of view;
+ * Hardware allows BODVBAT, BIAS FRO1M and COMP to stay powered, that's why they are excluded below) */
+ lv_low_power_mode_cfg.PDCTRL0 = (~exclude_from_pd) | (uint32_t)kPDRUNCFG_PD_BIAS | (uint32_t)kPDRUNCFG_PD_BODVBAT |
+ (uint32_t)kPDRUNCFG_PD_FRO1M | (uint32_t)kPDRUNCFG_PD_COMP;
+
+ /* SRAM retention control during DEEPPOWERDOWN */
+ /* RAM00 used by ROM code to restart. */
+ sram_retention_ctrl = sram_retention_ctrl & (~(LOWPOWER_SRAMRETCTRL_RETEN_RAM00));
+
+ /* SRAM retention control during DEEPPOWERDOWN */
+ lv_low_power_mode_cfg.SRAMRETCTRL = sram_retention_ctrl;
+
+ /* Sanity check: If retention is required for any of SRAM instances, make sure LDO MEM will stay powered */
+ if ((sram_retention_ctrl & 0x7FFFUL) != 0UL)
+ {
+ lv_low_power_mode_cfg.PDCTRL0 &= ~(uint32_t)kPDRUNCFG_PD_LDOMEM;
+ }
+
+ /* Voltage control in Low Power Modes */
+ /* The Memories Voltage settings below are for voltage scaling */
+ lv_low_power_mode_cfg.VOLTAGE = lf_set_ldo_ao_ldo_mem_voltage(LOWPOWER_CFG_LPMODE_DEEPPOWERDOWN, 0);
+
+ lv_low_power_mode_cfg.WAKEUPINT =
+ wakeup_interrupts & (WAKEUP_RTC_LITE_ALARM_WAKEUP |
+ WAKEUP_OS_EVENT_TIMER); /* CPU Wake up sources control : only WAKEUP_RTC_LITE_ALARM_WAKEUP,
+ WAKEUP_OS_EVENT_TIMER */
+ lv_low_power_mode_cfg.WAKEUPSRC =
+ wakeup_interrupts &
+ (WAKEUP_RTC_LITE_ALARM_WAKEUP | WAKEUP_OS_EVENT_TIMER |
+ WAKEUP_ALLWAKEUPIOS); /*!< Hardware Wake up sources control: : only WAKEUP_RTC_LITE_ALARM_WAKEUP,
+ WAKEUP_OS_EVENT_TIMER and WAKEUP_ALLWAKEUPIOS */
+
+ /* Wake up I/O sources */
+ lv_low_power_mode_cfg.WAKEUPIOSRC = lf_wakeup_io_ctrl(wakeup_io_ctrl);
+
+ cpu0_nmi_enable = SYSCON->NMISRC & SYSCON_NMISRC_NMIENCPU0_MASK; /* Save the configuration of the NMI Register */
+ SYSCON->NMISRC &= ~SYSCON_NMISRC_NMIENCPU0_MASK; /* Disable NMI of CPU0 */
+
+ /* Save the configuration of the CPU interrupt enable Registers (because they are overwritten inside the low power
+ * API */
+ cpu0_int_enable_0 = NVIC->ISER[0];
+ cpu0_int_enable_1 = NVIC->ISER[1];
+
+ /* Save the configuration of the PMC RESETCTRL register */
+ /* BOD VBAT disable reset */
+ pmc_reset_ctrl =
+ PMC->RESETCTRL & (~(PMC_RESETCTRL_BODVBATRESETENA_SECURE_MASK | PMC_RESETCTRL_BODVBATRESETENA_SECURE_DP_MASK));
+ pmc_reset_ctrl |= (0x2UL << PMC_RESETCTRL_BODVBATRESETENA_SECURE_SHIFT) |
+ (0x2UL << PMC_RESETCTRL_BODVBATRESETENA_SECURE_DP_SHIFT);
+
+ /* BOD CORE disable reset */
+ pmc_reset_ctrl &= (~(PMC_RESETCTRL_BODCORERESETENA_SECURE_MASK | PMC_RESETCTRL_BODCORERESETENA_SECURE_DP_MASK));
+ pmc_reset_ctrl |= (0x2UL << PMC_RESETCTRL_BODCORERESETENA_SECURE_SHIFT) |
+ (0x2UL << PMC_RESETCTRL_BODCORERESETENA_SECURE_DP_SHIFT);
+
+ PMC->RESETCTRL = pmc_reset_ctrl;
+
+ /* Enter low power mode */
+ POWER_EnterLowPower(&lv_low_power_mode_cfg);
+
+ /*** We'll reach this point ONLY and ONLY if the DEEPPOWERDOWN has not been taken (for instance because an RTC or
+ * OSTIMER interrupt is pending) ***/
+
+ /* Restore the configuration of the NMI Register */
+ SYSCON->NMISRC |= cpu0_nmi_enable;
+
+ /* Restore PMC RESETCTRL register */
+ PMC->RESETCTRL = pmc_reset_ctrl;
+
+ /* Restore the configuration of the CPU interrupt enable Registers (because they have been overwritten inside the
+ * low power API */
+ NVIC->ISER[0] = cpu0_int_enable_0;
+ NVIC->ISER[1] = cpu0_int_enable_1;
+}
+
+/**
+ * brief PMC Sleep function call
+ * return nothing
+ */
+void POWER_EnterSleep(void)
+{
+ uint32_t pmsk;
+ pmsk = __get_PRIMASK();
+ __disable_irq();
+ SCB->SCR &= ~SCB_SCR_SLEEPDEEP_Msk;
+ __WFI();
+ __set_PRIMASK(pmsk);
+}
+
+/**
+ * @brief Get Digital Core logic supply source to be used during Deep Sleep.
+ * @param [in] exclude_from_pd: COmpoenents NOT to be powered down during Deep Sleep
+ * @param [out] core_supply: 0 = LDO DEEPSLEEP will be used / 1 = DCDC will be used
+ * @param [out] dcdc_voltage: as defined by V_DCDC_* in fsl_power.h
+
+ * @return Nothing
+ */
+static void lf_get_deepsleep_core_supply_cfg(uint32_t exclude_from_pd, uint32_t *dcdc_voltage)
+{
+ *dcdc_voltage = V_DCDC_0P950; /* Default value */
+
+ if (((exclude_from_pd & (uint32_t)kPDRUNCFG_PD_USB1_PHY) != 0) &&
+ ((exclude_from_pd & (uint32_t)kPDRUNCFG_PD_LDOUSBHS) != 0))
+ {
+ /* USB High Speed is required as wake-up source in Deep Sleep mode */
+ PMC->MISCCTRL |= PMC_MISCCTRL_LOWPWR_FLASH_BUF_MASK; /* Force flash buffer in low power mode */
+ *dcdc_voltage = V_DCDC_1P000; /* Set DCDC voltage to be 1.000 V (USB HS IP cannot work below 0.990 V) */
+ }
+}
+
+/**
+ * @brief
+ * @param
+ * @return
+ */
+static uint32_t lf_set_ldo_ao_ldo_mem_voltage(uint32_t p_lp_mode, uint32_t p_dcdc_voltage)
+{
+#define FLASH_NMPA_LDO_AO_ADDRS (FLASH_NMPA_BASE + 0x0F4U) // N4M (0x3FCF4U) / N4S (0x9FCF4U)
+#define FLASH_NMPA_LDO_AO_DSLP_TRIM_VALID_MASK (0x100U)
+#define FLASH_NMPA_LDO_AO_DSLP_TRIM_MASK (0x3E00U)
+#define FLASH_NMPA_LDO_AO_DSLP_TRIM_SHIFT (9U)
+#define FLASH_NMPA_LDO_AO_PDWN_TRIM_VALID_MASK (0x10000U)
+#define FLASH_NMPA_LDO_AO_PDWN_TRIM_MASK (0x3E0000U)
+#define FLASH_NMPA_LDO_AO_PDWN_TRIM_SHIFT (17U)
+#define FLASH_NMPA_LDO_AO_DPDW_TRIM_VALID_MASK (0x1000000U)
+#define FLASH_NMPA_LDO_AO_DPDW_TRIM_MASK (0x3E000000U)
+#define FLASH_NMPA_LDO_AO_DPDW_TRIM_SHIFT (25U)
+
+ uint32_t ldo_ao_trim, voltage;
+ uint32_t lv_v_ldo_pmu, lv_v_ldo_pmu_boost;
+
+ ldo_ao_trim = (*((volatile unsigned int *)(FLASH_NMPA_LDO_AO_ADDRS)));
+
+ switch (p_lp_mode)
+ {
+ case LOWPOWER_CFG_LPMODE_DEEPSLEEP:
+ {
+ if ((ldo_ao_trim & FLASH_NMPA_LDO_AO_DSLP_TRIM_VALID_MASK) != 0UL)
+ {
+ /* Apply settings coming from Flash */
+ lv_v_ldo_pmu = (ldo_ao_trim & FLASH_NMPA_LDO_AO_DSLP_TRIM_MASK) >> FLASH_NMPA_LDO_AO_DSLP_TRIM_SHIFT;
+ lv_v_ldo_pmu_boost = lv_v_ldo_pmu - 2UL; /* - 50 mV */
+ }
+ else
+ {
+ /* Apply default settings */
+ lv_v_ldo_pmu = (uint32_t)V_AO_0P900;
+ lv_v_ldo_pmu_boost = (uint32_t)V_AO_0P850;
+ }
+ }
+ break;
+
+ case LOWPOWER_CFG_LPMODE_POWERDOWN:
+ {
+ if ((ldo_ao_trim & FLASH_NMPA_LDO_AO_PDWN_TRIM_VALID_MASK) != 0UL)
+ {
+ /* Apply settings coming from Flash */
+ lv_v_ldo_pmu = (ldo_ao_trim & FLASH_NMPA_LDO_AO_PDWN_TRIM_MASK) >> FLASH_NMPA_LDO_AO_PDWN_TRIM_SHIFT;
+ lv_v_ldo_pmu_boost = lv_v_ldo_pmu - 2UL; /* - 50 mV */
+ }
+ else
+ {
+ /* Apply default settings */
+ lv_v_ldo_pmu = (uint32_t)V_AO_0P800;
+ lv_v_ldo_pmu_boost = (uint32_t)V_AO_0P750;
+ }
+ }
+ break;
+
+ case LOWPOWER_CFG_LPMODE_DEEPPOWERDOWN:
+ {
+ if ((ldo_ao_trim & FLASH_NMPA_LDO_AO_DPDW_TRIM_VALID_MASK) != 0UL)
+ {
+ /* Apply settings coming from Flash */
+ lv_v_ldo_pmu = (ldo_ao_trim & FLASH_NMPA_LDO_AO_DPDW_TRIM_MASK) >> FLASH_NMPA_LDO_AO_DPDW_TRIM_SHIFT;
+ lv_v_ldo_pmu_boost = lv_v_ldo_pmu - 2UL; /* - 50 mV */
+ }
+ else
+ {
+ /* Apply default settings */
+ lv_v_ldo_pmu = (uint32_t)V_AO_0P800;
+ lv_v_ldo_pmu_boost = (uint32_t)V_AO_0P750;
+ }
+ }
+ break;
+
+ default:
+ /* Should never reach this point */
+ lv_v_ldo_pmu = (uint32_t)V_AO_1P100;
+ lv_v_ldo_pmu_boost = (uint32_t)V_AO_1P050;
+ break;
+ }
+
+ /* The Memories Voltage settings below are for voltage scaling */
+ voltage =
+ (lv_v_ldo_pmu << LOWPOWER_VOLTAGE_LDO_PMU_INDEX) | /* */
+ (lv_v_ldo_pmu_boost << LOWPOWER_VOLTAGE_LDO_PMU_BOOST_INDEX) | /* */
+ ((uint32_t)V_AO_0P750 << LOWPOWER_VOLTAGE_LDO_MEM_INDEX) | /* Set to 0.75V (voltage Scaling) */
+ ((uint32_t)V_AO_0P700 << LOWPOWER_VOLTAGE_LDO_MEM_BOOST_INDEX) | /* Set to 0.7V (voltage Scaling) */
+ ((uint32_t)V_DEEPSLEEP_0P900
+ << LOWPOWER_VOLTAGE_LDO_DEEP_SLEEP_INDEX) | /* Set to 0.90 V (Not used because LDO_DEEP_SLEEP is disabled)*/
+ (p_dcdc_voltage << LOWPOWER_VOLTAGE_DCDC_INDEX) /* */
+ ;
+
+ return (voltage);
+}
+
+/**
+ * @brief
+ * @param
+ * @return
+ */
+static uint32_t lf_wakeup_io_ctrl(uint32_t p_wakeup_io_ctrl)
+{
+ uint32_t wake_up_type;
+ uint32_t wakeup_io_ctrl_reg;
+ uint8_t use_external_pullupdown = 0;
+
+ /* Configure Pull up & Pull down based on the required wake-up edge */
+ CLOCK_EnableClock(kCLOCK_Iocon);
+
+ wakeup_io_ctrl_reg = 0UL;
+
+ /* Wake-up I/O 0 */
+ wake_up_type = (p_wakeup_io_ctrl & 0x3UL) >> LOWPOWER_WAKEUPIOSRC_PIO0_INDEX;
+ wakeup_io_ctrl_reg |= (wake_up_type << LOWPOWER_WAKEUPIOSRC_PIO0_INDEX);
+ use_external_pullupdown = (uint8_t)((p_wakeup_io_ctrl & LOWPOWER_WAKEUPIO_PIO0_USEEXTERNALPULLUPDOWN_MASK) >>
+ LOWPOWER_WAKEUPIO_PIO0_USEEXTERNALPULLUPDOWN_INDEX);
+
+ if (use_external_pullupdown == 0UL)
+ {
+ if ((wake_up_type == 1UL) || (wake_up_type == 3UL))
+ {
+ /* Rising edge and both rising and falling edges */
+ IOCON->PIO[1][1] = IOCON_PIO_DIGIMODE(1) | IOCON_PIO_MODE(1); /* Pull down */
+ wakeup_io_ctrl_reg |=
+ ((uint32_t)LOWPOWER_WAKEUPIOSRC_IO_MODE_PULLDOWN << LOWPOWER_WAKEUPIOSRC_PIO0MODE_INDEX);
+ }
+ else
+ {
+ if (wake_up_type == 2UL)
+ {
+ /* Falling edge only */
+ IOCON->PIO[1][1] = IOCON_PIO_DIGIMODE(1) | IOCON_PIO_MODE(2); /* Pull up */
+ wakeup_io_ctrl_reg |=
+ ((uint32_t)LOWPOWER_WAKEUPIOSRC_IO_MODE_PULLUP << LOWPOWER_WAKEUPIOSRC_PIO0MODE_INDEX);
+ }
+ else
+ {
+ /* Wake-up I/O is disabled : set it as required by the user */
+ if ((p_wakeup_io_ctrl & LOWPOWER_WAKEUPIO_PIO0_DISABLEPULLUPDOWN_MASK) != 0UL)
+ {
+ /* Wake-up I/O is configured as Plain Input */
+ // @TODO not used p_wakeup_io_ctrl &= ~LOWPOWER_WAKEUPIO_PIO0_PULLUPDOWN_MASK;
+ wakeup_io_ctrl_reg |=
+ ((uint32_t)LOWPOWER_WAKEUPIOSRC_IO_MODE_PLAIN << LOWPOWER_WAKEUPIOSRC_PIO0MODE_INDEX);
+ }
+ else
+ {
+ /* Wake-up I/O is configured as pull-up or pull-down */
+ // @TODO update for mask name
+ if ((p_wakeup_io_ctrl & LOWPOWER_WAKEUPIO_PIO0_PULLUPDOWN_MASK) != 0UL)
+ {
+ /* Wake-up I/O is configured as pull-up */
+ wakeup_io_ctrl_reg |=
+ ((uint32_t)LOWPOWER_WAKEUPIOSRC_IO_MODE_PULLUP << LOWPOWER_WAKEUPIOSRC_PIO0MODE_INDEX);
+ }
+ else
+ {
+ /* Wake-up I/O is configured as pull-down */
+ wakeup_io_ctrl_reg |=
+ ((uint32_t)LOWPOWER_WAKEUPIOSRC_IO_MODE_PULLDOWN << LOWPOWER_WAKEUPIOSRC_PIO0MODE_INDEX);
+ }
+ }
+ }
+ }
+ }
+ else
+ {
+ wakeup_io_ctrl_reg |= ((uint32_t)LOWPOWER_WAKEUPIOSRC_IO_MODE_PLAIN << LOWPOWER_WAKEUPIOSRC_PIO0MODE_INDEX);
+ }
+
+ /* Wake-up I/O 1 */
+ wake_up_type = (p_wakeup_io_ctrl & 0xCUL) >> LOWPOWER_WAKEUPIOSRC_PIO1_INDEX;
+ wakeup_io_ctrl_reg |= (wake_up_type << LOWPOWER_WAKEUPIOSRC_PIO1_INDEX);
+ use_external_pullupdown = (uint8_t)((p_wakeup_io_ctrl & LOWPOWER_WAKEUPIO_PIO1_USEEXTERNALPULLUPDOWN_MASK) >>
+ LOWPOWER_WAKEUPIO_PIO1_USEEXTERNALPULLUPDOWN_INDEX);
+
+ if (use_external_pullupdown == 0UL)
+ {
+ if ((wake_up_type == 1UL) || (wake_up_type == 3UL))
+ {
+ /* Rising edge and both rising and falling edges */
+ IOCON->PIO[0][28] = IOCON_PIO_DIGIMODE(1) | IOCON_PIO_MODE(1); /* Pull down */
+ wakeup_io_ctrl_reg |=
+ ((uint32_t)LOWPOWER_WAKEUPIOSRC_IO_MODE_PULLDOWN << LOWPOWER_WAKEUPIOSRC_PIO1MODE_INDEX);
+ }
+ else
+ {
+ if (wake_up_type == 2UL)
+ {
+ /* Falling edge only */
+ IOCON->PIO[0][28] = IOCON_PIO_DIGIMODE(1) | IOCON_PIO_MODE(2); /* Pull up */
+ wakeup_io_ctrl_reg |=
+ ((uint32_t)LOWPOWER_WAKEUPIOSRC_IO_MODE_PULLUP << LOWPOWER_WAKEUPIOSRC_PIO1MODE_INDEX);
+ }
+ else
+ {
+ /* Wake-up I/O is disabled : set it as required by the user */
+ if ((p_wakeup_io_ctrl & LOWPOWER_WAKEUPIO_PIO1_DISABLEPULLUPDOWN_MASK) != 0UL)
+ {
+ /* Wake-up I/O is configured as Plain Input */
+ // @TODO not used p_wakeup_io_ctrl &= ~LOWPOWER_WAKEUPIO_PIO1_PULLUPDOWN_MASK;
+ wakeup_io_ctrl_reg |=
+ ((uint32_t)LOWPOWER_WAKEUPIOSRC_IO_MODE_PLAIN << LOWPOWER_WAKEUPIOSRC_PIO1MODE_INDEX);
+ }
+ else
+ {
+ /* Wake-up I/O is configured as pull-up or pull-down */
+ // @TODO update for mask name
+ if ((p_wakeup_io_ctrl & LOWPOWER_WAKEUPIO_PIO1_PULLUPDOWN_MASK) != 0UL)
+ {
+ /* Wake-up I/O is configured as pull-up */
+ wakeup_io_ctrl_reg |=
+ ((uint32_t)LOWPOWER_WAKEUPIOSRC_IO_MODE_PULLUP << LOWPOWER_WAKEUPIOSRC_PIO1MODE_INDEX);
+ }
+ else
+ {
+ /* Wake-up I/O is configured as pull-down */
+ wakeup_io_ctrl_reg |=
+ ((uint32_t)LOWPOWER_WAKEUPIOSRC_IO_MODE_PULLDOWN << LOWPOWER_WAKEUPIOSRC_PIO1MODE_INDEX);
+ }
+ }
+ }
+ }
+ }
+ else
+ {
+ wakeup_io_ctrl_reg |= ((uint32_t)LOWPOWER_WAKEUPIOSRC_IO_MODE_PLAIN << LOWPOWER_WAKEUPIOSRC_PIO1MODE_INDEX);
+ }
+
+ /* Wake-up I/O 2 */
+ wake_up_type = (p_wakeup_io_ctrl & 0x30UL) >> LOWPOWER_WAKEUPIOSRC_PIO2_INDEX;
+ wakeup_io_ctrl_reg |= (wake_up_type << LOWPOWER_WAKEUPIOSRC_PIO2_INDEX);
+ use_external_pullupdown = (uint8_t)((p_wakeup_io_ctrl & LOWPOWER_WAKEUPIO_PIO2_USEEXTERNALPULLUPDOWN_MASK) >>
+ LOWPOWER_WAKEUPIO_PIO2_USEEXTERNALPULLUPDOWN_INDEX);
+
+ if (use_external_pullupdown == 0UL)
+ {
+ if ((wake_up_type == 1UL) || (wake_up_type == 3UL))
+ {
+ /* Rising edge and both rising and falling edges */
+ IOCON->PIO[1][18] = IOCON_PIO_DIGIMODE(1) | IOCON_PIO_MODE(1); /* Pull down */
+ wakeup_io_ctrl_reg |=
+ ((uint32_t)LOWPOWER_WAKEUPIOSRC_IO_MODE_PULLDOWN << LOWPOWER_WAKEUPIOSRC_PIO2MODE_INDEX);
+ }
+ else
+ {
+ if (wake_up_type == 2UL)
+ {
+ /* Falling edge only */
+ IOCON->PIO[1][18] = IOCON_PIO_DIGIMODE(1) | IOCON_PIO_MODE(2); /* Pull up */
+ wakeup_io_ctrl_reg |=
+ ((uint32_t)LOWPOWER_WAKEUPIOSRC_IO_MODE_PULLUP << LOWPOWER_WAKEUPIOSRC_PIO2MODE_INDEX);
+ }
+ else
+ {
+ /* Wake-up I/O is disabled : set it as required by the user */
+ if ((p_wakeup_io_ctrl & LOWPOWER_WAKEUPIO_PIO2_DISABLEPULLUPDOWN_MASK) != 0UL)
+ {
+ /* Wake-up I/O is configured as Plain Input */
+ // @TODO not used p_wakeup_io_ctrl &= ~LOWPOWER_WAKEUPIO_PIO2_PULLUPDOWN_MASK;
+ wakeup_io_ctrl_reg |=
+ ((uint32_t)LOWPOWER_WAKEUPIOSRC_IO_MODE_PLAIN << LOWPOWER_WAKEUPIOSRC_PIO2MODE_INDEX);
+ }
+ else
+ {
+ /* Wake-up I/O is configured as pull-up or pull-down */
+ // @TODO update for mask name
+ if ((p_wakeup_io_ctrl & LOWPOWER_WAKEUPIO_PIO2_PULLUPDOWN_MASK) != 0UL)
+ {
+ /* Wake-up I/O is configured as pull-up */
+ wakeup_io_ctrl_reg |=
+ ((uint32_t)LOWPOWER_WAKEUPIOSRC_IO_MODE_PULLUP << LOWPOWER_WAKEUPIOSRC_PIO2MODE_INDEX);
+ }
+ else
+ {
+ /* Wake-up I/O is configured as pull-down */
+ wakeup_io_ctrl_reg |=
+ ((uint32_t)LOWPOWER_WAKEUPIOSRC_IO_MODE_PULLDOWN << LOWPOWER_WAKEUPIOSRC_PIO2MODE_INDEX);
+ }
+ }
+ }
+ }
+ }
+ else
+ {
+ wakeup_io_ctrl_reg |= ((uint32_t)LOWPOWER_WAKEUPIOSRC_IO_MODE_PLAIN << LOWPOWER_WAKEUPIOSRC_PIO2MODE_INDEX);
+ }
+
+ /* Wake-up I/O 3 */
+ wake_up_type = (p_wakeup_io_ctrl & 0xC0UL) >> LOWPOWER_WAKEUPIOSRC_PIO3_INDEX;
+ wakeup_io_ctrl_reg |= (wake_up_type << LOWPOWER_WAKEUPIOSRC_PIO3_INDEX);
+ use_external_pullupdown = (uint8_t)((p_wakeup_io_ctrl & LOWPOWER_WAKEUPIO_PIO3_USEEXTERNALPULLUPDOWN_MASK) >>
+ LOWPOWER_WAKEUPIO_PIO3_USEEXTERNALPULLUPDOWN_INDEX);
+
+ if (use_external_pullupdown == 0UL)
+ {
+ if ((wake_up_type == 1UL) || (wake_up_type == 3UL))
+ {
+ /* Rising edge and both rising and falling edges */
+ IOCON->PIO[1][30] = IOCON_PIO_DIGIMODE(1) | IOCON_PIO_MODE(1); /* Pull down */
+ wakeup_io_ctrl_reg |=
+ ((uint32_t)LOWPOWER_WAKEUPIOSRC_IO_MODE_PULLDOWN << LOWPOWER_WAKEUPIOSRC_PIO3MODE_INDEX);
+ }
+ else
+ {
+ if (wake_up_type == 2UL)
+ {
+ /* Falling edge only */
+ IOCON->PIO[1][30] = IOCON_PIO_DIGIMODE(1) | IOCON_PIO_MODE(2); /* Pull up */
+ wakeup_io_ctrl_reg |=
+ ((uint32_t)LOWPOWER_WAKEUPIOSRC_IO_MODE_PULLUP << LOWPOWER_WAKEUPIOSRC_PIO3MODE_INDEX);
+ }
+ else
+ {
+ /* Wake-up I/O is disabled : set it as required by the user */
+ if ((p_wakeup_io_ctrl & LOWPOWER_WAKEUPIO_PIO3_DISABLEPULLUPDOWN_MASK) != 0UL)
+ {
+ /* Wake-up I/O is configured as Plain Input */
+ // @TODO not used p_wakeup_io_ctrl &= ~LOWPOWER_WAKEUPIO_PIO3_PULLUPDOWN_MASK;
+ wakeup_io_ctrl_reg |=
+ ((uint32_t)LOWPOWER_WAKEUPIOSRC_IO_MODE_PLAIN << LOWPOWER_WAKEUPIOSRC_PIO3MODE_INDEX);
+ }
+ else
+ {
+ /* Wake-up I/O is configured as pull-up or pull-down */
+ // @TODO update for mask name
+ if ((p_wakeup_io_ctrl & LOWPOWER_WAKEUPIO_PIO3_PULLUPDOWN_MASK) != 0UL)
+ {
+ /* Wake-up I/O is configured as pull-up */
+ wakeup_io_ctrl_reg |=
+ ((uint32_t)LOWPOWER_WAKEUPIOSRC_IO_MODE_PULLUP << LOWPOWER_WAKEUPIOSRC_PIO3MODE_INDEX);
+ }
+ else
+ {
+ /* Wake-up I/O is configured as pull-down */
+ wakeup_io_ctrl_reg |=
+ ((uint32_t)LOWPOWER_WAKEUPIOSRC_IO_MODE_PULLDOWN << LOWPOWER_WAKEUPIOSRC_PIO3MODE_INDEX);
+ }
+ }
+ }
+ }
+ }
+ else
+ {
+ wakeup_io_ctrl_reg |= ((uint32_t)LOWPOWER_WAKEUPIOSRC_IO_MODE_PLAIN << LOWPOWER_WAKEUPIOSRC_PIO3MODE_INDEX);
+ }
+
+ return (wakeup_io_ctrl_reg);
+}
+
+/**
+ * @brief
+ * @param
+ * @return
+ */
+static uint8_t CLOCK_u8OscCapConvert(uint8_t u8OscCap, uint8_t u8CapBankDiscontinuity)
+{
+ /* Compensate for discontinuity in the capacitor banks */
+ if (u8OscCap < 64U)
+ {
+ if (u8OscCap >= u8CapBankDiscontinuity)
+ {
+ u8OscCap -= u8CapBankDiscontinuity;
+ }
+ else
+ {
+ u8OscCap = 0U;
+ }
+ }
+ else
+ {
+ if (u8OscCap <= (127U - u8CapBankDiscontinuity))
+ {
+ u8OscCap += u8CapBankDiscontinuity;
+ }
+ else
+ {
+ u8OscCap = 127U;
+ }
+ }
+ return u8OscCap;
+}
+
+/**
+ * @brief Described in fsl_common.h
+ * @param
+ * @return
+ */
+static void lowpower_set_system_voltage(uint32_t system_voltage_mv)
+{
+ /*
+ * Set system voltage
+ */
+ uint32_t lv_ldo_ao = (uint32_t)V_AO_1P100; /* */
+ uint32_t lv_ldo_ao_boost = (uint32_t)V_AO_1P150; /* */
+ uint32_t lv_dcdc = (uint32_t)V_DCDC_1P100; /* */
+
+ if (system_voltage_mv <= 950UL)
+ {
+ lv_dcdc = (uint32_t)V_DCDC_0P950;
+ lv_ldo_ao = (uint32_t)V_AO_0P960;
+ lv_ldo_ao_boost = (uint32_t)V_AO_1P010;
+ }
+ else if (system_voltage_mv <= 975UL)
+ {
+ lv_dcdc = (uint32_t)V_DCDC_0P975;
+ lv_ldo_ao = (uint32_t)V_AO_0P980;
+ lv_ldo_ao_boost = (uint32_t)V_AO_1P030;
+ }
+ else if (system_voltage_mv <= 1000UL)
+ {
+ lv_dcdc = (uint32_t)V_DCDC_1P000;
+ lv_ldo_ao = (uint32_t)V_AO_1P000;
+ lv_ldo_ao_boost = (uint32_t)V_AO_1P050;
+ }
+ else if (system_voltage_mv <= 1025UL)
+ {
+ lv_dcdc = (uint32_t)V_DCDC_1P025;
+ lv_ldo_ao = (uint32_t)V_AO_1P030;
+ lv_ldo_ao_boost = (uint32_t)V_AO_1P080;
+ }
+ else if (system_voltage_mv <= 1050UL)
+ {
+ lv_dcdc = (uint32_t)V_DCDC_1P050;
+ lv_ldo_ao = (uint32_t)V_AO_1P060;
+ lv_ldo_ao_boost = (uint32_t)V_AO_1P110;
+ }
+ else if (system_voltage_mv <= 1075UL)
+ {
+ lv_dcdc = (uint32_t)V_DCDC_1P075;
+ lv_ldo_ao = (uint32_t)V_AO_1P080;
+ lv_ldo_ao_boost = (uint32_t)V_AO_1P130;
+ }
+ else if (system_voltage_mv <= 1100UL)
+ {
+ lv_dcdc = (uint32_t)V_DCDC_1P100;
+ lv_ldo_ao = (uint32_t)V_AO_1P100;
+ lv_ldo_ao_boost = (uint32_t)V_AO_1P150;
+ }
+ else if (system_voltage_mv <= 1125UL)
+ {
+ lv_dcdc = (uint32_t)V_DCDC_1P125;
+ lv_ldo_ao = (uint32_t)V_AO_1P130;
+ lv_ldo_ao_boost = (uint32_t)V_AO_1P160;
+ }
+ else if (system_voltage_mv <= 1150UL)
+ {
+ lv_dcdc = (uint32_t)V_DCDC_1P150;
+ lv_ldo_ao = (uint32_t)V_AO_1P160;
+ lv_ldo_ao_boost = (uint32_t)V_AO_1P220;
+ }
+ else if (system_voltage_mv <= 1175UL)
+ {
+ lv_dcdc = (uint32_t)V_DCDC_1P175;
+ lv_ldo_ao = (uint32_t)V_AO_1P160;
+ lv_ldo_ao_boost = (uint32_t)V_AO_1P220;
+ }
+ else
+ {
+ lv_dcdc = (uint32_t)V_DCDC_1P200;
+ lv_ldo_ao = (uint32_t)V_AO_1P160;
+ lv_ldo_ao_boost = (uint32_t)V_AO_1P220;
+ }
+
+ /* Set up LDO Always-On voltages */
+ PMC->LDOPMU = (PMC->LDOPMU & (~PMC_LDOPMU_VADJ_MASK) & (~PMC_LDOPMU_VADJ_BOOST_MASK)) | PMC_LDOPMU_VADJ(lv_ldo_ao) |
+ PMC_LDOPMU_VADJ_BOOST(lv_ldo_ao_boost);
+
+ /* Set up DCDC voltage */
+ PMC->DCDC0 = (PMC->DCDC0 & (~PMC_DCDC0_VOUT_MASK)) | PMC_DCDC0_VOUT(lv_dcdc);
+}
+
+/**
+ * @brief Described in fsl_common.h
+ * @param
+ * @return
+ */
+static void lowpower_set_dcdc_power_profile(lowpower_dcdc_power_profile_enum dcdc_power_profile)
+{
+#define FLASH_NMPA_DCDC_POWER_PROFILE_LOW_0_ADDRS (FLASH_NMPA_BASE + 0xE0U)
+#define FLASH_NMPA_DCDC_POWER_PROFILE_LOW_1_ADDRS (FLASH_NMPA_BASE + 0xE4U)
+#define FLASH_NMPA_DCDC_POWER_PROFILE_MEDIUM_0_ADDRS (FLASH_NMPA_BASE + 0xE8U)
+#define FLASH_NMPA_DCDC_POWER_PROFILE_MEDIUM_1_ADDRS (FLASH_NMPA_BASE + 0xECU)
+#define FLASH_NMPA_DCDC_POWER_PROFILE_HIGH_0_ADDRS (FLASH_NMPA_BASE + 0xD8U)
+#define FLASH_NMPA_DCDC_POWER_PROFILE_HIGH_1_ADDRS (FLASH_NMPA_BASE + 0xDCU)
+
+ const uint32_t PMC_DCDC0_DEFAULT = 0x010C4E68;
+ const uint32_t PMC_DCDC1_DEFAULT = 0x01803A98;
+
+ uint32_t dcdcTrimValue0;
+ uint32_t dcdcTrimValue1;
+
+ switch (dcdc_power_profile)
+ {
+ case DCDC_POWER_PROFILE_LOW:
+ /* Low */
+ dcdcTrimValue0 = (*((volatile unsigned int *)(FLASH_NMPA_DCDC_POWER_PROFILE_LOW_0_ADDRS)));
+ dcdcTrimValue1 = (*((volatile unsigned int *)(FLASH_NMPA_DCDC_POWER_PROFILE_LOW_1_ADDRS)));
+
+ if (0UL != (dcdcTrimValue0 & 0x1UL))
+ {
+ dcdcTrimValue0 = dcdcTrimValue0 >> 1;
+
+ PMC->DCDC0 = dcdcTrimValue0;
+ PMC->DCDC1 = dcdcTrimValue1;
+#if (defined(NIOBE_DEBUG_LEVEL) && (NIOBE_DEBUG_LEVEL >= 1))
+ PRINTF(
+ "\nINFO : DCDC Power Profile set to "
+ "LOW"
+ "\n");
+#endif
+ }
+ break;
+
+ case DCDC_POWER_PROFILE_MEDIUM:
+ /* Medium */
+ dcdcTrimValue0 = (*((volatile unsigned int *)(FLASH_NMPA_DCDC_POWER_PROFILE_MEDIUM_0_ADDRS)));
+ dcdcTrimValue1 = (*((volatile unsigned int *)(FLASH_NMPA_DCDC_POWER_PROFILE_MEDIUM_1_ADDRS)));
+
+ if (0UL != (dcdcTrimValue0 & 0x1UL))
+ {
+ dcdcTrimValue0 = dcdcTrimValue0 >> 1;
+
+ PMC->DCDC0 = dcdcTrimValue0;
+ PMC->DCDC1 = dcdcTrimValue1;
+#if (defined(NIOBE_DEBUG_LEVEL) && (NIOBE_DEBUG_LEVEL >= 1))
+ PRINTF(
+ "\nINFO : DCDC Power Profile set to "
+ "MEDIUM"
+ "\n");
+#endif
+ }
+ break;
+
+ case DCDC_POWER_PROFILE_HIGH:
+ /* High */
+ dcdcTrimValue0 = (*((volatile unsigned int *)(FLASH_NMPA_DCDC_POWER_PROFILE_HIGH_0_ADDRS)));
+ dcdcTrimValue1 = (*((volatile unsigned int *)(FLASH_NMPA_DCDC_POWER_PROFILE_HIGH_1_ADDRS)));
+
+ if (0UL != (dcdcTrimValue0 & 0x1UL))
+ {
+ dcdcTrimValue0 = dcdcTrimValue0 >> 1;
+
+ PMC->DCDC0 = dcdcTrimValue0;
+ PMC->DCDC1 = dcdcTrimValue1;
+#if (defined(NIOBE_DEBUG_LEVEL) && (NIOBE_DEBUG_LEVEL >= 1))
+ PRINTF(
+ "\nINFO : DCDC Power Profile set to "
+ "HIGH"
+ "\n");
+#endif
+ }
+ break;
+
+ default:
+ /* Low */
+ PMC->DCDC0 = PMC_DCDC0_DEFAULT;
+ PMC->DCDC1 = PMC_DCDC1_DEFAULT;
+#if (defined(NIOBE_DEBUG_LEVEL) && (NIOBE_DEBUG_LEVEL >= 1))
+ PRINTF(
+ "\nINFO : DCDC Power Profile set to "
+ "LOW"
+ "\n");
+#endif
+ break;
+ }
+}
+
+/**
+ * @brief
+ * @param
+ * @return
+ */
+static lowpower_process_corner_enum lowpower_get_part_process_corner(void)
+{
+#define FLASH_NMPA_PVT_MONITOR_0_RINGO_ADDRS (FLASH_NMPA_BASE + 0x130U)
+#define FLASH_NMPA_PVT_MONITOR_1_RINGO_ADDRS (FLASH_NMPA_BASE + 0x140U)
+
+ lowpower_process_corner_enum part_process_corner;
+ uint32_t pvt_ringo_hz;
+ uint32_t pvt_ringo_0 = (*((volatile unsigned int *)(FLASH_NMPA_PVT_MONITOR_0_RINGO_ADDRS)));
+ uint32_t pvt_ringo_1 = (*((volatile unsigned int *)(FLASH_NMPA_PVT_MONITOR_1_RINGO_ADDRS)));
+
+ /*
+ * Check that the PVT Monitors Trimmings in flash are valid.
+ */
+ if (0UL != (pvt_ringo_0 & 0x1UL))
+ {
+ /* PVT Trimmings in Flash are valid */
+ pvt_ringo_0 = pvt_ringo_0 >> 1;
+ }
+ else
+ {
+ /* PVT Trimmings in Flash are NOT valid (average value assumed) */
+ pvt_ringo_0 = PROCESS_NNN_AVG_HZ;
+ }
+
+ if (0UL != (pvt_ringo_1 & 0x1UL))
+ {
+ /* PVT Trimmings in Flash are valid */
+ pvt_ringo_1 = pvt_ringo_1 >> 1;
+ }
+ else
+ {
+ /* PVT Trimmings in Flash are NOT valid (average value assumed) */
+ pvt_ringo_1 = PROCESS_NNN_AVG_HZ;
+ }
+
+ if (pvt_ringo_1 <= pvt_ringo_0)
+ {
+ pvt_ringo_hz = pvt_ringo_1;
+ }
+ else
+ {
+ pvt_ringo_hz = pvt_ringo_0;
+ }
+
+ /*
+ * Determine the process corner based on the value of the Ring Oscillator frequency
+ */
+ if (pvt_ringo_hz <= PROCESS_NNN_MIN_HZ)
+ {
+ /* SSS Process Corner */
+ part_process_corner = PROCESS_CORNER_SSS;
+#if (defined(NIOBE_DEBUG_LEVEL) && (NIOBE_DEBUG_LEVEL >= 1))
+ PRINTF(
+ "\nINFO : Process Corner : "
+ "SSS"
+ "\n");
+#endif
+ }
+ else
+ {
+ if (pvt_ringo_hz <= PROCESS_NNN_MAX_HZ)
+ {
+ /* NNN Process Corner */
+ part_process_corner = PROCESS_CORNER_NNN;
+#if (defined(NIOBE_DEBUG_LEVEL) && (NIOBE_DEBUG_LEVEL >= 1))
+ PRINTF(
+ "\nINFO : Process Corner : "
+ "NNN"
+ "\n");
+#endif
+ }
+ else
+ {
+ /* FFF Process Corner */
+ part_process_corner = PROCESS_CORNER_FFF;
+#if (defined(NIOBE_DEBUG_LEVEL) && (NIOBE_DEBUG_LEVEL >= 1))
+ PRINTF(
+ "\nINFO : Process Corner : "
+ "FFF"
+ "\n");
+#endif
+ }
+ }
+
+ return (part_process_corner);
+}
+
+/**
+ * @brief Described in fsl_common.h
+ * @param
+ * @return
+ */
+static void lowpower_set_voltage_for_process(lowpower_dcdc_power_profile_enum dcdc_power_profile)
+{
+ /* Get Sample Process Corner */
+ lowpower_process_corner_enum part_process_corner = lowpower_get_part_process_corner();
+
+ switch (part_process_corner)
+ {
+ case PROCESS_CORNER_SSS:
+ /* Slow Corner */
+ {
+ switch (dcdc_power_profile)
+ {
+ case DCDC_POWER_PROFILE_MEDIUM:
+ /* Medium */
+ lowpower_set_system_voltage(VOLTAGE_SSS_MED_MV);
+ break;
+
+ case DCDC_POWER_PROFILE_HIGH:
+ /* High */
+ lowpower_set_system_voltage(VOLTAGE_SSS_HIG_MV);
+ break;
+
+ default:
+ /* DCDC_POWER_PROFILE_LOW */
+ lowpower_set_system_voltage(VOLTAGE_SSS_LOW_MV);
+ break;
+ } // switch(dcdc_power_profile)
+ }
+ break;
+
+ case PROCESS_CORNER_FFF:
+ /* Fast Corner */
+ {
+ switch (dcdc_power_profile)
+ {
+ case DCDC_POWER_PROFILE_MEDIUM:
+ /* Medium */
+ lowpower_set_system_voltage(VOLTAGE_FFF_MED_MV);
+ break;
+
+ case DCDC_POWER_PROFILE_HIGH:
+ /* High */
+ lowpower_set_system_voltage(VOLTAGE_FFF_HIG_MV);
+ break;
+
+ default:
+ /* DCDC_POWER_PROFILE_LOW */
+ lowpower_set_system_voltage(VOLTAGE_FFF_LOW_MV);
+ break;
+ } // switch(dcdc_power_profile)
+ }
+ break;
+
+ default:
+ /* Nominal (NNN) and all others Process Corners : assume Nominal Corner */
+ {
+ switch (dcdc_power_profile)
+ {
+ case DCDC_POWER_PROFILE_MEDIUM:
+ /* Medium */
+ lowpower_set_system_voltage(VOLTAGE_NNN_MED_MV);
+ break;
+
+ case DCDC_POWER_PROFILE_HIGH:
+ /* High */
+ lowpower_set_system_voltage(VOLTAGE_NNN_HIG_MV);
+ break;
+
+ default:
+ /* DCDC_POWER_PROFILE_LOW */
+ lowpower_set_system_voltage(VOLTAGE_NNN_LOW_MV);
+ break;
+ } // switch(dcdc_power_profile)
+ break;
+ }
+ } // switch(part_process_corner)
+}
+
+/**
+ * @brief Described in fsl_common.h
+ * @param
+ * @return
+ */
+void POWER_SetVoltageForFreq(uint32_t system_freq_hz)
+{
+ if (system_freq_hz <= DCDC_POWER_PROFILE_LOW_MAX_FREQ_HZ)
+ {
+ /* [0 Hz - DCDC_POWER_PROFILE_LOW_MAX_FREQ_HZ Hz] */
+ lowpower_set_dcdc_power_profile(DCDC_POWER_PROFILE_LOW); /* DCDC VOUT = 1.05 V by default */
+ lowpower_set_voltage_for_process(DCDC_POWER_PROFILE_LOW);
+ }
+ else
+ {
+ if (system_freq_hz <= DCDC_POWER_PROFILE_MEDIUM_MAX_FREQ_HZ)
+ {
+ /* ]DCDC_POWER_PROFILE_LOW_MAX_FREQ_HZ Hz - DCDC_POWER_PROFILE_MEDIUM_MAX_FREQ_HZ Hz] */
+ lowpower_set_dcdc_power_profile(DCDC_POWER_PROFILE_MEDIUM); /* DCDC VOUT = 1.15 V by default */
+ lowpower_set_voltage_for_process(DCDC_POWER_PROFILE_MEDIUM);
+ }
+ else
+ {
+ /* > DCDC_POWER_PROFILE_MEDIUM_MAX_FREQ_HZ Hz */
+ lowpower_set_dcdc_power_profile(DCDC_POWER_PROFILE_HIGH); /* DCDC VOUT = 1.2 V by default */
+ lowpower_set_voltage_for_process(DCDC_POWER_PROFILE_HIGH);
+ }
+ }
+}
+
+void POWER_Xtal16mhzCapabankTrim(int32_t pi32_16MfXtalIecLoadpF_x100,
+ int32_t pi32_16MfXtalPPcbParCappF_x100,
+ int32_t pi32_16MfXtalNPcbParCappF_x100)
+{
+ uint32_t u32XOTrimValue;
+ uint8_t u8IECXinCapCal6pF, u8IECXinCapCal8pF, u8IECXoutCapCal6pF, u8IECXoutCapCal8pF, u8XOSlave;
+ int32_t iaXin_x4, ibXin, iaXout_x4, ibXout;
+ int32_t iXOCapInpF_x100, iXOCapOutpF_x100;
+ uint8_t u8XOCapInCtrl, u8XOCapOutCtrl;
+ uint32_t u32RegVal;
+ int32_t i32Tmp;
+
+ /* Enable and set LDO, if not already done */
+ POWER_SetXtal16mhzLdo();
+ /* Get Cal values from Flash */
+ u32XOTrimValue = GET_16MXO_TRIM();
+ /* Check validity and apply */
+ if ((0UL != (u32XOTrimValue & 1UL)) && (0UL != ((u32XOTrimValue >> 15UL) & 1UL)))
+ {
+ /* These fields are 7 bits, unsigned */
+ u8IECXinCapCal6pF = (uint8_t)((u32XOTrimValue >> 1UL) & 0x7fUL);
+ u8IECXinCapCal8pF = (uint8_t)((u32XOTrimValue >> 8UL) & 0x7fUL);
+ u8IECXoutCapCal6pF = (uint8_t)((u32XOTrimValue >> 16UL) & 0x7fUL);
+ u8IECXoutCapCal8pF = (uint8_t)((u32XOTrimValue >> 23UL) & 0x7fUL);
+ /* This field is 1 bit */
+ u8XOSlave = (uint8_t)((u32XOTrimValue >> 30UL) & 0x1UL);
+ /* Linear fit coefficients calculation */
+ iaXin_x4 = (int)u8IECXinCapCal8pF - (int)u8IECXinCapCal6pF;
+ ibXin = (int)u8IECXinCapCal6pF - iaXin_x4 * 3;
+ iaXout_x4 = (int)u8IECXoutCapCal8pF - (int)u8IECXoutCapCal6pF;
+ ibXout = (int)u8IECXoutCapCal6pF - iaXout_x4 * 3;
+ }
+ else
+ {
+ iaXin_x4 = 20; // gain in LSB/pF
+ ibXin = -9; // offset in LSB
+ iaXout_x4 = 20; // gain in LSB/pF
+ ibXout = -13; // offset in LSB
+ u8XOSlave = 0;
+ }
+ /* In & out load cap calculation with derating */
+ iXOCapInpF_x100 = 2 * pi32_16MfXtalIecLoadpF_x100 - pi32_16MfXtalNPcbParCappF_x100 +
+ 39 * ((int32_t)XO_SLAVE_EN - (int32_t)u8XOSlave) - 15;
+ iXOCapOutpF_x100 = 2 * pi32_16MfXtalIecLoadpF_x100 - pi32_16MfXtalPPcbParCappF_x100 - 21;
+ /* In & out XO_OSC_CAP_Code_CTRL calculation, with rounding */
+ i32Tmp = ((iXOCapInpF_x100 * iaXin_x4 + ibXin * 400) + 200) / 400;
+ u8XOCapInCtrl = (uint8_t)i32Tmp;
+ i32Tmp = ((iXOCapOutpF_x100 * iaXout_x4 + ibXout * 400) + 200) / 400;
+ u8XOCapOutCtrl = (uint8_t)i32Tmp;
+ /* Read register and clear fields to be written */
+ u32RegVal = ANACTRL->XO32M_CTRL;
+ u32RegVal &= ~(ANACTRL_XO32M_CTRL_OSC_CAP_IN_MASK | ANACTRL_XO32M_CTRL_OSC_CAP_OUT_MASK);
+ /* Configuration of 32 MHz XO output buffers */
+#if (XO_SLAVE_EN == 0)
+ u32RegVal &= ~(ANACTRL_XO32M_CTRL_SLAVE_MASK | ANACTRL_XO32M_CTRL_ACBUF_PASS_ENABLE_MASK);
+#else
+ u32RegVal |= ANACTRL_XO32M_CTRL_SLAVE_MASK | ANACTRL_XO32M_CTRL_ACBUF_PASS_ENABLE_MASK;
+#endif
+ /* XO_OSC_CAP_Code_CTRL to XO_OSC_CAP_Code conversion */
+ u32RegVal |= (uint32_t)CLOCK_u8OscCapConvert(u8XOCapInCtrl, 13) << ANACTRL_XO32M_CTRL_OSC_CAP_IN_SHIFT;
+ u32RegVal |= (uint32_t)CLOCK_u8OscCapConvert(u8XOCapOutCtrl, 13) << ANACTRL_XO32M_CTRL_OSC_CAP_OUT_SHIFT;
+ /* Write back to register */
+ ANACTRL->XO32M_CTRL = u32RegVal;
+}
+
+void POWER_Xtal32khzCapabankTrim(int32_t pi32_32kfXtalIecLoadpF_x100,
+ int32_t pi32_32kfXtalPPcbParCappF_x100,
+ int32_t pi32_32kfXtalNPcbParCappF_x100)
+{
+ uint32_t u32XOTrimValue;
+ uint8_t u8IECXinCapCal6pF, u8IECXinCapCal8pF, u8IECXoutCapCal6pF, u8IECXoutCapCal8pF;
+ int32_t iaXin_x4, ibXin, iaXout_x4, ibXout;
+ int32_t iXOCapInpF_x100, iXOCapOutpF_x100;
+ uint8_t u8XOCapInCtrl, u8XOCapOutCtrl;
+ uint32_t u32RegVal;
+ int32_t i32Tmp;
+ /* Get Cal values from Flash */
+ u32XOTrimValue = GET_32KXO_TRIM();
+ /* check validity and apply */
+ if ((0UL != (u32XOTrimValue & 1UL)) && (0UL != ((u32XOTrimValue >> 15UL) & 1UL)))
+ {
+ /* These fields are 7 bits, unsigned */
+ u8IECXinCapCal6pF = (uint8_t)((u32XOTrimValue >> 1UL) & 0x7fUL);
+ u8IECXinCapCal8pF = (uint8_t)((u32XOTrimValue >> 8UL) & 0x7fUL);
+ u8IECXoutCapCal6pF = (uint8_t)((u32XOTrimValue >> 16UL) & 0x7fUL);
+ u8IECXoutCapCal8pF = (uint8_t)((u32XOTrimValue >> 23UL) & 0x7fUL);
+ /* Linear fit coefficients calculation */
+ iaXin_x4 = (int)u8IECXinCapCal8pF - (int)u8IECXinCapCal6pF;
+ ibXin = (int)u8IECXinCapCal6pF - iaXin_x4 * 3;
+ iaXout_x4 = (int)u8IECXoutCapCal8pF - (int)u8IECXoutCapCal6pF;
+ ibXout = (int)u8IECXoutCapCal6pF - iaXout_x4 * 3;
+ }
+ else
+ {
+ iaXin_x4 = 16; // gain in LSB/pF
+ ibXin = 12; // offset in LSB
+ iaXout_x4 = 16; // gain in LSB/pF
+ ibXout = 11; // offset in LSB
+ }
+
+ /* In & out load cap calculation with derating */
+ iXOCapInpF_x100 = 2 * pi32_32kfXtalIecLoadpF_x100 - pi32_32kfXtalNPcbParCappF_x100 - 130;
+ iXOCapOutpF_x100 = 2 * pi32_32kfXtalIecLoadpF_x100 - pi32_32kfXtalPPcbParCappF_x100 - 41;
+
+ /* In & out XO_OSC_CAP_Code_CTRL calculation, with rounding */
+ i32Tmp = ((iXOCapInpF_x100 * iaXin_x4 + ibXin * 400) + 200) / 400;
+ u8XOCapInCtrl = (uint8_t)i32Tmp;
+ i32Tmp = ((iXOCapOutpF_x100 * iaXout_x4 + ibXout * 400) + 200) / 400;
+ u8XOCapOutCtrl = (uint8_t)i32Tmp;
+
+ /* Read register and clear fields to be written */
+ u32RegVal = PMC->XTAL32K;
+ u32RegVal &= ~(PMC_XTAL32K_CAPBANKIN_MASK | PMC_XTAL32K_CAPBANKOUT_MASK);
+
+ /* XO_OSC_CAP_Code_CTRL to XO_OSC_CAP_Code conversion */
+ u32RegVal |= (uint32_t)CLOCK_u8OscCapConvert(u8XOCapInCtrl, 23) << PMC_XTAL32K_CAPBANKIN_SHIFT;
+ u32RegVal |= (uint32_t)CLOCK_u8OscCapConvert(u8XOCapOutCtrl, 23) << PMC_XTAL32K_CAPBANKOUT_SHIFT;
+
+ /* Write back to register */
+ PMC->XTAL32K = u32RegVal;
+}
+
+void POWER_SetXtal16mhzLdo(void)
+{
+ uint32_t temp;
+ const uint32_t u32Mask =
+ (ANACTRL_LDO_XO32M_VOUT_MASK | ANACTRL_LDO_XO32M_IBIAS_MASK | ANACTRL_LDO_XO32M_STABMODE_MASK);
+
+ const uint32_t u32Value =
+ (ANACTRL_LDO_XO32M_VOUT(0x5) | ANACTRL_LDO_XO32M_IBIAS(0x2) | ANACTRL_LDO_XO32M_STABMODE(0x1));
+
+ /* Enable & set-up XTAL 32 MHz clock LDO */
+ temp = ANACTRL->LDO_XO32M;
+
+ if ((temp & u32Mask) != u32Value)
+ {
+ temp &= ~u32Mask;
+
+ /*
+ * Enable the XTAL32M LDO
+ * Adjust the output voltage level, 0x5 for 1.1V
+ * Adjust the biasing current, 0x2 value
+ * Stability configuration, 0x1 default mode
+ */
+ temp |= u32Value;
+
+ ANACTRL->LDO_XO32M = temp;
+
+ /* Delay for LDO to be up */
+ // CLOCK_uDelay(20);
+ }
+
+ /* Enable LDO XO32M */
+ PMC->PDRUNCFGCLR0 = PMC_PDRUNCFG0_PDEN_LDOXO32M_MASK;
+}
+
+/*!
+ * @brief set BOD VBAT level.
+ *
+ * @param level BOD detect level
+ * @param hyst BoD Hysteresis control
+ * @param enBodVbatReset VBAT brown out detect reset
+ */
+void POWER_SetBodVbatLevel(power_bod_vbat_level_t level, power_bod_hyst_t hyst, bool enBodVbatReset)
+{
+ uint32_t pmc_reset_ctrl;
+ /* BOD VBAT disable reset */
+ pmc_reset_ctrl =
+ PMC->RESETCTRL & (~(PMC_RESETCTRL_BODVBATRESETENA_SECURE_MASK | PMC_RESETCTRL_BODVBATRESETENA_SECURE_DP_MASK));
+ pmc_reset_ctrl |= (0x2UL << PMC_RESETCTRL_BODVBATRESETENA_SECURE_SHIFT) |
+ (0x2UL << PMC_RESETCTRL_BODVBATRESETENA_SECURE_DP_SHIFT);
+
+ PMC->RESETCTRL = pmc_reset_ctrl;
+
+ PMC->BODVBAT = (PMC->BODVBAT & (~(PMC_BODVBAT_TRIGLVL_MASK | PMC_BODVBAT_HYST_MASK))) | PMC_BODVBAT_TRIGLVL(level) |
+ PMC_BODVBAT_HYST(hyst);
+
+ /* BOD VBAT enable reset */
+ if ((uint32_t)enBodVbatReset == 1UL)
+ {
+ pmc_reset_ctrl &= (~(PMC_RESETCTRL_BODVBATRESETENA_SECURE_MASK | PMC_RESETCTRL_BODVBATRESETENA_SECURE_DP_MASK));
+ pmc_reset_ctrl |= (0x1UL << PMC_RESETCTRL_BODVBATRESETENA_SECURE_SHIFT) |
+ (0x1UL << PMC_RESETCTRL_BODVBATRESETENA_SECURE_DP_SHIFT);
+ PMC->RESETCTRL = pmc_reset_ctrl;
+ }
+}
+
+#if defined(PMC_BODCORE_TRIGLVL_MASK)
+/*!
+ * @brief set BOD core level.
+ *
+ * @param level BOD detect level
+ * @param hyst BoD Hysteresis control
+ * @param enBodCoreReset core brown out detect reset
+ */
+void POWER_SetBodCoreLevel(power_bod_core_level_t level, power_bod_hyst_t hyst, bool enBodCoreReset)
+{
+ uint32_t pmc_reset_ctrl;
+ /* BOD CORE disable reset */
+ pmc_reset_ctrl =
+ PMC->RESETCTRL & (~(PMC_RESETCTRL_BODCORERESETENA_SECURE_MASK | PMC_RESETCTRL_BODCORERESETENA_SECURE_DP_MASK));
+ pmc_reset_ctrl |=
+ (0x2 << PMC_RESETCTRL_BODCORERESETENA_SECURE_SHIFT) | (0x2 << PMC_RESETCTRL_BODCORERESETENA_SECURE_DP_SHIFT);
+
+ PMC->RESETCTRL = pmc_reset_ctrl;
+
+ PMC->BODCORE = (PMC->BODCORE & (~(PMC_BODCORE_TRIGLVL_MASK | PMC_BODCORE_HYST_MASK))) | PMC_BODCORE_TRIGLVL(level) |
+ PMC_BODCORE_HYST(hyst);
+
+ /* BOD CORE enable reset */
+ if (enBodCoreReset == 1)
+ {
+ pmc_reset_ctrl &= (~(PMC_RESETCTRL_BODCORERESETENA_SECURE_MASK | PMC_RESETCTRL_BODCORERESETENA_SECURE_DP_MASK));
+ pmc_reset_ctrl |= (0x1 << PMC_RESETCTRL_BODCORERESETENA_SECURE_SHIFT) |
+ (0x1 << PMC_RESETCTRL_BODCORERESETENA_SECURE_DP_SHIFT);
+ PMC->RESETCTRL = pmc_reset_ctrl;
+ }
+}
+#endif
+
+/**
+ * @brief Return some key information related to the device reset causes / wake-up sources, for all power modes.
+ * @param p_reset_cause : the device reset cause, according to the definition of power_device_reset_cause_t type.
+ * @param p_boot_mode : the device boot mode, according to the definition of power_device_boot_mode_t type.
+ * @param p_wakeupio_cause: the wake-up pin sources, according to the definition of register PMC->WAKEIOCAUSE[3:0].
+
+ * @return Nothing
+ *
+ * !!! IMPORTANT ERRATA - IMPORTANT ERRATA - IMPORTANT ERRATA !!!
+ * !!! valid ONLY for LPC55S69 (not for LPC55S16 and LPC55S06) !!!
+ * !!! when FALLING EDGE DETECTION is enabled on wake-up pins: !!!
+ * - 1. p_wakeupio_cause is NOT ACCURATE
+ * - 2. Spurious kRESET_CAUSE_DPDRESET_WAKEUPIO* event is reported when
+ * several wake-up sources are enabled during DEEP-POWER-DOWN
+ * (like enabling wake-up on RTC and Falling edge wake-up pins)
+ *
+ */
+void POWER_GetWakeUpCause(power_device_reset_cause_t *p_reset_cause,
+ power_device_boot_mode_t *p_boot_mode,
+ uint32_t *p_wakeupio_cause)
+{
+ uint32_t reset_cause_reg;
+ uint32_t boot_mode_reg;
+
+#if (defined(LPC55S06_SERIES) || defined(LPC55S04_SERIES) || defined(LPC5506_SERIES) || defined(LPC5504_SERIES) || \
+ defined(LPC5502_SERIES) || defined(LPC55S16_SERIES) || defined(LPC55S14_SERIES) || defined(LPC5516_SERIES) || \
+ defined(LPC5514_SERIES) || defined(LPC5512_SERIES))
+ reset_cause_reg = (PMC->AOREG1) & 0x3FF0UL;
+#else /* LPC55S69/28 */
+ reset_cause_reg = (PMC->AOREG1) & 0x1FF0UL;
+#endif
+
+ /*
+ * Prioritize interrupts source with respect to their critical level
+ */
+#if (defined(LPC55S06_SERIES) || defined(LPC55S04_SERIES) || defined(LPC5506_SERIES) || defined(LPC5504_SERIES) || \
+ defined(LPC5502_SERIES) || defined(LPC55S16_SERIES) || defined(LPC55S14_SERIES) || defined(LPC5516_SERIES) || \
+ defined(LPC5514_SERIES) || defined(LPC5512_SERIES))
+ if (0UL != (reset_cause_reg & PMC_AOREG1_CDOGRESET_MASK))
+ { /* Code Watchdog Reset */
+ *p_reset_cause = kRESET_CAUSE_CDOGRESET;
+ *p_boot_mode = kBOOT_MODE_POWER_UP;
+ *p_wakeupio_cause = 0; /* Device has not been waked-up by any wake-up pins */
+ }
+ else
+#endif
+ {
+ if (0UL != (reset_cause_reg & PMC_AOREG1_WDTRESET_MASK))
+ { /* Watchdog Timer Reset */
+ *p_reset_cause = kRESET_CAUSE_WDTRESET;
+ *p_boot_mode = kBOOT_MODE_POWER_UP;
+ *p_wakeupio_cause = 0; /* Device has not been waked-up by any wake-up pins */
+ }
+ else
+ {
+ if (0UL != (reset_cause_reg & PMC_AOREG1_SYSTEMRESET_MASK))
+ { /* ARM System Reset */
+ *p_reset_cause = kRESET_CAUSE_ARMSYSTEMRESET;
+ *p_boot_mode = kBOOT_MODE_POWER_UP;
+ *p_wakeupio_cause = 0; /* Device has not been waked-up by any wake-up pins */
+ }
+ else
+ {
+ boot_mode_reg = (PMC->STATUS & PMC_STATUS_BOOTMODE_MASK) >> PMC_STATUS_BOOTMODE_SHIFT;
+
+ if (boot_mode_reg == 0UL) /* POWER-UP: Power On Reset, Pin reset, Brown Out Detectors, Software Reset */
+ {
+ *p_boot_mode = kBOOT_MODE_POWER_UP; /* All non wake-up from a Low Power mode */
+ *p_wakeupio_cause = 0; /* Device has not been waked-up by any wake-up pins */
+
+ /*
+ * Prioritise Reset causes, starting from the strongest (Power On Reset)
+ */
+ if (0UL != (reset_cause_reg & PMC_AOREG1_POR_MASK))
+ { /* Power On Reset */
+ *p_reset_cause = kRESET_CAUSE_POR;
+ }
+ else
+ {
+ if (0UL != (reset_cause_reg & PMC_AOREG1_BODRESET_MASK))
+ { /* Brown-out Detector reset (either BODVBAT or BODCORE) */
+ *p_reset_cause = kRESET_CAUSE_BODRESET;
+ }
+ else
+ {
+ if (0UL != (reset_cause_reg & PMC_AOREG1_PADRESET_MASK))
+ { /* Hardware Pin Reset */
+ *p_reset_cause = kRESET_CAUSE_PADRESET;
+ }
+ else
+ {
+ if (0UL != (reset_cause_reg & PMC_AOREG1_SWRRESET_MASK))
+ { /* Software triggered Reset */
+ *p_reset_cause = kRESET_CAUSE_SWRRESET;
+ }
+ else
+ { /* Unknown Reset Cause */
+ *p_reset_cause = kRESET_CAUSE_NOT_DETERMINISTIC;
+ }
+ }
+ }
+ }
+
+#if (defined(LPC55S06_SERIES) || defined(LPC55S04_SERIES) || defined(LPC5506_SERIES) || defined(LPC5504_SERIES) || \
+ defined(LPC5502_SERIES) || defined(LPC55S16_SERIES) || defined(LPC55S14_SERIES) || defined(LPC5516_SERIES) || \
+ defined(LPC5514_SERIES) || defined(LPC5512_SERIES))
+ /* Transfer the control of the 4 wake-up pins to IOCON (instead of the Power Management Controller
+ */
+ PMC->WAKEUPIOCTRL = PMC->WAKEUPIOCTRL & (~PMC_WAKEUPIOCTRL_WAKEUPIO_ENABLE_CTRL_MASK);
+#endif
+ }
+ else /* DEEP-SLEEP, POWER-DOWN and DEEP-POWER-DOWN */
+ {
+ /*
+ * 1- First, save wakeup_io_cause register ...
+ */
+ *p_wakeupio_cause = PMC->WAKEIOCAUSE;
+
+ if (boot_mode_reg == 3UL) /* DEEP-POWER-DOWN */
+ {
+ *p_boot_mode = kBOOT_MODE_LP_DEEP_POWER_DOWN;
+
+ switch (((reset_cause_reg >> PMC_AOREG1_DPDRESET_WAKEUPIO_SHIFT) & 0x7UL))
+ {
+ case 1:
+ *p_reset_cause = kRESET_CAUSE_DPDRESET_WAKEUPIO;
+ break;
+ case 2:
+ *p_reset_cause = kRESET_CAUSE_DPDRESET_RTC;
+ break;
+ case 3:
+ *p_reset_cause = kRESET_CAUSE_DPDRESET_WAKEUPIO_RTC;
+ break;
+ case 4:
+ *p_reset_cause = kRESET_CAUSE_DPDRESET_OSTIMER;
+ break;
+ case 5:
+ *p_reset_cause = kRESET_CAUSE_DPDRESET_WAKEUPIO_OSTIMER;
+ break;
+ case 6:
+ *p_reset_cause = kRESET_CAUSE_DPDRESET_RTC_OSTIMER;
+ break;
+ case 7:
+ *p_reset_cause = kRESET_CAUSE_DPDRESET_WAKEUPIO_RTC_OSTIMER;
+ break;
+ default:
+ /* Unknown Reset Cause */
+ *p_reset_cause = kRESET_CAUSE_NOT_DETERMINISTIC;
+ break;
+ }
+
+#if (defined(LPC55S06_SERIES) || defined(LPC55S04_SERIES) || defined(LPC5506_SERIES) || defined(LPC5504_SERIES) || \
+ defined(LPC5502_SERIES) || defined(LPC55S16_SERIES) || defined(LPC55S14_SERIES) || defined(LPC5516_SERIES) || \
+ defined(LPC5514_SERIES) || defined(LPC5512_SERIES))
+ /*
+ * 2- Next, transfer the control of the 4 wake-up pins
+ * to IOCON (instead of the Power Management Controller)
+ */
+ PMC->WAKEUPIOCTRL = PMC->WAKEUPIOCTRL & (~PMC_WAKEUPIOCTRL_WAKEUPIO_ENABLE_CTRL_MASK);
+#endif
+ }
+ else /* DEEP-SLEEP and POWER-DOWN */
+ {
+ *p_reset_cause = kRESET_CAUSE_NOT_RELEVANT;
+
+ /*
+ * The control of the 4 wake-up pins is already in IOCON,
+ * so there is nothing special to do.
+ */
+
+ if (boot_mode_reg == 1UL) /* DEEP-SLEEP */
+ {
+ *p_boot_mode = kBOOT_MODE_LP_DEEP_SLEEP;
+ }
+ else /* POWER-DOWN */
+ {
+ *p_boot_mode = kBOOT_MODE_LP_POWER_DOWN;
+
+ } /* if ( boot_mode_reg == 1 ) DEEP-SLEEP */
+
+ } /* if ( boot_mode == 3 ) DEEP-POWER-DOWN */
+
+ } /* if ( boot_mode == 0 ) POWER-UP */
+
+ } /* if ( reset_cause_reg & PMC_AOREG1_CDOGRESET_MASK ) */
+
+ } /* if ( reset_cause_reg & PMC_AOREG1_WDTRESET_MASK ) */
+
+ } /* if ( reset_cause_reg & PMC_AOREG1_SYSTEMRESET_MASK ) */
+}
diff --git a/drivers/fsl_power.h b/drivers/fsl_power.h
new file mode 100644
index 0000000..691921f
--- /dev/null
+++ b/drivers/fsl_power.h
@@ -0,0 +1,598 @@
+/*
+ * Copyright 2017, NXP
+ * All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+#ifndef _FSL_POWER_H_
+#define _FSL_POWER_H_
+
+#include "fsl_common.h"
+#include "fsl_device_registers.h"
+#include
+
+/*!
+ * @addtogroup power
+ * @{
+ */
+/*******************************************************************************
+ * Definitions
+ ******************************************************************************/
+
+/*! @name Driver version */
+/*@{*/
+/*! @brief power driver version 1.0.0. */
+#define FSL_POWER_DRIVER_VERSION (MAKE_VERSION(1, 0, 0))
+/*@}*/
+
+/* Power mode configuration API parameter */
+typedef enum _power_mode_config
+{
+ kPmu_Sleep = 0U,
+ kPmu_Deep_Sleep = 1U,
+ kPmu_PowerDown = 2U,
+ kPmu_Deep_PowerDown = 3U,
+} power_mode_cfg_t;
+
+/**
+ * @brief Analog components power modes control during low power modes
+ */
+typedef enum pd_bits
+{
+ kPDRUNCFG_PD_DCDC = (1UL << 0),
+ kPDRUNCFG_PD_BIAS = (1UL << 1),
+ kPDRUNCFG_PD_BODCORE = (1UL << 2),
+ kPDRUNCFG_PD_BODVBAT = (1UL << 3),
+ kPDRUNCFG_PD_FRO1M = (1UL << 4),
+ kPDRUNCFG_PD_FRO192M = (1UL << 5),
+ kPDRUNCFG_PD_FRO32K = (1UL << 6),
+ kPDRUNCFG_PD_XTAL32K = (1UL << 7),
+ kPDRUNCFG_PD_XTAL32M = (1UL << 8),
+ kPDRUNCFG_PD_PLL0 = (1UL << 9),
+ kPDRUNCFG_PD_PLL1 = (1UL << 10),
+ kPDRUNCFG_PD_USB0_PHY = (1UL << 11),
+ kPDRUNCFG_PD_USB1_PHY = (1UL << 12),
+ kPDRUNCFG_PD_COMP = (1UL << 13),
+ kPDRUNCFG_PD_TEMPSENS = (1UL << 14),
+ kPDRUNCFG_PD_GPADC = (1UL << 15),
+ kPDRUNCFG_PD_LDOMEM = (1UL << 16),
+ kPDRUNCFG_PD_LDODEEPSLEEP = (1UL << 17),
+ kPDRUNCFG_PD_LDOUSBHS = (1UL << 18),
+ kPDRUNCFG_PD_LDOGPADC = (1UL << 19),
+ kPDRUNCFG_PD_LDOXO32M = (1UL << 20),
+ kPDRUNCFG_PD_LDOFLASHNV = (1UL << 21),
+ kPDRUNCFG_PD_RNG = (1UL << 22),
+ kPDRUNCFG_PD_PLL0_SSCG = (1UL << 23),
+ kPDRUNCFG_PD_ROM = (1UL << 24),
+ /*
+ This enum member has no practical meaning,it is used to avoid MISRA issue,
+ user should not trying to use it.
+ */
+ kPDRUNCFG_ForceUnsigned = 0x80000000U,
+} pd_bit_t;
+
+/**
+ * @brief BOD VBAT level
+ */
+typedef enum _power_bod_vbat_level
+{
+ kPOWER_BodVbatLevel1000mv = 0, /*!< Brown out detector VBAT level 1V */
+ kPOWER_BodVbatLevel1100mv = 1, /*!< Brown out detector VBAT level 1.1V */
+ kPOWER_BodVbatLevel1200mv = 2, /*!< Brown out detector VBAT level 1.2V */
+ kPOWER_BodVbatLevel1300mv = 3, /*!< Brown out detector VBAT level 1.3V */
+ kPOWER_BodVbatLevel1400mv = 4, /*!< Brown out detector VBAT level 1.4V */
+ kPOWER_BodVbatLevel1500mv = 5, /*!< Brown out detector VBAT level 1.5V */
+ kPOWER_BodVbatLevel1600mv = 6, /*!< Brown out detector VBAT level 1.6V */
+ kPOWER_BodVbatLevel1650mv = 7, /*!< Brown out detector VBAT level 1.65V */
+ kPOWER_BodVbatLevel1700mv = 8, /*!< Brown out detector VBAT level 1.7V */
+ kPOWER_BodVbatLevel1750mv = 9, /*!< Brown out detector VBAT level 1.75V */
+ kPOWER_BodVbatLevel1800mv = 10, /*!< Brown out detector VBAT level 1.8V */
+ kPOWER_BodVbatLevel1900mv = 11, /*!< Brown out detector VBAT level 1.9V */
+ kPOWER_BodVbatLevel2000mv = 12, /*!< Brown out detector VBAT level 2V */
+ kPOWER_BodVbatLevel2100mv = 13, /*!< Brown out detector VBAT level 2.1V */
+ kPOWER_BodVbatLevel2200mv = 14, /*!< Brown out detector VBAT level 2.2V */
+ kPOWER_BodVbatLevel2300mv = 15, /*!< Brown out detector VBAT level 2.3V */
+ kPOWER_BodVbatLevel2400mv = 16, /*!< Brown out detector VBAT level 2.4V */
+ kPOWER_BodVbatLevel2500mv = 17, /*!< Brown out detector VBAT level 2.5V */
+ kPOWER_BodVbatLevel2600mv = 18, /*!< Brown out detector VBAT level 2.6V */
+ kPOWER_BodVbatLevel2700mv = 19, /*!< Brown out detector VBAT level 2.7V */
+ kPOWER_BodVbatLevel2806mv = 20, /*!< Brown out detector VBAT level 2.806V */
+ kPOWER_BodVbatLevel2900mv = 21, /*!< Brown out detector VBAT level 2.9V */
+ kPOWER_BodVbatLevel3000mv = 22, /*!< Brown out detector VBAT level 3.0V */
+ kPOWER_BodVbatLevel3100mv = 23, /*!< Brown out detector VBAT level 3.1V */
+ kPOWER_BodVbatLevel3200mv = 24, /*!< Brown out detector VBAT level 3.2V */
+ kPOWER_BodVbatLevel3300mv = 25, /*!< Brown out detector VBAT level 3.3V */
+} power_bod_vbat_level_t;
+
+/**
+ * @brief BOD Hysteresis control
+ */
+typedef enum _power_bod_hyst
+{
+ kPOWER_BodHystLevel25mv = 0U, /*!< BOD Hysteresis control level 25mv */
+ kPOWER_BodHystLevel50mv = 1U, /*!< BOD Hysteresis control level 50mv */
+ kPOWER_BodHystLevel75mv = 2U, /*!< BOD Hysteresis control level 75mv */
+ kPOWER_BodHystLevel100mv = 3U, /*!< BOD Hysteresis control level 100mv */
+} power_bod_hyst_t;
+/**
+ * @brief BOD core level
+ */
+typedef enum _power_bod_core_level
+{
+ kPOWER_BodCoreLevel600mv = 0, /*!< Brown out detector core level 600mV */
+ kPOWER_BodCoreLevel650mv = 1, /*!< Brown out detector core level 650mV */
+ kPOWER_BodCoreLevel700mv = 2, /*!< Brown out detector core level 700mV */
+ kPOWER_BodCoreLevel750mv = 3, /*!< Brown out detector core level 750mV */
+ kPOWER_BodCoreLevel800mv = 4, /*!< Brown out detector core level 800mV */
+ kPOWER_BodCoreLevel850mv = 5, /*!< Brown out detector core level 850mV */
+ kPOWER_BodCoreLevel900mv = 6, /*!< Brown out detector core level 900mV */
+ kPOWER_BodCoreLevel950mv = 7, /*!< Brown out detector core level 950mV */
+} power_bod_core_level_t;
+
+/**
+ * @brief Device Reset Causes
+ */
+typedef enum _power_device_reset_cause
+{
+ kRESET_CAUSE_POR = 0UL, /*!< Power On Reset */
+ kRESET_CAUSE_PADRESET = 1UL, /*!< Hardware Pin Reset */
+ kRESET_CAUSE_BODRESET = 2UL, /*!< Brown-out Detector reset (either BODVBAT or BODCORE) */
+ kRESET_CAUSE_ARMSYSTEMRESET = 3UL, /*!< ARM System Reset */
+ kRESET_CAUSE_WDTRESET = 4UL, /*!< Watchdog Timer Reset */
+ kRESET_CAUSE_SWRRESET = 5UL, /*!< Software Reset */
+ kRESET_CAUSE_CDOGRESET = 6UL, /*!< Code Watchdog Reset */
+ /* Reset causes in DEEP-POWER-DOWN low power mode */
+ kRESET_CAUSE_DPDRESET_WAKEUPIO = 7UL, /*!< Any of the 4 wake-up pins */
+ kRESET_CAUSE_DPDRESET_RTC = 8UL, /*!< Real Time Counter (RTC) */
+ kRESET_CAUSE_DPDRESET_OSTIMER = 9UL, /*!< OS Event Timer (OSTIMER) */
+ kRESET_CAUSE_DPDRESET_WAKEUPIO_RTC = 10UL, /*!< Any of the 4 wake-up pins and RTC (it is not possible to distinguish
+ which of these 2 events occured first) */
+ kRESET_CAUSE_DPDRESET_WAKEUPIO_OSTIMER = 11UL, /*!< Any of the 4 wake-up pins and OSTIMER (it is not possible to
+ distinguish which of these 2 events occured first) */
+ kRESET_CAUSE_DPDRESET_RTC_OSTIMER = 12UL, /*!< Real Time Counter or OS Event Timer (it is not possible to
+ distinguish which of these 2 events occured first) */
+ kRESET_CAUSE_DPDRESET_WAKEUPIO_RTC_OSTIMER = 13UL, /*!< Any of the 4 wake-up pins (it is not possible to distinguish
+ which of these 3 events occured first) */
+ /* Miscallenous */
+ kRESET_CAUSE_NOT_RELEVANT =
+ 14UL, /*!< No reset cause (for example, this code is used when waking up from DEEP-SLEEP low power mode) */
+ kRESET_CAUSE_NOT_DETERMINISTIC = 15UL, /*!< Unknown Reset Cause. Should be treated like "Hardware Pin Reset" from an
+ application point of view. */
+} power_device_reset_cause_t;
+
+/**
+ * @brief Device Boot Modes
+ */
+typedef enum _power_device_boot_mode
+{
+ kBOOT_MODE_POWER_UP =
+ 0UL, /*!< All non Low Power Mode wake up (Power On Reset, Pin Reset, BoD Reset, ARM System Reset ... ) */
+ kBOOT_MODE_LP_DEEP_SLEEP = 1UL, /*!< Wake up from DEEP-SLEEP Low Power mode */
+ kBOOT_MODE_LP_POWER_DOWN = 2UL, /*!< Wake up from POWER-DOWN Low Power mode */
+ kBOOT_MODE_LP_DEEP_POWER_DOWN = 4UL, /*!< Wake up from DEEP-POWER-DOWN Low Power mode */
+} power_device_boot_mode_t;
+
+/**
+ * @brief SRAM instances retention control during low power modes
+ */
+#define LOWPOWER_SRAMRETCTRL_RETEN_RAMX0 \
+ (1UL << 0) /*!< Enable SRAMX_0 retention when entering in Low power modes */
+#define LOWPOWER_SRAMRETCTRL_RETEN_RAMX1 \
+ (1UL << 1) /*!< Enable SRAMX_1 retention when entering in Low power modes */
+#define LOWPOWER_SRAMRETCTRL_RETEN_RAMX2 \
+ (1UL << 2) /*!< Enable SRAMX_2 retention when entering in Low power modes */
+#define LOWPOWER_SRAMRETCTRL_RETEN_RAMX3 \
+ (1UL << 3) /*!< Enable SRAMX_3 retention when entering in Low power modes */
+#define LOWPOWER_SRAMRETCTRL_RETEN_RAM00 \
+ (1UL << 4) /*!< Enable SRAM0_0 retention when entering in Low power modes */
+#define LOWPOWER_SRAMRETCTRL_RETEN_RAM10 \
+ (1UL << 6) /*!< Enable SRAM1_0 retention when entering in Low power modes */
+#define LOWPOWER_SRAMRETCTRL_RETEN_RAM20 \
+ (1UL << 7) /*!< Enable SRAM2_0 retention when entering in Low power modes */
+#define LOWPOWER_SRAMRETCTRL_RETEN_RAM_USB_HS \
+ (1UL << 14) /*!< Enable SRAM USB HS retention when entering in Low power modes */
+
+/**
+ * @brief Low Power Modes Wake up sources
+ */
+#define WAKEUP_SYS (1ULL << 0) /*!< [SLEEP, DEEP SLEEP ] */ /* WWDT0_IRQ and BOD_IRQ*/
+#define WAKEUP_SDMA0 (1ULL << 1) /*!< [SLEEP, DEEP SLEEP ] */
+#define WAKEUP_GPIO_GLOBALINT0 (1ULL << 2) /*!< [SLEEP, DEEP SLEEP, POWER DOWN ] */
+#define WAKEUP_GPIO_GLOBALINT1 (1ULL << 3) /*!< [SLEEP, DEEP SLEEP, POWER DOWN ] */
+#define WAKEUP_GPIO_INT0_0 (1ULL << 4) /*!< [SLEEP, DEEP SLEEP ] */
+#define WAKEUP_GPIO_INT0_1 (1ULL << 5) /*!< [SLEEP, DEEP SLEEP ] */
+#define WAKEUP_GPIO_INT0_2 (1ULL << 6) /*!< [SLEEP, DEEP SLEEP ] */
+#define WAKEUP_GPIO_INT0_3 (1ULL << 7) /*!< [SLEEP, DEEP SLEEP ] */
+#define WAKEUP_UTICK (1ULL << 8) /*!< [SLEEP, ] */
+#define WAKEUP_MRT (1ULL << 9) /*!< [SLEEP, ] */
+#define WAKEUP_CTIMER0 (1ULL << 10) /*!< [SLEEP, DEEP SLEEP ] */
+#define WAKEUP_CTIMER1 (1ULL << 11) /*!< [SLEEP, DEEP SLEEP ] */
+#define WAKEUP_SCT (1ULL << 12) /*!< [SLEEP, ] */
+#define WAKEUP_CTIMER3 (1ULL << 13) /*!< [SLEEP, DEEP SLEEP ] */
+#define WAKEUP_FLEXCOMM0 (1ULL << 14) /*!< [SLEEP, DEEP SLEEP ] */
+#define WAKEUP_FLEXCOMM1 (1ULL << 15) /*!< [SLEEP, DEEP SLEEP ] */
+#define WAKEUP_FLEXCOMM2 (1ULL << 16) /*!< [SLEEP, DEEP SLEEP ] */
+#define WAKEUP_FLEXCOMM3 (1ULL << 17) /*!< [SLEEP, DEEP SLEEP, POWER DOWN ] */
+#define WAKEUP_FLEXCOMM4 (1ULL << 18) /*!< [SLEEP, DEEP SLEEP ] */
+#define WAKEUP_FLEXCOMM5 (1ULL << 19) /*!< [SLEEP, DEEP SLEEP ] */
+#define WAKEUP_FLEXCOMM6 (1ULL << 20) /*!< [SLEEP, DEEP SLEEP ] */
+#define WAKEUP_FLEXCOMM7 (1ULL << 21) /*!< [SLEEP, DEEP SLEEP ] */
+#define WAKEUP_ADC (1ULL << 22) /*!< [SLEEP, ] */
+// reserved (1ULL << 23)
+#define WAKEUP_ACMP (1ULL << 24) /*!< [SLEEP, DEEP SLEEP, POWER DOWN ] */
+// reserved (1ULL << 25)
+// reserved (1ULL << 26)
+#define WAKEUP_USB0_NEEDCLK (1ULL << 27) /*!< [SLEEP, DEEP SLEEP ] */
+#define WAKEUP_USB0 (1ULL << 28) /*!< [SLEEP, DEEP SLEEP ] */
+#define WAKEUP_RTC_LITE_ALARM_WAKEUP (1ULL << 29) /*!< [SLEEP, DEEP SLEEP, POWER DOWN, DEEP POWER DOWN] */
+// reserved (1ULL << 30)
+// reserved (1ULL << 31)
+#define WAKEUP_GPIO_INT0_4 (1ULL << 32) /*!< [SLEEP, DEEP SLEEP ] */
+#define WAKEUP_GPIO_INT0_5 (1ULL << 33) /*!< [SLEEP, DEEP SLEEP ] */
+#define WAKEUP_GPIO_INT0_6 (1ULL << 34) /*!< [SLEEP, DEEP SLEEP ] */
+#define WAKEUP_GPIO_INT0_7 (1ULL << 35) /*!< [SLEEP, DEEP SLEEP ] */
+#define WAKEUP_CTIMER2 (1ULL << 36) /*!< [SLEEP, DEEP SLEEP ] */
+#define WAKEUP_CTIMER4 (1ULL << 37) /*!< [SLEEP, DEEP SLEEP ] */
+#define WAKEUP_OS_EVENT_TIMER (1ULL << 38) /*!< [SLEEP, DEEP SLEEP, POWER DOWN, DEEP POWER DOWN] */
+// reserved (1ULL << 39)
+// reserved (1ULL << 40)
+// reserved (1ULL << 41)
+// reserved (1ULL << 42)
+#define CAN0_INT0 (1ULL << 43) /*!< [SLEEP, ] */
+#define CAN1_INT0 (1ULL << 44) /*!< [SLEEP, ] */
+// reserved (1ULL << 45)
+// reserved (1ULL << 46)
+#define WAKEUP_USB1 (1ULL << 47) /*!< [SLEEP, DEEP SLEEP ] */
+#define WAKEUP_USB1_NEEDCLK (1ULL << 48) /*!< [SLEEP, DEEP SLEEP ] */
+#define WAKEUP_SEC_HYPERVISOR_CALL (1ULL << 49) /*!< [SLEEP, ] */
+#define WAKEUP_SEC_GPIO_INT0_0 (1ULL << 50) /*!< [SLEEP, DEEP SLEEP ] */
+#define WAKEUP_SEC_GPIO_INT0_1 (1ULL << 51) /*!< [SLEEP, DEEP SLEEP ] */
+#define WAKEUP_PLU (1ULL << 52) /*!< [SLEEP, DEEP SLEEP ] */
+#define WAKEUP_SEC_VIO (1ULL << 53)
+#define WAKEUP_SHA (1ULL << 54) /*!< [SLEEP, ] */
+#define WAKEUP_CASPER (1ULL << 55) /*!< [SLEEP, ] */
+#define WAKEUP_PUF (1ULL << 56) /*!< [SLEEP, ] */
+// reserved (1ULL << 57)
+#define WAKEUP_SDMA1 (1ULL << 58) /*!< [SLEEP, DEEP SLEEP ] */
+#define WAKEUP_LSPI_HS (1ULL << 59) /*!< [SLEEP, DEEP SLEEP ] */
+//#define CDOG (1ULL << 60) !< [SLEEP, ]
+// reserved (1ULL << 61)
+// reserved (1ULL << 62)
+#define WAKEUP_ALLWAKEUPIOS (1ULL << 63) /*!< [ , DEEP POWER DOWN] */
+
+/**
+ * @brief Sleep Postpone
+ */
+#define LOWPOWER_HWWAKE_FORCED (1UL << 0) /*!< Force peripheral clocking to stay on during deep-sleep mode. */
+#define LOWPOWER_HWWAKE_PERIPHERALS \
+ (1UL << 1) /*!< Wake for Flexcomms. Any Flexcomm FIFO reaching the level specified by its own TXLVL will cause \
+ peripheral clocking to wake up temporarily while the related status is asserted */
+#define LOWPOWER_HWWAKE_SDMA0 \
+ (1UL << 3) /*!< Wake for DMA0. DMA0 being busy will cause peripheral clocking to remain running until DMA \
+ completes. Used in conjonction with LOWPOWER_HWWAKE_PERIPHERALS */
+#define LOWPOWER_HWWAKE_SDMA1 \
+ (1UL << 5) /*!< Wake for DMA1. DMA0 being busy will cause peripheral clocking to remain running until DMA \
+ completes. Used in conjonction with LOWPOWER_HWWAKE_PERIPHERALS */
+#define LOWPOWER_HWWAKE_ENABLE_FRO192M \
+ (1UL << 31) /*!< Need to be set if FRO192M is disable - via PDCTRL0 - in Deep Sleep mode and any of \
+ LOWPOWER_HWWAKE_PERIPHERALS, LOWPOWER_HWWAKE_SDMA0 or LOWPOWER_HWWAKE_SDMA1 is set */
+
+#define LOWPOWER_CPURETCTRL_ENA_DISABLE 0 /*!< In POWER DOWN mode, CPU Retention is disabled */
+#define LOWPOWER_CPURETCTRL_ENA_ENABLE 1 /*!< In POWER DOWN mode, CPU Retention is enabled */
+/**
+ * @brief Wake up I/O sources
+ */
+#define LOWPOWER_WAKEUPIOSRC_PIO0_INDEX 0 /*!< Pin P1( 1) */
+#define LOWPOWER_WAKEUPIOSRC_PIO1_INDEX 2 /*!< Pin P0(28) */
+#define LOWPOWER_WAKEUPIOSRC_PIO2_INDEX 4 /*!< Pin P1(18) */
+#define LOWPOWER_WAKEUPIOSRC_PIO3_INDEX 6 /*!< Pin P1(30) */
+
+#define LOWPOWER_WAKEUPIOSRC_DISABLE 0 /*!< Wake up is disable */
+#define LOWPOWER_WAKEUPIOSRC_RISING 1 /*!< Wake up on rising edge */
+#define LOWPOWER_WAKEUPIOSRC_FALLING 2 /*!< Wake up on falling edge */
+#define LOWPOWER_WAKEUPIOSRC_RISING_FALLING 3 /*!< Wake up on both rising or falling edges */
+
+#define LOWPOWER_WAKEUPIOSRC_PIO0MODE_INDEX 12 /*!< Pin P1( 1) */
+#define LOWPOWER_WAKEUPIOSRC_PIO1MODE_INDEX 14 /*!< Pin P0(28) */
+#define LOWPOWER_WAKEUPIOSRC_PIO2MODE_INDEX 16 /*!< Pin P1(18) */
+#define LOWPOWER_WAKEUPIOSRC_PIO3MODE_INDEX 18 /*!< Pin P1(30) */
+
+#define LOWPOWER_WAKEUPIOSRC_IO_MODE_PLAIN 0 /*!< Wake up Pad is plain input */
+#define LOWPOWER_WAKEUPIOSRC_IO_MODE_PULLDOWN 1 /*!< Wake up Pad is pull-down */
+#define LOWPOWER_WAKEUPIOSRC_IO_MODE_PULLUP 2 /*!< Wake up Pad is pull-up */
+#define LOWPOWER_WAKEUPIOSRC_IO_MODE_REPEATER 3 /*!< Wake up Pad is in repeater */
+
+#define LOWPOWER_WAKEUPIO_PIO0_PULLUPDOWN_INDEX 8 /*!< Wake-up I/O 0 pull-up/down configuration index */
+#define LOWPOWER_WAKEUPIO_PIO1_PULLUPDOWN_INDEX 9 /*!< Wake-up I/O 1 pull-up/down configuration index */
+#define LOWPOWER_WAKEUPIO_PIO2_PULLUPDOWN_INDEX 10 /*!< Wake-up I/O 2 pull-up/down configuration index */
+#define LOWPOWER_WAKEUPIO_PIO3_PULLUPDOWN_INDEX 11 /*!< Wake-up I/O 3 pull-up/down configuration index */
+
+#define LOWPOWER_WAKEUPIO_PIO0_PULLUPDOWN_MASK \
+ (1UL << LOWPOWER_WAKEUPIO_PIO0_PULLUPDOWN_INDEX) /*!< Wake-up I/O 0 pull-up/down mask */
+#define LOWPOWER_WAKEUPIO_PIO1_PULLUPDOWN_MASK \
+ (1UL << LOWPOWER_WAKEUPIO_PIO1_PULLUPDOWN_INDEX) /*!< Wake-up I/O 1 pull-up/down mask */
+#define LOWPOWER_WAKEUPIO_PIO2_PULLUPDOWN_MASK \
+ (1UL << LOWPOWER_WAKEUPIO_PIO2_PULLUPDOWN_INDEX) /*!< Wake-up I/O 2 pull-up/down mask */
+#define LOWPOWER_WAKEUPIO_PIO3_PULLUPDOWN_MASK \
+ (1UL << LOWPOWER_WAKEUPIO_PIO3_PULLUPDOWN_INDEX) /*!< Wake-up I/O 3 pull-up/down mask */
+
+#define LOWPOWER_WAKEUPIO_PULLDOWN 0 /*!< Select pull-down */
+#define LOWPOWER_WAKEUPIO_PULLUP 1 /*!< Select pull-up */
+
+#define LOWPOWER_WAKEUPIO_PIO0_DISABLEPULLUPDOWN_INDEX \
+ 12 /*!< Wake-up I/O 0 pull-up/down disable/enable control index */
+#define LOWPOWER_WAKEUPIO_PIO1_DISABLEPULLUPDOWN_INDEX \
+ 13 /*!< Wake-up I/O 1 pull-up/down disable/enable control index */
+#define LOWPOWER_WAKEUPIO_PIO2_DISABLEPULLUPDOWN_INDEX \
+ 14 /*!< Wake-up I/O 2 pull-up/down disable/enable control index */
+#define LOWPOWER_WAKEUPIO_PIO3_DISABLEPULLUPDOWN_INDEX \
+ 15 /*!< Wake-up I/O 3 pull-up/down disable/enable control index */
+#define LOWPOWER_WAKEUPIO_PIO0_DISABLEPULLUPDOWN_MASK \
+ (1UL << LOWPOWER_WAKEUPIO_PIO0_DISABLEPULLUPDOWN_INDEX) /*!< Wake-up I/O 0 pull-up/down disable/enable mask */
+#define LOWPOWER_WAKEUPIO_PIO1_DISABLEPULLUPDOWN_MASK \
+ (1UL << LOWPOWER_WAKEUPIO_PIO1_DISABLEPULLUPDOWN_INDEX) /*!< Wake-up I/O 1 pull-up/down disable/enable mask */
+#define LOWPOWER_WAKEUPIO_PIO2_DISABLEPULLUPDOWN_MASK \
+ (1UL << LOWPOWER_WAKEUPIO_PIO2_DISABLEPULLUPDOWN_INDEX) /*!< Wake-up I/O 2 pull-up/down disable/enable mask */
+#define LOWPOWER_WAKEUPIO_PIO3_DISABLEPULLUPDOWN_MASK \
+ (1UL << LOWPOWER_WAKEUPIO_PIO3_DISABLEPULLUPDOWN_INDEX) /*!< Wake-up I/O 3 pull-up/down disable/enable mask */
+
+#define LOWPOWER_WAKEUPIO_PIO0_USEEXTERNALPULLUPDOWN_INDEX \
+ (16) /*!< Wake-up I/O 0 use external pull-up/down disable/enable control index*/
+#define LOWPOWER_WAKEUPIO_PIO1_USEEXTERNALPULLUPDOWN_INDEX \
+ (17) /*!< Wake-up I/O 1 use external pull-up/down disable/enable control index */
+#define LOWPOWER_WAKEUPIO_PIO2_USEEXTERNALPULLUPDOWN_INDEX \
+ (18) /*!< Wake-up I/O 2 use external pull-up/down disable/enable control index */
+#define LOWPOWER_WAKEUPIO_PIO3_USEEXTERNALPULLUPDOWN_INDEX \
+ (19) /*!< Wake-up I/O 3 use external pull-up/down disable/enable control index */
+#define LOWPOWER_WAKEUPIO_PIO0_USEEXTERNALPULLUPDOWN_MASK \
+ (1UL << LOWPOWER_WAKEUPIO_PIO0_USEEXTERNALPULLUPDOWN_INDEX) /*!< Wake-up I/O 0 use external pull-up/down \
+ disable/enable mask, 0: disable, 1: enable */
+#define LOWPOWER_WAKEUPIO_PIO1_USEEXTERNALPULLUPDOWN_MASK \
+ (1UL << LOWPOWER_WAKEUPIO_PIO1_USEEXTERNALPULLUPDOWN_INDEX) /*!< Wake-up I/O 1 use external pull-up/down \
+ disable/enable mask, 0: disable, 1: enable */
+#define LOWPOWER_WAKEUPIO_PIO2_USEEXTERNALPULLUPDOWN_MASK \
+ (1UL << LOWPOWER_WAKEUPIO_PIO2_USEEXTERNALPULLUPDOWN_INDEX) /*!< Wake-up I/O 2 use external pull-up/down \
+ disable/enable mask, 0: disable, 1: enable */
+#define LOWPOWER_WAKEUPIO_PIO3_USEEXTERNALPULLUPDOWN_MASK \
+ (1UL << LOWPOWER_WAKEUPIO_PIO3_USEEXTERNALPULLUPDOWN_INDEX) /*!< Wake-up I/O 3 use external pull-up/down \
+ disable/enable mask, 0: disable, 1: enable */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+/*******************************************************************************
+ * API
+ ******************************************************************************/
+
+/*!
+ * @brief API to enable PDRUNCFG bit in the Syscon. Note that enabling the bit powers down the peripheral
+ *
+ * @param en peripheral for which to enable the PDRUNCFG bit
+ * @return none
+ */
+static inline void POWER_EnablePD(pd_bit_t en)
+{
+ /* PDRUNCFGSET */
+ PMC->PDRUNCFGSET0 = (uint32_t)en;
+}
+
+/*!
+ * @brief API to disable PDRUNCFG bit in the Syscon. Note that disabling the bit powers up the peripheral
+ *
+ * @param en peripheral for which to disable the PDRUNCFG bit
+ * @return none
+ */
+static inline void POWER_DisablePD(pd_bit_t en)
+{
+ /* PDRUNCFGCLR */
+ PMC->PDRUNCFGCLR0 = (uint32_t)en;
+}
+
+/*!
+ * @brief set BOD VBAT level.
+ *
+ * @param level BOD detect level
+ * @param hyst BoD Hysteresis control
+ * @param enBodVbatReset VBAT brown out detect reset
+ */
+void POWER_SetBodVbatLevel(power_bod_vbat_level_t level, power_bod_hyst_t hyst, bool enBodVbatReset);
+
+#if defined(PMC_BODCORE_TRIGLVL_MASK)
+/*!
+ * @brief set BOD core level.
+ *
+ * @param level BOD detect level
+ * @param hyst BoD Hysteresis control
+ * @param enBodCoreReset core brown out detect reset
+ */
+void POWER_SetBodCoreLevel(power_bod_core_level_t level, power_bod_hyst_t hyst, bool enBodCoreReset);
+#endif
+
+/*!
+ * @brief API to enable deep sleep bit in the ARM Core.
+ *
+ * @return none
+ */
+static inline void POWER_EnableDeepSleep(void)
+{
+ SCB->SCR |= SCB_SCR_SLEEPDEEP_Msk;
+}
+
+/*!
+ * @brief API to disable deep sleep bit in the ARM Core.
+ *
+ * @return none
+ */
+static inline void POWER_DisableDeepSleep(void)
+{
+ SCB->SCR &= ~SCB_SCR_SLEEPDEEP_Msk;
+}
+
+/**
+ * @brief Shut off the Flash and execute the _WFI(), then power up the Flash after wake-up event
+ * This MUST BE EXECUTED outside the Flash:
+ * either from ROM or from SRAM. The rest could stay in Flash. But, for consistency, it is
+ * preferable to have all functions defined in this file implemented in ROM.
+ *
+ * @return Nothing
+ */
+void POWER_CycleCpuAndFlash(void);
+
+/**
+ * @brief Configures and enters in DEEP-SLEEP low power mode
+ * @param exclude_from_pd:
+ * @param sram_retention_ctrl:
+ * @param wakeup_interrupts:
+ * @param hardware_wake_ctrl:
+
+ * @return Nothing
+ *
+ * !!! IMPORTANT NOTES :
+ 0 - CPU0 & System CLock frequency is switched to FRO12MHz and is NOT restored back by the API.
+ * 1 - CPU0 Interrupt Enable registers (NVIC->ISER) are modified by this function. They are restored back in
+ case of CPU retention or if POWERDOWN is not taken (for instance because an interrupt is pending).
+ * 2 - The Non Maskable Interrupt (NMI) is disabled and its configuration before calling this function will be
+ restored back if POWERDOWN is not taken (for instance because an RTC or OSTIMER interrupt is pending).
+ * 3 - The HARD FAULT handler should execute from SRAM. (The Hard fault handler should initiate a full chip
+ reset) reset)
+ */
+void POWER_EnterDeepSleep(uint32_t exclude_from_pd,
+ uint32_t sram_retention_ctrl,
+ uint64_t wakeup_interrupts,
+ uint32_t hardware_wake_ctrl);
+
+/**
+ * @brief Configures and enters in POWERDOWN low power mode
+ * @param exclude_from_pd:
+ * @param sram_retention_ctrl:
+ * @param wakeup_interrupts:
+ * @param cpu_retention_ctrl: 0 = CPU retention is disable / 1 = CPU retention is enabled, all other values are
+ RESERVED.
+
+ * @return Nothing
+ *
+ * !!! IMPORTANT NOTES :
+ 0 - CPU0 & System CLock frequency is switched to FRO12MHz and is NOT restored back by the API.
+ * 1 - CPU0 Interrupt Enable registers (NVIC->ISER) are modified by this function. They are restored back in
+ case of CPU retention or if POWERDOWN is not taken (for instance because an interrupt is pending).
+ * 2 - The Non Maskable Interrupt (NMI) is disabled and its configuration before calling this function will be
+ restored back if POWERDOWN is not taken (for instance because an RTC or OSTIMER interrupt is pending).
+ * 3 - In case of CPU retention, it is the responsability of the user to make sure that SRAM instance
+ containing the stack used to call this function WILL BE preserved during low power (via parameter
+ "sram_retention_ctrl")
+ * 4 - The HARD FAULT handler should execute from SRAM. (The Hard fault handler should initiate a full chip
+ reset) reset)
+ */
+
+void POWER_EnterPowerDown(uint32_t exclude_from_pd,
+ uint32_t sram_retention_ctrl,
+ uint64_t wakeup_interrupts,
+ uint32_t cpu_retention_ctrl);
+
+/**
+ * @brief Configures and enters in DEEPPOWERDOWN low power mode
+ * @param exclude_from_pd:
+ * @param sram_retention_ctrl:
+ * @param wakeup_interrupts:
+ * @param wakeup_io_ctrl:
+
+ * @return Nothing
+ *
+ * !!! IMPORTANT NOTES :
+ 0 - CPU0 & System CLock frequency is switched to FRO12MHz and is NOT restored back by the API.
+ * 1 - CPU0 Interrupt Enable registers (NVIC->ISER) are modified by this function. They are restored back if
+ DEEPPOWERDOWN is not taken (for instance because an RTC or OSTIMER interrupt is pending).
+ * 2 - The Non Maskable Interrupt (NMI) is disabled and its configuration before calling this function will be
+ restored back if DEEPPOWERDOWN is not taken (for instance because an RTC or OSTIMER interrupt is pending).
+ * 3 - The HARD FAULT handler should execute from SRAM. (The Hard fault handler should initiate a full chip
+ reset)
+ */
+void POWER_EnterDeepPowerDown(uint32_t exclude_from_pd,
+ uint32_t sram_retention_ctrl,
+ uint64_t wakeup_interrupts,
+ uint32_t wakeup_io_ctrl);
+
+/**
+ * @brief Configures and enters in SLEEP low power mode
+ *
+ * @return Nothing
+ */
+void POWER_EnterSleep(void);
+
+/*!
+ * @brief Power Library API to choose normal regulation and set the voltage for the desired operating frequency.
+ *
+ * @param system_freq_hz - The desired frequency (in Hertz) at which the part would like to operate,
+ * note that the voltage and flash wait states should be set before changing frequency
+ * @return none
+ */
+void POWER_SetVoltageForFreq(uint32_t system_freq_hz);
+
+/**
+ * @brief Sets board-specific trim values for 16MHz XTAL
+ * @param pi32_16MfXtalIecLoadpF_x100 Load capacitance, pF x 100. For example, 6pF becomes 600, 1.2pF becomes 120
+ * @param pi32_16MfXtalPPcbParCappF_x100 PCB +ve parasitic capacitance, pF x 100. For example, 6pF becomes 600, 1.2pF
+ * becomes 120
+ * @param pi32_16MfXtalNPcbParCappF_x100 PCB -ve parasitic capacitance, pF x 100. For example, 6pF becomes 600, 1.2pF
+ * becomes 120
+ * @return none
+ * @note Following default Values can be used:
+ * pi32_32MfXtalIecLoadpF_x100 Load capacitance, pF x 100 : 600
+ * pi32_32MfXtalPPcbParCappF_x100 PCB +ve parasitic capacitance, pF x 100 : 20
+ * pi32_32MfXtalNPcbParCappF_x100 PCB -ve parasitic capacitance, pF x 100 : 40
+ */
+extern void POWER_Xtal16mhzCapabankTrim(int32_t pi32_16MfXtalIecLoadpF_x100,
+ int32_t pi32_16MfXtalPPcbParCappF_x100,
+ int32_t pi32_16MfXtalNPcbParCappF_x100);
+/**
+ * @brief Sets board-specific trim values for 32kHz XTAL
+ * @param pi32_32kfXtalIecLoadpF_x100 Load capacitance, pF x 100. For example, 6pF becomes 600, 1.2pF becomes 120
+ * @param pi32_32kfXtalPPcbParCappF_x100 PCB +ve parasitic capacitance, pF x 100. For example, 6pF becomes 600, 1.2pF
+ becomes 120
+ * @param pi32_32kfXtalNPcbParCappF_x100 PCB -ve parasitic capacitance, pF x 100. For example, 6pF becomes 600, 1.2pF
+ becomes 120
+
+ * @return none
+ * @note Following default Values can be used:
+ * pi32_32kfXtalIecLoadpF_x100 Load capacitance, pF x 100 : 600
+ * pi32_32kfXtalPPcbParCappF_x100 PCB +ve parasitic capacitance, pF x 100 : 40
+ * pi32_32kfXtalNPcbParCappF_x100 PCB -ve parasitic capacitance, pF x 100 : 40
+ */
+extern void POWER_Xtal32khzCapabankTrim(int32_t pi32_32kfXtalIecLoadpF_x100,
+ int32_t pi32_32kfXtalPPcbParCappF_x100,
+ int32_t pi32_32kfXtalNPcbParCappF_x100);
+/**
+ * @brief Enables and sets LDO for 16MHz XTAL
+ * @return none
+ */
+extern void POWER_SetXtal16mhzLdo(void);
+
+/**
+ * @brief Return some key information related to the device reset causes / wake-up sources, for all power modes.
+ * @param p_reset_cause : the device reset cause, according to the definition of power_device_reset_cause_t type.
+ * @param p_boot_mode : the device boot mode, according to the definition of power_device_boot_mode_t type.
+ * @param p_wakeupio_cause: the wake-up pin sources, according to the definition of register PMC->WAKEIOCAUSE[3:0].
+
+ * @return Nothing
+ *
+ * !!! IMPORTANT ERRATA - IMPORTANT ERRATA - IMPORTANT ERRATA !!!
+ * !!! valid ONLY for LPC55S69 (not for LPC55S16 and LPC55S06) !!!
+ * !!! when FALLING EDGE DETECTION is enabled on wake-up pins: !!!
+ * - 1. p_wakeupio_cause is NOT ACCURATE
+ * - 2. Spurious kRESET_CAUSE_DPDRESET_WAKEUPIO* event is reported when
+ * several wake-up sources are enabled during DEEP-POWER-DOWN
+ * (like enabling wake-up on RTC and Falling edge wake-up pins)
+ *
+ */
+void POWER_GetWakeUpCause(power_device_reset_cause_t *p_reset_cause,
+ power_device_boot_mode_t *p_boot_mode,
+ uint32_t *p_wakeupio_cause);
+#ifdef __cplusplus
+}
+#endif
+
+/**
+ * @}
+ */
+
+#endif /* _FSL_POWER_H_ */
diff --git a/drivers/fsl_reset.c b/drivers/fsl_reset.c
new file mode 100644
index 0000000..12e4081
--- /dev/null
+++ b/drivers/fsl_reset.c
@@ -0,0 +1,99 @@
+/*
+ * Copyright (c) 2016, Freescale Semiconductor, Inc.
+ * Copyright 2016, NXP
+ * All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include "fsl_common.h"
+#include "fsl_reset.h"
+
+/*******************************************************************************
+ * Definitions
+ ******************************************************************************/
+/* Component ID definition, used by tools. */
+#ifndef FSL_COMPONENT_ID
+#define FSL_COMPONENT_ID "platform.drivers.reset"
+#endif
+
+/*******************************************************************************
+ * Variables
+ ******************************************************************************/
+
+/*******************************************************************************
+ * Prototypes
+ ******************************************************************************/
+
+/*******************************************************************************
+ * Code
+ ******************************************************************************/
+
+#if (defined(FSL_FEATURE_SOC_SYSCON_COUNT) && (FSL_FEATURE_SOC_SYSCON_COUNT > 0))
+
+/*!
+ * brief Assert reset to peripheral.
+ *
+ * Asserts reset signal to specified peripheral module.
+ *
+ * param peripheral Assert reset to this peripheral. The enum argument contains encoding of reset register
+ * and reset bit position in the reset register.
+ */
+void RESET_SetPeripheralReset(reset_ip_name_t peripheral)
+{
+ const uint32_t regIndex = ((uint32_t)peripheral & 0xFFFF0000u) >> 16;
+ const uint32_t bitPos = ((uint32_t)peripheral & 0x0000FFFFu);
+ const uint32_t bitMask = 1UL << bitPos;
+
+ assert(bitPos < 32u);
+
+ /* reset register is in SYSCON */
+ /* set bit */
+ SYSCON->PRESETCTRLSET[regIndex] = bitMask;
+ /* wait until it reads 0b1 */
+ while (0u == (SYSCON->PRESETCTRLX[regIndex] & bitMask))
+ {
+ }
+}
+
+/*!
+ * brief Clear reset to peripheral.
+ *
+ * Clears reset signal to specified peripheral module, allows it to operate.
+ *
+ * param peripheral Clear reset to this peripheral. The enum argument contains encoding of reset register
+ * and reset bit position in the reset register.
+ */
+void RESET_ClearPeripheralReset(reset_ip_name_t peripheral)
+{
+ const uint32_t regIndex = ((uint32_t)peripheral & 0xFFFF0000u) >> 16;
+ const uint32_t bitPos = ((uint32_t)peripheral & 0x0000FFFFu);
+ const uint32_t bitMask = 1UL << bitPos;
+
+ assert(bitPos < 32u);
+
+ /* reset register is in SYSCON */
+
+ /* clear bit */
+ SYSCON->PRESETCTRLCLR[regIndex] = bitMask;
+ /* wait until it reads 0b0 */
+ while (bitMask == (SYSCON->PRESETCTRLX[regIndex] & bitMask))
+ {
+ }
+}
+
+/*!
+ * brief Reset peripheral module.
+ *
+ * Reset peripheral module.
+ *
+ * param peripheral Peripheral to reset. The enum argument contains encoding of reset register
+ * and reset bit position in the reset register.
+ */
+void RESET_PeripheralReset(reset_ip_name_t peripheral)
+{
+ RESET_SetPeripheralReset(peripheral);
+ RESET_ClearPeripheralReset(peripheral);
+}
+
+#endif /* FSL_FEATURE_SOC_SYSCON_COUNT || FSL_FEATURE_SOC_ASYNC_SYSCON_COUNT */
diff --git a/drivers/fsl_reset.h b/drivers/fsl_reset.h
new file mode 100644
index 0000000..3194f68
--- /dev/null
+++ b/drivers/fsl_reset.h
@@ -0,0 +1,255 @@
+/*
+ * Copyright (c) 2016, Freescale Semiconductor, Inc.
+ * Copyright 2016, NXP
+ * All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef _FSL_RESET_H_
+#define _FSL_RESET_H_
+
+#include
+#include
+#include
+#include
+#include "fsl_device_registers.h"
+
+/*!
+ * @addtogroup reset
+ * @{
+ */
+
+/*******************************************************************************
+ * Definitions
+ ******************************************************************************/
+
+/*! @name Driver version */
+/*@{*/
+/*! @brief reset driver version 2.0.0. */
+#define FSL_RESET_DRIVER_VERSION (MAKE_VERSION(2, 0, 0))
+/*@}*/
+
+/*!
+ * @brief Enumeration for peripheral reset control bits
+ *
+ * Defines the enumeration for peripheral reset control bits in PRESETCTRL/ASYNCPRESETCTRL registers
+ */
+typedef enum _SYSCON_RSTn
+{
+ kROM_RST_SHIFT_RSTn = 0 | 1U, /**< ROM reset control */
+ kSRAM1_RST_SHIFT_RSTn = 0 | 3U, /**< SRAM1 reset control */
+ kSRAM2_RST_SHIFT_RSTn = 0 | 4U, /**< SRAM2 reset control */
+ kFLASH_RST_SHIFT_RSTn = 0 | 7U, /**< Flash controller reset control */
+ kFMC_RST_SHIFT_RSTn = 0 | 8U, /**< Flash accelerator reset control */
+ kMUX0_RST_SHIFT_RSTn = 0 | 11U, /**< Input mux0 reset control */
+ kIOCON_RST_SHIFT_RSTn = 0 | 13U, /**< IOCON reset control */
+ kGPIO0_RST_SHIFT_RSTn = 0 | 14U, /**< GPIO0 reset control */
+ kGPIO1_RST_SHIFT_RSTn = 0 | 15U, /**< GPIO1 reset control */
+ kPINT_RST_SHIFT_RSTn = 0 | 18U, /**< Pin interrupt (PINT) reset control */
+ kGINT_RST_SHIFT_RSTn = 0 | 19U, /**< Grouped interrupt (PINT) reset control. */
+ kDMA0_RST_SHIFT_RSTn = 0 | 20U, /**< DMA reset control */
+ kCRC_RST_SHIFT_RSTn = 0 | 21U, /**< CRC reset control */
+ kWWDT_RST_SHIFT_RSTn = 0 | 22U, /**< Watchdog timer reset control */
+ kRTC_RST_SHIFT_RSTn = 0 | 23U, /**< RTC reset control */
+ kMAILBOX_RST_SHIFT_RSTn = 0 | 26U, /**< Mailbox reset control */
+ kADC0_RST_SHIFT_RSTn = 0 | 27U, /**< ADC0 reset control */
+
+ kMRT_RST_SHIFT_RSTn = 65536 | 0U, /**< Multi-rate timer (MRT) reset control */
+ kOSTIMER0_RST_SHIFT_RSTn = 65536 | 1U, /**< OSTimer0 reset control */
+ kSCT0_RST_SHIFT_RSTn = 65536 | 2U, /**< SCTimer/PWM 0 (SCT0) reset control */
+ kMCAN_RST_SHIFT_RSTn = 65536 | 7U, /**< MCAN reset control */
+ kUTICK_RST_SHIFT_RSTn = 65536 | 10U, /**< Micro-tick timer reset control */
+ kFC0_RST_SHIFT_RSTn = 65536 | 11U, /**< Flexcomm Interface 0 reset control */
+ kFC1_RST_SHIFT_RSTn = 65536 | 12U, /**< Flexcomm Interface 1 reset control */
+ kFC2_RST_SHIFT_RSTn = 65536 | 13U, /**< Flexcomm Interface 2 reset control */
+ kFC3_RST_SHIFT_RSTn = 65536 | 14U, /**< Flexcomm Interface 3 reset control */
+ kFC4_RST_SHIFT_RSTn = 65536 | 15U, /**< Flexcomm Interface 4 reset control */
+ kFC5_RST_SHIFT_RSTn = 65536 | 16U, /**< Flexcomm Interface 5 reset control */
+ kFC6_RST_SHIFT_RSTn = 65536 | 17U, /**< Flexcomm Interface 6 reset control */
+ kFC7_RST_SHIFT_RSTn = 65536 | 18U, /**< Flexcomm Interface 7 reset control */
+ kCTIMER2_RST_SHIFT_RSTn = 65536 | 22U, /**< CTimer 2 reset control */
+ kUSB0D_RST_SHIFT_RSTn = 65536 | 25U, /**< USB0 Device reset control */
+ kCTIMER0_RST_SHIFT_RSTn = 65536 | 26U, /**< CTimer 0 reset control */
+ kCTIMER1_RST_SHIFT_RSTn = 65536 | 27U, /**< CTimer 1 reset control */
+ kEZHA_RST_SHIFT_RSTn = 65536 | 30U, /**< EZHA reset control */
+ kEZHB_RST_SHIFT_RSTn = 65536 | 31U, /**< EZHB reset control */
+
+ kDMA1_RST_SHIFT_RSTn = 131072 | 1U, /**< DMA1 reset control */
+ kCMP_RST_SHIFT_RSTn = 131072 | 2U, /**< CMP reset control */
+ kUSB1H_RST_SHIFT_RSTn = 131072 | 4U, /**< USBHS Host reset control */
+ kUSB1D_RST_SHIFT_RSTn = 131072 | 5U, /**< USBHS Device reset control */
+ kUSB1RAM_RST_SHIFT_RSTn = 131072 | 6U, /**< USB RAM reset control */
+ kUSB1_RST_SHIFT_RSTn = 131072 | 7U, /**< USBHS reset control */
+ kFREQME_RST_SHIFT_RSTn = 131072 | 8U, /**< FREQME reset control */
+ kCDOG_RST_SHIFT_RSTn = 131072 | 11U, /**< Code Watchdog reset control */
+ kRNG_RST_SHIFT_RSTn = 131072 | 13U, /**< RNG reset control */
+ kSYSCTL_RST_SHIFT_RSTn = 131072 | 15U, /**< SYSCTL reset control */
+ kUSB0HMR_RST_SHIFT_RSTn = 131072 | 16U, /**< USB0HMR reset control */
+ kUSB0HSL_RST_SHIFT_RSTn = 131072 | 17U, /**< USB0HSL reset control */
+ kHASHCRYPT_RST_SHIFT_RSTn = 131072 | 18U, /**< HASHCRYPT reset control */
+ kPLULUT_RST_SHIFT_RSTn = 131072 | 20U, /**< PLU LUT reset control */
+ kCTIMER3_RST_SHIFT_RSTn = 131072 | 21U, /**< CTimer 3 reset control */
+ kCTIMER4_RST_SHIFT_RSTn = 131072 | 22U, /**< CTimer 4 reset control */
+ kPUF_RST_SHIFT_RSTn = 131072 | 23U, /**< PUF reset control */
+ kCASPER_RST_SHIFT_RSTn = 131072 | 24U, /**< CASPER reset control */
+ kANALOGCTL_RST_SHIFT_RSTn = 131072 | 27U, /**< ANALOG_CTL reset control */
+ kHSLSPI_RST_SHIFT_RSTn = 131072 | 28U, /**< HS LSPI reset control */
+ kGPIOSEC_RST_SHIFT_RSTn = 131072 | 29U, /**< GPIO Secure reset control */
+ kGPIOSECINT_RST_SHIFT_RSTn = 131072 | 30U, /**< GPIO Secure int reset control */
+} SYSCON_RSTn_t;
+
+/** Array initializers with peripheral reset bits **/
+#define ADC_RSTS \
+ { \
+ kADC0_RST_SHIFT_RSTn \
+ } /* Reset bits for ADC peripheral */
+#define MCAN_RSTS \
+ { \
+ kMCAN_RST_SHIFT_RSTn \
+ } /* Reset bits for CAN peripheral */
+#define CRC_RSTS \
+ { \
+ kCRC_RST_SHIFT_RSTn \
+ } /* Reset bits for CRC peripheral */
+#define CTIMER_RSTS \
+ { \
+ kCTIMER0_RST_SHIFT_RSTn, kCTIMER1_RST_SHIFT_RSTn, kCTIMER2_RST_SHIFT_RSTn, kCTIMER3_RST_SHIFT_RSTn, \
+ kCTIMER4_RST_SHIFT_RSTn \
+ } /* Reset bits for CTIMER peripheral */
+#define DMA_RSTS_N \
+ { \
+ kDMA0_RST_SHIFT_RSTn, kDMA1_RST_SHIFT_RSTn \
+ } /* Reset bits for DMA peripheral */
+
+#define FLEXCOMM_RSTS \
+ { \
+ kFC0_RST_SHIFT_RSTn, kFC1_RST_SHIFT_RSTn, kFC2_RST_SHIFT_RSTn, kFC3_RST_SHIFT_RSTn, kFC4_RST_SHIFT_RSTn, \
+ kFC5_RST_SHIFT_RSTn, kFC6_RST_SHIFT_RSTn, kFC7_RST_SHIFT_RSTn, kHSLSPI_RST_SHIFT_RSTn \
+ } /* Reset bits for FLEXCOMM peripheral */
+#define GINT_RSTS \
+ { \
+ kGINT_RST_SHIFT_RSTn, kGINT_RST_SHIFT_RSTn \
+ } /* Reset bits for GINT peripheral. GINT0 & GINT1 share same slot */
+#define GPIO_RSTS_N \
+ { \
+ kGPIO0_RST_SHIFT_RSTn, kGPIO1_RST_SHIFT_RSTn \
+ } /* Reset bits for GPIO peripheral */
+#define INPUTMUX_RSTS \
+ { \
+ kMUX0_RST_SHIFT_RSTn \
+ } /* Reset bits for INPUTMUX peripheral */
+#define IOCON_RSTS \
+ { \
+ kIOCON_RST_SHIFT_RSTn \
+ } /* Reset bits for IOCON peripheral */
+#define FLASH_RSTS \
+ { \
+ kFLASH_RST_SHIFT_RSTn, kFMC_RST_SHIFT_RSTn \
+ } /* Reset bits for Flash peripheral */
+#define MRT_RSTS \
+ { \
+ kMRT_RST_SHIFT_RSTn \
+ } /* Reset bits for MRT peripheral */
+#define PINT_RSTS \
+ { \
+ kPINT_RST_SHIFT_RSTn \
+ } /* Reset bits for PINT peripheral */
+#define CDOG_RSTS \
+ { \
+ kCDOG_RST_SHIFT_RSTn \
+ } /* Reset bits for CDOG peripheral */
+#define RNG_RSTS \
+ { \
+ kRNG_RST_SHIFT_RSTn \
+ } /* Reset bits for RNG peripheral */
+#define SCT_RSTS \
+ { \
+ kSCT0_RST_SHIFT_RSTn \
+ } /* Reset bits for SCT peripheral */
+#define USB0D_RST \
+ { \
+ kUSB0D_RST_SHIFT_RSTn \
+ } /* Reset bits for USB0D peripheral */
+#define USB0HMR_RST \
+ { \
+ kUSB0HMR_RST_SHIFT_RSTn \
+ } /* Reset bits for USB0HMR peripheral */
+#define USB0HSL_RST \
+ { \
+ kUSB0HSL_RST_SHIFT_RSTn \
+ } /* Reset bits for USB0HSL peripheral */
+#define USB1H_RST \
+ { \
+ kUSB1H_RST_SHIFT_RSTn \
+ } /* Reset bits for USB1H peripheral */
+#define USB1D_RST \
+ { \
+ kUSB1D_RST_SHIFT_RSTn \
+ } /* Reset bits for USB1D peripheral */
+#define USB1RAM_RST \
+ { \
+ kUSB1RAM_RST_SHIFT_RSTn \
+ } /* Reset bits for USB1RAM peripheral */
+#define UTICK_RSTS \
+ { \
+ kUTICK_RST_SHIFT_RSTn \
+ } /* Reset bits for UTICK peripheral */
+#define WWDT_RSTS \
+ { \
+ kWWDT_RST_SHIFT_RSTn \
+ } /* Reset bits for WWDT peripheral */
+#define PLU_RSTS_N \
+ { \
+ kPLULUT_RST_SHIFT_RSTn \
+ } /* Reset bits for PLU peripheral */
+#define OSTIMER_RSTS \
+ { \
+ kOSTIMER0_RST_SHIFT_RSTn \
+ } /* Reset bits for OSTIMER peripheral */
+typedef SYSCON_RSTn_t reset_ip_name_t;
+
+/*******************************************************************************
+ * API
+ ******************************************************************************/
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+/*!
+ * @brief Assert reset to peripheral.
+ *
+ * Asserts reset signal to specified peripheral module.
+ *
+ * @param peripheral Assert reset to this peripheral. The enum argument contains encoding of reset register
+ * and reset bit position in the reset register.
+ */
+void RESET_SetPeripheralReset(reset_ip_name_t peripheral);
+
+/*!
+ * @brief Clear reset to peripheral.
+ *
+ * Clears reset signal to specified peripheral module, allows it to operate.
+ *
+ * @param peripheral Clear reset to this peripheral. The enum argument contains encoding of reset register
+ * and reset bit position in the reset register.
+ */
+void RESET_ClearPeripheralReset(reset_ip_name_t peripheral);
+
+/*!
+ * @brief Reset peripheral module.
+ *
+ * Reset peripheral module.
+ *
+ * @param peripheral Peripheral to reset. The enum argument contains encoding of reset register
+ * and reset bit position in the reset register.
+ */
+void RESET_PeripheralReset(reset_ip_name_t peripheral);
+
+#if defined(__cplusplus)
+}
+#endif
+
+/*! @} */
+
+#endif /* _FSL_RESET_H_ */
diff --git a/drivers/fsl_usart.c b/drivers/fsl_usart.c
new file mode 100644
index 0000000..03cb0c9
--- /dev/null
+++ b/drivers/fsl_usart.c
@@ -0,0 +1,1156 @@
+/*
+ * Copyright (c) 2016, Freescale Semiconductor, Inc.
+ * Copyright 2016-2021 NXP
+ * All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include "fsl_usart.h"
+#include "fsl_device_registers.h"
+#include "fsl_flexcomm.h"
+
+/*******************************************************************************
+ * Definitions
+ ******************************************************************************/
+
+/* Component ID definition, used by tools. */
+#ifndef FSL_COMPONENT_ID
+#define FSL_COMPONENT_ID "platform.drivers.flexcomm_usart"
+#endif
+
+/*!
+ * @brief Used for conversion from `flexcomm_usart_irq_handler_t` to `flexcomm_irq_handler_t`
+ */
+typedef union usart_to_flexcomm
+{
+ flexcomm_usart_irq_handler_t usart_master_handler;
+ flexcomm_irq_handler_t flexcomm_handler;
+} usart_to_flexcomm_t;
+
+enum
+{
+ kUSART_TxIdle, /* TX idle. */
+ kUSART_TxBusy, /* TX busy. */
+ kUSART_RxIdle, /* RX idle. */
+ kUSART_RxBusy /* RX busy. */
+};
+
+/*******************************************************************************
+ * Variables
+ ******************************************************************************/
+
+/*! @brief IRQ name array */
+static const IRQn_Type s_usartIRQ[] = USART_IRQS;
+
+/*! @brief Array to map USART instance number to base address. */
+static const uint32_t s_usartBaseAddrs[FSL_FEATURE_SOC_USART_COUNT] = USART_BASE_ADDRS;
+
+/*******************************************************************************
+ * Code
+ ******************************************************************************/
+
+/* Get the index corresponding to the USART */
+/*! brief Returns instance number for USART peripheral base address. */
+uint32_t USART_GetInstance(USART_Type *base)
+{
+ uint32_t i;
+
+ for (i = 0; i < (uint32_t)FSL_FEATURE_SOC_USART_COUNT; i++)
+ {
+ if ((uint32_t)base == s_usartBaseAddrs[i])
+ {
+ break;
+ }
+ }
+
+ assert(i < (uint32_t)FSL_FEATURE_SOC_USART_COUNT);
+ return i;
+}
+
+/*!
+ * brief Get the length of received data in RX ring buffer.
+ *
+ * param handle USART handle pointer.
+ * return Length of received data in RX ring buffer.
+ */
+size_t USART_TransferGetRxRingBufferLength(usart_handle_t *handle)
+{
+ size_t size;
+
+ /* Check arguments */
+ assert(NULL != handle);
+ uint16_t rxRingBufferHead = handle->rxRingBufferHead;
+ uint16_t rxRingBufferTail = handle->rxRingBufferTail;
+
+ if (rxRingBufferTail > rxRingBufferHead)
+ {
+ size = (size_t)rxRingBufferHead + handle->rxRingBufferSize - (size_t)rxRingBufferTail;
+ }
+ else
+ {
+ size = (size_t)rxRingBufferHead - (size_t)rxRingBufferTail;
+ }
+ return size;
+}
+
+static bool USART_TransferIsRxRingBufferFull(usart_handle_t *handle)
+{
+ bool full;
+
+ /* Check arguments */
+ assert(NULL != handle);
+
+ if (USART_TransferGetRxRingBufferLength(handle) == (handle->rxRingBufferSize - 1U))
+ {
+ full = true;
+ }
+ else
+ {
+ full = false;
+ }
+ return full;
+}
+
+/*!
+ * brief Sets up the RX ring buffer.
+ *
+ * This function sets up the RX ring buffer to a specific USART handle.
+ *
+ * When the RX ring buffer is used, data received are stored into the ring buffer even when the
+ * user doesn't call the USART_TransferReceiveNonBlocking() API. If there is already data received
+ * in the ring buffer, the user can get the received data from the ring buffer directly.
+ *
+ * note When using the RX ring buffer, one byte is reserved for internal use. In other
+ * words, if p ringBufferSize is 32, then only 31 bytes are used for saving data.
+ *
+ * param base USART peripheral base address.
+ * param handle USART handle pointer.
+ * param ringBuffer Start address of the ring buffer for background receiving. Pass NULL to disable the ring buffer.
+ * param ringBufferSize size of the ring buffer.
+ */
+void USART_TransferStartRingBuffer(USART_Type *base, usart_handle_t *handle, uint8_t *ringBuffer, size_t ringBufferSize)
+{
+ /* Check arguments */
+ assert(NULL != base);
+ assert(NULL != handle);
+ assert(NULL != ringBuffer);
+
+ /* Setup the ringbuffer address */
+ handle->rxRingBuffer = ringBuffer;
+ handle->rxRingBufferSize = ringBufferSize;
+ handle->rxRingBufferHead = 0U;
+ handle->rxRingBufferTail = 0U;
+ /* ring buffer is ready we can start receiving data */
+ base->FIFOINTENSET = USART_FIFOINTENSET_RXLVL_MASK | USART_FIFOINTENSET_RXERR_MASK;
+}
+
+/*!
+ * brief Aborts the background transfer and uninstalls the ring buffer.
+ *
+ * This function aborts the background transfer and uninstalls the ring buffer.
+ *
+ * param base USART peripheral base address.
+ * param handle USART handle pointer.
+ */
+void USART_TransferStopRingBuffer(USART_Type *base, usart_handle_t *handle)
+{
+ /* Check arguments */
+ assert(NULL != base);
+ assert(NULL != handle);
+
+ if (handle->rxState == (uint8_t)kUSART_RxIdle)
+ {
+ base->FIFOINTENCLR = USART_FIFOINTENCLR_RXLVL_MASK | USART_FIFOINTENCLR_RXERR_MASK;
+ }
+ handle->rxRingBuffer = NULL;
+ handle->rxRingBufferSize = 0U;
+ handle->rxRingBufferHead = 0U;
+ handle->rxRingBufferTail = 0U;
+}
+
+/*!
+ * brief Initializes a USART instance with user configuration structure and peripheral clock.
+ *
+ * This function configures the USART module with the user-defined settings. The user can configure the configuration
+ * structure and also get the default configuration by using the USART_GetDefaultConfig() function.
+ * Example below shows how to use this API to configure USART.
+ * code
+ * usart_config_t usartConfig;
+ * usartConfig.baudRate_Bps = 115200U;
+ * usartConfig.parityMode = kUSART_ParityDisabled;
+ * usartConfig.stopBitCount = kUSART_OneStopBit;
+ * USART_Init(USART1, &usartConfig, 20000000U);
+ * endcode
+ *
+ * param base USART peripheral base address.
+ * param config Pointer to user-defined configuration structure.
+ * param srcClock_Hz USART clock source frequency in HZ.
+ * retval kStatus_USART_BaudrateNotSupport Baudrate is not support in current clock source.
+ * retval kStatus_InvalidArgument USART base address is not valid
+ * retval kStatus_Success Status USART initialize succeed
+ */
+status_t USART_Init(USART_Type *base, const usart_config_t *config, uint32_t srcClock_Hz)
+{
+ int result;
+
+ /* check arguments */
+ assert(!((NULL == base) || (NULL == config) || (0U == srcClock_Hz)));
+ if ((NULL == base) || (NULL == config) || (0U == srcClock_Hz))
+ {
+ return kStatus_InvalidArgument;
+ }
+
+ /* initialize flexcomm to USART mode */
+ result = FLEXCOMM_Init(base, FLEXCOMM_PERIPH_USART);
+ if (kStatus_Success != result)
+ {
+ return result;
+ }
+
+ if (config->enableTx)
+ {
+ /* empty and enable txFIFO */
+ base->FIFOCFG |= USART_FIFOCFG_EMPTYTX_MASK | USART_FIFOCFG_ENABLETX_MASK;
+ /* setup trigger level */
+ base->FIFOTRIG &= ~(USART_FIFOTRIG_TXLVL_MASK);
+ base->FIFOTRIG |= USART_FIFOTRIG_TXLVL(config->txWatermark);
+ /* enable trigger interrupt */
+ base->FIFOTRIG |= USART_FIFOTRIG_TXLVLENA_MASK;
+ }
+
+ /* empty and enable rxFIFO */
+ if (config->enableRx)
+ {
+ base->FIFOCFG |= USART_FIFOCFG_EMPTYRX_MASK | USART_FIFOCFG_ENABLERX_MASK;
+ /* setup trigger level */
+ base->FIFOTRIG &= ~(USART_FIFOTRIG_RXLVL_MASK);
+ base->FIFOTRIG |= USART_FIFOTRIG_RXLVL(config->rxWatermark);
+ /* enable trigger interrupt */
+ base->FIFOTRIG |= USART_FIFOTRIG_RXLVLENA_MASK;
+ }
+ /* setup configuration and enable USART */
+ base->CFG = USART_CFG_PARITYSEL(config->parityMode) | USART_CFG_STOPLEN(config->stopBitCount) |
+ USART_CFG_DATALEN(config->bitCountPerChar) | USART_CFG_LOOP(config->loopback) |
+ USART_CFG_SYNCEN((uint32_t)config->syncMode >> 1) | USART_CFG_SYNCMST((uint8_t)config->syncMode) |
+ USART_CFG_CLKPOL(config->clockPolarity) | USART_CFG_MODE32K(config->enableMode32k) |
+ USART_CFG_CTSEN(config->enableHardwareFlowControl) | USART_CFG_ENABLE_MASK;
+
+ /* Setup baudrate */
+ if (config->enableMode32k)
+ {
+ if ((9600U % config->baudRate_Bps) == 0U)
+ {
+ base->BRG = 9600U / config->baudRate_Bps;
+ }
+ else
+ {
+ return kStatus_USART_BaudrateNotSupport;
+ }
+ }
+ else
+ {
+ result = USART_SetBaudRate(base, config->baudRate_Bps, srcClock_Hz);
+ if (kStatus_Success != result)
+ {
+ return result;
+ }
+ }
+ /* Setting continuous Clock configuration. used for synchronous mode. */
+ USART_EnableContinuousSCLK(base, config->enableContinuousSCLK);
+
+ return kStatus_Success;
+}
+
+/*!
+ * brief Deinitializes a USART instance.
+ *
+ * This function waits for TX complete, disables TX and RX, and disables the USART clock.
+ *
+ * param base USART peripheral base address.
+ */
+void USART_Deinit(USART_Type *base)
+{
+ /* Check arguments */
+ assert(NULL != base);
+ while (0U == (base->STAT & USART_STAT_TXIDLE_MASK))
+ {
+ }
+ /* Disable interrupts, disable dma requests, disable peripheral */
+ base->FIFOINTENCLR = USART_FIFOINTENCLR_TXERR_MASK | USART_FIFOINTENCLR_RXERR_MASK | USART_FIFOINTENCLR_TXLVL_MASK |
+ USART_FIFOINTENCLR_RXLVL_MASK;
+ base->FIFOCFG &= ~(USART_FIFOCFG_DMATX_MASK | USART_FIFOCFG_DMARX_MASK);
+ base->CFG &= ~(USART_CFG_ENABLE_MASK);
+}
+
+/*!
+ * brief Gets the default configuration structure.
+ *
+ * This function initializes the USART configuration structure to a default value. The default
+ * values are:
+ * usartConfig->baudRate_Bps = 115200U;
+ * usartConfig->parityMode = kUSART_ParityDisabled;
+ * usartConfig->stopBitCount = kUSART_OneStopBit;
+ * usartConfig->bitCountPerChar = kUSART_8BitsPerChar;
+ * usartConfig->loopback = false;
+ * usartConfig->enableTx = false;
+ * usartConfig->enableRx = false;
+ *
+ * param config Pointer to configuration structure.
+ */
+void USART_GetDefaultConfig(usart_config_t *config)
+{
+ /* Check arguments */
+ assert(NULL != config);
+
+ /* Initializes the configure structure to zero. */
+ (void)memset(config, 0, sizeof(*config));
+
+ /* Set always all members ! */
+ config->baudRate_Bps = 115200U;
+ config->parityMode = kUSART_ParityDisabled;
+ config->stopBitCount = kUSART_OneStopBit;
+ config->bitCountPerChar = kUSART_8BitsPerChar;
+ config->loopback = false;
+ config->enableRx = false;
+ config->enableTx = false;
+ config->enableMode32k = false;
+ config->txWatermark = kUSART_TxFifo0;
+ config->rxWatermark = kUSART_RxFifo1;
+ config->syncMode = kUSART_SyncModeDisabled;
+ config->enableContinuousSCLK = false;
+ config->clockPolarity = kUSART_RxSampleOnFallingEdge;
+ config->enableHardwareFlowControl = false;
+}
+
+/*!
+ * brief Sets the USART instance baud rate.
+ *
+ * This function configures the USART module baud rate. This function is used to update
+ * the USART module baud rate after the USART module is initialized by the USART_Init.
+ * code
+ * USART_SetBaudRate(USART1, 115200U, 20000000U);
+ * endcode
+ *
+ * param base USART peripheral base address.
+ * param baudrate_Bps USART baudrate to be set.
+ * param srcClock_Hz USART clock source frequency in HZ.
+ * retval kStatus_USART_BaudrateNotSupport Baudrate is not support in current clock source.
+ * retval kStatus_Success Set baudrate succeed.
+ * retval kStatus_InvalidArgument One or more arguments are invalid.
+ */
+status_t USART_SetBaudRate(USART_Type *base, uint32_t baudrate_Bps, uint32_t srcClock_Hz)
+{
+ uint32_t best_diff = (uint32_t)-1, best_osrval = 0xf, best_brgval = (uint32_t)-1;
+ uint32_t osrval, brgval, diff, baudrate;
+
+ /* check arguments */
+ assert(!((NULL == base) || (0U == baudrate_Bps) || (0U == srcClock_Hz)));
+ if ((NULL == base) || (0U == baudrate_Bps) || (0U == srcClock_Hz))
+ {
+ return kStatus_InvalidArgument;
+ }
+
+ /* If synchronous master mode is enabled, only configure the BRG value. */
+ if ((base->CFG & USART_CFG_SYNCEN_MASK) != 0U)
+ {
+ if ((base->CFG & USART_CFG_SYNCMST_MASK) != 0U)
+ {
+ brgval = srcClock_Hz / baudrate_Bps;
+ base->BRG = brgval - 1U;
+ }
+ }
+ else
+ {
+ /*
+ * Smaller values of OSR can make the sampling position within a data bit less accurate and may
+ * potentially cause more noise errors or incorrect data.
+ */
+ for (osrval = best_osrval; osrval >= 8U; osrval--)
+ {
+ brgval = (((srcClock_Hz * 10U) / ((osrval + 1U) * baudrate_Bps)) - 5U) / 10U;
+ if (brgval > 0xFFFFU)
+ {
+ continue;
+ }
+ baudrate = srcClock_Hz / ((osrval + 1U) * (brgval + 1U));
+ diff = (baudrate_Bps < baudrate) ? (baudrate - baudrate_Bps) : (baudrate_Bps - baudrate);
+ if (diff < best_diff)
+ {
+ best_diff = diff;
+ best_osrval = osrval;
+ best_brgval = brgval;
+ }
+ }
+
+ /* Check to see if actual baud rate is within 3% of desired baud rate
+ * based on the best calculated OSR and BRG value */
+ baudrate = srcClock_Hz / ((best_osrval + 1U) * (best_brgval + 1U));
+ diff = (baudrate_Bps < baudrate) ? (baudrate - baudrate_Bps) : (baudrate_Bps - baudrate);
+ if (diff > ((baudrate_Bps / 100U) * 3U))
+ {
+ return kStatus_USART_BaudrateNotSupport;
+ }
+
+ /* value over range */
+ if (best_brgval > 0xFFFFU)
+ {
+ return kStatus_USART_BaudrateNotSupport;
+ }
+
+ base->OSR = best_osrval;
+ base->BRG = best_brgval;
+ }
+
+ return kStatus_Success;
+}
+
+/*!
+ * brief Enable 32 kHz mode which USART uses clock from the RTC oscillator as the clock source.
+ *
+ * Please note that in order to use a 32 kHz clock to operate USART properly, the RTC oscillator
+ * and its 32 kHz output must be manully enabled by user, by calling RTC_Init and setting
+ * SYSCON_RTCOSCCTRL_EN bit to 1.
+ * And in 32kHz clocking mode the USART can only work at 9600 baudrate or at the baudrate that
+ * 9600 can evenly divide, eg: 4800, 3200.
+ *
+ * param base USART peripheral base address.
+ * param baudRate_Bps USART baudrate to be set..
+ * param enableMode32k true is 32k mode, false is normal mode.
+ * param srcClock_Hz USART clock source frequency in HZ.
+ * retval kStatus_USART_BaudrateNotSupport Baudrate is not support in current clock source.
+ * retval kStatus_Success Set baudrate succeed.
+ * retval kStatus_InvalidArgument One or more arguments are invalid.
+ */
+status_t USART_Enable32kMode(USART_Type *base, uint32_t baudRate_Bps, bool enableMode32k, uint32_t srcClock_Hz)
+{
+ status_t result = kStatus_Success;
+ base->CFG &= ~(USART_CFG_ENABLE_MASK);
+ if (enableMode32k)
+ {
+ base->CFG |= USART_CFG_MODE32K_MASK;
+ if ((9600U % baudRate_Bps) == 0U)
+ {
+ base->BRG = 9600U / baudRate_Bps - 1U;
+ }
+ else
+ {
+ return kStatus_USART_BaudrateNotSupport;
+ }
+ }
+ else
+ {
+ base->CFG &= ~(USART_CFG_MODE32K_MASK);
+ result = USART_SetBaudRate(base, baudRate_Bps, srcClock_Hz);
+ if (kStatus_Success != result)
+ {
+ return result;
+ }
+ }
+ base->CFG |= USART_CFG_ENABLE_MASK;
+ return result;
+}
+
+/*!
+ * brief Enable 9-bit data mode for USART.
+ *
+ * This function set the 9-bit mode for USART module. The 9th bit is not used for parity thus can be modified by user.
+ *
+ * param base USART peripheral base address.
+ * param enable true to enable, false to disable.
+ */
+void USART_Enable9bitMode(USART_Type *base, bool enable)
+{
+ assert(base != NULL);
+
+ uint32_t temp = 0U;
+
+ if (enable)
+ {
+ /* Set USART 9-bit mode, disable parity. */
+ temp = base->CFG & ~((uint32_t)USART_CFG_DATALEN_MASK | (uint32_t)USART_CFG_PARITYSEL_MASK);
+ temp |= (uint32_t)USART_CFG_DATALEN(0x2U);
+ base->CFG = temp;
+ }
+ else
+ {
+ /* Set USART to 8-bit mode. */
+ base->CFG &= ~((uint32_t)USART_CFG_DATALEN_MASK);
+ base->CFG |= (uint32_t)USART_CFG_DATALEN(0x1U);
+ }
+}
+
+/*!
+ * brief Transmit an address frame in 9-bit data mode.
+ *
+ * param base USART peripheral base address.
+ * param address USART slave address.
+ */
+void USART_SendAddress(USART_Type *base, uint8_t address)
+{
+ assert(base != NULL);
+ base->FIFOWR = ((uint32_t)address | 0x100UL);
+}
+
+/*!
+ * brief Writes to the TX register using a blocking method.
+ *
+ * This function polls the TX register, waits for the TX register to be empty or for the TX FIFO
+ * to have room and writes data to the TX buffer.
+ *
+ * param base USART peripheral base address.
+ * param data Start address of the data to write.
+ * param length Size of the data to write.
+ * retval kStatus_USART_Timeout Transmission timed out and was aborted.
+ * retval kStatus_InvalidArgument Invalid argument.
+ * retval kStatus_Success Successfully wrote all data.
+ */
+status_t USART_WriteBlocking(USART_Type *base, const uint8_t *data, size_t length)
+{
+ /* Check arguments */
+ assert(!((NULL == base) || (NULL == data)));
+#if UART_RETRY_TIMES
+ uint32_t waitTimes;
+#endif
+ if ((NULL == base) || (NULL == data))
+ {
+ return kStatus_InvalidArgument;
+ }
+ /* Check whether txFIFO is enabled */
+ if (0U == (base->FIFOCFG & USART_FIFOCFG_ENABLETX_MASK))
+ {
+ return kStatus_InvalidArgument;
+ }
+ for (; length > 0U; length--)
+ {
+ /* Loop until txFIFO get some space for new data */
+#if UART_RETRY_TIMES
+ waitTimes = UART_RETRY_TIMES;
+ while ((0U == (base->FIFOSTAT & USART_FIFOSTAT_TXNOTFULL_MASK)) && (--waitTimes != 0U))
+#else
+ while (0U == (base->FIFOSTAT & USART_FIFOSTAT_TXNOTFULL_MASK))
+#endif
+ {
+ }
+#if UART_RETRY_TIMES
+ if (0U == waitTimes)
+ {
+ return kStatus_USART_Timeout;
+ }
+#endif
+ base->FIFOWR = *data;
+ data++;
+ }
+ /* Wait to finish transfer */
+#if UART_RETRY_TIMES
+ waitTimes = UART_RETRY_TIMES;
+ while ((0U == (base->STAT & USART_STAT_TXIDLE_MASK)) && (--waitTimes != 0U))
+#else
+ while (0U == (base->STAT & USART_STAT_TXIDLE_MASK))
+#endif
+ {
+ }
+#if UART_RETRY_TIMES
+ if (0U == waitTimes)
+ {
+ return kStatus_USART_Timeout;
+ }
+#endif
+ return kStatus_Success;
+}
+
+/*!
+ * brief Read RX data register using a blocking method.
+ *
+ * This function polls the RX register, waits for the RX register to be full or for RX FIFO to
+ * have data and read data from the TX register.
+ *
+ * param base USART peripheral base address.
+ * param data Start address of the buffer to store the received data.
+ * param length Size of the buffer.
+ * retval kStatus_USART_FramingError Receiver overrun happened while receiving data.
+ * retval kStatus_USART_ParityError Noise error happened while receiving data.
+ * retval kStatus_USART_NoiseError Framing error happened while receiving data.
+ * retval kStatus_USART_RxError Overflow or underflow rxFIFO happened.
+ * retval kStatus_USART_Timeout Transmission timed out and was aborted.
+ * retval kStatus_Success Successfully received all data.
+ */
+status_t USART_ReadBlocking(USART_Type *base, uint8_t *data, size_t length)
+{
+ uint32_t statusFlag;
+ status_t status = kStatus_Success;
+#if UART_RETRY_TIMES
+ uint32_t waitTimes;
+#endif
+
+ /* check arguments */
+ assert(!((NULL == base) || (NULL == data)));
+ if ((NULL == base) || (NULL == data))
+ {
+ return kStatus_InvalidArgument;
+ }
+
+ /* Check whether rxFIFO is enabled */
+ if ((base->FIFOCFG & USART_FIFOCFG_ENABLERX_MASK) == 0U)
+ {
+ return kStatus_Fail;
+ }
+ for (; length > 0U; length--)
+ {
+ /* loop until rxFIFO have some data to read */
+#if UART_RETRY_TIMES
+ waitTimes = UART_RETRY_TIMES;
+ while (((base->FIFOSTAT & USART_FIFOSTAT_RXNOTEMPTY_MASK) == 0U) && (--waitTimes != 0U))
+#else
+ while ((base->FIFOSTAT & USART_FIFOSTAT_RXNOTEMPTY_MASK) == 0U)
+#endif
+ {
+ }
+#if UART_RETRY_TIMES
+ if (waitTimes == 0U)
+ {
+ status = kStatus_USART_Timeout;
+ break;
+ }
+#endif
+ /* check rxFIFO statusFlag */
+ if ((base->FIFOSTAT & USART_FIFOSTAT_RXERR_MASK) != 0U)
+ {
+ base->FIFOCFG |= USART_FIFOCFG_EMPTYRX_MASK;
+ base->FIFOSTAT |= USART_FIFOSTAT_RXERR_MASK;
+ status = kStatus_USART_RxError;
+ break;
+ }
+ /* check receive statusFlag */
+ statusFlag = base->STAT;
+ /* Clear all status flags */
+ base->STAT |= statusFlag;
+ if ((statusFlag & USART_STAT_PARITYERRINT_MASK) != 0U)
+ {
+ status = kStatus_USART_ParityError;
+ }
+ if ((statusFlag & USART_STAT_FRAMERRINT_MASK) != 0U)
+ {
+ status = kStatus_USART_FramingError;
+ }
+ if ((statusFlag & USART_STAT_RXNOISEINT_MASK) != 0U)
+ {
+ status = kStatus_USART_NoiseError;
+ }
+
+ if (kStatus_Success == status)
+ {
+ *data = (uint8_t)base->FIFORD;
+ data++;
+ }
+ else
+ {
+ break;
+ }
+ }
+ return status;
+}
+
+/*!
+ * brief Initializes the USART handle.
+ *
+ * This function initializes the USART handle which can be used for other USART
+ * transactional APIs. Usually, for a specified USART instance,
+ * call this API once to get the initialized handle.
+ *
+ * param base USART peripheral base address.
+ * param handle USART handle pointer.
+ * param callback The callback function.
+ * param userData The parameter of the callback function.
+ */
+status_t USART_TransferCreateHandle(USART_Type *base,
+ usart_handle_t *handle,
+ usart_transfer_callback_t callback,
+ void *userData)
+{
+ /* Check 'base' */
+ assert(!((NULL == base) || (NULL == handle)));
+
+ uint32_t instance = 0;
+ usart_to_flexcomm_t handler;
+ handler.usart_master_handler = USART_TransferHandleIRQ;
+
+ if ((NULL == base) || (NULL == handle))
+ {
+ return kStatus_InvalidArgument;
+ }
+
+ instance = USART_GetInstance(base);
+
+ (void)memset(handle, 0, sizeof(*handle));
+ /* Set the TX/RX state. */
+ handle->rxState = (uint8_t)kUSART_RxIdle;
+ handle->txState = (uint8_t)kUSART_TxIdle;
+ /* Set the callback and user data. */
+ handle->callback = callback;
+ handle->userData = userData;
+ handle->rxWatermark = (uint8_t)USART_FIFOTRIG_RXLVL_GET(base);
+ handle->txWatermark = (uint8_t)USART_FIFOTRIG_TXLVL_GET(base);
+
+ FLEXCOMM_SetIRQHandler(base, handler.flexcomm_handler, handle);
+
+ /* Enable interrupt in NVIC. */
+ (void)EnableIRQ(s_usartIRQ[instance]);
+
+ return kStatus_Success;
+}
+
+/*!
+ * brief Transmits a buffer of data using the interrupt method.
+ *
+ * This function sends data using an interrupt method. This is a non-blocking function, which
+ * returns directly without waiting for all data to be written to the TX register. When
+ * all data is written to the TX register in the IRQ handler, the USART driver calls the callback
+ * function and passes the ref kStatus_USART_TxIdle as status parameter.
+ *
+ * param base USART peripheral base address.
+ * param handle USART handle pointer.
+ * param xfer USART transfer structure. See #usart_transfer_t.
+ * retval kStatus_Success Successfully start the data transmission.
+ * retval kStatus_USART_TxBusy Previous transmission still not finished, data not all written to TX register yet.
+ * retval kStatus_InvalidArgument Invalid argument.
+ */
+status_t USART_TransferSendNonBlocking(USART_Type *base, usart_handle_t *handle, usart_transfer_t *xfer)
+{
+ /* Check arguments */
+ assert(!((NULL == base) || (NULL == handle) || (NULL == xfer)));
+ if ((NULL == base) || (NULL == handle) || (NULL == xfer))
+ {
+ return kStatus_InvalidArgument;
+ }
+ /* Check xfer members */
+ assert(!((0U == xfer->dataSize) || (NULL == xfer->txData)));
+ if ((0U == xfer->dataSize) || (NULL == xfer->txData))
+ {
+ return kStatus_InvalidArgument;
+ }
+
+ /* Return error if current TX busy. */
+ if ((uint8_t)kUSART_TxBusy == handle->txState)
+ {
+ return kStatus_USART_TxBusy;
+ }
+ else
+ {
+ /* Disable IRQ when configuring transfer handle, in case interrupt occurs during the process and messes up the
+ * handle value. */
+ uint32_t interruptMask = USART_GetEnabledInterrupts(base);
+ USART_DisableInterrupts(base, interruptMask);
+ handle->txData = xfer->txData;
+ handle->txDataSize = xfer->dataSize;
+ handle->txDataSizeAll = xfer->dataSize;
+ handle->txState = (uint8_t)kUSART_TxBusy;
+ /* Enable transmiter interrupt and the previously disabled interrupt. */
+ USART_EnableInterrupts(base, interruptMask | (uint32_t)kUSART_TxLevelInterruptEnable);
+ }
+ return kStatus_Success;
+}
+
+/*!
+ * brief Aborts the interrupt-driven data transmit.
+ *
+ * This function aborts the interrupt driven data sending. The user can get the remainBtyes to find out
+ * how many bytes are still not sent out.
+ *
+ * param base USART peripheral base address.
+ * param handle USART handle pointer.
+ */
+void USART_TransferAbortSend(USART_Type *base, usart_handle_t *handle)
+{
+ assert(NULL != handle);
+
+ /* Disable interrupts */
+ USART_DisableInterrupts(base, (uint32_t)kUSART_TxLevelInterruptEnable);
+ /* Empty txFIFO */
+ base->FIFOCFG |= USART_FIFOCFG_EMPTYTX_MASK;
+
+ handle->txDataSize = 0U;
+ handle->txState = (uint8_t)kUSART_TxIdle;
+}
+
+/*!
+ * brief Get the number of bytes that have been sent out to bus.
+ *
+ * This function gets the number of bytes that have been sent out to bus by interrupt method.
+ *
+ * param base USART peripheral base address.
+ * param handle USART handle pointer.
+ * param count Send bytes count.
+ * retval kStatus_NoTransferInProgress No send in progress.
+ * retval kStatus_InvalidArgument Parameter is invalid.
+ * retval kStatus_Success Get successfully through the parameter \p count;
+ */
+status_t USART_TransferGetSendCount(USART_Type *base, usart_handle_t *handle, uint32_t *count)
+{
+ assert(NULL != handle);
+ assert(NULL != count);
+
+ if ((uint8_t)kUSART_TxIdle == handle->txState)
+ {
+ return kStatus_NoTransferInProgress;
+ }
+
+ *count = handle->txDataSizeAll - handle->txDataSize -
+ ((base->FIFOSTAT & USART_FIFOSTAT_TXLVL_MASK) >> USART_FIFOSTAT_TXLVL_SHIFT);
+
+ return kStatus_Success;
+}
+
+/*!
+ * brief Receives a buffer of data using an interrupt method.
+ *
+ * This function receives data using an interrupt method. This is a non-blocking function, which
+ * returns without waiting for all data to be received.
+ * If the RX ring buffer is used and not empty, the data in the ring buffer is copied and
+ * the parameter p receivedBytes shows how many bytes are copied from the ring buffer.
+ * After copying, if the data in the ring buffer is not enough to read, the receive
+ * request is saved by the USART driver. When the new data arrives, the receive request
+ * is serviced first. When all data is received, the USART driver notifies the upper layer
+ * through a callback function and passes the status parameter ref kStatus_USART_RxIdle.
+ * For example, the upper layer needs 10 bytes but there are only 5 bytes in the ring buffer.
+ * The 5 bytes are copied to the xfer->data and this function returns with the
+ * parameter p receivedBytes set to 5. For the left 5 bytes, newly arrived data is
+ * saved from the xfer->data[5]. When 5 bytes are received, the USART driver notifies the upper layer.
+ * If the RX ring buffer is not enabled, this function enables the RX and RX interrupt
+ * to receive data to the xfer->data. When all data is received, the upper layer is notified.
+ *
+ * param base USART peripheral base address.
+ * param handle USART handle pointer.
+ * param xfer USART transfer structure, see #usart_transfer_t.
+ * param receivedBytes Bytes received from the ring buffer directly.
+ * retval kStatus_Success Successfully queue the transfer into transmit queue.
+ * retval kStatus_USART_RxBusy Previous receive request is not finished.
+ * retval kStatus_InvalidArgument Invalid argument.
+ */
+status_t USART_TransferReceiveNonBlocking(USART_Type *base,
+ usart_handle_t *handle,
+ usart_transfer_t *xfer,
+ size_t *receivedBytes)
+{
+ uint32_t i;
+ /* How many bytes to copy from ring buffer to user memory. */
+ size_t bytesToCopy = 0U;
+ /* How many bytes to receive. */
+ size_t bytesToReceive;
+ /* How many bytes currently have received. */
+ size_t bytesCurrentReceived;
+ uint32_t interruptMask = 0U;
+
+ /* Check arguments */
+ assert(!((NULL == base) || (NULL == handle) || (NULL == xfer)));
+ if ((NULL == base) || (NULL == handle) || (NULL == xfer))
+ {
+ return kStatus_InvalidArgument;
+ }
+ /* Check xfer members */
+ assert(!((0U == xfer->dataSize) || (NULL == xfer->rxData)));
+ if ((0U == xfer->dataSize) || (NULL == xfer->rxData))
+ {
+ return kStatus_InvalidArgument;
+ }
+
+ /* Enable address detect when address match is enabled. */
+ if ((base->CFG & (uint32_t)USART_CFG_AUTOADDR_MASK) != 0U)
+ {
+ base->CTL |= (uint32_t)USART_CTL_ADDRDET_MASK;
+ }
+
+ /* How to get data:
+ 1. If RX ring buffer is not enabled, then save xfer->data and xfer->dataSize
+ to uart handle, enable interrupt to store received data to xfer->data. When
+ all data received, trigger callback.
+ 2. If RX ring buffer is enabled and not empty, get data from ring buffer first.
+ If there are enough data in ring buffer, copy them to xfer->data and return.
+ If there are not enough data in ring buffer, copy all of them to xfer->data,
+ save the xfer->data remained empty space to uart handle, receive data
+ to this empty space and trigger callback when finished. */
+ if ((uint8_t)kUSART_RxBusy == handle->rxState)
+ {
+ return kStatus_USART_RxBusy;
+ }
+ else
+ {
+ bytesToReceive = xfer->dataSize;
+ bytesCurrentReceived = 0U;
+ /* If RX ring buffer is used. */
+ if (handle->rxRingBuffer != NULL)
+ {
+ /* Disable IRQ, protect ring buffer. */
+ interruptMask = USART_GetEnabledInterrupts(base);
+ USART_DisableInterrupts(base, interruptMask);
+
+ /* How many bytes in RX ring buffer currently. */
+ bytesToCopy = USART_TransferGetRxRingBufferLength(handle);
+ if (bytesToCopy != 0U)
+ {
+ bytesToCopy = MIN(bytesToReceive, bytesToCopy);
+ bytesToReceive -= bytesToCopy;
+ /* Copy data from ring buffer to user memory. */
+ for (i = 0U; i < bytesToCopy; i++)
+ {
+ xfer->rxData[bytesCurrentReceived++] = handle->rxRingBuffer[handle->rxRingBufferTail];
+ /* Wrap to 0. Not use modulo (%) because it might be large and slow. */
+ if ((size_t)handle->rxRingBufferTail + 1U == handle->rxRingBufferSize)
+ {
+ handle->rxRingBufferTail = 0U;
+ }
+ else
+ {
+ handle->rxRingBufferTail++;
+ }
+ }
+ }
+ /* If ring buffer does not have enough data, still need to read more data. */
+ if (bytesToReceive != 0U)
+ {
+ /* No data in ring buffer, save the request to UART handle. */
+ handle->rxData = xfer->rxData + bytesCurrentReceived;
+ handle->rxDataSize = bytesToReceive;
+ handle->rxDataSizeAll = xfer->dataSize;
+ handle->rxState = (uint8_t)kUSART_RxBusy;
+ }
+ /* Re-enable IRQ. */
+ USART_EnableInterrupts(base, interruptMask);
+ /* Call user callback since all data are received. */
+ if (0U == bytesToReceive)
+ {
+ if (handle->callback != NULL)
+ {
+ handle->callback(base, handle, kStatus_USART_RxIdle, handle->userData);
+ }
+ }
+ }
+ /* Ring buffer not used. */
+ else
+ {
+ /* Disable IRQ when configuring transfer handle, in case interrupt occurs during the process and messes up
+ * the handle value. */
+ interruptMask = USART_GetEnabledInterrupts(base);
+ USART_DisableInterrupts(base, interruptMask);
+ handle->rxData = xfer->rxData + bytesCurrentReceived;
+ handle->rxDataSize = bytesToReceive;
+ handle->rxDataSizeAll = bytesToReceive;
+ handle->rxState = (uint8_t)kUSART_RxBusy;
+
+ /* Enable RX interrupt. */
+ base->FIFOINTENSET = USART_FIFOINTENSET_RXLVL_MASK;
+ /* Re-enable IRQ. */
+ USART_EnableInterrupts(base, interruptMask);
+ }
+ /* Return the how many bytes have read. */
+ if (receivedBytes != NULL)
+ {
+ *receivedBytes = bytesCurrentReceived;
+ }
+ }
+ return kStatus_Success;
+}
+
+/*!
+ * brief Aborts the interrupt-driven data receiving.
+ *
+ * This function aborts the interrupt-driven data receiving. The user can get the remainBytes to find out
+ * how many bytes not received yet.
+ *
+ * param base USART peripheral base address.
+ * param handle USART handle pointer.
+ */
+void USART_TransferAbortReceive(USART_Type *base, usart_handle_t *handle)
+{
+ assert(NULL != handle);
+
+ /* Only abort the receive to handle->rxData, the RX ring buffer is still working. */
+ if (NULL == handle->rxRingBuffer)
+ {
+ /* Disable interrupts */
+ USART_DisableInterrupts(base, (uint32_t)kUSART_RxLevelInterruptEnable);
+ /* Empty rxFIFO */
+ base->FIFOCFG |= USART_FIFOCFG_EMPTYRX_MASK;
+ }
+
+ handle->rxDataSize = 0U;
+ handle->rxState = (uint8_t)kUSART_RxIdle;
+}
+
+/*!
+ * brief Get the number of bytes that have been received.
+ *
+ * This function gets the number of bytes that have been received.
+ *
+ * param base USART peripheral base address.
+ * param handle USART handle pointer.
+ * param count Receive bytes count.
+ * retval kStatus_NoTransferInProgress No receive in progress.
+ * retval kStatus_InvalidArgument Parameter is invalid.
+ * retval kStatus_Success Get successfully through the parameter \p count;
+ */
+status_t USART_TransferGetReceiveCount(USART_Type *base, usart_handle_t *handle, uint32_t *count)
+{
+ assert(NULL != handle);
+ assert(NULL != count);
+
+ if ((uint8_t)kUSART_RxIdle == handle->rxState)
+ {
+ return kStatus_NoTransferInProgress;
+ }
+
+ *count = handle->rxDataSizeAll - handle->rxDataSize;
+
+ return kStatus_Success;
+}
+
+/*!
+ * brief USART IRQ handle function.
+ *
+ * This function handles the USART transmit and receive IRQ request.
+ *
+ * param base USART peripheral base address.
+ * param handle USART handle pointer.
+ */
+void USART_TransferHandleIRQ(USART_Type *base, usart_handle_t *handle)
+{
+ /* Check arguments */
+ assert((NULL != base) && (NULL != handle));
+
+ bool receiveEnabled = ((handle->rxDataSize != 0U) || (handle->rxRingBuffer != NULL));
+ bool sendEnabled = (handle->txDataSize != 0U);
+ uint8_t rxdata;
+ size_t tmpsize;
+
+ /* If RX overrun. */
+ if ((base->FIFOSTAT & USART_FIFOSTAT_RXERR_MASK) != 0U)
+ {
+ /* Clear rx error state. */
+ base->FIFOSTAT |= USART_FIFOSTAT_RXERR_MASK;
+ /* clear rxFIFO */
+ base->FIFOCFG |= USART_FIFOCFG_EMPTYRX_MASK;
+ /* Trigger callback. */
+ if (handle->callback != NULL)
+ {
+ handle->callback(base, handle, kStatus_USART_RxError, handle->userData);
+ }
+ }
+ while ((receiveEnabled && ((base->FIFOSTAT & USART_FIFOSTAT_RXNOTEMPTY_MASK) != 0U)) ||
+ (sendEnabled && ((base->FIFOSTAT & USART_FIFOSTAT_TXNOTFULL_MASK) != 0U)))
+ {
+ /* Receive data */
+ if (receiveEnabled && ((base->FIFOSTAT & USART_FIFOSTAT_RXNOTEMPTY_MASK) != 0U))
+ {
+ /* Clear address detect when RXFIFO has data. */
+ base->CTL &= ~(uint32_t)USART_CTL_ADDRDET_MASK;
+ /* Receive to app bufffer if app buffer is present */
+ if (handle->rxDataSize != 0U)
+ {
+ rxdata = (uint8_t)base->FIFORD;
+ *handle->rxData = rxdata;
+ handle->rxDataSize--;
+ handle->rxData++;
+ receiveEnabled = ((handle->rxDataSize != 0U) || (handle->rxRingBuffer != NULL));
+ if (0U == handle->rxDataSize)
+ {
+ if (NULL == handle->rxRingBuffer)
+ {
+ base->FIFOINTENCLR = USART_FIFOINTENCLR_RXLVL_MASK | USART_FIFOINTENSET_RXERR_MASK;
+ }
+ handle->rxState = (uint8_t)kUSART_RxIdle;
+ if (handle->callback != NULL)
+ {
+ handle->callback(base, handle, kStatus_USART_RxIdle, handle->userData);
+ }
+ }
+ }
+ /* Otherwise receive to ring buffer if ring buffer is present */
+ else
+ {
+ if (handle->rxRingBuffer != NULL)
+ {
+ /* If RX ring buffer is full, trigger callback to notify over run. */
+ if (USART_TransferIsRxRingBufferFull(handle))
+ {
+ if (handle->callback != NULL)
+ {
+ handle->callback(base, handle, kStatus_USART_RxRingBufferOverrun, handle->userData);
+ }
+ }
+ /* If ring buffer is still full after callback function, the oldest data is overridden. */
+ if (USART_TransferIsRxRingBufferFull(handle))
+ {
+ /* Increase handle->rxRingBufferTail to make room for new data. */
+ if ((size_t)handle->rxRingBufferTail + 1U == handle->rxRingBufferSize)
+ {
+ handle->rxRingBufferTail = 0U;
+ }
+ else
+ {
+ handle->rxRingBufferTail++;
+ }
+ }
+ /* Read data. */
+ rxdata = (uint8_t)base->FIFORD;
+ handle->rxRingBuffer[handle->rxRingBufferHead] = rxdata;
+ /* Increase handle->rxRingBufferHead. */
+ if ((size_t)handle->rxRingBufferHead + 1U == handle->rxRingBufferSize)
+ {
+ handle->rxRingBufferHead = 0U;
+ }
+ else
+ {
+ handle->rxRingBufferHead++;
+ }
+ }
+ }
+ }
+ /* Send data */
+ if (sendEnabled && ((base->FIFOSTAT & USART_FIFOSTAT_TXNOTFULL_MASK) != 0U))
+ {
+ base->FIFOWR = *handle->txData;
+ handle->txDataSize--;
+ handle->txData++;
+ sendEnabled = handle->txDataSize != 0U;
+ if (!sendEnabled)
+ {
+ base->FIFOINTENCLR = USART_FIFOINTENCLR_TXLVL_MASK;
+
+ base->INTENSET = USART_INTENSET_TXIDLEEN_MASK;
+ }
+ }
+ }
+
+ /* Tx idle and the interrupt is enabled. */
+ if ((0U != (base->INTENSET & USART_INTENSET_TXIDLEEN_MASK)) && (0U != (base->INTSTAT & USART_INTSTAT_TXIDLE_MASK)))
+ {
+ /* Set txState to idle only when all data has been sent out to bus. */
+ handle->txState = (uint8_t)kUSART_TxIdle;
+ /* Disable tx idle interrupt */
+ base->INTENCLR = USART_INTENCLR_TXIDLECLR_MASK;
+
+ /* Trigger callback. */
+ if (handle->callback != NULL)
+ {
+ handle->callback(base, handle, kStatus_USART_TxIdle, handle->userData);
+ }
+ }
+
+ /* ring buffer is not used */
+ if (NULL == handle->rxRingBuffer)
+ {
+ tmpsize = handle->rxDataSize;
+
+ /* restore if rx transfer ends and rxLevel is different from default value */
+ if ((tmpsize == 0U) && (USART_FIFOTRIG_RXLVL_GET(base) != handle->rxWatermark))
+ {
+ base->FIFOTRIG =
+ (base->FIFOTRIG & (~USART_FIFOTRIG_RXLVL_MASK)) | USART_FIFOTRIG_RXLVL(handle->rxWatermark);
+ }
+ /* decrease level if rx transfer is bellow */
+ if ((tmpsize != 0U) && (tmpsize < (USART_FIFOTRIG_RXLVL_GET(base) + 1U)))
+ {
+ base->FIFOTRIG = (base->FIFOTRIG & (~USART_FIFOTRIG_RXLVL_MASK)) | (USART_FIFOTRIG_RXLVL(tmpsize - 1U));
+ }
+ }
+}
diff --git a/drivers/fsl_usart.h b/drivers/fsl_usart.h
new file mode 100644
index 0000000..53af19b
--- /dev/null
+++ b/drivers/fsl_usart.h
@@ -0,0 +1,862 @@
+/*
+ * Copyright (c) 2016, Freescale Semiconductor, Inc.
+ * Copyright 2016-2021 NXP
+ * All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+#ifndef _FSL_USART_H_
+#define _FSL_USART_H_
+
+#include "fsl_common.h"
+
+/*!
+ * @addtogroup usart_driver
+ * @{
+ */
+
+/*******************************************************************************
+ * Definitions
+ ******************************************************************************/
+
+/*! @name Driver version */
+/*@{*/
+/*! @brief USART driver version. */
+#define FSL_USART_DRIVER_VERSION (MAKE_VERSION(2, 6, 0))
+/*@}*/
+
+#define USART_FIFOTRIG_TXLVL_GET(base) (((base)->FIFOTRIG & USART_FIFOTRIG_TXLVL_MASK) >> USART_FIFOTRIG_TXLVL_SHIFT)
+#define USART_FIFOTRIG_RXLVL_GET(base) (((base)->FIFOTRIG & USART_FIFOTRIG_RXLVL_MASK) >> USART_FIFOTRIG_RXLVL_SHIFT)
+
+/*! @brief Retry times for waiting flag. */
+#ifndef UART_RETRY_TIMES
+#define UART_RETRY_TIMES 0U /* Defining to zero means to keep waiting for the flag until it is assert/deassert. */
+#endif
+
+/*! @brief Error codes for the USART driver. */
+enum
+{
+ kStatus_USART_TxBusy = MAKE_STATUS(kStatusGroup_LPC_USART, 0), /*!< Transmitter is busy. */
+ kStatus_USART_RxBusy = MAKE_STATUS(kStatusGroup_LPC_USART, 1), /*!< Receiver is busy. */
+ kStatus_USART_TxIdle = MAKE_STATUS(kStatusGroup_LPC_USART, 2), /*!< USART transmitter is idle. */
+ kStatus_USART_RxIdle = MAKE_STATUS(kStatusGroup_LPC_USART, 3), /*!< USART receiver is idle. */
+ kStatus_USART_TxError = MAKE_STATUS(kStatusGroup_LPC_USART, 7), /*!< Error happens on txFIFO. */
+ kStatus_USART_RxError = MAKE_STATUS(kStatusGroup_LPC_USART, 9), /*!< Error happens on rxFIFO. */
+ kStatus_USART_RxRingBufferOverrun = MAKE_STATUS(kStatusGroup_LPC_USART, 8), /*!< Error happens on rx ring buffer */
+ kStatus_USART_NoiseError = MAKE_STATUS(kStatusGroup_LPC_USART, 10), /*!< USART noise error. */
+ kStatus_USART_FramingError = MAKE_STATUS(kStatusGroup_LPC_USART, 11), /*!< USART framing error. */
+ kStatus_USART_ParityError = MAKE_STATUS(kStatusGroup_LPC_USART, 12), /*!< USART parity error. */
+ kStatus_USART_BaudrateNotSupport =
+ MAKE_STATUS(kStatusGroup_LPC_USART, 13), /*!< Baudrate is not support in current clock source */
+ kStatus_USART_Timeout = MAKE_STATUS(kStatusGroup_LPC_USART, 14), /*!< USART time out. */
+};
+
+/*! @brief USART synchronous mode. */
+typedef enum _usart_sync_mode
+{
+ kUSART_SyncModeDisabled = 0x0U, /*!< Asynchronous mode. */
+ kUSART_SyncModeSlave = 0x2U, /*!< Synchronous slave mode. */
+ kUSART_SyncModeMaster = 0x3U, /*!< Synchronous master mode. */
+} usart_sync_mode_t;
+
+/*! @brief USART parity mode. */
+typedef enum _usart_parity_mode
+{
+ kUSART_ParityDisabled = 0x0U, /*!< Parity disabled */
+ kUSART_ParityEven = 0x2U, /*!< Parity enabled, type even, bit setting: PE|PT = 10 */
+ kUSART_ParityOdd = 0x3U, /*!< Parity enabled, type odd, bit setting: PE|PT = 11 */
+} usart_parity_mode_t;
+
+/*! @brief USART stop bit count. */
+typedef enum _usart_stop_bit_count
+{
+ kUSART_OneStopBit = 0U, /*!< One stop bit */
+ kUSART_TwoStopBit = 1U, /*!< Two stop bits */
+} usart_stop_bit_count_t;
+
+/*! @brief USART data size. */
+typedef enum _usart_data_len
+{
+ kUSART_7BitsPerChar = 0U, /*!< Seven bit mode */
+ kUSART_8BitsPerChar = 1U, /*!< Eight bit mode */
+} usart_data_len_t;
+
+/*! @brief USART clock polarity configuration, used in sync mode.*/
+typedef enum _usart_clock_polarity
+{
+ kUSART_RxSampleOnFallingEdge = 0x0U, /*!< Un_RXD is sampled on the falling edge of SCLK. */
+ kUSART_RxSampleOnRisingEdge = 0x1U, /*!< Un_RXD is sampled on the rising edge of SCLK. */
+} usart_clock_polarity_t;
+
+/*! @brief txFIFO watermark values */
+typedef enum _usart_txfifo_watermark
+{
+ kUSART_TxFifo0 = 0, /*!< USART tx watermark is empty */
+ kUSART_TxFifo1 = 1, /*!< USART tx watermark at 1 item */
+ kUSART_TxFifo2 = 2, /*!< USART tx watermark at 2 items */
+ kUSART_TxFifo3 = 3, /*!< USART tx watermark at 3 items */
+ kUSART_TxFifo4 = 4, /*!< USART tx watermark at 4 items */
+ kUSART_TxFifo5 = 5, /*!< USART tx watermark at 5 items */
+ kUSART_TxFifo6 = 6, /*!< USART tx watermark at 6 items */
+ kUSART_TxFifo7 = 7, /*!< USART tx watermark at 7 items */
+} usart_txfifo_watermark_t;
+
+/*! @brief rxFIFO watermark values */
+typedef enum _usart_rxfifo_watermark
+{
+ kUSART_RxFifo1 = 0, /*!< USART rx watermark at 1 item */
+ kUSART_RxFifo2 = 1, /*!< USART rx watermark at 2 items */
+ kUSART_RxFifo3 = 2, /*!< USART rx watermark at 3 items */
+ kUSART_RxFifo4 = 3, /*!< USART rx watermark at 4 items */
+ kUSART_RxFifo5 = 4, /*!< USART rx watermark at 5 items */
+ kUSART_RxFifo6 = 5, /*!< USART rx watermark at 6 items */
+ kUSART_RxFifo7 = 6, /*!< USART rx watermark at 7 items */
+ kUSART_RxFifo8 = 7, /*!< USART rx watermark at 8 items */
+} usart_rxfifo_watermark_t;
+
+/*!
+ * @brief USART interrupt configuration structure, default settings all disabled.
+ */
+enum _usart_interrupt_enable
+{
+ kUSART_TxErrorInterruptEnable = (USART_FIFOINTENSET_TXERR_MASK),
+ kUSART_RxErrorInterruptEnable = (USART_FIFOINTENSET_RXERR_MASK),
+ kUSART_TxLevelInterruptEnable = (USART_FIFOINTENSET_TXLVL_MASK),
+ kUSART_RxLevelInterruptEnable = (USART_FIFOINTENSET_RXLVL_MASK),
+};
+
+/*!
+ * @brief USART status flags.
+ *
+ * This provides constants for the USART status flags for use in the USART functions.
+ */
+enum _usart_flags
+{
+ kUSART_TxError = (USART_FIFOSTAT_TXERR_MASK), /*!< TEERR bit, sets if TX buffer is error */
+ kUSART_RxError = (USART_FIFOSTAT_RXERR_MASK), /*!< RXERR bit, sets if RX buffer is error */
+ kUSART_TxFifoEmptyFlag = (USART_FIFOSTAT_TXEMPTY_MASK), /*!< TXEMPTY bit, sets if TX buffer is empty */
+ kUSART_TxFifoNotFullFlag = (USART_FIFOSTAT_TXNOTFULL_MASK), /*!< TXNOTFULL bit, sets if TX buffer is not full */
+ kUSART_RxFifoNotEmptyFlag = (USART_FIFOSTAT_RXNOTEMPTY_MASK), /*!< RXNOEMPTY bit, sets if RX buffer is not empty */
+ kUSART_RxFifoFullFlag = (USART_FIFOSTAT_RXFULL_MASK), /*!< RXFULL bit, sets if RX buffer is full */
+};
+
+/*! @brief USART configuration structure. */
+typedef struct _usart_config
+{
+ uint32_t baudRate_Bps; /*!< USART baud rate */
+ usart_parity_mode_t parityMode; /*!< Parity mode, disabled (default), even, odd */
+ usart_stop_bit_count_t stopBitCount; /*!< Number of stop bits, 1 stop bit (default) or 2 stop bits */
+ usart_data_len_t bitCountPerChar; /*!< Data length - 7 bit, 8 bit */
+ bool loopback; /*!< Enable peripheral loopback */
+ bool enableRx; /*!< Enable RX */
+ bool enableTx; /*!< Enable TX */
+ bool enableContinuousSCLK; /*!< USART continuous Clock generation enable in synchronous master mode. */
+ bool enableMode32k; /*!< USART uses 32 kHz clock from the RTC oscillator as the clock source. */
+ bool enableHardwareFlowControl; /*!< Enable hardware control RTS/CTS */
+ usart_txfifo_watermark_t txWatermark; /*!< txFIFO watermark */
+ usart_rxfifo_watermark_t rxWatermark; /*!< rxFIFO watermark */
+ usart_sync_mode_t syncMode; /*!< Transfer mode select - asynchronous, synchronous master, synchronous slave. */
+ usart_clock_polarity_t clockPolarity; /*!< Selects the clock polarity and sampling edge in synchronous mode. */
+} usart_config_t;
+
+/*! @brief USART transfer structure. */
+typedef struct _usart_transfer
+{
+ /*
+ * Use separate TX and RX data pointer, because TX data is const data.
+ * The member data is kept for backward compatibility.
+ */
+ union
+ {
+ uint8_t *data; /*!< The buffer of data to be transfer.*/
+ uint8_t *rxData; /*!< The buffer to receive data. */
+ const uint8_t *txData; /*!< The buffer of data to be sent. */
+ };
+ size_t dataSize; /*!< The byte count to be transfer. */
+} usart_transfer_t;
+
+/* Forward declaration of the handle typedef. */
+typedef struct _usart_handle usart_handle_t;
+
+/*! @brief USART transfer callback function. */
+typedef void (*usart_transfer_callback_t)(USART_Type *base, usart_handle_t *handle, status_t status, void *userData);
+
+/*! @brief USART handle structure. */
+struct _usart_handle
+{
+ const uint8_t *volatile txData; /*!< Address of remaining data to send. */
+ volatile size_t txDataSize; /*!< Size of the remaining data to send. */
+ size_t txDataSizeAll; /*!< Size of the data to send out. */
+ uint8_t *volatile rxData; /*!< Address of remaining data to receive. */
+ volatile size_t rxDataSize; /*!< Size of the remaining data to receive. */
+ size_t rxDataSizeAll; /*!< Size of the data to receive. */
+
+ uint8_t *rxRingBuffer; /*!< Start address of the receiver ring buffer. */
+ size_t rxRingBufferSize; /*!< Size of the ring buffer. */
+ volatile uint16_t rxRingBufferHead; /*!< Index for the driver to store received data into ring buffer. */
+ volatile uint16_t rxRingBufferTail; /*!< Index for the user to get data from the ring buffer. */
+
+ usart_transfer_callback_t callback; /*!< Callback function. */
+ void *userData; /*!< USART callback function parameter.*/
+
+ volatile uint8_t txState; /*!< TX transfer state. */
+ volatile uint8_t rxState; /*!< RX transfer state */
+
+ uint8_t txWatermark; /*!< txFIFO watermark */
+ uint8_t rxWatermark; /*!< rxFIFO watermark */
+};
+
+/*! @brief Typedef for usart interrupt handler. */
+typedef void (*flexcomm_usart_irq_handler_t)(USART_Type *base, usart_handle_t *handle);
+
+/*******************************************************************************
+ * API
+ ******************************************************************************/
+
+#if defined(__cplusplus)
+extern "C" {
+#endif /* _cplusplus */
+
+/*! @brief Returns instance number for USART peripheral base address. */
+uint32_t USART_GetInstance(USART_Type *base);
+
+/*!
+ * @name Initialization and deinitialization
+ * @{
+ */
+
+/*!
+ * @brief Initializes a USART instance with user configuration structure and peripheral clock.
+ *
+ * This function configures the USART module with the user-defined settings. The user can configure the configuration
+ * structure and also get the default configuration by using the USART_GetDefaultConfig() function.
+ * Example below shows how to use this API to configure USART.
+ * @code
+ * usart_config_t usartConfig;
+ * usartConfig.baudRate_Bps = 115200U;
+ * usartConfig.parityMode = kUSART_ParityDisabled;
+ * usartConfig.stopBitCount = kUSART_OneStopBit;
+ * USART_Init(USART1, &usartConfig, 20000000U);
+ * @endcode
+ *
+ * @param base USART peripheral base address.
+ * @param config Pointer to user-defined configuration structure.
+ * @param srcClock_Hz USART clock source frequency in HZ.
+ * @retval kStatus_USART_BaudrateNotSupport Baudrate is not support in current clock source.
+ * @retval kStatus_InvalidArgument USART base address is not valid
+ * @retval kStatus_Success Status USART initialize succeed
+ */
+status_t USART_Init(USART_Type *base, const usart_config_t *config, uint32_t srcClock_Hz);
+
+/*!
+ * @brief Deinitializes a USART instance.
+ *
+ * This function waits for TX complete, disables TX and RX, and disables the USART clock.
+ *
+ * @param base USART peripheral base address.
+ */
+void USART_Deinit(USART_Type *base);
+
+/*!
+ * @brief Gets the default configuration structure.
+ *
+ * This function initializes the USART configuration structure to a default value. The default
+ * values are:
+ * usartConfig->baudRate_Bps = 115200U;
+ * usartConfig->parityMode = kUSART_ParityDisabled;
+ * usartConfig->stopBitCount = kUSART_OneStopBit;
+ * usartConfig->bitCountPerChar = kUSART_8BitsPerChar;
+ * usartConfig->loopback = false;
+ * usartConfig->enableTx = false;
+ * usartConfig->enableRx = false;
+ *
+ * @param config Pointer to configuration structure.
+ */
+void USART_GetDefaultConfig(usart_config_t *config);
+
+/*!
+ * @brief Sets the USART instance baud rate.
+ *
+ * This function configures the USART module baud rate. This function is used to update
+ * the USART module baud rate after the USART module is initialized by the USART_Init.
+ * @code
+ * USART_SetBaudRate(USART1, 115200U, 20000000U);
+ * @endcode
+ *
+ * @param base USART peripheral base address.
+ * @param baudrate_Bps USART baudrate to be set.
+ * @param srcClock_Hz USART clock source frequency in HZ.
+ * @retval kStatus_USART_BaudrateNotSupport Baudrate is not support in current clock source.
+ * @retval kStatus_Success Set baudrate succeed.
+ * @retval kStatus_InvalidArgument One or more arguments are invalid.
+ */
+status_t USART_SetBaudRate(USART_Type *base, uint32_t baudrate_Bps, uint32_t srcClock_Hz);
+
+/*!
+ * @brief Enable 32 kHz mode which USART uses clock from the RTC oscillator as the clock source
+ *
+ * Please note that in order to use a 32 kHz clock to operate USART properly, the RTC oscillator
+ * and its 32 kHz output must be manully enabled by user, by calling RTC_Init and setting
+ * SYSCON_RTCOSCCTRL_EN bit to 1.
+ * And in 32kHz clocking mode the USART can only work at 9600 baudrate or at the baudrate that
+ * 9600 can evenly divide, eg: 4800, 3200.
+ *
+ * @param base USART peripheral base address.
+ * @param baudRate_Bps USART baudrate to be set..
+ * @param enableMode32k true is 32k mode, false is normal mode.
+ * @param srcClock_Hz USART clock source frequency in HZ.
+ * @retval kStatus_USART_BaudrateNotSupport Baudrate is not support in current clock source.
+ * @retval kStatus_Success Set baudrate succeed.
+ * @retval kStatus_InvalidArgument One or more arguments are invalid.
+ */
+status_t USART_Enable32kMode(USART_Type *base, uint32_t baudRate_Bps, bool enableMode32k, uint32_t srcClock_Hz);
+
+/*!
+ * @brief Enable 9-bit data mode for USART.
+ *
+ * This function set the 9-bit mode for USART module. The 9th bit is not used for parity thus can be modified by user.
+ *
+ * @param base USART peripheral base address.
+ * @param enable true to enable, false to disable.
+ */
+void USART_Enable9bitMode(USART_Type *base, bool enable);
+
+/*!
+ * @brief Set the USART slave address.
+ *
+ * This function configures the address for USART module that works as slave in 9-bit data mode. When the address
+ * detection is enabled, the frame it receices with MSB being 1 is considered as an address frame, otherwise it is
+ * considered as data frame. Once the address frame matches slave's own addresses, this slave is addressed. This
+ * address frame and its following data frames are stored in the receive buffer, otherwise the frames will be discarded.
+ * To un-address a slave, just send an address frame with unmatched address.
+ *
+ * @note Any USART instance joined in the multi-slave system can work as slave. The position of the address mark is the
+ * same as the parity bit when parity is enabled for 8 bit and 9 bit data formats.
+ *
+ * @param base USART peripheral base address.
+ * @param address USART slave address.
+ */
+static inline void USART_SetMatchAddress(USART_Type *base, uint8_t address)
+{
+ /* Configure match address. */
+ base->ADDR = (uint32_t)address;
+}
+
+/*!
+ * @brief Enable the USART match address feature.
+ *
+ * @param base USART peripheral base address.
+ * @param match true to enable match address, false to disable.
+ */
+static inline void USART_EnableMatchAddress(USART_Type *base, bool match)
+{
+ /* Configure match address enable bit. */
+ if (match)
+ {
+ base->CFG |= (uint32_t)USART_CFG_AUTOADDR_MASK;
+ base->CTL |= (uint32_t)USART_CTL_ADDRDET_MASK;
+ }
+ else
+ {
+ base->CFG &= ~(uint32_t)USART_CFG_AUTOADDR_MASK;
+ base->CTL &= ~(uint32_t)USART_CTL_ADDRDET_MASK;
+ }
+}
+
+/* @} */
+
+/*!
+ * @name Status
+ * @{
+ */
+
+/*!
+ * @brief Get USART status flags.
+ *
+ * This function get all USART status flags, the flags are returned as the logical
+ * OR value of the enumerators @ref _usart_flags. To check a specific status,
+ * compare the return value with enumerators in @ref _usart_flags.
+ * For example, to check whether the TX is empty:
+ * @code
+ * if (kUSART_TxFifoNotFullFlag & USART_GetStatusFlags(USART1))
+ * {
+ * ...
+ * }
+ * @endcode
+ *
+ * @param base USART peripheral base address.
+ * @return USART status flags which are ORed by the enumerators in the _usart_flags.
+ */
+static inline uint32_t USART_GetStatusFlags(USART_Type *base)
+{
+ return base->FIFOSTAT;
+}
+
+/*!
+ * @brief Clear USART status flags.
+ *
+ * This function clear supported USART status flags
+ * Flags that can be cleared or set are:
+ * kUSART_TxError
+ * kUSART_RxError
+ * For example:
+ * @code
+ * USART_ClearStatusFlags(USART1, kUSART_TxError | kUSART_RxError)
+ * @endcode
+ *
+ * @param base USART peripheral base address.
+ * @param mask status flags to be cleared.
+ */
+static inline void USART_ClearStatusFlags(USART_Type *base, uint32_t mask)
+{
+ /* Only TXERR, RXERR fields support write. Remaining fields should be set to zero */
+ base->FIFOSTAT = mask & (USART_FIFOSTAT_TXERR_MASK | USART_FIFOSTAT_RXERR_MASK);
+}
+
+/* @} */
+
+/*!
+ * @name Interrupts
+ * @{
+ */
+
+/*!
+ * @brief Enables USART interrupts according to the provided mask.
+ *
+ * This function enables the USART interrupts according to the provided mask. The mask
+ * is a logical OR of enumeration members. See @ref _usart_interrupt_enable.
+ * For example, to enable TX empty interrupt and RX full interrupt:
+ * @code
+ * USART_EnableInterrupts(USART1, kUSART_TxLevelInterruptEnable | kUSART_RxLevelInterruptEnable);
+ * @endcode
+ *
+ * @param base USART peripheral base address.
+ * @param mask The interrupts to enable. Logical OR of @ref _usart_interrupt_enable.
+ */
+static inline void USART_EnableInterrupts(USART_Type *base, uint32_t mask)
+{
+ base->FIFOINTENSET = mask & 0xFUL;
+}
+
+/*!
+ * @brief Disables USART interrupts according to a provided mask.
+ *
+ * This function disables the USART interrupts according to a provided mask. The mask
+ * is a logical OR of enumeration members. See @ref _usart_interrupt_enable.
+ * This example shows how to disable the TX empty interrupt and RX full interrupt:
+ * @code
+ * USART_DisableInterrupts(USART1, kUSART_TxLevelInterruptEnable | kUSART_RxLevelInterruptEnable);
+ * @endcode
+ *
+ * @param base USART peripheral base address.
+ * @param mask The interrupts to disable. Logical OR of @ref _usart_interrupt_enable.
+ */
+static inline void USART_DisableInterrupts(USART_Type *base, uint32_t mask)
+{
+ base->FIFOINTENCLR = mask & 0xFUL;
+}
+
+/*!
+ * @brief Returns enabled USART interrupts.
+ *
+ * This function returns the enabled USART interrupts.
+ *
+ * @param base USART peripheral base address.
+ */
+static inline uint32_t USART_GetEnabledInterrupts(USART_Type *base)
+{
+ return base->FIFOINTENSET;
+}
+
+/*!
+ * @brief Enable DMA for Tx
+ */
+static inline void USART_EnableTxDMA(USART_Type *base, bool enable)
+{
+ if (enable)
+ {
+ base->FIFOCFG |= USART_FIFOCFG_DMATX_MASK;
+ }
+ else
+ {
+ base->FIFOCFG &= ~(USART_FIFOCFG_DMATX_MASK);
+ }
+}
+
+/*!
+ * @brief Enable DMA for Rx
+ */
+static inline void USART_EnableRxDMA(USART_Type *base, bool enable)
+{
+ if (enable)
+ {
+ base->FIFOCFG |= USART_FIFOCFG_DMARX_MASK;
+ }
+ else
+ {
+ base->FIFOCFG &= ~(USART_FIFOCFG_DMARX_MASK);
+ }
+}
+
+/*!
+ * @brief Enable CTS.
+ * This function will determine whether CTS is used for flow control.
+ *
+ * @param base USART peripheral base address.
+ * @param enable Enable CTS or not, true for enable and false for disable.
+ */
+static inline void USART_EnableCTS(USART_Type *base, bool enable)
+{
+ if (enable)
+ {
+ base->CFG |= USART_CFG_CTSEN_MASK;
+ }
+ else
+ {
+ base->CFG &= ~USART_CFG_CTSEN_MASK;
+ }
+}
+
+/*!
+ * @brief Continuous Clock generation.
+ * By default, SCLK is only output while data is being transmitted in synchronous mode.
+ * Enable this funciton, SCLK will run continuously in synchronous mode, allowing
+ * characters to be received on Un_RxD independently from transmission on Un_TXD).
+ *
+ * @param base USART peripheral base address.
+ * @param enable Enable Continuous Clock generation mode or not, true for enable and false for disable.
+ */
+static inline void USART_EnableContinuousSCLK(USART_Type *base, bool enable)
+{
+ if (enable)
+ {
+ base->CTL |= USART_CTL_CC_MASK;
+ }
+ else
+ {
+ base->CTL &= ~USART_CTL_CC_MASK;
+ }
+}
+
+/*!
+ * @brief Enable Continuous Clock generation bit auto clear.
+ * While enable this cuntion, the Continuous Clock bit is automatically cleared when a complete
+ * character has been received. This bit is cleared at the same time.
+ *
+ * @param base USART peripheral base address.
+ * @param enable Enable auto clear or not, true for enable and false for disable.
+ */
+static inline void USART_EnableAutoClearSCLK(USART_Type *base, bool enable)
+{
+ if (enable)
+ {
+ base->CTL |= USART_CTL_CLRCCONRX_MASK;
+ }
+ else
+ {
+ base->CTL &= ~USART_CTL_CLRCCONRX_MASK;
+ }
+}
+
+/*!
+ * @brief Sets the rx FIFO watermark.
+ *
+ * @param base USART peripheral base address.
+ * @param water Rx FIFO watermark.
+ */
+static inline void USART_SetRxFifoWatermark(USART_Type *base, uint8_t water)
+{
+ assert(water <= (USART_FIFOTRIG_RXLVL_MASK >> USART_FIFOTRIG_RXLVL_SHIFT));
+ base->FIFOTRIG = (base->FIFOTRIG & ~USART_FIFOTRIG_RXLVL_MASK) | USART_FIFOTRIG_RXLVL(water);
+}
+
+/*!
+ * @brief Sets the tx FIFO watermark.
+ *
+ * @param base USART peripheral base address.
+ * @param water Tx FIFO watermark.
+ */
+static inline void USART_SetTxFifoWatermark(USART_Type *base, uint8_t water)
+{
+ assert(water <= (USART_FIFOTRIG_TXLVL_MASK >> USART_FIFOTRIG_TXLVL_SHIFT));
+ base->FIFOTRIG = (base->FIFOTRIG & ~USART_FIFOTRIG_TXLVL_MASK) | USART_FIFOTRIG_TXLVL(water);
+}
+/* @} */
+
+/*!
+ * @name Bus Operations
+ * @{
+ */
+
+/*!
+ * @brief Writes to the FIFOWR register.
+ *
+ * This function writes data to the txFIFO directly. The upper layer must ensure
+ * that txFIFO has space for data to write before calling this function.
+ *
+ * @param base USART peripheral base address.
+ * @param data The byte to write.
+ */
+static inline void USART_WriteByte(USART_Type *base, uint8_t data)
+{
+ base->FIFOWR = data;
+}
+
+/*!
+ * @brief Reads the FIFORD register directly.
+ *
+ * This function reads data from the rxFIFO directly. The upper layer must
+ * ensure that the rxFIFO is not empty before calling this function.
+ *
+ * @param base USART peripheral base address.
+ * @return The byte read from USART data register.
+ */
+static inline uint8_t USART_ReadByte(USART_Type *base)
+{
+ return (uint8_t)base->FIFORD;
+}
+
+/*!
+ * @brief Gets the rx FIFO data count.
+ *
+ * @param base USART peripheral base address.
+ * @return rx FIFO data count.
+ */
+static inline uint8_t USART_GetRxFifoCount(USART_Type *base)
+{
+ return (uint8_t)((base->FIFOSTAT & USART_FIFOSTAT_RXLVL_MASK) >> USART_FIFOSTAT_RXLVL_SHIFT);
+}
+
+/*!
+ * @brief Gets the tx FIFO data count.
+ *
+ * @param base USART peripheral base address.
+ * @return tx FIFO data count.
+ */
+static inline uint8_t USART_GetTxFifoCount(USART_Type *base)
+{
+ return (uint8_t)((base->FIFOSTAT & USART_FIFOSTAT_TXLVL_MASK) >> USART_FIFOSTAT_TXLVL_SHIFT);
+}
+
+/*!
+ * @brief Transmit an address frame in 9-bit data mode.
+ *
+ * @param base USART peripheral base address.
+ * @param address USART slave address.
+ */
+void USART_SendAddress(USART_Type *base, uint8_t address);
+
+/*!
+ * @brief Writes to the TX register using a blocking method.
+ *
+ * This function polls the TX register, waits for the TX register to be empty or for the TX FIFO
+ * to have room and writes data to the TX buffer.
+ *
+ * @param base USART peripheral base address.
+ * @param data Start address of the data to write.
+ * @param length Size of the data to write.
+ * @retval kStatus_USART_Timeout Transmission timed out and was aborted.
+ * @retval kStatus_InvalidArgument Invalid argument.
+ * @retval kStatus_Success Successfully wrote all data.
+ */
+status_t USART_WriteBlocking(USART_Type *base, const uint8_t *data, size_t length);
+
+/*!
+ * @brief Read RX data register using a blocking method.
+ *
+ * This function polls the RX register, waits for the RX register to be full or for RX FIFO to
+ * have data and read data from the TX register.
+ *
+ * @param base USART peripheral base address.
+ * @param data Start address of the buffer to store the received data.
+ * @param length Size of the buffer.
+ * @retval kStatus_USART_FramingError Receiver overrun happened while receiving data.
+ * @retval kStatus_USART_ParityError Noise error happened while receiving data.
+ * @retval kStatus_USART_NoiseError Framing error happened while receiving data.
+ * @retval kStatus_USART_RxError Overflow or underflow rxFIFO happened.
+ * @retval kStatus_USART_Timeout Transmission timed out and was aborted.
+ * @retval kStatus_Success Successfully received all data.
+ */
+status_t USART_ReadBlocking(USART_Type *base, uint8_t *data, size_t length);
+
+/* @} */
+
+/*!
+ * @name Transactional
+ * @{
+ */
+
+/*!
+ * @brief Initializes the USART handle.
+ *
+ * This function initializes the USART handle which can be used for other USART
+ * transactional APIs. Usually, for a specified USART instance,
+ * call this API once to get the initialized handle.
+ *
+ * @param base USART peripheral base address.
+ * @param handle USART handle pointer.
+ * @param callback The callback function.
+ * @param userData The parameter of the callback function.
+ */
+status_t USART_TransferCreateHandle(USART_Type *base,
+ usart_handle_t *handle,
+ usart_transfer_callback_t callback,
+ void *userData);
+
+/*!
+ * @brief Transmits a buffer of data using the interrupt method.
+ *
+ * This function sends data using an interrupt method. This is a non-blocking function, which
+ * returns directly without waiting for all data to be written to the TX register. When
+ * all data is written to the TX register in the IRQ handler, the USART driver calls the callback
+ * function and passes the @ref kStatus_USART_TxIdle as status parameter.
+ *
+ * @param base USART peripheral base address.
+ * @param handle USART handle pointer.
+ * @param xfer USART transfer structure. See #usart_transfer_t.
+ * @retval kStatus_Success Successfully start the data transmission.
+ * @retval kStatus_USART_TxBusy Previous transmission still not finished, data not all written to TX register yet.
+ * @retval kStatus_InvalidArgument Invalid argument.
+ */
+status_t USART_TransferSendNonBlocking(USART_Type *base, usart_handle_t *handle, usart_transfer_t *xfer);
+
+/*!
+ * @brief Sets up the RX ring buffer.
+ *
+ * This function sets up the RX ring buffer to a specific USART handle.
+ *
+ * When the RX ring buffer is used, data received are stored into the ring buffer even when the
+ * user doesn't call the USART_TransferReceiveNonBlocking() API. If there is already data received
+ * in the ring buffer, the user can get the received data from the ring buffer directly.
+ *
+ * @note When using the RX ring buffer, one byte is reserved for internal use. In other
+ * words, if @p ringBufferSize is 32, then only 31 bytes are used for saving data.
+ *
+ * @param base USART peripheral base address.
+ * @param handle USART handle pointer.
+ * @param ringBuffer Start address of the ring buffer for background receiving. Pass NULL to disable the ring buffer.
+ * @param ringBufferSize size of the ring buffer.
+ */
+void USART_TransferStartRingBuffer(USART_Type *base,
+ usart_handle_t *handle,
+ uint8_t *ringBuffer,
+ size_t ringBufferSize);
+
+/*!
+ * @brief Aborts the background transfer and uninstalls the ring buffer.
+ *
+ * This function aborts the background transfer and uninstalls the ring buffer.
+ *
+ * @param base USART peripheral base address.
+ * @param handle USART handle pointer.
+ */
+void USART_TransferStopRingBuffer(USART_Type *base, usart_handle_t *handle);
+
+/*!
+ * @brief Get the length of received data in RX ring buffer.
+ *
+ * @param handle USART handle pointer.
+ * @return Length of received data in RX ring buffer.
+ */
+size_t USART_TransferGetRxRingBufferLength(usart_handle_t *handle);
+
+/*!
+ * @brief Aborts the interrupt-driven data transmit.
+ *
+ * This function aborts the interrupt driven data sending. The user can get the remainBtyes to find out
+ * how many bytes are still not sent out.
+ *
+ * @param base USART peripheral base address.
+ * @param handle USART handle pointer.
+ */
+void USART_TransferAbortSend(USART_Type *base, usart_handle_t *handle);
+
+/*!
+ * @brief Get the number of bytes that have been sent out to bus.
+ *
+ * This function gets the number of bytes that have been sent out to bus by interrupt method.
+ *
+ * @param base USART peripheral base address.
+ * @param handle USART handle pointer.
+ * @param count Send bytes count.
+ * @retval kStatus_NoTransferInProgress No send in progress.
+ * @retval kStatus_InvalidArgument Parameter is invalid.
+ * @retval kStatus_Success Get successfully through the parameter \p count;
+ */
+status_t USART_TransferGetSendCount(USART_Type *base, usart_handle_t *handle, uint32_t *count);
+
+/*!
+ * @brief Receives a buffer of data using an interrupt method.
+ *
+ * This function receives data using an interrupt method. This is a non-blocking function, which
+ * returns without waiting for all data to be received.
+ * If the RX ring buffer is used and not empty, the data in the ring buffer is copied and
+ * the parameter @p receivedBytes shows how many bytes are copied from the ring buffer.
+ * After copying, if the data in the ring buffer is not enough to read, the receive
+ * request is saved by the USART driver. When the new data arrives, the receive request
+ * is serviced first. When all data is received, the USART driver notifies the upper layer
+ * through a callback function and passes the status parameter @ref kStatus_USART_RxIdle.
+ * For example, the upper layer needs 10 bytes but there are only 5 bytes in the ring buffer.
+ * The 5 bytes are copied to the xfer->data and this function returns with the
+ * parameter @p receivedBytes set to 5. For the left 5 bytes, newly arrived data is
+ * saved from the xfer->data[5]. When 5 bytes are received, the USART driver notifies the upper layer.
+ * If the RX ring buffer is not enabled, this function enables the RX and RX interrupt
+ * to receive data to the xfer->data. When all data is received, the upper layer is notified.
+ *
+ * @param base USART peripheral base address.
+ * @param handle USART handle pointer.
+ * @param xfer USART transfer structure, see #usart_transfer_t.
+ * @param receivedBytes Bytes received from the ring buffer directly.
+ * @retval kStatus_Success Successfully queue the transfer into transmit queue.
+ * @retval kStatus_USART_RxBusy Previous receive request is not finished.
+ * @retval kStatus_InvalidArgument Invalid argument.
+ */
+status_t USART_TransferReceiveNonBlocking(USART_Type *base,
+ usart_handle_t *handle,
+ usart_transfer_t *xfer,
+ size_t *receivedBytes);
+
+/*!
+ * @brief Aborts the interrupt-driven data receiving.
+ *
+ * This function aborts the interrupt-driven data receiving. The user can get the remainBytes to find out
+ * how many bytes not received yet.
+ *
+ * @param base USART peripheral base address.
+ * @param handle USART handle pointer.
+ */
+void USART_TransferAbortReceive(USART_Type *base, usart_handle_t *handle);
+
+/*!
+ * @brief Get the number of bytes that have been received.
+ *
+ * This function gets the number of bytes that have been received.
+ *
+ * @param base USART peripheral base address.
+ * @param handle USART handle pointer.
+ * @param count Receive bytes count.
+ * @retval kStatus_NoTransferInProgress No receive in progress.
+ * @retval kStatus_InvalidArgument Parameter is invalid.
+ * @retval kStatus_Success Get successfully through the parameter \p count;
+ */
+status_t USART_TransferGetReceiveCount(USART_Type *base, usart_handle_t *handle, uint32_t *count);
+
+/*!
+ * @brief USART IRQ handle function.
+ *
+ * This function handles the USART transmit and receive IRQ request.
+ *
+ * @param base USART peripheral base address.
+ * @param handle USART handle pointer.
+ */
+void USART_TransferHandleIRQ(USART_Type *base, usart_handle_t *handle);
+
+/* @} */
+
+#if defined(__cplusplus)
+}
+#endif
+
+/*! @}*/
+
+#endif /* _FSL_USART_H_ */