From 704b264b8a2aa27c8f48cedbe829b488699ed022 Mon Sep 17 00:00:00 2001 From: Mathias Brossard Date: Fri, 29 Oct 2021 23:08:25 -0500 Subject: [PATCH] cmsis_uart: use CMSIS UART driver for kl27z --- records/hic_hal/kl27z.yaml | 1 + source/board/microbitv2/IO_Config_Override.h | 22 +- source/board/microbitv2/i2c_commands.c | 1 + source/board/microbitv2/power.c | 22 +- source/hic_hal/freescale/kl27z/IO_Config.h | 18 +- .../freescale/kl27z/MKL27Z4/fsl_clock.c | 107 +- .../freescale/kl27z/MKL27Z4/fsl_clock.h | 44 +- .../freescale/kl27z/MKL27Z4/fsl_common.c | 280 ++ .../freescale/kl27z/MKL27Z4/fsl_common.h | 667 ++++ .../hic_hal/freescale/kl27z/MKL27Z4/fsl_dma.h | 585 +++ .../freescale/kl27z/MKL27Z4/fsl_dmamux.h | 177 + .../freescale/kl27z/MKL27Z4/fsl_lpuart.c | 2051 ++++++++++ .../freescale/kl27z/MKL27Z4/fsl_lpuart.h | 862 +++++ .../kl27z/MKL27Z4/fsl_lpuart_cmsis.c | 3314 +++++++++++++++++ .../kl27z/MKL27Z4/fsl_lpuart_cmsis.h | 89 + .../freescale/kl27z/MKL27Z4/fsl_lpuart_dma.h | 171 + source/hic_hal/freescale/kl27z/RTE_Device.h | 97 + source/hic_hal/freescale/kl27z/hic_init.c | 43 +- source/hic_hal/freescale/kl27z/uart.c | 293 -- 19 files changed, 8424 insertions(+), 420 deletions(-) create mode 100644 source/hic_hal/freescale/kl27z/MKL27Z4/fsl_common.c create mode 100644 source/hic_hal/freescale/kl27z/MKL27Z4/fsl_common.h create mode 100644 source/hic_hal/freescale/kl27z/MKL27Z4/fsl_dma.h create mode 100644 source/hic_hal/freescale/kl27z/MKL27Z4/fsl_dmamux.h create mode 100644 source/hic_hal/freescale/kl27z/MKL27Z4/fsl_lpuart.c create mode 100644 source/hic_hal/freescale/kl27z/MKL27Z4/fsl_lpuart.h create mode 100644 source/hic_hal/freescale/kl27z/MKL27Z4/fsl_lpuart_cmsis.c create mode 100644 source/hic_hal/freescale/kl27z/MKL27Z4/fsl_lpuart_cmsis.h create mode 100644 source/hic_hal/freescale/kl27z/MKL27Z4/fsl_lpuart_dma.h create mode 100644 source/hic_hal/freescale/kl27z/RTE_Device.h delete mode 100644 source/hic_hal/freescale/kl27z/uart.c diff --git a/records/hic_hal/kl27z.yaml b/records/hic_hal/kl27z.yaml index 1e887bf87d..0c2fa6c375 100644 --- a/records/hic_hal/kl27z.yaml +++ b/records/hic_hal/kl27z.yaml @@ -21,6 +21,7 @@ common: - source/hic_hal/freescale - source/hic_hal/freescale/kl27z - source/hic_hal/freescale/kl27z/MKL27Z4 + - source/hic_hal/cmsis-driver/uart fsl_flash_driver: - source/hic_hal/freescale/iap diff --git a/source/board/microbitv2/IO_Config_Override.h b/source/board/microbitv2/IO_Config_Override.h index 2859c5eb11..df22fe77fb 100644 --- a/source/board/microbitv2/IO_Config_Override.h +++ b/source/board/microbitv2/IO_Config_Override.h @@ -147,21 +147,21 @@ COMPILER_ASSERT(DAPLINK_HIC_ID == DAPLINK_HIC_ID_KL27Z); // Target Running LED Not available // UART -#define UART_PORT PORTA -#define UART_NUM (1) -// RX PTA18 -#define PIN_UART_RX_GPIO PTA + +// UART RX PTA18 +#define PIN_UART_RX_PORT PORTA #define PIN_UART_RX_BIT (18) #define PIN_UART_RX (1<PDIR) >> PIN_WAKE_ON_EDGE_BIT) & 0x01U) ? false : true; @@ -102,7 +102,7 @@ void power_init(void) { // Configure pin as GPIO PORT_SetPinMux(PIN_WAKE_ON_EDGE_PORT, PIN_WAKE_ON_EDGE_BIT, kPORT_MuxAsGpio); - + /* Power related. */ SMC_SetPowerModeProtection(SMC, kSMC_AllowPowerModeAll); if (kRCM_SourceWakeup & RCM_GetPreviousResetSources(RCM)) /* Wakeup from VLLS. */ @@ -191,22 +191,22 @@ static void power_mode_switch(smc_power_state_t curPowerState, app_power_mode_t static void power_pre_switch_hook(smc_power_state_t originPowerState, app_power_mode_t targetMode) { /* Wait for debug console output finished. */ - while (!(LPUART_STAT_TC_MASK & UART->STAT)) + while (!(LPUART_STAT_TC_MASK & LPUART1->STAT)) { } uart_uninitialize(); /* Disable pins to lower current leakage */ - PORT_SetPinMux(UART_PORT, PIN_UART_RX_BIT, kPORT_PinDisabledOrAnalog); - PORT_SetPinMux(UART_PORT, PIN_UART_TX_BIT, kPORT_PinDisabledOrAnalog); + PORT_SetPinMux(PIN_UART_RX_PORT, PIN_UART_RX_BIT, kPORT_PinDisabledOrAnalog); + PORT_SetPinMux(PIN_UART_TX_PORT, PIN_UART_TX_BIT, kPORT_PinDisabledOrAnalog); PORT_SetPinMux(PIN_HID_LED_PORT, PIN_HID_LED_BIT, kPORT_PinDisabledOrAnalog); - + /* Disable I/O pin SWCLK */ PIN_SWCLK_PORT->PCR[PIN_SWCLK_BIT] = 0; - + /* Disable I/O pin SWDIO */ PIN_SWDIO_PORT->PCR[PIN_SWDIO_BIT] = 0; - + /* If targetMode is VLLS0, disable I2C pins */ if (kAPP_PowerModeVlls0 == targetMode) { @@ -229,10 +229,10 @@ static void power_post_switch_hook(smc_power_state_t originPowerState, app_power PIN_SWDIO_PORT->PCR[PIN_SWDIO_BIT] = PORT_PCR_MUX(1) | /* GPIO */ PORT_PCR_PE_MASK | /* Pull enable */ PORT_PCR_PS_MASK; /* Pull-up */ - + /* re-configure pinmux of disabled pins */ - PORT_SetPinMux(UART_PORT, PIN_UART_RX_BIT, (port_mux_t)PIN_UART_RX_MUX_ALT); - PORT_SetPinMux(UART_PORT, PIN_UART_TX_BIT, (port_mux_t)PIN_UART_TX_MUX_ALT); + PORT_SetPinMux(PIN_UART_RX_PORT, PIN_UART_RX_BIT, PIN_UART_RX_MUX_ALT); + PORT_SetPinMux(PIN_UART_TX_PORT, PIN_UART_TX_BIT, PIN_UART_TX_MUX_ALT); uart_initialize(); i2c_deinitialize(); diff --git a/source/hic_hal/freescale/kl27z/IO_Config.h b/source/hic_hal/freescale/kl27z/IO_Config.h index 79f067fdf0..76c0fe5c31 100644 --- a/source/hic_hal/freescale/kl27z/IO_Config.h +++ b/source/hic_hal/freescale/kl27z/IO_Config.h @@ -92,21 +92,21 @@ COMPILER_ASSERT(DAPLINK_HIC_ID == DAPLINK_HIC_ID_KL27Z); #define SW_RESET_NOT_PRESSED (1) // UART -#define UART_PORT PORTA -#define UART_NUM (1) -// RX PTA18 -#define PIN_UART_RX_GPIO PTA + +// UART RX PTA18 +#define PIN_UART_RX_PORT PORTA #define PIN_UART_RX_BIT (18) #define PIN_UART_RX (1<C1 & MCG_C1_IRCLKEN_MASK) || (kMCGLITE_ClkSrcLirc == MCG_S_CLKST_VAL)) + if (((MCG->C1 & MCG_C1_IRCLKEN_MASK) != 0U) || ((uint8_t)kMCGLITE_ClkSrcLirc == MCG_S_CLKST_VAL)) { - return lircFreqs[MCG_C2_IRCS_VAL]; + freq = lircFreqs[MCG_C2_IRCS_VAL]; } else { - return 0U; + freq = 0U; } + + return freq; } static uint8_t CLOCK_GetOscRangeFromFreq(uint32_t freq) @@ -114,16 +117,20 @@ static uint8_t CLOCK_GetOscRangeFromFreq(uint32_t freq) */ uint32_t CLOCK_GetOsc0ErClkFreq(void) { - if (OSC0->CR & OSC_CR_ERCLKEN_MASK) + uint32_t freq; + + if ((OSC0->CR & OSC_CR_ERCLKEN_MASK) != 0U) { /* Please call CLOCK_SetXtal0Freq base on board setting before using OSC0 clock. */ assert(g_xtal0Freq); - return g_xtal0Freq; + freq = g_xtal0Freq; } else { - return 0U; + freq = 0U; } + + return freq; } /*! @@ -162,7 +169,7 @@ uint32_t CLOCK_GetEr32kClkFreq(void) */ uint32_t CLOCK_GetPlatClkFreq(void) { - return CLOCK_GetOutClkFreq() / (SIM_CLKDIV1_OUTDIV1_VAL + 1); + return CLOCK_GetOutClkFreq() / (SIM_CLKDIV1_OUTDIV1_VAL + 1U); } /*! @@ -174,8 +181,8 @@ uint32_t CLOCK_GetFlashClkFreq(void) { uint32_t freq; - freq = CLOCK_GetOutClkFreq() / (SIM_CLKDIV1_OUTDIV1_VAL + 1); - freq /= (SIM_CLKDIV1_OUTDIV4_VAL + 1); + freq = CLOCK_GetOutClkFreq() / (SIM_CLKDIV1_OUTDIV1_VAL + 1U); + freq /= (SIM_CLKDIV1_OUTDIV4_VAL + 1U); return freq; } @@ -189,8 +196,8 @@ uint32_t CLOCK_GetBusClkFreq(void) { uint32_t freq; - freq = CLOCK_GetOutClkFreq() / (SIM_CLKDIV1_OUTDIV1_VAL + 1); - freq /= (SIM_CLKDIV1_OUTDIV4_VAL + 1); + freq = CLOCK_GetOutClkFreq() / (SIM_CLKDIV1_OUTDIV1_VAL + 1U); + freq /= (SIM_CLKDIV1_OUTDIV4_VAL + 1U); return freq; } @@ -202,7 +209,7 @@ uint32_t CLOCK_GetBusClkFreq(void) */ uint32_t CLOCK_GetCoreSysClkFreq(void) { - return CLOCK_GetOutClkFreq() / (SIM_CLKDIV1_OUTDIV1_VAL + 1); + return CLOCK_GetOutClkFreq() / (SIM_CLKDIV1_OUTDIV1_VAL + 1U); } /*! @@ -223,12 +230,12 @@ uint32_t CLOCK_GetFreq(clock_name_t clockName) { case kCLOCK_CoreSysClk: case kCLOCK_PlatClk: - freq = CLOCK_GetOutClkFreq() / (SIM_CLKDIV1_OUTDIV1_VAL + 1); + freq = CLOCK_GetOutClkFreq() / (SIM_CLKDIV1_OUTDIV1_VAL + 1U); break; case kCLOCK_BusClk: case kCLOCK_FlashClk: - freq = CLOCK_GetOutClkFreq() / (SIM_CLKDIV1_OUTDIV1_VAL + 1); - freq /= (SIM_CLKDIV1_OUTDIV4_VAL + 1); + freq = CLOCK_GetOutClkFreq() / (SIM_CLKDIV1_OUTDIV1_VAL + 1U); + freq /= (SIM_CLKDIV1_OUTDIV4_VAL + 1U); break; case kCLOCK_Er32kClk: freq = CLOCK_GetEr32kClkFreq(); @@ -326,15 +333,19 @@ uint32_t CLOCK_GetInternalRefClkFreq(void) */ uint32_t CLOCK_GetPeriphClkFreq(void) { + uint32_t freq; + /* Check whether the HIRC is enabled. */ - if ((MCG->MC & MCG_MC_HIRCEN_MASK) || (kMCGLITE_ClkSrcHirc == MCG_S_CLKST_VAL)) + if (((MCG->MC & MCG_MC_HIRCEN_MASK) != 0U) || ((uint8_t)kMCGLITE_ClkSrcHirc == MCG_S_CLKST_VAL)) { - return MCG_HIRC_FREQ; + freq = MCG_HIRC_FREQ; } else { - return 0U; + freq = 0U; } + + return freq; } /*! @@ -351,13 +362,13 @@ uint32_t CLOCK_GetOutClkFreq(void) switch (MCG_S_CLKST_VAL) { - case kMCGLITE_ClkSrcHirc: + case (uint8_t)kMCGLITE_ClkSrcHirc: freq = MCG_HIRC_FREQ; break; - case kMCGLITE_ClkSrcLirc: + case (uint8_t)kMCGLITE_ClkSrcLirc: freq = CLOCK_GetLircClkFreq() >> MCG_SC_FCRDIV_VAL; break; - case kMCGLITE_ClkSrcExt: + case (uint8_t)kMCGLITE_ClkSrcExt: /* Please call CLOCK_SetXtal0Freq base on board setting before using OSC0 clock. */ assert(g_xtal0Freq); freq = g_xtal0Freq; @@ -383,11 +394,11 @@ mcglite_mode_t CLOCK_GetMode(void) switch (MCG_S_CLKST_VAL) { - case kMCGLITE_ClkSrcHirc: /* HIRC */ + case (uint8_t)kMCGLITE_ClkSrcHirc: /* HIRC */ mode = kMCGLITE_ModeHirc48M; break; - case kMCGLITE_ClkSrcLirc: /* LIRC */ - if (kMCGLITE_Lirc2M == MCG_C2_IRCS_VAL) + case (uint8_t)kMCGLITE_ClkSrcLirc: /* LIRC */ + if ((uint8_t)kMCGLITE_Lirc2M == MCG_C2_IRCS_VAL) { mode = kMCGLITE_ModeLirc2M; } @@ -396,7 +407,7 @@ mcglite_mode_t CLOCK_GetMode(void) mode = kMCGLITE_ModeLirc8M; } break; - case kMCGLITE_ClkSrcExt: /* EXT */ + case (uint8_t)kMCGLITE_ClkSrcExt: /* EXT */ mode = kMCGLITE_ModeExt; break; default: @@ -424,11 +435,11 @@ status_t CLOCK_SetMcgliteConfig(mcglite_config_t const *targetConfig) * If switch between LIRC8M and LIRC2M, need to switch to HIRC mode first, * because could not switch directly. */ - if ((kMCGLITE_ClkSrcLirc == MCG_S_CLKST_VAL) && (kMCGLITE_ClkSrcLirc == targetConfig->outSrc) && - (MCG_C2_IRCS_VAL != targetConfig->ircs)) + if (((uint8_t)kMCGLITE_ClkSrcLirc == MCG_S_CLKST_VAL) && (kMCGLITE_ClkSrcLirc == targetConfig->outSrc) && + (MCG_C2_IRCS_VAL != (uint8_t)(targetConfig->ircs))) { - MCG->C1 = (MCG->C1 & ~MCG_C1_CLKS_MASK) | MCG_C1_CLKS(kMCGLITE_ClkSrcHirc); - while (kMCGLITE_ClkSrcHirc != MCG_S_CLKST_VAL) + MCG->C1 = (uint8_t)((MCG->C1 & ~MCG_C1_CLKS_MASK) | MCG_C1_CLKS(kMCGLITE_ClkSrcHirc)); + while ((uint8_t)kMCGLITE_ClkSrcHirc != MCG_S_CLKST_VAL) { } } @@ -436,22 +447,22 @@ status_t CLOCK_SetMcgliteConfig(mcglite_config_t const *targetConfig) /* Set configuration now. */ MCG->SC = MCG_SC_FCRDIV(targetConfig->fcrdiv); MCG->MC = MCG_MC_HIRCEN(targetConfig->hircEnableInNotHircMode) | MCG_MC_LIRC_DIV2(targetConfig->lircDiv2); - MCG->C2 = (MCG->C2 & ~MCG_C2_IRCS_MASK) | MCG_C2_IRCS(targetConfig->ircs); + MCG->C2 = (uint8_t)((MCG->C2 & ~MCG_C2_IRCS_MASK) | MCG_C2_IRCS(targetConfig->ircs)); MCG->C1 = MCG_C1_CLKS(targetConfig->outSrc) | targetConfig->irclkEnableMode; /* * If external oscillator used and MCG_Lite is set to EXT mode, need to * wait for the OSC stable. */ - if ((MCG->C2 & MCG_C2_EREFS0_MASK) && (kMCGLITE_ClkSrcExt == targetConfig->outSrc)) + if (((MCG->C2 & MCG_C2_EREFS0_MASK) != 0U) && (kMCGLITE_ClkSrcExt == targetConfig->outSrc)) { - while (!(MCG->S & MCG_S_OSCINIT0_MASK)) + while (0U == (MCG->S & MCG_S_OSCINIT0_MASK)) { } } /* Wait for clock source change completed. */ - while (targetConfig->outSrc != MCG_S_CLKST_VAL) + while ((uint8_t)targetConfig->outSrc != MCG_S_CLKST_VAL) { } @@ -474,10 +485,10 @@ void CLOCK_InitOsc0(osc_config_t const *config) MCG->C2 = ((MCG->C2 & MCG_C2_IRCS_MASK) | MCG_C2_RANGE0(range) | (uint8_t)config->workMode); - if ((kOSC_ModeExt != config->workMode) && (OSC0->CR & OSC_CR_ERCLKEN_MASK)) + if ((kOSC_ModeExt != config->workMode) && ((OSC0->CR & OSC_CR_ERCLKEN_MASK) != 0U)) { /* Wait for stable. */ - while (!(MCG->S & MCG_S_OSCINIT0_MASK)) + while (0U == (MCG->S & MCG_S_OSCINIT0_MASK)) { } } @@ -493,29 +504,3 @@ void CLOCK_DeinitOsc0(void) OSC0->CR = 0U; MCG->C2 &= MCG_C2_IRCS_MASK; } - -/*! - * brief Delay at least for several microseconds. - * Please note that, this API will calculate the microsecond period with the maximum devices - * supported CPU frequency, so this API will only delay for at least the given microseconds, if precise - * delay count was needed, please implement a new timer count to achieve this function. - * - * param delay_us Delay time in unit of microsecond. - */ -__attribute__((weak)) void SDK_DelayAtLeastUs(uint32_t delay_us) -{ - assert(0U != delay_us); - - uint32_t count = (uint32_t)USEC_TO_COUNT(delay_us, SDK_DEVICE_MAXIMUM_CPU_CLOCK_FREQUENCY); - - /* - * Calculate the real delay count depend on the excute instructions cycles, - * users can change the divider value to adapt to the real IDE optimise level. - */ - count = (count / 4U); - - for (; count > 0UL; count--) - { - __NOP(); - } -} diff --git a/source/hic_hal/freescale/kl27z/MKL27Z4/fsl_clock.h b/source/hic_hal/freescale/kl27z/MKL27Z4/fsl_clock.h index c0fb08c807..c0834bf404 100644 --- a/source/hic_hal/freescale/kl27z/MKL27Z4/fsl_clock.h +++ b/source/hic_hal/freescale/kl27z/MKL27Z4/fsl_clock.h @@ -40,22 +40,18 @@ /*! @name Driver version */ /*@{*/ -/*! @brief CLOCK driver version 2.2.0. */ -#define FSL_CLOCK_DRIVER_VERSION (MAKE_VERSION(2, 2, 0)) +/*! @brief CLOCK driver version 2.3.1. */ +#define FSL_CLOCK_DRIVER_VERSION (MAKE_VERSION(2, 3, 1)) /*@}*/ -#ifndef SDK_DEVICE_MAXIMUM_CPU_CLOCK_FREQUENCY -#define SDK_DEVICE_MAXIMUM_CPU_CLOCK_FREQUENCY 48000000 -#endif - /*! @brief External XTAL0 (OSC0) clock frequency. * * The XTAL0/EXTAL0 (OSC0) clock frequency in Hz. When the clock is set up, use the * function CLOCK_SetXtal0Freq to set the value in the clock driver. For example, * if XTAL0 is 8 MHz: * @code - * CLOCK_InitOsc0(...); // Set up the OSC0 - * CLOCK_SetXtal0Freq(80000000); // Set the XTAL0 value to clock driver. + * CLOCK_InitOsc0(...); + * CLOCK_SetXtal0Freq(80000000); * @endcode * * This is important for the multicore platforms where one core needs to set up the @@ -75,6 +71,10 @@ extern volatile uint32_t g_xtal0Freq; */ extern volatile uint32_t g_xtal32Freq; +/* 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 (48000000UL) +#endif /*! @brief Clock ip name array for DMAMUX. */ #define DMAMUX_CLOCKS \ { \ @@ -99,12 +99,6 @@ extern volatile uint32_t g_xtal32Freq; kCLOCK_Spi0, kCLOCK_Spi1 \ } -/*! @brief Clock ip name array for SLCD. */ -#define SLCD_CLOCKS \ - { \ - kCLOCK_Slcd0 \ - } - /*! @brief Clock ip name array for PIT. */ #define PIT_CLOCKS \ { \ @@ -291,7 +285,6 @@ typedef enum _clock_ip_name kCLOCK_PortC = CLK_GATE_DEFINE(0x1038U, 11U), kCLOCK_PortD = CLK_GATE_DEFINE(0x1038U, 12U), kCLOCK_PortE = CLK_GATE_DEFINE(0x1038U, 13U), - kCLOCK_Slcd0 = CLK_GATE_DEFINE(0x1038U, 19U), kCLOCK_Lpuart0 = CLK_GATE_DEFINE(0x1038U, 20U), kCLOCK_Lpuart1 = CLK_GATE_DEFINE(0x1038U, 21U), kCLOCK_Flexio0 = CLK_GATE_DEFINE(0x1038U, 31U), @@ -438,7 +431,7 @@ extern "C" { static inline void CLOCK_EnableClock(clock_ip_name_t name) { uint32_t regAddr = SIM_BASE + CLK_GATE_ABSTRACT_REG_OFFSET((uint32_t)name); - (*(volatile uint32_t *)regAddr) |= (1U << CLK_GATE_ABSTRACT_BITS_SHIFT((uint32_t)name)); + (*(volatile uint32_t *)regAddr) |= (1UL << CLK_GATE_ABSTRACT_BITS_SHIFT((uint32_t)name)); } /*! @@ -449,7 +442,7 @@ static inline void CLOCK_EnableClock(clock_ip_name_t name) static inline void CLOCK_DisableClock(clock_ip_name_t name) { uint32_t regAddr = SIM_BASE + CLK_GATE_ABSTRACT_REG_OFFSET((uint32_t)name); - (*(volatile uint32_t *)regAddr) &= ~(1U << CLK_GATE_ABSTRACT_BITS_SHIFT((uint32_t)name)); + (*(volatile uint32_t *)regAddr) &= ~(1UL << CLK_GATE_ABSTRACT_BITS_SHIFT((uint32_t)name)); } /*! @@ -630,7 +623,7 @@ void CLOCK_SetSimConfig(sim_clock_config_t const *config); */ static inline void CLOCK_SetSimSafeDivs(void) { - SIM->CLKDIV1 = 0x10030000U; + SIM->CLKDIV1 = 0x10070000U; } /*! @@ -726,7 +719,7 @@ static inline void OSC_SetExtRefClkConfig(OSC_Type *base, oscer_config_t const * { uint8_t reg = base->CR; - reg &= ~(OSC_CR_ERCLKEN_MASK | OSC_CR_EREFSTEN_MASK); + reg &= (uint8_t)(~(OSC_CR_ERCLKEN_MASK | OSC_CR_EREFSTEN_MASK)); reg |= config->enableMode; base->CR = reg; @@ -744,7 +737,6 @@ static inline void OSC_SetExtRefClkConfig(OSC_Type *base, oscer_config_t const * * * Example: @code - // To enable only 2 pF and 8 pF capacitor load, please use like this. OSC_SetCapLoad(OSC, kOSC_Cap2P | kOSC_Cap8P); @endcode */ @@ -753,7 +745,7 @@ static inline void OSC_SetCapLoad(OSC_Type *base, uint8_t capLoad) { uint8_t reg = base->CR; - reg &= ~(OSC_CR_SC2P_MASK | OSC_CR_SC4P_MASK | OSC_CR_SC8P_MASK | OSC_CR_SC16P_MASK); + reg &= (uint8_t)(~(OSC_CR_SC2P_MASK | OSC_CR_SC4P_MASK | OSC_CR_SC8P_MASK | OSC_CR_SC16P_MASK)); reg |= capLoad; base->CR = reg; @@ -803,16 +795,6 @@ static inline void CLOCK_SetXtal32Freq(uint32_t freq) } /* @} */ -/*! - * @brief Delay at least for several microseconds. - * Please note that, this API will calculate the microsecond period with the maximum - * supported CPU frequency, so this API will only delay for at least the given microseconds, if precise - * delay count was needed, please implement a new timer count to achieve this function. - * - * @param delay_us Delay time in unit of microsecond. - */ -void SDK_DelayAtLeastUs(uint32_t delay_us); - #if defined(__cplusplus) } #endif /* __cplusplus */ diff --git a/source/hic_hal/freescale/kl27z/MKL27Z4/fsl_common.c b/source/hic_hal/freescale/kl27z/MKL27Z4/fsl_common.c new file mode 100644 index 0000000000..fd96a955c3 --- /dev/null +++ b/source/hic_hal/freescale/kl27z/MKL27Z4/fsl_common.c @@ -0,0 +1,280 @@ +/* + * Copyright (c) 2015-2016, Freescale Semiconductor, Inc. + * Copyright 2016-2019 NXP + * All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include "fsl_common.h" +#define SDK_MEM_MAGIC_NUMBER 12345U + +typedef struct _mem_align_control_block +{ + uint16_t identifier; /*!< Identifier for the memory control block. */ + uint16_t offset; /*!< offset from aligned address to real address */ +} mem_align_cb_t; + +/* Component ID definition, used by tools. */ +#ifndef FSL_COMPONENT_ID +#define FSL_COMPONENT_ID "platform.drivers.common" +#endif + +#ifndef __GIC_PRIO_BITS +#if defined(ENABLE_RAM_VECTOR_TABLE) +uint32_t InstallIRQHandler(IRQn_Type irq, uint32_t irqHandler) +{ +/* 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[irq + 16]; + /* make sure the __VECTOR_RAM is noncachable */ + __VECTOR_RAM[irq + 16] = irqHandler; + + EnableGlobalIRQ(irqMaskValue); + SDK_ISR_EXIT_BARRIER; + + return ret; +} +#endif /* ENABLE_RAM_VECTOR_TABLE. */ +#endif /* __GIC_PRIO_BITS. */ + +#if (defined(FSL_FEATURE_SOC_SYSCON_COUNT) && (FSL_FEATURE_SOC_SYSCON_COUNT > 0)) +#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] = 1u << intNumber; + EnableIRQ(interrupt); /* also enable interrupt at NVIC */ +} + +void DisableDeepSleepIRQ(IRQn_Type interrupt) +{ + uint32_t intNumber = (uint32_t)interrupt; + + DisableIRQ(interrupt); /* also disable interrupt at NVIC */ + uint32_t index = 0; + + while (intNumber >= 32u) + { + index++; + intNumber -= 32u; + } + + SYSCON->STARTERCLR[index] = 1u << intNumber; +} +#endif /* FSL_FEATURE_SYSCON_STARTER_DISCONTINUOUS */ +#endif /* FSL_FEATURE_SOC_SYSCON_COUNT */ + +void *SDK_Malloc(size_t size, size_t alignbytes) +{ + mem_align_cb_t *p_cb = NULL; + uint32_t alignedsize = SDK_SIZEALIGN(size, alignbytes) + alignbytes + sizeof(mem_align_cb_t); + union + { + void *pointer_value; + uint32_t unsigned_value; + } 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; + uint32_t unsigned_value; + } 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); +} + +/*! + * @brief Delay function bases on while loop, every loop includes three instructions. + * + * @param count Counts of loop needed for dalay. + */ +#if defined(SDK_DELAY_USE_DWT) && defined(DWT) +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; + } +} + +uint32_t getCpuCycleCount(void) +{ + return DWT->CYCCNT; +} +#elif defined __XCC__ +extern uint32_t xthal_get_ccount(void); +void enableCpuCycleCounter(void) +{ + /* do nothing */ +} + +uint32_t getCpuCycleCount(void) +{ + return xthal_get_ccount(); +} +#endif + +#ifndef __XCC__ +#if (!defined(SDK_DELAY_USE_DWT)) || (!defined(DWT)) +#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"); +} +#endif /* defined(__CC_ARM) */ +#endif /* (!defined(SDK_DELAY_USE_DWT)) || (!defined(DWT)) */ +#endif /* __XCC__ */ +/*! + * @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 delay_us and + * coreClock_Hz have limitation. For example, in the platform with 1GHz coreClock_Hz, the delay_us only supports + * up to 4294967 in current code. If long time delay is needed, please implement a new delay function. + * + * @param delay_us Delay time in unit of microsecond. + * @param coreClock_Hz Core clock frequency with Hz. + */ +void SDK_DelayAtLeastUs(uint32_t delay_us, uint32_t coreClock_Hz) +{ + assert(0U != delay_us); + uint64_t count = USEC_TO_COUNT(delay_us, coreClock_Hz); + assert(count <= UINT32_MAX); + +#if defined(SDK_DELAY_USE_DWT) && defined(DWT) || (defined __XCC__) /* 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) || (defined __XCC__) */ +} diff --git a/source/hic_hal/freescale/kl27z/MKL27Z4/fsl_common.h b/source/hic_hal/freescale/kl27z/MKL27Z4/fsl_common.h new file mode 100644 index 0000000000..8351608e8b --- /dev/null +++ b/source/hic_hal/freescale/kl27z/MKL27Z4/fsl_common.h @@ -0,0 +1,667 @@ +/* + * Copyright (c) 2015-2016, Freescale Semiconductor, Inc. + * Copyright 2016-2020 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__) +#include +#endif + +#include "fsl_device_registers.h" +#include "util.h" + +/*! + * @addtogroup ksdk_common + * @{ + */ + +/******************************************************************************* + * Definitions + ******************************************************************************/ + +// Redefine assert to DAPLink's assert utility for code size savings. +#define assert(x) util_assert((x)); + +/*! @brief Construct a status code value from a group and code number. */ +#define MAKE_STATUS(group, code) ((((group)*100) + (code))) + +/*! @brief Construct the version number for drivers. */ +#define MAKE_VERSION(major, minor, bugfix) (((major) << 16) | ((minor) << 8) | (bugfix)) + +/*! @name Driver version */ +/*@{*/ +/*! @brief common driver version 2.2.4. */ +#define FSL_COMMON_DRIVER_VERSION (MAKE_VERSION(2, 2, 4)) +/*@}*/ + +/* 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. */ + +/*! @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_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_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. */ + +}; + +/*! \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. */ +}; + +/*! @brief Type used for all status and error return values. */ +typedef int32_t status_t; + +/* + * Macro guard for whether to use default weak IRQ implementation in drivers + */ +#ifndef FSL_DRIVER_TRANSFER_DOUBLE_WEAK_IRQ +#define FSL_DRIVER_TRANSFER_DOUBLE_WEAK_IRQ 1 +#endif + +// /*! @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 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 +/*! 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_PRAGMA(data_alignment = FSL_FEATURE_L1DCACHE_LINESIZE_BYTE) var +#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_PRAGMA(data_alignment = FSL_FEATURE_L2CACHE_LINESIZE_BYTE) var +#endif +#elif defined(__CC_ARM) || defined(__ARMCC_VERSION) +/*! Macro to define a variable with alignbytes alignment */ +#define SDK_ALIGN(var, alignbytes) __attribute__((aligned(alignbytes))) var +/*! Macro to define a variable with L1 d-cache line size alignment */ +#if defined(FSL_FEATURE_L1DCACHE_LINESIZE_BYTE) +#define SDK_L1DCACHE_ALIGN(var) __attribute__((aligned(FSL_FEATURE_L1DCACHE_LINESIZE_BYTE))) var +#endif +/*! Macro to define a variable with L2 cache line size alignment */ +#if defined(FSL_FEATURE_L2CACHE_LINESIZE_BYTE) +#define SDK_L2CACHE_ALIGN(var) __attribute__((aligned(FSL_FEATURE_L2CACHE_LINESIZE_BYTE))) var +#endif +#elif defined(__GNUC__) +/*! Macro to define a variable with alignbytes alignment */ +#define SDK_ALIGN(var, alignbytes) var __attribute__((aligned(alignbytes))) +/*! Macro to define a variable with L1 d-cache line size alignment */ +#if defined(FSL_FEATURE_L1DCACHE_LINESIZE_BYTE) +#define SDK_L1DCACHE_ALIGN(var) var __attribute__((aligned(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) var __attribute__((aligned(FSL_FEATURE_L2CACHE_LINESIZE_BYTE))) +#endif +#else +#error Toolchain not supported +#define SDK_ALIGN(var, alignbytes) var +#if defined(FSL_FEATURE_L1DCACHE_LINESIZE_BYTE) +#define SDK_L1DCACHE_ALIGN(var) var +#endif +#if defined(FSL_FEATURE_L2CACHE_LINESIZE_BYTE) +#define SDK_L2CACHE_ALIGN(var) var +#endif +#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(__ICCARM__)) +#if ((!(defined(FSL_FEATURE_HAS_NO_NONCACHEABLE_SECTION) && FSL_FEATURE_HAS_NO_NONCACHEABLE_SECTION)) && defined(FSL_FEATURE_L1ICACHE_LINESIZE_BYTE)) +#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" +#else +#define AT_NONCACHEABLE_SECTION(var) var +#define AT_NONCACHEABLE_SECTION_ALIGN(var, alignbytes) SDK_PRAGMA(data_alignment = alignbytes) var +#define AT_NONCACHEABLE_SECTION_INIT(var) var +#define AT_NONCACHEABLE_SECTION_ALIGN_INIT(var, alignbytes) SDK_PRAGMA(data_alignment = alignbytes) var +#endif +#elif(defined(__CC_ARM) || defined(__ARMCC_VERSION)) +#if ((!(defined(FSL_FEATURE_HAS_NO_NONCACHEABLE_SECTION) && FSL_FEATURE_HAS_NO_NONCACHEABLE_SECTION)) && defined(FSL_FEATURE_L1ICACHE_LINESIZE_BYTE)) +#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 +#else +#define AT_NONCACHEABLE_SECTION(var) var +#define AT_NONCACHEABLE_SECTION_ALIGN(var, alignbytes) __attribute__((aligned(alignbytes))) var +#define AT_NONCACHEABLE_SECTION_INIT(var) var +#define AT_NONCACHEABLE_SECTION_ALIGN_INIT(var, alignbytes) __attribute__((aligned(alignbytes))) var +#endif +#elif(defined(__XCC__)) +#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"))) var +#define AT_NONCACHEABLE_SECTION_ALIGN(var, alignbytes) \ + __attribute__((section("NonCacheable"))) var __attribute__((aligned(alignbytes))) +#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. + */ +#if ((!(defined(FSL_FEATURE_HAS_NO_NONCACHEABLE_SECTION) && FSL_FEATURE_HAS_NO_NONCACHEABLE_SECTION)) && defined(FSL_FEATURE_L1ICACHE_LINESIZE_BYTE)) +#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 +#define AT_NONCACHEABLE_SECTION(var) var +#define AT_NONCACHEABLE_SECTION_ALIGN(var, alignbytes) var __attribute__((aligned(alignbytes))) +#define AT_NONCACHEABLE_SECTION_INIT(var) var +#define AT_NONCACHEABLE_SECTION_ALIGN_INIT(var, alignbytes) var __attribute__((aligned(alignbytes))) +#endif +#else +#error Toolchain not supported. +#define AT_NONCACHEABLE_SECTION(var) var +#define AT_NONCACHEABLE_SECTION_ALIGN(var, alignbytes) var +#define AT_NONCACHEABLE_SECTION_INIT(var) var +#define AT_NONCACHEABLE_SECTION_ALIGN_INIT(var, alignbytes) var +#endif +/* @} */ + +/*! @name Time sensitive region */ +/* @{ */ +#if defined(FSL_SDK_DRIVER_QUICK_ACCESS_ENABLE) && FSL_SDK_DRIVER_QUICK_ACCESS_ENABLE +#if (defined(__ICCARM__)) +#define AT_QUICKACCESS_SECTION_CODE(func) func @"CodeQuickAccess" +#define AT_QUICKACCESS_SECTION_DATA(func) func @"DataQuickAccess" +#elif(defined(__CC_ARM) || defined(__ARMCC_VERSION)) +#define AT_QUICKACCESS_SECTION_CODE(func) __attribute__((section("CodeQuickAccess"), __noinline__)) func +#define AT_QUICKACCESS_SECTION_DATA(func) __attribute__((section("DataQuickAccess"))) func +#elif(defined(__GNUC__)) +#define AT_QUICKACCESS_SECTION_CODE(func) __attribute__((section("CodeQuickAccess"), __noinline__)) func +#define AT_QUICKACCESS_SECTION_DATA(func) __attribute__((section("DataQuickAccess"))) func +#else +#error Toolchain not supported. +#endif /* defined(__ICCARM__) */ +#else +#if (defined(__ICCARM__)) +#define AT_QUICKACCESS_SECTION_CODE(func) func +#define AT_QUICKACCESS_SECTION_DATA(func) func +#elif(defined(__CC_ARM) || defined(__ARMCC_VERSION)) +#define AT_QUICKACCESS_SECTION_CODE(func) func +#define AT_QUICKACCESS_SECTION_DATA(func) func +#elif(defined(__GNUC__)) +#define AT_QUICKACCESS_SECTION_CODE(func) func +#define AT_QUICKACCESS_SECTION_DATA(func) func +#else +#error Toolchain not supported. +#endif +#endif /* __FSL_SDK_DRIVER_QUICK_ACCESS_ENABLE */ +/* @} */ + +/*! @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__) */ +/* @} */ + +/*! @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 +/* @} */ + +#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 + + /*! + * @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) + { + if (NotAvail_IRQn == interrupt) + { + return kStatus_Fail; + } + +#if defined(FSL_FEATURE_NUMBER_OF_LEVEL1_INT_VECTORS) && (FSL_FEATURE_NUMBER_OF_LEVEL1_INT_VECTORS > 0) + if ((uint32_t)interrupt >= (uint32_t)FSL_FEATURE_NUMBER_OF_LEVEL1_INT_VECTORS) + { + return kStatus_Fail; + } +#endif + +#if defined(__GIC_PRIO_BITS) + GIC_EnableIRQ(interrupt); +#else + NVIC_EnableIRQ(interrupt); +#endif + return kStatus_Success; + } + + /*! + * @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) + { + if (NotAvail_IRQn == interrupt) + { + return kStatus_Fail; + } + +#if defined(FSL_FEATURE_NUMBER_OF_LEVEL1_INT_VECTORS) && (FSL_FEATURE_NUMBER_OF_LEVEL1_INT_VECTORS > 0) + if ((uint32_t)interrupt >= (uint32_t)FSL_FEATURE_NUMBER_OF_LEVEL1_INT_VECTORS) + { + return kStatus_Fail; + } +#endif + +#if defined(__GIC_PRIO_BITS) + GIC_DisableIRQ(interrupt); +#else + NVIC_DisableIRQ(interrupt); +#endif + return kStatus_Success; + } + + /*! + * @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 (__XCC__) + return 0; +#else +#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 +#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 (__XCC__) +#else +#if defined(CPSR_I_Msk) + __set_CPSR((__get_CPSR() & ~CPSR_I_Msk) | primask); +#else + __set_PRIMASK(primask); +#endif +#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)) + /*! + * @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_SOC_SYSCON_COUNT */ + + /*! + * @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 delay_us Delay time in unit of microsecond. + * @param coreClock_Hz Core clock frequency with Hz. + */ + void SDK_DelayAtLeastUs(uint32_t delay_us, uint32_t coreClock_Hz); + +#if defined(__cplusplus) +} +#endif + +/*! @} */ + +#endif /* _FSL_COMMON_H_ */ diff --git a/source/hic_hal/freescale/kl27z/MKL27Z4/fsl_dma.h b/source/hic_hal/freescale/kl27z/MKL27Z4/fsl_dma.h new file mode 100644 index 0000000000..7b336625e2 --- /dev/null +++ b/source/hic_hal/freescale/kl27z/MKL27Z4/fsl_dma.h @@ -0,0 +1,585 @@ +/* + * Copyright (c) 2015, Freescale Semiconductor, Inc. + * Copyright 2016-2017 NXP + * All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef _FSL_DMA_H_ +#define _FSL_DMA_H_ + +#include "fsl_common.h" + +/*! + * @addtogroup dma + * @{ + */ + +/******************************************************************************* + * Definitions + ******************************************************************************/ + +/*! @name Driver version */ +/*@{*/ +/*! @brief DMA driver version 2.0.2. */ +#define FSL_DMA_DRIVER_VERSION (MAKE_VERSION(2, 0, 2)) +/*@}*/ + +/*! @brief _dma_channel_status_flags status flag for the DMA driver. */ +enum +{ + kDMA_TransactionsBCRFlag = DMA_DSR_BCR_BCR_MASK, /*!< Contains the number of bytes yet to be + transferred for a given block */ + kDMA_TransactionsDoneFlag = DMA_DSR_BCR_DONE_MASK, /*!< Transactions Done */ + kDMA_TransactionsBusyFlag = DMA_DSR_BCR_BSY_MASK, /*!< Transactions Busy */ + kDMA_TransactionsRequestFlag = DMA_DSR_BCR_REQ_MASK, /*!< Transactions Request */ + kDMA_BusErrorOnDestinationFlag = DMA_DSR_BCR_BED_MASK, /*!< Bus Error on Destination */ + kDMA_BusErrorOnSourceFlag = DMA_DSR_BCR_BES_MASK, /*!< Bus Error on Source */ + kDMA_ConfigurationErrorFlag = DMA_DSR_BCR_CE_MASK, /*!< Configuration Error */ +}; + +/*! @brief DMA transfer size type*/ +typedef enum _dma_transfer_size +{ + kDMA_Transfersize32bits = 0x0U, /*!< 32 bits are transferred for every read/write */ + kDMA_Transfersize8bits, /*!< 8 bits are transferred for every read/write */ + kDMA_Transfersize16bits, /*!< 16b its are transferred for every read/write */ +} dma_transfer_size_t; + +/*! @brief Configuration type for the DMA modulo */ +typedef enum _dma_modulo +{ + kDMA_ModuloDisable = 0x0U, /*!< Buffer disabled */ + kDMA_Modulo16Bytes, /*!< Circular buffer size is 16 bytes. */ + kDMA_Modulo32Bytes, /*!< Circular buffer size is 32 bytes. */ + kDMA_Modulo64Bytes, /*!< Circular buffer size is 64 bytes. */ + kDMA_Modulo128Bytes, /*!< Circular buffer size is 128 bytes. */ + kDMA_Modulo256Bytes, /*!< Circular buffer size is 256 bytes. */ + kDMA_Modulo512Bytes, /*!< Circular buffer size is 512 bytes. */ + kDMA_Modulo1KBytes, /*!< Circular buffer size is 1 KB. */ + kDMA_Modulo2KBytes, /*!< Circular buffer size is 2 KB. */ + kDMA_Modulo4KBytes, /*!< Circular buffer size is 4 KB. */ + kDMA_Modulo8KBytes, /*!< Circular buffer size is 8 KB. */ + kDMA_Modulo16KBytes, /*!< Circular buffer size is 16 KB. */ + kDMA_Modulo32KBytes, /*!< Circular buffer size is 32 KB. */ + kDMA_Modulo64KBytes, /*!< Circular buffer size is 64 KB. */ + kDMA_Modulo128KBytes, /*!< Circular buffer size is 128 KB. */ + kDMA_Modulo256KBytes, /*!< Circular buffer size is 256 KB. */ +} dma_modulo_t; + +/*! @brief DMA channel link type */ +typedef enum _dma_channel_link_type +{ + kDMA_ChannelLinkDisable = 0x0U, /*!< No channel link. */ + kDMA_ChannelLinkChannel1AndChannel2, /*!< Perform a link to channel LCH1 after each cycle-steal transfer. + followed by a link to LCH2 after the BCR decrements to 0. */ + kDMA_ChannelLinkChannel1, /*!< Perform a link to LCH1 after each cycle-steal transfer. */ + kDMA_ChannelLinkChannel1AfterBCR0, /*!< Perform a link to LCH1 after the BCR decrements. */ +} dma_channel_link_type_t; + +/*! @brief DMA transfer type */ +typedef enum _dma_transfer_type +{ + kDMA_MemoryToMemory = 0x0U, /*!< Memory to Memory transfer. */ + kDMA_PeripheralToMemory, /*!< Peripheral to Memory transfer. */ + kDMA_MemoryToPeripheral, /*!< Memory to Peripheral transfer. */ +} dma_transfer_type_t; + +/*! @brief DMA transfer options */ +typedef enum _dma_transfer_options +{ + kDMA_NoOptions = 0x0U, /*!< Transfer without options. */ + kDMA_EnableInterrupt, /*!< Enable interrupt while transfer complete. */ +} dma_transfer_options_t; + +/*! @brief _dma_transfer_status DMA transfer status */ +enum +{ + kStatus_DMA_Busy = MAKE_STATUS(kStatusGroup_DMA, 0), /*!< DMA is busy. */ +}; + +/*! @brief DMA transfer configuration structure */ +typedef struct _dma_transfer_config +{ + uint32_t srcAddr; /*!< DMA transfer source address. */ + uint32_t destAddr; /*!< DMA destination address.*/ + bool enableSrcIncrement; /*!< Source address increase after each transfer. */ + dma_transfer_size_t srcSize; /*!< Source transfer size unit. */ + bool enableDestIncrement; /*!< Destination address increase after each transfer. */ + dma_transfer_size_t destSize; /*!< Destination transfer unit.*/ + uint32_t transferSize; /*!< The number of bytes to be transferred. */ +} dma_transfer_config_t; + +/*! @brief DMA transfer configuration structure */ +typedef struct _dma_channel_link_config +{ + dma_channel_link_type_t linkType; /*!< Channel link type. */ + uint32_t channel1; /*!< The index of channel 1. */ + uint32_t channel2; /*!< The index of channel 2. */ +} dma_channel_link_config_t; + +struct _dma_handle; +/*! @brief Callback function prototype for the DMA driver. */ +typedef void (*dma_callback)(struct _dma_handle *handle, void *userData); + +/*! @brief DMA DMA handle structure */ +typedef struct _dma_handle +{ + DMA_Type *base; /*!< DMA peripheral address. */ + uint8_t channel; /*!< DMA channel used. */ + dma_callback callback; /*!< DMA callback function.*/ + void *userData; /*!< Callback parameter. */ +} dma_handle_t; + +/******************************************************************************* + * API + ******************************************************************************/ +#if defined(__cplusplus) +extern "C" { +#endif /* __cplusplus */ + +/*! + * @name DMA Initialization and De-initialization + * @{ + */ + +/*! + * @brief Initializes the DMA peripheral. + * + * This function ungates the DMA clock. + * + * @param base DMA peripheral base address. + */ +void DMA_Init(DMA_Type *base); + +/*! + * @brief Deinitializes the DMA peripheral. + * + * This function gates the DMA clock. + * + * @param base DMA peripheral base address. + */ +void DMA_Deinit(DMA_Type *base); + +/* @} */ +/*! + * @name DMA Channel Operation + * @{ + */ + +/*! + * @brief Resets the DMA channel. + * + * Sets all register values to reset values and enables + * the cycle steal and auto stop channel request features. + * + * @param base DMA peripheral base address. + * @param channel DMA channel number. + */ +void DMA_ResetChannel(DMA_Type *base, uint32_t channel); + +/*! + * @brief Configures the DMA transfer attribute. + * + * This function configures the transfer attribute including the source address, + * destination address, transfer size, and so on. + * This example shows how to set up the dma_transfer_config_t + * parameters and how to call the DMA_ConfigBasicTransfer function. + * @code + * dma_transfer_config_t transferConfig; + * memset(&transferConfig, 0, sizeof(transferConfig)); + * transferConfig.srcAddr = (uint32_t)srcAddr; + * transferConfig.destAddr = (uint32_t)destAddr; + * transferConfig.enbaleSrcIncrement = true; + * transferConfig.enableDestIncrement = true; + * transferConfig.srcSize = kDMA_Transfersize32bits; + * transferConfig.destSize = kDMA_Transfersize32bits; + * transferConfig.transferSize = sizeof(uint32_t) * BUFF_LENGTH; + * DMA_SetTransferConfig(DMA0, 0, &transferConfig); + * @endcode + * + * @param base DMA peripheral base address. + * @param channel DMA channel number. + * @param config Pointer to the DMA transfer configuration structure. + */ +void DMA_SetTransferConfig(DMA_Type *base, uint32_t channel, const dma_transfer_config_t *config); + +/*! + * @brief Configures the DMA channel link feature. + * + * This function allows DMA channels to have their transfers linked. The current DMA channel + * triggers a DMA request to the linked channels (LCH1 or LCH2) depending on the channel link + * type. + * Perform a link to channel LCH1 after each cycle-steal transfer followed by a link to LCH2 + * after the BCR decrements to 0 if the type is kDMA_ChannelLinkChannel1AndChannel2. + * Perform a link to LCH1 after each cycle-steal transfer if the type is kDMA_ChannelLinkChannel1. + * Perform a link to LCH1 after the BCR decrements to 0 if the type is kDMA_ChannelLinkChannel1AfterBCR0. + * + * @param base DMA peripheral base address. + * @param channel DMA channel number. + * @param config Pointer to the channel link configuration structure. + */ +void DMA_SetChannelLinkConfig(DMA_Type *base, uint32_t channel, const dma_channel_link_config_t *config); + +/*! + * @brief Sets the DMA source address for the DMA transfer. + * + * @param base DMA peripheral base address. + * @param channel DMA channel number. + * @param srcAddr DMA source address. + */ +static inline void DMA_SetSourceAddress(DMA_Type *base, uint32_t channel, uint32_t srcAddr) +{ + assert(channel < (uint32_t)FSL_FEATURE_DMAMUX_MODULE_CHANNEL); + + base->DMA[channel].SAR = srcAddr; +} + +/*! + * @brief Sets the DMA destination address for the DMA transfer. + * + * @param base DMA peripheral base address. + * @param channel DMA channel number. + * @param destAddr DMA destination address. + */ +static inline void DMA_SetDestinationAddress(DMA_Type *base, uint32_t channel, uint32_t destAddr) +{ + assert(channel < (uint32_t)FSL_FEATURE_DMAMUX_MODULE_CHANNEL); + + base->DMA[channel].DAR = destAddr; +} + +/*! + * @brief Sets the DMA transfer size for the DMA transfer. + * + * @param base DMA peripheral base address. + * @param channel DMA channel number. + * @param size The number of bytes to be transferred. + */ +static inline void DMA_SetTransferSize(DMA_Type *base, uint32_t channel, uint32_t size) +{ + assert(channel < (uint32_t)FSL_FEATURE_DMAMUX_MODULE_CHANNEL); + + base->DMA[channel].DSR_BCR = DMA_DSR_BCR_BCR(size); +} + +/*! + * @brief Sets the DMA modulo for the DMA transfer. + * + * This function defines a specific address range specified to be the value after (SAR + SSIZE)/(DAR + DSIZE) + * calculation is performed or the original register value. It provides the ability to implement a circular + * data queue easily. + * + * @param base DMA peripheral base address. + * @param channel DMA channel number. + * @param srcModulo source address modulo. + * @param destModulo destination address modulo. + */ +void DMA_SetModulo(DMA_Type *base, uint32_t channel, dma_modulo_t srcModulo, dma_modulo_t destModulo); + +/*! + * @brief Enables the DMA cycle steal for the DMA transfer. + * + * If the cycle steal feature is enabled (true), the DMA controller forces a single read/write transfer per request, + * or it continuously makes read/write transfers until the BCR decrements to 0. + * + * @param base DMA peripheral base address. + * @param channel DMA channel number. + * @param enable The command for enable (true) or disable (false). + */ +static inline void DMA_EnableCycleSteal(DMA_Type *base, uint32_t channel, bool enable) +{ + assert(channel < (uint32_t)FSL_FEATURE_DMAMUX_MODULE_CHANNEL); + + base->DMA[channel].DCR = (base->DMA[channel].DCR & (~DMA_DCR_CS_MASK)) | DMA_DCR_CS(enable); +} + +/*! + * @brief Enables the DMA auto align for the DMA transfer. + * + * If the auto align feature is enabled (true), the appropriate address register increments + * regardless of DINC or SINC. + * + * @param base DMA peripheral base address. + * @param channel DMA channel number. + * @param enable The command for enable (true) or disable (false). + */ +static inline void DMA_EnableAutoAlign(DMA_Type *base, uint32_t channel, bool enable) +{ + assert(channel < (uint32_t)FSL_FEATURE_DMAMUX_MODULE_CHANNEL); + + base->DMA[channel].DCR = (base->DMA[channel].DCR & (~DMA_DCR_AA_MASK)) | DMA_DCR_AA(enable); +} + +/*! + * @brief Enables the DMA async request for the DMA transfer. + * + * If the async request feature is enabled (true), the DMA supports asynchronous DREQs + * while the MCU is in stop mode. + * + * @param base DMA peripheral base address. + * @param channel DMA channel number. + * @param enable The command for enable (true) or disable (false). + */ +static inline void DMA_EnableAsyncRequest(DMA_Type *base, uint32_t channel, bool enable) +{ + assert(channel < (uint32_t)FSL_FEATURE_DMAMUX_MODULE_CHANNEL); + + base->DMA[channel].DCR = (base->DMA[channel].DCR & (~DMA_DCR_EADREQ_MASK)) | DMA_DCR_EADREQ(enable); +} + +/*! + * @brief Enables an interrupt for the DMA transfer. + * + * @param base DMA peripheral base address. + * @param channel DMA channel number. + */ +static inline void DMA_EnableInterrupts(DMA_Type *base, uint32_t channel) +{ + assert(channel < (uint32_t)FSL_FEATURE_DMAMUX_MODULE_CHANNEL); + + base->DMA[channel].DCR |= DMA_DCR_EINT(true); +} + +/*! + * @brief Disables an interrupt for the DMA transfer. + * + * @param base DMA peripheral base address. + * @param channel DMA channel number. + */ +static inline void DMA_DisableInterrupts(DMA_Type *base, uint32_t channel) +{ + assert(channel < (uint32_t)FSL_FEATURE_DMAMUX_MODULE_CHANNEL); + + base->DMA[channel].DCR &= ~DMA_DCR_EINT_MASK; +} + +/* @} */ +/*! + * @name DMA Channel Transfer Operation + * @{ + */ + +/*! + * @brief Enables the DMA hardware channel request. + * + * @param base DMA peripheral base address. + * @param channel The DMA channel number. + */ +static inline void DMA_EnableChannelRequest(DMA_Type *base, uint32_t channel) +{ + assert(channel < (uint32_t)FSL_FEATURE_DMAMUX_MODULE_CHANNEL); + + base->DMA[channel].DCR |= DMA_DCR_ERQ_MASK; +} + +/*! + * @brief Disables the DMA hardware channel request. + * + * @param base DMA peripheral base address. + * @param channel DMA channel number. + */ +static inline void DMA_DisableChannelRequest(DMA_Type *base, uint32_t channel) +{ + assert(channel < (uint32_t)FSL_FEATURE_DMAMUX_MODULE_CHANNEL); + + base->DMA[channel].DCR &= ~DMA_DCR_ERQ_MASK; +} + +/*! + * @brief Starts the DMA transfer with a software trigger. + * + * This function starts only one read/write iteration. + * + * @param base DMA peripheral base address. + * @param channel The DMA channel number. + */ +static inline void DMA_TriggerChannelStart(DMA_Type *base, uint32_t channel) +{ + assert(channel < (uint32_t)FSL_FEATURE_DMAMUX_MODULE_CHANNEL); + + base->DMA[channel].DCR |= DMA_DCR_START_MASK; +} + +/* @} */ +/*! + * @name DMA Channel Status Operation + * @{ + */ + +/*! + * @brief Gets the remaining bytes of the current DMA transfer. + * + * @param base DMA peripheral base address. + * @param channel DMA channel number. + * @return The number of bytes which have not been transferred yet. + */ +static inline uint32_t DMA_GetRemainingBytes(DMA_Type *base, uint32_t channel) +{ + assert(channel < (uint32_t)FSL_FEATURE_DMAMUX_MODULE_CHANNEL); + + return (base->DMA[channel].DSR_BCR & DMA_DSR_BCR_BCR_MASK) >> DMA_DSR_BCR_BCR_SHIFT; +} + +/*! + * @brief Gets the DMA channel status flags. + * + * @param base DMA peripheral base address. + * @param channel DMA channel number. + * @return The mask of the channel status. Use the _dma_channel_status_flags + * type to decode the return 32 bit variables. + */ +static inline uint32_t DMA_GetChannelStatusFlags(DMA_Type *base, uint32_t channel) +{ + assert(channel < (uint32_t)FSL_FEATURE_DMAMUX_MODULE_CHANNEL); + + return base->DMA[channel].DSR_BCR; +} + +/*! + * @brief Clears the DMA channel status flags. + * + * @param base DMA peripheral base address. + * @param channel DMA channel number. + * @param mask The mask of the channel status to be cleared. Use + * the defined _dma_channel_status_flags type. + */ +static inline void DMA_ClearChannelStatusFlags(DMA_Type *base, uint32_t channel, uint32_t mask) +{ + assert(channel < (uint32_t)FSL_FEATURE_DMAMUX_MODULE_CHANNEL); + + if (mask != 0U) + { + base->DMA[channel].DSR_BCR |= DMA_DSR_BCR_DONE(true); + } +} + +/* @} */ +/*! + * @name DMA Channel Transactional Operation + * @{ + */ + +/*! + * @brief Creates the DMA handle. + * + * This function is called first if using the transactional API for the DMA. This function + * initializes the internal state of the DMA handle. + * + * @param handle DMA handle pointer. The DMA handle stores callback function and + * parameters. + * @param base DMA peripheral base address. + * @param channel DMA channel number. + */ +void DMA_CreateHandle(dma_handle_t *handle, DMA_Type *base, uint32_t channel); + +/*! + * @brief Sets the DMA callback function. + * + * This callback is called in the DMA IRQ handler. Use the callback to do something + * after the current transfer complete. + * + * @param handle DMA handle pointer. + * @param callback DMA callback function pointer. + * @param userData Parameter for callback function. If it is not needed, just set to NULL. + */ +void DMA_SetCallback(dma_handle_t *handle, dma_callback callback, void *userData); + +/*! + * @brief Prepares the DMA transfer configuration structure. + * + * This function prepares the transfer configuration structure according to the user input. + * + * @param config Pointer to the user configuration structure of type dma_transfer_config_t. + * @param srcAddr DMA transfer source address. + * @param srcWidth DMA transfer source address width (byte). + * @param destAddr DMA transfer destination address. + * @param destWidth DMA transfer destination address width (byte). + * @param transferBytes DMA transfer bytes to be transferred. + * @param type DMA transfer type. + */ +void DMA_PrepareTransfer(dma_transfer_config_t *config, + void *srcAddr, + uint32_t srcWidth, + void *destAddr, + uint32_t destWidth, + uint32_t transferBytes, + dma_transfer_type_t type); + +/*! + * @brief Submits the DMA transfer request. + * + * This function submits the DMA transfer request according to the transfer configuration structure. + * + * @param handle DMA handle pointer. + * @param config Pointer to DMA transfer configuration structure. + * @param options Additional configurations for transfer. Use + * the defined dma_transfer_options_t type. + * @retval kStatus_DMA_Success It indicates that the DMA submit transfer request succeeded. + * @retval kStatus_DMA_Busy It indicates that the DMA is busy. Submit transfer request is not allowed. + * @note This function can't process multi transfer request. + */ +status_t DMA_SubmitTransfer(dma_handle_t *handle, const dma_transfer_config_t *config, uint32_t options); + +/*! + * @brief DMA starts a transfer. + * + * This function enables the channel request. Call this function + * after submitting a transfer request. + * + * @param handle DMA handle pointer. + * @retval kStatus_DMA_Success It indicates that the DMA start transfer succeed. + * @retval kStatus_DMA_Busy It indicates that the DMA has started a transfer. + */ +static inline void DMA_StartTransfer(dma_handle_t *handle) +{ + assert(handle != NULL); + + handle->base->DMA[handle->channel].DCR |= DMA_DCR_ERQ_MASK; +} + +/*! + * @brief DMA stops a transfer. + * + * This function disables the channel request to stop a DMA transfer. + * The transfer can be resumed by calling the DMA_StartTransfer. + * + * @param handle DMA handle pointer. + */ +static inline void DMA_StopTransfer(dma_handle_t *handle) +{ + assert(handle != NULL); + + handle->base->DMA[handle->channel].DCR &= ~DMA_DCR_ERQ_MASK; +} + +/*! + * @brief DMA aborts a transfer. + * + * This function disables the channel request and clears all status bits. + * Submit another transfer after calling this API. + * + * @param handle DMA handle pointer. + */ +void DMA_AbortTransfer(dma_handle_t *handle); + +/*! + * @brief DMA IRQ handler for current transfer complete. + * + * This function clears the channel interrupt flag and calls + * the callback function if it is not NULL. + * + * @param handle DMA handle pointer. + */ +void DMA_HandleIRQ(dma_handle_t *handle); + +/* @} */ + +#if defined(__cplusplus) +} +#endif /* __cplusplus */ + +/* @}*/ + +#endif /* _FSL_DMA_H_ */ diff --git a/source/hic_hal/freescale/kl27z/MKL27Z4/fsl_dmamux.h b/source/hic_hal/freescale/kl27z/MKL27Z4/fsl_dmamux.h new file mode 100644 index 0000000000..de0c21bcf2 --- /dev/null +++ b/source/hic_hal/freescale/kl27z/MKL27Z4/fsl_dmamux.h @@ -0,0 +1,177 @@ +/* + * Copyright (c) 2015, Freescale Semiconductor, Inc. + * Copyright 2016-2017 NXP + * All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef _FSL_DMAMUX_H_ +#define _FSL_DMAMUX_H_ + +#include "fsl_common.h" + +/*! + * @addtogroup dmamux + * @{ + */ + +/******************************************************************************* + * Definitions + ******************************************************************************/ + +/*! @name Driver version */ +/*@{*/ +/*! @brief DMAMUX driver version 2.0.4. */ +#define FSL_DMAMUX_DRIVER_VERSION (MAKE_VERSION(2, 0, 4)) +/*@}*/ + +/******************************************************************************* + * API + ******************************************************************************/ + +#if defined(__cplusplus) +extern "C" { +#endif /* __cplusplus */ + +/*! + * @name DMAMUX Initialization and de-initialization + * @{ + */ + +/*! + * @brief Initializes the DMAMUX peripheral. + * + * This function ungates the DMAMUX clock. + * + * @param base DMAMUX peripheral base address. + * + */ +void DMAMUX_Init(DMAMUX_Type *base); + +/*! + * @brief Deinitializes the DMAMUX peripheral. + * + * This function gates the DMAMUX clock. + * + * @param base DMAMUX peripheral base address. + */ +void DMAMUX_Deinit(DMAMUX_Type *base); + +/* @} */ +/*! + * @name DMAMUX Channel Operation + * @{ + */ + +/*! + * @brief Enables the DMAMUX channel. + * + * This function enables the DMAMUX channel. + * + * @param base DMAMUX peripheral base address. + * @param channel DMAMUX channel number. + */ +static inline void DMAMUX_EnableChannel(DMAMUX_Type *base, uint32_t channel) +{ + assert(channel < (uint32_t)FSL_FEATURE_DMAMUX_MODULE_CHANNEL); + + base->CHCFG[channel] |= DMAMUX_CHCFG_ENBL_MASK; +} + +/*! + * @brief Disables the DMAMUX channel. + * + * This function disables the DMAMUX channel. + * + * @note The user must disable the DMAMUX channel before configuring it. + * @param base DMAMUX peripheral base address. + * @param channel DMAMUX channel number. + */ +static inline void DMAMUX_DisableChannel(DMAMUX_Type *base, uint32_t channel) +{ + assert(channel < (uint32_t)FSL_FEATURE_DMAMUX_MODULE_CHANNEL); + + base->CHCFG[channel] &= ~(uint8_t)DMAMUX_CHCFG_ENBL_MASK; +} + +/*! + * @brief Configures the DMAMUX channel source. + * + * @param base DMAMUX peripheral base address. + * @param channel DMAMUX channel number. + * @param source Channel source, which is used to trigger the DMA transfer. + */ +static inline void DMAMUX_SetSource(DMAMUX_Type *base, uint32_t channel, uint32_t source) +{ + assert(channel < (uint32_t)FSL_FEATURE_DMAMUX_MODULE_CHANNEL); + + base->CHCFG[channel] = (uint8_t)((base->CHCFG[channel] & ~DMAMUX_CHCFG_SOURCE_MASK) | DMAMUX_CHCFG_SOURCE(source)); +} + +#if defined(FSL_FEATURE_DMAMUX_HAS_TRIG) && FSL_FEATURE_DMAMUX_HAS_TRIG > 0U +/*! + * @brief Enables the DMAMUX period trigger. + * + * This function enables the DMAMUX period trigger feature. + * + * @param base DMAMUX peripheral base address. + * @param channel DMAMUX channel number. + */ +static inline void DMAMUX_EnablePeriodTrigger(DMAMUX_Type *base, uint32_t channel) +{ + assert(channel < (uint32_t)FSL_FEATURE_DMAMUX_MODULE_CHANNEL); + + base->CHCFG[channel] |= DMAMUX_CHCFG_TRIG_MASK; +} + +/*! + * @brief Disables the DMAMUX period trigger. + * + * This function disables the DMAMUX period trigger. + * + * @param base DMAMUX peripheral base address. + * @param channel DMAMUX channel number. + */ +static inline void DMAMUX_DisablePeriodTrigger(DMAMUX_Type *base, uint32_t channel) +{ + assert(channel < (uint32_t)FSL_FEATURE_DMAMUX_MODULE_CHANNEL); + + base->CHCFG[channel] &= ~(uint8_t)DMAMUX_CHCFG_TRIG_MASK; +} +#endif /* FSL_FEATURE_DMAMUX_HAS_TRIG */ + +#if (defined(FSL_FEATURE_DMAMUX_HAS_A_ON) && FSL_FEATURE_DMAMUX_HAS_A_ON) +/*! + * @brief Enables the DMA channel to be always ON. + * + * This function enables the DMAMUX channel always ON feature. + * + * @param base DMAMUX peripheral base address. + * @param channel DMAMUX channel number. + * @param enable Switcher of the always ON feature. "true" means enabled, "false" means disabled. + */ +static inline void DMAMUX_EnableAlwaysOn(DMAMUX_Type *base, uint32_t channel, bool enable) +{ + assert(channel < (uint32_t)FSL_FEATURE_DMAMUX_MODULE_CHANNEL); + + if (enable) + { + base->CHCFG[channel] |= DMAMUX_CHCFG_A_ON_MASK; + } + else + { + base->CHCFG[channel] &= ~DMAMUX_CHCFG_A_ON_MASK; + } +} +#endif /* FSL_FEATURE_DMAMUX_HAS_A_ON */ + +/* @} */ + +#if defined(__cplusplus) +} +#endif /* __cplusplus */ + +/* @} */ + +#endif /* _FSL_DMAMUX_H_ */ diff --git a/source/hic_hal/freescale/kl27z/MKL27Z4/fsl_lpuart.c b/source/hic_hal/freescale/kl27z/MKL27Z4/fsl_lpuart.c new file mode 100644 index 0000000000..379fd8aec0 --- /dev/null +++ b/source/hic_hal/freescale/kl27z/MKL27Z4/fsl_lpuart.c @@ -0,0 +1,2051 @@ +/* + * Copyright (c) 2015-2016, Freescale Semiconductor, Inc. + * Copyright 2016-2020 NXP + * All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include "fsl_lpuart.h" + +/******************************************************************************* + * Definitions + ******************************************************************************/ + +/* Component ID definition, used by tools. */ +#ifndef FSL_COMPONENT_ID +#define FSL_COMPONENT_ID "platform.drivers.lpuart" +#endif + +/* LPUART transfer state. */ +enum +{ + kLPUART_TxIdle, /*!< TX idle. */ + kLPUART_TxBusy, /*!< TX busy. */ + kLPUART_RxIdle, /*!< RX idle. */ + kLPUART_RxBusy /*!< RX busy. */ +}; + +/* Typedef for interrupt handler. */ +typedef void (*lpuart_isr_t)(LPUART_Type *base, lpuart_handle_t *handle); + +/******************************************************************************* + * Prototypes + ******************************************************************************/ +/*! + * @brief Check whether the RX ring buffer is full. + * + * @userData handle LPUART handle pointer. + * @retval true RX ring buffer is full. + * @retval false RX ring buffer is not full. + */ +static bool LPUART_TransferIsRxRingBufferFull(LPUART_Type *base, lpuart_handle_t *handle); + +/*! + * @brief Write to TX register using non-blocking method. + * + * This function writes data to the TX register directly, upper layer must make + * sure the TX register is empty or TX FIFO has empty room before calling this function. + * + * @note This function does not check whether all the data has been sent out to bus, + * so before disable TX, check kLPUART_TransmissionCompleteFlag to ensure the TX is + * finished. + * + * @param base LPUART peripheral base address. + * @param data Start address of the data to write. + * @param length Size of the buffer to be sent. + */ +static void LPUART_WriteNonBlocking(LPUART_Type *base, const uint8_t *data, size_t length); + +/*! + * @brief Read RX register using non-blocking method. + * + * This function reads data from the TX register directly, upper layer must make + * sure the RX register is full or TX FIFO has data before calling this function. + * + * @param base LPUART peripheral base address. + * @param data Start address of the buffer to store the received data. + * @param length Size of the buffer. + */ +static void LPUART_ReadNonBlocking(LPUART_Type *base, uint8_t *data, size_t length); + +/******************************************************************************* + * Variables + ******************************************************************************/ +/* Array of LPUART peripheral base address. */ +static LPUART_Type *const s_lpuartBases[] = LPUART_BASE_PTRS; +/* Array of LPUART handle. */ +static lpuart_handle_t *s_lpuartHandle[ARRAY_SIZE(s_lpuartBases)]; +/* Array of LPUART IRQ number. */ +#if defined(FSL_FEATURE_LPUART_HAS_SEPARATE_RX_TX_IRQ) && FSL_FEATURE_LPUART_HAS_SEPARATE_RX_TX_IRQ +static const IRQn_Type s_lpuartRxIRQ[] = LPUART_RX_IRQS; +static const IRQn_Type s_lpuartTxIRQ[] = LPUART_TX_IRQS; +#else +static const IRQn_Type s_lpuartIRQ[] = LPUART_RX_TX_IRQS; +#endif +#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) +/* Array of LPUART clock name. */ +static const clock_ip_name_t s_lpuartClock[] = LPUART_CLOCKS; + +#if defined(LPUART_PERIPH_CLOCKS) +/* Array of LPUART functional clock name. */ +static const clock_ip_name_t s_lpuartPeriphClocks[] = LPUART_PERIPH_CLOCKS; +#endif + +#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */ + +/* LPUART ISR for transactional APIs. */ +#if defined(__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050) +static lpuart_isr_t s_lpuartIsr = (lpuart_isr_t)DefaultISR; +#else +static lpuart_isr_t s_lpuartIsr; +#endif + +/******************************************************************************* + * Code + ******************************************************************************/ +/*! + * brief Get the LPUART instance from peripheral base address. + * + * param base LPUART peripheral base address. + * return LPUART instance. + */ +uint32_t LPUART_GetInstance(LPUART_Type *base) +{ + uint32_t instance; + + /* Find the instance index from base address mappings. */ + for (instance = 0U; instance < ARRAY_SIZE(s_lpuartBases); instance++) + { + if (s_lpuartBases[instance] == base) + { + break; + } + } + + assert(instance < ARRAY_SIZE(s_lpuartBases)); + + return instance; +} + +/*! + * brief Get the length of received data in RX ring buffer. + * + * userData handle LPUART handle pointer. + * return Length of received data in RX ring buffer. + */ +size_t LPUART_TransferGetRxRingBufferLength(LPUART_Type *base, lpuart_handle_t *handle) +{ + assert(NULL != handle); + + size_t size; + size_t tmpRxRingBufferSize = handle->rxRingBufferSize; + uint16_t tmpRxRingBufferTail = handle->rxRingBufferTail; + uint16_t tmpRxRingBufferHead = handle->rxRingBufferHead; + + if (tmpRxRingBufferTail > tmpRxRingBufferHead) + { + size = ((size_t)tmpRxRingBufferHead + tmpRxRingBufferSize - (size_t)tmpRxRingBufferTail); + } + else + { + size = ((size_t)tmpRxRingBufferHead - (size_t)tmpRxRingBufferTail); + } + + return size; +} + +static bool LPUART_TransferIsRxRingBufferFull(LPUART_Type *base, lpuart_handle_t *handle) +{ + assert(NULL != handle); + + bool full; + + if (LPUART_TransferGetRxRingBufferLength(base, handle) == (handle->rxRingBufferSize - 1U)) + { + full = true; + } + else + { + full = false; + } + return full; +} + +static void LPUART_WriteNonBlocking(LPUART_Type *base, const uint8_t *data, size_t length) +{ + assert(NULL != data); + + size_t i; + + /* The Non Blocking write data API assume user have ensured there is enough space in + peripheral to write. */ + for (i = 0; i < length; i++) + { + base->DATA = data[i]; + } +} + +static void LPUART_ReadNonBlocking(LPUART_Type *base, uint8_t *data, size_t length) +{ + assert(NULL != data); + + size_t i; +#if defined(FSL_FEATURE_LPUART_HAS_7BIT_DATA_SUPPORT) && FSL_FEATURE_LPUART_HAS_7BIT_DATA_SUPPORT + uint32_t ctrl = base->CTRL; + bool isSevenDataBits = (((ctrl & LPUART_CTRL_M7_MASK) != 0U) || + (((ctrl & LPUART_CTRL_M_MASK) == 0U) && ((ctrl & LPUART_CTRL_PE_MASK) != 0U))); +#endif + + /* The Non Blocking read data API assume user have ensured there is enough space in + peripheral to write. */ + for (i = 0; i < length; i++) + { +#if defined(FSL_FEATURE_LPUART_HAS_7BIT_DATA_SUPPORT) && FSL_FEATURE_LPUART_HAS_7BIT_DATA_SUPPORT + if (isSevenDataBits) + { + data[i] = (uint8_t)(base->DATA & 0x7FU); + } + else + { + data[i] = (uint8_t)base->DATA; + } +#else + data[i] = (uint8_t)(base->DATA); +#endif + } +} + +/*! + * brief Initializes an LPUART instance with the user configuration structure and the peripheral clock. + * + * This function configures the LPUART module with user-defined settings. Call the LPUART_GetDefaultConfig() function + * to configure the configuration structure and get the default configuration. + * The example below shows how to use this API to configure the LPUART. + * code + * lpuart_config_t lpuartConfig; + * lpuartConfig.baudRate_Bps = 115200U; + * lpuartConfig.parityMode = kLPUART_ParityDisabled; + * lpuartConfig.dataBitsCount = kLPUART_EightDataBits; + * lpuartConfig.isMsb = false; + * lpuartConfig.stopBitCount = kLPUART_OneStopBit; + * lpuartConfig.txFifoWatermark = 0; + * lpuartConfig.rxFifoWatermark = 1; + * LPUART_Init(LPUART1, &lpuartConfig, 20000000U); + * endcode + * + * param base LPUART peripheral base address. + * param config Pointer to a user-defined configuration structure. + * param srcClock_Hz LPUART clock source frequency in HZ. + * retval kStatus_LPUART_BaudrateNotSupport Baudrate is not support in current clock source. + * retval kStatus_Success LPUART initialize succeed + */ +status_t LPUART_Init(LPUART_Type *base, const lpuart_config_t *config, uint32_t srcClock_Hz) +{ + assert(NULL != config); + assert(0U < config->baudRate_Bps); +#if defined(FSL_FEATURE_LPUART_HAS_FIFO) && FSL_FEATURE_LPUART_HAS_FIFO + assert((uint8_t)FSL_FEATURE_LPUART_FIFO_SIZEn(base) >= config->txFifoWatermark); + assert((uint8_t)FSL_FEATURE_LPUART_FIFO_SIZEn(base) >= config->rxFifoWatermark); +#endif + + status_t status = kStatus_Success; + uint32_t temp; + uint16_t sbr, sbrTemp; + uint8_t osr, osrTemp; + uint32_t tempDiff, calculatedBaud, baudDiff; + + /* This LPUART instantiation uses a slightly different baud rate calculation + * The idea is to use the best OSR (over-sampling rate) possible + * Note, OSR is typically hard-set to 16 in other LPUART instantiations + * loop to find the best OSR value possible, one that generates minimum baudDiff + * iterate through the rest of the supported values of OSR */ + + baudDiff = config->baudRate_Bps; + osr = 0U; + sbr = 0U; + for (osrTemp = 4U; osrTemp <= 32U; osrTemp++) + { + /* calculate the temporary sbr value */ + sbrTemp = (uint16_t)((srcClock_Hz * 10U / (config->baudRate_Bps * (uint32_t)osrTemp) + 5U) / 10U); + /*set sbrTemp to 1 if the sourceClockInHz can not satisfy the desired baud rate*/ + if (sbrTemp == 0U) + { + sbrTemp = 1U; + } + /* Calculate the baud rate based on the temporary OSR and SBR values */ + calculatedBaud = (srcClock_Hz / ((uint32_t)osrTemp * (uint32_t)sbrTemp)); + tempDiff = calculatedBaud > config->baudRate_Bps ? (calculatedBaud - config->baudRate_Bps) : + (config->baudRate_Bps - calculatedBaud); + + if (tempDiff <= baudDiff) + { + baudDiff = tempDiff; + osr = osrTemp; /* update and store the best OSR value calculated */ + sbr = sbrTemp; /* update store the best SBR value calculated */ + } + } + + /* Check to see if actual baud rate is within 3% of desired baud rate + * based on the best calculate OSR value */ + if (baudDiff > ((config->baudRate_Bps / 100U) * 3U)) + { + /* Unacceptable baud rate difference of more than 3%*/ + status = kStatus_LPUART_BaudrateNotSupport; + } + else + { +#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) + + uint32_t instance = LPUART_GetInstance(base); + + /* Enable lpuart clock */ + CLOCK_EnableClock(s_lpuartClock[instance]); +#if defined(LPUART_PERIPH_CLOCKS) + CLOCK_EnableClock(s_lpuartPeriphClocks[instance]); +#endif + +#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */ + +#if defined(FSL_FEATURE_LPUART_HAS_GLOBAL) && FSL_FEATURE_LPUART_HAS_GLOBAL + /*Reset all internal logic and registers, except the Global Register */ + LPUART_SoftwareReset(base); +#else + /* Disable LPUART TX RX before setting. */ + base->CTRL &= ~(LPUART_CTRL_TE_MASK | LPUART_CTRL_RE_MASK); +#endif + + temp = base->BAUD; + + /* Acceptable baud rate, check if OSR is between 4x and 7x oversampling. + * If so, then "BOTHEDGE" sampling must be turned on */ + if ((osr > 3U) && (osr < 8U)) + { + temp |= LPUART_BAUD_BOTHEDGE_MASK; + } + + /* program the osr value (bit value is one less than actual value) */ + temp &= ~LPUART_BAUD_OSR_MASK; + temp |= LPUART_BAUD_OSR((uint32_t)osr - 1UL); + + /* write the sbr value to the BAUD registers */ + temp &= ~LPUART_BAUD_SBR_MASK; + base->BAUD = temp | LPUART_BAUD_SBR(sbr); + + /* Set bit count and parity mode. */ + base->BAUD &= ~LPUART_BAUD_M10_MASK; + + temp = base->CTRL & ~(LPUART_CTRL_PE_MASK | LPUART_CTRL_PT_MASK | LPUART_CTRL_M_MASK | LPUART_CTRL_ILT_MASK | + LPUART_CTRL_IDLECFG_MASK); + + temp |= (uint8_t)config->parityMode | LPUART_CTRL_IDLECFG(config->rxIdleConfig) | + LPUART_CTRL_ILT(config->rxIdleType); + +#if defined(FSL_FEATURE_LPUART_HAS_7BIT_DATA_SUPPORT) && FSL_FEATURE_LPUART_HAS_7BIT_DATA_SUPPORT + if (kLPUART_SevenDataBits == config->dataBitsCount) + { + if (kLPUART_ParityDisabled != config->parityMode) + { + temp &= ~LPUART_CTRL_M7_MASK; /* Seven data bits and one parity bit */ + } + else + { + temp |= LPUART_CTRL_M7_MASK; + } + } + else +#endif + { + if (kLPUART_ParityDisabled != config->parityMode) + { + temp |= LPUART_CTRL_M_MASK; /* Eight data bits and one parity bit */ + } + } + + base->CTRL = temp; + +#if defined(FSL_FEATURE_LPUART_HAS_STOP_BIT_CONFIG_SUPPORT) && FSL_FEATURE_LPUART_HAS_STOP_BIT_CONFIG_SUPPORT + /* set stop bit per char */ + temp = base->BAUD & ~LPUART_BAUD_SBNS_MASK; + base->BAUD = temp | LPUART_BAUD_SBNS((uint8_t)config->stopBitCount); +#endif + +#if defined(FSL_FEATURE_LPUART_HAS_FIFO) && FSL_FEATURE_LPUART_HAS_FIFO + /* Set tx/rx WATER watermark + Note: + Take care of the RX FIFO, RX interrupt request only assert when received bytes + equal or more than RX water mark, there is potential issue if RX water + mark larger than 1. + For example, if RX FIFO water mark is 2, upper layer needs 5 bytes and + 5 bytes are received. the last byte will be saved in FIFO but not trigger + RX interrupt because the water mark is 2. + */ + base->WATER = (((uint32_t)(config->rxFifoWatermark) << 16U) | config->txFifoWatermark); + + /* Enable tx/rx FIFO */ + base->FIFO |= (LPUART_FIFO_TXFE_MASK | LPUART_FIFO_RXFE_MASK); + + /* Flush FIFO */ + base->FIFO |= (LPUART_FIFO_TXFLUSH_MASK | LPUART_FIFO_RXFLUSH_MASK); +#endif + + /* Clear all status flags */ + temp = (LPUART_STAT_RXEDGIF_MASK | LPUART_STAT_IDLE_MASK | LPUART_STAT_OR_MASK | LPUART_STAT_NF_MASK | + LPUART_STAT_FE_MASK | LPUART_STAT_PF_MASK); + +#if defined(FSL_FEATURE_LPUART_HAS_LIN_BREAK_DETECT) && FSL_FEATURE_LPUART_HAS_LIN_BREAK_DETECT + temp |= LPUART_STAT_LBKDIF_MASK; +#endif + +#if defined(FSL_FEATURE_LPUART_HAS_ADDRESS_MATCHING) && FSL_FEATURE_LPUART_HAS_ADDRESS_MATCHING + temp |= (LPUART_STAT_MA1F_MASK | LPUART_STAT_MA2F_MASK); +#endif + +#if defined(FSL_FEATURE_LPUART_HAS_MODEM_SUPPORT) && FSL_FEATURE_LPUART_HAS_MODEM_SUPPORT + /* Set the CTS configuration/TX CTS source. */ + base->MODIR |= LPUART_MODIR_TXCTSC(config->txCtsConfig) | LPUART_MODIR_TXCTSSRC(config->txCtsSource); + if (true == config->enableRxRTS) + { + /* Enable the receiver RTS(request-to-send) function. */ + base->MODIR |= LPUART_MODIR_RXRTSE_MASK; + } + if (true == config->enableTxCTS) + { + /* Enable the CTS(clear-to-send) function. */ + base->MODIR |= LPUART_MODIR_TXCTSE_MASK; + } +#endif + + /* Set data bits order. */ + if (true == config->isMsb) + { + temp |= LPUART_STAT_MSBF_MASK; + } + else + { + temp &= ~LPUART_STAT_MSBF_MASK; + } + + base->STAT |= temp; + + /* Enable TX/RX base on configure structure. */ + temp = base->CTRL; + if (true == config->enableTx) + { + temp |= LPUART_CTRL_TE_MASK; + } + + if (true == config->enableRx) + { + temp |= LPUART_CTRL_RE_MASK; + } + + base->CTRL = temp; + } + + return status; +} +/*! + * brief Deinitializes a LPUART instance. + * + * This function waits for transmit to complete, disables TX and RX, and disables the LPUART clock. + * + * param base LPUART peripheral base address. + */ +void LPUART_Deinit(LPUART_Type *base) +{ + uint32_t temp; + +#if defined(FSL_FEATURE_LPUART_HAS_FIFO) && FSL_FEATURE_LPUART_HAS_FIFO + /* Wait tx FIFO send out*/ + while (0U != ((base->WATER & LPUART_WATER_TXCOUNT_MASK) >> LPUART_WATER_TXWATER_SHIFT)) + { + } +#endif + /* Wait last char shift out */ + while (0U == (base->STAT & LPUART_STAT_TC_MASK)) + { + } + + /* Clear all status flags */ + temp = (LPUART_STAT_RXEDGIF_MASK | LPUART_STAT_IDLE_MASK | LPUART_STAT_OR_MASK | LPUART_STAT_NF_MASK | + LPUART_STAT_FE_MASK | LPUART_STAT_PF_MASK); + +#if defined(FSL_FEATURE_LPUART_HAS_LIN_BREAK_DETECT) && FSL_FEATURE_LPUART_HAS_LIN_BREAK_DETECT + temp |= LPUART_STAT_LBKDIF_MASK; +#endif + +#if defined(FSL_FEATURE_LPUART_HAS_ADDRESS_MATCHING) && FSL_FEATURE_LPUART_HAS_ADDRESS_MATCHING + temp |= (LPUART_STAT_MA1F_MASK | LPUART_STAT_MA2F_MASK); +#endif + + base->STAT |= temp; + + /* Disable the module. */ + base->CTRL = 0U; + +#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) + uint32_t instance = LPUART_GetInstance(base); + + /* Disable lpuart clock */ + CLOCK_DisableClock(s_lpuartClock[instance]); + +#if defined(LPUART_PERIPH_CLOCKS) + CLOCK_DisableClock(s_lpuartPeriphClocks[instance]); +#endif + +#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */ +} + +/*! + * brief Gets the default configuration structure. + * + * This function initializes the LPUART configuration structure to a default value. The default + * values are: + * lpuartConfig->baudRate_Bps = 115200U; + * lpuartConfig->parityMode = kLPUART_ParityDisabled; + * lpuartConfig->dataBitsCount = kLPUART_EightDataBits; + * lpuartConfig->isMsb = false; + * lpuartConfig->stopBitCount = kLPUART_OneStopBit; + * lpuartConfig->txFifoWatermark = 0; + * lpuartConfig->rxFifoWatermark = 1; + * lpuartConfig->rxIdleType = kLPUART_IdleTypeStartBit; + * lpuartConfig->rxIdleConfig = kLPUART_IdleCharacter1; + * lpuartConfig->enableTx = false; + * lpuartConfig->enableRx = false; + * + * param config Pointer to a configuration structure. + */ +void LPUART_GetDefaultConfig(lpuart_config_t *config) +{ + assert(NULL != config); + + /* Initializes the configure structure to zero. */ + (void)memset(config, 0, sizeof(*config)); + + config->baudRate_Bps = 115200U; + config->parityMode = kLPUART_ParityDisabled; + config->dataBitsCount = kLPUART_EightDataBits; + config->isMsb = false; +#if defined(FSL_FEATURE_LPUART_HAS_STOP_BIT_CONFIG_SUPPORT) && FSL_FEATURE_LPUART_HAS_STOP_BIT_CONFIG_SUPPORT + config->stopBitCount = kLPUART_OneStopBit; +#endif +#if defined(FSL_FEATURE_LPUART_HAS_FIFO) && FSL_FEATURE_LPUART_HAS_FIFO + config->txFifoWatermark = 0U; + config->rxFifoWatermark = 0U; +#endif +#if defined(FSL_FEATURE_LPUART_HAS_MODEM_SUPPORT) && FSL_FEATURE_LPUART_HAS_MODEM_SUPPORT + config->enableRxRTS = false; + config->enableTxCTS = false; + config->txCtsConfig = kLPUART_CtsSampleAtStart; + config->txCtsSource = kLPUART_CtsSourcePin; +#endif + config->rxIdleType = kLPUART_IdleTypeStartBit; + config->rxIdleConfig = kLPUART_IdleCharacter1; + config->enableTx = false; + config->enableRx = false; +} + +/*! + * brief Sets the LPUART instance baudrate. + * + * This function configures the LPUART module baudrate. This function is used to update + * the LPUART module baudrate after the LPUART module is initialized by the LPUART_Init. + * code + * LPUART_SetBaudRate(LPUART1, 115200U, 20000000U); + * endcode + * + * param base LPUART peripheral base address. + * param baudRate_Bps LPUART baudrate to be set. + * param srcClock_Hz LPUART clock source frequency in HZ. + * retval kStatus_LPUART_BaudrateNotSupport Baudrate is not supported in the current clock source. + * retval kStatus_Success Set baudrate succeeded. + */ +status_t LPUART_SetBaudRate(LPUART_Type *base, uint32_t baudRate_Bps, uint32_t srcClock_Hz) +{ + assert(0U < baudRate_Bps); + + status_t status = kStatus_Success; + uint32_t temp, oldCtrl; + uint16_t sbr, sbrTemp; + uint8_t osr, osrTemp; + uint32_t tempDiff, calculatedBaud, baudDiff; + + /* This LPUART instantiation uses a slightly different baud rate calculation + * The idea is to use the best OSR (over-sampling rate) possible + * Note, OSR is typically hard-set to 16 in other LPUART instantiations + * loop to find the best OSR value possible, one that generates minimum baudDiff + * iterate through the rest of the supported values of OSR */ + + baudDiff = baudRate_Bps; + osr = 0U; + sbr = 0U; + for (osrTemp = 4U; osrTemp <= 32U; osrTemp++) + { + /* calculate the temporary sbr value */ + sbrTemp = (uint16_t)((srcClock_Hz * 10U / (baudRate_Bps * (uint32_t)osrTemp) + 5U) / 10U); + /*set sbrTemp to 1 if the sourceClockInHz can not satisfy the desired baud rate*/ + if (sbrTemp == 0U) + { + sbrTemp = 1U; + } + /* Calculate the baud rate based on the temporary OSR and SBR values */ + calculatedBaud = srcClock_Hz / ((uint32_t)osrTemp * (uint32_t)sbrTemp); + + tempDiff = calculatedBaud > baudRate_Bps ? (calculatedBaud - baudRate_Bps) : (baudRate_Bps - calculatedBaud); + + if (tempDiff <= baudDiff) + { + baudDiff = tempDiff; + osr = osrTemp; /* update and store the best OSR value calculated */ + sbr = sbrTemp; /* update store the best SBR value calculated */ + } + } + + /* Check to see if actual baud rate is within 3% of desired baud rate + * based on the best calculate OSR value */ + if (baudDiff < (uint32_t)((baudRate_Bps / 100U) * 3U)) + { + /* Store CTRL before disable Tx and Rx */ + oldCtrl = base->CTRL; + + /* Disable LPUART TX RX before setting. */ + base->CTRL &= ~(LPUART_CTRL_TE_MASK | LPUART_CTRL_RE_MASK); + + temp = base->BAUD; + + /* Acceptable baud rate, check if OSR is between 4x and 7x oversampling. + * If so, then "BOTHEDGE" sampling must be turned on */ + if ((osr > 3U) && (osr < 8U)) + { + temp |= LPUART_BAUD_BOTHEDGE_MASK; + } + + /* program the osr value (bit value is one less than actual value) */ + temp &= ~LPUART_BAUD_OSR_MASK; + temp |= LPUART_BAUD_OSR((uint32_t)osr - 1UL); + + /* write the sbr value to the BAUD registers */ + temp &= ~LPUART_BAUD_SBR_MASK; + base->BAUD = temp | LPUART_BAUD_SBR(sbr); + + /* Restore CTRL. */ + base->CTRL = oldCtrl; + } + else + { + /* Unacceptable baud rate difference of more than 3%*/ + status = kStatus_LPUART_BaudrateNotSupport; + } + + return status; +} + +/*! + * brief Enables LPUART interrupts according to a provided mask. + * + * This function enables the LPUART interrupts according to a provided mask. The mask + * is a logical OR of enumeration members. See the ref _lpuart_interrupt_enable. + * This examples shows how to enable TX empty interrupt and RX full interrupt: + * code + * LPUART_EnableInterrupts(LPUART1,kLPUART_TxDataRegEmptyInterruptEnable | kLPUART_RxDataRegFullInterruptEnable); + * endcode + * + * param base LPUART peripheral base address. + * param mask The interrupts to enable. Logical OR of ref _uart_interrupt_enable. + */ +void LPUART_EnableInterrupts(LPUART_Type *base, uint32_t mask) +{ + base->BAUD |= ((mask << 8U) & (LPUART_BAUD_LBKDIE_MASK | LPUART_BAUD_RXEDGIE_MASK)); +#if defined(FSL_FEATURE_LPUART_HAS_FIFO) && FSL_FEATURE_LPUART_HAS_FIFO + base->FIFO = (base->FIFO & ~(LPUART_FIFO_TXOF_MASK | LPUART_FIFO_RXUF_MASK)) | + ((mask << 8U) & (LPUART_FIFO_TXOFE_MASK | LPUART_FIFO_RXUFE_MASK)); +#endif + mask &= 0xFFFFFF00U; + base->CTRL |= mask; +} + +/*! + * brief Disables LPUART interrupts according to a provided mask. + * + * This function disables the LPUART interrupts according to a provided mask. The mask + * is a logical OR of enumeration members. See ref _lpuart_interrupt_enable. + * This example shows how to disable the TX empty interrupt and RX full interrupt: + * code + * LPUART_DisableInterrupts(LPUART1,kLPUART_TxDataRegEmptyInterruptEnable | kLPUART_RxDataRegFullInterruptEnable); + * endcode + * + * param base LPUART peripheral base address. + * param mask The interrupts to disable. Logical OR of ref _lpuart_interrupt_enable. + */ +void LPUART_DisableInterrupts(LPUART_Type *base, uint32_t mask) +{ + base->BAUD &= ~((mask << 8U) & (LPUART_BAUD_LBKDIE_MASK | LPUART_BAUD_RXEDGIE_MASK)); +#if defined(FSL_FEATURE_LPUART_HAS_FIFO) && FSL_FEATURE_LPUART_HAS_FIFO + base->FIFO = (base->FIFO & ~(LPUART_FIFO_TXOF_MASK | LPUART_FIFO_RXUF_MASK)) & + ~((mask << 8U) & (LPUART_FIFO_TXOFE_MASK | LPUART_FIFO_RXUFE_MASK)); +#endif + mask &= 0xFFFFFF00U; + base->CTRL &= ~mask; +} + +/*! + * brief Gets enabled LPUART interrupts. + * + * This function gets the enabled LPUART interrupts. The enabled interrupts are returned + * as the logical OR value of the enumerators ref _lpuart_interrupt_enable. To check + * a specific interrupt enable status, compare the return value with enumerators + * in ref _lpuart_interrupt_enable. + * For example, to check whether the TX empty interrupt is enabled: + * code + * uint32_t enabledInterrupts = LPUART_GetEnabledInterrupts(LPUART1); + * + * if (kLPUART_TxDataRegEmptyInterruptEnable & enabledInterrupts) + * { + * ... + * } + * endcode + * + * param base LPUART peripheral base address. + * return LPUART interrupt flags which are logical OR of the enumerators in ref _lpuart_interrupt_enable. + */ +uint32_t LPUART_GetEnabledInterrupts(LPUART_Type *base) +{ + uint32_t temp; + temp = (base->BAUD & (LPUART_BAUD_LBKDIE_MASK | LPUART_BAUD_RXEDGIE_MASK)) >> 8U; +#if defined(FSL_FEATURE_LPUART_HAS_FIFO) && FSL_FEATURE_LPUART_HAS_FIFO + temp |= (base->FIFO & (LPUART_FIFO_TXOFE_MASK | LPUART_FIFO_RXUFE_MASK)) >> 8U; +#endif + temp |= (uint32_t)(base->CTRL & 0xFF0C000u); + + return temp; +} + +/*! + * brief Gets LPUART status flags. + * + * This function gets all LPUART status flags. The flags are returned as the logical + * OR value of the enumerators ref _lpuart_flags. To check for a specific status, + * compare the return value with enumerators in the ref _lpuart_flags. + * For example, to check whether the TX is empty: + * code + * if (kLPUART_TxDataRegEmptyFlag & LPUART_GetStatusFlags(LPUART1)) + * { + * ... + * } + * endcode + * + * param base LPUART peripheral base address. + * return LPUART status flags which are ORed by the enumerators in the _lpuart_flags. + */ +uint32_t LPUART_GetStatusFlags(LPUART_Type *base) +{ + uint32_t temp; + temp = base->STAT; +#if defined(FSL_FEATURE_LPUART_HAS_FIFO) && FSL_FEATURE_LPUART_HAS_FIFO + temp |= (base->FIFO & + (LPUART_FIFO_TXEMPT_MASK | LPUART_FIFO_RXEMPT_MASK | LPUART_FIFO_TXOF_MASK | LPUART_FIFO_RXUF_MASK)) >> + 16U; +#endif + return temp; +} + +/*! + * brief Clears status flags with a provided mask. + * + * This function clears LPUART status flags with a provided mask. Automatically cleared flags + * can't be cleared by this function. + * Flags that can only cleared or set by hardware are: + * kLPUART_TxDataRegEmptyFlag, kLPUART_TransmissionCompleteFlag, kLPUART_RxDataRegFullFlag, + * kLPUART_RxActiveFlag, kLPUART_NoiseErrorInRxDataRegFlag, kLPUART_ParityErrorInRxDataRegFlag, + * kLPUART_TxFifoEmptyFlag,kLPUART_RxFifoEmptyFlag + * Note: This API should be called when the Tx/Rx is idle, otherwise it takes no effects. + * + * param base LPUART peripheral base address. + * param mask the status flags to be cleared. The user can use the enumerators in the + * _lpuart_status_flag_t to do the OR operation and get the mask. + * return 0 succeed, others failed. + * retval kStatus_LPUART_FlagCannotClearManually The flag can't be cleared by this function but + * it is cleared automatically by hardware. + * retval kStatus_Success Status in the mask are cleared. + */ +status_t LPUART_ClearStatusFlags(LPUART_Type *base, uint32_t mask) +{ + uint32_t temp; + status_t status; +#if defined(FSL_FEATURE_LPUART_HAS_FIFO) && FSL_FEATURE_LPUART_HAS_FIFO + temp = (uint32_t)base->FIFO; + temp &= (uint32_t)(~(LPUART_FIFO_TXOF_MASK | LPUART_FIFO_RXUF_MASK)); + temp |= (mask << 16U) & (LPUART_FIFO_TXOF_MASK | LPUART_FIFO_RXUF_MASK); + base->FIFO = temp; +#endif + temp = (uint32_t)base->STAT; +#if defined(FSL_FEATURE_LPUART_HAS_LIN_BREAK_DETECT) && FSL_FEATURE_LPUART_HAS_LIN_BREAK_DETECT + temp &= (uint32_t)(~(LPUART_STAT_LBKDIF_MASK)); + temp |= mask & LPUART_STAT_LBKDIF_MASK; +#endif + temp &= (uint32_t)(~(LPUART_STAT_RXEDGIF_MASK | LPUART_STAT_IDLE_MASK | LPUART_STAT_OR_MASK | LPUART_STAT_NF_MASK | + LPUART_STAT_FE_MASK | LPUART_STAT_PF_MASK)); + temp |= mask & (LPUART_STAT_RXEDGIF_MASK | LPUART_STAT_IDLE_MASK | LPUART_STAT_OR_MASK | LPUART_STAT_NF_MASK | + LPUART_STAT_FE_MASK | LPUART_STAT_PF_MASK); +#if defined(FSL_FEATURE_LPUART_HAS_ADDRESS_MATCHING) && FSL_FEATURE_LPUART_HAS_ADDRESS_MATCHING + temp &= (uint32_t)(~(LPUART_STAT_MA2F_MASK | LPUART_STAT_MA1F_MASK)); + temp |= mask & (LPUART_STAT_MA2F_MASK | LPUART_STAT_MA1F_MASK); +#endif + base->STAT = temp; + /* If some flags still pending. */ + if (0U != (mask & LPUART_GetStatusFlags(base))) + { + /* Some flags can only clear or set by the hardware itself, these flags are: kLPUART_TxDataRegEmptyFlag, + kLPUART_TransmissionCompleteFlag, kLPUART_RxDataRegFullFlag, kLPUART_RxActiveFlag, + kLPUART_NoiseErrorInRxDataRegFlag, kLPUART_ParityErrorInRxDataRegFlag, + kLPUART_TxFifoEmptyFlag, kLPUART_RxFifoEmptyFlag. */ + status = kStatus_LPUART_FlagCannotClearManually; /* flags can not clear manually */ + } + else + { + status = kStatus_Success; + } + + return status; +} + +/*! + * brief Writes to the transmitter register using a blocking method. + * + * This function polls the transmitter register, first waits for the register to be empty or TX FIFO to have room, + * and writes data to the transmitter buffer, then waits for the data to be sent out to bus. + * + * param base LPUART peripheral base address. + * param data Start address of the data to write. + * param length Size of the data to write. + * retval kStatus_LPUART_Timeout Transmission timed out and was aborted. + * retval kStatus_Success Successfully wrote all data. + */ +status_t LPUART_WriteBlocking(LPUART_Type *base, const uint8_t *data, size_t length) +{ + assert(NULL != data); + + const uint8_t *dataAddress = data; + size_t transferSize = length; + +#if UART_RETRY_TIMES + uint32_t waitTimes; +#endif + + while (0U != transferSize) + { +#if UART_RETRY_TIMES + waitTimes = UART_RETRY_TIMES; + while ((0U == (base->STAT & LPUART_STAT_TDRE_MASK)) && (0U != --waitTimes)) +#else + while (0U == (base->STAT & LPUART_STAT_TDRE_MASK)) +#endif + { + } +#if UART_RETRY_TIMES + if (0U == waitTimes) + { + return kStatus_LPUART_Timeout; + } +#endif + base->DATA = *(dataAddress); + dataAddress++; + transferSize--; + } + /* Ensure all the data in the transmit buffer are sent out to bus. */ +#if UART_RETRY_TIMES + waitTimes = UART_RETRY_TIMES; + while ((0U == (base->STAT & LPUART_STAT_TC_MASK)) && (0U != --waitTimes)) +#else + while (0U == (base->STAT & LPUART_STAT_TC_MASK)) +#endif + { + } +#if UART_RETRY_TIMES + if (0U == waitTimes) + { + return kStatus_LPUART_Timeout; + } +#endif + return kStatus_Success; +} + +/*! + * brief Reads the receiver data register using a blocking method. + * + * This function polls the receiver register, waits for the receiver register full or receiver FIFO + * has data, and reads data from the TX register. + * + * param base LPUART peripheral base address. + * param data Start address of the buffer to store the received data. + * param length Size of the buffer. + * retval kStatus_LPUART_RxHardwareOverrun Receiver overrun happened while receiving data. + * retval kStatus_LPUART_NoiseError Noise error happened while receiving data. + * retval kStatus_LPUART_FramingError Framing error happened while receiving data. + * retval kStatus_LPUART_ParityError Parity error happened while receiving data. + * retval kStatus_LPUART_Timeout Transmission timed out and was aborted. + * retval kStatus_Success Successfully received all data. + */ +status_t LPUART_ReadBlocking(LPUART_Type *base, uint8_t *data, size_t length) +{ + assert(NULL != data); + + status_t status = kStatus_Success; + uint32_t statusFlag; + uint8_t *dataAddress = data; + +#if defined(FSL_FEATURE_LPUART_HAS_7BIT_DATA_SUPPORT) && FSL_FEATURE_LPUART_HAS_7BIT_DATA_SUPPORT + uint32_t ctrl = base->CTRL; + bool isSevenDataBits = (((ctrl & LPUART_CTRL_M7_MASK) != 0U) || + (((ctrl & LPUART_CTRL_M_MASK) == 0U) && ((ctrl & LPUART_CTRL_PE_MASK) != 0U))); +#endif + +#if UART_RETRY_TIMES + uint32_t waitTimes; +#endif + + while (0U != (length--)) + { +#if UART_RETRY_TIMES + waitTimes = UART_RETRY_TIMES; +#endif +#if defined(FSL_FEATURE_LPUART_HAS_FIFO) && FSL_FEATURE_LPUART_HAS_FIFO + while (0U == ((base->WATER & LPUART_WATER_RXCOUNT_MASK) >> LPUART_WATER_RXCOUNT_SHIFT)) +#else + while (0U == (base->STAT & LPUART_STAT_RDRF_MASK)) +#endif + { +#if UART_RETRY_TIMES + if (0U == --waitTimes) + { + status = kStatus_LPUART_Timeout; + break; + } +#endif + statusFlag = LPUART_GetStatusFlags(base); + + if (0U != (statusFlag & (uint32_t)kLPUART_RxOverrunFlag)) + { + status = ((kStatus_Success == LPUART_ClearStatusFlags(base, (uint32_t)kLPUART_RxOverrunFlag)) ? + (kStatus_LPUART_RxHardwareOverrun) : + (kStatus_LPUART_FlagCannotClearManually)); + /* Other error flags(FE, NF, and PF) are prevented from setting once OR is set, no need to check other + * error flags*/ + break; + } + + if (0U != (statusFlag & (uint32_t)kLPUART_ParityErrorFlag)) + { + status = ((kStatus_Success == LPUART_ClearStatusFlags(base, (uint32_t)kLPUART_ParityErrorFlag)) ? + (kStatus_LPUART_ParityError) : + (kStatus_LPUART_FlagCannotClearManually)); + } + + if (0U != (statusFlag & (uint32_t)kLPUART_FramingErrorFlag)) + { + status = ((kStatus_Success == LPUART_ClearStatusFlags(base, (uint32_t)kLPUART_FramingErrorFlag)) ? + (kStatus_LPUART_FramingError) : + (kStatus_LPUART_FlagCannotClearManually)); + } + + if (0U != (statusFlag & (uint32_t)kLPUART_NoiseErrorFlag)) + { + status = ((kStatus_Success == LPUART_ClearStatusFlags(base, (uint32_t)kLPUART_NoiseErrorFlag)) ? + (kStatus_LPUART_NoiseError) : + (kStatus_LPUART_FlagCannotClearManually)); + } + if (kStatus_Success != status) + { + break; + } + } + + if (kStatus_Success == status) + { +#if defined(FSL_FEATURE_LPUART_HAS_7BIT_DATA_SUPPORT) && FSL_FEATURE_LPUART_HAS_7BIT_DATA_SUPPORT + if (isSevenDataBits) + { + *(dataAddress) = (uint8_t)(base->DATA & 0x7FU); + dataAddress++; + } + else + { + *(dataAddress) = (uint8_t)base->DATA; + dataAddress++; + } +#else + *(dataAddress) = (uint8_t)base->DATA; + dataAddress++; +#endif + } + else + { + break; + } + } + + return status; +} + +/*! + * brief Initializes the LPUART handle. + * + * This function initializes the LPUART handle, which can be used for other LPUART + * transactional APIs. Usually, for a specified LPUART instance, + * call this API once to get the initialized handle. + * + * The LPUART driver supports the "background" receiving, which means that user can set up + * an RX ring buffer optionally. Data received is stored into the ring buffer even when the + * user doesn't call the LPUART_TransferReceiveNonBlocking() API. If there is already data received + * in the ring buffer, the user can get the received data from the ring buffer directly. + * The ring buffer is disabled if passing NULL as p ringBuffer. + * + * param base LPUART peripheral base address. + * param handle LPUART handle pointer. + * param callback Callback function. + * param userData User data. + */ +void LPUART_TransferCreateHandle(LPUART_Type *base, + lpuart_handle_t *handle, + lpuart_transfer_callback_t callback, + void *userData) +{ + assert(NULL != handle); + + uint32_t instance; + +#if defined(FSL_FEATURE_LPUART_HAS_7BIT_DATA_SUPPORT) && FSL_FEATURE_LPUART_HAS_7BIT_DATA_SUPPORT + uint32_t ctrl = base->CTRL; + bool isSevenDataBits = (((ctrl & LPUART_CTRL_M7_MASK) != 0U) || + (((ctrl & LPUART_CTRL_M_MASK) == 0U) && ((ctrl & LPUART_CTRL_PE_MASK) != 0U))); +#endif + + /* Zero the handle. */ + (void)memset(handle, 0, sizeof(lpuart_handle_t)); + + /* Set the TX/RX state. */ + handle->rxState = (uint8_t)kLPUART_RxIdle; + handle->txState = (uint8_t)kLPUART_TxIdle; + + /* Set the callback and user data. */ + handle->callback = callback; + handle->userData = userData; + +#if defined(FSL_FEATURE_LPUART_HAS_7BIT_DATA_SUPPORT) && FSL_FEATURE_LPUART_HAS_7BIT_DATA_SUPPORT + /* Initial seven data bits flag */ + handle->isSevenDataBits = isSevenDataBits; +#endif + + /* Get instance from peripheral base address. */ + instance = LPUART_GetInstance(base); + + /* Save the handle in global variables to support the double weak mechanism. */ + s_lpuartHandle[instance] = handle; + + s_lpuartIsr = LPUART_TransferHandleIRQ; + +/* Enable interrupt in NVIC. */ +#if defined(FSL_FEATURE_LPUART_HAS_SEPARATE_RX_TX_IRQ) && FSL_FEATURE_LPUART_HAS_SEPARATE_RX_TX_IRQ + (void)EnableIRQ(s_lpuartRxIRQ[instance]); + (void)EnableIRQ(s_lpuartTxIRQ[instance]); +#else + (void)EnableIRQ(s_lpuartIRQ[instance]); +#endif +} + +/*! + * brief Sets up the RX ring buffer. + * + * This function sets up the RX ring buffer to a specific UART handle. + * + * When the RX ring buffer is used, data received is stored into the ring buffer even when + * the user doesn't call the UART_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 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 LPUART peripheral base address. + * param handle LPUART handle pointer. + * param ringBuffer Start address of ring buffer for background receiving. Pass NULL to disable the ring buffer. + * param ringBufferSize size of the ring buffer. + */ +void LPUART_TransferStartRingBuffer(LPUART_Type *base, + lpuart_handle_t *handle, + uint8_t *ringBuffer, + size_t ringBufferSize) +{ + assert(NULL != handle); + assert(NULL != ringBuffer); + + /* Setup the ring buffer address */ + handle->rxRingBuffer = ringBuffer; + handle->rxRingBufferSize = ringBufferSize; + handle->rxRingBufferHead = 0U; + handle->rxRingBufferTail = 0U; + + /* Enable the interrupt to accept the data when user need the ring buffer. */ + LPUART_EnableInterrupts( + base, (uint32_t)kLPUART_RxDataRegFullInterruptEnable | (uint32_t)kLPUART_RxOverrunInterruptEnable); +} + +/*! + * brief Aborts the background transfer and uninstalls the ring buffer. + * + * This function aborts the background transfer and uninstalls the ring buffer. + * + * param base LPUART peripheral base address. + * param handle LPUART handle pointer. + */ +void LPUART_TransferStopRingBuffer(LPUART_Type *base, lpuart_handle_t *handle) +{ + assert(NULL != handle); + + if (handle->rxState == (uint8_t)kLPUART_RxIdle) + { + LPUART_DisableInterrupts( + base, (uint32_t)kLPUART_RxDataRegFullInterruptEnable | (uint32_t)kLPUART_RxOverrunInterruptEnable); + } + + handle->rxRingBuffer = NULL; + handle->rxRingBufferSize = 0U; + handle->rxRingBufferHead = 0U; + handle->rxRingBufferTail = 0U; +} + +/*! + * brief Transmits a buffer of data using the interrupt method. + * + * This function send data using an interrupt method. This is a non-blocking function, which + * returns directly without waiting for all data written to the transmitter register. When + * all data is written to the TX register in the ISR, the LPUART driver calls the callback + * function and passes the ref kStatus_LPUART_TxIdle as status parameter. + * + * note The kStatus_LPUART_TxIdle is passed to the upper layer when all data are written + * to the TX register. However, there is no check to ensure that all the data sent out. Before disabling the TX, + * check the kLPUART_TransmissionCompleteFlag to ensure that the transmit is finished. + * + * param base LPUART peripheral base address. + * param handle LPUART handle pointer. + * param xfer LPUART transfer structure, see #lpuart_transfer_t. + * retval kStatus_Success Successfully start the data transmission. + * retval kStatus_LPUART_TxBusy Previous transmission still not finished, data not all written to the TX register. + * retval kStatus_InvalidArgument Invalid argument. + */ +status_t LPUART_TransferSendNonBlocking(LPUART_Type *base, lpuart_handle_t *handle, lpuart_transfer_t *xfer) +{ + assert(NULL != handle); + assert(NULL != xfer); + assert(NULL != xfer->data); + assert(0U != xfer->dataSize); + + status_t status; + + /* Return error if current TX busy. */ + if ((uint8_t)kLPUART_TxBusy == handle->txState) + { + status = kStatus_LPUART_TxBusy; + } + else + { + handle->txData = xfer->data; + handle->txDataSize = xfer->dataSize; + handle->txDataSizeAll = xfer->dataSize; + handle->txState = (uint8_t)kLPUART_TxBusy; + + /* Enable transmitter interrupt. */ + LPUART_EnableInterrupts(base, (uint32_t)kLPUART_TxDataRegEmptyInterruptEnable); + + status = kStatus_Success; + } + + return status; +} + +/*! + * 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 not sent out. + * + * param base LPUART peripheral base address. + * param handle LPUART handle pointer. + */ +void LPUART_TransferAbortSend(LPUART_Type *base, lpuart_handle_t *handle) +{ + assert(NULL != handle); + + LPUART_DisableInterrupts( + base, (uint32_t)kLPUART_TxDataRegEmptyInterruptEnable | (uint32_t)kLPUART_TransmissionCompleteInterruptEnable); + + handle->txDataSize = 0; + handle->txState = (uint8_t)kLPUART_TxIdle; +} + +/*! + * brief Gets 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 an interrupt method. + * + * param base LPUART peripheral base address. + * param handle LPUART 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 LPUART_TransferGetSendCount(LPUART_Type *base, lpuart_handle_t *handle, uint32_t *count) +{ + assert(NULL != handle); + assert(NULL != count); + + status_t status = kStatus_Success; + size_t tmptxDataSize = handle->txDataSize; + + if ((uint8_t)kLPUART_TxIdle == handle->txState) + { + status = kStatus_NoTransferInProgress; + } + else + { +#if defined(FSL_FEATURE_LPUART_HAS_FIFO) && FSL_FEATURE_LPUART_HAS_FIFO + *count = handle->txDataSizeAll - tmptxDataSize - + ((base->WATER & LPUART_WATER_TXCOUNT_MASK) >> LPUART_WATER_TXCOUNT_SHIFT); +#else + if ((base->STAT & (uint32_t)kLPUART_TxDataRegEmptyFlag) != 0U) + { + *count = handle->txDataSizeAll - tmptxDataSize; + } + else + { + *count = handle->txDataSizeAll - tmptxDataSize - 1U; + } +#endif + } + + return status; +} + +/*! + * brief Receives a buffer of data using the interrupt method. + * + * This function receives data using an interrupt method. This is a non-blocking function + * which returns without waiting to ensure that all data are 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 for read, the receive + * request is saved by the LPUART driver. When the new data arrives, the receive request + * is serviced first. When all data is received, the LPUART driver notifies the upper layer + * through a callback function and passes a status parameter ref kStatus_UART_RxIdle. + * For example, the upper layer needs 10 bytes but there are only 5 bytes in ring buffer. + * The 5 bytes are copied to xfer->data, which returns with the + * parameter p receivedBytes set to 5. For the remaining 5 bytes, the newly arrived data is + * saved from xfer->data[5]. When 5 bytes are received, the LPUART 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 xfer->data. When all data is received, the upper layer is notified. + * + * param base LPUART peripheral base address. + * param handle LPUART handle pointer. + * param xfer LPUART transfer structure, see #uart_transfer_t. + * param receivedBytes Bytes received from the ring buffer directly. + * retval kStatus_Success Successfully queue the transfer into the transmit queue. + * retval kStatus_LPUART_RxBusy Previous receive request is not finished. + * retval kStatus_InvalidArgument Invalid argument. + */ +status_t LPUART_TransferReceiveNonBlocking(LPUART_Type *base, + lpuart_handle_t *handle, + lpuart_transfer_t *xfer, + size_t *receivedBytes) +{ + assert(NULL != handle); + assert(NULL != xfer); + assert(NULL != xfer->data); + assert(0U != xfer->dataSize); + + uint32_t i; + status_t status; + /* 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; + + /* How to get data: + 1. If RX ring buffer is not enabled, then save xfer->data and xfer->dataSize + to lpuart 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 lpuart handle, receive data + to this empty space and trigger callback when finished. */ + + if ((uint8_t)kLPUART_RxBusy == handle->rxState) + { + status = kStatus_LPUART_RxBusy; + } + else + { + bytesToReceive = xfer->dataSize; + bytesCurrentReceived = 0; + + /* If RX ring buffer is used. */ + if (NULL != handle->rxRingBuffer) + { + /* Disable LPUART RX IRQ, protect ring buffer. */ + LPUART_DisableInterrupts(base, (uint32_t)kLPUART_RxDataRegFullInterruptEnable); + + /* How many bytes in RX ring buffer currently. */ + bytesToCopy = LPUART_TransferGetRxRingBufferLength(base, handle); + + if (0U != bytesToCopy) + { + bytesToCopy = MIN(bytesToReceive, bytesToCopy); + + bytesToReceive -= bytesToCopy; + + /* Copy data from ring buffer to user memory. */ + for (i = 0U; i < bytesToCopy; i++) + { + xfer->data[bytesCurrentReceived] = handle->rxRingBuffer[handle->rxRingBufferTail]; + bytesCurrentReceived++; + + /* Wrap to 0. Not use modulo (%) because it might be large and slow. */ + if (((uint32_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 (0U != bytesToReceive) + { + /* No data in ring buffer, save the request to LPUART handle. */ + handle->rxData = xfer->data + bytesCurrentReceived; + handle->rxDataSize = bytesToReceive; + handle->rxDataSizeAll = bytesToReceive; + handle->rxState = (uint8_t)kLPUART_RxBusy; + } + /* Enable LPUART RX IRQ if previously enabled. */ + LPUART_EnableInterrupts(base, (uint32_t)kLPUART_RxDataRegFullInterruptEnable); + + /* Call user callback since all data are received. */ + if (0U == bytesToReceive) + { + if (NULL != handle->callback) + { + handle->callback(base, handle, kStatus_LPUART_RxIdle, handle->userData); + } + } + } + /* Ring buffer not used. */ + else + { + handle->rxData = xfer->data + bytesCurrentReceived; + handle->rxDataSize = bytesToReceive; + handle->rxDataSizeAll = bytesToReceive; + handle->rxState = (uint8_t)kLPUART_RxBusy; + + /* Enable RX interrupt. */ + LPUART_EnableInterrupts(base, (uint32_t)kLPUART_RxDataRegFullInterruptEnable | + (uint32_t)kLPUART_RxOverrunInterruptEnable | + (uint32_t)kLPUART_IdleLineInterruptEnable); + } + + /* Return the how many bytes have read. */ + if (NULL != receivedBytes) + { + *receivedBytes = bytesCurrentReceived; + } + + status = kStatus_Success; + } + + return status; +} + +/*! + * 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 LPUART peripheral base address. + * param handle LPUART handle pointer. + */ +void LPUART_TransferAbortReceive(LPUART_Type *base, lpuart_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 RX interrupt. */ + LPUART_DisableInterrupts(base, (uint32_t)kLPUART_RxDataRegFullInterruptEnable | + (uint32_t)kLPUART_RxOverrunInterruptEnable | + (uint32_t)kLPUART_IdleLineInterruptEnable); + } + + handle->rxDataSize = 0U; + handle->rxState = (uint8_t)kLPUART_RxIdle; +} + +/*! + * brief Gets the number of bytes that have been received. + * + * This function gets the number of bytes that have been received. + * + * param base LPUART peripheral base address. + * param handle LPUART 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 LPUART_TransferGetReceiveCount(LPUART_Type *base, lpuart_handle_t *handle, uint32_t *count) +{ + assert(NULL != handle); + assert(NULL != count); + + status_t status = kStatus_Success; + size_t tmprxDataSize = handle->rxDataSize; + + if ((uint8_t)kLPUART_RxIdle == handle->rxState) + { + status = kStatus_NoTransferInProgress; + } + else + { + *count = handle->rxDataSizeAll - tmprxDataSize; + } + + return status; +} + +/*! + * brief LPUART IRQ handle function. + * + * This function handles the LPUART transmit and receive IRQ request. + * + * param base LPUART peripheral base address. + * param handle LPUART handle pointer. + */ +void LPUART_TransferHandleIRQ(LPUART_Type *base, lpuart_handle_t *handle) +{ + assert(NULL != handle); + + uint8_t count; + uint8_t tempCount; + uint32_t status = LPUART_GetStatusFlags(base); + uint32_t enabledInterrupts = LPUART_GetEnabledInterrupts(base); + uint16_t tpmRxRingBufferHead; + uint32_t tpmData; + + /* If RX overrun. */ + if ((uint32_t)kLPUART_RxOverrunFlag == ((uint32_t)kLPUART_RxOverrunFlag & status)) + { + /* Clear overrun flag, otherwise the RX does not work. */ + base->STAT = ((base->STAT & 0x3FE00000U) | LPUART_STAT_OR_MASK); + + /* Trigger callback. */ + if (NULL != (handle->callback)) + { + handle->callback(base, handle, kStatus_LPUART_RxHardwareOverrun, handle->userData); + } + } + + /* If IDLE flag is set and the IDLE interrupt is enabled. */ + if ((0U != ((uint32_t)kLPUART_IdleLineFlag & status)) && + (0U != ((uint32_t)kLPUART_IdleLineInterruptEnable & enabledInterrupts))) + { +#if defined(FSL_FEATURE_LPUART_HAS_FIFO) && FSL_FEATURE_LPUART_HAS_FIFO + count = ((uint8_t)((base->WATER & LPUART_WATER_RXCOUNT_MASK) >> LPUART_WATER_RXCOUNT_SHIFT)); + + while ((0U != handle->rxDataSize) && (0U != count)) + { + tempCount = (uint8_t)MIN(handle->rxDataSize, count); + + /* Using non block API to read the data from the registers. */ + LPUART_ReadNonBlocking(base, handle->rxData, tempCount); + handle->rxData += tempCount; + handle->rxDataSize -= tempCount; + count -= tempCount; + + /* If rxDataSize is 0, disable idle line interrupt.*/ + if (0U == (handle->rxDataSize)) + { + handle->rxState = (uint8_t)kLPUART_RxIdle; + + LPUART_DisableInterrupts( + base, (uint32_t)kLPUART_RxDataRegFullInterruptEnable | (uint32_t)kLPUART_RxOverrunInterruptEnable); + if (NULL != handle->callback) + { + handle->callback(base, handle, kStatus_LPUART_RxIdle, handle->userData); + } + } + } +#endif + /* Clear IDLE flag.*/ + base->STAT |= LPUART_STAT_IDLE_MASK; + + /* If rxDataSize is 0, disable idle line interrupt.*/ + if (0U != (handle->rxDataSize)) + { + LPUART_DisableInterrupts(base, (uint32_t)kLPUART_IdleLineInterruptEnable); + } + /* If callback is not NULL and rxDataSize is not 0. */ + if ((0U != handle->rxDataSize) && (NULL != handle->callback)) + { + handle->callback(base, handle, kStatus_LPUART_IdleLineDetected, handle->userData); + } + } + /* Receive data register full */ + if ((0U != ((uint32_t)kLPUART_RxDataRegFullFlag & status)) && + (0U != ((uint32_t)kLPUART_RxDataRegFullInterruptEnable & enabledInterrupts))) + { +/* Get the size that can be stored into buffer for this interrupt. */ +#if defined(FSL_FEATURE_LPUART_HAS_FIFO) && FSL_FEATURE_LPUART_HAS_FIFO + count = ((uint8_t)((base->WATER & LPUART_WATER_RXCOUNT_MASK) >> LPUART_WATER_RXCOUNT_SHIFT)); +#else + count = 1; +#endif + + /* If handle->rxDataSize is not 0, first save data to handle->rxData. */ + while ((0U != handle->rxDataSize) && (0U != count)) + { +#if defined(FSL_FEATURE_LPUART_HAS_FIFO) && FSL_FEATURE_LPUART_HAS_FIFO + tempCount = (uint8_t)MIN(handle->rxDataSize, count); +#else + tempCount = 1; +#endif + + /* Using non block API to read the data from the registers. */ + LPUART_ReadNonBlocking(base, handle->rxData, tempCount); + handle->rxData += tempCount; + handle->rxDataSize -= tempCount; + count -= tempCount; + + /* If all the data required for upper layer is ready, trigger callback. */ + if (0U == handle->rxDataSize) + { + handle->rxState = (uint8_t)kLPUART_RxIdle; + + if (NULL != handle->callback) + { + handle->callback(base, handle, kStatus_LPUART_RxIdle, handle->userData); + } + } + } + + /* If use RX ring buffer, receive data to ring buffer. */ + if (NULL != handle->rxRingBuffer) + { + while (0U != count--) + { + /* If RX ring buffer is full, trigger callback to notify over run. */ + if (LPUART_TransferIsRxRingBufferFull(base, handle)) + { + if (NULL != handle->callback) + { + handle->callback(base, handle, kStatus_LPUART_RxRingBufferOverrun, handle->userData); + } + } + + /* If ring buffer is still full after callback function, the oldest data is overridden. */ + if (LPUART_TransferIsRxRingBufferFull(base, handle)) + { + /* Increase handle->rxRingBufferTail to make room for new data. */ + if (((uint32_t)handle->rxRingBufferTail + 1U) == handle->rxRingBufferSize) + { + handle->rxRingBufferTail = 0U; + } + else + { + handle->rxRingBufferTail++; + } + } + + /* Read data. */ + tpmRxRingBufferHead = handle->rxRingBufferHead; + tpmData = base->DATA; +#if defined(FSL_FEATURE_LPUART_HAS_7BIT_DATA_SUPPORT) && FSL_FEATURE_LPUART_HAS_7BIT_DATA_SUPPORT + if (handle->isSevenDataBits) + { + handle->rxRingBuffer[tpmRxRingBufferHead] = (uint8_t)(tpmData & 0x7FU); + } + else + { + handle->rxRingBuffer[tpmRxRingBufferHead] = (uint8_t)tpmData; + } +#else + handle->rxRingBuffer[tpmRxRingBufferHead] = (uint8_t)tpmData; +#endif + + /* Increase handle->rxRingBufferHead. */ + if (((uint32_t)handle->rxRingBufferHead + 1U) == handle->rxRingBufferSize) + { + handle->rxRingBufferHead = 0U; + } + else + { + handle->rxRingBufferHead++; + } + } + } + /* If no receive requst pending, stop RX interrupt. */ + else if (0U == handle->rxDataSize) + { + LPUART_DisableInterrupts( + base, (uint32_t)kLPUART_RxDataRegFullInterruptEnable | (uint32_t)kLPUART_RxOverrunInterruptEnable); + } + else + { + } + } + + /* Send data register empty and the interrupt is enabled. */ + if ((0U != ((uint32_t)kLPUART_TxDataRegEmptyFlag & status)) && + (0U != ((uint32_t)kLPUART_TxDataRegEmptyInterruptEnable & enabledInterrupts))) + { +/* Get the bytes that available at this moment. */ +#if defined(FSL_FEATURE_LPUART_HAS_FIFO) && FSL_FEATURE_LPUART_HAS_FIFO + count = (uint8_t)FSL_FEATURE_LPUART_FIFO_SIZEn(base) - + (uint8_t)((base->WATER & LPUART_WATER_TXCOUNT_MASK) >> LPUART_WATER_TXCOUNT_SHIFT); +#else + count = 1; +#endif + + while ((0U != handle->txDataSize) && (0U != count)) + { +#if defined(FSL_FEATURE_LPUART_HAS_FIFO) && FSL_FEATURE_LPUART_HAS_FIFO + tempCount = (uint8_t)MIN(handle->txDataSize, count); +#else + tempCount = 1; +#endif + + /* Using non block API to write the data to the registers. */ + LPUART_WriteNonBlocking(base, handle->txData, tempCount); + handle->txData += tempCount; + handle->txDataSize -= tempCount; + count -= tempCount; + + /* If all the data are written to data register, notify user with the callback, then TX finished. */ + if (0U == handle->txDataSize) + { + /* Disable TX register empty interrupt. */ + base->CTRL = (base->CTRL & ~LPUART_CTRL_TIE_MASK); + /* Enable transmission complete interrupt. */ + LPUART_EnableInterrupts(base, (uint32_t)kLPUART_TransmissionCompleteInterruptEnable); + } + } + } + + /* Transmission complete and the interrupt is enabled. */ + if ((0U != ((uint32_t)kLPUART_TransmissionCompleteFlag & status)) && + (0U != ((uint32_t)kLPUART_TransmissionCompleteInterruptEnable & enabledInterrupts))) + { + /* Set txState to idle only when all data has been sent out to bus. */ + handle->txState = (uint8_t)kLPUART_TxIdle; + /* Disable transmission complete interrupt. */ + LPUART_DisableInterrupts(base, (uint32_t)kLPUART_TransmissionCompleteInterruptEnable); + + /* Trigger callback. */ + if (NULL != handle->callback) + { + handle->callback(base, handle, kStatus_LPUART_TxIdle, handle->userData); + } + } +} + +/*! + * brief LPUART Error IRQ handle function. + * + * This function handles the LPUART error IRQ request. + * + * param base LPUART peripheral base address. + * param handle LPUART handle pointer. + */ +void LPUART_TransferHandleErrorIRQ(LPUART_Type *base, lpuart_handle_t *handle) +{ + /* To be implemented by User. */ +} +#if defined(FSL_FEATURE_LPUART_HAS_SHARED_IRQ0_IRQ1) && FSL_FEATURE_LPUART_HAS_SHARED_IRQ0_IRQ1 +#if defined(FSL_FEATURE_LPUART_HAS_SEPARATE_RX_TX_IRQ) && FSL_FEATURE_LPUART_HAS_SEPARATE_RX_TX_IRQ +void LPUART0_LPUART1_RX_DriverIRQHandler(void) +{ + uint32_t stat = 0U; + uint32_t ctrl = 0U; + + if (CLOCK_isEnabledClock(s_lpuartClock[0])) + { + stat = LPUART0->STAT; + ctrl = LPUART0->CTRL; + if ((LPUART_STAT_OR_MASK & stat) || ((LPUART_STAT_RDRF_MASK & stat) && (LPUART_CTRL_RIE_MASK & ctrl))) + { + s_lpuartIsr(LPUART0, s_lpuartHandle[0]); + } + } + if (CLOCK_isEnabledClock(s_lpuartClock[1])) + { + stat = LPUART1->STAT; + ctrl = LPUART1->CTRL; + if ((LPUART_STAT_OR_MASK & stat) || ((LPUART_STAT_RDRF_MASK & stat) && (LPUART_CTRL_RIE_MASK & ctrl))) + { + s_lpuartIsr(LPUART1, s_lpuartHandle[1]); + } + } + SDK_ISR_EXIT_BARRIER; +} +void LPUART0_LPUART1_TX_DriverIRQHandler(void) +{ + uint32_t stat = 0U; + uint32_t ctrl = 0U; + + if (CLOCK_isEnabledClock(s_lpuartClock[0])) + { + stat = LPUART0->STAT; + ctrl = LPUART0->CTRL; + if ((LPUART_STAT_OR_MASK & stat) || ((stat & LPUART_STAT_TDRE_MASK) && (ctrl & LPUART_CTRL_TIE_MASK))) + { + s_lpuartIsr(LPUART0, s_lpuartHandle[0]); + } + } + if (CLOCK_isEnabledClock(s_lpuartClock[1])) + { + stat = LPUART1->STAT; + ctrl = LPUART1->CTRL; + if ((LPUART_STAT_OR_MASK & stat) || ((stat & LPUART_STAT_TDRE_MASK) && (ctrl & LPUART_CTRL_TIE_MASK))) + { + s_lpuartIsr(LPUART1, s_lpuartHandle[1]); + } + } + SDK_ISR_EXIT_BARRIER; +} +#else +void LPUART0_LPUART1_DriverIRQHandler(void) +{ + uint32_t stat = 0U; + uint32_t ctrl = 0U; + + if (CLOCK_isEnabledClock(s_lpuartClock[0])) + { + stat = LPUART0->STAT; + ctrl = LPUART0->CTRL; + if ((0U != (LPUART_STAT_OR_MASK & stat)) || + ((0U != (LPUART_STAT_RDRF_MASK & stat)) && (0U != (LPUART_CTRL_RIE_MASK & ctrl))) || + ((0U != (stat & LPUART_STAT_TDRE_MASK)) && (0U != (ctrl & LPUART_CTRL_TIE_MASK)))) + { + s_lpuartIsr(LPUART0, s_lpuartHandle[0]); + } + } + if (CLOCK_isEnabledClock(s_lpuartClock[1])) + { + stat = LPUART1->STAT; + ctrl = LPUART1->CTRL; + if ((0U != (LPUART_STAT_OR_MASK & stat)) || + ((0U != (LPUART_STAT_RDRF_MASK & stat)) && (0U != (LPUART_CTRL_RIE_MASK & ctrl))) || + ((0U != (stat & LPUART_STAT_TDRE_MASK)) && (0U != (ctrl & LPUART_CTRL_TIE_MASK)))) + { + s_lpuartIsr(LPUART1, s_lpuartHandle[1]); + } + } + SDK_ISR_EXIT_BARRIER; +} +#endif +#endif + +#if defined(LPUART0) +#if !(defined(FSL_FEATURE_LPUART_HAS_SHARED_IRQ0_IRQ1) && FSL_FEATURE_LPUART_HAS_SHARED_IRQ0_IRQ1) +#if defined(FSL_FEATURE_LPUART_HAS_SEPARATE_RX_TX_IRQ) && FSL_FEATURE_LPUART_HAS_SEPARATE_RX_TX_IRQ +void LPUART0_TX_DriverIRQHandler(void) +{ + s_lpuartIsr(LPUART0, s_lpuartHandle[0]); + SDK_ISR_EXIT_BARRIER; +} +void LPUART0_RX_DriverIRQHandler(void) +{ + s_lpuartIsr(LPUART0, s_lpuartHandle[0]); + SDK_ISR_EXIT_BARRIER; +} +#else +void LPUART0_DriverIRQHandler(void) +{ + s_lpuartIsr(LPUART0, s_lpuartHandle[0]); + SDK_ISR_EXIT_BARRIER; +} +#endif +#endif +#endif + +#if defined(LPUART1) +#if !(defined(FSL_FEATURE_LPUART_HAS_SHARED_IRQ0_IRQ1) && FSL_FEATURE_LPUART_HAS_SHARED_IRQ0_IRQ1) +#if defined(FSL_FEATURE_LPUART_HAS_SEPARATE_RX_TX_IRQ) && FSL_FEATURE_LPUART_HAS_SEPARATE_RX_TX_IRQ +void LPUART1_TX_DriverIRQHandler(void) +{ + s_lpuartIsr(LPUART1, s_lpuartHandle[1]); + SDK_ISR_EXIT_BARRIER; +} +void LPUART1_RX_DriverIRQHandler(void) +{ + s_lpuartIsr(LPUART1, s_lpuartHandle[1]); + SDK_ISR_EXIT_BARRIER; +} +#else +void LPUART1_DriverIRQHandler(void) +{ + s_lpuartIsr(LPUART1, s_lpuartHandle[1]); + SDK_ISR_EXIT_BARRIER; +} +#endif +#endif +#endif + +#if defined(LPUART2) +#if defined(FSL_FEATURE_LPUART_HAS_SEPARATE_RX_TX_IRQ) && FSL_FEATURE_LPUART_HAS_SEPARATE_RX_TX_IRQ +void LPUART2_TX_DriverIRQHandler(void) +{ + s_lpuartIsr(LPUART2, s_lpuartHandle[2]); + SDK_ISR_EXIT_BARRIER; +} +void LPUART2_RX_DriverIRQHandler(void) +{ + s_lpuartIsr(LPUART2, s_lpuartHandle[2]); + SDK_ISR_EXIT_BARRIER; +} +#else +void LPUART2_DriverIRQHandler(void) +{ + s_lpuartIsr(LPUART2, s_lpuartHandle[2]); + SDK_ISR_EXIT_BARRIER; +} +#endif +#endif + +#if defined(LPUART3) +#if defined(FSL_FEATURE_LPUART_HAS_SEPARATE_RX_TX_IRQ) && FSL_FEATURE_LPUART_HAS_SEPARATE_RX_TX_IRQ +void LPUART3_TX_DriverIRQHandler(void) +{ + s_lpuartIsr(LPUART3, s_lpuartHandle[3]); + SDK_ISR_EXIT_BARRIER; +} +void LPUART3_RX_DriverIRQHandler(void) +{ + s_lpuartIsr(LPUART3, s_lpuartHandle[3]); + SDK_ISR_EXIT_BARRIER; +} +#else +void LPUART3_DriverIRQHandler(void) +{ + s_lpuartIsr(LPUART3, s_lpuartHandle[3]); + SDK_ISR_EXIT_BARRIER; +} +#endif +#endif + +#if defined(LPUART4) +#if defined(FSL_FEATURE_LPUART_HAS_SEPARATE_RX_TX_IRQ) && FSL_FEATURE_LPUART_HAS_SEPARATE_RX_TX_IRQ +void LPUART4_TX_DriverIRQHandler(void) +{ + s_lpuartIsr(LPUART4, s_lpuartHandle[4]); + SDK_ISR_EXIT_BARRIER; +} +void LPUART4_RX_DriverIRQHandler(void) +{ + s_lpuartIsr(LPUART4, s_lpuartHandle[4]); + SDK_ISR_EXIT_BARRIER; +} +#else +void LPUART4_DriverIRQHandler(void) +{ + s_lpuartIsr(LPUART4, s_lpuartHandle[4]); + SDK_ISR_EXIT_BARRIER; +} +#endif +#endif + +#if defined(LPUART5) +#if defined(FSL_FEATURE_LPUART_HAS_SEPARATE_RX_TX_IRQ) && FSL_FEATURE_LPUART_HAS_SEPARATE_RX_TX_IRQ +void LPUART5_TX_DriverIRQHandler(void) +{ + s_lpuartIsr(LPUART5, s_lpuartHandle[5]); + SDK_ISR_EXIT_BARRIER; +} +void LPUART5_RX_DriverIRQHandler(void) +{ + s_lpuartIsr(LPUART5, s_lpuartHandle[5]); + SDK_ISR_EXIT_BARRIER; +} +#else +void LPUART5_DriverIRQHandler(void) +{ + s_lpuartIsr(LPUART5, s_lpuartHandle[5]); + SDK_ISR_EXIT_BARRIER; +} +#endif +#endif + +#if defined(LPUART6) +#if defined(FSL_FEATURE_LPUART_HAS_SEPARATE_RX_TX_IRQ) && FSL_FEATURE_LPUART_HAS_SEPARATE_RX_TX_IRQ +void LPUART6_TX_DriverIRQHandler(void) +{ + s_lpuartIsr(LPUART6, s_lpuartHandle[6]); + SDK_ISR_EXIT_BARRIER; +} +void LPUART6_RX_DriverIRQHandler(void) +{ + s_lpuartIsr(LPUART6, s_lpuartHandle[6]); + SDK_ISR_EXIT_BARRIER; +} +#else +void LPUART6_DriverIRQHandler(void) +{ + s_lpuartIsr(LPUART6, s_lpuartHandle[6]); + SDK_ISR_EXIT_BARRIER; +} +#endif +#endif + +#if defined(LPUART7) +#if defined(FSL_FEATURE_LPUART_HAS_SEPARATE_RX_TX_IRQ) && FSL_FEATURE_LPUART_HAS_SEPARATE_RX_TX_IRQ +void LPUART7_TX_DriverIRQHandler(void) +{ + s_lpuartIsr(LPUART7, s_lpuartHandle[7]); + SDK_ISR_EXIT_BARRIER; +} +void LPUART7_RX_DriverIRQHandler(void) +{ + s_lpuartIsr(LPUART7, s_lpuartHandle[7]); + SDK_ISR_EXIT_BARRIER; +} +#else +void LPUART7_DriverIRQHandler(void) +{ + s_lpuartIsr(LPUART7, s_lpuartHandle[7]); + SDK_ISR_EXIT_BARRIER; +} +#endif +#endif + +#if defined(LPUART8) +#if defined(FSL_FEATURE_LPUART_HAS_SEPARATE_RX_TX_IRQ) && FSL_FEATURE_LPUART_HAS_SEPARATE_RX_TX_IRQ +void LPUART8_TX_DriverIRQHandler(void) +{ + s_lpuartIsr(LPUART8, s_lpuartHandle[8]); + SDK_ISR_EXIT_BARRIER; +} +void LPUART8_RX_DriverIRQHandler(void) +{ + s_lpuartIsr(LPUART8, s_lpuartHandle[8]); + SDK_ISR_EXIT_BARRIER; +} +#else +void LPUART8_DriverIRQHandler(void) +{ + s_lpuartIsr(LPUART8, s_lpuartHandle[8]); + SDK_ISR_EXIT_BARRIER; +} +#endif +#endif + +#if defined(CM4_0__LPUART) +void M4_0_LPUART_DriverIRQHandler(void) +{ + s_lpuartIsr(CM4_0__LPUART, s_lpuartHandle[LPUART_GetInstance(CM4_0__LPUART)]); + SDK_ISR_EXIT_BARRIER; +} +#endif + +#if defined(CM4_1__LPUART) +void M4_1_LPUART_DriverIRQHandler(void) +{ + s_lpuartIsr(CM4_1__LPUART, s_lpuartHandle[LPUART_GetInstance(CM4_1__LPUART)]); + SDK_ISR_EXIT_BARRIER; +} +#endif + +#if defined(CM4__LPUART) +void M4_LPUART_DriverIRQHandler(void) +{ + s_lpuartIsr(CM4__LPUART, s_lpuartHandle[LPUART_GetInstance(CM4__LPUART)]); + SDK_ISR_EXIT_BARRIER; +} +#endif + +#if defined(DMA__LPUART0) +void DMA_UART0_INT_DriverIRQHandler(void) +{ + s_lpuartIsr(DMA__LPUART0, s_lpuartHandle[LPUART_GetInstance(DMA__LPUART0)]); + SDK_ISR_EXIT_BARRIER; +} +#endif + +#if defined(DMA__LPUART1) +void DMA_UART1_INT_DriverIRQHandler(void) +{ + s_lpuartIsr(DMA__LPUART1, s_lpuartHandle[LPUART_GetInstance(DMA__LPUART1)]); + SDK_ISR_EXIT_BARRIER; +} +#endif + +#if defined(DMA__LPUART2) +void DMA_UART2_INT_DriverIRQHandler(void) +{ + s_lpuartIsr(DMA__LPUART2, s_lpuartHandle[LPUART_GetInstance(DMA__LPUART2)]); + SDK_ISR_EXIT_BARRIER; +} +#endif + +#if defined(DMA__LPUART3) +void DMA_UART3_INT_DriverIRQHandler(void) +{ + s_lpuartIsr(DMA__LPUART3, s_lpuartHandle[LPUART_GetInstance(DMA__LPUART3)]); + SDK_ISR_EXIT_BARRIER; +} +#endif + +#if defined(DMA__LPUART4) +void DMA_UART4_INT_DriverIRQHandler(void) +{ + s_lpuartIsr(DMA__LPUART4, s_lpuartHandle[LPUART_GetInstance(DMA__LPUART4)]); + SDK_ISR_EXIT_BARRIER; +} +#endif + +#if defined(ADMA__LPUART0) +void ADMA_UART0_INT_DriverIRQHandler(void) +{ + s_lpuartIsr(ADMA__LPUART0, s_lpuartHandle[LPUART_GetInstance(ADMA__LPUART0)]); + SDK_ISR_EXIT_BARRIER; +} +#endif + +#if defined(ADMA__LPUART1) +void ADMA_UART1_INT_DriverIRQHandler(void) +{ + s_lpuartIsr(ADMA__LPUART1, s_lpuartHandle[LPUART_GetInstance(ADMA__LPUART1)]); + SDK_ISR_EXIT_BARRIER; +} +#endif + +#if defined(ADMA__LPUART2) +void ADMA_UART2_INT_DriverIRQHandler(void) +{ + s_lpuartIsr(ADMA__LPUART2, s_lpuartHandle[LPUART_GetInstance(ADMA__LPUART2)]); + SDK_ISR_EXIT_BARRIER; +} +#endif + +#if defined(ADMA__LPUART3) +void ADMA_UART3_INT_DriverIRQHandler(void) +{ + s_lpuartIsr(ADMA__LPUART3, s_lpuartHandle[LPUART_GetInstance(ADMA__LPUART3)]); + SDK_ISR_EXIT_BARRIER; +} +#endif diff --git a/source/hic_hal/freescale/kl27z/MKL27Z4/fsl_lpuart.h b/source/hic_hal/freescale/kl27z/MKL27Z4/fsl_lpuart.h new file mode 100644 index 0000000000..6ec3534c81 --- /dev/null +++ b/source/hic_hal/freescale/kl27z/MKL27Z4/fsl_lpuart.h @@ -0,0 +1,862 @@ +/* + * Copyright (c) 2015-2016, Freescale Semiconductor, Inc. + * Copyright 2016-2020 NXP + * All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ +#ifndef _FSL_LPUART_H_ +#define _FSL_LPUART_H_ + +#include "fsl_common.h" + +/*! + * @addtogroup lpuart_driver + * @{ + */ + +/******************************************************************************* + * Definitions + ******************************************************************************/ + +/*! @name Driver version */ +/*@{*/ +/*! @brief LPUART driver version 2.3.0. */ +#define FSL_LPUART_DRIVER_VERSION (MAKE_VERSION(2, 3, 0)) +/*@}*/ + +/*! @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 LPUART driver. */ +enum +{ + kStatus_LPUART_TxBusy = MAKE_STATUS(kStatusGroup_LPUART, 0), /*!< TX busy */ + kStatus_LPUART_RxBusy = MAKE_STATUS(kStatusGroup_LPUART, 1), /*!< RX busy */ + kStatus_LPUART_TxIdle = MAKE_STATUS(kStatusGroup_LPUART, 2), /*!< LPUART transmitter is idle. */ + kStatus_LPUART_RxIdle = MAKE_STATUS(kStatusGroup_LPUART, 3), /*!< LPUART receiver is idle. */ + kStatus_LPUART_TxWatermarkTooLarge = MAKE_STATUS(kStatusGroup_LPUART, 4), /*!< TX FIFO watermark too large */ + kStatus_LPUART_RxWatermarkTooLarge = MAKE_STATUS(kStatusGroup_LPUART, 5), /*!< RX FIFO watermark too large */ + kStatus_LPUART_FlagCannotClearManually = MAKE_STATUS(kStatusGroup_LPUART, 6), /*!< Some flag can't manually clear */ + kStatus_LPUART_Error = MAKE_STATUS(kStatusGroup_LPUART, 7), /*!< Error happens on LPUART. */ + kStatus_LPUART_RxRingBufferOverrun = + MAKE_STATUS(kStatusGroup_LPUART, 8), /*!< LPUART RX software ring buffer overrun. */ + kStatus_LPUART_RxHardwareOverrun = MAKE_STATUS(kStatusGroup_LPUART, 9), /*!< LPUART RX receiver overrun. */ + kStatus_LPUART_NoiseError = MAKE_STATUS(kStatusGroup_LPUART, 10), /*!< LPUART noise error. */ + kStatus_LPUART_FramingError = MAKE_STATUS(kStatusGroup_LPUART, 11), /*!< LPUART framing error. */ + kStatus_LPUART_ParityError = MAKE_STATUS(kStatusGroup_LPUART, 12), /*!< LPUART parity error. */ + kStatus_LPUART_BaudrateNotSupport = + MAKE_STATUS(kStatusGroup_LPUART, 13), /*!< Baudrate is not support in current clock source */ + kStatus_LPUART_IdleLineDetected = MAKE_STATUS(kStatusGroup_LPUART, 14), /*!< IDLE flag. */ + kStatus_LPUART_Timeout = MAKE_STATUS(kStatusGroup_LPUART, 15), /*!< LPUART times out. */ +}; + +/*! @brief LPUART parity mode. */ +typedef enum _lpuart_parity_mode +{ + kLPUART_ParityDisabled = 0x0U, /*!< Parity disabled */ + kLPUART_ParityEven = 0x2U, /*!< Parity enabled, type even, bit setting: PE|PT = 10 */ + kLPUART_ParityOdd = 0x3U, /*!< Parity enabled, type odd, bit setting: PE|PT = 11 */ +} lpuart_parity_mode_t; + +/*! @brief LPUART data bits count. */ +typedef enum _lpuart_data_bits +{ + kLPUART_EightDataBits = 0x0U, /*!< Eight data bit */ +#if defined(FSL_FEATURE_LPUART_HAS_7BIT_DATA_SUPPORT) && FSL_FEATURE_LPUART_HAS_7BIT_DATA_SUPPORT + kLPUART_SevenDataBits = 0x1U, /*!< Seven data bit */ +#endif +} lpuart_data_bits_t; + +/*! @brief LPUART stop bit count. */ +typedef enum _lpuart_stop_bit_count +{ + kLPUART_OneStopBit = 0U, /*!< One stop bit */ + kLPUART_TwoStopBit = 1U, /*!< Two stop bits */ +} lpuart_stop_bit_count_t; + +#if defined(FSL_FEATURE_LPUART_HAS_MODEM_SUPPORT) && FSL_FEATURE_LPUART_HAS_MODEM_SUPPORT +/*! @brief LPUART transmit CTS source. */ +typedef enum _lpuart_transmit_cts_source +{ + kLPUART_CtsSourcePin = 0U, /*!< CTS resource is the LPUART_CTS pin. */ + kLPUART_CtsSourceMatchResult = 1U, /*!< CTS resource is the match result. */ +} lpuart_transmit_cts_source_t; + +/*! @brief LPUART transmit CTS configure. */ +typedef enum _lpuart_transmit_cts_config +{ + kLPUART_CtsSampleAtStart = 0U, /*!< CTS input is sampled at the start of each character. */ + kLPUART_CtsSampleAtIdle = 1U, /*!< CTS input is sampled when the transmitter is idle */ +} lpuart_transmit_cts_config_t; +#endif + +/*! @brief LPUART idle flag type defines when the receiver starts counting. */ +typedef enum _lpuart_idle_type_select +{ + kLPUART_IdleTypeStartBit = 0U, /*!< Start counting after a valid start bit. */ + kLPUART_IdleTypeStopBit = 1U, /*!< Start counting after a stop bit. */ +} lpuart_idle_type_select_t; + +/*! @brief LPUART idle detected configuration. + * This structure defines the number of idle characters that must be received before + * the IDLE flag is set. + */ +typedef enum _lpuart_idle_config +{ + kLPUART_IdleCharacter1 = 0U, /*!< the number of idle characters. */ + kLPUART_IdleCharacter2 = 1U, /*!< the number of idle characters. */ + kLPUART_IdleCharacter4 = 2U, /*!< the number of idle characters. */ + kLPUART_IdleCharacter8 = 3U, /*!< the number of idle characters. */ + kLPUART_IdleCharacter16 = 4U, /*!< the number of idle characters. */ + kLPUART_IdleCharacter32 = 5U, /*!< the number of idle characters. */ + kLPUART_IdleCharacter64 = 6U, /*!< the number of idle characters. */ + kLPUART_IdleCharacter128 = 7U, /*!< the number of idle characters. */ +} lpuart_idle_config_t; + +/*! + * @brief LPUART interrupt configuration structure, default settings all disabled. + * + * This structure contains the settings for all LPUART interrupt configurations. + */ +enum _lpuart_interrupt_enable +{ +#if defined(FSL_FEATURE_LPUART_HAS_LIN_BREAK_DETECT) && FSL_FEATURE_LPUART_HAS_LIN_BREAK_DETECT + kLPUART_LinBreakInterruptEnable = (LPUART_BAUD_LBKDIE_MASK >> 8), /*!< LIN break detect. */ +#endif + kLPUART_RxActiveEdgeInterruptEnable = (LPUART_BAUD_RXEDGIE_MASK >> 8), /*!< Receive Active Edge. */ + kLPUART_TxDataRegEmptyInterruptEnable = (LPUART_CTRL_TIE_MASK), /*!< Transmit data register empty. */ + kLPUART_TransmissionCompleteInterruptEnable = (LPUART_CTRL_TCIE_MASK), /*!< Transmission complete. */ + kLPUART_RxDataRegFullInterruptEnable = (LPUART_CTRL_RIE_MASK), /*!< Receiver data register full. */ + kLPUART_IdleLineInterruptEnable = (LPUART_CTRL_ILIE_MASK), /*!< Idle line. */ + kLPUART_RxOverrunInterruptEnable = (LPUART_CTRL_ORIE_MASK), /*!< Receiver Overrun. */ + kLPUART_NoiseErrorInterruptEnable = (LPUART_CTRL_NEIE_MASK), /*!< Noise error flag. */ + kLPUART_FramingErrorInterruptEnable = (LPUART_CTRL_FEIE_MASK), /*!< Framing error flag. */ + kLPUART_ParityErrorInterruptEnable = (LPUART_CTRL_PEIE_MASK), /*!< Parity error flag. */ +#if defined(FSL_FEATURE_LPUART_HAS_FIFO) && FSL_FEATURE_LPUART_HAS_FIFO + kLPUART_TxFifoOverflowInterruptEnable = (LPUART_FIFO_TXOFE_MASK >> 8), /*!< Transmit FIFO Overflow. */ + kLPUART_RxFifoUnderflowInterruptEnable = (LPUART_FIFO_RXUFE_MASK >> 8), /*!< Receive FIFO Underflow. */ +#endif +}; + +/*! + * @brief LPUART status flags. + * + * This provides constants for the LPUART status flags for use in the LPUART functions. + */ +enum _lpuart_flags +{ + kLPUART_TxDataRegEmptyFlag = + (LPUART_STAT_TDRE_MASK), /*!< Transmit data register empty flag, sets when transmit buffer is empty */ + kLPUART_TransmissionCompleteFlag = + (LPUART_STAT_TC_MASK), /*!< Transmission complete flag, sets when transmission activity complete */ + kLPUART_RxDataRegFullFlag = + (LPUART_STAT_RDRF_MASK), /*!< Receive data register full flag, sets when the receive data buffer is full */ + kLPUART_IdleLineFlag = (LPUART_STAT_IDLE_MASK), /*!< Idle line detect flag, sets when idle line detected */ + kLPUART_RxOverrunFlag = (LPUART_STAT_OR_MASK), /*!< Receive Overrun, sets when new data is received before data is + read from receive register */ + kLPUART_NoiseErrorFlag = (LPUART_STAT_NF_MASK), /*!< Receive takes 3 samples of each received bit. If any of these + samples differ, noise flag sets */ + kLPUART_FramingErrorFlag = + (LPUART_STAT_FE_MASK), /*!< Frame error flag, sets if logic 0 was detected where stop bit expected */ + kLPUART_ParityErrorFlag = (LPUART_STAT_PF_MASK), /*!< If parity enabled, sets upon parity error detection */ +#if defined(FSL_FEATURE_LPUART_HAS_LIN_BREAK_DETECT) && FSL_FEATURE_LPUART_HAS_LIN_BREAK_DETECT + kLPUART_LinBreakFlag = (int)(LPUART_STAT_LBKDIF_MASK), /*!< LIN break detect interrupt flag, sets when LIN break + char detected and LIN circuit enabled */ +#endif + kLPUART_RxActiveEdgeFlag = + (LPUART_STAT_RXEDGIF_MASK), /*!< Receive pin active edge interrupt flag, sets when active edge detected */ + kLPUART_RxActiveFlag = + (LPUART_STAT_RAF_MASK), /*!< Receiver Active Flag (RAF), sets at beginning of valid start bit */ +#if defined(FSL_FEATURE_LPUART_HAS_ADDRESS_MATCHING) && FSL_FEATURE_LPUART_HAS_ADDRESS_MATCHING + kLPUART_DataMatch1Flag = LPUART_STAT_MA1F_MASK, /*!< The next character to be read from LPUART_DATA matches MA1*/ + kLPUART_DataMatch2Flag = LPUART_STAT_MA2F_MASK, /*!< The next character to be read from LPUART_DATA matches MA2*/ +#endif +#if defined(FSL_FEATURE_LPUART_HAS_EXTENDED_DATA_REGISTER_FLAGS) && FSL_FEATURE_LPUART_HAS_EXTENDED_DATA_REGISTER_FLAGS + kLPUART_NoiseErrorInRxDataRegFlag = + (LPUART_DATA_NOISY_MASK >> 10), /*!< NOISY bit, sets if noise detected in current data word */ + kLPUART_ParityErrorInRxDataRegFlag = + (LPUART_DATA_PARITYE_MASK >> 10), /*!< PARITY bit, sets if noise detected in current data word */ +#endif +#if defined(FSL_FEATURE_LPUART_HAS_FIFO) && FSL_FEATURE_LPUART_HAS_FIFO + kLPUART_TxFifoEmptyFlag = (LPUART_FIFO_TXEMPT_MASK >> 16), /*!< TXEMPT bit, sets if transmit buffer is empty */ + kLPUART_RxFifoEmptyFlag = (LPUART_FIFO_RXEMPT_MASK >> 16), /*!< RXEMPT bit, sets if receive buffer is empty */ + kLPUART_TxFifoOverflowFlag = + (LPUART_FIFO_TXOF_MASK >> 16), /*!< TXOF bit, sets if transmit buffer overflow occurred */ + kLPUART_RxFifoUnderflowFlag = + (LPUART_FIFO_RXUF_MASK >> 16), /*!< RXUF bit, sets if receive buffer underflow occurred */ +#endif +}; + +/*! @brief LPUART configuration structure. */ +typedef struct _lpuart_config +{ + uint32_t baudRate_Bps; /*!< LPUART baud rate */ + lpuart_parity_mode_t parityMode; /*!< Parity mode, disabled (default), even, odd */ + lpuart_data_bits_t dataBitsCount; /*!< Data bits count, eight (default), seven */ + bool isMsb; /*!< Data bits order, LSB (default), MSB */ +#if defined(FSL_FEATURE_LPUART_HAS_STOP_BIT_CONFIG_SUPPORT) && FSL_FEATURE_LPUART_HAS_STOP_BIT_CONFIG_SUPPORT + lpuart_stop_bit_count_t stopBitCount; /*!< Number of stop bits, 1 stop bit (default) or 2 stop bits */ +#endif +#if defined(FSL_FEATURE_LPUART_HAS_FIFO) && FSL_FEATURE_LPUART_HAS_FIFO + uint8_t txFifoWatermark; /*!< TX FIFO watermark */ + uint8_t rxFifoWatermark; /*!< RX FIFO watermark */ +#endif +#if defined(FSL_FEATURE_LPUART_HAS_MODEM_SUPPORT) && FSL_FEATURE_LPUART_HAS_MODEM_SUPPORT + bool enableRxRTS; /*!< RX RTS enable */ + bool enableTxCTS; /*!< TX CTS enable */ + lpuart_transmit_cts_source_t txCtsSource; /*!< TX CTS source */ + lpuart_transmit_cts_config_t txCtsConfig; /*!< TX CTS configure */ +#endif + lpuart_idle_type_select_t rxIdleType; /*!< RX IDLE type. */ + lpuart_idle_config_t rxIdleConfig; /*!< RX IDLE configuration. */ + bool enableTx; /*!< Enable TX */ + bool enableRx; /*!< Enable RX */ +} lpuart_config_t; + +/*! @brief LPUART transfer structure. */ +typedef struct _lpuart_transfer +{ + uint8_t *data; /*!< The buffer of data to be transfer.*/ + size_t dataSize; /*!< The byte count to be transfer. */ +} lpuart_transfer_t; + +/* Forward declaration of the handle typedef. */ +typedef struct _lpuart_handle lpuart_handle_t; + +/*! @brief LPUART transfer callback function. */ +typedef void (*lpuart_transfer_callback_t)(LPUART_Type *base, lpuart_handle_t *handle, status_t status, void *userData); + +/*! @brief LPUART handle structure. */ +struct _lpuart_handle +{ + 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. */ + + lpuart_transfer_callback_t callback; /*!< Callback function. */ + void *userData; /*!< LPUART callback function parameter.*/ + + volatile uint8_t txState; /*!< TX transfer state. */ + volatile uint8_t rxState; /*!< RX transfer state. */ + +#if defined(FSL_FEATURE_LPUART_HAS_7BIT_DATA_SUPPORT) && FSL_FEATURE_LPUART_HAS_7BIT_DATA_SUPPORT + bool isSevenDataBits; /*!< Seven data bits flag. */ +#endif +}; + +/******************************************************************************* + * API + ******************************************************************************/ + +#if defined(__cplusplus) +extern "C" { +#endif /* _cplusplus */ + +#if defined(FSL_FEATURE_LPUART_HAS_GLOBAL) && FSL_FEATURE_LPUART_HAS_GLOBAL + +/*! + * @name Software Reset + * @{ + */ + +/*! + * @brief Resets the LPUART using software. + * + * This function resets all internal logic and registers except the Global Register. + * Remains set until cleared by software. + * + * @param base LPUART peripheral base address. + */ +static inline void LPUART_SoftwareReset(LPUART_Type *base) +{ + base->GLOBAL |= LPUART_GLOBAL_RST_MASK; + base->GLOBAL &= ~LPUART_GLOBAL_RST_MASK; +} +/* @} */ +#endif /*FSL_FEATURE_LPUART_HAS_GLOBAL*/ + +/*! + * @name Initialization and deinitialization + * @{ + */ + +/*! + * @brief Initializes an LPUART instance with the user configuration structure and the peripheral clock. + * + * This function configures the LPUART module with user-defined settings. Call the LPUART_GetDefaultConfig() function + * to configure the configuration structure and get the default configuration. + * The example below shows how to use this API to configure the LPUART. + * @code + * lpuart_config_t lpuartConfig; + * lpuartConfig.baudRate_Bps = 115200U; + * lpuartConfig.parityMode = kLPUART_ParityDisabled; + * lpuartConfig.dataBitsCount = kLPUART_EightDataBits; + * lpuartConfig.isMsb = false; + * lpuartConfig.stopBitCount = kLPUART_OneStopBit; + * lpuartConfig.txFifoWatermark = 0; + * lpuartConfig.rxFifoWatermark = 1; + * LPUART_Init(LPUART1, &lpuartConfig, 20000000U); + * @endcode + * + * @param base LPUART peripheral base address. + * @param config Pointer to a user-defined configuration structure. + * @param srcClock_Hz LPUART clock source frequency in HZ. + * @retval kStatus_LPUART_BaudrateNotSupport Baudrate is not support in current clock source. + * @retval kStatus_Success LPUART initialize succeed + */ +status_t LPUART_Init(LPUART_Type *base, const lpuart_config_t *config, uint32_t srcClock_Hz); + +/*! + * @brief Deinitializes a LPUART instance. + * + * This function waits for transmit to complete, disables TX and RX, and disables the LPUART clock. + * + * @param base LPUART peripheral base address. + */ +void LPUART_Deinit(LPUART_Type *base); + +/*! + * @brief Gets the default configuration structure. + * + * This function initializes the LPUART configuration structure to a default value. The default + * values are: + * lpuartConfig->baudRate_Bps = 115200U; + * lpuartConfig->parityMode = kLPUART_ParityDisabled; + * lpuartConfig->dataBitsCount = kLPUART_EightDataBits; + * lpuartConfig->isMsb = false; + * lpuartConfig->stopBitCount = kLPUART_OneStopBit; + * lpuartConfig->txFifoWatermark = 0; + * lpuartConfig->rxFifoWatermark = 1; + * lpuartConfig->rxIdleType = kLPUART_IdleTypeStartBit; + * lpuartConfig->rxIdleConfig = kLPUART_IdleCharacter1; + * lpuartConfig->enableTx = false; + * lpuartConfig->enableRx = false; + * + * @param config Pointer to a configuration structure. + */ +void LPUART_GetDefaultConfig(lpuart_config_t *config); + +/*! + * @brief Sets the LPUART instance baudrate. + * + * This function configures the LPUART module baudrate. This function is used to update + * the LPUART module baudrate after the LPUART module is initialized by the LPUART_Init. + * @code + * LPUART_SetBaudRate(LPUART1, 115200U, 20000000U); + * @endcode + * + * @param base LPUART peripheral base address. + * @param baudRate_Bps LPUART baudrate to be set. + * @param srcClock_Hz LPUART clock source frequency in HZ. + * @retval kStatus_LPUART_BaudrateNotSupport Baudrate is not supported in the current clock source. + * @retval kStatus_Success Set baudrate succeeded. + */ +status_t LPUART_SetBaudRate(LPUART_Type *base, uint32_t baudRate_Bps, uint32_t srcClock_Hz); + +/* @} */ + +/*! + * @name Status + * @{ + */ + +/*! + * @brief Gets LPUART status flags. + * + * This function gets all LPUART status flags. The flags are returned as the logical + * OR value of the enumerators @ref _lpuart_flags. To check for a specific status, + * compare the return value with enumerators in the @ref _lpuart_flags. + * For example, to check whether the TX is empty: + * @code + * if (kLPUART_TxDataRegEmptyFlag & LPUART_GetStatusFlags(LPUART1)) + * { + * ... + * } + * @endcode + * + * @param base LPUART peripheral base address. + * @return LPUART status flags which are ORed by the enumerators in the _lpuart_flags. + */ +uint32_t LPUART_GetStatusFlags(LPUART_Type *base); + +/*! + * @brief Clears status flags with a provided mask. + * + * This function clears LPUART status flags with a provided mask. Automatically cleared flags + * can't be cleared by this function. + * Flags that can only cleared or set by hardware are: + * kLPUART_TxDataRegEmptyFlag, kLPUART_TransmissionCompleteFlag, kLPUART_RxDataRegFullFlag, + * kLPUART_RxActiveFlag, kLPUART_NoiseErrorInRxDataRegFlag, kLPUART_ParityErrorInRxDataRegFlag, + * kLPUART_TxFifoEmptyFlag,kLPUART_RxFifoEmptyFlag + * Note: This API should be called when the Tx/Rx is idle, otherwise it takes no effects. + * + * @param base LPUART peripheral base address. + * @param mask the status flags to be cleared. The user can use the enumerators in the + * _lpuart_status_flag_t to do the OR operation and get the mask. + * @return 0 succeed, others failed. + * @retval kStatus_LPUART_FlagCannotClearManually The flag can't be cleared by this function but + * it is cleared automatically by hardware. + * @retval kStatus_Success Status in the mask are cleared. + */ +status_t LPUART_ClearStatusFlags(LPUART_Type *base, uint32_t mask); + +/* @} */ + +/*! + * @name Interrupts + * @{ + */ + +/*! + * @brief Enables LPUART interrupts according to a provided mask. + * + * This function enables the LPUART interrupts according to a provided mask. The mask + * is a logical OR of enumeration members. See the @ref _lpuart_interrupt_enable. + * This examples shows how to enable TX empty interrupt and RX full interrupt: + * @code + * LPUART_EnableInterrupts(LPUART1,kLPUART_TxDataRegEmptyInterruptEnable | kLPUART_RxDataRegFullInterruptEnable); + * @endcode + * + * @param base LPUART peripheral base address. + * @param mask The interrupts to enable. Logical OR of the enumeration _uart_interrupt_enable. + */ +void LPUART_EnableInterrupts(LPUART_Type *base, uint32_t mask); + +/*! + * @brief Disables LPUART interrupts according to a provided mask. + * + * This function disables the LPUART interrupts according to a provided mask. The mask + * is a logical OR of enumeration members. See @ref _lpuart_interrupt_enable. + * This example shows how to disable the TX empty interrupt and RX full interrupt: + * @code + * LPUART_DisableInterrupts(LPUART1,kLPUART_TxDataRegEmptyInterruptEnable | kLPUART_RxDataRegFullInterruptEnable); + * @endcode + * + * @param base LPUART peripheral base address. + * @param mask The interrupts to disable. Logical OR of @ref _lpuart_interrupt_enable. + */ +void LPUART_DisableInterrupts(LPUART_Type *base, uint32_t mask); + +/*! + * @brief Gets enabled LPUART interrupts. + * + * This function gets the enabled LPUART interrupts. The enabled interrupts are returned + * as the logical OR value of the enumerators @ref _lpuart_interrupt_enable. To check + * a specific interrupt enable status, compare the return value with enumerators + * in @ref _lpuart_interrupt_enable. + * For example, to check whether the TX empty interrupt is enabled: + * @code + * uint32_t enabledInterrupts = LPUART_GetEnabledInterrupts(LPUART1); + * + * if (kLPUART_TxDataRegEmptyInterruptEnable & enabledInterrupts) + * { + * ... + * } + * @endcode + * + * @param base LPUART peripheral base address. + * @return LPUART interrupt flags which are logical OR of the enumerators in @ref _lpuart_interrupt_enable. + */ +uint32_t LPUART_GetEnabledInterrupts(LPUART_Type *base); + +#if defined(FSL_FEATURE_LPUART_HAS_DMA_ENABLE) && FSL_FEATURE_LPUART_HAS_DMA_ENABLE +/*! + * @brief Gets the LPUART data register address. + * + * This function returns the LPUART data register address, which is mainly used by the DMA/eDMA. + * + * @param base LPUART peripheral base address. + * @return LPUART data register addresses which are used both by the transmitter and receiver. + */ +static inline uint32_t LPUART_GetDataRegisterAddress(LPUART_Type *base) +{ + return (uint32_t) & (base->DATA); +} + +/*! + * @brief Enables or disables the LPUART transmitter DMA request. + * + * This function enables or disables the transmit data register empty flag, STAT[TDRE], to generate DMA requests. + * + * @param base LPUART peripheral base address. + * @param enable True to enable, false to disable. + */ +static inline void LPUART_EnableTxDMA(LPUART_Type *base, bool enable) +{ + if (enable) + { + base->BAUD |= LPUART_BAUD_TDMAE_MASK; + } + else + { + base->BAUD &= ~LPUART_BAUD_TDMAE_MASK; + } +} + +/*! + * @brief Enables or disables the LPUART receiver DMA. + * + * This function enables or disables the receiver data register full flag, STAT[RDRF], to generate DMA requests. + * + * @param base LPUART peripheral base address. + * @param enable True to enable, false to disable. + */ +static inline void LPUART_EnableRxDMA(LPUART_Type *base, bool enable) +{ + if (enable) + { + base->BAUD |= LPUART_BAUD_RDMAE_MASK; + } + else + { + base->BAUD &= ~LPUART_BAUD_RDMAE_MASK; + } +} + +/* @} */ +#endif /* FSL_FEATURE_LPUART_HAS_DMA_ENABLE */ + +/*! + * @name Bus Operations + * @{ + */ + +/*! + * @brief Get the LPUART instance from peripheral base address. + * + * @param base LPUART peripheral base address. + * @return LPUART instance. + */ +uint32_t LPUART_GetInstance(LPUART_Type *base); + +/*! + * @brief Enables or disables the LPUART transmitter. + * + * This function enables or disables the LPUART transmitter. + * + * @param base LPUART peripheral base address. + * @param enable True to enable, false to disable. + */ +static inline void LPUART_EnableTx(LPUART_Type *base, bool enable) +{ + if (enable) + { + base->CTRL |= LPUART_CTRL_TE_MASK; + } + else + { + base->CTRL &= ~LPUART_CTRL_TE_MASK; + } +} + +/*! + * @brief Enables or disables the LPUART receiver. + * + * This function enables or disables the LPUART receiver. + * + * @param base LPUART peripheral base address. + * @param enable True to enable, false to disable. + */ +static inline void LPUART_EnableRx(LPUART_Type *base, bool enable) +{ + if (enable) + { + base->CTRL |= LPUART_CTRL_RE_MASK; + } + else + { + base->CTRL &= ~LPUART_CTRL_RE_MASK; + } +} + +/*! + * @brief Writes to the transmitter register. + * + * This function writes data to the transmitter register directly. The upper layer must + * ensure that the TX register is empty or that the TX FIFO has room before calling this function. + * + * @param base LPUART peripheral base address. + * @param data Data write to the TX register. + */ +static inline void LPUART_WriteByte(LPUART_Type *base, uint8_t data) +{ + base->DATA = data; +} + +/*! + * @brief Reads the receiver register. + * + * This function reads data from the receiver register directly. The upper layer must + * ensure that the receiver register is full or that the RX FIFO has data before calling this function. + * + * @param base LPUART peripheral base address. + * @return Data read from data register. + */ +static inline uint8_t LPUART_ReadByte(LPUART_Type *base) +{ +#if defined(FSL_FEATURE_LPUART_HAS_7BIT_DATA_SUPPORT) && FSL_FEATURE_LPUART_HAS_7BIT_DATA_SUPPORT + uint32_t ctrl = base->CTRL; + uint8_t result; + bool isSevenDataBits = (((ctrl & LPUART_CTRL_M7_MASK) != 0U) || + (((ctrl & LPUART_CTRL_M7_MASK) == 0U) && ((ctrl & LPUART_CTRL_M_MASK) == 0U) && + ((ctrl & LPUART_CTRL_PE_MASK) != 0U))); + + if (isSevenDataBits) + { + result = (uint8_t)(base->DATA & 0x7FU); + } + else + { + result = (uint8_t)base->DATA; + } + + return result; +#else + return (uint8_t)(base->DATA); +#endif +} + +/*! + * @brief Writes to the transmitter register using a blocking method. + * + * This function polls the transmitter register, first waits for the register to be empty or TX FIFO to have room, + * and writes data to the transmitter buffer, then waits for the dat to be sent out to the bus. + * + * @param base LPUART peripheral base address. + * @param data Start address of the data to write. + * @param length Size of the data to write. + * @retval kStatus_LPUART_Timeout Transmission timed out and was aborted. + * @retval kStatus_Success Successfully wrote all data. + */ +status_t LPUART_WriteBlocking(LPUART_Type *base, const uint8_t *data, size_t length); + +/*! + * @brief Reads the receiver data register using a blocking method. + * + * This function polls the receiver register, waits for the receiver register full or receiver FIFO + * has data, and reads data from the TX register. + * + * @param base LPUART peripheral base address. + * @param data Start address of the buffer to store the received data. + * @param length Size of the buffer. + * @retval kStatus_LPUART_RxHardwareOverrun Receiver overrun happened while receiving data. + * @retval kStatus_LPUART_NoiseError Noise error happened while receiving data. + * @retval kStatus_LPUART_FramingError Framing error happened while receiving data. + * @retval kStatus_LPUART_ParityError Parity error happened while receiving data. + * @retval kStatus_LPUART_Timeout Transmission timed out and was aborted. + * @retval kStatus_Success Successfully received all data. + */ +status_t LPUART_ReadBlocking(LPUART_Type *base, uint8_t *data, size_t length); + +/* @} */ + +/*! + * @name Transactional + * @{ + */ + +/*! + * @brief Initializes the LPUART handle. + * + * This function initializes the LPUART handle, which can be used for other LPUART + * transactional APIs. Usually, for a specified LPUART instance, + * call this API once to get the initialized handle. + * + * The LPUART driver supports the "background" receiving, which means that user can set up + * an RX ring buffer optionally. Data received is stored into the ring buffer even when the + * user doesn't call the LPUART_TransferReceiveNonBlocking() API. If there is already data received + * in the ring buffer, the user can get the received data from the ring buffer directly. + * The ring buffer is disabled if passing NULL as @p ringBuffer. + * + * @param base LPUART peripheral base address. + * @param handle LPUART handle pointer. + * @param callback Callback function. + * @param userData User data. + */ +void LPUART_TransferCreateHandle(LPUART_Type *base, + lpuart_handle_t *handle, + lpuart_transfer_callback_t callback, + void *userData); +/*! + * @brief Transmits a buffer of data using the interrupt method. + * + * This function send data using an interrupt method. This is a non-blocking function, which + * returns directly without waiting for all data written to the transmitter register. When + * all data is written to the TX register in the ISR, the LPUART driver calls the callback + * function and passes the @ref kStatus_LPUART_TxIdle as status parameter. + * + * @note The kStatus_LPUART_TxIdle is passed to the upper layer when all data are written + * to the TX register. However, there is no check to ensure that all the data sent out. Before disabling the TX, + * check the kLPUART_TransmissionCompleteFlag to ensure that the transmit is finished. + * + * @param base LPUART peripheral base address. + * @param handle LPUART handle pointer. + * @param xfer LPUART transfer structure, see #lpuart_transfer_t. + * @retval kStatus_Success Successfully start the data transmission. + * @retval kStatus_LPUART_TxBusy Previous transmission still not finished, data not all written to the TX register. + * @retval kStatus_InvalidArgument Invalid argument. + */ +status_t LPUART_TransferSendNonBlocking(LPUART_Type *base, lpuart_handle_t *handle, lpuart_transfer_t *xfer); + +/*! + * @brief Sets up the RX ring buffer. + * + * This function sets up the RX ring buffer to a specific UART handle. + * + * When the RX ring buffer is used, data received is stored into the ring buffer even when + * the user doesn't call the UART_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 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 LPUART peripheral base address. + * @param handle LPUART handle pointer. + * @param ringBuffer Start address of ring buffer for background receiving. Pass NULL to disable the ring buffer. + * @param ringBufferSize size of the ring buffer. + */ +void LPUART_TransferStartRingBuffer(LPUART_Type *base, + lpuart_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 LPUART peripheral base address. + * @param handle LPUART handle pointer. + */ +void LPUART_TransferStopRingBuffer(LPUART_Type *base, lpuart_handle_t *handle); + +/*! + * @brief Get the length of received data in RX ring buffer. + * + * @param base LPUART peripheral base address. + * @param handle LPUART handle pointer. + * @return Length of received data in RX ring buffer. + */ +size_t LPUART_TransferGetRxRingBufferLength(LPUART_Type *base, lpuart_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 not sent out. + * + * @param base LPUART peripheral base address. + * @param handle LPUART handle pointer. + */ +void LPUART_TransferAbortSend(LPUART_Type *base, lpuart_handle_t *handle); + +/*! + * @brief Gets 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 an interrupt method. + * + * @param base LPUART peripheral base address. + * @param handle LPUART 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 LPUART_TransferGetSendCount(LPUART_Type *base, lpuart_handle_t *handle, uint32_t *count); + +/*! + * @brief Receives a buffer of data using the interrupt method. + * + * This function receives data using an interrupt method. This is a non-blocking function + * which returns without waiting to ensure that all data are 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 for read, the receive + * request is saved by the LPUART driver. When the new data arrives, the receive request + * is serviced first. When all data is received, the LPUART driver notifies the upper layer + * through a callback function and passes a status parameter kStatus_UART_RxIdle. + * For example, the upper layer needs 10 bytes but there are only 5 bytes in ring buffer. + * The 5 bytes are copied to xfer->data, which returns with the + * parameter @p receivedBytes set to 5. For the remaining 5 bytes, the newly arrived data is + * saved from xfer->data[5]. When 5 bytes are received, the LPUART 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 xfer->data. When all data is received, the upper layer is notified. + * + * @param base LPUART peripheral base address. + * @param handle LPUART handle pointer. + * @param xfer LPUART transfer structure, see uart_transfer_t. + * @param receivedBytes Bytes received from the ring buffer directly. + * @retval kStatus_Success Successfully queue the transfer into the transmit queue. + * @retval kStatus_LPUART_RxBusy Previous receive request is not finished. + * @retval kStatus_InvalidArgument Invalid argument. + */ +status_t LPUART_TransferReceiveNonBlocking(LPUART_Type *base, + lpuart_handle_t *handle, + lpuart_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 LPUART peripheral base address. + * @param handle LPUART handle pointer. + */ +void LPUART_TransferAbortReceive(LPUART_Type *base, lpuart_handle_t *handle); + +/*! + * @brief Gets the number of bytes that have been received. + * + * This function gets the number of bytes that have been received. + * + * @param base LPUART peripheral base address. + * @param handle LPUART 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 LPUART_TransferGetReceiveCount(LPUART_Type *base, lpuart_handle_t *handle, uint32_t *count); + +/*! + * @brief LPUART IRQ handle function. + * + * This function handles the LPUART transmit and receive IRQ request. + * + * @param base LPUART peripheral base address. + * @param handle LPUART handle pointer. + */ +void LPUART_TransferHandleIRQ(LPUART_Type *base, lpuart_handle_t *handle); + +/*! + * @brief LPUART Error IRQ handle function. + * + * This function handles the LPUART error IRQ request. + * + * @param base LPUART peripheral base address. + * @param handle LPUART handle pointer. + */ +void LPUART_TransferHandleErrorIRQ(LPUART_Type *base, lpuart_handle_t *handle); + +/* @} */ + +#if defined(__cplusplus) +} +#endif + +/*! @}*/ + +#endif /* _FSL_LPUART_H_ */ diff --git a/source/hic_hal/freescale/kl27z/MKL27Z4/fsl_lpuart_cmsis.c b/source/hic_hal/freescale/kl27z/MKL27Z4/fsl_lpuart_cmsis.c new file mode 100644 index 0000000000..dad0e18787 --- /dev/null +++ b/source/hic_hal/freescale/kl27z/MKL27Z4/fsl_lpuart_cmsis.c @@ -0,0 +1,3314 @@ +/* + * Copyright (c) 2013-2016 ARM Limited. All rights reserved. + * Copyright (c) 2016, Freescale Semiconductor, Inc. Not a Contribution. + * Copyright 2016-2017 NXP. Not a Contribution. + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "fsl_lpuart_cmsis.h" + +/* Component ID definition, used by tools. */ +#ifndef FSL_COMPONENT_ID +#define FSL_COMPONENT_ID "platform.drivers.lpuart_cmsis" +#endif + +/* Re-mapping for LPUART & UART indexing. */ +#if (FSL_FEATURE_SOC_LPUART_COUNT == 1) && FSL_FEATURE_SOC_UART_COUNT + +#ifdef RTE_USART0 +#undef RTE_USART0 +#endif +#ifdef RTE_USART0_DMA_EN +#undef RTE_USART0_DMA_EN +#endif +#ifdef RTE_USART0_DMA_TX_CH +#undef RTE_USART0_DMA_TX_CH +#endif +#ifdef RTE_USART0_DMA_TX_PERI_SEL +#undef RTE_USART0_DMA_TX_PERI_SEL +#endif +#ifdef RTE_USART0_DMA_TX_DMAMUX_BASE +#undef RTE_USART0_DMA_TX_DMAMUX_BASE +#endif +#ifdef RTE_USART0_DMA_TX_DMA_BASE +#undef RTE_USART0_DMA_TX_DMA_BASE +#endif +#ifdef RTE_USART0_DMA_RX_CH +#undef RTE_USART0_DMA_RX_CH +#endif +#ifdef RTE_USART0_DMA_RX_PERI_SEL +#undef RTE_USART0_DMA_RX_PERI_SEL +#endif +#ifdef RTE_USART0_DMA_RX_DMAMUX_BASE +#undef RTE_USART0_DMA_RX_DMAMUX_BASE +#endif +#ifdef RTE_USART0_DMA_RX_DMA_BASE +#undef RTE_USART0_DMA_RX_DMA_BASE +#endif +#ifdef USART0_RX_BUFFER_ENABLE +#undef USART0_RX_BUFFER_ENABLE +#endif + +#if (FSL_FEATURE_SOC_UART_COUNT == 3) + +#ifdef RTE_USART3 +#define RTE_USART0 RTE_USART3 +#endif +#ifdef RTE_USART3_DMA_EN +#define RTE_USART0_DMA_EN RTE_USART3_DMA_EN +#endif +#ifdef RTE_USART3_DMA_TX_CH +#define RTE_USART0_DMA_TX_CH RTE_USART3_DMA_TX_CH +#endif +#ifdef RTE_USART3_DMA_TX_PERI_SEL +#define RTE_USART0_DMA_TX_PERI_SEL RTE_USART3_DMA_TX_PERI_SEL +#endif +#ifdef RTE_USART3_DMA_TX_DMAMUX_BASE +#define RTE_USART0_DMA_TX_DMAMUX_BASE RTE_USART3_DMA_TX_DMAMUX_BASE +#endif +#ifdef RTE_USART3_DMA_TX_DMA_BASE +#define RTE_USART0_DMA_TX_DMA_BASE RTE_USART3_DMA_TX_DMA_BASE +#endif +#ifdef RTE_USART3_DMA_RX_CH +#define RTE_USART0_DMA_RX_CH RTE_USART3_DMA_RX_CH +#endif +#ifdef RTE_USART3_DMA_RX_PERI_SEL +#define RTE_USART0_DMA_RX_PERI_SEL RTE_USART3_DMA_RX_PERI_SEL +#endif +#ifdef RTE_USART3_DMA_RX_DMAMUX_BASE +#define RTE_USART0_DMA_RX_DMAMUX_BASE RTE_USART3_DMA_RX_DMAMUX_BASE +#endif +#ifdef RTE_USART3_DMA_RX_DMA_BASE +#define RTE_USART0_DMA_RX_DMA_BASE RTE_USART3_DMA_RX_DMA_BASE +#endif +#ifdef USART3_RX_BUFFER_ENABLE +#define USART0_RX_BUFFER_ENABLE USART3_RX_BUFFER_ENABLE +#endif + +#endif + +#if (FSL_FEATURE_SOC_UART_COUNT == 4) + +#ifdef RTE_USART4 +#define RTE_USART0 RTE_USART4 +#endif +#ifdef RTE_USART4_DMA_EN +#define RTE_USART0_DMA_EN RTE_USART4_DMA_EN +#endif +#ifdef RTE_USART4_DMA_TX_CH +#define RTE_USART0_DMA_TX_CH RTE_USART4_DMA_TX_CH +#endif +#ifdef RTE_USART4_DMA_TX_PERI_SEL +#define RTE_USART0_DMA_TX_PERI_SEL RTE_USART4_DMA_TX_PERI_SEL +#endif +#ifdef RTE_USART4_DMA_TX_DMAMUX_BASE +#define RTE_USART0_DMA_TX_DMAMUX_BASE RTE_USART4_DMA_TX_DMAMUX_BASE +#endif +#ifdef RTE_USART4_DMA_TX_DMA_BASE +#define RTE_USART0_DMA_TX_DMA_BASE RTE_USART4_DMA_TX_DMA_BASE +#endif +#ifdef RTE_USART4_DMA_RX_CH +#define RTE_USART0_DMA_RX_CH RTE_USART4_DMA_RX_CH +#endif +#ifdef RTE_USART4_DMA_RX_PERI_SEL +#define RTE_USART0_DMA_RX_PERI_SEL RTE_USART4_DMA_RX_PERI_SEL +#endif +#ifdef RTE_USART4_DMA_RX_DMAMUX_BASE +#define RTE_USART0_DMA_RX_DMAMUX_BASE RTE_USART4_DMA_RX_DMAMUX_BASE +#endif +#ifdef RTE_USART4_DMA_RX_DMA_BASE +#define RTE_USART0_DMA_RX_DMA_BASE RTE_USART4_DMA_RX_DMA_BASE +#endif +#ifdef USART4_RX_BUFFER_ENABLE +#define USART0_RX_BUFFER_ENABLE USART4_RX_BUFFER_ENABLE +#endif + +#endif + +#if (FSL_FEATURE_SOC_UART_COUNT == 5) + +#ifdef RTE_USART5 +#define RTE_USART0 RTE_USART5 +#endif +#ifdef RTE_USART5_DMA_EN +#define RTE_USART0_DMA_EN RTE_USART5_DMA_EN +#endif +#ifdef RTE_USART5_DMA_TX_CH +#define RTE_USART0_DMA_TX_CH RTE_USART5_DMA_TX_CH +#endif +#ifdef RTE_USART5_DMA_TX_PERI_SEL +#define RTE_USART0_DMA_TX_PERI_SEL RTE_USART5_DMA_TX_PERI_SEL +#endif +#ifdef RTE_USART5_DMA_TX_DMAMUX_BASE +#define RTE_USART0_DMA_TX_DMAMUX_BASE RTE_USART5_DMA_TX_DMAMUX_BASE +#endif +#ifdef RTE_USART5_DMA_TX_DMA_BASE +#define RTE_USART0_DMA_TX_DMA_BASE RTE_USART5_DMA_TX_DMA_BASE +#endif +#ifdef RTE_USART5_DMA_RX_CH +#define RTE_USART0_DMA_RX_CH RTE_USART5_DMA_RX_CH +#endif +#ifdef RTE_USART5_DMA_RX_PERI_SEL +#define RTE_USART0_DMA_RX_PERI_SEL RTE_USART5_DMA_RX_PERI_SEL +#endif +#ifdef RTE_USART5_DMA_RX_DMAMUX_BASE +#define RTE_USART0_DMA_RX_DMAMUX_BASE RTE_USART5_DMA_RX_DMAMUX_BASE +#endif +#ifdef RTE_USART5_DMA_RX_DMA_BASE +#define RTE_USART0_DMA_RX_DMA_BASE RTE_USART5_DMA_RX_DMA_BASE +#endif +#ifdef USART5_RX_BUFFER_ENABLE +#define USART0_RX_BUFFER_ENABLE USART5_RX_BUFFER_ENABLE +#endif + +#endif + +#endif + +#if ((RTE_USART0 && defined(LPUART0)) || (RTE_USART1 && defined(LPUART1)) || (RTE_USART2 && defined(LPUART2)) || \ + (RTE_USART3 && defined(LPUART3)) || (RTE_USART4 && defined(LPUART4)) || (RTE_USART5 && defined(LPUART5)) || \ + (RTE_USART6 && defined(LPUART6))) + +#define ARM_LPUART_DRV_VERSION ARM_DRIVER_VERSION_MAJOR_MINOR(2, 0) + +/* + * ARMCC does not support split the data section automatically, so the driver + * needs to split the data to separate sections explicitly, to reduce codesize. + */ +#if defined(__CC_ARM) || defined(__ARMCC_VERSION) +#define ARMCC_SECTION(section_name) __attribute__((section(section_name))) +#endif + +typedef const struct _cmsis_lpuart_resource +{ + LPUART_Type *base; /*!< LPUART peripheral base address. */ + uint32_t (*GetFreq)(void); /*!< Function to get the clock frequency. */ +} cmsis_lpuart_resource_t; + +typedef struct _cmsis_lpuart_non_blocking_driver_state +{ + cmsis_lpuart_resource_t *resource; /*!< Basic LPUART resource. */ + lpuart_handle_t *handle; /*!< Interupt transfer handle. */ + ARM_USART_SignalEvent_t cb_event; /*!< Callback function. */ + uint8_t flags; /*!< Control and state flags. */ +} cmsis_lpuart_non_blocking_driver_state_t; + +#if (defined(FSL_FEATURE_SOC_DMA_COUNT) && FSL_FEATURE_SOC_DMA_COUNT) +typedef struct _cmsis_lpuart_dma_resource +{ + DMA_Type *txDmaBase; /*!< DMA peripheral base address for TX. */ + uint32_t txDmaChannel; /*!< DMA channel for LPUART TX. */ + uint8_t txDmaRequest; /*!< TX DMA request source. */ + + DMA_Type *rxDmaBase; /*!< DMA peripheral base address for RX. */ + uint32_t rxDmaChannel; /*!< DMA channel for LPUART RX. */ + uint8_t rxDmaRequest; /*!< RX DMA request source. */ + +#if (defined(FSL_FEATURE_SOC_DMAMUX_COUNT) && FSL_FEATURE_SOC_DMAMUX_COUNT) + DMAMUX_Type *txDmamuxBase; /*!< DMAMUX peripheral base address for TX. */ + DMAMUX_Type *rxDmamuxBase; /*!< DMAMUX peripheral base address for RX. */ +#endif +} cmsis_lpuart_dma_resource_t; + +typedef struct _cmsis_lpuart_dma_driver_state +{ + cmsis_lpuart_resource_t *resource; /*!< LPUART basic resource. */ + cmsis_lpuart_dma_resource_t *dmaResource; /*!< LPUART DMA resource. */ + lpuart_dma_handle_t *handle; /*!< LPUART DMA transfer handle. */ + dma_handle_t *rxHandle; /*!< DMA RX handle. */ + dma_handle_t *txHandle; /*!< DMA TX handle. */ + ARM_USART_SignalEvent_t cb_event; /*!< Callback function. */ + uint8_t flags; /*!< Control and state flags. */ +} cmsis_lpuart_dma_driver_state_t; +#endif + +#if (defined(FSL_FEATURE_SOC_EDMA_COUNT) && FSL_FEATURE_SOC_EDMA_COUNT) +typedef struct _cmsis_lpuart_edma_resource +{ + DMA_Type *txEdmaBase; /*!< EDMA peripheral base address for TX. */ + uint32_t txEdmaChannel; /*!< EDMA channel for LPUART TX. */ + uint8_t txDmaRequest; /*!< TX EDMA request source. */ + + DMA_Type *rxEdmaBase; /*!< EDMA peripheral base address for RX. */ + uint32_t rxEdmaChannel; /*!< EDMA channel for LPUART RX. */ + uint8_t rxDmaRequest; /*!< RX EDMA request source. */ + +#if (defined(FSL_FEATURE_SOC_DMAMUX_COUNT) && FSL_FEATURE_SOC_DMAMUX_COUNT) + DMAMUX_Type *txDmamuxBase; /*!< DMAMUX peripheral base address for TX. */ + DMAMUX_Type *rxDmamuxBase; /*!< DMAMUX peripheral base address for RX. */ +#endif +} cmsis_lpuart_edma_resource_t; + +typedef struct _cmsis_lpuart_edma_driver_state +{ + cmsis_lpuart_resource_t *resource; /*!< LPUART basic resource. */ + cmsis_lpuart_edma_resource_t *dmaResource; /*!< LPUART EDMA resource. */ + lpuart_edma_handle_t *handle; /*!< LPUART EDMA transfer handle. */ + edma_handle_t *rxHandle; /*!< EDMA RX handle. */ + edma_handle_t *txHandle; /*!< EDMA TX handle. */ + ARM_USART_SignalEvent_t cb_event; /*!< Callback function. */ + uint8_t flags; /*!< Control and state flags. */ +} cmsis_lpuart_edma_driver_state_t; +#endif + +enum _lpuart_transfer_states +{ + kLPUART_TxIdle, /*!< TX idle. */ + kLPUART_TxBusy, /*!< TX busy. */ + kLPUART_RxIdle, /*!< RX idle. */ + kLPUART_RxBusy /*!< RX busy. */ +}; + +/* Driver Version */ +static const ARM_DRIVER_VERSION s_lpuartDriverVersion = {ARM_USART_API_VERSION, ARM_LPUART_DRV_VERSION}; + +static const ARM_USART_CAPABILITIES s_lpuartDriverCapabilities = { + 1, /* supports LPUART (Asynchronous) mode */ + 0, /* supports Synchronous Master mode */ + 0, /* supports Synchronous Slave mode */ + 0, /* supports LPUART Single-wire mode */ + 0, /* supports LPUART IrDA mode */ + 0, /* supports LPUART Smart Card mode */ + 0, /* Smart Card Clock generator */ + 0, /* RTS Flow Control available */ + 0, /* CTS Flow Control available */ + 0, /* Transmit completed event: \ref ARM_USART_EVENT_TX_COMPLETE */ + 0, /* Signal receive character timeout event: \ref ARM_USART_EVENT_RX_TIMEOUT */ + 0, /* RTS Line: 0=not available, 1=available */ + 0, /* CTS Line: 0=not available, 1=available */ + 0, /* DTR Line: 0=not available, 1=available */ + 0, /* DSR Line: 0=not available, 1=available */ + 0, /* DCD Line: 0=not available, 1=available */ + 0, /* RI Line: 0=not available, 1=available */ + 0, /* Signal CTS change event: \ref ARM_USART_EVENT_CTS */ + 0, /* Signal DSR change event: \ref ARM_USART_EVENT_DSR */ + 0, /* Signal DCD change event: \ref ARM_USART_EVENT_DCD */ + 0, /* Signal RI change event: \ref ARM_USART_EVENT_RI */ +}; + +/* + * Common control function used by LPUART_NonBlockingControl/LPUART_DmaControl/LPUART_EdmaControl + */ +static int32_t LPUART_CommonControl(uint32_t control, + uint32_t arg, + cmsis_lpuart_resource_t *resource, + uint8_t *isConfigured) +{ + lpuart_config_t config; + + LPUART_GetDefaultConfig(&config); + + switch (control & ARM_USART_CONTROL_Msk) + { + case ARM_USART_MODE_ASYNCHRONOUS: + /* USART Baudrate */ + config.baudRate_Bps = arg; + break; + + /* TX/RX IO is controlled in application layer. */ + case ARM_USART_CONTROL_TX: + if (arg) + { + LPUART_EnableTx(resource->base, true); + } + else + { + LPUART_EnableTx(resource->base, false); + } + return ARM_DRIVER_OK; + + case ARM_USART_CONTROL_RX: + if (arg) + { + LPUART_EnableRx(resource->base, true); + } + else + { + LPUART_EnableRx(resource->base, false); + } + + return ARM_DRIVER_OK; + + default: + return ARM_DRIVER_ERROR_UNSUPPORTED; + } + + switch (control & ARM_USART_DATA_BITS_Msk) + { +#if defined(FSL_FEATURE_LPUART_HAS_7BIT_DATA_SUPPORT) && FSL_FEATURE_LPUART_HAS_7BIT_DATA_SUPPORT + case ARM_USART_DATA_BITS_7: + config.dataBitsCount = kLPUART_SevenDataBits; + break; +#endif + case ARM_USART_DATA_BITS_8: + config.dataBitsCount = kLPUART_EightDataBits; + break; + + default: + return ARM_USART_ERROR_DATA_BITS; + } + + switch (control & ARM_USART_PARITY_Msk) + { + case ARM_USART_PARITY_NONE: + config.parityMode = kLPUART_ParityDisabled; + break; + case ARM_USART_PARITY_EVEN: + config.parityMode = kLPUART_ParityEven; + break; + case ARM_USART_PARITY_ODD: + config.parityMode = kLPUART_ParityOdd; + break; + default: + return ARM_USART_ERROR_PARITY; + } + + switch (control & ARM_USART_STOP_BITS_Msk) + { + case ARM_USART_STOP_BITS_1: + /* The GetDefaultConfig has already set for this case. */ + break; +#if defined(FSL_FEATURE_LPUART_HAS_STOP_BIT_CONFIG_SUPPORT) && FSL_FEATURE_LPUART_HAS_STOP_BIT_CONFIG_SUPPORT + case ARM_USART_STOP_BITS_2: + config.stopBitCount = kLPUART_TwoStopBit; + break; +#endif + default: + return ARM_USART_ERROR_STOP_BITS; + } + + /* If LPUART is already configured, deinit it first. */ + if ((*isConfigured) & USART_FLAG_CONFIGURED) + { + LPUART_Deinit(resource->base); + *isConfigured &= ~USART_FLAG_CONFIGURED; + } + + config.enableTx = true; + config.enableRx = true; + + if (kStatus_LPUART_BaudrateNotSupport == LPUART_Init(resource->base, &config, resource->GetFreq())) + { + return ARM_USART_ERROR_BAUDRATE; + } + + *isConfigured |= USART_FLAG_CONFIGURED; + + return ARM_DRIVER_OK; +} + +static ARM_DRIVER_VERSION LPUARTx_GetVersion(void) +{ + return s_lpuartDriverVersion; +} + +static ARM_USART_CAPABILITIES LPUARTx_GetCapabilities(void) +{ + return s_lpuartDriverCapabilities; +} + +static int32_t LPUARTx_SetModemControl(ARM_USART_MODEM_CONTROL control) +{ + return ARM_DRIVER_ERROR_UNSUPPORTED; +} + +static ARM_USART_MODEM_STATUS LPUARTx_GetModemStatus(void) +{ + ARM_USART_MODEM_STATUS modem_status; + + modem_status.cts = 0U; + modem_status.dsr = 0U; + modem_status.ri = 0U; + modem_status.dcd = 0U; + modem_status.reserved = 0U; + + return modem_status; +} + +#endif + +#if ((RTE_USART0_DMA_EN && defined(LPUART0)) || (RTE_USART1_DMA_EN && defined(LPUART1)) || \ + (RTE_USART2_DMA_EN && defined(LPUART2)) || (RTE_USART3_DMA_EN && defined(LPUART3)) || \ + (RTE_USART4_DMA_EN && defined(LPUART4)) || (RTE_USART5_DMA_EN && defined(LPUART5)) || \ + (RTE_USART6_DMA_EN && defined(LPUART6))) + +#if (defined(FSL_FEATURE_SOC_DMA_COUNT) && FSL_FEATURE_SOC_DMA_COUNT) +void KSDK_LPUART_DmaCallback(LPUART_Type *base, lpuart_dma_handle_t *handle, status_t status, void *userData) +{ + uint32_t event = 0U; + + if (kStatus_LPUART_TxIdle == status) + { + event = ARM_USART_EVENT_SEND_COMPLETE; + } + else if (kStatus_LPUART_RxIdle == status) + { + event = ARM_USART_EVENT_RECEIVE_COMPLETE; + } + + /* User data is actually CMSIS driver callback. */ + if ((0U != event) && (userData)) + { + ((ARM_USART_SignalEvent_t)userData)(event); + } +} + +static int32_t LPUART_DmaInitialize(ARM_USART_SignalEvent_t cb_event, cmsis_lpuart_dma_driver_state_t *lpuart) +{ + if (!(lpuart->flags & USART_FLAG_INIT)) + { + lpuart->cb_event = cb_event; + lpuart->flags = USART_FLAG_INIT; + } + + return ARM_DRIVER_OK; +} + +static int32_t LPUART_DmaUninitialize(cmsis_lpuart_dma_driver_state_t *lpuart) +{ + lpuart->flags = USART_FLAG_UNINIT; + return ARM_DRIVER_OK; +} + +static int32_t LPUART_DmaPowerControl(ARM_POWER_STATE state, cmsis_lpuart_dma_driver_state_t *lpuart) +{ + lpuart_config_t config; + cmsis_lpuart_dma_resource_t *dmaResource; + + switch (state) + { + case ARM_POWER_OFF: + if (lpuart->flags & USART_FLAG_POWER) + { + LPUART_Deinit(lpuart->resource->base); +#if (defined(FSL_FEATURE_SOC_DMAMUX_COUNT) && FSL_FEATURE_SOC_DMAMUX_COUNT) + DMAMUX_DisableChannel(lpuart->dmaResource->rxDmamuxBase, lpuart->dmaResource->rxDmaChannel); + DMAMUX_DisableChannel(lpuart->dmaResource->txDmamuxBase, lpuart->dmaResource->txDmaChannel); +#endif + lpuart->flags = USART_FLAG_INIT; + } + break; + case ARM_POWER_LOW: + return ARM_DRIVER_ERROR_UNSUPPORTED; + case ARM_POWER_FULL: + /* Must be initialized first. */ + if (lpuart->flags == USART_FLAG_UNINIT) + { + return ARM_DRIVER_ERROR; + } + + if (lpuart->flags & USART_FLAG_POWER) + { + /* Driver already powered */ + break; + } + + LPUART_GetDefaultConfig(&config); + config.enableTx = true; + config.enableRx = true; + + dmaResource = lpuart->dmaResource; + + /* Set up DMA setting. */ + DMA_CreateHandle(lpuart->rxHandle, dmaResource->rxDmaBase, dmaResource->rxDmaChannel); + + DMA_CreateHandle(lpuart->txHandle, dmaResource->txDmaBase, dmaResource->txDmaChannel); +#if (defined(FSL_FEATURE_SOC_DMAMUX_COUNT) && FSL_FEATURE_SOC_DMAMUX_COUNT) + DMAMUX_SetSource(dmaResource->rxDmamuxBase, dmaResource->rxDmaChannel, dmaResource->rxDmaRequest); + DMAMUX_EnableChannel(dmaResource->rxDmamuxBase, dmaResource->rxDmaChannel); + + DMAMUX_SetSource(dmaResource->txDmamuxBase, dmaResource->txDmaChannel, dmaResource->txDmaRequest); + DMAMUX_EnableChannel(dmaResource->txDmamuxBase, dmaResource->txDmaChannel); +#endif + /* Setup the LPUART. */ + LPUART_Init(lpuart->resource->base, &config, lpuart->resource->GetFreq()); + LPUART_TransferCreateHandleDMA(lpuart->resource->base, lpuart->handle, KSDK_LPUART_DmaCallback, + (void *)lpuart->cb_event, lpuart->txHandle, lpuart->rxHandle); + + lpuart->flags |= (USART_FLAG_POWER | USART_FLAG_CONFIGURED); + break; + default: + return ARM_DRIVER_ERROR_UNSUPPORTED; + } + + return ARM_DRIVER_OK; +} + +static int32_t LPUART_DmaSend(const void *data, uint32_t num, cmsis_lpuart_dma_driver_state_t *lpuart) +{ + int32_t ret; + status_t status; + lpuart_transfer_t xfer; + + xfer.data = (uint8_t *)data; + xfer.dataSize = num; + + status = LPUART_TransferSendDMA(lpuart->resource->base, lpuart->handle, &xfer); + + switch (status) + { + case kStatus_Success: + ret = ARM_DRIVER_OK; + break; + case kStatus_InvalidArgument: + ret = ARM_DRIVER_ERROR_PARAMETER; + break; + case kStatus_LPUART_RxBusy: + ret = ARM_DRIVER_ERROR_BUSY; + break; + default: + ret = ARM_DRIVER_ERROR; + break; + } + + return ret; +} + +static int32_t LPUART_DmaReceive(void *data, uint32_t num, cmsis_lpuart_dma_driver_state_t *lpuart) +{ + int32_t ret; + status_t status; + lpuart_transfer_t xfer; + + xfer.data = data; + xfer.dataSize = num; + + status = LPUART_TransferReceiveDMA(lpuart->resource->base, lpuart->handle, &xfer); + + switch (status) + { + case kStatus_Success: + ret = ARM_DRIVER_OK; + break; + case kStatus_InvalidArgument: + ret = ARM_DRIVER_ERROR_PARAMETER; + break; + case kStatus_LPUART_TxBusy: + ret = ARM_DRIVER_ERROR_BUSY; + break; + default: + ret = ARM_DRIVER_ERROR; + break; + } + + return ret; +} + +static int32_t LPUART_DmaTransfer(const void *data_out, + void *data_in, + uint32_t num, + cmsis_lpuart_dma_driver_state_t *lpuart) +{ + /* Only in synchronous mode */ + return ARM_DRIVER_ERROR; +} + +static uint32_t LPUART_DmaGetTxCount(cmsis_lpuart_dma_driver_state_t *lpuart) +{ + uint32_t cnt; + + /* If TX not in progress, then the TX count is txDataSizeAll saved in handle. */ + if (kStatus_NoTransferInProgress == LPUART_TransferGetSendCountDMA(lpuart->resource->base, lpuart->handle, &cnt)) + { + cnt = lpuart->handle->txDataSizeAll; + } + + return cnt; +} + +static uint32_t LPUART_DmaGetRxCount(cmsis_lpuart_dma_driver_state_t *lpuart) +{ + uint32_t cnt; + + if (kStatus_NoTransferInProgress == LPUART_TransferGetReceiveCountDMA(lpuart->resource->base, lpuart->handle, &cnt)) + { + cnt = lpuart->handle->rxDataSizeAll; + } + + return cnt; +} + +static int32_t LPUART_DmaControl(uint32_t control, uint32_t arg, cmsis_lpuart_dma_driver_state_t *lpuart) +{ + /* Must be power on. */ + if (!(lpuart->flags & USART_FLAG_POWER)) + { + return ARM_DRIVER_ERROR; + } + + /* Does not support these features. */ + if (control & (ARM_USART_FLOW_CONTROL_Msk | ARM_USART_CPOL_Msk | ARM_USART_CPHA_Msk)) + { + return ARM_DRIVER_ERROR_UNSUPPORTED; + } + + switch (control & ARM_USART_CONTROL_Msk) + { + /* Abort Send */ + case ARM_USART_ABORT_SEND: + LPUART_TransferAbortSendDMA(lpuart->resource->base, lpuart->handle); + return ARM_DRIVER_OK; + + /* Abort receive */ + case ARM_USART_ABORT_RECEIVE: + LPUART_TransferAbortReceiveDMA(lpuart->resource->base, lpuart->handle); + return ARM_DRIVER_OK; + + default: + break; + } + + return LPUART_CommonControl(control, arg, lpuart->resource, &lpuart->flags); +} + +static ARM_USART_STATUS LPUART_DmaGetStatus(cmsis_lpuart_dma_driver_state_t *lpuart) +{ + ARM_USART_STATUS stat; + uint32_t ksdk_lpuart_status = LPUART_GetStatusFlags(lpuart->resource->base); + + stat.tx_busy = ((kLPUART_TxBusy == lpuart->handle->txState) ? (1U) : (0U)); + stat.rx_busy = ((kLPUART_RxBusy == lpuart->handle->rxState) ? (1U) : (0U)); + + stat.tx_underflow = 0U; + stat.rx_overflow = (!(!(ksdk_lpuart_status & kLPUART_RxOverrunFlag))); +#if defined(FSL_FEATURE_LPUART_HAS_LIN_BREAK_DETECT) && FSL_FEATURE_LPUART_HAS_LIN_BREAK_DETECT + stat.rx_break = (!(!(ksdk_lpuart_status & (uint32_t)kLPUART_LinBreakFlag))); +#else + stat.rx_break = 0U; +#endif + stat.rx_framing_error = (!(!(ksdk_lpuart_status & kLPUART_FramingErrorFlag))); + stat.rx_parity_error = (!(!(ksdk_lpuart_status & kLPUART_ParityErrorFlag))); + stat.reserved = 0U; + + return stat; +} +#endif + +#if (defined(FSL_FEATURE_SOC_EDMA_COUNT) && FSL_FEATURE_SOC_EDMA_COUNT) +void KSDK_LPUART_EdmaCallback(LPUART_Type *base, lpuart_edma_handle_t *handle, status_t status, void *userData) +{ + uint32_t event = 0U; + + if (kStatus_LPUART_TxIdle == status) + { + event = ARM_USART_EVENT_SEND_COMPLETE; + } + if (kStatus_LPUART_RxIdle == status) + { + event = ARM_USART_EVENT_RECEIVE_COMPLETE; + } + + /* User data is actually CMSIS driver callback. */ + if ((0U != event) && (userData)) + { + ((ARM_USART_SignalEvent_t)userData)(event); + } +} + +static int32_t LPUART_EdmaInitialize(ARM_USART_SignalEvent_t cb_event, cmsis_lpuart_edma_driver_state_t *lpuart) +{ + if (!(lpuart->flags & USART_FLAG_INIT)) + { + lpuart->cb_event = cb_event; + lpuart->flags = USART_FLAG_INIT; + } + + return ARM_DRIVER_OK; +} + +static int32_t LPUART_EdmaUninitialize(cmsis_lpuart_edma_driver_state_t *lpuart) +{ + lpuart->flags = USART_FLAG_UNINIT; + return ARM_DRIVER_OK; +} + +static int32_t LPUART_EdmaPowerControl(ARM_POWER_STATE state, cmsis_lpuart_edma_driver_state_t *lpuart) +{ + lpuart_config_t config; + cmsis_lpuart_edma_resource_t *dmaResource; + + switch (state) + { + case ARM_POWER_OFF: + if (lpuart->flags & USART_FLAG_POWER) + { + LPUART_Deinit(lpuart->resource->base); + +#if (defined(FSL_FEATURE_SOC_DMAMUX_COUNT) && FSL_FEATURE_SOC_DMAMUX_COUNT) + DMAMUX_DisableChannel(lpuart->dmaResource->rxDmamuxBase, lpuart->dmaResource->rxEdmaChannel); + DMAMUX_DisableChannel(lpuart->dmaResource->txDmamuxBase, lpuart->dmaResource->txEdmaChannel); +#endif + lpuart->flags = USART_FLAG_INIT; + } + break; + case ARM_POWER_LOW: + return ARM_DRIVER_ERROR_UNSUPPORTED; + case ARM_POWER_FULL: + /* Must be initialized first. */ + if (lpuart->flags == USART_FLAG_UNINIT) + { + return ARM_DRIVER_ERROR; + } + + if (lpuart->flags & USART_FLAG_POWER) + { + /* Driver already powered */ + break; + } + + LPUART_GetDefaultConfig(&config); + config.enableTx = true; + config.enableRx = true; + + dmaResource = lpuart->dmaResource; + + /* Set up EDMA setting. */ + EDMA_CreateHandle(lpuart->rxHandle, dmaResource->rxEdmaBase, dmaResource->rxEdmaChannel); + EDMA_CreateHandle(lpuart->txHandle, dmaResource->txEdmaBase, dmaResource->txEdmaChannel); + +#if (defined(FSL_FEATURE_SOC_DMAMUX_COUNT) && FSL_FEATURE_SOC_DMAMUX_COUNT) + DMAMUX_SetSource(dmaResource->rxDmamuxBase, dmaResource->rxEdmaChannel, dmaResource->rxDmaRequest); + DMAMUX_EnableChannel(dmaResource->rxDmamuxBase, dmaResource->rxEdmaChannel); + + DMAMUX_SetSource(dmaResource->txDmamuxBase, dmaResource->txEdmaChannel, dmaResource->txDmaRequest); + DMAMUX_EnableChannel(dmaResource->txDmamuxBase, dmaResource->txEdmaChannel); +#endif + /* Setup the LPUART. */ + LPUART_Init(lpuart->resource->base, &config, lpuart->resource->GetFreq()); + LPUART_TransferCreateHandleEDMA(lpuart->resource->base, lpuart->handle, KSDK_LPUART_EdmaCallback, + (void *)lpuart->cb_event, lpuart->txHandle, lpuart->rxHandle); + + lpuart->flags |= (USART_FLAG_POWER | USART_FLAG_CONFIGURED); + break; + default: + return ARM_DRIVER_ERROR_UNSUPPORTED; + } + + return ARM_DRIVER_OK; +} + +static int32_t LPUART_EdmaSend(const void *data, uint32_t num, cmsis_lpuart_edma_driver_state_t *lpuart) +{ + int32_t ret; + status_t status; + lpuart_transfer_t xfer; + + xfer.data = (uint8_t *)data; + xfer.dataSize = num; + + status = LPUART_SendEDMA(lpuart->resource->base, lpuart->handle, &xfer); + + switch (status) + { + case kStatus_Success: + ret = ARM_DRIVER_OK; + break; + case kStatus_InvalidArgument: + ret = ARM_DRIVER_ERROR_PARAMETER; + break; + case kStatus_LPUART_RxBusy: + ret = ARM_DRIVER_ERROR_BUSY; + break; + default: + ret = ARM_DRIVER_ERROR; + break; + } + + return ret; +} + +static int32_t LPUART_EdmaReceive(void *data, uint32_t num, cmsis_lpuart_edma_driver_state_t *lpuart) +{ + int32_t ret; + status_t status; + lpuart_transfer_t xfer; + + xfer.data = data; + xfer.dataSize = num; + + status = LPUART_ReceiveEDMA(lpuart->resource->base, lpuart->handle, &xfer); + + switch (status) + { + case kStatus_Success: + ret = ARM_DRIVER_OK; + break; + case kStatus_InvalidArgument: + ret = ARM_DRIVER_ERROR_PARAMETER; + break; + case kStatus_LPUART_TxBusy: + ret = ARM_DRIVER_ERROR_BUSY; + break; + default: + ret = ARM_DRIVER_ERROR; + break; + } + + return ret; +} + +static int32_t LPUART_EdmaTransfer(const void *data_out, + void *data_in, + uint32_t num, + cmsis_lpuart_edma_driver_state_t *lpuart) +{ + /* Only in synchronous mode */ + return ARM_DRIVER_ERROR; +} + +static uint32_t LPUART_EdmaGetTxCount(cmsis_lpuart_edma_driver_state_t *lpuart) +{ + uint32_t cnt; + + if (kStatus_NoTransferInProgress == LPUART_TransferGetSendCountEDMA(lpuart->resource->base, lpuart->handle, &cnt)) + { + cnt = lpuart->handle->txDataSizeAll; + } + + return cnt; +} + +static uint32_t LPUART_EdmaGetRxCount(cmsis_lpuart_edma_driver_state_t *lpuart) +{ + uint32_t cnt; + + if (kStatus_NoTransferInProgress == + LPUART_TransferGetReceiveCountEDMA(lpuart->resource->base, lpuart->handle, &cnt)) + { + cnt = lpuart->handle->rxDataSizeAll; + } + + return cnt; +} + +static int32_t LPUART_EdmaControl(uint32_t control, uint32_t arg, cmsis_lpuart_edma_driver_state_t *lpuart) +{ + /* Must be power on. */ + if (!(lpuart->flags & USART_FLAG_POWER)) + { + return ARM_DRIVER_ERROR; + } + + /* Does not support these features. */ + if (control & (ARM_USART_FLOW_CONTROL_Msk | ARM_USART_CPOL_Msk | ARM_USART_CPHA_Msk)) + { + return ARM_DRIVER_ERROR_UNSUPPORTED; + } + + switch (control & ARM_USART_CONTROL_Msk) + { + /* Abort Send */ + case ARM_USART_ABORT_SEND: + LPUART_TransferAbortSendEDMA(lpuart->resource->base, lpuart->handle); + return ARM_DRIVER_OK; + + /* Abort receive */ + case ARM_USART_ABORT_RECEIVE: + LPUART_TransferAbortReceiveEDMA(lpuart->resource->base, lpuart->handle); + return ARM_DRIVER_OK; + + default: + break; + } + + return LPUART_CommonControl(control, arg, lpuart->resource, &lpuart->flags); +} + +static ARM_USART_STATUS LPUART_EdmaGetStatus(cmsis_lpuart_edma_driver_state_t *lpuart) +{ + ARM_USART_STATUS stat; + uint32_t ksdk_lpuart_status = LPUART_GetStatusFlags(lpuart->resource->base); + + stat.tx_busy = ((kLPUART_TxBusy == lpuart->handle->txState) ? (1U) : (0U)); + stat.rx_busy = ((kLPUART_RxBusy == lpuart->handle->rxState) ? (1U) : (0U)); + + stat.tx_underflow = 0U; + stat.rx_overflow = (!(!(ksdk_lpuart_status & kLPUART_RxOverrunFlag))); +#if defined(FSL_FEATURE_LPUART_HAS_LIN_BREAK_DETECT) && FSL_FEATURE_LPUART_HAS_LIN_BREAK_DETECT + stat.rx_break = (!(!(ksdk_lpuart_status & (uint32_t)kLPUART_LinBreakFlag))); +#else + stat.rx_break = 0U; +#endif + stat.rx_framing_error = (!(!(ksdk_lpuart_status & kLPUART_FramingErrorFlag))); + stat.rx_parity_error = (!(!(ksdk_lpuart_status & kLPUART_ParityErrorFlag))); + stat.reserved = 0U; + + return stat; +} +#endif + +#endif + +#if (((RTE_USART0 && !RTE_USART0_DMA_EN) && defined(LPUART0)) || \ + ((RTE_USART1 && !RTE_USART1_DMA_EN) && defined(LPUART1)) || \ + ((RTE_USART2 && !RTE_USART2_DMA_EN) && defined(LPUART2)) || \ + ((RTE_USART3 && !RTE_USART3_DMA_EN) && defined(LPUART3)) || \ + ((RTE_USART4 && !RTE_USART4_DMA_EN) && defined(LPUART4)) || \ + ((RTE_USART5 && !RTE_USART5_DMA_EN) && defined(LPUART5)) || \ + ((RTE_USART6 && !RTE_USART6_DMA_EN) && defined(LPUART6))) + +void KSDK_LPUART_NonBlockingCallback(LPUART_Type *base, lpuart_handle_t *handle, status_t status, void *userData) +{ + uint32_t event = 0U; + + if (kStatus_LPUART_TxIdle == status) + { + event = ARM_USART_EVENT_SEND_COMPLETE; + } + if (kStatus_LPUART_RxIdle == status) + { + event = ARM_USART_EVENT_RECEIVE_COMPLETE; + } + if (kStatus_LPUART_RxHardwareOverrun == status) + { + event = ARM_USART_EVENT_RX_OVERFLOW; + } + + /* User data is actually CMSIS driver callback. */ + if ((0U != event) && (userData)) + { + ((ARM_USART_SignalEvent_t)userData)(event); + } +} + +static int32_t LPUART_NonBlockingInitialize(ARM_USART_SignalEvent_t cb_event, + cmsis_lpuart_non_blocking_driver_state_t *lpuart) +{ + if (!(lpuart->flags & USART_FLAG_INIT)) + { + lpuart->cb_event = cb_event; + lpuart->flags = USART_FLAG_INIT; + } + + return ARM_DRIVER_OK; +} + +static int32_t LPUART_NonBlockingUninitialize(cmsis_lpuart_non_blocking_driver_state_t *lpuart) +{ + lpuart->flags = USART_FLAG_UNINIT; + return ARM_DRIVER_OK; +} + +static int32_t LPUART_NonBlockingPowerControl(ARM_POWER_STATE state, cmsis_lpuart_non_blocking_driver_state_t *lpuart) +{ + lpuart_config_t config; + + switch (state) + { + case ARM_POWER_OFF: + if (lpuart->flags & USART_FLAG_POWER) + { + LPUART_Deinit(lpuart->resource->base); + lpuart->flags = USART_FLAG_INIT; + } + break; + case ARM_POWER_LOW: + return ARM_DRIVER_ERROR_UNSUPPORTED; + case ARM_POWER_FULL: + /* Must be initialized first. */ + if (lpuart->flags == USART_FLAG_UNINIT) + { + return ARM_DRIVER_ERROR; + } + + if (lpuart->flags & USART_FLAG_POWER) + { + /* Driver already powered */ + break; + } + + LPUART_GetDefaultConfig(&config); + config.enableTx = true; + config.enableRx = true; + + LPUART_Init(lpuart->resource->base, &config, lpuart->resource->GetFreq()); + LPUART_TransferCreateHandle(lpuart->resource->base, lpuart->handle, KSDK_LPUART_NonBlockingCallback, + (void *)lpuart->cb_event); + lpuart->flags |= (USART_FLAG_POWER | USART_FLAG_CONFIGURED); + + break; + default: + return ARM_DRIVER_ERROR_UNSUPPORTED; + } + + return ARM_DRIVER_OK; +} + +static int32_t LPUART_NonBlockingSend(const void *data, uint32_t num, cmsis_lpuart_non_blocking_driver_state_t *lpuart) +{ + int32_t ret; + status_t status; + lpuart_transfer_t xfer; + + xfer.data = (uint8_t *)data; + xfer.dataSize = num; + + status = LPUART_TransferSendNonBlocking(lpuart->resource->base, lpuart->handle, &xfer); + + switch (status) + { + case kStatus_Success: + ret = ARM_DRIVER_OK; + break; + case kStatus_InvalidArgument: + ret = ARM_DRIVER_ERROR_PARAMETER; + break; + case kStatus_LPUART_RxBusy: + ret = ARM_DRIVER_ERROR_BUSY; + break; + default: + ret = ARM_DRIVER_ERROR; + break; + } + + return ret; +} + +static int32_t LPUART_NonBlockingReceive(void *data, uint32_t num, cmsis_lpuart_non_blocking_driver_state_t *lpuart) +{ + int32_t ret; + status_t status; + lpuart_transfer_t xfer; + + xfer.data = data; + xfer.dataSize = num; + + status = LPUART_TransferReceiveNonBlocking(lpuart->resource->base, lpuart->handle, &xfer, NULL); + + switch (status) + { + case kStatus_Success: + ret = ARM_DRIVER_OK; + break; + case kStatus_InvalidArgument: + ret = ARM_DRIVER_ERROR_PARAMETER; + break; + case kStatus_LPUART_TxBusy: + ret = ARM_DRIVER_ERROR_BUSY; + break; + default: + ret = ARM_DRIVER_ERROR; + break; + } + + return ret; +} + +static int32_t LPUART_NonBlockingTransfer(const void *data_out, + void *data_in, + uint32_t num, + cmsis_lpuart_non_blocking_driver_state_t *lpuart) +{ + /* Only in synchronous mode */ + return ARM_DRIVER_ERROR; +} + +static uint32_t LPUART_NonBlockingGetTxCount(cmsis_lpuart_non_blocking_driver_state_t *lpuart) +{ + uint32_t cnt; + + /* If TX not in progress, then the TX count is txDataSizeAll saved in handle. */ + if (kStatus_NoTransferInProgress == LPUART_TransferGetSendCount(lpuart->resource->base, lpuart->handle, &cnt)) + { + cnt = lpuart->handle->txDataSizeAll; + } + + return cnt; +} + +static uint32_t LPUART_NonBlockingGetRxCount(cmsis_lpuart_non_blocking_driver_state_t *lpuart) +{ + uint32_t cnt; + + if (kStatus_NoTransferInProgress == LPUART_TransferGetReceiveCount(lpuart->resource->base, lpuart->handle, &cnt)) + { + cnt = lpuart->handle->rxDataSizeAll; + } + + return cnt; +} + +static int32_t LPUART_NonBlockingControl(uint32_t control, + uint32_t arg, + cmsis_lpuart_non_blocking_driver_state_t *lpuart) +{ + /* Must be power on. */ + if (!(lpuart->flags & USART_FLAG_POWER)) + { + return ARM_DRIVER_ERROR; + } + + /* Does not support these features. */ + if (control & (ARM_USART_FLOW_CONTROL_Msk | ARM_USART_CPOL_Msk | ARM_USART_CPHA_Msk)) + { + return ARM_DRIVER_ERROR_UNSUPPORTED; + } + + switch (control & ARM_USART_CONTROL_Msk) + { + /* Abort Send */ + case ARM_USART_ABORT_SEND: + LPUART_TransferAbortSend(lpuart->resource->base, lpuart->handle); + return ARM_DRIVER_OK; + + /* Abort receive */ + case ARM_USART_ABORT_RECEIVE: + LPUART_TransferAbortReceive(lpuart->resource->base, lpuart->handle); + return ARM_DRIVER_OK; + + default: + break; + } + + return LPUART_CommonControl(control, arg, lpuart->resource, &lpuart->flags); +} + +static ARM_USART_STATUS LPUART_NonBlockingGetStatus(cmsis_lpuart_non_blocking_driver_state_t *lpuart) +{ + ARM_USART_STATUS stat; + uint32_t ksdk_lpuart_status = LPUART_GetStatusFlags(lpuart->resource->base); + + stat.tx_busy = ((kLPUART_TxBusy == lpuart->handle->txState) ? (1U) : (0U)); + stat.rx_busy = ((kLPUART_RxBusy == lpuart->handle->rxState) ? (1U) : (0U)); + + stat.tx_underflow = 0U; + stat.rx_overflow = (!(!(ksdk_lpuart_status & kLPUART_RxOverrunFlag))); +#if defined(FSL_FEATURE_LPUART_HAS_LIN_BREAK_DETECT) && FSL_FEATURE_LPUART_HAS_LIN_BREAK_DETECT + stat.rx_break = (!(!(ksdk_lpuart_status & (uint32_t)kLPUART_LinBreakFlag))); +#else + stat.rx_break = 0U; +#endif + stat.rx_framing_error = (!(!(ksdk_lpuart_status & kLPUART_FramingErrorFlag))); + stat.rx_parity_error = (!(!(ksdk_lpuart_status & kLPUART_ParityErrorFlag))); + stat.reserved = 0U; + + return stat; +} + +#endif + +#if defined(LPUART0) && RTE_USART0 + +/* User needs to provide the implementation for LPUART0_GetFreq/InitPins/DeinitPins +in the application for enabling according instance. */ +extern uint32_t LPUART0_GetFreq(void); +extern void LPUART0_InitPins(void); +extern void LPUART0_DeinitPins(void); + +cmsis_lpuart_resource_t LPUART0_Resource = {LPUART0, LPUART0_GetFreq}; + +#if RTE_USART0_DMA_EN + +#if (defined(FSL_FEATURE_SOC_DMA_COUNT) && FSL_FEATURE_SOC_DMA_COUNT) + +cmsis_lpuart_dma_resource_t LPUART0_DmaResource = { + RTE_USART0_DMA_TX_DMA_BASE, RTE_USART0_DMA_TX_CH, RTE_USART0_DMA_TX_PERI_SEL, + RTE_USART0_DMA_RX_DMA_BASE, RTE_USART0_DMA_RX_CH, RTE_USART0_DMA_RX_PERI_SEL, + +#if (defined(FSL_FEATURE_SOC_DMAMUX_COUNT) && FSL_FEATURE_SOC_DMAMUX_COUNT) + RTE_USART0_DMA_TX_DMAMUX_BASE, RTE_USART0_DMA_RX_DMAMUX_BASE, +#endif +}; + +lpuart_dma_handle_t LPUART0_DmaHandle; +dma_handle_t LPUART0_DmaRxHandle; +dma_handle_t LPUART0_DmaTxHandle; + +#if defined(__CC_ARM) || defined(__ARMCC_VERSION) +ARMCC_SECTION("lpuart0_dma_driver_state") +cmsis_lpuart_dma_driver_state_t LPUART0_DmaDriverState = { +#else +cmsis_lpuart_dma_driver_state_t LPUART0_DmaDriverState = { +#endif + &LPUART0_Resource, &LPUART0_DmaResource, &LPUART0_DmaHandle, &LPUART0_DmaRxHandle, &LPUART0_DmaTxHandle, +}; + +static int32_t LPUART0_DmaInitialize(ARM_USART_SignalEvent_t cb_event) +{ + LPUART0_InitPins(); + return LPUART_DmaInitialize(cb_event, &LPUART0_DmaDriverState); +} + +static int32_t LPUART0_DmaUninitialize(void) +{ + LPUART0_DeinitPins(); + return LPUART_DmaUninitialize(&LPUART0_DmaDriverState); +} + +static int32_t LPUART0_DmaPowerControl(ARM_POWER_STATE state) +{ + return LPUART_DmaPowerControl(state, &LPUART0_DmaDriverState); +} + +static int32_t LPUART0_DmaSend(const void *data, uint32_t num) +{ + return LPUART_DmaSend(data, num, &LPUART0_DmaDriverState); +} + +static int32_t LPUART0_DmaReceive(void *data, uint32_t num) +{ + return LPUART_DmaReceive(data, num, &LPUART0_DmaDriverState); +} + +static int32_t LPUART0_DmaTransfer(const void *data_out, void *data_in, uint32_t num) +{ + return LPUART_DmaTransfer(data_out, data_in, num, &LPUART0_DmaDriverState); +} + +static uint32_t LPUART0_DmaGetTxCount(void) +{ + return LPUART_DmaGetTxCount(&LPUART0_DmaDriverState); +} + +static uint32_t LPUART0_DmaGetRxCount(void) +{ + return LPUART_DmaGetRxCount(&LPUART0_DmaDriverState); +} + +static int32_t LPUART0_DmaControl(uint32_t control, uint32_t arg) +{ + return LPUART_DmaControl(control, arg, &LPUART0_DmaDriverState); +} + +static ARM_USART_STATUS LPUART0_DmaGetStatus(void) +{ + return LPUART_DmaGetStatus(&LPUART0_DmaDriverState); +} + +#endif + +#if (defined(FSL_FEATURE_SOC_EDMA_COUNT) && FSL_FEATURE_SOC_EDMA_COUNT) + +cmsis_lpuart_edma_resource_t LPUART0_EdmaResource = { + RTE_USART0_DMA_TX_DMA_BASE, RTE_USART0_DMA_TX_CH, RTE_USART0_DMA_TX_PERI_SEL, + + RTE_USART0_DMA_RX_DMA_BASE, RTE_USART0_DMA_RX_CH, RTE_USART0_DMA_RX_PERI_SEL, + +#if (defined(FSL_FEATURE_SOC_DMAMUX_COUNT) && FSL_FEATURE_SOC_DMAMUX_COUNT) + RTE_USART0_DMA_TX_DMAMUX_BASE, RTE_USART0_DMA_RX_DMAMUX_BASE, +#endif +}; + +lpuart_edma_handle_t LPUART0_EdmaHandle; +edma_handle_t LPUART0_EdmaRxHandle; +edma_handle_t LPUART0_EdmaTxHandle; + +#if defined(__CC_ARM) || defined(__ARMCC_VERSION) +ARMCC_SECTION("lpuart0_edma_driver_state") +cmsis_lpuart_edma_driver_state_t LPUART0_EdmaDriverState = { +#else +cmsis_lpuart_edma_driver_state_t LPUART0_EdmaDriverState = { +#endif + &LPUART0_Resource, &LPUART0_EdmaResource, &LPUART0_EdmaHandle, &LPUART0_EdmaRxHandle, &LPUART0_EdmaTxHandle, +}; + +static int32_t LPUART0_EdmaInitialize(ARM_USART_SignalEvent_t cb_event) +{ + LPUART0_InitPins(); + return LPUART_EdmaInitialize(cb_event, &LPUART0_EdmaDriverState); +} + +static int32_t LPUART0_EdmaUninitialize(void) +{ + LPUART0_DeinitPins(); + return LPUART_EdmaUninitialize(&LPUART0_EdmaDriverState); +} + +static int32_t LPUART0_EdmaPowerControl(ARM_POWER_STATE state) +{ + return LPUART_EdmaPowerControl(state, &LPUART0_EdmaDriverState); +} + +static int32_t LPUART0_EdmaSend(const void *data, uint32_t num) +{ + return LPUART_EdmaSend(data, num, &LPUART0_EdmaDriverState); +} + +static int32_t LPUART0_EdmaReceive(void *data, uint32_t num) +{ + return LPUART_EdmaReceive(data, num, &LPUART0_EdmaDriverState); +} + +static int32_t LPUART0_EdmaTransfer(const void *data_out, void *data_in, uint32_t num) +{ + return LPUART_EdmaTransfer(data_out, data_in, num, &LPUART0_EdmaDriverState); +} + +static uint32_t LPUART0_EdmaGetTxCount(void) +{ + return LPUART_EdmaGetTxCount(&LPUART0_EdmaDriverState); +} + +static uint32_t LPUART0_EdmaGetRxCount(void) +{ + return LPUART_EdmaGetRxCount(&LPUART0_EdmaDriverState); +} + +static int32_t LPUART0_EdmaControl(uint32_t control, uint32_t arg) +{ + return LPUART_EdmaControl(control, arg, &LPUART0_EdmaDriverState); +} + +static ARM_USART_STATUS LPUART0_EdmaGetStatus(void) +{ + return LPUART_EdmaGetStatus(&LPUART0_EdmaDriverState); +} + +#endif + +#else + +lpuart_handle_t LPUART0_Handle; + +#if defined(USART0_RX_BUFFER_ENABLE) && (USART0_RX_BUFFER_ENABLE == 1) +static uint8_t lpuart0_rxRingBuffer[USART_RX_BUFFER_LEN]; +#endif + +#if defined(USART1_RX_BUFFER_ENABLE) && (USART1_RX_BUFFER_ENABLE == 1) +static uint8_t lpuart1_rxRingBuffer[USART_RX_BUFFER_LEN]; +#endif + +#if defined(__CC_ARM) || defined(__ARMCC_VERSION) +ARMCC_SECTION("lpuart0_non_blocking_driver_state") +cmsis_lpuart_non_blocking_driver_state_t LPUART0_NonBlockingDriverState = { +#else +cmsis_lpuart_non_blocking_driver_state_t LPUART0_NonBlockingDriverState = { +#endif + &LPUART0_Resource, + &LPUART0_Handle, +}; + +static int32_t LPUART0_NonBlockingInitialize(ARM_USART_SignalEvent_t cb_event) +{ + LPUART0_InitPins(); + return LPUART_NonBlockingInitialize(cb_event, &LPUART0_NonBlockingDriverState); +} + +static int32_t LPUART0_NonBlockingUninitialize(void) +{ + LPUART0_DeinitPins(); + return LPUART_NonBlockingUninitialize(&LPUART0_NonBlockingDriverState); +} + +static int32_t LPUART0_NonBlockingPowerControl(ARM_POWER_STATE state) +{ + uint32_t result; + + result = LPUART_NonBlockingPowerControl(state, &LPUART0_NonBlockingDriverState); + +#if defined(USART0_RX_BUFFER_ENABLE) && (USART0_RX_BUFFER_ENABLE == 1) + if ((state == ARM_POWER_FULL) && (LPUART0_NonBlockingDriverState.handle->rxRingBuffer == NULL)) + { + LPUART_TransferStartRingBuffer(LPUART0_NonBlockingDriverState.resource->base, + LPUART0_NonBlockingDriverState.handle, lpuart0_rxRingBuffer, + USART_RX_BUFFER_LEN); + } +#endif + + return result; +} + +static int32_t LPUART0_NonBlockingSend(const void *data, uint32_t num) +{ + return LPUART_NonBlockingSend(data, num, &LPUART0_NonBlockingDriverState); +} + +static int32_t LPUART0_NonBlockingReceive(void *data, uint32_t num) +{ + return LPUART_NonBlockingReceive(data, num, &LPUART0_NonBlockingDriverState); +} + +static int32_t LPUART0_NonBlockingTransfer(const void *data_out, void *data_in, uint32_t num) +{ + return LPUART_NonBlockingTransfer(data_out, data_in, num, &LPUART0_NonBlockingDriverState); +} + +static uint32_t LPUART0_NonBlockingGetTxCount(void) +{ + return LPUART_NonBlockingGetTxCount(&LPUART0_NonBlockingDriverState); +} + +static uint32_t LPUART0_NonBlockingGetRxCount(void) +{ + return LPUART_NonBlockingGetRxCount(&LPUART0_NonBlockingDriverState); +} + +static int32_t LPUART0_NonBlockingControl(uint32_t control, uint32_t arg) +{ + int32_t result; + + result = LPUART_NonBlockingControl(control, arg, &LPUART0_NonBlockingDriverState); + if (ARM_DRIVER_OK != result) + { + return result; + } + + /* Enable the receive interrupts if ring buffer is used */ + if (LPUART0_NonBlockingDriverState.handle->rxRingBuffer != NULL) + { + LPUART_EnableInterrupts(LPUART0_NonBlockingDriverState.resource->base, + kLPUART_RxDataRegFullInterruptEnable | kLPUART_RxOverrunInterruptEnable); + } + + return ARM_DRIVER_OK; +} + +static ARM_USART_STATUS LPUART0_NonBlockingGetStatus(void) +{ + return LPUART_NonBlockingGetStatus(&LPUART0_NonBlockingDriverState); +} + +#endif + +#if (FSL_FEATURE_SOC_LPUART_COUNT == 1) +#if (FSL_FEATURE_SOC_UART_COUNT == 3) +ARM_DRIVER_USART Driver_USART3 = { +#elif (FSL_FEATURE_SOC_UART_COUNT == 4) +ARM_DRIVER_USART Driver_USART4 = { +#elif (FSL_FEATURE_SOC_UART_COUNT == 5) +ARM_DRIVER_USART Driver_USART5 = { +#else +ARM_DRIVER_USART Driver_USART0 = { +#endif +#else +ARM_DRIVER_USART Driver_USART0 = { +#endif + + LPUARTx_GetVersion, LPUARTx_GetCapabilities, +#if RTE_USART0_DMA_EN +#if (defined(FSL_FEATURE_SOC_EDMA_COUNT) && FSL_FEATURE_SOC_EDMA_COUNT) + LPUART0_EdmaInitialize, LPUART0_EdmaUninitialize, LPUART0_EdmaPowerControl, LPUART0_EdmaSend, + LPUART0_EdmaReceive, LPUART0_EdmaTransfer, LPUART0_EdmaGetTxCount, LPUART0_EdmaGetRxCount, + LPUART0_EdmaControl, LPUART0_EdmaGetStatus, +#else + LPUART0_DmaInitialize, LPUART0_DmaUninitialize, LPUART0_DmaPowerControl, LPUART0_DmaSend, LPUART0_DmaReceive, + LPUART0_DmaTransfer, LPUART0_DmaGetTxCount, LPUART0_DmaGetRxCount, LPUART0_DmaControl, LPUART0_DmaGetStatus, +#endif +#else + LPUART0_NonBlockingInitialize, + LPUART0_NonBlockingUninitialize, + LPUART0_NonBlockingPowerControl, + LPUART0_NonBlockingSend, + LPUART0_NonBlockingReceive, + LPUART0_NonBlockingTransfer, + LPUART0_NonBlockingGetTxCount, + LPUART0_NonBlockingGetRxCount, + LPUART0_NonBlockingControl, + LPUART0_NonBlockingGetStatus, +#endif + LPUARTx_SetModemControl, LPUARTx_GetModemStatus}; + +#endif /* LPUART0 */ + +#if defined(LPUART1) && RTE_USART1 + +/* User needs to provide the implementation for LPUART1_GetFreq/InitPins/DeinitPins +in the application for enabling according instance. */ +extern uint32_t LPUART1_GetFreq(void); +extern void LPUART1_InitPins(void); +extern void LPUART1_DeinitPins(void); + +cmsis_lpuart_resource_t LPUART1_Resource = {LPUART1, LPUART1_GetFreq}; + +#if RTE_USART1_DMA_EN + +#if (defined(FSL_FEATURE_SOC_DMA_COUNT) && FSL_FEATURE_SOC_DMA_COUNT) + +cmsis_lpuart_dma_resource_t LPUART1_DmaResource = { + RTE_USART1_DMA_TX_DMA_BASE, RTE_USART1_DMA_TX_CH, RTE_USART1_DMA_TX_PERI_SEL, + RTE_USART1_DMA_RX_DMA_BASE, RTE_USART1_DMA_RX_CH, RTE_USART1_DMA_RX_PERI_SEL, + +#if (defined(FSL_FEATURE_SOC_DMAMUX_COUNT) && FSL_FEATURE_SOC_DMAMUX_COUNT) + RTE_USART1_DMA_TX_DMAMUX_BASE, RTE_USART1_DMA_RX_DMAMUX_BASE, +#endif +}; + +lpuart_dma_handle_t LPUART1_DmaHandle; +dma_handle_t LPUART1_DmaRxHandle; +dma_handle_t LPUART1_DmaTxHandle; + +#if defined(__CC_ARM) || defined(__ARMCC_VERSION) +ARMCC_SECTION("lpuart1_dma_driver_state") +cmsis_lpuart_dma_driver_state_t LPUART1_DmaDriverState = { +#else +cmsis_lpuart_dma_driver_state_t LPUART1_DmaDriverState = { +#endif + &LPUART1_Resource, &LPUART1_DmaResource, &LPUART1_DmaHandle, &LPUART1_DmaRxHandle, &LPUART1_DmaTxHandle, +}; + +static int32_t LPUART1_DmaInitialize(ARM_USART_SignalEvent_t cb_event) +{ + LPUART1_InitPins(); + return LPUART_DmaInitialize(cb_event, &LPUART1_DmaDriverState); +} + +static int32_t LPUART1_DmaUninitialize(void) +{ + LPUART1_DeinitPins(); + return LPUART_DmaUninitialize(&LPUART1_DmaDriverState); +} + +static int32_t LPUART1_DmaPowerControl(ARM_POWER_STATE state) +{ + return LPUART_DmaPowerControl(state, &LPUART1_DmaDriverState); +} + +static int32_t LPUART1_DmaSend(const void *data, uint32_t num) +{ + return LPUART_DmaSend(data, num, &LPUART1_DmaDriverState); +} + +static int32_t LPUART1_DmaReceive(void *data, uint32_t num) +{ + return LPUART_DmaReceive(data, num, &LPUART1_DmaDriverState); +} + +static int32_t LPUART1_DmaTransfer(const void *data_out, void *data_in, uint32_t num) +{ + return LPUART_DmaTransfer(data_out, data_in, num, &LPUART1_DmaDriverState); +} + +static uint32_t LPUART1_DmaGetTxCount(void) +{ + return LPUART_DmaGetTxCount(&LPUART1_DmaDriverState); +} + +static uint32_t LPUART1_DmaGetRxCount(void) +{ + return LPUART_DmaGetRxCount(&LPUART1_DmaDriverState); +} + +static int32_t LPUART1_DmaControl(uint32_t control, uint32_t arg) +{ + return LPUART_DmaControl(control, arg, &LPUART1_DmaDriverState); +} + +static ARM_USART_STATUS LPUART1_DmaGetStatus(void) +{ + return LPUART_DmaGetStatus(&LPUART1_DmaDriverState); +} + +#endif + +#if (defined(FSL_FEATURE_SOC_EDMA_COUNT) && FSL_FEATURE_SOC_EDMA_COUNT) + +cmsis_lpuart_edma_resource_t LPUART1_EdmaResource = { + RTE_USART1_DMA_TX_DMA_BASE, RTE_USART1_DMA_TX_CH, RTE_USART1_DMA_TX_PERI_SEL, + RTE_USART1_DMA_RX_DMA_BASE, RTE_USART1_DMA_RX_CH, RTE_USART1_DMA_RX_PERI_SEL, + +#if (defined(FSL_FEATURE_SOC_DMAMUX_COUNT) && FSL_FEATURE_SOC_DMAMUX_COUNT) + RTE_USART1_DMA_TX_DMAMUX_BASE, RTE_USART1_DMA_RX_DMAMUX_BASE, +#endif +}; + +lpuart_edma_handle_t LPUART1_EdmaHandle; +edma_handle_t LPUART1_EdmaRxHandle; +edma_handle_t LPUART1_EdmaTxHandle; + +#if defined(__CC_ARM) || defined(__ARMCC_VERSION) +ARMCC_SECTION("lpuart1_edma_driver_state") +cmsis_lpuart_edma_driver_state_t LPUART1_EdmaDriverState = { +#else +cmsis_lpuart_edma_driver_state_t LPUART1_EdmaDriverState = { +#endif + &LPUART1_Resource, &LPUART1_EdmaResource, &LPUART1_EdmaHandle, &LPUART1_EdmaRxHandle, &LPUART1_EdmaTxHandle, +}; + +static int32_t LPUART1_EdmaInitialize(ARM_USART_SignalEvent_t cb_event) +{ + LPUART1_InitPins(); + return LPUART_EdmaInitialize(cb_event, &LPUART1_EdmaDriverState); +} + +static int32_t LPUART1_EdmaUninitialize(void) +{ + LPUART1_DeinitPins(); + return LPUART_EdmaUninitialize(&LPUART1_EdmaDriverState); +} + +static int32_t LPUART1_EdmaPowerControl(ARM_POWER_STATE state) +{ + return LPUART_EdmaPowerControl(state, &LPUART1_EdmaDriverState); +} + +static int32_t LPUART1_EdmaSend(const void *data, uint32_t num) +{ + return LPUART_EdmaSend(data, num, &LPUART1_EdmaDriverState); +} + +static int32_t LPUART1_EdmaReceive(void *data, uint32_t num) +{ + return LPUART_EdmaReceive(data, num, &LPUART1_EdmaDriverState); +} + +static int32_t LPUART1_EdmaTransfer(const void *data_out, void *data_in, uint32_t num) +{ + return LPUART_EdmaTransfer(data_out, data_in, num, &LPUART1_EdmaDriverState); +} + +static uint32_t LPUART1_EdmaGetTxCount(void) +{ + return LPUART_EdmaGetTxCount(&LPUART1_EdmaDriverState); +} + +static uint32_t LPUART1_EdmaGetRxCount(void) +{ + return LPUART_EdmaGetRxCount(&LPUART1_EdmaDriverState); +} + +static int32_t LPUART1_EdmaControl(uint32_t control, uint32_t arg) +{ + return LPUART_EdmaControl(control, arg, &LPUART1_EdmaDriverState); +} + +static ARM_USART_STATUS LPUART1_EdmaGetStatus(void) +{ + return LPUART_EdmaGetStatus(&LPUART1_EdmaDriverState); +} + +#endif + +#else + +lpuart_handle_t LPUART1_Handle; + +#if defined(USART1_RX_BUFFER_ENABLE) && (USART1_RX_BUFFER_ENABLE == 1) +static uint8_t lpuart1_rxRingBuffer[USART_RX_BUFFER_LEN]; +#endif + +#if defined(USART2_RX_BUFFER_ENABLE) && (USART2_RX_BUFFER_ENABLE == 1) +static uint8_t lpuart2_rxRingBuffer[USART_RX_BUFFER_LEN]; +#endif + +#if defined(__CC_ARM) || defined(__ARMCC_VERSION) +ARMCC_SECTION("lpuart1_non_blocking_driver_state") +cmsis_lpuart_non_blocking_driver_state_t LPUART1_NonBlockingDriverState = { +#else +cmsis_lpuart_non_blocking_driver_state_t LPUART1_NonBlockingDriverState = { +#endif + &LPUART1_Resource, + &LPUART1_Handle, +}; + +static int32_t LPUART1_NonBlockingInitialize(ARM_USART_SignalEvent_t cb_event) +{ + LPUART1_InitPins(); + return LPUART_NonBlockingInitialize(cb_event, &LPUART1_NonBlockingDriverState); +} + +static int32_t LPUART1_NonBlockingUninitialize(void) +{ + LPUART1_DeinitPins(); + return LPUART_NonBlockingUninitialize(&LPUART1_NonBlockingDriverState); +} + +static int32_t LPUART1_NonBlockingPowerControl(ARM_POWER_STATE state) +{ + uint32_t result; + + result = LPUART_NonBlockingPowerControl(state, &LPUART1_NonBlockingDriverState); + +#if defined(USART1_RX_BUFFER_ENABLE) && (USART1_RX_BUFFER_ENABLE == 1) + if ((state == ARM_POWER_FULL) && (LPUART1_NonBlockingDriverState.handle->rxRingBuffer == NULL)) + { + LPUART_TransferStartRingBuffer(LPUART1_NonBlockingDriverState.resource->base, + LPUART1_NonBlockingDriverState.handle, lpuart1_rxRingBuffer, + USART_RX_BUFFER_LEN); + } +#endif + + return result; +} + +static int32_t LPUART1_NonBlockingSend(const void *data, uint32_t num) +{ + return LPUART_NonBlockingSend(data, num, &LPUART1_NonBlockingDriverState); +} + +static int32_t LPUART1_NonBlockingReceive(void *data, uint32_t num) +{ + return LPUART_NonBlockingReceive(data, num, &LPUART1_NonBlockingDriverState); +} + +static int32_t LPUART1_NonBlockingTransfer(const void *data_out, void *data_in, uint32_t num) +{ + return LPUART_NonBlockingTransfer(data_out, data_in, num, &LPUART1_NonBlockingDriverState); +} + +static uint32_t LPUART1_NonBlockingGetTxCount(void) +{ + return LPUART_NonBlockingGetTxCount(&LPUART1_NonBlockingDriverState); +} + +static uint32_t LPUART1_NonBlockingGetRxCount(void) +{ + return LPUART_NonBlockingGetRxCount(&LPUART1_NonBlockingDriverState); +} + +static int32_t LPUART1_NonBlockingControl(uint32_t control, uint32_t arg) +{ + int32_t result; + + result = LPUART_NonBlockingControl(control, arg, &LPUART1_NonBlockingDriverState); + if (ARM_DRIVER_OK != result) + { + return result; + } + + /* Enable the receive interrupts if ring buffer is used */ + if (LPUART1_NonBlockingDriverState.handle->rxRingBuffer != NULL) + { + LPUART_EnableInterrupts(LPUART1_NonBlockingDriverState.resource->base, + kLPUART_RxDataRegFullInterruptEnable | kLPUART_RxOverrunInterruptEnable); + } + + return ARM_DRIVER_OK; +} + +static ARM_USART_STATUS LPUART1_NonBlockingGetStatus(void) +{ + return LPUART_NonBlockingGetStatus(&LPUART1_NonBlockingDriverState); +} + +#endif + +ARM_DRIVER_USART Driver_USART1 = {LPUARTx_GetVersion, LPUARTx_GetCapabilities, +#if RTE_USART1_DMA_EN +#if (defined(FSL_FEATURE_SOC_EDMA_COUNT) && FSL_FEATURE_SOC_EDMA_COUNT) + LPUART1_EdmaInitialize, LPUART1_EdmaUninitialize, LPUART1_EdmaPowerControl, + LPUART1_EdmaSend, LPUART1_EdmaReceive, LPUART1_EdmaTransfer, + LPUART1_EdmaGetTxCount, LPUART1_EdmaGetRxCount, LPUART1_EdmaControl, + LPUART1_EdmaGetStatus, +#else + LPUART1_DmaInitialize, LPUART1_DmaUninitialize, LPUART1_DmaPowerControl, + LPUART1_DmaSend, LPUART1_DmaReceive, LPUART1_DmaTransfer, + LPUART1_DmaGetTxCount, LPUART1_DmaGetRxCount, LPUART1_DmaControl, + LPUART1_DmaGetStatus, +#endif +#else + LPUART1_NonBlockingInitialize, + LPUART1_NonBlockingUninitialize, + LPUART1_NonBlockingPowerControl, + LPUART1_NonBlockingSend, + LPUART1_NonBlockingReceive, + LPUART1_NonBlockingTransfer, + LPUART1_NonBlockingGetTxCount, + LPUART1_NonBlockingGetRxCount, + LPUART1_NonBlockingControl, + LPUART1_NonBlockingGetStatus, +#endif + LPUARTx_SetModemControl, LPUARTx_GetModemStatus}; + +#endif /* LPUART1 */ + +#if defined(LPUART2) && RTE_USART2 + +/* User needs to provide the implementation for LPUART2_GetFreq/InitPins/DeinitPins +in the application for enabling according instance. */ +extern uint32_t LPUART2_GetFreq(void); +extern void LPUART2_InitPins(void); +extern void LPUART2_DeinitPins(void); + +cmsis_lpuart_resource_t LPUART2_Resource = {LPUART2, LPUART2_GetFreq}; + +#if RTE_USART2_DMA_EN + +#if (defined(FSL_FEATURE_SOC_DMA_COUNT) && FSL_FEATURE_SOC_DMA_COUNT) + +cmsis_lpuart_dma_resource_t LPUART2_DmaResource = { + RTE_USART2_DMA_TX_DMA_BASE, RTE_USART2_DMA_TX_CH, RTE_USART2_DMA_TX_PERI_SEL, + RTE_USART2_DMA_RX_DMA_BASE, RTE_USART2_DMA_RX_CH, RTE_USART2_DMA_RX_PERI_SEL, + +#if (defined(FSL_FEATURE_SOC_DMAMUX_COUNT) && FSL_FEATURE_SOC_DMAMUX_COUNT) + RTE_USART2_DMA_TX_DMAMUX_BASE, RTE_USART2_DMA_RX_DMAMUX_BASE, +#endif +}; + +lpuart_dma_handle_t LPUART2_DmaHandle; +dma_handle_t LPUART2_DmaRxHandle; +dma_handle_t LPUART2_DmaTxHandle; + +#if defined(__CC_ARM) || defined(__ARMCC_VERSION) +ARMCC_SECTION("lpuart2_dma_driver_state") +cmsis_lpuart_dma_driver_state_t LPUART2_DmaDriverState = { +#else +cmsis_lpuart_dma_driver_state_t LPUART2_DmaDriverState = { +#endif + &LPUART2_Resource, &LPUART2_DmaResource, &LPUART2_DmaHandle, &LPUART2_DmaRxHandle, &LPUART2_DmaTxHandle, +}; + +static int32_t LPUART2_DmaInitialize(ARM_USART_SignalEvent_t cb_event) +{ + LPUART2_InitPins(); + return LPUART_DmaInitialize(cb_event, &LPUART2_DmaDriverState); +} + +static int32_t LPUART2_DmaUninitialize(void) +{ + LPUART2_DeinitPins(); + return LPUART_DmaUninitialize(&LPUART2_DmaDriverState); +} + +static int32_t LPUART2_DmaPowerControl(ARM_POWER_STATE state) +{ + return LPUART_DmaPowerControl(state, &LPUART2_DmaDriverState); +} + +static int32_t LPUART2_DmaSend(const void *data, uint32_t num) +{ + return LPUART_DmaSend(data, num, &LPUART2_DmaDriverState); +} + +static int32_t LPUART2_DmaReceive(void *data, uint32_t num) +{ + return LPUART_DmaReceive(data, num, &LPUART2_DmaDriverState); +} + +static int32_t LPUART2_DmaTransfer(const void *data_out, void *data_in, uint32_t num) +{ + return LPUART_DmaTransfer(data_out, data_in, num, &LPUART2_DmaDriverState); +} + +static uint32_t LPUART2_DmaGetTxCount(void) +{ + return LPUART_DmaGetTxCount(&LPUART2_DmaDriverState); +} + +static uint32_t LPUART2_DmaGetRxCount(void) +{ + return LPUART_DmaGetRxCount(&LPUART2_DmaDriverState); +} + +static int32_t LPUART2_DmaControl(uint32_t control, uint32_t arg) +{ + return LPUART_DmaControl(control, arg, &LPUART2_DmaDriverState); +} + +static ARM_USART_STATUS LPUART2_DmaGetStatus(void) +{ + return LPUART_DmaGetStatus(&LPUART2_DmaDriverState); +} + +#endif + +#if (defined(FSL_FEATURE_SOC_EDMA_COUNT) && FSL_FEATURE_SOC_EDMA_COUNT) + +cmsis_lpuart_edma_resource_t LPUART2_EdmaResource = { + RTE_USART2_DMA_TX_DMA_BASE, RTE_USART2_DMA_TX_CH, RTE_USART2_DMA_TX_PERI_SEL, + RTE_USART2_DMA_RX_DMA_BASE, RTE_USART2_DMA_RX_CH, RTE_USART2_DMA_RX_PERI_SEL, + +#if (defined(FSL_FEATURE_SOC_DMAMUX_COUNT) && FSL_FEATURE_SOC_DMAMUX_COUNT) + RTE_USART2_DMA_TX_DMAMUX_BASE, RTE_USART2_DMA_RX_DMAMUX_BASE, +#endif +}; + +lpuart_edma_handle_t LPUART2_EdmaHandle; +edma_handle_t LPUART2_EdmaRxHandle; +edma_handle_t LPUART2_EdmaTxHandle; + +#if defined(__CC_ARM) || defined(__ARMCC_VERSION) +ARMCC_SECTION("lpuart2_edma_driver_state") +cmsis_lpuart_edma_driver_state_t LPUART2_EdmaDriverState = { +#else +cmsis_lpuart_edma_driver_state_t LPUART2_EdmaDriverState = { +#endif + &LPUART2_Resource, &LPUART2_EdmaResource, &LPUART2_EdmaHandle, &LPUART2_EdmaRxHandle, &LPUART2_EdmaTxHandle, +}; + +static int32_t LPUART2_EdmaInitialize(ARM_USART_SignalEvent_t cb_event) +{ + LPUART2_InitPins(); + return LPUART_EdmaInitialize(cb_event, &LPUART2_EdmaDriverState); +} + +static int32_t LPUART2_EdmaUninitialize(void) +{ + LPUART2_DeinitPins(); + return LPUART_EdmaUninitialize(&LPUART2_EdmaDriverState); +} + +static int32_t LPUART2_EdmaPowerControl(ARM_POWER_STATE state) +{ + return LPUART_EdmaPowerControl(state, &LPUART2_EdmaDriverState); +} + +static int32_t LPUART2_EdmaSend(const void *data, uint32_t num) +{ + return LPUART_EdmaSend(data, num, &LPUART2_EdmaDriverState); +} + +static int32_t LPUART2_EdmaReceive(void *data, uint32_t num) +{ + return LPUART_EdmaReceive(data, num, &LPUART2_EdmaDriverState); +} + +static int32_t LPUART2_EdmaTransfer(const void *data_out, void *data_in, uint32_t num) +{ + return LPUART_EdmaTransfer(data_out, data_in, num, &LPUART2_EdmaDriverState); +} + +static uint32_t LPUART2_EdmaGetTxCount(void) +{ + return LPUART_EdmaGetTxCount(&LPUART2_EdmaDriverState); +} + +static uint32_t LPUART2_EdmaGetRxCount(void) +{ + return LPUART_EdmaGetRxCount(&LPUART2_EdmaDriverState); +} + +static int32_t LPUART2_EdmaControl(uint32_t control, uint32_t arg) +{ + return LPUART_EdmaControl(control, arg, &LPUART2_EdmaDriverState); +} + +static ARM_USART_STATUS LPUART2_EdmaGetStatus(void) +{ + return LPUART_EdmaGetStatus(&LPUART2_EdmaDriverState); +} + +#endif + +#else + +lpuart_handle_t LPUART2_Handle; + +#if defined(USART2_RX_BUFFER_ENABLE) && (USART2_RX_BUFFER_ENABLE == 1) +static uint8_t lpuart2_rxRingBuffer[USART_RX_BUFFER_LEN]; +#endif + +#if defined(USART3_RX_BUFFER_ENABLE) && (USART3_RX_BUFFER_ENABLE == 1) +static uint8_t lpuart3_rxRingBuffer[USART_RX_BUFFER_LEN]; +#endif + +#if defined(__CC_ARM) || defined(__ARMCC_VERSION) +ARMCC_SECTION("lpuart2_non_blocking_driver_state") +cmsis_lpuart_non_blocking_driver_state_t LPUART2_NonBlockingDriverState = { +#else +cmsis_lpuart_non_blocking_driver_state_t LPUART2_NonBlockingDriverState = { +#endif + &LPUART2_Resource, + &LPUART2_Handle, +}; + +static int32_t LPUART2_NonBlockingInitialize(ARM_USART_SignalEvent_t cb_event) +{ + LPUART2_InitPins(); + return LPUART_NonBlockingInitialize(cb_event, &LPUART2_NonBlockingDriverState); +} + +static int32_t LPUART2_NonBlockingUninitialize(void) +{ + LPUART2_DeinitPins(); + return LPUART_NonBlockingUninitialize(&LPUART2_NonBlockingDriverState); +} + +static int32_t LPUART2_NonBlockingPowerControl(ARM_POWER_STATE state) +{ + uint32_t result; + + result = LPUART_NonBlockingPowerControl(state, &LPUART2_NonBlockingDriverState); + +#if defined(USART2_RX_BUFFER_ENABLE) && (USART2_RX_BUFFER_ENABLE == 1) + if ((state == ARM_POWER_FULL) && (LPUART2_NonBlockingDriverState.handle->rxRingBuffer == NULL)) + { + LPUART_TransferStartRingBuffer(LPUART2_NonBlockingDriverState.resource->base, + LPUART2_NonBlockingDriverState.handle, lpuart2_rxRingBuffer, + USART_RX_BUFFER_LEN); + } +#endif + + return result; +} + +static int32_t LPUART2_NonBlockingSend(const void *data, uint32_t num) +{ + return LPUART_NonBlockingSend(data, num, &LPUART2_NonBlockingDriverState); +} + +static int32_t LPUART2_NonBlockingReceive(void *data, uint32_t num) +{ + return LPUART_NonBlockingReceive(data, num, &LPUART2_NonBlockingDriverState); +} + +static int32_t LPUART2_NonBlockingTransfer(const void *data_out, void *data_in, uint32_t num) +{ + return LPUART_NonBlockingTransfer(data_out, data_in, num, &LPUART2_NonBlockingDriverState); +} + +static uint32_t LPUART2_NonBlockingGetTxCount(void) +{ + return LPUART_NonBlockingGetTxCount(&LPUART2_NonBlockingDriverState); +} + +static uint32_t LPUART2_NonBlockingGetRxCount(void) +{ + return LPUART_NonBlockingGetRxCount(&LPUART2_NonBlockingDriverState); +} + +static int32_t LPUART2_NonBlockingControl(uint32_t control, uint32_t arg) +{ + int32_t result; + + result = LPUART_NonBlockingControl(control, arg, &LPUART2_NonBlockingDriverState); + if (ARM_DRIVER_OK != result) + { + return result; + } + + /* Enable the receive interrupts if ring buffer is used */ + if (LPUART2_NonBlockingDriverState.handle->rxRingBuffer != NULL) + { + LPUART_EnableInterrupts(LPUART2_NonBlockingDriverState.resource->base, + kLPUART_RxDataRegFullInterruptEnable | kLPUART_RxOverrunInterruptEnable); + } + + return ARM_DRIVER_OK; +} + +static ARM_USART_STATUS LPUART2_NonBlockingGetStatus(void) +{ + return LPUART_NonBlockingGetStatus(&LPUART2_NonBlockingDriverState); +} + +#endif + +ARM_DRIVER_USART Driver_USART2 = {LPUARTx_GetVersion, LPUARTx_GetCapabilities, +#if RTE_USART2_DMA_EN +#if (defined(FSL_FEATURE_SOC_EDMA_COUNT) && FSL_FEATURE_SOC_EDMA_COUNT) + LPUART2_EdmaInitialize, LPUART2_EdmaUninitialize, LPUART2_EdmaPowerControl, + LPUART2_EdmaSend, LPUART2_EdmaReceive, LPUART2_EdmaTransfer, + LPUART2_EdmaGetTxCount, LPUART2_EdmaGetRxCount, LPUART2_EdmaControl, + LPUART2_EdmaGetStatus, +#else + LPUART2_DmaInitialize, LPUART2_DmaUninitialize, LPUART2_DmaPowerControl, + LPUART2_DmaSend, LPUART2_DmaReceive, LPUART2_DmaTransfer, + LPUART2_DmaGetTxCount, LPUART2_DmaGetRxCount, LPUART2_DmaControl, + LPUART2_DmaGetStatus, +#endif +#else + LPUART2_NonBlockingInitialize, + LPUART2_NonBlockingUninitialize, + LPUART2_NonBlockingPowerControl, + LPUART2_NonBlockingSend, + LPUART2_NonBlockingReceive, + LPUART2_NonBlockingTransfer, + LPUART2_NonBlockingGetTxCount, + LPUART2_NonBlockingGetRxCount, + LPUART2_NonBlockingControl, + LPUART2_NonBlockingGetStatus, +#endif + LPUARTx_SetModemControl, LPUARTx_GetModemStatus}; + +#endif /* LPUART2 */ + +#if defined(LPUART3) && RTE_USART3 + +/* User needs to provide the implementation for LPUART3_GetFreq/InitPins/DeinitPins +in the application for enabling according instance. */ +extern uint32_t LPUART3_GetFreq(void); +extern void LPUART3_InitPins(void); +extern void LPUART3_DeinitPins(void); + +cmsis_lpuart_resource_t LPUART3_Resource = {LPUART3, LPUART3_GetFreq}; + +#if RTE_USART3_DMA_EN + +#if (defined(FSL_FEATURE_SOC_DMA_COUNT) && FSL_FEATURE_SOC_DMA_COUNT) + +cmsis_lpuart_dma_resource_t LPUART3_DmaResource = { + RTE_USART3_DMA_TX_DMA_BASE, RTE_USART3_DMA_TX_CH, RTE_USART3_DMA_TX_PERI_SEL, + RTE_USART3_DMA_RX_DMA_BASE, RTE_USART3_DMA_RX_CH, RTE_USART3_DMA_RX_PERI_SEL, + +#if (defined(FSL_FEATURE_SOC_DMAMUX_COUNT) && FSL_FEATURE_SOC_DMAMUX_COUNT) + RTE_USART3_DMA_TX_DMAMUX_BASE, RTE_USART3_DMA_RX_DMAMUX_BASE, +#endif +}; + +lpuart_dma_handle_t LPUART3_DmaHandle; +dma_handle_t LPUART3_DmaRxHandle; +dma_handle_t LPUART3_DmaTxHandle; + +#if defined(__CC_ARM) || defined(__ARMCC_VERSION) +ARMCC_SECTION("lpuart3_dma_driver_state") +cmsis_lpuart_dma_driver_state_t LPUART3_DmaDriverState = { +#else +cmsis_lpuart_dma_driver_state_t LPUART3_DmaDriverState = { +#endif + &LPUART3_Resource, &LPUART3_DmaResource, &LPUART3_DmaHandle, &LPUART3_DmaRxHandle, &LPUART3_DmaTxHandle, +}; + +static int32_t LPUART3_DmaInitialize(ARM_USART_SignalEvent_t cb_event) +{ + LPUART3_InitPins(); + return LPUART_DmaInitialize(cb_event, &LPUART3_DmaDriverState); +} + +static int32_t LPUART3_DmaUninitialize(void) +{ + LPUART3_DeinitPins(); + return LPUART_DmaUninitialize(&LPUART3_DmaDriverState); +} + +static int32_t LPUART3_DmaPowerControl(ARM_POWER_STATE state) +{ + return LPUART_DmaPowerControl(state, &LPUART3_DmaDriverState); +} + +static int32_t LPUART3_DmaSend(const void *data, uint32_t num) +{ + return LPUART_DmaSend(data, num, &LPUART3_DmaDriverState); +} + +static int32_t LPUART3_DmaReceive(void *data, uint32_t num) +{ + return LPUART_DmaReceive(data, num, &LPUART3_DmaDriverState); +} + +static int32_t LPUART3_DmaTransfer(const void *data_out, void *data_in, uint32_t num) +{ + return LPUART_DmaTransfer(data_out, data_in, num, &LPUART3_DmaDriverState); +} + +static uint32_t LPUART3_DmaGetTxCount(void) +{ + return LPUART_DmaGetTxCount(&LPUART3_DmaDriverState); +} + +static uint32_t LPUART3_DmaGetRxCount(void) +{ + return LPUART_DmaGetRxCount(&LPUART3_DmaDriverState); +} + +static int32_t LPUART3_DmaControl(uint32_t control, uint32_t arg) +{ + return LPUART_DmaControl(control, arg, &LPUART3_DmaDriverState); +} + +static ARM_USART_STATUS LPUART3_DmaGetStatus(void) +{ + return LPUART_DmaGetStatus(&LPUART3_DmaDriverState); +} + +#endif + +#if (defined(FSL_FEATURE_SOC_EDMA_COUNT) && FSL_FEATURE_SOC_EDMA_COUNT) + +cmsis_lpuart_edma_resource_t LPUART3_EdmaResource = { + RTE_USART3_DMA_TX_DMA_BASE, RTE_USART3_DMA_TX_CH, RTE_USART3_DMA_TX_PERI_SEL, + RTE_USART3_DMA_RX_DMA_BASE, RTE_USART3_DMA_RX_CH, RTE_USART3_DMA_RX_PERI_SEL, + +#if (defined(FSL_FEATURE_SOC_DMAMUX_COUNT) && FSL_FEATURE_SOC_DMAMUX_COUNT) + RTE_USART3_DMA_TX_DMAMUX_BASE, RTE_USART3_DMA_RX_DMAMUX_BASE, +#endif +}; + +lpuart_edma_handle_t LPUART3_EdmaHandle; +edma_handle_t LPUART3_EdmaRxHandle; +edma_handle_t LPUART3_EdmaTxHandle; + +#if defined(__CC_ARM) || defined(__ARMCC_VERSION) +ARMCC_SECTION("lpuart3_edma_driver_state") +cmsis_lpuart_edma_driver_state_t LPUART3_EdmaDriverState = { +#else +cmsis_lpuart_edma_driver_state_t LPUART3_EdmaDriverState = { +#endif + &LPUART3_Resource, &LPUART3_EdmaResource, &LPUART3_EdmaHandle, &LPUART3_EdmaRxHandle, &LPUART3_EdmaTxHandle, +}; + +static int32_t LPUART3_EdmaInitialize(ARM_USART_SignalEvent_t cb_event) +{ + LPUART3_InitPins(); + return LPUART_EdmaInitialize(cb_event, &LPUART3_EdmaDriverState); +} + +static int32_t LPUART3_EdmaUninitialize(void) +{ + LPUART3_DeinitPins(); + return LPUART_EdmaUninitialize(&LPUART3_EdmaDriverState); +} + +static int32_t LPUART3_EdmaPowerControl(ARM_POWER_STATE state) +{ + return LPUART_EdmaPowerControl(state, &LPUART3_EdmaDriverState); +} + +static int32_t LPUART3_EdmaSend(const void *data, uint32_t num) +{ + return LPUART_EdmaSend(data, num, &LPUART3_EdmaDriverState); +} + +static int32_t LPUART3_EdmaReceive(void *data, uint32_t num) +{ + return LPUART_EdmaReceive(data, num, &LPUART3_EdmaDriverState); +} + +static int32_t LPUART3_EdmaTransfer(const void *data_out, void *data_in, uint32_t num) +{ + return LPUART_EdmaTransfer(data_out, data_in, num, &LPUART3_EdmaDriverState); +} + +static uint32_t LPUART3_EdmaGetTxCount(void) +{ + return LPUART_EdmaGetTxCount(&LPUART3_EdmaDriverState); +} + +static uint32_t LPUART3_EdmaGetRxCount(void) +{ + return LPUART_EdmaGetRxCount(&LPUART3_EdmaDriverState); +} + +static int32_t LPUART3_EdmaControl(uint32_t control, uint32_t arg) +{ + return LPUART_EdmaControl(control, arg, &LPUART3_EdmaDriverState); +} + +static ARM_USART_STATUS LPUART3_EdmaGetStatus(void) +{ + return LPUART_EdmaGetStatus(&LPUART3_EdmaDriverState); +} + +#endif + +#else + +lpuart_handle_t LPUART3_Handle; + +#if defined(USART3_RX_BUFFER_ENABLE) && (USART3_RX_BUFFER_ENABLE == 1) +static uint8_t lpuart3_rxRingBuffer[USART_RX_BUFFER_LEN]; +#endif + +#if defined(USART4_RX_BUFFER_ENABLE) && (USART4_RX_BUFFER_ENABLE == 1) +static uint8_t lpuart4_rxRingBuffer[USART_RX_BUFFER_LEN]; +#endif + +#if defined(__CC_ARM) || defined(__ARMCC_VERSION) +ARMCC_SECTION("lpuart3_non_blocking_driver_state") +cmsis_lpuart_non_blocking_driver_state_t LPUART3_NonBlockingDriverState = { +#else +cmsis_lpuart_non_blocking_driver_state_t LPUART3_NonBlockingDriverState = { +#endif + &LPUART3_Resource, + &LPUART3_Handle, +}; + +static int32_t LPUART3_NonBlockingInitialize(ARM_USART_SignalEvent_t cb_event) +{ + LPUART3_InitPins(); + return LPUART_NonBlockingInitialize(cb_event, &LPUART3_NonBlockingDriverState); +} + +static int32_t LPUART3_NonBlockingUninitialize(void) +{ + LPUART3_DeinitPins(); + return LPUART_NonBlockingUninitialize(&LPUART3_NonBlockingDriverState); +} + +static int32_t LPUART3_NonBlockingPowerControl(ARM_POWER_STATE state) +{ + uint32_t result; + + result = LPUART_NonBlockingPowerControl(state, &LPUART3_NonBlockingDriverState); + +#if defined(USART3_RX_BUFFER_ENABLE) && (USART3_RX_BUFFER_ENABLE == 1) + if ((state == ARM_POWER_FULL) && (LPUART3_NonBlockingDriverState.handle->rxRingBuffer == NULL)) + { + LPUART_TransferStartRingBuffer(LPUART3_NonBlockingDriverState.resource->base, + LPUART3_NonBlockingDriverState.handle, lpuart3_rxRingBuffer, + USART_RX_BUFFER_LEN); + } +#endif + + return result; +} + +static int32_t LPUART3_NonBlockingSend(const void *data, uint32_t num) +{ + return LPUART_NonBlockingSend(data, num, &LPUART3_NonBlockingDriverState); +} + +static int32_t LPUART3_NonBlockingReceive(void *data, uint32_t num) +{ + return LPUART_NonBlockingReceive(data, num, &LPUART3_NonBlockingDriverState); +} + +static int32_t LPUART3_NonBlockingTransfer(const void *data_out, void *data_in, uint32_t num) +{ + return LPUART_NonBlockingTransfer(data_out, data_in, num, &LPUART3_NonBlockingDriverState); +} + +static uint32_t LPUART3_NonBlockingGetTxCount(void) +{ + return LPUART_NonBlockingGetTxCount(&LPUART3_NonBlockingDriverState); +} + +static uint32_t LPUART3_NonBlockingGetRxCount(void) +{ + return LPUART_NonBlockingGetRxCount(&LPUART3_NonBlockingDriverState); +} + +static int32_t LPUART3_NonBlockingControl(uint32_t control, uint32_t arg) +{ + int32_t result; + + result = LPUART_NonBlockingControl(control, arg, &LPUART3_NonBlockingDriverState); + if (ARM_DRIVER_OK != result) + { + return result; + } + + /* Enable the receive interrupts if ring buffer is used */ + if (LPUART3_NonBlockingDriverState.handle->rxRingBuffer != NULL) + { + LPUART_EnableInterrupts(LPUART3_NonBlockingDriverState.resource->base, + kLPUART_RxDataRegFullInterruptEnable | kLPUART_RxOverrunInterruptEnable); + } + + return ARM_DRIVER_OK; +} + +static ARM_USART_STATUS LPUART3_NonBlockingGetStatus(void) +{ + return LPUART_NonBlockingGetStatus(&LPUART3_NonBlockingDriverState); +} + +#endif + +ARM_DRIVER_USART Driver_USART3 = {LPUARTx_GetVersion, LPUARTx_GetCapabilities, +#if RTE_USART3_DMA_EN +#if (defined(FSL_FEATURE_SOC_EDMA_COUNT) && FSL_FEATURE_SOC_EDMA_COUNT) + LPUART3_EdmaInitialize, LPUART3_EdmaUninitialize, LPUART3_EdmaPowerControl, + LPUART3_EdmaSend, LPUART3_EdmaReceive, LPUART3_EdmaTransfer, + LPUART3_EdmaGetTxCount, LPUART3_EdmaGetRxCount, LPUART3_EdmaControl, + LPUART3_EdmaGetStatus, +#else + LPUART3_DmaInitialize, LPUART3_DmaUninitialize, LPUART3_DmaPowerControl, + LPUART3_DmaSend, LPUART3_DmaReceive, LPUART3_DmaTransfer, + LPUART3_DmaGetTxCount, LPUART3_DmaGetRxCount, LPUART3_DmaControl, + LPUART3_DmaGetStatus, +#endif +#else + LPUART3_NonBlockingInitialize, + LPUART3_NonBlockingUninitialize, + LPUART3_NonBlockingPowerControl, + LPUART3_NonBlockingSend, + LPUART3_NonBlockingReceive, + LPUART3_NonBlockingTransfer, + LPUART3_NonBlockingGetTxCount, + LPUART3_NonBlockingGetRxCount, + LPUART3_NonBlockingControl, + LPUART3_NonBlockingGetStatus, +#endif + LPUARTx_SetModemControl, LPUARTx_GetModemStatus}; + +#endif /* LPUART3 */ + +#if defined(LPUART4) && RTE_USART4 + +/* User needs to provide the implementation for LPUART4_GetFreq/InitPins/DeinitPins +in the application for enabling according instance. */ +extern uint32_t LPUART4_GetFreq(void); +extern void LPUART4_InitPins(void); +extern void LPUART4_DeinitPins(void); + +cmsis_lpuart_resource_t LPUART4_Resource = {LPUART4, LPUART4_GetFreq}; + +#if RTE_USART4_DMA_EN + +#if (defined(FSL_FEATURE_SOC_DMA_COUNT) && FSL_FEATURE_SOC_DMA_COUNT) + +cmsis_lpuart_dma_resource_t LPUART4_DmaResource = { + RTE_USART4_DMA_TX_DMA_BASE, RTE_USART4_DMA_TX_CH, RTE_USART4_DMA_TX_PERI_SEL, + RTE_USART4_DMA_RX_DMA_BASE, RTE_USART4_DMA_RX_CH, RTE_USART4_DMA_RX_PERI_SEL, + +#if (defined(FSL_FEATURE_SOC_DMAMUX_COUNT) && FSL_FEATURE_SOC_DMAMUX_COUNT) + RTE_USART4_DMA_TX_DMAMUX_BASE, RTE_USART4_DMA_RX_DMAMUX_BASE, +#endif +}; + +lpuart_dma_handle_t LPUART4_DmaHandle; +dma_handle_t LPUART4_DmaRxHandle; +dma_handle_t LPUART4_DmaTxHandle; + +#if defined(__CC_ARM) || defined(__ARMCC_VERSION) +ARMCC_SECTION("lpuart4_dma_driver_state") +cmsis_lpuart_dma_driver_state_t LPUART4_DmaDriverState = { +#else +cmsis_lpuart_dma_driver_state_t LPUART4_DmaDriverState = { +#endif + &LPUART4_Resource, &LPUART4_DmaResource, &LPUART4_DmaHandle, &LPUART4_DmaRxHandle, &LPUART4_DmaTxHandle}; + +static int32_t LPUART4_DmaInitialize(ARM_USART_SignalEvent_t cb_event) +{ + LPUART4_InitPins(); + return LPUART_DmaInitialize(cb_event, &LPUART4_DmaDriverState); +} + +static int32_t LPUART4_DmaUninitialize(void) +{ + LPUART4_DeinitPins(); + return LPUART_DmaUninitialize(&LPUART4_DmaDriverState); +} + +static int32_t LPUART4_DmaPowerControl(ARM_POWER_STATE state) +{ + return LPUART_DmaPowerControl(state, &LPUART4_DmaDriverState); +} + +static int32_t LPUART4_DmaSend(const void *data, uint32_t num) +{ + return LPUART_DmaSend(data, num, &LPUART4_DmaDriverState); +} + +static int32_t LPUART4_DmaReceive(void *data, uint32_t num) +{ + return LPUART_DmaReceive(data, num, &LPUART4_DmaDriverState); +} + +static int32_t LPUART4_DmaTransfer(const void *data_out, void *data_in, uint32_t num) +{ + return LPUART_DmaTransfer(data_out, data_in, num, &LPUART4_DmaDriverState); +} + +static uint32_t LPUART4_DmaGetTxCount(void) +{ + return LPUART_DmaGetTxCount(&LPUART4_DmaDriverState); +} + +static uint32_t LPUART4_DmaGetRxCount(void) +{ + return LPUART_DmaGetRxCount(&LPUART4_DmaDriverState); +} + +static int32_t LPUART4_DmaControl(uint32_t control, uint32_t arg) +{ + return LPUART_DmaControl(control, arg, &LPUART4_DmaDriverState); +} + +static ARM_USART_STATUS LPUART4_DmaGetStatus(void) +{ + return LPUART_DmaGetStatus(&LPUART4_DmaDriverState); +} + +#endif + +#if (defined(FSL_FEATURE_SOC_EDMA_COUNT) && FSL_FEATURE_SOC_EDMA_COUNT) + +cmsis_lpuart_edma_resource_t LPUART4_EdmaResource = { + RTE_USART4_DMA_TX_DMA_BASE, RTE_USART4_DMA_TX_CH, RTE_USART4_DMA_TX_PERI_SEL, + RTE_USART4_DMA_RX_DMA_BASE, RTE_USART4_DMA_RX_CH, RTE_USART4_DMA_RX_PERI_SEL, + +#if (defined(FSL_FEATURE_SOC_DMAMUX_COUNT) && FSL_FEATURE_SOC_DMAMUX_COUNT) + RTE_USART4_DMA_TX_DMAMUX_BASE, RTE_USART4_DMA_RX_DMAMUX_BASE, +#endif +}; + +lpuart_edma_handle_t LPUART4_EdmaHandle; +edma_handle_t LPUART4_EdmaRxHandle; +edma_handle_t LPUART4_EdmaTxHandle; + +#if defined(__CC_ARM) || defined(__ARMCC_VERSION) +ARMCC_SECTION("lpuart4_edma_driver_state") +cmsis_lpuart_edma_driver_state_t LPUART4_EdmaDriverState = { +#else +cmsis_lpuart_edma_driver_state_t LPUART4_EdmaDriverState = { +#endif + &LPUART4_Resource, &LPUART4_EdmaResource, &LPUART4_EdmaHandle, &LPUART4_EdmaRxHandle, &LPUART4_EdmaTxHandle}; + +static int32_t LPUART4_EdmaInitialize(ARM_USART_SignalEvent_t cb_event) +{ + LPUART4_InitPins(); + return LPUART_EdmaInitialize(cb_event, &LPUART4_EdmaDriverState); +} + +static int32_t LPUART4_EdmaUninitialize(void) +{ + LPUART4_DeinitPins(); + return LPUART_EdmaUninitialize(&LPUART4_EdmaDriverState); +} + +static int32_t LPUART4_EdmaPowerControl(ARM_POWER_STATE state) +{ + return LPUART_EdmaPowerControl(state, &LPUART4_EdmaDriverState); +} + +static int32_t LPUART4_EdmaSend(const void *data, uint32_t num) +{ + return LPUART_EdmaSend(data, num, &LPUART4_EdmaDriverState); +} + +static int32_t LPUART4_EdmaReceive(void *data, uint32_t num) +{ + return LPUART_EdmaReceive(data, num, &LPUART4_EdmaDriverState); +} + +static int32_t LPUART4_EdmaTransfer(const void *data_out, void *data_in, uint32_t num) +{ + return LPUART_EdmaTransfer(data_out, data_in, num, &LPUART4_EdmaDriverState); +} + +static uint32_t LPUART4_EdmaGetTxCount(void) +{ + return LPUART_EdmaGetTxCount(&LPUART4_EdmaDriverState); +} + +static uint32_t LPUART4_EdmaGetRxCount(void) +{ + return LPUART_EdmaGetRxCount(&LPUART4_EdmaDriverState); +} + +static int32_t LPUART4_EdmaControl(uint32_t control, uint32_t arg) +{ + return LPUART_EdmaControl(control, arg, &LPUART4_EdmaDriverState); +} + +static ARM_USART_STATUS LPUART4_EdmaGetStatus(void) +{ + return LPUART_EdmaGetStatus(&LPUART4_EdmaDriverState); +} + +#endif + +#else + +lpuart_handle_t LPUART4_Handle; + +#if defined(USART4_RX_BUFFER_ENABLE) && (USART4_RX_BUFFER_ENABLE == 1) +static uint8_t lpuart4_rxRingBuffer[USART_RX_BUFFER_LEN]; +#endif + +#if defined(USART5_RX_BUFFER_ENABLE) && (USART5_RX_BUFFER_ENABLE == 1) +static uint8_t lpuart5_rxRingBuffer[USART_RX_BUFFER_LEN]; +#endif + +#if defined(__CC_ARM) || defined(__ARMCC_VERSION) +ARMCC_SECTION("lpuart4_non_blocking_driver_state") +cmsis_lpuart_non_blocking_driver_state_t LPUART4_NonBlockingDriverState = { +#else +cmsis_lpuart_non_blocking_driver_state_t LPUART4_NonBlockingDriverState = { +#endif + &LPUART4_Resource, + &LPUART4_Handle, +}; + +static int32_t LPUART4_NonBlockingInitialize(ARM_USART_SignalEvent_t cb_event) +{ + LPUART4_InitPins(); + return LPUART_NonBlockingInitialize(cb_event, &LPUART4_NonBlockingDriverState); +} + +static int32_t LPUART4_NonBlockingUninitialize(void) +{ + LPUART4_DeinitPins(); + return LPUART_NonBlockingUninitialize(&LPUART4_NonBlockingDriverState); +} + +static int32_t LPUART4_NonBlockingPowerControl(ARM_POWER_STATE state) +{ + uint32_t result; + + result = LPUART_NonBlockingPowerControl(state, &LPUART4_NonBlockingDriverState); + +#if defined(USART4_RX_BUFFER_ENABLE) && (USART4_RX_BUFFER_ENABLE == 1) + if ((state == ARM_POWER_FULL) && (LPUART4_NonBlockingDriverState.handle->rxRingBuffer == NULL)) + { + LPUART_TransferStartRingBuffer(LPUART4_NonBlockingDriverState.resource->base, + LPUART4_NonBlockingDriverState.handle, lpuart4_rxRingBuffer, + USART_RX_BUFFER_LEN); + } +#endif + + return result; +} + +static int32_t LPUART4_NonBlockingSend(const void *data, uint32_t num) +{ + return LPUART_NonBlockingSend(data, num, &LPUART4_NonBlockingDriverState); +} + +static int32_t LPUART4_NonBlockingReceive(void *data, uint32_t num) +{ + return LPUART_NonBlockingReceive(data, num, &LPUART4_NonBlockingDriverState); +} + +static int32_t LPUART4_NonBlockingTransfer(const void *data_out, void *data_in, uint32_t num) +{ + return LPUART_NonBlockingTransfer(data_out, data_in, num, &LPUART4_NonBlockingDriverState); +} + +static uint32_t LPUART4_NonBlockingGetTxCount(void) +{ + return LPUART_NonBlockingGetTxCount(&LPUART4_NonBlockingDriverState); +} + +static uint32_t LPUART4_NonBlockingGetRxCount(void) +{ + return LPUART_NonBlockingGetRxCount(&LPUART4_NonBlockingDriverState); +} + +static int32_t LPUART4_NonBlockingControl(uint32_t control, uint32_t arg) +{ + int32_t result; + + result = LPUART_NonBlockingControl(control, arg, &LPUART4_NonBlockingDriverState); + if (ARM_DRIVER_OK != result) + { + return result; + } + + /* Enable the receive interrupts if ring buffer is used */ + if (LPUART4_NonBlockingDriverState.handle->rxRingBuffer != NULL) + { + LPUART_EnableInterrupts(LPUART4_NonBlockingDriverState.resource->base, + kLPUART_RxDataRegFullInterruptEnable | kLPUART_RxOverrunInterruptEnable); + } + + return ARM_DRIVER_OK; +} + +static ARM_USART_STATUS LPUART4_NonBlockingGetStatus(void) +{ + return LPUART_NonBlockingGetStatus(&LPUART4_NonBlockingDriverState); +} + +#endif + +ARM_DRIVER_USART Driver_USART4 = {LPUARTx_GetVersion, LPUARTx_GetCapabilities, +#if RTE_USART4_DMA_EN +#if (defined(FSL_FEATURE_SOC_EDMA_COUNT) && FSL_FEATURE_SOC_EDMA_COUNT) + LPUART4_EdmaInitialize, LPUART4_EdmaUninitialize, LPUART4_EdmaPowerControl, + LPUART4_EdmaSend, LPUART4_EdmaReceive, LPUART4_EdmaTransfer, + LPUART4_EdmaGetTxCount, LPUART4_EdmaGetRxCount, LPUART4_EdmaControl, + LPUART4_EdmaGetStatus, +#else + LPUART4_DmaInitialize, LPUART4_DmaUninitialize, LPUART4_DmaPowerControl, + LPUART4_DmaSend, LPUART4_DmaReceive, LPUART4_DmaTransfer, + LPUART4_DmaGetTxCount, LPUART4_DmaGetRxCount, LPUART4_DmaControl, + LPUART4_DmaGetStatus, +#endif +#else + LPUART4_NonBlockingInitialize, + LPUART4_NonBlockingUninitialize, + LPUART4_NonBlockingPowerControl, + LPUART4_NonBlockingSend, + LPUART4_NonBlockingReceive, + LPUART4_NonBlockingTransfer, + LPUART4_NonBlockingGetTxCount, + LPUART4_NonBlockingGetRxCount, + LPUART4_NonBlockingControl, + LPUART4_NonBlockingGetStatus, +#endif + LPUARTx_SetModemControl, LPUARTx_GetModemStatus}; + +#endif /* LPUART4 */ + +#if defined(LPUART5) && RTE_USART5 + +/* User needs to provide the implementation for LPUART5_GetFreq/InitPins/DeinitPins +in the application for enabling according instance. */ +extern uint32_t LPUART5_GetFreq(void); +extern void LPUART5_InitPins(void); +extern void LPUART5_DeinitPins(void); + +cmsis_lpuart_resource_t LPUART5_Resource = {LPUART5, LPUART5_GetFreq}; + +#if RTE_USART5_DMA_EN + +#if (defined(FSL_FEATURE_SOC_DMA_COUNT) && FSL_FEATURE_SOC_DMA_COUNT) + +cmsis_lpuart_dma_resource_t LPUART5_DmaResource = { + RTE_USART5_DMA_TX_DMA_BASE, RTE_USART5_DMA_TX_CH, RTE_USART5_DMA_TX_PERI_SEL, + RTE_USART5_DMA_RX_DMA_BASE, RTE_USART5_DMA_RX_CH, RTE_USART5_DMA_RX_PERI_SEL, + +#if (defined(FSL_FEATURE_SOC_DMAMUX_COUNT) && FSL_FEATURE_SOC_DMAMUX_COUNT) + RTE_USART5_DMA_TX_DMAMUX_BASE, RTE_USART5_DMA_RX_DMAMUX_BASE, +#endif +}; + +lpuart_dma_handle_t LPUART5_DmaHandle; +dma_handle_t LPUART5_DmaRxHandle; +dma_handle_t LPUART5_DmaTxHandle; + +#if defined(__CC_ARM) || defined(__ARMCC_VERSION) +ARMCC_SECTION("lpuart5_dma_driver_state") +cmsis_lpuart_dma_driver_state_t LPUART5_DmaDriverState = { +#else +cmsis_lpuart_dma_driver_state_t LPUART5_DmaDriverState = { +#endif + &LPUART5_Resource, &LPUART5_DmaResource, &LPUART5_DmaHandle, &LPUART5_DmaRxHandle, &LPUART5_DmaTxHandle, +}; + +static int32_t LPUART5_DmaInitialize(ARM_USART_SignalEvent_t cb_event) +{ + LPUART5_InitPins(); + return LPUART_DmaInitialize(cb_event, &LPUART5_DmaDriverState); +} + +static int32_t LPUART5_DmaUninitialize(void) +{ + LPUART5_DeinitPins(); + return LPUART_DmaUninitialize(&LPUART5_DmaDriverState); +} + +static int32_t LPUART5_DmaPowerControl(ARM_POWER_STATE state) +{ + return LPUART_DmaPowerControl(state, &LPUART5_DmaDriverState); +} + +static int32_t LPUART5_DmaSend(const void *data, uint32_t num) +{ + return LPUART_DmaSend(data, num, &LPUART5_DmaDriverState); +} + +static int32_t LPUART5_DmaReceive(void *data, uint32_t num) +{ + return LPUART_DmaReceive(data, num, &LPUART5_DmaDriverState); +} + +static int32_t LPUART5_DmaTransfer(const void *data_out, void *data_in, uint32_t num) +{ + return LPUART_DmaTransfer(data_out, data_in, num, &LPUART5_DmaDriverState); +} + +static uint32_t LPUART5_DmaGetTxCount(void) +{ + return LPUART_DmaGetTxCount(&LPUART5_DmaDriverState); +} + +static uint32_t LPUART5_DmaGetRxCount(void) +{ + return LPUART_DmaGetRxCount(&LPUART5_DmaDriverState); +} + +static int32_t LPUART5_DmaControl(uint32_t control, uint32_t arg) +{ + return LPUART_DmaControl(control, arg, &LPUART5_DmaDriverState); +} + +static ARM_USART_STATUS LPUART5_DmaGetStatus(void) +{ + return LPUART_DmaGetStatus(&LPUART5_DmaDriverState); +} + +/* LPUART5 Driver Control Block */ + +#endif + +#if (defined(FSL_FEATURE_SOC_EDMA_COUNT) && FSL_FEATURE_SOC_EDMA_COUNT) + +cmsis_lpuart_edma_resource_t LPUART5_EdmaResource = { + RTE_USART5_DMA_TX_DMA_BASE, RTE_USART5_DMA_TX_CH, RTE_USART5_DMA_TX_PERI_SEL, + RTE_USART5_DMA_RX_DMA_BASE, RTE_USART5_DMA_RX_CH, RTE_USART5_DMA_RX_PERI_SEL, + +#if (defined(FSL_FEATURE_SOC_DMAMUX_COUNT) && FSL_FEATURE_SOC_DMAMUX_COUNT) + RTE_USART5_DMA_TX_DMAMUX_BASE, RTE_USART5_DMA_RX_DMAMUX_BASE, +#endif +}; + +lpuart_edma_handle_t LPUART5_EdmaHandle; +edma_handle_t LPUART5_EdmaRxHandle; +edma_handle_t LPUART5_EdmaTxHandle; + +#if defined(__CC_ARM) || defined(__ARMCC_VERSION) +ARMCC_SECTION("lpuart5_edma_driver_state") +cmsis_lpuart_edma_driver_state_t LPUART5_EdmaDriverState = { +#else +cmsis_lpuart_edma_driver_state_t LPUART5_EdmaDriverState = { +#endif + &LPUART5_Resource, &LPUART5_EdmaResource, &LPUART5_EdmaHandle, &LPUART5_EdmaRxHandle, &LPUART5_EdmaTxHandle, +}; + +static int32_t LPUART5_EdmaInitialize(ARM_USART_SignalEvent_t cb_event) +{ + LPUART5_InitPins(); + return LPUART_EdmaInitialize(cb_event, &LPUART5_EdmaDriverState); +} + +static int32_t LPUART5_EdmaUninitialize(void) +{ + LPUART5_DeinitPins(); + return LPUART_EdmaUninitialize(&LPUART5_EdmaDriverState); +} + +static int32_t LPUART5_EdmaPowerControl(ARM_POWER_STATE state) +{ + return LPUART_EdmaPowerControl(state, &LPUART5_EdmaDriverState); +} + +static int32_t LPUART5_EdmaSend(const void *data, uint32_t num) +{ + return LPUART_EdmaSend(data, num, &LPUART5_EdmaDriverState); +} + +static int32_t LPUART5_EdmaReceive(void *data, uint32_t num) +{ + return LPUART_EdmaReceive(data, num, &LPUART5_EdmaDriverState); +} + +static int32_t LPUART5_EdmaTransfer(const void *data_out, void *data_in, uint32_t num) +{ + return LPUART_EdmaTransfer(data_out, data_in, num, &LPUART5_EdmaDriverState); +} + +static uint32_t LPUART5_EdmaGetTxCount(void) +{ + return LPUART_EdmaGetTxCount(&LPUART5_EdmaDriverState); +} + +static uint32_t LPUART5_EdmaGetRxCount(void) +{ + return LPUART_EdmaGetRxCount(&LPUART5_EdmaDriverState); +} + +static int32_t LPUART5_EdmaControl(uint32_t control, uint32_t arg) +{ + return LPUART_EdmaControl(control, arg, &LPUART5_EdmaDriverState); +} + +static ARM_USART_STATUS LPUART5_EdmaGetStatus(void) +{ + return LPUART_EdmaGetStatus(&LPUART5_EdmaDriverState); +} + +#endif + +#else + +lpuart_handle_t LPUART5_Handle; + +#if defined(USART5_RX_BUFFER_ENABLE) && (USART5_RX_BUFFER_ENABLE == 1) +static uint8_t lpuart5_rxRingBuffer[USART_RX_BUFFER_LEN]; +#endif + +#if defined(__CC_ARM) || defined(__ARMCC_VERSION) +ARMCC_SECTION("lpuart5_non_blocking_driver_state") +cmsis_lpuart_non_blocking_driver_state_t LPUART5_NonBlockingDriverState = { +#else +cmsis_lpuart_non_blocking_driver_state_t LPUART5_NonBlockingDriverState = { +#endif + &LPUART5_Resource, + &LPUART5_Handle, +}; + +static int32_t LPUART5_NonBlockingInitialize(ARM_USART_SignalEvent_t cb_event) +{ + LPUART5_InitPins(); + return LPUART_NonBlockingInitialize(cb_event, &LPUART5_NonBlockingDriverState); +} + +static int32_t LPUART5_NonBlockingUninitialize(void) +{ + LPUART5_DeinitPins(); + return LPUART_NonBlockingUninitialize(&LPUART5_NonBlockingDriverState); +} + +static int32_t LPUART5_NonBlockingPowerControl(ARM_POWER_STATE state) +{ + uint32_t result; + + result = LPUART_NonBlockingPowerControl(state, &LPUART5_NonBlockingDriverState); + +#if defined(USART5_RX_BUFFER_ENABLE) && (USART5_RX_BUFFER_ENABLE == 1) + if ((state == ARM_POWER_FULL) && (LPUART5_NonBlockingDriverState.handle->rxRingBuffer == NULL)) + { + LPUART_TransferStartRingBuffer(LPUART5_NonBlockingDriverState.resource->base, + LPUART5_NonBlockingDriverState.handle, lpuart5_rxRingBuffer, + USART_RX_BUFFER_LEN); + } +#endif + + return result; +} + +static int32_t LPUART5_NonBlockingSend(const void *data, uint32_t num) +{ + return LPUART_NonBlockingSend(data, num, &LPUART5_NonBlockingDriverState); +} + +static int32_t LPUART5_NonBlockingReceive(void *data, uint32_t num) +{ + return LPUART_NonBlockingReceive(data, num, &LPUART5_NonBlockingDriverState); +} + +static int32_t LPUART5_NonBlockingTransfer(const void *data_out, void *data_in, uint32_t num) +{ + return LPUART_NonBlockingTransfer(data_out, data_in, num, &LPUART5_NonBlockingDriverState); +} + +static uint32_t LPUART5_NonBlockingGetTxCount(void) +{ + return LPUART_NonBlockingGetTxCount(&LPUART5_NonBlockingDriverState); +} + +static uint32_t LPUART5_NonBlockingGetRxCount(void) +{ + return LPUART_NonBlockingGetRxCount(&LPUART5_NonBlockingDriverState); +} + +static int32_t LPUART5_NonBlockingControl(uint32_t control, uint32_t arg) +{ + int32_t result; + + result = LPUART_NonBlockingControl(control, arg, &LPUART5_NonBlockingDriverState); + if (ARM_DRIVER_OK != result) + { + return result; + } + + /* Enable the receive interrupts if ring buffer is used */ + if (LPUART5_NonBlockingDriverState.handle->rxRingBuffer != NULL) + { + LPUART_EnableInterrupts(LPUART5_NonBlockingDriverState.resource->base, + kLPUART_RxDataRegFullInterruptEnable | kLPUART_RxOverrunInterruptEnable); + } + + return ARM_DRIVER_OK; +} + +static ARM_USART_STATUS LPUART5_NonBlockingGetStatus(void) +{ + return LPUART_NonBlockingGetStatus(&LPUART5_NonBlockingDriverState); +} + +#endif + +ARM_DRIVER_USART Driver_USART5 = {LPUARTx_GetVersion, LPUARTx_GetCapabilities, +#if RTE_USART5_DMA_EN +#if (defined(FSL_FEATURE_SOC_EDMA_COUNT) && FSL_FEATURE_SOC_EDMA_COUNT) + LPUART5_EdmaInitialize, LPUART5_EdmaUninitialize, LPUART5_EdmaPowerControl, + LPUART5_EdmaSend, LPUART5_EdmaReceive, LPUART5_EdmaTransfer, + LPUART5_EdmaGetTxCount, LPUART5_EdmaGetRxCount, LPUART5_EdmaControl, + LPUART5_EdmaGetStatus, +#else + LPUART5_DmaInitialize, LPUART5_DmaUninitialize, LPUART5_DmaPowerControl, + LPUART5_DmaSend, LPUART5_DmaReceive, LPUART5_DmaTransfer, + LPUART5_DmaGetTxCount, LPUART5_DmaGetRxCount, LPUART5_DmaControl, + LPUART5_DmaGetStatus, +#endif /* FSL_FEATURE_SOC_EDMA_COUNT */ +#else + LPUART5_NonBlockingInitialize, + LPUART5_NonBlockingUninitialize, + LPUART5_NonBlockingPowerControl, + LPUART5_NonBlockingSend, + LPUART5_NonBlockingReceive, + LPUART5_NonBlockingTransfer, + LPUART5_NonBlockingGetTxCount, + LPUART5_NonBlockingGetRxCount, + LPUART5_NonBlockingControl, + LPUART5_NonBlockingGetStatus, +#endif /* RTE_USART5_DMA_EN */ + LPUARTx_SetModemControl, LPUARTx_GetModemStatus}; + +#endif /* LPUART5 */ + +#if defined(LPUART6) && RTE_USART6 + +/* User needs to provide the implementation for LPUART5_GetFreq/InitPins/DeinitPins +in the application for enabling according instance. */ +extern uint32_t LPUART6_GetFreq(void); +extern void LPUART6_InitPins(void); +extern void LPUART6_DeinitPins(void); + +cmsis_lpuart_resource_t LPUART6_Resource = {LPUART6, LPUART6_GetFreq}; + +#if RTE_USART6_DMA_EN + +#if (defined(FSL_FEATURE_SOC_DMA_COUNT) && FSL_FEATURE_SOC_DMA_COUNT) + +cmsis_lpuart_dma_resource_t LPUART6_DmaResource = { + RTE_USART6_DMA_TX_DMA_BASE, RTE_USART6_DMA_TX_CH, RTE_USART6_DMA_TX_PERI_SEL, + RTE_USART6_DMA_RX_DMA_BASE, RTE_USART6_DMA_RX_CH, RTE_USART6_DMA_RX_PERI_SEL, + +#if (defined(FSL_FEATURE_SOC_DMAMUX_COUNT) && FSL_FEATURE_SOC_DMAMUX_COUNT) + RTE_USART6_DMA_TX_DMAMUX_BASE, RTE_USART6_DMA_RX_DMAMUX_BASE, +#endif +}; + +lpuart_dma_handle_t LPUART6_DmaHandle; +dma_handle_t LPUART6_DmaRxHandle; +dma_handle_t LPUART6_DmaTxHandle; + +#if defined(__CC_ARM) || defined(__ARMCC_VERSION) +ARMCC_SECTION("lpuart5_dma_driver_state") +cmsis_lpuart_dma_driver_state_t LPUART6_DmaDriverState = { +#else +cmsis_lpuart_dma_driver_state_t LPUART6_DmaDriverState = { +#endif + &LPUART6_Resource, &LPUART6_DmaResource, &LPUART6_DmaHandle, &LPUART6_DmaRxHandle, &LPUART6_DmaTxHandle, +}; + +static int32_t LPUART6_DmaInitialize(ARM_USART_SignalEvent_t cb_event) +{ + LPUART6_InitPins(); + return LPUART_DmaInitialize(cb_event, &LPUART6_DmaDriverState); +} + +static int32_t LPUART6_DmaUninitialize(void) +{ + LPUART6_DeinitPins(); + return LPUART_DmaUninitialize(&LPUART6_DmaDriverState); +} + +static int32_t LPUART6_DmaPowerControl(ARM_POWER_STATE state) +{ + return LPUART_DmaPowerControl(state, &LPUART6_DmaDriverState); +} + +static int32_t LPUART6_DmaSend(const void *data, uint32_t num) +{ + return LPUART_DmaSend(data, num, &LPUART6_DmaDriverState); +} + +static int32_t LPUART6_DmaReceive(void *data, uint32_t num) +{ + return LPUART_DmaReceive(data, num, &LPUART6_DmaDriverState); +} + +static int32_t LPUART6_DmaTransfer(const void *data_out, void *data_in, uint32_t num) +{ + return LPUART_DmaTransfer(data_out, data_in, num, &LPUART6_DmaDriverState); +} + +static uint32_t LPUART6_DmaGetTxCount(void) +{ + return LPUART_DmaGetTxCount(&LPUART6_DmaDriverState); +} + +static uint32_t LPUART6_DmaGetRxCount(void) +{ + return LPUART_DmaGetRxCount(&LPUART6_DmaDriverState); +} + +static int32_t LPUART6_DmaControl(uint32_t control, uint32_t arg) +{ + return LPUART_DmaControl(control, arg, &LPUART6_DmaDriverState); +} + +static ARM_USART_STATUS LPUART6_DmaGetStatus(void) +{ + return LPUART_DmaGetStatus(&LPUART6_DmaDriverState); +} + +/* LPUART6 Driver Control Block */ + +#endif + +#if (defined(FSL_FEATURE_SOC_EDMA_COUNT) && FSL_FEATURE_SOC_EDMA_COUNT) + +cmsis_lpuart_edma_resource_t LPUART6_EdmaResource = { + RTE_USART6_DMA_TX_DMA_BASE, RTE_USART6_DMA_TX_CH, RTE_USART6_DMA_TX_PERI_SEL, + RTE_USART6_DMA_RX_DMA_BASE, RTE_USART6_DMA_RX_CH, RTE_USART6_DMA_RX_PERI_SEL, + +#if (defined(FSL_FEATURE_SOC_DMAMUX_COUNT) && FSL_FEATURE_SOC_DMAMUX_COUNT) + RTE_USART6_DMA_TX_DMAMUX_BASE, RTE_USART6_DMA_RX_DMAMUX_BASE, +#endif +}; + +lpuart_edma_handle_t LPUART6_EdmaHandle; +edma_handle_t LPUART6_EdmaRxHandle; +edma_handle_t LPUART6_EdmaTxHandle; + +#if defined(__CC_ARM) || defined(__ARMCC_VERSION) +ARMCC_SECTION("lpuart6_edma_driver_state") +cmsis_lpuart_edma_driver_state_t LPUART6_EdmaDriverState = { +#else +cmsis_lpuart_edma_driver_state_t LPUART6_EdmaDriverState = { +#endif + &LPUART6_Resource, &LPUART6_EdmaResource, &LPUART6_EdmaHandle, &LPUART6_EdmaRxHandle, &LPUART6_EdmaTxHandle, +}; + +static int32_t LPUART6_EdmaInitialize(ARM_USART_SignalEvent_t cb_event) +{ + LPUART6_InitPins(); + return LPUART_EdmaInitialize(cb_event, &LPUART6_EdmaDriverState); +} + +static int32_t LPUART6_EdmaUninitialize(void) +{ + LPUART6_DeinitPins(); + return LPUART_EdmaUninitialize(&LPUART6_EdmaDriverState); +} + +static int32_t LPUART6_EdmaPowerControl(ARM_POWER_STATE state) +{ + return LPUART_EdmaPowerControl(state, &LPUART6_EdmaDriverState); +} + +static int32_t LPUART6_EdmaSend(const void *data, uint32_t num) +{ + return LPUART_EdmaSend(data, num, &LPUART6_EdmaDriverState); +} + +static int32_t LPUART6_EdmaReceive(void *data, uint32_t num) +{ + return LPUART_EdmaReceive(data, num, &LPUART6_EdmaDriverState); +} + +static int32_t LPUART6_EdmaTransfer(const void *data_out, void *data_in, uint32_t num) +{ + return LPUART_EdmaTransfer(data_out, data_in, num, &LPUART6_EdmaDriverState); +} + +static uint32_t LPUART6_EdmaGetTxCount(void) +{ + return LPUART_EdmaGetTxCount(&LPUART6_EdmaDriverState); +} + +static uint32_t LPUART6_EdmaGetRxCount(void) +{ + return LPUART_EdmaGetRxCount(&LPUART6_EdmaDriverState); +} + +static int32_t LPUART6_EdmaControl(uint32_t control, uint32_t arg) +{ + return LPUART_EdmaControl(control, arg, &LPUART6_EdmaDriverState); +} + +static ARM_USART_STATUS LPUART6_EdmaGetStatus(void) +{ + return LPUART_EdmaGetStatus(&LPUART6_EdmaDriverState); +} + +#endif + +#else + +lpuart_handle_t LPUART6_Handle; + +#if defined(USART6_RX_BUFFER_ENABLE) && (USART6_RX_BUFFER_ENABLE == 1) +static uint8_t lpuart6_rxRingBuffer[USART_RX_BUFFER_LEN]; +#endif + +#if defined(__CC_ARM) || defined(__ARMCC_VERSION) +ARMCC_SECTION("lpuart6_non_blocking_driver_state") +cmsis_lpuart_non_blocking_driver_state_t LPUART6_NonBlockingDriverState = { +#else +cmsis_lpuart_non_blocking_driver_state_t LPUART6_NonBlockingDriverState = { +#endif + &LPUART6_Resource, + &LPUART6_Handle, +}; + +static int32_t LPUART6_NonBlockingInitialize(ARM_USART_SignalEvent_t cb_event) +{ + LPUART6_InitPins(); + return LPUART_NonBlockingInitialize(cb_event, &LPUART6_NonBlockingDriverState); +} + +static int32_t LPUART6_NonBlockingUninitialize(void) +{ + LPUART6_DeinitPins(); + return LPUART_NonBlockingUninitialize(&LPUART6_NonBlockingDriverState); +} + +static int32_t LPUART6_NonBlockingPowerControl(ARM_POWER_STATE state) +{ + uint32_t result; + + result = LPUART_NonBlockingPowerControl(state, &LPUART6_NonBlockingDriverState); + +#if defined(USART6_RX_BUFFER_ENABLE) && (USART6_RX_BUFFER_ENABLE == 1) + if ((state == ARM_POWER_FULL) && (LPUART6_NonBlockingDriverState.handle->rxRingBuffer == NULL)) + { + LPUART_TransferStartRingBuffer(LPUART6_NonBlockingDriverState.resource->base, + LPUART6_NonBlockingDriverState.handle, lpuart6_rxRingBuffer, + USART_RX_BUFFER_LEN); + } +#endif + + return result; +} + +static int32_t LPUART6_NonBlockingSend(const void *data, uint32_t num) +{ + return LPUART_NonBlockingSend(data, num, &LPUART6_NonBlockingDriverState); +} + +static int32_t LPUART6_NonBlockingReceive(void *data, uint32_t num) +{ + return LPUART_NonBlockingReceive(data, num, &LPUART6_NonBlockingDriverState); +} + +static int32_t LPUART6_NonBlockingTransfer(const void *data_out, void *data_in, uint32_t num) +{ + return LPUART_NonBlockingTransfer(data_out, data_in, num, &LPUART6_NonBlockingDriverState); +} + +static uint32_t LPUART6_NonBlockingGetTxCount(void) +{ + return LPUART_NonBlockingGetTxCount(&LPUART6_NonBlockingDriverState); +} + +static uint32_t LPUART6_NonBlockingGetRxCount(void) +{ + return LPUART_NonBlockingGetRxCount(&LPUART6_NonBlockingDriverState); +} + +static int32_t LPUART6_NonBlockingControl(uint32_t control, uint32_t arg) +{ + int32_t result; + + result = LPUART_NonBlockingControl(control, arg, &LPUART6_NonBlockingDriverState); + if (ARM_DRIVER_OK != result) + { + return result; + } + + /* Enable the receive interrupts if ring buffer is used */ + if (LPUART6_NonBlockingDriverState.handle->rxRingBuffer != NULL) + { + LPUART_EnableInterrupts(LPUART6_NonBlockingDriverState.resource->base, + kLPUART_RxDataRegFullInterruptEnable | kLPUART_RxOverrunInterruptEnable); + } + + return ARM_DRIVER_OK; +} + +static ARM_USART_STATUS LPUART6_NonBlockingGetStatus(void) +{ + return LPUART_NonBlockingGetStatus(&LPUART6_NonBlockingDriverState); +} + +#endif + +ARM_DRIVER_USART Driver_USART6 = {LPUARTx_GetVersion, LPUARTx_GetCapabilities, +#if RTE_USART6_DMA_EN +#if (defined(FSL_FEATURE_SOC_EDMA_COUNT) && FSL_FEATURE_SOC_EDMA_COUNT) + LPUART6_EdmaInitialize, LPUART6_EdmaUninitialize, LPUART6_EdmaPowerControl, + LPUART6_EdmaSend, LPUART6_EdmaReceive, LPUART6_EdmaTransfer, + LPUART6_EdmaGetTxCount, LPUART6_EdmaGetRxCount, LPUART6_EdmaControl, + LPUART6_EdmaGetStatus, +#else + LPUART6_DmaInitialize, LPUART6_DmaUninitialize, LPUART6_DmaPowerControl, + LPUART6_DmaSend, LPUART6_DmaReceive, LPUART6_DmaTransfer, + LPUART6_DmaGetTxCount, LPUART6_DmaGetRxCount, LPUART6_DmaControl, + LPUART6_DmaGetStatus, +#endif /* FSL_FEATURE_SOC_EDMA_COUNT */ +#else + LPUART6_NonBlockingInitialize, + LPUART6_NonBlockingUninitialize, + LPUART6_NonBlockingPowerControl, + LPUART6_NonBlockingSend, + LPUART6_NonBlockingReceive, + LPUART6_NonBlockingTransfer, + LPUART6_NonBlockingGetTxCount, + LPUART6_NonBlockingGetRxCount, + LPUART6_NonBlockingControl, + LPUART6_NonBlockingGetStatus, +#endif /* RTE_USART6_DMA_EN */ + LPUARTx_SetModemControl, LPUARTx_GetModemStatus}; + +#endif /* LPUART6 */ diff --git a/source/hic_hal/freescale/kl27z/MKL27Z4/fsl_lpuart_cmsis.h b/source/hic_hal/freescale/kl27z/MKL27Z4/fsl_lpuart_cmsis.h new file mode 100644 index 0000000000..ee4a0eedba --- /dev/null +++ b/source/hic_hal/freescale/kl27z/MKL27Z4/fsl_lpuart_cmsis.h @@ -0,0 +1,89 @@ +/* + * Copyright (c) 2013-2016 ARM Limited. All rights reserved. + * Copyright (c) 2016, Freescale Semiconductor, Inc. Not a Contribution. + * Copyright 2016-2017 NXP. Not a Contribution. + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef _FSL_LPUART_CMSIS_H_ +#define _FSL_LPUART_CMSIS_H_ + +#include "fsl_common.h" +#include "Driver_USART.h" +#include "RTE_Device.h" +#include "fsl_lpuart.h" +#if (defined(FSL_FEATURE_SOC_DMAMUX_COUNT) && FSL_FEATURE_SOC_DMAMUX_COUNT) +#include "fsl_dmamux.h" +#endif +#if (defined(FSL_FEATURE_SOC_DMA_COUNT) && FSL_FEATURE_SOC_DMA_COUNT) +#include "fsl_lpuart_dma.h" +#endif +#if (defined(FSL_FEATURE_SOC_EDMA_COUNT) && FSL_FEATURE_SOC_EDMA_COUNT) +#include "fsl_lpuart_edma.h" +#endif + +#if defined(LPUART0) +extern ARM_DRIVER_USART Driver_USART0; +#endif /* LPUART0 */ + +#if defined(LPUART1) +extern ARM_DRIVER_USART Driver_USART1; +#endif /* LPUART1 */ + +#if defined(LPUART2) +extern ARM_DRIVER_USART Driver_USART2; +#endif /* LPUART2 */ + +#if defined(LPUART3) +extern ARM_DRIVER_USART Driver_USART3; +#endif /* LPUART3 */ + +#if defined(LPUART4) +extern ARM_DRIVER_USART Driver_USART4; +#endif /* LPUART4 */ + +#if defined(LPUART5) +extern ARM_DRIVER_USART Driver_USART5; +#endif /* LPUART5 */ + +#if defined(LPUART6) +extern ARM_DRIVER_USART Driver_USART6; +#endif /* LPUART6 */ + +#if (FSL_FEATURE_SOC_LPUART_COUNT == 1) && (FSL_FEATURE_SOC_UART_COUNT == 3) + +extern ARM_DRIVER_USART Driver_USART3; + +#endif + +#if (FSL_FEATURE_SOC_LPUART_COUNT == 1) && (FSL_FEATURE_SOC_UART_COUNT == 4) + +extern ARM_DRIVER_USART Driver_USART4; + +#endif + +#if (FSL_FEATURE_SOC_LPUART_COUNT == 1) && (FSL_FEATURE_SOC_UART_COUNT == 5) +extern ARM_DRIVER_USART Driver_USART5; + +#endif + +/* USART Driver state flags */ +#define USART_FLAG_UNINIT (0) +#define USART_FLAG_INIT (1 << 0) +#define USART_FLAG_POWER (1 << 1) +#define USART_FLAG_CONFIGURED (1 << 2) + +#endif /* _FSL_LPUART_CMSIS_H_ */ diff --git a/source/hic_hal/freescale/kl27z/MKL27Z4/fsl_lpuart_dma.h b/source/hic_hal/freescale/kl27z/MKL27Z4/fsl_lpuart_dma.h new file mode 100644 index 0000000000..0f59e68fe3 --- /dev/null +++ b/source/hic_hal/freescale/kl27z/MKL27Z4/fsl_lpuart_dma.h @@ -0,0 +1,171 @@ +/* + * Copyright (c) 2015, Freescale Semiconductor, Inc. + * Copyright 2016-2020 NXP + * All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ +#ifndef _FSL_LPUART_DMA_H_ +#define _FSL_LPUART_DMA_H_ + +#include "fsl_lpuart.h" +#include "fsl_dma.h" + +/*! + * @addtogroup lpuart_dma_driver + * @{ + */ + +/******************************************************************************* + * Definitions + ******************************************************************************/ + +/*! @name Driver version */ +/*@{*/ +/*! @brief LPUART DMA driver version 2.3.0. */ +#define FSL_LPUART_DMA_DRIVER_VERSION (MAKE_VERSION(2, 3, 0)) +/*@}*/ + +/* Forward declaration of the handle typedef. */ +typedef struct _lpuart_dma_handle lpuart_dma_handle_t; + +/*! @brief LPUART transfer callback function. */ +typedef void (*lpuart_dma_transfer_callback_t)(LPUART_Type *base, + lpuart_dma_handle_t *handle, + status_t status, + void *userData); + +/*! + * @brief LPUART DMA handle + */ +struct _lpuart_dma_handle +{ + lpuart_dma_transfer_callback_t callback; /*!< Callback function. */ + void *userData; /*!< LPUART callback function parameter.*/ + size_t rxDataSizeAll; /*!< Size of the data to receive. */ + size_t txDataSizeAll; /*!< Size of the data to send out. */ + + dma_handle_t *txDmaHandle; /*!< The DMA TX channel used. */ + dma_handle_t *rxDmaHandle; /*!< The DMA RX channel used. */ + + volatile uint8_t txState; /*!< TX transfer state. */ + volatile uint8_t rxState; /*!< RX transfer state */ +}; + +/******************************************************************************* + * API + ******************************************************************************/ + +#if defined(__cplusplus) +extern "C" { +#endif + +/*! + * @name EDMA transactional + * @{ + */ + +/*! + * @brief Initializes the LPUART handle which is used in transactional functions. + * @param base LPUART peripheral base address. + * @param handle Pointer to lpuart_dma_handle_t structure. + * @param callback Callback function. + * @param userData User data. + * @param txDmaHandle User-requested DMA handle for TX DMA transfer. + * @param rxDmaHandle User-requested DMA handle for RX DMA transfer. + */ +void LPUART_TransferCreateHandleDMA(LPUART_Type *base, + lpuart_dma_handle_t *handle, + lpuart_dma_transfer_callback_t callback, + void *userData, + dma_handle_t *txDmaHandle, + dma_handle_t *rxDmaHandle); + +/*! + * @brief Sends data using DMA. + * + * This function sends data using DMA. This is a non-blocking function, which returns + * right away. When all data is sent, the send callback function is called. + * + * @param base LPUART peripheral base address. + * @param handle LPUART handle pointer. + * @param xfer LPUART DMA transfer structure. See #lpuart_transfer_t. + * @retval kStatus_Success if succeed, others failed. + * @retval kStatus_LPUART_TxBusy Previous transfer on going. + * @retval kStatus_InvalidArgument Invalid argument. + */ +status_t LPUART_TransferSendDMA(LPUART_Type *base, lpuart_dma_handle_t *handle, lpuart_transfer_t *xfer); + +/*! + * @brief Receives data using DMA. + * + * This function receives data using DMA. This is a non-blocking function, which returns + * right away. When all data is received, the receive callback function is called. + * + * @param base LPUART peripheral base address. + * @param handle Pointer to lpuart_dma_handle_t structure. + * @param xfer LPUART DMA transfer structure. See #lpuart_transfer_t. + * @retval kStatus_Success if succeed, others failed. + * @retval kStatus_LPUART_RxBusy Previous transfer on going. + * @retval kStatus_InvalidArgument Invalid argument. + */ +status_t LPUART_TransferReceiveDMA(LPUART_Type *base, lpuart_dma_handle_t *handle, lpuart_transfer_t *xfer); + +/*! + * @brief Aborts the sent data using DMA. + * + * This function aborts send data using DMA. + * + * @param base LPUART peripheral base address + * @param handle Pointer to lpuart_dma_handle_t structure + */ +void LPUART_TransferAbortSendDMA(LPUART_Type *base, lpuart_dma_handle_t *handle); + +/*! + * @brief Aborts the received data using DMA. + * + * This function aborts the received data using DMA. + * + * @param base LPUART peripheral base address + * @param handle Pointer to lpuart_dma_handle_t structure + */ +void LPUART_TransferAbortReceiveDMA(LPUART_Type *base, lpuart_dma_handle_t *handle); + +/*! + * @brief Gets the number of bytes written to the LPUART TX register. + * + * This function gets the number of bytes that have been written to LPUART TX + * register by DMA. + * + * @param base LPUART peripheral base address. + * @param handle LPUART 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 LPUART_TransferGetSendCountDMA(LPUART_Type *base, lpuart_dma_handle_t *handle, uint32_t *count); + +/*! + * @brief Gets the number of received bytes. + * + * This function gets the number of received bytes. + * + * @param base LPUART peripheral base address. + * @param handle LPUART 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 LPUART_TransferGetReceiveCountDMA(LPUART_Type *base, lpuart_dma_handle_t *handle, uint32_t *count); + +/*@}*/ + +#if defined(__cplusplus) +} +#endif + +/*! @}*/ + +#endif /* _FSL_LPUART_DMA_H_ */ diff --git a/source/hic_hal/freescale/kl27z/RTE_Device.h b/source/hic_hal/freescale/kl27z/RTE_Device.h new file mode 100644 index 0000000000..794fd2f190 --- /dev/null +++ b/source/hic_hal/freescale/kl27z/RTE_Device.h @@ -0,0 +1,97 @@ +/* + * Copyright (c) 2016, Freescale Semiconductor, Inc. + * Copyright 2016 - 2017 , NXP + * All rights reserved. + * + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef __RTE_DEVICE_H +#define __RTE_DEVICE_H + +/* UART Select. */ +/* Select LPUART0 - LPUART1. */ +#define RTE_USART0 0 +#define RTE_USART0_DMA_EN 0 +#define RTE_USART1 1 +#define RTE_USART1_DMA_EN 0 +#define RTE_USART2 0 +#define RTE_USART2_DMA_EN 0 + +/* UART configuration. */ +#define USART_RX_BUFFER_LEN 64 +#define USART0_RX_BUFFER_ENABLE 0 +#define USART1_RX_BUFFER_ENABLE 0 +#define USART2_RX_BUFFER_ENABLE 0 + +#define RTE_USART0_DMA_TX_CH 0 +#define RTE_USART0_DMA_TX_PERI_SEL (uint8_t) kDmaRequestMux0LPUART0Tx +#define RTE_USART0_DMA_TX_DMAMUX_BASE DMAMUX0 +#define RTE_USART0_DMA_TX_DMA_BASE DMA0 +#define RTE_USART0_DMA_RX_CH 1 +#define RTE_USART0_DMA_RX_PERI_SEL (uint8_t) kDmaRequestMux0LPUART0Rx +#define RTE_USART0_DMA_RX_DMAMUX_BASE DMAMUX0 +#define RTE_USART0_DMA_RX_DMA_BASE DMA0 + +#define RTE_USART1_DMA_TX_CH 0 +#define RTE_USART1_DMA_TX_PERI_SEL (uint8_t) kDmaRequestMux0LPUART1Tx +#define RTE_USART1_DMA_TX_DMAMUX_BASE DMAMUX0 +#define RTE_USART1_DMA_TX_DMA_BASE DMA0 +#define RTE_USART1_DMA_RX_CH 1 +#define RTE_USART1_DMA_RX_PERI_SEL (uint8_t) kDmaRequestMux0LPUART1Rx +#define RTE_USART1_DMA_RX_DMAMUX_BASE DMAMUX0 +#define RTE_USART1_DMA_RX_DMA_BASE DMA0 + +#define RTE_USART2_DMA_TX_CH 0 +#define RTE_USART2_DMA_TX_PERI_SEL (uint8_t) kDmaRequestMux0UART2Tx +#define RTE_USART2_DMA_TX_DMAMUX_BASE DMAMUX0 +#define RTE_USART2_DMA_TX_DMA_BASE DMA0 +#define RTE_USART2_DMA_RX_CH 1 +#define RTE_USART2_DMA_RX_PERI_SEL (uint8_t) kDmaRequestMux0UART2Rx +#define RTE_USART2_DMA_RX_DMAMUX_BASE DMAMUX0 +#define RTE_USART2_DMA_RX_DMA_BASE DMA0 + +/* I2C Select, I2C0 - I2C1. */ +#define RTE_I2C0 0 +#define RTE_I2C0_DMA_EN 0 +#define RTE_I2C1 0 +#define RTE_I2C1_DMA_EN 0 + +/*I2C configuration*/ +#define RTE_I2C0_Master_DMA_BASE DMA0 +#define RTE_I2C0_Master_DMA_CH 0 +#define RTE_I2C0_Master_DMAMUX_BASE DMAMUX0 +#define RTE_I2C0_Master_PERI_SEL kDmaRequestMux0I2C0 + +#define RTE_I2C1_Master_DMA_BASE DMA0 +#define RTE_I2C1_Master_DMA_CH 1 +#define RTE_I2C1_Master_DMAMUX_BASE DMAMUX0 +#define RTE_I2C1_Master_PERI_SEL kDmaRequestMux0I2C1 + +/* SPI select, SPI0 - SPI1. */ +#define RTE_SPI0 0 +#define RTE_SPI0_DMA_EN 0 +#define RTE_SPI1 0 +#define RTE_SPI1_DMA_EN 0 + +/* SPI configuration. */ +#define RTE_SPI0_DMA_TX_CH 0 +#define RTE_SPI0_DMA_TX_PERI_SEL (uint8_t) kDmaRequestMux0SPI0Tx +#define RTE_SPI0_DMA_TX_DMAMUX_BASE DMAMUX0 +#define RTE_SPI0_DMA_TX_DMA_BASE DMA0 +#define RTE_SPI0_DMA_RX_CH 1 +#define RTE_SPI0_DMA_RX_PERI_SEL (uint8_t) kDmaRequestMux0SPI0Rx +#define RTE_SPI0_DMA_RX_DMAMUX_BASE DMAMUX0 +#define RTE_SPI0_DMA_RX_DMA_BASE DMA0 + +#define RTE_SPI1_DMA_TX_CH 2 +#define RTE_SPI1_DMA_TX_PERI_SEL (uint8_t) kDmaRequestMux0SPI1Tx +#define RTE_SPI1_DMA_TX_DMAMUX_BASE DMAMUX0 +#define RTE_SPI1_DMA_TX_DMA_BASE DMA0 +#define RTE_SPI1_DMA_RX_CH 3 +#define RTE_SPI1_DMA_RX_PERI_SEL (uint8_t) kDmaRequestMux0SPI1Rx +#define RTE_SPI1_DMA_RX_DMAMUX_BASE DMAMUX0 +#define RTE_SPI1_DMA_RX_DMA_BASE DMA0 + +#endif /* __RTE_DEVICE_H */ diff --git a/source/hic_hal/freescale/kl27z/hic_init.c b/source/hic_hal/freescale/kl27z/hic_init.c index 42a3ebeedc..1f30f7f26e 100644 --- a/source/hic_hal/freescale/kl27z/hic_init.c +++ b/source/hic_hal/freescale/kl27z/hic_init.c @@ -21,15 +21,50 @@ */ #include "fsl_device_registers.h" +#include "fsl_clock.h" +#include "fsl_port.h" +#include "IO_Config.h" /* Enable all clocks needed for USB to function */ void hic_enable_usb_clocks(void) { /* Set USB clock to 48 MHz */ - MCG->MC |= MCG_MC_HIRCEN_MASK; /* Enable the HIRC clock in the MCG */ - SIM->SCGC4 |= SIM_SCGC4_USBFS_MASK; /* Enable the USB clock */ + MCG->MC |= MCG_MC_HIRCEN_MASK; /* Enable the HIRC clock in the MCG */ + SIM->SCGC4 |= SIM_SCGC4_USBFS_MASK; /* Enable the USB clock */ USB0->CLK_RECOVER_INT_EN |= USB_CLK_RECOVER_IRC_EN_IRC_EN_MASK; - USB0->CLK_RECOVER_CTRL |= USB_CLK_RECOVER_CTRL_CLOCK_RECOVER_EN_MASK; - SIM->SOPT2 |= SIM_SOPT2_USBSRC_MASK; /* MCGPLLCLK used as src */ + USB0->CLK_RECOVER_CTRL |= USB_CLK_RECOVER_CTRL_CLOCK_RECOVER_EN_MASK; + SIM->SOPT2 |= SIM_SOPT2_USBSRC_MASK; /* MCGPLLCLK used as src */ } +void sdk_init(void) { + CLOCK_EnableClock(kCLOCK_PortA); + CLOCK_EnableClock(kCLOCK_PortB); + CLOCK_EnableClock(kCLOCK_PortC); + CLOCK_EnableClock(kCLOCK_PortD); + CLOCK_EnableClock(kCLOCK_PortE); + + NVIC_SetPriority(CMSIS_UART_IRQ, (1UL << __NVIC_PRIO_BITS) - 1UL); +} + +uint32_t LPUART1_GetFreq(void) +{ + CLOCK_SetLpuart1Clock(1); + return CLOCK_GetPeriphClkFreq(); +} + +void LPUART1_InitPins(void) +{ + CLOCK_SetLpuart1Clock(1); + CLOCK_EnableClock(kCLOCK_Lpuart1); + + PORT_SetPinMux(PIN_UART_RX_PORT, PIN_UART_RX_BIT, PIN_UART_RX_MUX_ALT); + PORT_SetPinMux(PIN_UART_TX_PORT, PIN_UART_TX_BIT, PIN_UART_TX_MUX_ALT); +} + +void LPUART1_DeinitPins(void) +{ + PORT_SetPinMux(PIN_UART_RX_PORT, PIN_UART_RX_BIT, kPORT_PinDisabledOrAnalog); + PORT_SetPinMux(PIN_UART_TX_PORT, PIN_UART_TX_BIT, kPORT_PinDisabledOrAnalog); + + CLOCK_DisableClock(kCLOCK_Lpuart1); +} diff --git a/source/hic_hal/freescale/kl27z/uart.c b/source/hic_hal/freescale/kl27z/uart.c deleted file mode 100644 index 080d513792..0000000000 --- a/source/hic_hal/freescale/kl27z/uart.c +++ /dev/null @@ -1,293 +0,0 @@ -/** - * @file uart.c - * @brief - * - * DAPLink Interface Firmware - * Copyright (c) 2009-2016, ARM Limited, All Rights Reserved - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "string.h" - -#include "uart.h" -#include "util.h" -#include "cortex_m.h" -#include "IO_Config.h" -#include "circ_buf.h" -#include "settings.h" // for config_get_overflow_detect -#include "fsl_clock.h" - -#define RX_OVRF_MSG "\n" -#define RX_OVRF_MSG_SIZE (sizeof(RX_OVRF_MSG) - 1) -#define BUFFER_SIZE (512) - -circ_buf_t write_buffer; -uint8_t write_buffer_data[BUFFER_SIZE]; -circ_buf_t read_buffer; -uint8_t read_buffer_data[BUFFER_SIZE]; - -void clear_buffers(void) -{ - util_assert(!(UART->CTRL & LPUART_CTRL_TIE_MASK)); - circ_buf_init(&write_buffer, write_buffer_data, sizeof(write_buffer_data)); - circ_buf_init(&read_buffer, read_buffer_data, sizeof(read_buffer_data)); -} - -int32_t uart_initialize(void) -{ - NVIC_DisableIRQ(UART_RX_TX_IRQn); - - // enable clk port - if (UART_PORT == PORTA) { - SIM->SCGC5 |= SIM_SCGC5_PORTA_MASK; - } - - if (UART_PORT == PORTC) { - SIM->SCGC5 |= SIM_SCGC5_PORTC_MASK; - } - - if (UART_PORT == PORTD) { - SIM->SCGC5 |= SIM_SCGC5_PORTD_MASK; - } - - if (UART_PORT == PORTE) { - SIM->SCGC5 |= SIM_SCGC5_PORTE_MASK; - } - - // enable clk uart - if (0 == UART_NUM) { - CLOCK_SetLpuart0Clock(1); - CLOCK_EnableClock(kCLOCK_Lpuart0); - } - - if (1 == UART_NUM) { - CLOCK_SetLpuart1Clock(1); - CLOCK_EnableClock(kCLOCK_Lpuart1); - } - - - // transmitter and receiver disabled - UART->CTRL &= ~(LPUART_CTRL_RE_MASK | LPUART_CTRL_TE_MASK); - // disable interrupt - UART->CTRL &= ~(LPUART_CTRL_RIE_MASK | LPUART_CTRL_TIE_MASK); - - clear_buffers(); - - // alternate setting - UART_PORT->PCR[PIN_UART_RX_BIT] = PORT_PCR_MUX(PIN_UART_RX_MUX_ALT); - UART_PORT->PCR[PIN_UART_TX_BIT] = PORT_PCR_MUX(PIN_UART_TX_MUX_ALT); - // transmitter and receiver enabled - UART->CTRL |= LPUART_CTRL_RE_MASK | LPUART_CTRL_TE_MASK; - // Enable receiver interrupt and RX Overrun interrupt - UART->CTRL |= LPUART_CTRL_RIE_MASK | LPUART_CTRL_ORIE_MASK; - - NVIC_SetPriority(UART_RX_TX_IRQn, (1UL << __NVIC_PRIO_BITS) - 1UL); - NVIC_ClearPendingIRQ(UART_RX_TX_IRQn); - NVIC_EnableIRQ(UART_RX_TX_IRQn); - return 1; -} - -int32_t uart_uninitialize(void) -{ - // transmitter and receiver disabled - UART->CTRL &= ~(LPUART_CTRL_RE_MASK | LPUART_CTRL_TE_MASK); - // disable interrupt - UART->CTRL &= ~(LPUART_CTRL_RIE_MASK | LPUART_CTRL_TIE_MASK | LPUART_CTRL_ORIE_MASK); - clear_buffers(); - - // disable uart clock - if (0 == UART_NUM) { - CLOCK_DisableClock(kCLOCK_Lpuart0); - } - - if (1 == UART_NUM) { - CLOCK_DisableClock(kCLOCK_Lpuart1); - } - return 1; -} - -int32_t uart_reset(void) -{ - // disable interrupt - NVIC_DisableIRQ(UART_RX_TX_IRQn); - // disable TIE interrupt - UART->CTRL &= ~(LPUART_CTRL_TIE_MASK); - clear_buffers(); - // enable interrupt - NVIC_EnableIRQ(UART_RX_TX_IRQn); - return 1; -} - -int32_t uart_set_configuration(UART_Configuration *config) -{ - uint8_t data_bits = 8; - uint8_t parity_enable = 0; - uint8_t parity_type = 0; - uint32_t dll; - // disable interrupt - NVIC_DisableIRQ(UART_RX_TX_IRQn); - UART->CTRL &= ~(LPUART_CTRL_RIE_MASK | LPUART_CTRL_TIE_MASK); - // Disable receiver and transmitter while updating - UART->CTRL &= ~(LPUART_CTRL_RE_MASK | LPUART_CTRL_TE_MASK); - clear_buffers(); - - // set data bits, stop bits, parity - if ((config->DataBits < 8) || (config->DataBits > 9)) { - data_bits = 8; - } - - data_bits -= 8; - - if (config->Parity == 1) { - parity_enable = 1; - parity_type = 1; - data_bits++; - } else if (config->Parity == 2) { - parity_enable = 1; - parity_type = 0; - data_bits++; - } - - // does not support 10 bit data comm - if (data_bits == 2) { - data_bits = 0; - parity_enable = 0; - parity_type = 0; - } - - // data bits, parity and parity mode - UART->CTRL = data_bits << LPUART_CTRL_M_SHIFT | - parity_enable << LPUART_CTRL_PE_SHIFT | - parity_type << LPUART_CTRL_PT_SHIFT; - dll = SystemCoreClock / (16 * config->Baudrate); - - // set baudrate - UART->BAUD = ((UART->BAUD & ~LPUART_BAUD_SBR_MASK) | LPUART_BAUD_SBR(dll)); - // Enable transmitter and receiver - UART->CTRL |= LPUART_CTRL_RE_MASK | LPUART_CTRL_TE_MASK; - // Enable UART interrupt - NVIC_ClearPendingIRQ(UART_RX_TX_IRQn); - NVIC_EnableIRQ(UART_RX_TX_IRQn); - UART->CTRL |= LPUART_CTRL_RIE_MASK | LPUART_CTRL_ORIE_MASK; - return 1; -} - -int32_t uart_get_configuration(UART_Configuration *config) -{ - return 1; -} - -int32_t uart_write_free(void) -{ - return circ_buf_count_free(&write_buffer); -} - -int32_t uart_write_data(uint8_t *data, uint16_t size) -{ - cortex_int_state_t state; - uint32_t cnt; - - cnt = circ_buf_write(&write_buffer, data, size); - - // Atomically enable TX - state = cortex_int_get_and_disable(); - if (circ_buf_count_used(&write_buffer)) { - UART->CTRL |= LPUART_CTRL_TIE_MASK; - } - cortex_int_restore(state); - - return cnt; -} - -int32_t uart_read_data(uint8_t *data, uint16_t size) -{ - return circ_buf_read(&read_buffer, data, size); -} - -void uart_enable_flow_control(bool enabled) -{ - // Flow control not implemented for this platform -} - -void UART_RX_TX_IRQHandler(void) -{ - uint32_t s1; - volatile uint8_t errorData; - // read interrupt status - s1 = UART->STAT; - // mask off interrupts that are not enabled - if (!(UART->CTRL & LPUART_CTRL_RIE_MASK)) { - s1 &= ~LPUART_STAT_RDRF_MASK; - } - if (!(UART->CTRL & LPUART_CTRL_TIE_MASK)) { - s1 &= ~LPUART_STAT_TDRE_MASK; - } - - // If RX overrun - if (s1 & LPUART_STAT_OR_MASK) - { - // Clear overrun flag, otherwise the RX does not work. - UART->STAT = ((UART->STAT & 0x3FE00000U) | LPUART_STAT_OR_MASK); - - if (config_get_overflow_detect()) { - if (RX_OVRF_MSG_SIZE <= circ_buf_count_free(&read_buffer)) { - circ_buf_write(&read_buffer, (uint8_t*)RX_OVRF_MSG, RX_OVRF_MSG_SIZE); - } - } - } - - // handle character to transmit - if (s1 & LPUART_STAT_TDRE_MASK) { - // Assert that there is data in the buffer - util_assert(circ_buf_count_used(&write_buffer) > 0); - // Send out data - UART->DATA = circ_buf_pop(&write_buffer); - // Turn off the transmitter if that was the last byte - if (circ_buf_count_used(&write_buffer) == 0) { - // disable TIE interrupt - UART->CTRL &= ~(LPUART_CTRL_TIE_MASK); - // Clear any pending irq that could be triggered before disabling TIE - NVIC_ClearPendingIRQ(UART_RX_TX_IRQn); - } - } - - // handle received character - if (s1 & LPUART_STAT_RDRF_MASK) { - if ((s1 & LPUART_STAT_NF_MASK) || (s1 & LPUART_STAT_FE_MASK)) { - errorData = UART->DATA; - // Clear frame error or Noise flags - UART->STAT = ((UART->STAT & 0x3FE00000U) | LPUART_STAT_NF_MASK | LPUART_STAT_FE_MASK); - } else { - uint32_t free; - uint8_t data; - - data = UART->DATA; - free = circ_buf_count_free(&read_buffer); - if (free > RX_OVRF_MSG_SIZE) { - circ_buf_push(&read_buffer, data); - } else if (config_get_overflow_detect()) { - if (RX_OVRF_MSG_SIZE == free) { - circ_buf_write(&read_buffer, (uint8_t*)RX_OVRF_MSG, RX_OVRF_MSG_SIZE); - } else { - // Drop newest - } - } else { - // Drop oldest - circ_buf_pop(&read_buffer); - circ_buf_push(&read_buffer, data); - } - } - } -}