diff --git a/records/hic_hal/kl27z.yaml b/records/hic_hal/kl27z.yaml index 0407345b01..c4042104ca 100644 --- a/records/hic_hal/kl27z.yaml +++ b/records/hic_hal/kl27z.yaml @@ -22,6 +22,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/records/hic_hal/lpc55s26.yaml b/records/hic_hal/lpc55s26.yaml index 56191ee926..7bfeeb68e8 100644 --- a/records/hic_hal/lpc55s26.yaml +++ b/records/hic_hal/lpc55s26.yaml @@ -17,6 +17,7 @@ common: - source/hic_hal/nxp/lpc55xx - source/hic_hal/nxp/lpc55xx/drivers - source/hic_hal/nxp/lpc55xx/LPC55S26 + - source/hic_hal/cmsis-driver/uart tool_specific: gcc_arm: diff --git a/records/hic_hal/lpc55s69.yaml b/records/hic_hal/lpc55s69.yaml index d849bf67ba..8fb8fe2cc8 100644 --- a/records/hic_hal/lpc55s69.yaml +++ b/records/hic_hal/lpc55s69.yaml @@ -17,6 +17,7 @@ common: - source/hic_hal/nxp/lpc55xx - source/hic_hal/nxp/lpc55xx/drivers - source/hic_hal/nxp/lpc55xx/LPC55S69 + - source/hic_hal/cmsis-driver/uart tool_specific: uvision: diff --git a/records/hic_hal/nrf52820.yaml b/records/hic_hal/nrf52820.yaml index a91ff3801c..3043cd6412 100644 --- a/records/hic_hal/nrf52820.yaml +++ b/records/hic_hal/nrf52820.yaml @@ -22,6 +22,7 @@ common: - source/hic_hal/nordic/nrf52820 - source/hic_hal/nordic/nrf52820/cmsis - source/hic_hal/nordic/nrf52820/nrfx/drivers + - source/hic_hal/cmsis-driver/uart tool_specific: uvision: diff --git a/records/hic_hal/stm32f103xb.yaml b/records/hic_hal/stm32f103xb.yaml index 3b7e51ef88..638fcd5870 100644 --- a/records/hic_hal/stm32f103xb.yaml +++ b/records/hic_hal/stm32f103xb.yaml @@ -7,6 +7,7 @@ common: - INTERFACE_STM32F103XB - USE_HAL_DRIVER - STM32F103xB + - STM32F10X_MD - DAPLINK_HIC_ID=0x97969908 # DAPLINK_HIC_ID_STM32F103XB - __packed=__packed # Prevent redefinition of __packed with ARMCC - DAPLINK_NO_ASSERT_FILENAMES @@ -21,6 +22,7 @@ common: - source/hic_hal/stm32/stm32f103xb - source/hic_hal/stm32/stm32f103xb/cmsis - source/hic_hal/stm32/stm32f103xb/STM32F1xx_HAL_Driver/Src + - source/hic_hal/cmsis-driver/uart/uart.c tool_specific: uvision: diff --git a/source/board/microbitv2/i2c_commands.c b/source/board/microbitv2/i2c_commands.c index 58700633a3..50d8ae14d1 100644 --- a/source/board/microbitv2/i2c_commands.c +++ b/source/board/microbitv2/i2c_commands.c @@ -29,6 +29,7 @@ #include "storage.h" #include "gpio_extra.h" #include "microbitv2.h" +#include "util.h" extern uint16_t board_id_hex; diff --git a/source/board/microbitv2/kl27z/IO_Config_Override.h b/source/board/microbitv2/kl27z/IO_Config_Override.h index 7e8599aaa5..8bcc08521d 100644 --- a/source/board/microbitv2/kl27z/IO_Config_Override.h +++ b/source/board/microbitv2/kl27z/IO_Config_Override.h @@ -135,21 +135,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<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 */ @@ -254,8 +254,8 @@ static void power_post_switch_hook(smc_power_state_t originPowerState, app_power 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(); // TODO: Check if this is necessary, when we have time to test. This has always been in the V2 code. diff --git a/source/board/override_nm180410/IO_Config_Override.h b/source/board/override_nm180410/IO_Config_Override.h index de3d90495f..155ad36ea7 100644 --- a/source/board/override_nm180410/IO_Config_Override.h +++ b/source/board/override_nm180410/IO_Config_Override.h @@ -106,6 +106,11 @@ COMPILER_ASSERT((DAPLINK_HIC_ID == DAPLINK_HIC_ID_LPC55XX) || #define PIN_UART_TX (30U) #define PIN_UART_TX_MASK (1U << PIN_UART_TX) +// cmsis-driver/uart/uart.c configuration +#include "fsl_usart_cmsis.h" +#define CMSIS_UART_INSTANCE (Driver_USART0) +#define CMSIS_UART_IRQ (FLEXCOMM0_IRQn) + // LED_A: LED_CDC PIO1_13 // LED_B: LED_MSC PIO1_20 // LED_C: LED_WEBHID PIO1_9 diff --git a/source/hic_hal/nxp/lpc55xx/uart.c b/source/hic_hal/cmsis-driver/uart/uart.c similarity index 79% rename from source/hic_hal/nxp/lpc55xx/uart.c rename to source/hic_hal/cmsis-driver/uart/uart.c index 77a1914e2c..540fa7cd8d 100644 --- a/source/hic_hal/nxp/lpc55xx/uart.c +++ b/source/hic_hal/cmsis-driver/uart/uart.c @@ -1,6 +1,6 @@ /** * @file uart.c - * @brief + * @brief UART Function for HIC using CMSIS-Driver * * DAPLink Interface Firmware * Copyright (c) 2020 Arm Limited, All Rights Reserved @@ -20,18 +20,13 @@ */ #include "string.h" -#include "fsl_device_registers.h" -#include "fsl_usart_cmsis.h" #include "uart.h" #include "util.h" #include "cortex_m.h" #include "circ_buf.h" #include "settings.h" // for config_get_overflow_detect - -#define USART_INSTANCE (Driver_USART0) -#define USART_IRQ (FLEXCOMM0_IRQn) - -extern uint32_t SystemCoreClock; +#include "Driver_USART.h" +#include "IO_Config.h" static void clear_buffers(void); @@ -43,6 +38,9 @@ circ_buf_t write_buffer; uint8_t write_buffer_data[BUFFER_SIZE]; circ_buf_t read_buffer; uint8_t read_buffer_data[BUFFER_SIZE]; +uint16_t cur_line_state; +uint32_t cur_control; +uint32_t cur_baud; struct { // Number of bytes pending to be transferred. This is 0 if there is no @@ -64,18 +62,21 @@ int32_t uart_initialize(void) { clear_buffers(); cb_buf.tx_size = 0; - USART_INSTANCE.Initialize(uart_handler); - USART_INSTANCE.PowerControl(ARM_POWER_FULL); + CMSIS_UART_INSTANCE.Initialize(uart_handler); + CMSIS_UART_INSTANCE.PowerControl(ARM_POWER_FULL); + cur_line_state = 0; + cur_control = 0; + cur_baud = 0; return 1; } int32_t uart_uninitialize(void) { - USART_INSTANCE.Control(ARM_USART_CONTROL_RX, 0); - USART_INSTANCE.Control(ARM_USART_ABORT_RECEIVE, 0U); - USART_INSTANCE.PowerControl(ARM_POWER_OFF); - USART_INSTANCE.Uninitialize(); + CMSIS_UART_INSTANCE.Control(ARM_USART_CONTROL_RX, 0); + CMSIS_UART_INSTANCE.Control(ARM_USART_ABORT_RECEIVE, 0U); + CMSIS_UART_INSTANCE.PowerControl(ARM_POWER_OFF); + CMSIS_UART_INSTANCE.Uninitialize(); clear_buffers(); cb_buf.tx_size = 0; @@ -85,14 +86,14 @@ int32_t uart_uninitialize(void) int32_t uart_reset(void) { // disable interrupt - NVIC_DisableIRQ(USART_IRQ); + NVIC_DisableIRQ(CMSIS_UART_IRQ); clear_buffers(); if (cb_buf.tx_size != 0) { - USART_INSTANCE.Control(ARM_USART_ABORT_SEND, 0U); + CMSIS_UART_INSTANCE.Control(ARM_USART_ABORT_SEND, 0U); cb_buf.tx_size = 0; } // enable interrupt - NVIC_EnableIRQ(USART_IRQ); + NVIC_EnableIRQ(CMSIS_UART_IRQ); return 1; } @@ -161,27 +162,35 @@ int32_t uart_set_configuration(UART_Configuration *config) break; } - NVIC_DisableIRQ(USART_IRQ); + if ((control == cur_control) && (config->Baudrate == cur_baud)) { + return 1; + } + cur_control = control; + cur_baud = config->Baudrate; + + NVIC_DisableIRQ(CMSIS_UART_IRQ); clear_buffers(); if (cb_buf.tx_size != 0) { - USART_INSTANCE.Control(ARM_USART_ABORT_SEND, 0U); + CMSIS_UART_INSTANCE.Control(ARM_USART_ABORT_SEND, 0U); cb_buf.tx_size = 0; } // If there was no Receive() call in progress aborting it is harmless. - USART_INSTANCE.Control(ARM_USART_CONTROL_RX, 0U); - USART_INSTANCE.Control(ARM_USART_ABORT_RECEIVE, 0U); + CMSIS_UART_INSTANCE.Control(ARM_USART_CONTROL_RX, 0U); + CMSIS_UART_INSTANCE.Control(ARM_USART_ABORT_RECEIVE, 0U); - uint32_t r = USART_INSTANCE.Control(control, config->Baudrate); + uint32_t r = CMSIS_UART_INSTANCE.Control(control, config->Baudrate); if (r != ARM_DRIVER_OK) { return 0; } - USART_INSTANCE.Control(ARM_USART_CONTROL_TX, 1); - USART_INSTANCE.Control(ARM_USART_CONTROL_RX, 1); - USART_INSTANCE.Receive(&(cb_buf.rx), 1); + CMSIS_UART_INSTANCE.Control(ARM_USART_CONTROL_TX, 1); + CMSIS_UART_INSTANCE.Control(ARM_USART_CONTROL_RX, 1); + CMSIS_UART_INSTANCE.Receive(&(cb_buf.rx), 1); + + NVIC_ClearPendingIRQ(CMSIS_UART_IRQ); + NVIC_EnableIRQ(CMSIS_UART_IRQ); - NVIC_ClearPendingIRQ(USART_IRQ); - NVIC_EnableIRQ(USART_IRQ); + uart_reset(); return 1; } @@ -193,6 +202,10 @@ int32_t uart_get_configuration(UART_Configuration *config) void uart_set_control_line_state(uint16_t ctrl_bmp) { + if (ctrl_bmp != cur_line_state) { + uart_reset(); + cur_line_state = ctrl_bmp; + } } int32_t uart_write_free(void) @@ -215,7 +228,7 @@ static void uart_start_tx_transfer() { } cb_buf.tx_size = tx_size; if (tx_size) { - USART_INSTANCE.Send(buf, tx_size); + CMSIS_UART_INSTANCE.Send(buf, tx_size); } } @@ -254,7 +267,7 @@ void uart_handler(uint32_t event) { } else { // Drop character } - USART_INSTANCE.Receive(&(cb_buf.rx), 1); + CMSIS_UART_INSTANCE.Receive(&(cb_buf.rx), 1); } if (event & ARM_USART_EVENT_SEND_COMPLETE) { 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 b109d182fc..0000000000 --- a/source/hic_hal/freescale/kl27z/uart.c +++ /dev/null @@ -1,297 +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; -} - -void uart_set_control_line_state(uint16_t ctrl_bmp) -{ -} - -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); - } - } - } -} diff --git a/source/hic_hal/nordic/nrf52820/IO_Config.h b/source/hic_hal/nordic/nrf52820/IO_Config.h index 817b3bc407..d71ff52d18 100644 --- a/source/hic_hal/nordic/nrf52820/IO_Config.h +++ b/source/hic_hal/nordic/nrf52820/IO_Config.h @@ -85,6 +85,12 @@ extern uint32_t i2c_sda_pin; #define UART_TX_PIN uart_tx_pin #define UART_RX_PIN uart_rx_pin +// cmsis-driver/uart/uart.c configuration +#include "Driver_USART.h" +extern ARM_DRIVER_USART Driver_USART0; +#define CMSIS_UART_INSTANCE (Driver_USART0) +#define CMSIS_UART_IRQ (UARTE0_UART0_IRQn) + // I2C #define I2C_SCL_PIN i2c_scl_pin #define I2C_SDA_PIN i2c_sda_pin diff --git a/source/hic_hal/nordic/nrf52820/uart.c b/source/hic_hal/nordic/nrf52820/uart.c deleted file mode 100644 index 5bac440cd6..0000000000 --- a/source/hic_hal/nordic/nrf52820/uart.c +++ /dev/null @@ -1,262 +0,0 @@ -/** - * @file uart.c - * @brief UART Function for nrf52820 HIC - * - * DAPLink Interface Firmware - * Copyright (c) 2021, 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 "Driver_USART.h" -#include "uart.h" -#include "util.h" -#include "cortex_m.h" -#include "circ_buf.h" -#include "settings.h" // for config_get_overflow_detect - -#define USART_INSTANCE (Driver_USART0) -#define USART_IRQ (UARTE0_UART0_IRQn) - -extern ARM_DRIVER_USART USART_INSTANCE; - -static void clear_buffers(void); - -#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]; -uint16_t cur_line_state; -uint32_t cur_control; -uint32_t cur_baud; - -struct { - // Number of bytes pending to be transferred. This is 0 if there is no - // ongoing transfer and the uart_handler processed the last transfer. - volatile uint32_t tx_size; - - uint8_t rx; - uint8_t tx; -} cb_buf; - -void uart_handler(uint32_t event); - -void clear_buffers(void) -{ - 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) -{ - clear_buffers(); - cb_buf.tx_size = 0; - USART_INSTANCE.Initialize(uart_handler); - USART_INSTANCE.PowerControl(ARM_POWER_FULL); - cur_line_state = 0; - cur_control = 0; - cur_baud = 0; - - return 1; -} - -int32_t uart_uninitialize(void) -{ - USART_INSTANCE.Control(ARM_USART_CONTROL_RX, 0); - USART_INSTANCE.Control(ARM_USART_ABORT_RECEIVE, 0U); - USART_INSTANCE.PowerControl(ARM_POWER_OFF); - USART_INSTANCE.Uninitialize(); - clear_buffers(); - cb_buf.tx_size = 0; - - return 1; -} - -int32_t uart_reset(void) -{ - // disable interrupt - NVIC_DisableIRQ(USART_IRQ); - clear_buffers(); - // enable interrupt - NVIC_EnableIRQ(USART_IRQ); - - return 1; -} - -int32_t uart_set_configuration(UART_Configuration *config) -{ - uint32_t control = ARM_USART_MODE_ASYNCHRONOUS; - - switch (config->DataBits) { - case UART_DATA_BITS_5: - control |= ARM_USART_DATA_BITS_5; - break; - - case UART_DATA_BITS_6: - control |= ARM_USART_DATA_BITS_6; - break; - - case UART_DATA_BITS_7: - control |= ARM_USART_DATA_BITS_7; - break; - - case UART_DATA_BITS_8: /* fallthrough */ - default: - control |= ARM_USART_DATA_BITS_8; - break; - } - - switch (config->Parity) { - case UART_PARITY_EVEN: - control |= ARM_USART_PARITY_EVEN; - break; - - case UART_PARITY_ODD: - control |= ARM_USART_PARITY_ODD; - break; - - case UART_PARITY_NONE: /* fallthrough */ - default: - control |= ARM_USART_PARITY_NONE; - break; - } - - switch (config->StopBits) { - case UART_STOP_BITS_1: /* fallthrough */ - default: - control |= ARM_USART_STOP_BITS_1; - break; - - case UART_STOP_BITS_1_5: - control |= ARM_USART_STOP_BITS_1_5; - break; - - case UART_STOP_BITS_2: - control |= ARM_USART_STOP_BITS_2; - break; - } - - switch (config->FlowControl) { - case UART_FLOW_CONTROL_NONE: /* fallthrough */ - default: - control |= ARM_USART_FLOW_CONTROL_NONE; - break; - - case UART_FLOW_CONTROL_RTS_CTS: - control |= ARM_USART_FLOW_CONTROL_RTS_CTS; - break; - } - - if ((control == cur_control) && (config->Baudrate == cur_baud)) { - return 1; - } - cur_control = control; - cur_baud = config->Baudrate; - - NVIC_DisableIRQ(USART_IRQ); - clear_buffers(); - - // If there was no Receive() call in progress aborting it is harmless. - USART_INSTANCE.Control(ARM_USART_CONTROL_RX, 0U); - USART_INSTANCE.Control(ARM_USART_ABORT_RECEIVE, 0U); - - uint32_t r = USART_INSTANCE.Control(control, config->Baudrate); - if (r != ARM_DRIVER_OK) { - return 0; - } - USART_INSTANCE.Control(ARM_USART_CONTROL_TX, 1); - USART_INSTANCE.Control(ARM_USART_CONTROL_RX, 1); - USART_INSTANCE.Receive(&(cb_buf.rx), 1); - - NVIC_ClearPendingIRQ(USART_IRQ); - NVIC_EnableIRQ(USART_IRQ); - - uart_reset(); - - return 1; -} - -int32_t uart_get_configuration(UART_Configuration *config) -{ - return 1; -} - -void uart_set_control_line_state(uint16_t ctrl_bmp) -{ - if (ctrl_bmp != cur_line_state) { - uart_reset(); - cur_line_state = ctrl_bmp; - } -} - -int32_t uart_write_free(void) -{ - return circ_buf_count_free(&write_buffer); -} - -int32_t uart_write_data(uint8_t *data, uint16_t size) -{ - if (size == 0) { - return 0; - } - - // Disable interrupts to prevent the uart_handler from modifying the - // circular buffer at the same time. - NVIC_DisableIRQ(USART_IRQ); - uint32_t cnt = circ_buf_write(&write_buffer, data, size); - if (cb_buf.tx_size == 0 && circ_buf_count_used(&write_buffer) > 0) { - // There's no pending transfer, so we need to start the process. - cb_buf.tx = circ_buf_pop(&write_buffer); - USART_INSTANCE.Send(&(cb_buf.tx), 1); - cb_buf.tx_size = 1; - } - NVIC_EnableIRQ(USART_IRQ); - - return cnt; -} - -int32_t uart_read_data(uint8_t *data, uint16_t size) -{ - return circ_buf_read(&read_buffer, data, size); -} - -void uart_handler(uint32_t event) { - if (event & ARM_USART_EVENT_RECEIVE_COMPLETE) { - uint32_t free = circ_buf_count_free(&read_buffer); - if (free > RX_OVRF_MSG_SIZE) { - circ_buf_push(&read_buffer, cb_buf.rx); - } else if ((RX_OVRF_MSG_SIZE == free) && config_get_overflow_detect()) { - circ_buf_write(&read_buffer, (uint8_t*)RX_OVRF_MSG, RX_OVRF_MSG_SIZE); - } else { - // Drop character - } - USART_INSTANCE.Receive(&(cb_buf.rx), 1); - } - - if (event & ARM_USART_EVENT_SEND_COMPLETE) { - if (circ_buf_count_used(&write_buffer) > 0) { - cb_buf.tx = circ_buf_pop(&write_buffer); - USART_INSTANCE.Send(&(cb_buf.tx), 1); - } else { - // Signals that next call to uart_write_data() should start a - // transfer. - cb_buf.tx_size = 0; - } - } -} diff --git a/source/hic_hal/nxp/lpc55xx/IO_Config.h b/source/hic_hal/nxp/lpc55xx/IO_Config.h index aa707d1518..335a0ac686 100644 --- a/source/hic_hal/nxp/lpc55xx/IO_Config.h +++ b/source/hic_hal/nxp/lpc55xx/IO_Config.h @@ -116,6 +116,11 @@ COMPILER_ASSERT((DAPLINK_HIC_ID == DAPLINK_HIC_ID_LPC55XX) || #define PIN_UART_TX (25U) #define PIN_UART_TX_MASK (1U << PIN_UART_TX) +// cmsis-driver/uart/uart.c configuration +#include "fsl_usart_cmsis.h" +#define CMSIS_UART_INSTANCE (Driver_USART0) +#define CMSIS_UART_IRQ (FLEXCOMM0_IRQn) + // Debug Unit LEDs diff --git a/source/hic_hal/stm32/stm32f103xb/IO_Config.h b/source/hic_hal/stm32/stm32f103xb/IO_Config.h index de9a4667e4..d55b019ec6 100644 --- a/source/hic_hal/stm32/stm32f103xb/IO_Config.h +++ b/source/hic_hal/stm32/stm32f103xb/IO_Config.h @@ -82,5 +82,9 @@ COMPILER_ASSERT(DAPLINK_HIC_ID == DAPLINK_HIC_ID_STM32F103XB); #define PIN_MSC_LED GPIO_PIN_9 #define PIN_MSC_LED_Bit 9 +#include "Driver_USART.h" +extern ARM_DRIVER_USART Driver_USART2; +#define CMSIS_UART_INSTANCE (Driver_USART2) +#define CMSIS_UART_IRQ (USART2_IRQn) #endif diff --git a/source/hic_hal/stm32/stm32f103xb/RTE_Device.h b/source/hic_hal/stm32/stm32f103xb/RTE_Device.h new file mode 100644 index 0000000000..8ef7f6e9ff --- /dev/null +++ b/source/hic_hal/stm32/stm32f103xb/RTE_Device.h @@ -0,0 +1,407 @@ +/* ----------------------------------------------------------------------------- + * Copyright (c) 2013-2016 Arm Limited (or its affiliates). 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 + * + * 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. + * + * + * $Date: 09. September 2016 + * $Revision: V1.1.2 + * + * Project: RTE Device Configuration for STMicroelectronics STM32F1xx + * + * -------------------------------------------------------------------------- */ + +//-------- <<< Use Configuration Wizard in Context Menu >>> -------------------- + +#ifndef __RTE_DEVICE_H +#define __RTE_DEVICE_H + + +#define GPIO_PORT(num) \ + ((num == 0) ? GPIOA : \ + (num == 1) ? GPIOB : \ + (num == 2) ? GPIOC : \ + (num == 3) ? GPIOD : \ + (num == 4) ? GPIOE : \ + (num == 5) ? GPIOF : \ + (num == 6) ? GPIOG : \ + NULL) + + +// Clock Configuration +// High-speed Internal Clock <1-999999999> +#define RTE_HSI 8000000 +// High-speed External Clock <1-999999999> +#define RTE_HSE 25000000 +// System Clock <1-999999999> +#define RTE_SYSCLK 72000000 +// HCLK Clock <1-999999999> +#define RTE_HCLK 72000000 +// APB1 Clock <1-999999999> +#define RTE_PCLK1 36000000 +// APB2 Clock <1-999999999> +#define RTE_PCLK2 72000000 +// ADC Clock <1-999999999> +#define RTE_ADCCLK 36000000 +// USB Clock +#define RTE_USBCLK 48000000 +// + + +// USART1 (Universal synchronous asynchronous receiver transmitter) +// Configuration settings for Driver_USART1 in component ::CMSIS Driver:USART +#define RTE_USART1 0 + +// USART1_TX Pin <0=>Not Used <1=>PA9 +#define RTE_USART1_TX_PORT_ID_DEF 0 +#if (RTE_USART1_TX_PORT_ID_DEF == 0) +#define RTE_USART1_TX_DEF 0 +#elif (RTE_USART1_TX_PORT_ID_DEF == 1) +#define RTE_USART1_TX_DEF 1 +#define RTE_USART1_TX_PORT_DEF GPIOA +#define RTE_USART1_TX_BIT_DEF 9 +#else +#error "Invalid USART1_TX Pin Configuration!" +#endif + +// USART1_RX Pin <0=>Not Used <1=>PA10 +#define RTE_USART1_RX_PORT_ID_DEF 0 +#if (RTE_USART1_RX_PORT_ID_DEF == 0) +#define RTE_USART1_RX_DEF 0 +#elif (RTE_USART1_RX_PORT_ID_DEF == 1) +#define RTE_USART1_RX_DEF 1 +#define RTE_USART1_RX_PORT_DEF GPIOA +#define RTE_USART1_RX_BIT_DEF 10 +#else +#error "Invalid USART1_RX Pin Configuration!" +#endif + +// USART1_CK Pin <0=>Not Used <1=>PA8 +#define RTE_USART1_CK_PORT_ID_DEF 0 +#if (RTE_USART1_CK_PORT_ID_DEF == 0) +#define RTE_USART1_CK 0 +#elif (RTE_USART1_CK_PORT_ID_DEF == 1) +#define RTE_USART1_CK 1 +#define RTE_USART1_CK_PORT_DEF GPIOA +#define RTE_USART1_CK_BIT_DEF 8 +#else +#error "Invalid USART1_CK Pin Configuration!" +#endif + +// USART1_CTS Pin <0=>Not Used <1=>PA11 +#define RTE_USART1_CTS_PORT_ID_DEF 0 +#if (RTE_USART1_CTS_PORT_ID_DEF == 0) +#define RTE_USART1_CTS 0 +#elif (RTE_USART1_CTS_PORT_ID_DEF == 1) +#define RTE_USART1_CTS 1 +#define RTE_USART1_CTS_PORT_DEF GPIOA +#define RTE_USART1_CTS_BIT_DEF 11 +#else +#error "Invalid USART1_CTS Pin Configuration!" +#endif + +// USART1_RTS Pin <0=>Not Used <1=>PA12 +#define RTE_USART1_RTS_PORT_ID_DEF 0 +#if (RTE_USART1_RTS_PORT_ID_DEF == 0) +#define RTE_USART1_RTS 0 +#elif (RTE_USART1_RTS_PORT_ID_DEF == 1) +#define RTE_USART1_RTS 1 +#define RTE_USART1_RTS_PORT_DEF GPIOA +#define RTE_USART1_RTS_BIT_DEF 12 +#else +#error "Invalid USART1_RTS Pin Configuration!" +#endif + +// USART1 Pin Remap +// Enable USART1 Pin Remapping +#define RTE_USART1_REMAP_FULL 0 + +// USART1_TX Pin <0=>Not Used <1=>PB6 +#define RTE_USART1_TX_PORT_ID_FULL 0 +#if (RTE_USART1_TX_PORT_ID_FULL == 0) +#define RTE_USART1_TX_FULL 0 +#elif (RTE_USART1_TX_PORT_ID_FULL == 1) +#define RTE_USART1_TX_FULL 1 +#define RTE_USART1_TX_PORT_FULL GPIOB +#define RTE_USART1_TX_BIT_FULL 6 +#else +#error "Invalid USART1_TX Pin Configuration!" +#endif + +// USART1_RX Pin <0=>Not Used <1=>PB7 +#define RTE_USART1_RX_PORT_ID_FULL 0 +#if (RTE_USART1_RX_PORT_ID_FULL == 0) +#define RTE_USART1_RX_FULL 0 +#elif (RTE_USART1_RX_PORT_ID_FULL == 1) +#define RTE_USART1_RX_FULL 1 +#define RTE_USART1_RX_PORT_FULL GPIOB +#define RTE_USART1_RX_BIT_FULL 7 +#else +#error "Invalid USART1_RX Pin Configuration!" +#endif +// + +#if (RTE_USART1_REMAP_FULL) +#define RTE_USART1_AF_REMAP AFIO_USART1_REMAP +#define RTE_USART1_TX RTE_USART1_TX_FULL +#define RTE_USART1_TX_PORT RTE_USART1_TX_PORT_FULL +#define RTE_USART1_TX_BIT RTE_USART1_TX_BIT_FULL +#define RTE_USART1_RX RTE_USART1_RX_FULL +#define RTE_USART1_RX_PORT RTE_USART1_RX_PORT_FULL +#define RTE_USART1_RX_BIT RTE_USART1_RX_BIT_FULL +#define RTE_USART1_CK_PORT RTE_USART1_CK_PORT_DEF +#define RTE_USART1_CK_BIT RTE_USART1_CK_BIT_DEF +#define RTE_USART1_CTS_PORT RTE_USART1_CTS_PORT_DEF +#define RTE_USART1_CTS_BIT RTE_USART1_CTS_BIT_DEF +#define RTE_USART1_RTS_PORT RTE_USART1_RTS_PORT_DEF +#define RTE_USART1_RTS_BIT RTE_USART1_RTS_BIT_DEF +#else +#define RTE_USART1_AF_REMAP AFIO_USART1_NO_REMAP +#define RTE_USART1_TX RTE_USART1_TX_DEF +#define RTE_USART1_TX_PORT RTE_USART1_TX_PORT_DEF +#define RTE_USART1_TX_BIT RTE_USART1_TX_BIT_DEF +#define RTE_USART1_RX RTE_USART1_RX_DEF +#define RTE_USART1_RX_PORT RTE_USART1_RX_PORT_DEF +#define RTE_USART1_RX_BIT RTE_USART1_RX_BIT_DEF +#define RTE_USART1_CK_PORT RTE_USART1_CK_PORT_DEF +#define RTE_USART1_CK_BIT RTE_USART1_CK_BIT_DEF +#define RTE_USART1_CTS_PORT RTE_USART1_CTS_PORT_DEF +#define RTE_USART1_CTS_BIT RTE_USART1_CTS_BIT_DEF +#define RTE_USART1_RTS_PORT RTE_USART1_RTS_PORT_DEF +#define RTE_USART1_RTS_BIT RTE_USART1_RTS_BIT_DEF +#endif + +// DMA Rx +// Number <1=>1 +// Selects DMA Number (only DMA1 can be used) +// Channel <5=>5 +// Selects DMA Channel (only Channel 5 can be used) +// Priority <0=>Low <1=>Medium <2=>High <3=>Very high +// Set DMA Channel priority +// +#define RTE_USART1_RX_DMA 0 +#define RTE_USART1_RX_DMA_NUMBER 1 +#define RTE_USART1_RX_DMA_CHANNEL 5 +#define RTE_USART1_RX_DMA_PRIORITY 0 +// DMA Tx +// Number <1=>1 +// Selects DMA Number (only DMA1 can be used) +// Channel <4=>4 +// Selects DMA Channel (only Channel 4 can be used) +// Priority <0=>Low <1=>Medium <2=>High <3=>Very high +// Set DMA Channel priority +// +#define RTE_USART1_TX_DMA 0 +#define RTE_USART1_TX_DMA_NUMBER 1 +#define RTE_USART1_TX_DMA_CHANNEL 4 +#define RTE_USART1_TX_DMA_PRIORITY 0 +// + + +// USART2 (Universal synchronous asynchronous receiver transmitter) +// Configuration settings for Driver_USART2 in component ::CMSIS Driver:USART +#define RTE_USART2 1 + +// USART2_TX Pin <0=>Not Used <1=>PA2 +#define RTE_USART2_TX_PORT_ID_DEF 1 +#if (RTE_USART2_TX_PORT_ID_DEF == 0) +#define RTE_USART2_TX_DEF 0 +#elif (RTE_USART2_TX_PORT_ID_DEF == 1) +#define RTE_USART2_TX_DEF 1 +#define RTE_USART2_TX_PORT_DEF GPIOA +#define RTE_USART2_TX_BIT_DEF 2 +#else +#error "Invalid USART2_TX Pin Configuration!" +#endif + +// USART2_RX Pin <0=>Not Used <1=>PA3 +#define RTE_USART2_RX_PORT_ID_DEF 1 +#if (RTE_USART2_RX_PORT_ID_DEF == 0) +#define RTE_USART2_RX_DEF 0 +#elif (RTE_USART2_RX_PORT_ID_DEF == 1) +#define RTE_USART2_RX_DEF 1 +#define RTE_USART2_RX_PORT_DEF GPIOA +#define RTE_USART2_RX_BIT_DEF 3 +#else +#error "Invalid USART2_RX Pin Configuration!" +#endif + +// USART2_CK Pin <0=>Not Used <1=>PA4 +#define RTE_USART2_CK_PORT_ID_DEF 0 +#if (RTE_USART2_CK_PORT_ID_DEF == 0) +#define RTE_USART2_CK_DEF 0 +#elif (RTE_USART2_CK_PORT_ID_DEF == 1) +#define RTE_USART2_CK_DEF 1 +#define RTE_USART2_CK_PORT_DEF GPIOA +#define RTE_USART2_CK_BIT_DEF 4 +#else +#error "Invalid USART2_CK Pin Configuration!" +#endif + +// USART2_CTS Pin <0=>Not Used <1=>PA0 +#define RTE_USART2_CTS_PORT_ID_DEF 0 +#if (RTE_USART2_CTS_PORT_ID_DEF == 0) +#define RTE_USART2_CTS_DEF 0 +#elif (RTE_USART2_CTS_PORT_ID_DEF == 1) +#define RTE_USART2_CTS_DEF 1 +#define RTE_USART2_CTS_PORT_DEF GPIOA +#define RTE_USART2_CTS_BIT_DEF 0 +#else +#error "Invalid USART2_CTS Pin Configuration!" +#endif + +// USART2_RTS Pin <0=>Not Used <1=>PA1 +#define RTE_USART2_RTS_PORT_ID_DEF 0 +#if (RTE_USART2_RTS_PORT_ID_DEF == 0) +#define RTE_USART2_RTS_DEF 0 +#elif (RTE_USART2_RTS_PORT_ID_DEF == 1) +#define RTE_USART2_RTS_DEF 1 +#define RTE_USART2_RTS_PORT_DEF GPIOA +#define RTE_USART2_RTS_BIT_DEF 1 +#else +#error "Invalid USART2_RTS Pin Configuration!" +#endif + +// USART2 Pin Remap +// Enable USART2 Pin Remapping +#define RTE_USART2_REMAP_FULL 0 + +// USART2_TX Pin <0=>Not Used <1=>PD5 +#define RTE_USART2_TX_PORT_ID_FULL 0 +#if (RTE_USART2_TX_PORT_ID_FULL == 0) +#define RTE_USART2_TX_FULL 0 +#elif (RTE_USART2_TX_PORT_ID_FULL == 1) +#define RTE_USART2_TX_FULL 1 +#define RTE_USART2_TX_PORT_FULL GPIOD +#define RTE_USART2_TX_BIT_FULL 5 +#else +#error "Invalid USART2_TX Pin Configuration!" +#endif + +// USART2_RX Pin <0=>Not Used <1=>PD6 +#define RTE_USART2_RX_PORT_ID_FULL 0 +#if (RTE_USART2_RX_PORT_ID_FULL == 0) +#define RTE_USART2_RX_FULL 0 +#elif (RTE_USART2_RX_PORT_ID_FULL == 1) +#define RTE_USART2_RX_FULL 1 +#define RTE_USART2_RX_PORT_FULL GPIOD +#define RTE_USART2_RX_BIT_FULL 6 +#else +#error "Invalid USART2_RX Pin Configuration!" +#endif + +// USART2_CK Pin <0=>Not Used <1=>PD7 +#define RTE_USART2_CK_PORT_ID_FULL 0 +#if (RTE_USART2_CK_PORT_ID_FULL == 0) +#define RTE_USART2_CK_FULL 0 +#elif (RTE_USART2_CK_PORT_ID_FULL == 1) +#define RTE_USART2_CK_FULL 1 +#define RTE_USART2_CK_PORT_FULL GPIOD +#define RTE_USART2_CK_BIT_FULL 7 +#else +#error "Invalid USART2_CK Pin Configuration!" +#endif + +// USART2_CTS Pin <0=>Not Used <1=>PD3 +#define RTE_USART2_CTS_PORT_ID_FULL 0 +#if (RTE_USART2_CTS_PORT_ID_FULL == 0) +#define RTE_USART2_CTS_FULL 0 +#elif (RTE_USART2_CTS_PORT_ID_FULL == 1) +#define RTE_USART2_CTS_FULL 1 +#define RTE_USART2_CTS_PORT_FULL GPIOD +#define RTE_USART2_CTS_BIT_FULL 3 +#else +#error "Invalid USART2_CTS Pin Configuration!" +#endif + +// USART2_RTS Pin <0=>Not Used <1=>PD4 +#define RTE_USART2_RTS_PORT_ID_FULL 0 +#if (RTE_USART2_RTS_PORT_ID_FULL == 0) +#define RTE_USART2_RTS_FULL 0 +#elif (RTE_USART2_RTS_PORT_ID_FULL == 1) +#define RTE_USART2_RTS_FULL 1 +#define RTE_USART2_RTS_PORT_FULL GPIOD +#define RTE_USART2_RTS_BIT_FULL 4 +#else +#error "Invalid USART2_RTS Pin Configuration!" +#endif +// + +#if (RTE_USART2_REMAP_FULL) +#define RTE_USART2_AF_REMAP AFIO_USART2_REMAP +#define RTE_USART2_TX RTE_USART2_TX_FULL +#define RTE_USART2_TX_PORT RTE_USART2_TX_PORT_FULL +#define RTE_USART2_TX_BIT RTE_USART2_TX_BIT_FULL +#define RTE_USART2_RX RTE_USART2_RX_FULL +#define RTE_USART2_RX_PORT RTE_USART2_RX_PORT_FULL +#define RTE_USART2_RX_BIT RTE_USART2_RX_BIT_FULL +#define RTE_USART2_CK RTE_USART2_CK_FULL +#define RTE_USART2_CK_PORT RTE_USART2_CK_PORT_FULL +#define RTE_USART2_CK_BIT RTE_USART2_CK_BIT_FULL +#define RTE_USART2_CTS RTE_USART2_CTS_FULL +#define RTE_USART2_CTS_PORT RTE_USART2_CTS_PORT_FULL +#define RTE_USART2_CTS_BIT RTE_USART2_CTS_BIT_FULL +#define RTE_USART2_RTS RTE_USART2_RTS_FULL +#define RTE_USART2_RTS_PORT RTE_USART2_RTS_PORT_FULL +#define RTE_USART2_RTS_BIT RTE_USART2_RTS_BIT_FULL +#else +#define RTE_USART2_AF_REMAP AFIO_USART2_NO_REMAP +#define RTE_USART2_TX RTE_USART2_TX_DEF +#define RTE_USART2_TX_PORT RTE_USART2_TX_PORT_DEF +#define RTE_USART2_TX_BIT RTE_USART2_TX_BIT_DEF +#define RTE_USART2_RX RTE_USART2_RX_DEF +#define RTE_USART2_RX_PORT RTE_USART2_RX_PORT_DEF +#define RTE_USART2_RX_BIT RTE_USART2_RX_BIT_DEF +#define RTE_USART2_CK RTE_USART2_CK_DEF +#define RTE_USART2_CK_PORT RTE_USART2_CK_PORT_DEF +#define RTE_USART2_CK_BIT RTE_USART2_CK_BIT_DEF +#define RTE_USART2_CTS RTE_USART2_CTS_DEF +#define RTE_USART2_CTS_PORT RTE_USART2_CTS_PORT_DEF +#define RTE_USART2_CTS_BIT RTE_USART2_CTS_BIT_DEF +#define RTE_USART2_RTS RTE_USART2_RTS_DEF +#define RTE_USART2_RTS_PORT RTE_USART2_RTS_PORT_DEF +#define RTE_USART2_RTS_BIT RTE_USART2_RTS_BIT_DEF +#endif + +// DMA Rx +// Number <1=>1 +// Selects DMA Number (only DMA1 can be used) +// Channel <6=>6 +// Selects DMA Channel (only Channel 6 can be used) +// Priority <0=>Low <1=>Medium <2=>High <3=>Very high +// Set DMA Channel priority +// +#define RTE_USART2_RX_DMA 0 +#define RTE_USART2_RX_DMA_NUMBER 1 +#define RTE_USART2_RX_DMA_CHANNEL 6 +#define RTE_USART2_RX_DMA_PRIORITY 0 + +// DMA Tx +// Number <1=>1 +// Selects DMA Number (only DMA1 can be used) +// Channel <7=>7 +// Selects DMA Channel (only Channel 7 can be used) +// Priority <0=>Low <1=>Medium <2=>High <3=>Very high +// Set DMA Channel priority +// +#define RTE_USART2_TX_DMA 0 +#define RTE_USART2_TX_DMA_NUMBER 1 +#define RTE_USART2_TX_DMA_CHANNEL 7 +#define RTE_USART2_TX_DMA_PRIORITY 0 + +// + +#endif /* __RTE_DEVICE_H */ diff --git a/source/hic_hal/stm32/stm32f103xb/cmsis/DMA_STM32F10x.c b/source/hic_hal/stm32/stm32f103xb/cmsis/DMA_STM32F10x.c new file mode 100644 index 0000000000..3f1d53e8f2 --- /dev/null +++ b/source/hic_hal/stm32/stm32f103xb/cmsis/DMA_STM32F10x.c @@ -0,0 +1,490 @@ +/* ----------------------------------------------------------------------------- + * Copyright (c) 2013-2020 Arm Limited (or its affiliates). 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 + * + * 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. + * + * + * $Date: 27. November 2020 + * $Revision: V1.3 + * + * Project: DMA Driver for ST STM32F10x + * -------------------------------------------------------------------- */ + +/* History: + * Version 1.3 + * Added support for ARM Compiler 6 + * Version 1.2 + * DMAx_Channel variable is checked for initialized channels in DMA_ChannelUninitialize function + * Version 1.1 + * DMA2 peripheral added to build when HD, XL, HD_VL or CL device is used + * Version 1.0 + * Initial release + */ + +#include "DMA_STM32F10x.h" + +#if defined(STM32F10X_HD) || defined(STM32F10X_XL) || \ + defined(STM32F10X_HD_VL) || defined(STM32F10X_CL) + /* DMA2 peripheral exists on HD, XL, HD_VL and CL devices */ + #define STM32F10X_ENABLE_DMA2 +#endif + +/// DMA Variables +static uint8_t DMA1_Channel; // Used DMA1 Channels +#if defined (STM32F10X_ENABLE_DMA2) +static uint8_t DMA2_Channel; // Used DMA2 Channels +#endif + + +/// DMA Functions + +/** + \fn void DMA_ChannelInitialize (uint32_t dma, uint32_t channel) + \brief Initialize DMA Channel + \param[in] dma DMA number + \param[in] channel DMA channel number +*/ +void DMA_ChannelInitialize (uint32_t dma, uint32_t channel) { + + switch (dma) { + case 1: + RCC->AHBENR |= RCC_AHBENR_DMA1EN; + switch (channel) { + case 1: + DMA1_Channel1->CCR = 0; + DMA1->IFCR = DMA_IFCR_CGIF1 | DMA_IFCR_CTEIF1 | + DMA_IFCR_CHTIF1 | DMA_IFCR_CTCIF1; + NVIC_ClearPendingIRQ(DMA1_Channel1_IRQn); + NVIC_EnableIRQ(DMA1_Channel1_IRQn); + break; + case 2: + DMA1_Channel2->CCR = 0; + DMA1->IFCR = DMA_IFCR_CGIF2 | DMA_IFCR_CTEIF2 | + DMA_IFCR_CHTIF2 | DMA_IFCR_CTCIF2; + NVIC_ClearPendingIRQ(DMA1_Channel2_IRQn); + NVIC_EnableIRQ(DMA1_Channel2_IRQn); + break; + case 3: + DMA1_Channel3->CCR = 0; + DMA1->IFCR = DMA_IFCR_CGIF3 | DMA_IFCR_CTEIF3 | + DMA_IFCR_CHTIF3 | DMA_IFCR_CTCIF3; + NVIC_ClearPendingIRQ(DMA1_Channel3_IRQn); + NVIC_EnableIRQ(DMA1_Channel3_IRQn); + break; + case 4: + DMA1_Channel4->CCR = 0; + DMA1->IFCR = DMA_IFCR_CGIF4 | DMA_IFCR_CTEIF4 | + DMA_IFCR_CHTIF4 | DMA_IFCR_CTCIF4; + NVIC_ClearPendingIRQ(DMA1_Channel4_IRQn); + NVIC_EnableIRQ(DMA1_Channel4_IRQn); + break; + case 5: + DMA1_Channel5->CCR = 0; + DMA1->IFCR = DMA_IFCR_CGIF5 | DMA_IFCR_CTEIF5 | + DMA_IFCR_CHTIF5 | DMA_IFCR_CTCIF5; + NVIC_ClearPendingIRQ(DMA1_Channel5_IRQn); + NVIC_EnableIRQ(DMA1_Channel5_IRQn); + break; + case 6: + DMA1_Channel6->CCR = 0; + DMA1->IFCR = DMA_IFCR_CGIF6 | DMA_IFCR_CTEIF6 | + DMA_IFCR_CHTIF6 | DMA_IFCR_CTCIF6; + NVIC_ClearPendingIRQ(DMA1_Channel6_IRQn); + NVIC_EnableIRQ(DMA1_Channel6_IRQn); + break; + case 7: + DMA1_Channel7->CCR = 0; + DMA1->IFCR = DMA_IFCR_CGIF7 | DMA_IFCR_CTEIF7 | + DMA_IFCR_CHTIF7 | DMA_IFCR_CTCIF7; + NVIC_ClearPendingIRQ(DMA1_Channel7_IRQn); + NVIC_EnableIRQ(DMA1_Channel7_IRQn); + break; + } + DMA1_Channel |= 1 << channel; + break; + + #if defined (STM32F10X_ENABLE_DMA2) + case 2: + RCC->AHBENR |= RCC_AHBENR_DMA2EN; + switch (channel) { + case 1: + DMA2_Channel1->CCR = 0; + DMA2->IFCR = DMA_IFCR_CGIF1 | DMA_IFCR_CTEIF1 | + DMA_IFCR_CHTIF1 | DMA_IFCR_CTCIF1; + NVIC_ClearPendingIRQ(DMA2_Channel1_IRQn); + NVIC_EnableIRQ(DMA2_Channel1_IRQn); + break; + case 2: + DMA2_Channel2->CCR = 0; + DMA2->IFCR = DMA_IFCR_CGIF2 | DMA_IFCR_CTEIF2 | + DMA_IFCR_CHTIF2 | DMA_IFCR_CTCIF2; + NVIC_ClearPendingIRQ(DMA2_Channel2_IRQn); + NVIC_EnableIRQ(DMA2_Channel2_IRQn); + break; + case 3: + DMA2_Channel3->CCR = 0; + DMA2->IFCR = DMA_IFCR_CGIF3 | DMA_IFCR_CTEIF3 | + DMA_IFCR_CHTIF3 | DMA_IFCR_CTCIF3; + NVIC_ClearPendingIRQ(DMA2_Channel3_IRQn); + NVIC_EnableIRQ(DMA2_Channel3_IRQn); + break; + case 4: + DMA2_Channel4->CCR = 0; + DMA2->IFCR = DMA_IFCR_CGIF4 | DMA_IFCR_CTEIF4 | + DMA_IFCR_CHTIF4 | DMA_IFCR_CTCIF4; + + #if defined (STM32F10X_CL) + NVIC_ClearPendingIRQ(DMA2_Channel4_IRQn); + NVIC_EnableIRQ(DMA2_Channel4_IRQn); + #else + NVIC_ClearPendingIRQ(DMA2_Channel4_5_IRQn); + NVIC_EnableIRQ(DMA2_Channel4_5_IRQn); + #endif + break; + case 5: + DMA2_Channel5->CCR = 0; + DMA2->IFCR = DMA_IFCR_CGIF5 | DMA_IFCR_CTEIF5 | + DMA_IFCR_CHTIF5 | DMA_IFCR_CTCIF5; + + #if defined (STM32F10X_CL) + NVIC_ClearPendingIRQ(DMA2_Channel5_IRQn); + NVIC_EnableIRQ(DMA2_Channel5_IRQn); + #elif defined (STM32F10X_HD_VL) + if (AFIO->MAPR2 & AFIO_MAPR2_MISC_REMAP) { + /* DMA2 Channel 5 mapped at position 60 */ + NVIC_ClearPendingIRQ(DMA2_Channel5_IRQn); + NVIC_EnableIRQ(DMA2_Channel5_IRQn); + } + else { + NVIC_ClearPendingIRQ(DMA2_Channel4_5_IRQn); + NVIC_EnableIRQ(DMA2_Channel4_5_IRQn); + } + #else + NVIC_ClearPendingIRQ(DMA2_Channel4_5_IRQn); + NVIC_EnableIRQ(DMA2_Channel4_5_IRQn); + #endif + break; + } + DMA2_Channel |= 1 << channel; + break; + #endif + } +} + +/** + \fn void DMA_ChannelUninitialize (uint32_t dma, uint32_t channel) + \brief Uninitialize DMA Channel + \param[in] dma DMA number + \param[in] channel DMA channel number +*/ +void DMA_ChannelUninitialize (uint32_t dma, uint32_t channel) { + + switch (dma) { + case 1: + if (DMA1_Channel == 0) { + // All DMA1 Channels are uninitialized + return; + } + switch (channel) { + case 1: + NVIC_DisableIRQ(DMA1_Channel1_IRQn); + DMA1_Channel1->CCR = 0; + break; + case 2: + NVIC_DisableIRQ(DMA1_Channel2_IRQn); + DMA1_Channel2->CCR = 0; + break; + case 3: + NVIC_DisableIRQ(DMA1_Channel3_IRQn); + DMA1_Channel3->CCR = 0; + break; + case 4: + NVIC_DisableIRQ(DMA1_Channel4_IRQn); + DMA1_Channel4->CCR = 0; + break; + case 5: + NVIC_DisableIRQ(DMA1_Channel5_IRQn); + DMA1_Channel5->CCR = 0; + break; + case 6: + NVIC_DisableIRQ(DMA1_Channel6_IRQn); + DMA1_Channel6->CCR = 0; + break; + case 7: + NVIC_DisableIRQ(DMA1_Channel7_IRQn); + DMA1_Channel7->CCR = 0; + break; + } + DMA1_Channel &= ~(1 << channel); + if (DMA1_Channel == 0){ + RCC->AHBENR &= ~RCC_AHBENR_DMA1EN; + } + break; + + #if defined (STM32F10X_ENABLE_DMA2) + case 2: + if (DMA2_Channel == 0) { + // All DMA2 Channels are uninitialized + return; + } + switch (channel) { + case 1: + NVIC_DisableIRQ(DMA2_Channel1_IRQn); + DMA2_Channel1->CCR = 0; + break; + case 2: + NVIC_DisableIRQ(DMA2_Channel2_IRQn); + DMA2_Channel2->CCR = 0; + break; + case 3: + NVIC_DisableIRQ(DMA2_Channel3_IRQn); + DMA2_Channel3->CCR = 0; + break; + case 4: + #if defined (STM32F10X_CL) + NVIC_DisableIRQ(DMA2_Channel4_IRQn); + #else + /* If Channel 5 disabled, disable also Channel 4 */ + if (!(DMA2_Channel & (1 << 5))) { + NVIC_DisableIRQ(DMA2_Channel4_5_IRQn); + } + #endif + DMA2_Channel4->CCR = 0; + break; + case 5: + #if defined (STM32F10X_CL) + NVIC_DisableIRQ(DMA2_Channel5_IRQn); + #elif defined (STM32F10X_HD_VL) + if (AFIO->MAPR2 & AFIO_MAPR2_MISC_REMAP) { + /* DMA2 Channel 5 mapped at position 60 */ + NVIC_DisableIRQ(DMA2_Channel5_IRQn); + } + else { + /* If Channel 4 disabled, disable also Channel 5 */ + if (!(DMA2_Channel & (1 << 4))) { + NVIC_DisableIRQ(DMA2_Channel4_5_IRQn); + } + } + #else + /* If Channel 4 disabled, disable also Channel 5 */ + if (!(DMA2_Channel & (1 << 4))) { + NVIC_DisableIRQ(DMA2_Channel4_5_IRQn); + } + #endif + DMA2_Channel5->CCR = 0; + break; + } + DMA2_Channel &= ~(1 << channel); + if (DMA2_Channel == 0){ + RCC->AHBENR &= ~RCC_AHBENR_DMA2EN; + } + break; + #endif + } +} + + +/// DMA1 Channel Events +__WEAK void DMA1_Channel1_Event (uint32_t event) {;} +__WEAK void DMA1_Channel2_Event (uint32_t event) {;} +__WEAK void DMA1_Channel3_Event (uint32_t event) {;} +__WEAK void DMA1_Channel4_Event (uint32_t event) {;} +__WEAK void DMA1_Channel5_Event (uint32_t event) {;} +__WEAK void DMA1_Channel6_Event (uint32_t event) {;} +__WEAK void DMA1_Channel7_Event (uint32_t event) {;} + + +#if defined (STM32F10X_ENABLE_DMA2) +/// DMA2 Channel Events +__WEAK void DMA2_Channel1_Event (uint32_t event) {;} +__WEAK void DMA2_Channel2_Event (uint32_t event) {;} +__WEAK void DMA2_Channel3_Event (uint32_t event) {;} +__WEAK void DMA2_Channel4_Event (uint32_t event) {;} +__WEAK void DMA2_Channel5_Event (uint32_t event) {;} +#endif + +/** + \fn void DMA1_Channel1_IRQHandler (void) + \brief DMA1 Channel0 interrupt handler +*/ +void DMA1_Channel1_IRQHandler (void) { + uint32_t events; + + events = (DMA1->ISR >> 0) & DMA_CHANNEL_FLAGS; + DMA1->IFCR = events << 0; + DMA1_Channel1_Event(events); +} + +/** + \fn void DMA1_Channel2_IRQHandler (void) + \brief DMA1 Channel2 interrupt handler +*/ +void DMA1_Channel2_IRQHandler (void) { + uint32_t events; + + events = (DMA1->ISR >> 4) & DMA_CHANNEL_FLAGS; + DMA1->IFCR = events << 4; + DMA1_Channel2_Event(events); +} + +/** + \fn void DMA1_Channel3_IRQHandler (void) + \brief DMA1 Channel3 interrupt handler +*/ +void DMA1_Channel3_IRQHandler (void) { + uint32_t events; + + events = (DMA1->ISR >> 8) & DMA_CHANNEL_FLAGS; + DMA1->IFCR = events << 8; + DMA1_Channel3_Event(events); +} + +/** + \fn void DMA1_Channel4_IRQHandler (void) + \brief DMA1 Channel4 interrupt handler +*/ +void DMA1_Channel4_IRQHandler (void) { + uint32_t events; + + events = (DMA1->ISR >> 12) & DMA_CHANNEL_FLAGS; + DMA1->IFCR = events << 12; + DMA1_Channel4_Event(events); +} + +/** + \fn void DMA1_Channel5_IRQHandler (void) + \brief DMA1 Channel5 interrupt handler +*/ +void DMA1_Channel5_IRQHandler (void) { + uint32_t events; + + events = (DMA1->ISR >> 16) & DMA_CHANNEL_FLAGS; + DMA1->IFCR = events << 16; + DMA1_Channel5_Event(events); +} + +/** + \fn void DMA1_Channel6_IRQHandler (void) + \brief DMA1 Channel6 interrupt handler +*/ +void DMA1_Channel6_IRQHandler (void) { + uint32_t events; + + events = (DMA1->ISR >> 20) & DMA_CHANNEL_FLAGS; + DMA1->IFCR = events << 20; + DMA1_Channel6_Event(events); +} + +/** + \fn void DMA1_Channel7_IRQHandler (void) + \brief DMA1 Channel7 interrupt handler +*/ +void DMA1_Channel7_IRQHandler (void) { + uint32_t events; + + events = (DMA1->ISR >> 24) & DMA_CHANNEL_FLAGS; + DMA1->IFCR = events << 24; + DMA1_Channel7_Event(events); +} + + +#if defined (STM32F10X_ENABLE_DMA2) +/** + \fn void DMA2_Channel1_IRQHandler (void) + \brief DMA2 Channel1 interrupt handler +*/ +void DMA2_Channel1_IRQHandler (void) { + uint32_t events; + + events = (DMA2->ISR >> 0) & DMA_CHANNEL_FLAGS; + DMA2->IFCR = events << 0; + DMA2_Channel1_Event(events); +} + +/** + \fn void DMA2_Channel2_IRQHandler (void) + \brief DMA2 Channel2 interrupt handler +*/ +void DMA2_Channel2_IRQHandler (void) { + uint32_t events; + + events = (DMA2->ISR >> 4) & DMA_CHANNEL_FLAGS; + DMA2->IFCR = events << 4; + DMA2_Channel2_Event(events); +} + +/** + \fn void DMA2_Channel3_IRQHandler (void) + \brief DMA2 Channel3 interrupt handler +*/ +void DMA2_Channel3_IRQHandler (void) { + uint32_t events; + + events = (DMA2->ISR >> 8) & DMA_CHANNEL_FLAGS; + DMA2->IFCR = events << 8; + DMA2_Channel3_Event(events); +} + +#if !defined(STM32F10X_CL) +/** + \fn void DMA2_Channel4_IRQHandler (void) + \brief DMA2 Channel4 interrupt handler +*/ +void DMA2_Channel4_IRQHandler (void) { + uint32_t events; + + events = (DMA2->ISR >> 12) & DMA_CHANNEL_FLAGS; + DMA2->IFCR = events << 12; + DMA2_Channel4_Event(events); +} +#endif + +#if defined(STM32F10X_HD_VL) || defined (STM32F10X_CL) +/** + \fn void DMA2_Channel5_IRQHandler (void) + \brief DMA2 Channel5 interrupt handler +*/ +void DMA2_Channel5_IRQHandler (void) { + uint32_t events; + + events = (DMA2->ISR >> 16) & DMA_CHANNEL_FLAGS; + DMA2->IFCR = events << 16; + DMA2_Channel5_Event(events); +} +#endif + +/** + \fn void DMA2_Channel4_5_IRQHandler (void) + \brief DMA2 Channel 4 and 5 interrupt handler +*/ +void DMA2_Channel4_5_IRQHandler (void) { + uint32_t events; + + events = (DMA2->ISR >> 12) & DMA_CHANNEL_FLAGS; + if (events) { + /* Channel 4 events */ + DMA2->IFCR = events << 12; + DMA2_Channel4_Event(events); + } + + events = (DMA2->ISR >> 16) & DMA_CHANNEL_FLAGS; + if (events) { + /* Channel 5 events */ + DMA2->IFCR = events << 16; + DMA2_Channel5_Event(events); + } +} +#endif diff --git a/source/hic_hal/stm32/stm32f103xb/cmsis/DMA_STM32F10x.h b/source/hic_hal/stm32/stm32f103xb/cmsis/DMA_STM32F10x.h new file mode 100644 index 0000000000..21f99aefeb --- /dev/null +++ b/source/hic_hal/stm32/stm32f103xb/cmsis/DMA_STM32F10x.h @@ -0,0 +1,178 @@ +/* ----------------------------------------------------------------------------- + * Copyright (c) 2013 Arm Limited (or its affiliates). 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 + * + * 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. + * + * + * $Date: 27. August 2013 + * $Revision: V1.01 + * + * Project: DMA Driver definitions for ST STM32F10x + * -------------------------------------------------------------------- */ + +#ifndef __DMA_STM32F10X_H +#define __DMA_STM32F10X_H + +#include +#include +#include "stm32f1xx.h" + + +#if defined (__CC_ARM) +#define __FORCE_INLINE static __forceinline +#else +#define __FORCE_INLINE __STATIC_INLINE +#endif + + +#define _DMAx_CHANNELy(x, y) DMA##x##_Channel##y +#define DMAx_CHANNELy(x, y) _DMAx_CHANNELy(x, y) + +#define _DMAx_CHANNELy_EVENT(x, y) DMA##x##_Channel##y##_Event +#define DMAx_CHANNELy_EVENT(x, y) _DMAx_CHANNELy_EVENT(x, y) + + +// DMA channel Interrupt Flags +#define DMA_CHANNEL_GLOBAL_INTERRUPT (1UL<<0) +#define DMA_CHANNEL_TRANSFER_COMPLETE (1UL<<1) +#define DMA_CHANNEL_HALF_TRANSFER (1UL<<2) +#define DMA_CHANNEL_TRANSFER_ERROR (1UL<<3) +#define DMA_CHANNEL_FLAGS (DMA_CHANNEL_TRANSFER_ERROR | \ + DMA_CHANNEL_HALF_TRANSFER | \ + DMA_CHANNEL_TRANSFER_COMPLETE | \ + DMA_CHANNEL_GLOBAL_INTERRUPT) + +// DMA channel Configuration Register definitions +#define DMA_TRANSFER_ERROR_INTERRUPT DMA_CCR1_TEIE +#define DMA_HALF_TRANSFER_INTERRUPT DMA_CCR1_HTIE +#define DMA_TRANSFER_COMPLETE_INTERRUPT DMA_CCR1_TCIE +#define DMA_PERIPHERAL_TO_MEMORY 0 +#define DMA_READ_MEMORY DMA_CCR1_DIR +#ifndef DMA_MEMORY_TO_MEMORY +#define DMA_MEMORY_TO_MEMORY DMA_CCR1_MEM2MEM +#endif +#define DMA_CIRCULAR_MODE DMA_CCR1_CIRC +#define DMA_PERIPHERAL_INCREMENT DMA_CCR1_PINC +#define DMA_MEMORY_INCREMENT DMA_CCR1_MINC +#define DMA_PERIPHERAL_DATA_8BIT 0 +#define DMA_PERIPHERAL_DATA_16BIT DMA_CCR1_PSIZE_0 +#define DMA_PERIPHERAL_DATA_32BIT DMA_CCR1_PSIZE_1 +#define DMA_MEMORY_DATA_8BIT 0 +#define DMA_MEMORY_DATA_16BIT DMA_CCR1_MSIZE_0 +#define DMA_MEMORY_DATA_32BIT DMA_CCR1_MSIZE_1 +#define DMA_PRIORITY_POS 12 +#define DMA_PRIORITY_MASK DMA_CCR1_PL +#ifdef DMA_CCR_EN +#define DMA_CHANNEL_EN DMA_CCR_EN +#else +#define DMA_CHANNEL_EN DMA_CCR1_EN +#endif + + +// DMA Information definitions +typedef struct _DMA_INFO { + DMA_Channel_TypeDef *ptr_channel; + uint8_t dma; + uint8_t channel; + uint8_t priority; +} DMA_INFO; + + +/// DMA Functions + +/** + \fn void DMA_ChannelInitialize (uint32_t dma, uint32_t channel) + \brief Initialize DMA Channel + \param[in] dma DMA number + \param[in] channel DMA channel number +*/ +extern void DMA_ChannelInitialize (uint32_t dma, uint32_t channel); + +/** + \fn void DMA_ChannelUninitialize (uint32_t dma, uint32_t channel) + \brief Uninitialize DMA channel + \param[in] dma DMA number + \param[in] channel DMA channel number +*/ +extern void DMA_ChannelUninitialize (uint32_t dma, uint32_t channel); + +/** + \fn void DMA_ChannelConfigure (DMA_Channel_TypeDef *DMA_Channel, + uint32_t ccr, + uint32_t cpar, + uint32_t cmar, + uint32_t cndtr); + \brief Configure DMA channel for next transfer + \param[in] DMA_Channel specifies pointer to DMA channel peripheral + \param[in] ccr Configuration register value + \param[in] cpar Peripheral address register value + \param[in] cmar Memory address register value + \param[in] cndtr Number of data transfer register value +*/ +__FORCE_INLINE void DMA_ChannelConfigure (DMA_Channel_TypeDef *DMA_Channel, + uint32_t ccr, + uint32_t cpar, + uint32_t cmar, + uint32_t cndtr) { + DMA_Channel->CCR = ccr; + DMA_Channel->CPAR = cpar; + DMA_Channel->CMAR = cmar; + DMA_Channel->CNDTR = cndtr; +} + + +/** + \fn void DMA_ChannelEnable (DMA_Channel_TypeDef *DMA_Channel) + \brief Enable channel and/or start memory to memory transfer + \param[in] DMA_Channel Pointer to DMA channel peripheral +*/ +__FORCE_INLINE void DMA_ChannelEnable (DMA_Channel_TypeDef *DMA_Channel) { + DMA_Channel->CCR |= DMA_CHANNEL_EN; +} + +/** + \fn void DMA_ChannelDisable (DMA_Channel_TypeDef *DMA_Channel) + \brief Disable channel and/or stop memory to memory transfer + \param[in] DMA_Channel Pointer to DMA channel peripheral +*/ +__FORCE_INLINE void DMA_ChannelDisable (DMA_Channel_TypeDef *DMA_Channel) { + DMA_Channel->CCR &= ~DMA_CHANNEL_EN; +} + +/** + \fn bool DMA_ChannelStatus (DMA_Channel_TypeDef *DMA_Channel) + \brief Check if channel is enabled or disabled + \param[in] DMA_Channel Pointer to DMA channel peripheral + \return Channel Status + - \b true Enabled + - \b false Disabled +*/ +__FORCE_INLINE bool DMA_ChannelStatus (DMA_Channel_TypeDef *DMA_Channel) { + return (DMA_Channel->CCR & DMA_CHANNEL_EN) ? true : false; +} + +/** + \fn uint32_t DMA_ChannelTransferItemCount (DMA_Channel_TypeDef *DMA_Channel) + \brief Get number of data items to transfer + \param[in] DMA_channel Pointer to DMA channel peripheral + \return Number of data items to transfer +*/ +__FORCE_INLINE uint32_t DMA_ChannelTransferItemCount (DMA_Channel_TypeDef *DMA_Channel) { + return DMA_Channel->CNDTR; +} + + +#endif /* __DMA_STM32F10X_H */ diff --git a/source/hic_hal/stm32/stm32f103xb/cmsis/GPIO_STM32F10x.c b/source/hic_hal/stm32/stm32f103xb/cmsis/GPIO_STM32F10x.c new file mode 100644 index 0000000000..e6e57046d7 --- /dev/null +++ b/source/hic_hal/stm32/stm32f103xb/cmsis/GPIO_STM32F10x.c @@ -0,0 +1,197 @@ +/* ----------------------------------------------------------------------------- + * Copyright (c) 2016 Arm Limited (or its affiliates). 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 + * + * 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. + * + * + * $Date: 26. April 2016 + * $Revision: V1.3 + * + * Project: GPIO Driver for ST STM32F10x + * -------------------------------------------------------------------- */ + +#include "GPIO_STM32F10x.h" + +/* History: + * Version 1.3 + * Corrected corruption of Serial wire JTAG pins alternate function configuration. + * Version 1.2 + * Added GPIO_GetPortClockState function + * GPIO_PinConfigure function enables GPIO peripheral clock, if not already enabled + * Version 1.1 + * GPIO_PortClock and GPIO_PinConfigure functions rewritten + * GPIO_STM32F1xx header file cleaned up and simplified + * GPIO_AFConfigure function and accompanying definitions added + * Version 1.0 + * Initial release + */ + +/* Serial wire JTAG pins alternate function Configuration + * Can be user defined by C preprocessor: + * AFIO_SWJ_FULL, AFIO_SWJ_FULL_NO_NJTRST, AFIO_SWJ_JTAG_NO_SW, AFIO_SWJ_NO_JTAG_NO_SW + */ +#ifndef AFIO_MAPR_SWJ_CFG_VAL +#define AFIO_MAPR_SWJ_CFG_VAL (AFIO_SWJ_FULL) // Full SWJ (JTAG-DP + SW-DP) +#endif + +/** + \fn void GPIO_PortClock (GPIO_TypeDef *GPIOx, bool en) + \brief Port Clock Control + \param[in] GPIOx Pointer to GPIO peripheral + \param[in] enable Enable or disable clock +*/ +void GPIO_PortClock (GPIO_TypeDef *GPIOx, bool enable) { + + if (enable) { + if (GPIOx == GPIOA) RCC->APB2ENR |= (1U << 2); + else if (GPIOx == GPIOB) RCC->APB2ENR |= (1U << 3); + else if (GPIOx == GPIOC) RCC->APB2ENR |= (1U << 4); + else if (GPIOx == GPIOD) RCC->APB2ENR |= (1U << 5); + else if (GPIOx == GPIOE) RCC->APB2ENR |= (1U << 6); +#ifdef GPIOF + else if (GPIOx == GPIOF) RCC->APB2ENR |= (1U << 7); +#endif +#ifdef GPIOG + else if (GPIOx == GPIOG) RCC->APB2ENR |= (1U << 8); +#endif + } else { + if (GPIOx == GPIOA) RCC->APB2ENR &= ~(1U << 2); + else if (GPIOx == GPIOB) RCC->APB2ENR &= ~(1U << 3); + else if (GPIOx == GPIOC) RCC->APB2ENR &= ~(1U << 4); + else if (GPIOx == GPIOD) RCC->APB2ENR &= ~(1U << 5); + else if (GPIOx == GPIOE) RCC->APB2ENR &= ~(1U << 6); +#ifdef GPIOF + else if (GPIOx == GPIOF) RCC->APB2ENR &= ~(1U << 7); +#endif +#ifdef GPIOG + else if (GPIOx == GPIOG) RCC->APB2ENR &= ~(1U << 8); +#endif + } +} + +/** + \fn bool GPIO_GetPortClockState (GPIO_TypeDef *GPIOx) + \brief Get GPIO port clock state + \param[in] GPIOx Pointer to GPIO peripheral + \return true - enabled + false - disabled +*/ +bool GPIO_GetPortClockState (GPIO_TypeDef *GPIOx) { + + if (GPIOx == GPIOA) { return ((RCC->APB2ENR & (1U << 2)) != 0U); } + else if (GPIOx == GPIOB) { return ((RCC->APB2ENR & (1U << 3)) != 0U); } + else if (GPIOx == GPIOC) { return ((RCC->APB2ENR & (1U << 4)) != 0U); } + else if (GPIOx == GPIOD) { return ((RCC->APB2ENR & (1U << 5)) != 0U); } + else if (GPIOx == GPIOE) { return ((RCC->APB2ENR & (1U << 6)) != 0U); } +#ifdef GPIOF + else if (GPIOx == GPIOF) { return ((RCC->APB2ENR & (1U << 7)) != 0U); } +#endif +#ifdef GPIOG + else if (GPIOx == GPIOG) { return ((RCC->APB2ENR & (1U << 8)) != 0U); } +#endif + + return false; +} + + +/** + \fn bool GPIO_PinConfigure (GPIO_TypeDef *GPIOx, + uint32_t num, + GPIO_CONF conf, + GPIO_MODE mode) + \brief Configure port pin + \param[in] GPIOx Pointer to GPIO peripheral + \param[in] num Port pin number + \param[in] mode \ref GPIO_MODE + \param[in] conf \ref GPIO_CONF + \return true - success + false - error +*/ +bool GPIO_PinConfigure(GPIO_TypeDef *GPIOx, uint32_t num, GPIO_CONF conf, + GPIO_MODE mode) { + __IO uint32_t *reg; + if (num > 15) return false; + + if (GPIO_GetPortClockState(GPIOx) == false) { + /* Enable GPIOx peripheral clock */ + GPIO_PortClock (GPIOx, true); + } + + if (mode == GPIO_MODE_IN) { + if (conf == GPIO_IN_PULL_DOWN) { + /* Enable pull down on selected input */ + GPIOx->ODR &= ~(1 << num); + } + else if (conf == GPIO_IN_PULL_UP) { + /* Enable pull up on selected input */ + conf &= ~1; + GPIOx->ODR |= (1 << num); + } + } + + if (num < 8) { + reg = &GPIOx->CRL; + } + else { + num -= 8; + reg = &GPIOx->CRH; + } + *reg &= ~(0xF << (num << 2)); + *reg |= ((conf << 2) | mode) << (num << 2); + return true; +} + + +/** + \fn void GPIO_AFConfigure (AFIO_REMAP af_type) + \brief Configure alternate functions + \param[in] af_type Alternate function remap type +*/ +void GPIO_AFConfigure (AFIO_REMAP af_type) { + uint32_t msk, val; + volatile uint32_t mapr; + + if (af_type != AFIO_UNAVAILABLE_REMAP) { + msk = (af_type >> 5) & 0x07; + val = (af_type >> 8) & 0x0F; + + if (!(RCC->APB2ENR & RCC_APB2ENR_AFIOEN)) { + /* Enable AFIO peripheral clock */ + RCC->APB2ENR |= RCC_APB2ENR_AFIOEN; + } + if (af_type & (1 << 12)) { + /* AF remap and debug I/O config register 2 */ + mapr = AFIO->MAPR2; + mapr &= ~(msk << (af_type & 0x1F)); + mapr |= (val << (af_type & 0x1F)); + AFIO->MAPR2 = mapr; + } + else { + /* AF remap and debug I/O config register */ + mapr = AFIO->MAPR; + mapr &= ~(msk << (af_type & 0x1F)); + mapr |= (val << (af_type & 0x1F)); + + /* Serial wire JTAG configuration */ + msk = (AFIO_MAPR_SWJ_CFG_VAL >> 5) & 0x07; + val = (AFIO_MAPR_SWJ_CFG_VAL >> 8) & 0x0F; + mapr &= ~(msk << (AFIO_MAPR_SWJ_CFG_VAL & 0x1F)); + mapr |= (val << (AFIO_MAPR_SWJ_CFG_VAL & 0x1F)); + + AFIO->MAPR = mapr; + } + } +} diff --git a/source/hic_hal/stm32/stm32f103xb/cmsis/GPIO_STM32F10x.h b/source/hic_hal/stm32/stm32f103xb/cmsis/GPIO_STM32F10x.h new file mode 100644 index 0000000000..2c1143f36c --- /dev/null +++ b/source/hic_hal/stm32/stm32f103xb/cmsis/GPIO_STM32F10x.h @@ -0,0 +1,257 @@ +/* ----------------------------------------------------------------------------- + * Copyright (c) 2013 Arm Limited (or its affiliates). 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 + * + * 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. + * + * + * $Date: 26. August 2013 + * $Revision: V1.2 + * + * Project: GPIO Driver definitions for ST STM32F10x + * -------------------------------------------------------------------- */ + +#ifndef __GPIO_STM32F10X_H +#define __GPIO_STM32F10X_H + +#include +#include "stm32f1xx.h" + + +#if defined (__CC_ARM) + #define __FORCE_INLINE static __forceinline +#else + #define __FORCE_INLINE __STATIC_INLINE +#endif + +/// GPIO Pin identifier +typedef struct _GPIO_PIN_ID { + GPIO_TypeDef *port; + uint8_t num; +} GPIO_PIN_ID; + +/// Port Mode +typedef enum { + GPIO_MODE_IN = 0x00, /// GPIO is input + GPIO_MODE_OUT10MHZ = 0x01, /// Max output Speed 10MHz + GPIO_MODE_OUT2MHZ = 0x02, /// Max output Speed 2MHz + GPIO_MODE_OUT50MHZ = 0x03 /// Max output Speed 50MHz +} GPIO_MODE; + +/// Port Conf +typedef enum { + GPIO_OUT_PUSH_PULL = 0x00, /// general purpose output push-pull + GPIO_OUT_OPENDRAIN = 0x01, /// general purpose output open-drain + GPIO_AF_PUSHPULL = 0x02, /// alternate function push-pull + GPIO_AF_OPENDRAIN = 0x03, /// alternate function open-drain + GPIO_IN_ANALOG = 0x00, /// input analog + GPIO_IN_FLOATING = 0x01, /// input floating + GPIO_IN_PULL_DOWN = 0x02, /// alternate function push-pull + GPIO_IN_PULL_UP = 0x03 /// alternate function pull up +} GPIO_CONF; + +/* Alternate function definition macro */ +#define AFIO_FUNC_DEF(bit, mask, val, reg) ((bit) | (mask << 5) | (val << 8) | (reg << 12)) + +/// Alternate function I/O remap +typedef enum { + /* AF remap and debug I/O config register */ + AFIO_SPI1_NO_REMAP = AFIO_FUNC_DEF (0, 1, 0, 0), + AFIO_SPI1_REMAP = AFIO_FUNC_DEF (0, 1, 1, 0), + AFIO_I2C1_NO_REMAP = AFIO_FUNC_DEF (1, 1, 0, 0), + AFIO_I2C1_REMAP = AFIO_FUNC_DEF (1, 1, 1, 0), + AFIO_USART1_NO_REMAP = AFIO_FUNC_DEF (2, 1, 0, 0), + AFIO_USART1_REMAP = AFIO_FUNC_DEF (2, 1, 1, 0), + AFIO_USART2_NO_REMAP = AFIO_FUNC_DEF (3, 1, 0, 0), + AFIO_USART2_REMAP = AFIO_FUNC_DEF (3, 1, 1, 0), + AFIO_USART3_NO_REMAP = AFIO_FUNC_DEF (4, 3, 0, 0), + AFIO_USART3_REMAP_PARTIAL = AFIO_FUNC_DEF (4, 3, 1, 0), + AFIO_USART3_REMAP_FULL = AFIO_FUNC_DEF (4, 3, 3, 0), + AFIO_TIM1_NO_REMAP = AFIO_FUNC_DEF (6, 3, 0, 0), + AFIO_TIM1_REMAP_PARTIAL = AFIO_FUNC_DEF (6, 3, 1, 0), + AFIO_TIM1_REMAP_FULL = AFIO_FUNC_DEF (6, 3, 3, 0), + AFIO_TIM2_NO_REMAP = AFIO_FUNC_DEF (8, 3, 0, 0), + AFIO_TIM2_REMAP_PARTIAL_1 = AFIO_FUNC_DEF (8, 3, 1, 0), + AFIO_TIM2_REMAP_PARTIAL_2 = AFIO_FUNC_DEF (8, 3, 2, 0), + AFIO_TIM2_REMAP_FULL = AFIO_FUNC_DEF (8, 3, 3, 0), + AFIO_TIM3_NO_REMAP = AFIO_FUNC_DEF (10, 3, 0, 0), + AFIO_TIM3_REMAP_PARTIAL = AFIO_FUNC_DEF (10, 3, 2, 0), + AFIO_TIM3_REMAP_FULL = AFIO_FUNC_DEF (10, 3, 3, 0), + AFIO_TIM4_NO_REMAP = AFIO_FUNC_DEF (12, 1, 0, 0), + AFIO_TIM4_REMAP = AFIO_FUNC_DEF (12, 1, 1, 0), + AFIO_CAN_PA11_PA12 = AFIO_FUNC_DEF (13, 3, 0, 0), + AFIO_CAN_PB8_PB9 = AFIO_FUNC_DEF (13, 3, 2, 0), + AFIO_CAN_PD0_PD1 = AFIO_FUNC_DEF (13, 3, 3, 0), + AFIO_PD01_NO_REMAP = AFIO_FUNC_DEF (15, 1, 0, 0), + AFIO_PD01_REMAP = AFIO_FUNC_DEF (15, 1, 1, 0), + AFIO_TIM5CH4_NO_REMAP = AFIO_FUNC_DEF (16, 1, 0, 0), + AFIO_TIM5CH4_REMAP = AFIO_FUNC_DEF (16, 1, 1, 0), + AFIO_ADC1_ETRGINJ_NO_REMAP = AFIO_FUNC_DEF (17, 1, 0, 0), + AFIO_ADC1_ETRGINJ_REMAP = AFIO_FUNC_DEF (17, 1, 1, 0), + AFIO_ADC1_ETRGREG_NO_REMAP = AFIO_FUNC_DEF (18, 1, 0, 0), + AFIO_ADC1_ETRGREG_REMAP = AFIO_FUNC_DEF (18, 1, 1, 0), + AFIO_ADC2_ETRGINJ_NO_REMAP = AFIO_FUNC_DEF (19, 1, 0, 0), + AFIO_ADC2_ETRGINJ_REMAP = AFIO_FUNC_DEF (19, 1, 1, 0), + AFIO_ADC2_ETRGREG_NO_REMAP = AFIO_FUNC_DEF (20, 1, 0, 0), + AFIO_ADC2_ETRGREG_REMAP = AFIO_FUNC_DEF (20, 1, 1, 0), +#if defined(STM32F10X_CL) + AFIO_ETH_NO_REMAP = AFIO_FUNC_DEF (21, 1, 0, 0), + AFIO_ETH_REMAP = AFIO_FUNC_DEF (21, 1, 1, 0), + AFIO_CAN2_NO_REMAP = AFIO_FUNC_DEF (22, 1, 0, 0), + AFIO_CAN2_REMAP = AFIO_FUNC_DEF (22, 1, 1, 0), + AFIO_ETH_MII_SEL = AFIO_FUNC_DEF (23, 1, 0, 0), + AFIO_ETH_RMII_SEL = AFIO_FUNC_DEF (23, 1, 1, 0), +#endif + AFIO_SWJ_FULL = AFIO_FUNC_DEF (24, 7, 0, 0), + AFIO_SWJ_FULL_NO_NJTRST = AFIO_FUNC_DEF (24, 7, 1, 0), + AFIO_SWJ_JTAG_NO_SW = AFIO_FUNC_DEF (24, 7, 2, 0), + AFIO_SWJ_NO_JTAG_NO_SW = AFIO_FUNC_DEF (24, 7, 4, 0), +#if defined(STM32F10X_CL) + AFIO_SPI3_NO_REMAP = AFIO_FUNC_DEF (28, 1, 0, 0), + AFIO_SPI3_REMAP = AFIO_FUNC_DEF (28, 1, 1, 0), + AFIO_TIM2ITR_NO_REMAP = AFIO_FUNC_DEF (29, 1, 0, 0), + AFIO_TIM2ITR_REMAP = AFIO_FUNC_DEF (29, 1, 1, 0), + AFIO_PTP_PPS_NO_REMAP = AFIO_FUNC_DEF (30, 1, 0, 0), + AFIO_PTP_PPS_REMAP = AFIO_FUNC_DEF (30, 1, 1, 0), +#endif + + /* AF remap and debug I/O config register 2 */ + AFIO_TIM15_NO_REMAP = AFIO_FUNC_DEF (0, 1, 0, 1), + AFIO_TIM15_REMAP = AFIO_FUNC_DEF (0, 1, 1, 1), + AFIO_TIM16_NO_REMAP = AFIO_FUNC_DEF (1, 1, 0, 1), + AFIO_TIM16_REMAP = AFIO_FUNC_DEF (1, 1, 1, 1), + AFIO_TIM17_NO_REMAP = AFIO_FUNC_DEF (2, 1, 0, 1), + AFIO_TIM17_REMAP = AFIO_FUNC_DEF (2, 1, 1, 1), + AFIO_CEC_NO_REMAP = AFIO_FUNC_DEF (3, 1, 0, 1), + AFIO_CEC_REMAP = AFIO_FUNC_DEF (3, 1, 1, 1), + AFIO_TIM1_DMA_NO_REMAP = AFIO_FUNC_DEF (4, 1, 0, 1), + AFIO_TIM1_DMA_REMAP = AFIO_FUNC_DEF (4, 1, 1, 1), + + AFIO_TIM9_NO_REMAP = AFIO_FUNC_DEF (5, 1, 0, 1), + AFIO_TIM9_REMAP = AFIO_FUNC_DEF (5, 1, 1, 1), + AFIO_TIM10_NO_REMAP = AFIO_FUNC_DEF (6, 1, 0, 1), + AFIO_TIM10_REMAP = AFIO_FUNC_DEF (6, 1, 1, 1), + AFIO_TIM11_NO_REMAP = AFIO_FUNC_DEF (7, 1, 0, 1), + AFIO_TIM11_REMAP = AFIO_FUNC_DEF (7, 1, 1, 1), + AFIO_TIM13_NO_REMAP = AFIO_FUNC_DEF (8, 1, 0, 1), + AFIO_TIM13_REMAP = AFIO_FUNC_DEF (8, 1, 0, 1), + AFIO_TIM14_NO_REMAP = AFIO_FUNC_DEF (9, 1, 0, 1), + AFIO_TIM14_REMAP = AFIO_FUNC_DEF (9, 1, 1, 1), + AFIO_FSMC_NADV_NO_REMAP = AFIO_FUNC_DEF (10, 1, 0, 1), + AFIO_FSMC_NADV_REMAP = AFIO_FUNC_DEF (10, 1, 1, 1), + + AFIO_TIM67_DAC_DMA_NO_REMAP = AFIO_FUNC_DEF(11, 1, 0, 1), + AFIO_TIM67_DAC_DMA_REMAP = AFIO_FUNC_DEF (11, 1, 1, 1), + AFIO_TIM12_NO_REMAP = AFIO_FUNC_DEF (12, 1, 0, 1), + AFIO_TIM12_REMAP = AFIO_FUNC_DEF (12, 1, 1, 1), + AFIO_MISC_NO_REMAP = AFIO_FUNC_DEF (13, 1, 0, 1), + AFIO_MISC_REMAP = AFIO_FUNC_DEF (13, 1, 1, 1), + + /* Reserved value */ + AFIO_UNAVAILABLE_REMAP = AFIO_FUNC_DEF (0, 0, 0, 0) +} AFIO_REMAP; + + +/** + \fn void GPIO_PortClock (GPIO_TypeDef *GPIOx, bool en) + \brief Port Clock Control + \param[in] GPIOx Pointer to GPIO peripheral + \param[in] enable Enable or disable clock +*/ +extern void GPIO_PortClock (GPIO_TypeDef *GPIOx, bool enable); + +/** + \fn bool GPIO_GetPortClockState (GPIO_TypeDef *GPIOx) + \brief Get GPIO port clock state + \param[in] GPIOx Pointer to GPIO peripheral + \return true - enabled + false - disabled +*/ +extern bool GPIO_GetPortClockState (GPIO_TypeDef *GPIOx); + +/** + \fn bool GPIO_PinConfigure (GPIO_TypeDef *GPIOx, + uint32_t num, + GPIO_CONF conf, + GPIO_MODE mode) + \brief Configure port pin + \param[in] GPIOx Pointer to GPIO peripheral + \param[in] num Port pin number + \param[in] mode \ref GPIO_MODE + \param[in] conf \ref GPIO_CONF + \return true - success + false - error +*/ +bool GPIO_PinConfigure(GPIO_TypeDef *GPIOx, + uint32_t num, + GPIO_CONF conf, + GPIO_MODE mode); + +/** + \fn void GPIO_PinWrite (GPIO_TypeDef *GPIOx, uint32_t num, uint32_t val) + \brief Write port pin + \param[in] GPIOx Pointer to GPIO peripheral + \param[in] num Port pin number + \param[in] val Port pin value (0 or 1) +*/ +__FORCE_INLINE void GPIO_PinWrite (GPIO_TypeDef *GPIOx, uint32_t num, uint32_t val) { + if (val & 1) { + GPIOx->BSRR = (1UL << num); // set + } else { + GPIOx->BSRR = (1UL << (num + 16)); // clr + } +} + +/** + \fn uint32_t GPIO_PinRead (GPIO_TypeDef *GPIOx, uint32_t num) + \brief Read port pin + \param[in] GPIOx Pointer to GPIO peripheral + \param[in] num Port pin number + \return pin value (0 or 1) +*/ +__FORCE_INLINE uint32_t GPIO_PinRead (GPIO_TypeDef *GPIOx, uint32_t num) { + return ((GPIOx->IDR >> num) & 1); +} + +/** + \fn void GPIO_PortWrite (GPIO_TypeDef *GPIOx, uint16_t mask, uint16_t val) + \brief Write port pins + \param[in] GPIOx Pointer to GPIO peripheral + \param[in] mask Selected pins + \param[in] val Pin values +*/ +__FORCE_INLINE void GPIO_PortWrite (GPIO_TypeDef *GPIOx, uint16_t mask, uint16_t val) { + GPIOx->ODR = (GPIOx->ODR & ~mask) | val; +} + +/** + \fn uint16_t GPIO_PortRead (GPIO_TypeDef *GPIOx) + \brief Read port pins + \param[in] GPIOx Pointer to GPIO peripheral + \return port pin inputs +*/ +__FORCE_INLINE uint16_t GPIO_PortRead (GPIO_TypeDef *GPIOx) { + return (GPIOx->IDR); +} + +/** + \fn void GPIO_AFConfigure (AFIO_REMAP af_type) + \brief Configure alternate functions + \param[in] af_type Alternate function remap type +*/ +void GPIO_AFConfigure (AFIO_REMAP af_type); + + +#endif /* __GPIO_STM32F10X_H */ diff --git a/source/hic_hal/stm32/stm32f103xb/cmsis/USART_STM32F10x.c b/source/hic_hal/stm32/stm32f103xb/cmsis/USART_STM32F10x.c new file mode 100644 index 0000000000..d7e4955b0b --- /dev/null +++ b/source/hic_hal/stm32/stm32f103xb/cmsis/USART_STM32F10x.c @@ -0,0 +1,2347 @@ +/* ----------------------------------------------------------------------------- + * Copyright (c) 2013-2017 Arm Limited (or its affiliates). 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 + * + * 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. + * + * + * $Date: 11. July 2017 + * $Revision: V2.3 + * + * Driver: Driver_USART1, Driver_USART2, Driver_USART3, + * Driver_USART4, Driver_USART5 + * Configured: via RTE_Device.h or MX_Device.h configuration file + * Project: USART Driver for ST STM32F1xx + * -------------------------------------------------------------------------- + * Use the following configuration settings in the middleware component + * to connect to this driver. + * + * Configuration Setting Value UART Interface + * --------------------- ----- -------------- + * Connect to hardware via Driver_USART# = 1 use USART1 + * Connect to hardware via Driver_USART# = 2 use USART2 + * Connect to hardware via Driver_USART# = 3 use USART3 + * Connect to hardware via Driver_USART# = 4 use UART4 + * Connect to hardware via Driver_USART# = 5 use UART5 + * -------------------------------------------------------------------------- */ + +/* History: + * Version 2.3 + * Corrected condition for ARM_USART_SET_IRDA_PULSE control + * Version 2.2 + * Corrected CTS handling and added Signal CTS change event. + * Version 2.1 + * Corrected USART Peripheral Reset and Clock enable/disable + * - Added checking if peripheral is available on selected device + * Version 2.0 + * Updated to CMSIS Driver API V2.02 + * Version 1.01 + * Based on API V1.10 (namespace prefix ARM_ added) + * Version 1.00 + * Initial release + */ + +#include "USART_STM32F10x.h" + +#define ARM_USART_DRV_VERSION ARM_DRIVER_VERSION_MAJOR_MINOR(2,3) + +// Driver Version +static const ARM_DRIVER_VERSION usart_driver_version = { ARM_USART_API_VERSION, ARM_USART_DRV_VERSION }; + +// USART1 +#ifdef MX_USART1 + +// USART1 Run-Time Information +static USART_INFO USART1_Info = {0}; +static USART_TRANSFER_INFO USART1_TransferInfo = {0}; + +#ifdef MX_USART1_TX_Pin + static USART_PIN USART1_tx = {MX_USART1_TX_GPIOx, MX_USART1_TX_GPIO_Pin }; +#endif +#ifdef MX_USART1_RX_Pin + static USART_PIN USART1_rx = {MX_USART1_RX_GPIOx, MX_USART1_RX_GPIO_Pin }; +#endif +#ifdef MX_USART1_CK_Pin + static USART_PIN USART1_ck = {MX_USART1_CK_GPIOx, MX_USART1_CK_GPIO_Pin }; +#endif +#ifdef MX_USART1_RTS_Pin + static USART_PIN USART1_rts = {MX_USART1_RTS_GPIOx, MX_USART1_RTS_GPIO_Pin}; +#endif +#ifdef MX_USART1_CTS_Pin + static USART_PIN USART1_cts = {MX_USART1_CTS_GPIOx, MX_USART1_CTS_GPIO_Pin}; +#endif + +#ifdef MX_USART1_TX_DMA_Instance + static USART_DMA USART1_DMA_Tx = { + MX_USART1_TX_DMA_Instance, + MX_USART1_TX_DMA_Number, + MX_USART1_TX_DMA_Channel, + MX_USART1_TX_DMA_Priority + }; +#endif +#ifdef MX_USART1_RX_DMA_Instance + static USART_DMA USART1_DMA_Rx = { + MX_USART1_RX_DMA_Instance, + MX_USART1_RX_DMA_Number, + MX_USART1_RX_DMA_Channel, + MX_USART1_RX_DMA_Priority + }; +#endif + +// USART1 Resources +static const USART_RESOURCES USART1_Resources = { + { // Capabilities + 1, // supports UART (Asynchronous) mode +#ifdef MX_USART1_CK_Pin + 1, // supports Synchronous Master mode +#else + 0, // supports Synchronous Master mode +#endif + 0, // supports Synchronous Slave mode + 1, // supports UART Single-wire mode + 1, // supports UART IrDA mode + 1, // supports UART Smart Card mode + 0, // Smart Card Clock generator +#ifdef MX_USART1_RTS_Pin + 1, // RTS Flow Control available +#else + 0, // RTS Flow Control available +#endif +#ifdef MX_USART1_CTS_Pin + 1, // CTS Flow Control available +#else + 0, // CTS Flow Control available +#endif + 1, // Transmit completed event: \ref ARM_USART_EVENT_TX_COMPLETE + 1, // Signal receive character timeout event: \ref ARM_USART_EVENT_RX_TIMEOUT +#ifdef MX_USART1_RTS_Pin + 1, // RTS Line: 0=not available, 1=available +#else + 0, // RTS Line: 0=not available, 1=available +#endif +#ifdef MX_USART1_CTS_Pin + 1, // CTS Line: 0=not available, 1=available +#else + 0, // CTS Line: 0=not available, 1=available +#endif + 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 +#ifdef MX_USART1_CTS_Pin + 1, // Signal CTS change event: \ref ARM_USART_EVENT_CTS +#else + 0, // Signal CTS change event: \ref ARM_USART_EVENT_CTS +#endif + 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 + }, + + USART1, + RTE_PCLK2, + + // PINS + { +#ifdef MX_USART1_TX_Pin + &USART1_tx, +#else + NULL, +#endif +#ifdef MX_USART1_RX_Pin + &USART1_rx, +#else + NULL, +#endif +#ifdef MX_USART1_CK_Pin + &USART1_ck, +#else + NULL, +#endif +#ifdef MX_USART1_RTS_Pin + &USART1_rts, +#else + NULL, +#endif +#ifdef MX_USART1_CTS_Pin + &USART1_cts, +#else + NULL, +#endif + MX_USART1_REMAP_DEF, + MX_USART1_REMAP, + }, + + USART1_IRQn, + +#ifdef MX_USART1_TX_DMA_Instance + &USART1_DMA_Tx, +#else + NULL, +#endif +#ifdef MX_USART1_RX_DMA_Instance + &USART1_DMA_Rx, +#else + NULL, +#endif + + &USART1_Info, + &USART1_TransferInfo +}; +#endif + +// USART2 +#ifdef MX_USART2 + +// USART2 Run-Time Information +static USART_INFO USART2_Info = {0}; +static USART_TRANSFER_INFO USART2_TransferInfo = {0}; + +#ifdef MX_USART2_TX_Pin + static USART_PIN USART2_tx = {MX_USART2_TX_GPIOx, MX_USART2_TX_GPIO_Pin }; +#endif +#ifdef MX_USART2_RX_Pin + static USART_PIN USART2_rx = {MX_USART2_RX_GPIOx, MX_USART2_RX_GPIO_Pin }; +#endif +#ifdef MX_USART2_CK_Pin + static USART_PIN USART2_ck = {MX_USART2_CK_GPIOx, MX_USART2_CK_GPIO_Pin }; +#endif +#ifdef MX_USART2_RTS_Pin + static USART_PIN USART2_rts = {MX_USART2_RTS_GPIOx, MX_USART2_RTS_GPIO_Pin}; +#endif +#ifdef MX_USART2_CTS_Pin + static USART_PIN USART2_cts = {MX_USART2_CTS_GPIOx, MX_USART2_CTS_GPIO_Pin}; +#endif + +#ifdef MX_USART2_TX_DMA_Instance + static USART_DMA USART2_DMA_Tx = { + MX_USART2_TX_DMA_Instance, + MX_USART2_TX_DMA_Number, + MX_USART2_TX_DMA_Channel, + MX_USART2_TX_DMA_Priority + }; +#endif +#ifdef MX_USART2_RX_DMA_Instance + static USART_DMA USART2_DMA_Rx = { + MX_USART2_RX_DMA_Instance, + MX_USART2_RX_DMA_Number, + MX_USART2_RX_DMA_Channel, + MX_USART2_RX_DMA_Priority + }; +#endif + +// USART2 Resources +static const USART_RESOURCES USART2_Resources = { + { // Capabilities + 1, // supports UART (Asynchronous) mode +#ifdef MX_USART2_CK_Pin + 1, // supports Synchronous Master mode +#else + 0, // supports Synchronous Master mode +#endif + 0, // supports Synchronous Slave mode + 1, // supports UART Single-wire mode + 1, // supports UART IrDA mode + 1, // supports UART Smart Card mode + 0, // Smart Card Clock generator +#ifdef MX_USART2_RTS_Pin + 1, // RTS Flow Control available +#else + 0, // RTS Flow Control available +#endif +#ifdef MX_USART2_CTS_Pin + 1, // CTS Flow Control available +#else + 0, // CTS Flow Control available +#endif + 1, // Transmit completed event: \ref ARM_USART_EVENT_TX_COMPLETE + 1, // Signal receive character timeout event: \ref ARM_USART_EVENT_RX_TIMEOUT +#ifdef MX_USART2_RTS_Pin + 1, // RTS Line: 0=not available, 1=available +#else + 0, // RTS Line: 0=not available, 1=available +#endif +#ifdef MX_USART2_CTS_Pin + 1, // CTS Line: 0=not available, 1=available +#else + 0, // CTS Line: 0=not available, 1=available +#endif + 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 +#ifdef MX_USART2_CTS_Pin + 1, // Signal CTS change event: \ref ARM_USART_EVENT_CTS +#else + 0, // Signal CTS change event: \ref ARM_USART_EVENT_CTS +#endif + 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 + }, + + USART2, + RTE_PCLK1, + + // PINS + { +#ifdef MX_USART2_TX_Pin + &USART2_tx, +#else + NULL, +#endif +#ifdef MX_USART2_RX_Pin + &USART2_rx, +#else + NULL, +#endif +#ifdef MX_USART2_CK_Pin + &USART2_ck, +#else + NULL, +#endif +#ifdef MX_USART2_RTS_Pin + &USART2_rts, +#else + NULL, +#endif +#ifdef MX_USART2_CTS_Pin + &USART2_cts, +#else + NULL, +#endif + MX_USART2_REMAP_DEF, + MX_USART2_REMAP, + }, + + USART2_IRQn, + +#ifdef MX_USART2_TX_DMA_Instance + &USART2_DMA_Tx, +#else + NULL, +#endif +#ifdef MX_USART2_RX_DMA_Instance + &USART2_DMA_Rx, +#else + NULL, +#endif + + &USART2_Info, + &USART2_TransferInfo +}; +#endif + +// USART3 +#ifdef MX_USART3 + +// USART3 Run-Time Information +static USART_INFO USART3_Info = {0}; +static USART_TRANSFER_INFO USART3_TransferInfo = {0}; + +#ifdef MX_USART3_TX_Pin + static USART_PIN USART3_tx = {MX_USART3_TX_GPIOx, MX_USART3_TX_GPIO_Pin }; +#endif +#ifdef MX_USART3_RX_Pin + static USART_PIN USART3_rx = {MX_USART3_RX_GPIOx, MX_USART3_RX_GPIO_Pin }; +#endif +#ifdef MX_USART3_CK_Pin + static USART_PIN USART3_ck = {MX_USART3_CK_GPIOx, MX_USART3_CK_GPIO_Pin }; +#endif +#ifdef MX_USART3_RTS_Pin + static USART_PIN USART3_rts = {MX_USART3_RTS_GPIOx, MX_USART3_RTS_GPIO_Pin}; +#endif +#ifdef MX_USART3_CTS_Pin + static USART_PIN USART3_cts = {MX_USART3_CTS_GPIOx, MX_USART3_CTS_GPIO_Pin}; +#endif + +#ifdef MX_USART3_TX_DMA_Instance + static USART_DMA USART3_DMA_Tx = { + MX_USART3_TX_DMA_Instance, + MX_USART3_TX_DMA_Number, + MX_USART3_TX_DMA_Channel, + MX_USART3_TX_DMA_Priority + }; +#endif +#ifdef MX_USART3_RX_DMA_Instance + static USART_DMA USART3_DMA_Rx = { + MX_USART3_RX_DMA_Instance, + MX_USART3_RX_DMA_Number, + MX_USART3_RX_DMA_Channel, + MX_USART3_RX_DMA_Priority + }; +#endif + +// USART3 Resources +static const USART_RESOURCES USART3_Resources = { + { // Capabilities + 1, // supports UART (Asynchronous) mode +#ifdef MX_USART3_CK_Pin + 1, // supports Synchronous Master mode +#else + 0, // supports Synchronous Master mode +#endif + 0, // supports Synchronous Slave mode + 1, // supports UART Single-wire mode + 1, // supports UART IrDA mode + 1, // supports UART Smart Card mode + 0, // Smart Card Clock generator +#ifdef MX_USART3_RTS_Pin + 1, // RTS Flow Control available +#else + 0, // RTS Flow Control available +#endif +#ifdef MX_USART3_CTS_Pin + 1, // CTS Flow Control available +#else + 0, // CTS Flow Control available +#endif + 1, // Transmit completed event: \ref ARM_USART_EVENT_TX_COMPLETE + 1, // Signal receive character timeout event: \ref ARM_USART_EVENT_RX_TIMEOUT +#ifdef MX_USART3_RTS_Pin + 1, // RTS Line: 0=not available, 1=available +#else + 0, // RTS Line: 0=not available, 1=available +#endif +#ifdef MX_USART3_CTS_Pin + 1, // CTS Line: 0=not available, 1=available +#else + 0, // CTS Line: 0=not available, 1=available +#endif + 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 +#ifdef MX_USART3_CTS_Pin + 1, // Signal CTS change event: \ref ARM_USART_EVENT_CTS +#else + 0, // Signal CTS change event: \ref ARM_USART_EVENT_CTS +#endif + 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 + }, + + USART3, + RTE_PCLK1, + + // PINS + { +#ifdef MX_USART3_TX_Pin + &USART3_tx, +#else + NULL, +#endif +#ifdef MX_USART3_RX_Pin + &USART3_rx, +#else + NULL, +#endif +#ifdef MX_USART3_CK_Pin + &USART3_ck, +#else + NULL, +#endif +#ifdef MX_USART3_RTS_Pin + &USART3_rts, +#else + NULL, +#endif +#ifdef MX_USART3_CTS_Pin + &USART3_cts, +#else + NULL, +#endif + MX_USART3_REMAP_DEF, + MX_USART3_REMAP, + }, + + USART3_IRQn, + +#ifdef MX_USART3_TX_DMA_Instance + &USART3_DMA_Tx, +#else + NULL, +#endif +#ifdef MX_USART3_RX_DMA_Instance + &USART3_DMA_Rx, +#else + NULL, +#endif + + &USART3_Info, + &USART3_TransferInfo +}; +#endif + +// UART4 +#ifdef MX_UART4 + +// UART4 Run-Time Information +static USART_INFO UART4_Info = {0}; +static USART_TRANSFER_INFO UART4_TransferInfo = {0}; + +#ifdef MX_UART4_TX_Pin + static USART_PIN UART4_tx = {MX_UART4_TX_GPIOx, MX_UART4_TX_GPIO_Pin}; +#endif +#ifdef MX_UART4_RX_Pin + static USART_PIN UART4_rx = {MX_UART4_RX_GPIOx, MX_UART4_RX_GPIO_Pin}; +#endif + +#ifdef MX_UART4_TX_DMA_Instance + static USART_DMA UART4_DMA_Tx = { + MX_UART4_TX_DMA_Instance, + MX_UART4_TX_DMA_Number, + MX_UART4_TX_DMA_Channel, + MX_UART4_TX_DMA_Priority + }; +#endif +#ifdef MX_UART4_RX_DMA_Instance + static USART_DMA UART4_DMA_Rx = { + MX_UART4_RX_DMA_Instance, + MX_UART4_RX_DMA_Number, + MX_UART4_RX_DMA_Channel, + MX_UART4_RX_DMA_Priority + }; +#endif + +// UART4 Resources +static const USART_RESOURCES USART4_Resources = { + { // Capabilities + 1, // supports UART (Asynchronous) mode + 0, // supports Synchronous Master mode + 0, // supports Synchronous Slave mode + 1, // supports UART Single-wire mode + 1, // supports UART IrDA mode + 0, // supports UART Smart Card mode + 0, // Smart Card Clock generator + 0, // RTS Flow Control available + 0, // CTS Flow Control available + 1, // Transmit completed event: \ref ARM_USART_EVENT_TX_COMPLETE + 1, // 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 + }, + + UART4, + RTE_PCLK1, + + // PINS + { +#ifdef MX_UART4_TX_Pin + &UART4_tx, +#else + NULL, +#endif +#ifdef MX_UART4_RX_Pin + &UART4_rx, +#else + NULL, +#endif + NULL, + NULL, + NULL, + MX_UART4_REMAP_DEF, + MX_UART4_REMAP, + }, + + UART4_IRQn, + +#ifdef MX_UART4_TX_DMA_Instance + &UART4_DMA_Tx, +#else + NULL, +#endif +#ifdef MX_UART4_RX_DMA_Instance + &UART4_DMA_Rx, +#else + NULL, +#endif + + &UART4_Info, + &UART4_TransferInfo +}; +#endif + +// UART5 +#ifdef MX_UART5 + +// UART5 Run-Time Information +static USART_INFO UART5_Info = {0}; +static USART_TRANSFER_INFO UART5_TransferInfo = {0}; + +#ifdef MX_UART5_TX_Pin + static USART_PIN UART5_tx = {MX_UART5_TX_GPIOx, MX_UART5_TX_GPIO_Pin}; +#endif +#ifdef MX_UART5_RX_Pin + static USART_PIN UART5_rx = {MX_UART5_RX_GPIOx, MX_UART5_RX_GPIO_Pin}; +#endif + +#ifdef MX_UART5_TX_DMA_Instance + static USART_DMA UART5_DMA_Tx = { + MX_UART5_TX_DMA_Instance, + MX_UART5_TX_DMA_Number, + MX_UART5_TX_DMA_Channel, + MX_UART5_TX_DMA_Priority + }; +#endif +#ifdef MX_UART5_RX_DMA_Instance + static USART_DMA UART5_DMA_Rx = { + MX_UART5_RX_DMA_Instance, + MX_UART5_RX_DMA_Number, + MX_UART5_RX_DMA_Channel, + MX_UART5_RX_DMA_Priority + }; +#endif + +// UART5 Resources +static const USART_RESOURCES USART5_Resources = { + { // Capabilities + 1, // supports UART (Asynchronous) mode + 0, // supports Synchronous Master mode + 0, // supports Synchronous Slave mode + 1, // supports UART Single-wire mode + 1, // supports UART IrDA mode + 0, // supports UART Smart Card mode + 0, // Smart Card Clock generator + 0, // RTS Flow Control available + 0, // CTS Flow Control available + 1, // Transmit completed event: \ref ARM_USART_EVENT_TX_COMPLETE + 1, // 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 + }, + + UART5, + RTE_PCLK1, + + // PINS + { +#ifdef MX_UART5_TX_Pin + &UART5_tx, +#else + NULL, +#endif +#ifdef MX_UART5_RX_Pin + &UART5_rx, +#else + NULL, +#endif + NULL, + NULL, + NULL, + MX_UART5_REMAP_DEF, + MX_UART5_REMAP, + }, + + UART5_IRQn, + +#ifdef MX_UART5_TX_DMA_Instance + &UART5_DMA_Tx, +#else + NULL, +#endif +#ifdef MX_UART5_RX_DMA_Instance + &UART5_DMA_Rx, +#else + NULL, +#endif + + &UART5_Info, + &UART5_TransferInfo +}; +#endif + +// Auxiliary functions +/** + \fn void USART_PeripheralReset (const USART_TypeDef *usart) + \brief USART Reset +*/ +static void USART_PeripheralReset (const USART_TypeDef *usart) { + + if (usart == USART1) { RCC->APB2RSTR |= RCC_APB2RSTR_USART1RST; } + if (usart == USART2) { RCC->APB1RSTR |= RCC_APB1RSTR_USART2RST; } +#if !defined (STM32F10X_LD) && !defined (STM32F10X_LD_VL) + if (usart == USART3) { RCC->APB1RSTR |= RCC_APB1RSTR_USART3RST; } +#endif +#if defined(STM32F10X_HD) || defined(STM32F10X_CL) || defined(STM32F10X_XL) || defined(STM32F10X_HD_VL) + if (usart == UART4) { RCC->APB1RSTR |= RCC_APB1RSTR_UART4RST; } + if (usart == UART5) { RCC->APB1RSTR |= RCC_APB1RSTR_UART5RST; } +#endif + + __NOP(); __NOP(); __NOP(); __NOP(); + + if (usart == USART1) { RCC->APB2RSTR &= ~RCC_APB2RSTR_USART1RST; } + if (usart == USART2) { RCC->APB1RSTR &= ~RCC_APB1RSTR_USART2RST; } +#if !defined (STM32F10X_LD) && !defined (STM32F10X_LD_VL) + if (usart == USART3) { RCC->APB1RSTR &= ~RCC_APB1RSTR_USART3RST; } +#endif +#if defined(STM32F10X_HD) || defined(STM32F10X_CL) || defined(STM32F10X_XL) || defined(STM32F10X_HD_VL) + if (usart == UART4) { RCC->APB1RSTR &= ~RCC_APB1RSTR_UART4RST; } + if (usart == UART5) { RCC->APB1RSTR &= ~RCC_APB1RSTR_UART5RST; } +#endif +} + +// Function prototypes +void USART_IRQHandler (const USART_RESOURCES *usart); +#ifdef __USART_DMA_TX +void USART_TX_DMA_Complete(const USART_RESOURCES *usart); +#endif +#ifdef __USART_DMA_RX +void USART_RX_DMA_Complete(const USART_RESOURCES *usart); +#endif +static int32_t USART_Receive ( void *data, + uint32_t num, + const USART_RESOURCES *usart); + +// USART Driver functions + +/** + \fn ARM_DRIVER_VERSION USARTx_GetVersion (void) + \brief Get driver version. + \return \ref ARM_DRIVER_VERSION +*/ +static ARM_DRIVER_VERSION USARTx_GetVersion (void) { + return usart_driver_version; +} + +/** + \fn ARM_USART_CAPABILITIES USART_GetCapabilities (const USART_RESOURCES *usart) + \brief Get driver capabilities + \param[in] usart Pointer to USART resources + \return \ref ARM_USART_CAPABILITIES +*/ +static ARM_USART_CAPABILITIES USART_GetCapabilities (const USART_RESOURCES *usart) { + return usart->capabilities; +} + +/** + \fn int32_t USART_Initialize ( ARM_USART_SignalEvent_t cb_event + const USART_RESOURCES *usart) + \brief Initialize USART Interface. + \param[in] cb_event Pointer to \ref ARM_USART_SignalEvent + \param[in] usart Pointer to USART resources + \return \ref execution_status +*/ +static int32_t USART_Initialize ( ARM_USART_SignalEvent_t cb_event, + const USART_RESOURCES *usart) { + + if (usart->info->flags & USART_FLAG_INITIALIZED) { + // Driver is already initialized + return ARM_DRIVER_OK; + } + + // Initialize USART Run-time Resources + usart->info->cb_event = cb_event; + + usart->info->status.tx_busy = 0U; + usart->info->status.rx_busy = 0U; + usart->info->status.tx_underflow = 0U; + usart->info->status.rx_overflow = 0U; + usart->info->status.rx_break = 0U; + usart->info->status.rx_framing_error = 0U; + usart->info->status.rx_parity_error = 0U; + + usart->info->mode = 0U; + usart->xfer->send_active = 0U; + + // Clear transfer information + memset(usart->xfer, 0, sizeof(USART_TRANSFER_INFO)); + + // Setup pin remap + GPIO_AFConfigure(usart->io.afio); + + // Enable TX pin port clock + if (usart->io.tx) { + GPIO_PortClock (usart->io.tx->port, true); + } + + // Enable RX pin port clock + if (usart->io.rx) { + GPIO_PortClock (usart->io.rx->port, true); + } + + // Enable CK pin port clock + if (usart->io.ck) { + GPIO_PortClock (usart->io.ck->port, true); + } + + // Enable RTS pin port clock + if (usart->io.rts) { + GPIO_PortClock (usart->io.rts->port, true); + } + + // Enable CTS pin port clock + if (usart->io.cts) { + GPIO_PortClock (usart->io.cts->port, true); + } + + usart->info->flags = USART_FLAG_INITIALIZED; + + return ARM_DRIVER_OK; +} + +/** + \fn int32_t USART_Uninitialize (const USART_RESOURCES *usart) + \brief De-initialize USART Interface. + \param[in] usart Pointer to USART resources + \return \ref execution_status +*/ +static int32_t USART_Uninitialize (const USART_RESOURCES *usart) { + + // Unconfigure USART pins + if (usart->io.tx) GPIO_PinConfigure(usart->io.tx->port, usart->io.tx->pin, GPIO_IN_ANALOG, GPIO_MODE_IN); + if (usart->io.rx) GPIO_PinConfigure(usart->io.rx->port, usart->io.rx->pin, GPIO_IN_ANALOG, GPIO_MODE_IN); + if (usart->io.ck) GPIO_PinConfigure(usart->io.ck->port, usart->io.ck->pin, GPIO_IN_ANALOG, GPIO_MODE_IN); + if (usart->io.rts) GPIO_PinConfigure(usart->io.rts->port, usart->io.rts->pin, GPIO_IN_ANALOG, GPIO_MODE_IN); + if (usart->io.cts) GPIO_PinConfigure(usart->io.cts->port, usart->io.cts->pin, GPIO_IN_ANALOG, GPIO_MODE_IN); + + // Unconfigure pin remap + GPIO_AFConfigure(usart->io.afio_def); + + // Reset USART status flags + usart->info->flags = 0U; + + return ARM_DRIVER_OK; +} + +/** + \fn int32_t USART_PowerControl (ARM_POWER_STATE state) + \brief Control USART Interface Power. + \param[in] state Power state + \param[in] usart Pointer to USART resources + \return \ref execution_status +*/ +static int32_t USART_PowerControl ( ARM_POWER_STATE state, + const USART_RESOURCES *usart) { + + switch (state) { + case ARM_POWER_OFF: + // Peripheral reset + USART_PeripheralReset (usart->reg); + + NVIC_DisableIRQ (usart->irq_num); + +#ifdef __USART_DMA + if (usart->dma_rx) { + // Deinitialize DMA + DMA_ChannelUninitialize (usart->dma_rx->dma_num, usart->dma_rx->ch_num); + } + + if (usart->dma_tx) { + // Deinitialize DMA + DMA_ChannelUninitialize (usart->dma_tx->dma_num, usart->dma_tx->ch_num); + } +#endif + + // Disable USART clock + if (usart->reg == USART1) { RCC->APB2ENR &= ~RCC_APB2ENR_USART1EN; } + if (usart->reg == USART2) { RCC->APB1ENR &= ~RCC_APB1ENR_USART2EN; } +#if !defined (STM32F10X_LD) && !defined (STM32F10X_LD_VL) + if (usart->reg == USART3) { RCC->APB1ENR &= ~RCC_APB1ENR_USART3EN; } +#endif +#if defined(STM32F10X_HD) || defined(STM32F10X_CL) || defined(STM32F10X_XL) || defined(STM32F10X_HD_VL) + if (usart->reg == UART4) { RCC->APB1ENR &= ~RCC_APB1ENR_UART4EN; } + if (usart->reg == UART5) { RCC->APB1ENR &= ~RCC_APB1ENR_UART5EN; } +#endif + + // Clear Status flags + usart->info->status.tx_busy = 0U; + usart->info->status.rx_busy = 0U; + usart->info->status.tx_underflow = 0U; + usart->info->status.rx_overflow = 0U; + usart->info->status.rx_break = 0U; + usart->info->status.rx_framing_error = 0U; + usart->info->status.rx_parity_error = 0U; + usart->xfer->send_active = 0U; + + usart->info->flags &= ~USART_FLAG_POWERED; + break; + + case ARM_POWER_LOW: + return ARM_DRIVER_ERROR_UNSUPPORTED; + + case ARM_POWER_FULL: + if ((usart->info->flags & USART_FLAG_INITIALIZED) == 0U) { + return ARM_DRIVER_ERROR; + } + if ((usart->info->flags & USART_FLAG_POWERED) != 0U) { + return ARM_DRIVER_OK; + } + + // Clear Status flags + usart->info->status.tx_busy = 0U; + usart->info->status.rx_busy = 0U; + usart->info->status.tx_underflow = 0U; + usart->info->status.rx_overflow = 0U; + usart->info->status.rx_break = 0U; + usart->info->status.rx_framing_error = 0U; + usart->info->status.rx_parity_error = 0U; + + usart->xfer->send_active = 0U; + usart->xfer->def_val = 0U; + usart->xfer->sync_mode = 0U; + usart->xfer->break_flag = 0U; + usart->info->mode = 0U; + usart->info->flow_control = 0U; + + usart->info->flags = USART_FLAG_POWERED | USART_FLAG_INITIALIZED; + + // Enable USART clock + if (usart->reg == USART1) { RCC->APB2ENR |= RCC_APB2ENR_USART1EN; } + if (usart->reg == USART2) { RCC->APB1ENR |= RCC_APB1ENR_USART2EN; } +#if !defined (STM32F10X_LD) && !defined (STM32F10X_LD_VL) + if (usart->reg == USART3) { RCC->APB1ENR |= RCC_APB1ENR_USART3EN; } +#endif +#if defined(STM32F10X_HD) || defined(STM32F10X_CL) || defined(STM32F10X_XL) || defined(STM32F10X_HD_VL) + if (usart->reg == UART4) { RCC->APB1ENR |= RCC_APB1ENR_UART4EN; } + if (usart->reg == UART5) { RCC->APB1ENR |= RCC_APB1ENR_UART5EN; } +#endif + + // Clear and Enable USART IRQ + NVIC_ClearPendingIRQ(usart->irq_num); + NVIC_EnableIRQ(usart->irq_num); + +#ifdef __USART_DMA + if (usart->dma_rx) { + // Initialize DMA + DMA_ChannelInitialize (usart->dma_rx->dma_num, usart->dma_rx->ch_num); + } + + if (usart->dma_tx) { + // Initialize DMA + DMA_ChannelInitialize (usart->dma_tx->dma_num, usart->dma_tx->ch_num); + } +#endif + + // Peripheral reset + USART_PeripheralReset (usart->reg); + break; + default: return ARM_DRIVER_ERROR_UNSUPPORTED; + } + return ARM_DRIVER_OK; +} + +/** + \fn int32_t USART_Send (const void *data, + uint32_t num, + const USART_RESOURCES *usart) + \brief Start sending data to USART transmitter. + \param[in] data Pointer to buffer with data to send to USART transmitter + \param[in] num Number of data items to send + \param[in] usart Pointer to USART resources + \return \ref execution_status +*/ +static int32_t USART_Send (const void *data, + uint32_t num, + const USART_RESOURCES *usart) { + int32_t stat; + +#ifdef __USART_DMA_TX + uint32_t cfg, cr1; +#endif + + if ((data == NULL) || (num == 0U)) { + // Invalid parameters + return ARM_DRIVER_ERROR_PARAMETER; + } + + if ((usart->info->flags & USART_FLAG_CONFIGURED) == 0U) { + // USART is not configured (mode not selected) + return ARM_DRIVER_ERROR; + } + + if (usart->xfer->send_active != 0U) { + // Send is not completed yet + return ARM_DRIVER_ERROR_BUSY; + } + + // Set Send active flag + usart->xfer->send_active = 1U; + + // Save transmit buffer info + usart->xfer->tx_buf = (uint8_t *)data; + usart->xfer->tx_num = num; + usart->xfer->tx_cnt = 0U; + +#ifdef __USART_DMA_TX + cfg = DMA_MEMORY_INCREMENT; +#endif + + // Synchronous mode + if (usart->info->mode == ARM_USART_MODE_SYNCHRONOUS_MASTER) { + if (usart->xfer->sync_mode == 0U) { + usart->xfer->sync_mode = USART_SYNC_MODE_TX; + // Start dummy reads + stat = USART_Receive (&usart->xfer->dump_val, num, usart); + if (stat == ARM_DRIVER_ERROR_BUSY) { return ARM_DRIVER_ERROR_BUSY; } + +#ifdef __USART_DMA_TX + } else { + if (usart->xfer->sync_mode == USART_SYNC_MODE_RX) { + // Dummy DMA writes (do not increment source address) + cfg = 0; + } +#endif + } + } + +#ifdef __USART_DMA_TX + // DMA mode + if (usart->dma_tx) { + // Configure and enable tx DMA channel + cfg |= ((usart->dma_tx->priority << DMA_PRIORITY_POS) & DMA_PRIORITY_MASK) | + DMA_READ_MEMORY | + DMA_TRANSFER_COMPLETE_INTERRUPT; + + cr1 = usart->reg->CR1; + if (((cr1 & USART_CR1_M) != 0U) && ((cr1 & USART_CR1_PCE) == 0U)) { + // 9-bit data frame, no parity + cfg |= DMA_PERIPHERAL_DATA_16BIT | DMA_MEMORY_DATA_16BIT; + } else { + // 8-bit data frame + cfg |= DMA_PERIPHERAL_DATA_8BIT | DMA_MEMORY_DATA_8BIT; + } + + DMA_ChannelConfigure(usart->dma_tx->instance, + cfg, + (uint32_t)(&usart->reg->DR), + (uint32_t)(uint32_t)data, + num); + DMA_ChannelEnable(usart->dma_tx->instance); + + // DMA Enable transmitter + usart->reg->CR3 |= USART_CR3_DMAT; + } else +#endif + // Interrupt mode + { + // TXE interrupt enable + usart->reg->CR1 |= USART_CR1_TXEIE; + } + + return ARM_DRIVER_OK; +} + +/** + \fn int32_t USART_Receive ( void *data, + uint32_t num, + const USART_RESOURCES *usart) + \brief Start receiving data from USART receiver. + \param[out] data Pointer to buffer for data to receive from USART receiver + \param[in] num Number of data items to receive + \param[in] usart Pointer to USART resources + \return \ref execution_status +*/ +static int32_t USART_Receive ( void *data, + uint32_t num, + const USART_RESOURCES *usart) { + + int32_t stat; + +#ifdef __USART_DMA_RX + uint32_t cfg, cr1; +#endif + + if ((data == NULL) || (num == 0U)) { + // Invalid parameters + return ARM_DRIVER_ERROR_PARAMETER; + } + + if ((usart->info->flags & USART_FLAG_CONFIGURED) == 0U) { + // USART is not configured (mode not selected) + return ARM_DRIVER_ERROR; + } + + // Check if receiver is busy + if (usart->info->status.rx_busy == 1U) { + return ARM_DRIVER_ERROR_BUSY; + } + + // Disable RXNE Interrupt + usart->reg->CR1 &= ~USART_CR1_RXNEIE; + + // Save number of data to be received + usart->xfer->rx_num = num; + + // Clear RX statuses + usart->info->status.rx_break = 0U; + usart->info->status.rx_framing_error = 0U; + usart->info->status.rx_overflow = 0U; + usart->info->status.rx_parity_error = 0U; + + // Save receive buffer info + usart->xfer->rx_buf = (uint8_t *)data; + usart->xfer->rx_cnt = 0U; + + // Set RX busy flag + usart->info->status.rx_busy = 1U; + +#ifdef __USART_DMA_RX + + cfg = DMA_MEMORY_INCREMENT; + + // Synchronous mode + if (usart->info->mode == ARM_USART_MODE_SYNCHRONOUS_MASTER) { + if (usart->xfer->sync_mode == USART_SYNC_MODE_TX) { + // Dummy DMA reads (do not increment destination address) + cfg = 0U; + } + } + + // DMA mode + if (usart->dma_rx) { + // Configure and enable rx DMA channel + cfg |= ((usart->dma_rx->priority << DMA_PRIORITY_POS) & DMA_PRIORITY_MASK) | + DMA_PERIPHERAL_TO_MEMORY | + DMA_TRANSFER_COMPLETE_INTERRUPT; + + cr1 = usart->reg->CR1; + if (((cr1 & USART_CR1_M) != 0U) && ((cr1 & USART_CR1_PCE) == 0U)) { + // 9-bit data frame, no parity + cfg |= DMA_PERIPHERAL_DATA_16BIT | DMA_MEMORY_DATA_16BIT; + } else { + // 8-bit data frame + cfg |= DMA_PERIPHERAL_DATA_8BIT | DMA_MEMORY_DATA_8BIT; + } + + DMA_ChannelConfigure(usart->dma_rx->instance, + cfg, + (uint32_t)(&usart->reg->DR), + (uint32_t)(uint32_t)data, + num); + DMA_ChannelEnable(usart->dma_rx->instance); + + usart->reg->CR3 |= USART_CR3_DMAR; + // Enable IDLE interrupt + usart->reg->CR1 |= USART_CR1_IDLEIE; + } else +#endif + { + // Enable RXNE and IDLE interrupt + usart->reg->CR1 |= (USART_CR1_IDLEIE | USART_CR1_RXNEIE); + } + + // Synchronous mode + if (usart->info->mode == ARM_USART_MODE_SYNCHRONOUS_MASTER) { + if (usart->xfer->sync_mode == 0U) { + usart->xfer->sync_mode = USART_SYNC_MODE_RX; + // Send dummy data + stat = USART_Send (&usart->xfer->def_val, num, usart); + if (stat == ARM_DRIVER_ERROR_BUSY) { return ARM_DRIVER_ERROR_BUSY; } + } + } + + return ARM_DRIVER_OK; +} + +/** + \fn int32_t USART_Transfer (const void *data_out, + void *data_in, + uint32_t num, + const USART_RESOURCES *usart) + \brief Start sending/receiving data to/from USART transmitter/receiver. + \param[in] data_out Pointer to buffer with data to send to USART transmitter + \param[out] data_in Pointer to buffer for data to receive from USART receiver + \param[in] num Number of data items to transfer + \param[in] usart Pointer to USART resources + \return \ref execution_status +*/ +static int32_t USART_Transfer (const void *data_out, + void *data_in, + uint32_t num, + const USART_RESOURCES *usart) { + int32_t status; + + if ((data_out == NULL) || (data_in == NULL) || (num == 0U)) { + // Invalid parameters + return ARM_DRIVER_ERROR_PARAMETER; + } + + if ((usart->info->flags & USART_FLAG_CONFIGURED) == 0U) { + // USART is not configured + return ARM_DRIVER_ERROR; + } + + if (usart->info->mode == ARM_USART_MODE_SYNCHRONOUS_MASTER) { + + // Set xfer mode + usart->xfer->sync_mode = USART_SYNC_MODE_TX_RX; + + // Receive + status = USART_Receive (data_in, num, usart); + if (status != ARM_DRIVER_OK) { return status; } + + // Send + status = USART_Send (data_out, num, usart); + if (status != ARM_DRIVER_OK) { return status; } + + } else { + // Only in synchronous mode + return ARM_DRIVER_ERROR; + } + return ARM_DRIVER_OK; +} + +/** + \fn uint32_t USART_GetTxCount (const USART_RESOURCES *usart) + \brief Get transmitted data count. + \param[in] usart Pointer to USART resources + \return number of data items transmitted +*/ +static uint32_t USART_GetTxCount (const USART_RESOURCES *usart) { + +#ifdef __USART_DMA_TX + if (usart->dma_tx) { + return (usart->xfer->tx_num - DMA_ChannelTransferItemCount(usart->dma_tx->instance)); + } else +#endif + { + return usart->xfer->tx_cnt; + } +} + +/** + \fn uint32_t USART_GetRxCount (const USART_RESOURCES *usart) + \brief Get received data count. + \param[in] usart Pointer to USART resources + \return number of data items received +*/ +static uint32_t USART_GetRxCount (const USART_RESOURCES *usart) { + +#ifdef __USART_DMA_RX + if (usart->dma_rx) { + return (usart->xfer->rx_num - DMA_ChannelTransferItemCount(usart->dma_rx->instance)); + } else +#endif + { + return usart->xfer->rx_cnt; + } +} + +/** + \fn int32_t USART_Control ( uint32_t control, + uint32_t arg, + const USART_RESOURCES *usart) + \brief Control USART Interface. + \param[in] control Operation + \param[in] arg Argument of operation (optional) + \param[in] usart Pointer to USART resources + \return common \ref execution_status and driver specific \ref usart_execution_status +*/ +static int32_t USART_Control ( uint32_t control, + uint32_t arg, + const USART_RESOURCES *usart) { + uint32_t val, mode, flow_control, br, i; + uint32_t cr1, cr2, cr3; + + if ((usart->info->flags & USART_FLAG_POWERED) == 0U) { + // USART not powered + return ARM_DRIVER_ERROR; + } + + cr1 = 0U; + cr2 = 0U; + cr3 = 0U; + + switch (control & ARM_USART_CONTROL_Msk) { + // Control break + case ARM_USART_CONTROL_BREAK: + if (arg) { + if (usart->xfer->send_active != 0U) { return ARM_DRIVER_ERROR_BUSY; } + + // Set Send active and Break flag + usart->xfer->send_active = 1U; + usart->xfer->break_flag = 1U; + + // Enable TX interrupt and send break + usart->reg->CR1 |= USART_CR1_TXEIE | USART_CR1_SBK; + } else { + if (usart->xfer->break_flag) { + // Disable TX interrupt + usart->reg->CR1 &= ~USART_CR1_TXEIE; + + // Clear break and Send Active flag + usart->xfer->break_flag = 0U; + usart->xfer->send_active = 0U; + } + } + return ARM_DRIVER_OK; + + // Abort Send + case ARM_USART_ABORT_SEND: + // Disable TX and TC interrupt + usart->reg->CR1 &= ~(USART_CR1_TXEIE | USART_CR1_TCIE); + + // If DMA mode - disable DMA channel + if ((usart->dma_tx != NULL) && (usart->xfer->send_active != 0)) { + // DMA disable transmitter + usart->reg->CR3 &= ~USART_CR3_DMAT; + + // Abort TX DMA transfer + DMA_ChannelDisable (usart->dma_tx->instance); + } + + // Clear break flag + usart->xfer->break_flag = 0U; + + // Clear Send active flag + usart->xfer->send_active = 0U; + return ARM_DRIVER_OK; + + // Abort receive + case ARM_USART_ABORT_RECEIVE: + // Disable RX interrupt + usart->reg->CR1 &= ~USART_CR1_RXNEIE; + + // If DMA mode - disable DMA channel + if ((usart->dma_rx != NULL) && (usart->info->status.rx_busy != 0)) { + // DMA disable Receiver + usart->reg->CR3 &= ~USART_CR3_DMAR; + + // Abort RX DMA transfer + DMA_ChannelDisable (usart->dma_rx->instance); + } + + // Clear RX busy status + usart->info->status.rx_busy = 0U; + + return ARM_DRIVER_OK; + + // Abort transfer + case ARM_USART_ABORT_TRANSFER: + // Disable TX, TC and RX interrupt + usart->reg->CR1 &= ~(USART_CR1_TXEIE | USART_CR1_TCIE | USART_CR1_RXNEIE); + + // If DMA mode - disable DMA channel + if ((usart->dma_tx != NULL) && (usart->xfer->send_active != 0U)) { + // DMA disable transmitter + usart->reg->CR3 &= ~USART_CR3_DMAT; + + // Abort TX DMA transfer + DMA_ChannelDisable (usart->dma_tx->instance); + } + + // If DMA mode - disable DMA channel + if ((usart->dma_rx != NULL) && (usart->info->status.rx_busy != 0U)) { + // DMA disable Receiver + usart->reg->CR3 &= ~USART_CR3_DMAR; + + // Abort RX DMA transfer + DMA_ChannelDisable (usart->dma_rx->instance); + } + + // Clear busy statuses + usart->info->status.rx_busy = 0U; + usart->xfer->send_active = 0U; + return ARM_DRIVER_OK; + + // Control TX + case ARM_USART_CONTROL_TX: + // Check if TX pin available + if (usart->io.tx == NULL) { return ARM_DRIVER_ERROR; } + if (arg) { + if (usart->info->mode != ARM_USART_MODE_SMART_CARD) { + // USART TX pin function selected + GPIO_PinConfigure(usart->io.tx->port, usart->io.tx->pin, GPIO_AF_PUSHPULL, GPIO_MODE_OUT50MHZ); + } + usart->info->flags |= USART_FLAG_TX_ENABLED; + + // Transmitter enable + usart->reg->CR1 |= USART_CR1_TE; + } else { + // Transmitter disable + usart->reg->CR1 &= ~USART_CR1_TE; + + usart->info->flags &= ~USART_FLAG_TX_ENABLED; + + if (usart->info->mode != ARM_USART_MODE_SMART_CARD) { + // GPIO pin function selected + if (usart->io.tx) { + GPIO_PinConfigure(usart->io.tx->port, usart->io.tx->pin, GPIO_IN_ANALOG, GPIO_MODE_IN); + } + } + } + return ARM_DRIVER_OK; + + // Control RX + case ARM_USART_CONTROL_RX: + // Check if RX line available + if (usart->io.rx == NULL) { return ARM_DRIVER_ERROR; } + if (arg) { + if ((usart->info->mode != ARM_USART_MODE_SMART_CARD) && + (usart->info->mode != ARM_USART_MODE_SINGLE_WIRE )) { + // USART RX pin function selected + GPIO_PinConfigure(usart->io.rx->port, usart->io.rx->pin, GPIO_IN_FLOATING, GPIO_MODE_IN); + } + usart->info->flags |= USART_FLAG_RX_ENABLED; + + // Enable Error interrupt, + usart->reg->CR3 |= USART_CR3_EIE; + + // Break detection interrupt enable + usart->reg->CR2 |= USART_CR2_LBDIE; + + // Enable Idle line interrupt + usart->reg->CR1 |= USART_CR1_IDLEIE; + + if (((usart->info->status.rx_busy != 0U) && (usart->dma_rx != NULL)) == false) { + usart->reg->CR1 |= USART_CR1_RXNEIE; + } + + // Receiver enable + usart->reg->CR1 |= USART_CR1_RE; + + } else { + // Receiver disable + usart->reg->CR1 &= ~USART_CR1_RE; + + usart->info->flags &= ~USART_FLAG_RX_ENABLED; + + if ((usart->info->mode != ARM_USART_MODE_SMART_CARD) && + (usart->info->mode != ARM_USART_MODE_SINGLE_WIRE )) { + // GPIO pin function selected + if (usart->io.rx) { + GPIO_PinConfigure(usart->io.rx->port, usart->io.rx->pin, GPIO_IN_ANALOG, GPIO_MODE_IN); + } + } + } + return ARM_DRIVER_OK; + default: break; + } + + // Check if busy + if ((usart->info->status.rx_busy != 0U) || (usart->xfer->send_active != 0U)) { + return ARM_DRIVER_ERROR_BUSY; + } + + if (((usart->reg->CR1 & USART_CR1_TE) != 0U) && ((usart->reg->SR & USART_SR_TC) == 0U)) { + return ARM_DRIVER_ERROR_BUSY; + } + + switch (control & ARM_USART_CONTROL_Msk) { + case ARM_USART_MODE_ASYNCHRONOUS: + mode = ARM_USART_MODE_ASYNCHRONOUS; + break; + case ARM_USART_MODE_SYNCHRONOUS_MASTER: + if (usart->capabilities.synchronous_master) { + // Enable Clock pin + cr2 |= USART_CR2_CLKEN; + + // Enable last bit clock pulse + cr2 |= USART_CR2_LBCL; + } else { return ARM_USART_ERROR_MODE; } + mode = ARM_USART_MODE_SYNCHRONOUS_MASTER; + break; + case ARM_USART_MODE_SYNCHRONOUS_SLAVE: + return ARM_USART_ERROR_MODE; + case ARM_USART_MODE_SINGLE_WIRE: + // Enable Half duplex + cr3 |= USART_CR3_HDSEL; + mode = ARM_USART_MODE_SINGLE_WIRE; + break; + case ARM_USART_MODE_IRDA: + // Enable IrDA mode + cr3 |= USART_CR3_IREN; + mode = ARM_USART_MODE_IRDA; + break; + case ARM_USART_MODE_SMART_CARD: + if (usart->capabilities.smart_card) { + // Enable Smart card mode + cr3 |= USART_CR3_SCEN; + } else { return ARM_USART_ERROR_MODE; } + mode = ARM_USART_MODE_SMART_CARD; + break; + + // Default TX value + case ARM_USART_SET_DEFAULT_TX_VALUE: + usart->xfer->def_val = (uint16_t)arg; + return ARM_DRIVER_OK; + + // IrDA pulse + case ARM_USART_SET_IRDA_PULSE: + if (usart->info->mode == ARM_USART_MODE_IRDA) { + if (arg != 0U) { + // IrDa low-power + usart->reg->CR3 |= USART_CR3_IRLP; + + // Get clock + val = usart->pclk; + + // Calculate period in ns + val = 1000000000U / val; + for (i = 1U; i < 256U; i++) { + if ((val * i) > arg) { break; } + } + if (i == 256U) { return ARM_DRIVER_ERROR; } + usart->reg->GTPR = (usart->reg->GTPR & ~USART_GTPR_PSC) | i; + } + } else { return ARM_DRIVER_ERROR; } + return ARM_DRIVER_OK; + + // SmartCard guard time + case ARM_USART_SET_SMART_CARD_GUARD_TIME: + if (usart->info->mode == ARM_USART_MODE_SMART_CARD) { + if (arg > 255U) return ARM_DRIVER_ERROR; + + usart->reg->GTPR = (usart->reg->GTPR & ~USART_GTPR_GT) | arg; + } else { return ARM_DRIVER_ERROR; } + return ARM_DRIVER_OK; + + // SmartCard clock + case ARM_USART_SET_SMART_CARD_CLOCK: + if (usart->info->mode == ARM_USART_MODE_SMART_CARD) { + // Get clock + val = usart->pclk; + + // Calculate period in ns + val = 1000000000U / val; + for (i = 1U; i <64U; i++) { + // if in +-2% tolerance + if (((val * i * 2U * 100U) < (arg * 102U)) && + ((val * i * 2U * 100U) > (arg * 98U)) ) { + break; + } + } + if (i == 64U) { return ARM_DRIVER_ERROR; } + + usart->reg->GTPR = (usart->reg->GTPR & ~USART_GTPR_PSC) | i; + } else { return ARM_DRIVER_ERROR; } + return ARM_DRIVER_OK; + + // SmartCard NACK + case ARM_USART_CONTROL_SMART_CARD_NACK: + if (usart->info->mode == ARM_USART_MODE_SMART_CARD) { + // SmartCard NACK Enable + if (arg != 0U) { usart->reg->CR3 |= USART_CR3_NACK; } + } else { return ARM_DRIVER_ERROR; } + return ARM_DRIVER_OK; + + // Unsupported command + default: { return ARM_DRIVER_ERROR_UNSUPPORTED; } + } + + // USART Data bits + switch (control & ARM_USART_DATA_BITS_Msk) { + case ARM_USART_DATA_BITS_7: + if ((control & ARM_USART_PARITY_Msk) == ARM_USART_PARITY_NONE) { + return ARM_USART_ERROR_DATA_BITS; + } + + // 7 data bits, 8. data bit is parity bit + break; + case ARM_USART_DATA_BITS_8: + if ((control & ARM_USART_PARITY_Msk) == ARM_USART_PARITY_NONE) { + // 8-data bits, no parity + } else { + // 11-bit break detection + cr2 |= USART_CR2_LBDL; + + // 8-data bits, 9. bit is parity bit + cr1 |= USART_CR1_M; + } + break; + case ARM_USART_DATA_BITS_9: + if ((control & ARM_USART_PARITY_Msk) != ARM_USART_PARITY_NONE) { + return ARM_USART_ERROR_DATA_BITS; + } + + // 11-bit break detection + cr2 |= USART_CR2_LBDL; + + // 9-data bits, no parity + cr1 |= USART_CR1_M; + break; + default: return ARM_USART_ERROR_DATA_BITS; + } + + // USART Parity + switch (control & ARM_USART_PARITY_Msk) { + case ARM_USART_PARITY_NONE: break; + case ARM_USART_PARITY_EVEN: cr1 |= USART_CR1_PCE; break; + case ARM_USART_PARITY_ODD: cr1 |= (USART_CR1_PCE | + USART_CR1_PS); break; + default: return ARM_USART_ERROR_PARITY; + } + + // USART Stop bits + switch (control & ARM_USART_STOP_BITS_Msk) { + case ARM_USART_STOP_BITS_1: break; + case ARM_USART_STOP_BITS_2: cr2 |= USART_CR2_STOP_1; break; + case ARM_USART_STOP_BITS_1_5: cr2 |= USART_CR2_STOP_0 | + USART_CR2_STOP_1; break; + case ARM_USART_STOP_BITS_0_5: cr2 |= USART_CR2_STOP_0; break; + default: return ARM_USART_ERROR_STOP_BITS; + } + + // USART Flow control + switch (control & ARM_USART_FLOW_CONTROL_Msk) { + case ARM_USART_FLOW_CONTROL_NONE: + flow_control = ARM_USART_FLOW_CONTROL_NONE; + break; + case ARM_USART_FLOW_CONTROL_RTS: + if (usart->capabilities.flow_control_rts) { + flow_control = ARM_USART_FLOW_CONTROL_RTS; + // RTS Enable + cr3 |= USART_CR3_RTSE; + } + else { return ARM_USART_ERROR_FLOW_CONTROL; } + break; + case ARM_USART_FLOW_CONTROL_CTS: + if (usart->capabilities.flow_control_cts) { + flow_control = ARM_USART_FLOW_CONTROL_CTS; + // CTS Enable, CTS interrupt enable + cr3 |= USART_CR3_CTSE | USART_CR3_CTSIE; + } + else { return ARM_USART_ERROR_FLOW_CONTROL; } + break; + case ARM_USART_FLOW_CONTROL_RTS_CTS: + if ((usart->capabilities.flow_control_rts != 0U) && + (usart->capabilities.flow_control_cts != 0U)) { + flow_control = ARM_USART_FLOW_CONTROL_RTS_CTS; + // RTS and CTS Enable, CTS interrupt enable + cr3 |= (USART_CR3_RTSE | USART_CR3_CTSE | USART_CR3_CTSIE); + } else { return ARM_USART_ERROR_FLOW_CONTROL; } + break; + default: return ARM_USART_ERROR_FLOW_CONTROL; + } + + // Clock setting for synchronous mode + if (mode == ARM_USART_MODE_SYNCHRONOUS_MASTER) { + + // Polarity + switch (control & ARM_USART_CPOL_Msk) { + case ARM_USART_CPOL0: + break; + case ARM_USART_CPOL1: + cr2 |= USART_CR2_CPOL; + break; + default: return ARM_USART_ERROR_CPOL; + } + + // Phase + switch (control & ARM_USART_CPHA_Msk) { + case ARM_USART_CPHA0: + break; + case ARM_USART_CPHA1: + cr2 |= USART_CR2_CPHA; + break; + default: return ARM_USART_ERROR_CPHA; + } + } + + // USART Baudrate + val = (uint32_t) (USART_BAUDRATE_DIVIDER(usart->pclk, arg)); + br = ((usart->pclk << 4U) / (val & 0xFFFFU)) >> 4U; + // If inside +/- 2% tolerance, baud rate configured correctly + if (!(((br * 100U) < (arg * 102U)) && ((br * 100U) > (arg * 98U)))) { + return ARM_USART_ERROR_BAUDRATE; + } + + // USART Disable + usart->reg->CR1 &= ~USART_CR1_UE; + + // Configure Baud rate register + usart->reg->BRR = val; + + // Configuration is OK - Mode is valid + usart->info->mode = mode; + + // Save flow control mode + usart->info->flow_control = flow_control; + + // Configure TX pin regarding mode and transmitter state + switch (usart->info->mode) { + case ARM_USART_MODE_SMART_CARD: + // USART TX pin function selected + if (usart->io.tx) { + GPIO_PinConfigure(usart->io.tx->port, usart->io.tx->pin, GPIO_AF_PUSHPULL, GPIO_MODE_OUT50MHZ); + } + break; + default: + // Synchronous master/slave, asynchronous, single-wire and IrDA mode + if (usart->info->flags & USART_FLAG_TX_ENABLED) { + // USART TX pin function selected + if (usart->io.tx) { + GPIO_PinConfigure(usart->io.tx->port, usart->io.tx->pin, GPIO_AF_PUSHPULL, GPIO_MODE_OUT50MHZ); + } + } else { + // GPIO pin function selected + if (usart->io.tx) { + GPIO_PinConfigure(usart->io.tx->port, usart->io.tx->pin, GPIO_IN_ANALOG, GPIO_MODE_IN); + } + } + } + + // Configure RX pin regarding mode and receiver state + switch (usart->info->mode) { + case ARM_USART_MODE_SINGLE_WIRE: + case ARM_USART_MODE_SMART_CARD: + // GPIO pin function selected + if (usart->io.rx) { + GPIO_PinConfigure(usart->io.rx->port, usart->io.rx->pin, GPIO_IN_ANALOG, GPIO_MODE_IN); + } + break; + default: + // Synchronous master/slave, asynchronous and IrDA mode + if (usart->info->flags & USART_FLAG_RX_ENABLED) { + // USART RX pin function selected + if (usart->io.rx) { + GPIO_PinConfigure(usart->io.rx->port, usart->io.rx->pin, GPIO_IN_FLOATING, GPIO_MODE_IN); + } + } else { + // GPIO pin function selected + if (usart->io.rx) { + GPIO_PinConfigure(usart->io.rx->port, usart->io.rx->pin, GPIO_IN_ANALOG, GPIO_MODE_IN); + } + } + break; + } + + // Configure CLK pin regarding mode + if (usart->io.ck) { + switch (usart->info->mode) { + case ARM_USART_MODE_SMART_CARD: + case ARM_USART_MODE_SYNCHRONOUS_MASTER: + // USART CK pin function selected + GPIO_PinConfigure(usart->io.ck->port, usart->io.ck->pin, GPIO_AF_PUSHPULL, GPIO_MODE_OUT50MHZ); + break; + default: + // Asynchronous, Single-wire and IrDA mode + // GPIO pin function selected + GPIO_PinConfigure(usart->io.ck->port, usart->io.ck->pin, GPIO_IN_ANALOG, GPIO_MODE_IN); + } + } + + // Configure RTS pin regarding Flow control configuration + if (usart->io.rts) { + if ((flow_control == ARM_USART_FLOW_CONTROL_RTS) || + (flow_control == ARM_USART_FLOW_CONTROL_RTS_CTS)) { + // USART RTS Alternate function + GPIO_PinConfigure(usart->io.rts->port, usart->io.rts->pin, GPIO_AF_PUSHPULL, GPIO_MODE_OUT50MHZ); + } else { + // GPIO output + GPIO_PinConfigure(usart->io.rts->port, usart->io.rts->pin, GPIO_OUT_PUSH_PULL, GPIO_MODE_IN); + } + } + + // Configure CTS pin regarding Flow control configuration + if (usart->io.cts) { + if ((flow_control == ARM_USART_FLOW_CONTROL_CTS) || + (flow_control == ARM_USART_FLOW_CONTROL_RTS_CTS)) { + // USART CTS Alternate function + GPIO_PinConfigure(usart->io.cts->port, usart->io.cts->pin, GPIO_IN_FLOATING, GPIO_MODE_IN); + } else { + // GPIO input + GPIO_PinConfigure(usart->io.cts->port, usart->io.cts->pin, GPIO_IN_FLOATING, GPIO_MODE_IN); + } + } + + // Configure USART control registers + usart->reg->CR1 = cr1; + usart->reg->CR2 = cr2; + usart->reg->CR3 = cr3; + + // USART Enable + usart->reg->CR1 |= USART_CR1_UE; + + // Set configured flag + usart->info->flags |= USART_FLAG_CONFIGURED; + + return ARM_DRIVER_OK; +} + +/** + \fn ARM_USART_STATUS USART_GetStatus (const USART_RESOURCES *usart) + \brief Get USART status. + \param[in] usart Pointer to USART resources + \return USART status \ref ARM_USART_STATUS +*/ +static ARM_USART_STATUS USART_GetStatus (const USART_RESOURCES *usart) { + ARM_USART_STATUS status; + + if (usart->xfer->send_active != 0U) { + status.tx_busy = 1U; + } else { + status.tx_busy = ((usart->reg->SR & USART_SR_TC) ? (0U) : (1U)); + } + status.rx_busy = usart->info->status.rx_busy; + status.tx_underflow = usart->info->status.tx_underflow; + status.rx_overflow = usart->info->status.rx_overflow; + status.rx_break = usart->info->status.rx_break; + status.rx_framing_error = usart->info->status.rx_framing_error; + status.rx_parity_error = usart->info->status.rx_parity_error; + + return status; +} + +/** + \fn int32_t USART_SetModemControl ( ARM_USART_MODEM_CONTROL control, + const USART_RESOURCES *usart) + \brief Set USART Modem Control line state. + \param[in] control \ref ARM_USART_MODEM_CONTROL + \param[in] usart Pointer to USART resources + \return \ref execution_status +*/ +static int32_t USART_SetModemControl ( ARM_USART_MODEM_CONTROL control, + const USART_RESOURCES *usart) { + + switch (control) { + case ARM_USART_RTS_CLEAR: + if ((usart->info->flow_control == ARM_USART_FLOW_CONTROL_NONE) || + (usart->info->flow_control == ARM_USART_FLOW_CONTROL_CTS)) { + if (usart->io.rts) { + GPIO_PinWrite (usart->io.rts->port, usart->io.rts->pin, 1U); + } + } else { + // Hardware RTS + return ARM_DRIVER_ERROR; + } + break; + case ARM_USART_RTS_SET: + if ((usart->info->flow_control == ARM_USART_FLOW_CONTROL_NONE) || + (usart->info->flow_control == ARM_USART_FLOW_CONTROL_CTS)) { + if (usart->io.rts) { + GPIO_PinWrite (usart->io.rts->port, usart->io.rts->pin, 0U); + } + } else { + // Hardware RTS + return ARM_DRIVER_ERROR; + } + break; + case ARM_USART_DTR_CLEAR: + case ARM_USART_DTR_SET: + default: return ARM_DRIVER_ERROR; + } + + return ARM_DRIVER_OK; +} + +/** + \fn ARM_USART_MODEM_STATUS USART_GetModemStatus (const USART_RESOURCES *usart) + \brief Get USART Modem Status lines state. + \param[in] usart Pointer to USART resources + \return modem status \ref ARM_USART_MODEM_STATUS +*/ +static ARM_USART_MODEM_STATUS USART_GetModemStatus (const USART_RESOURCES *usart) { + ARM_USART_MODEM_STATUS modem_status; + + modem_status.cts = 0U; + if ((usart->info->flow_control == ARM_USART_FLOW_CONTROL_NONE) || + (usart->info->flow_control == ARM_USART_FLOW_CONTROL_RTS)) { + if (usart->io.cts) { + if (GPIO_PinRead (usart->io.cts->port, usart->io.cts->pin) == 0U) { + modem_status.cts = 1U; + } + } + } + modem_status.dsr = 0U; + modem_status.ri = 0U; + modem_status.dcd = 0U; + + return modem_status; +} + + +/** + \fn void USART_IRQHandler (const USART_RESOURCES *usart) + \brief USART Interrupt handler. + \param[in] usart Pointer to USART resources +*/ +void USART_IRQHandler (const USART_RESOURCES *usart) { + uint32_t val, sr, event; + uint16_t data; + + // Read USART status register + sr = usart->reg->SR; + + // Reset local variables + val = 0U; + event = 0U; + data = 0U; + + // Read Data register not empty + if (sr & USART_SR_RXNE & usart->reg->CR1) { + // Check for RX overflow + if (usart->info->status.rx_busy == 0U) { + // New receive has not been started + // Dump RX data + usart->reg->DR; + usart->info->status.rx_overflow = 1; + event |= ARM_USART_EVENT_RX_OVERFLOW; + } else { + if ((usart->info->mode == ARM_USART_MODE_SYNCHRONOUS_MASTER) && + (usart->xfer->sync_mode == USART_SYNC_MODE_TX)) { + // Dummy read in synchronous transmit only mode + usart->reg->DR; + } else { + // Read data from RX FIFO into receive buffer + data = (uint16_t)usart->reg->DR; + } + + *(usart->xfer->rx_buf++) = (uint8_t)data; + + // If nine bit data, no parity + val = usart->reg->CR1; + if (((val & USART_CR1_PCE) == 0U) && + ((val & USART_CR1_M) != 0U)) { + *(usart->xfer->rx_buf++) = (uint8_t)(data >> 8U); + } + usart->xfer->rx_cnt++; + + // Check if requested amount of data is received + if (usart->xfer->rx_cnt == usart->xfer->rx_num) { + + // Disable IDLE interrupt + usart->reg->CR1 &= ~USART_CR1_IDLEIE; + + // Clear RX busy flag and set receive transfer complete event + usart->info->status.rx_busy = 0U; + if (usart->info->mode == ARM_USART_MODE_SYNCHRONOUS_MASTER) { + val = usart->xfer->sync_mode; + usart->xfer->sync_mode = 0U; + switch (val) { + case USART_SYNC_MODE_TX: + event |= ARM_USART_EVENT_SEND_COMPLETE; + break; + case USART_SYNC_MODE_RX: + event |= ARM_USART_EVENT_RECEIVE_COMPLETE; + break; + case USART_SYNC_MODE_TX_RX: + event |= ARM_USART_EVENT_TRANSFER_COMPLETE; + break; + default: break; + } + } else { + event |= ARM_USART_EVENT_RECEIVE_COMPLETE; + } + } + } + } + + // IDLE line + if (sr & USART_SR_IDLE & usart->reg->CR1) { + // Dummy read to clear IDLE interrupt + usart->reg->DR; + event |= ARM_USART_EVENT_RX_TIMEOUT; + } + + // Transmit data register empty + if (sr & USART_SR_TXE & usart->reg->CR1) { + + // Break handling + if (usart->xfer->break_flag) { + // Send break + usart->reg->CR1 |= USART_CR1_SBK; + } else { + if(usart->xfer->tx_num != usart->xfer->tx_cnt) { + if ((usart->info->mode == ARM_USART_MODE_SYNCHRONOUS_MASTER) && + (usart->xfer->sync_mode == USART_SYNC_MODE_RX)) { + // Dummy write in synchronous receive only mode + data = usart->xfer->def_val; + } else { + // Write data to TX FIFO + data = *(usart->xfer->tx_buf++); + + // If nine bit data, no parity + val = usart->reg->CR1; + if (((val & USART_CR1_PCE) == 0U) && + ((val & USART_CR1_M) != 0U)) { + data |= *(usart->xfer->tx_buf++) << 8U; + } + } + } + usart->xfer->tx_cnt++; + + // Write to data register + usart->reg->DR = data; + + // Check if all data is transmitted + if (usart->xfer->tx_num == usart->xfer->tx_cnt) { + // Disable TXE interrupt + usart->reg->CR1 &= ~USART_CR1_TXEIE; + + // Enable TC interrupt + usart->reg->CR1 |= USART_CR1_TCIE; + + usart->xfer->send_active = 0U; + + // Set send complete event + if (usart->info->mode == ARM_USART_MODE_SYNCHRONOUS_MASTER) { + if ((usart->xfer->sync_mode == USART_SYNC_MODE_TX) && + ((usart->info->flags & USART_FLAG_RX_ENABLED) == 0U)) { + event |= ARM_USART_EVENT_SEND_COMPLETE; + } + } else { + event |= ARM_USART_EVENT_SEND_COMPLETE; + } + } + } + } + + // Transmission complete + if (sr & USART_SR_TC & usart->reg->CR1) { + // Disable transmission complete interrupt + usart->reg->CR1 &= ~USART_CR1_TCIE; + event |= ARM_USART_EVENT_TX_COMPLETE; + } + + // RX Overrun + if ((sr & USART_SR_ORE) != 0U) { + // Shift register has been overwritten + // Dummy data read to clear the ORE flag + usart->reg->DR; + usart->info->status.rx_overflow = 1U; + event |= ARM_USART_EVENT_RX_OVERFLOW; + } + + // Framing error + if ((sr & USART_SR_FE) != 0U) { + // Dummy data read to clear the FE flag + usart->reg->DR; + usart->info->status.rx_framing_error = 1U; + event |= ARM_USART_EVENT_RX_FRAMING_ERROR; + } + + // Parity error + if ((sr & USART_SR_PE) != 0U) { + // Dummy data read to clear the PE flag + usart->reg->DR; + usart->info->status.rx_parity_error = 1U; + event |= ARM_USART_EVENT_RX_PARITY_ERROR; + } + + // Break Detection + if ((sr & USART_SR_LBD) != 0U) { + // Clear Break detection flag + usart->reg->SR &= ~USART_SR_LBD; + + usart->info->status.rx_break = 1U; + event |= ARM_USART_EVENT_RX_BREAK; + } + + // CTS changed + if ((sr & USART_SR_CTS) != 0U) { + // Clear CTS flag + usart->reg->SR &= ~USART_SR_CTS; + + event |= ARM_USART_EVENT_CTS; + } + + // Send Event + if ((event && usart->info->cb_event) != 0U) { + usart->info->cb_event (event); + } +} + +#ifdef __USART_DMA_TX +void USART_TX_DMA_Complete(const USART_RESOURCES *usart) { + + if ((DMA_ChannelTransferItemCount(usart->dma_tx->instance) != 0U) && (usart->xfer->tx_num != 0U)) { + // TX DMA Complete caused by send/transfer abort + return; + } + + usart->xfer->tx_cnt = usart->xfer->tx_num; + // Clear TX busy flag + usart->xfer->send_active = 0U; + + // TC interrupt enable + usart->reg->CR1 |= USART_CR1_TCIE; + + // Set Send Complete event for asynchronous transfers + if (usart->info->mode != ARM_USART_MODE_SYNCHRONOUS_MASTER) { + if (usart->info->cb_event) { + usart->info->cb_event (ARM_USART_EVENT_SEND_COMPLETE); + } + } +} +#endif + +#ifdef __USART_DMA_RX +void USART_RX_DMA_Complete(const USART_RESOURCES *usart) { + uint32_t val, event; + + if ((DMA_ChannelTransferItemCount(usart->dma_rx->instance) != 0U) && (usart->xfer->rx_num != 0U)) { + // RX DMA Complete caused by receive/transfer abort + return; + } + + // Disable IDLE interrupt + usart->reg->CR1 &= ~USART_CR1_IDLEIE; + + event = 0U; + + if (usart->info->mode == ARM_USART_MODE_SYNCHRONOUS_MASTER) { + val = usart->xfer->sync_mode; + usart->xfer->sync_mode = 0U; + switch (val) { + case USART_SYNC_MODE_TX: + event = ARM_USART_EVENT_SEND_COMPLETE; + break; + case USART_SYNC_MODE_RX: + event = ARM_USART_EVENT_RECEIVE_COMPLETE; + break; + case USART_SYNC_MODE_TX_RX: + event = ARM_USART_EVENT_TRANSFER_COMPLETE; + break; + default: break; + } + } else { + event = ARM_USART_EVENT_RECEIVE_COMPLETE; + } + + usart->xfer->rx_cnt = usart->xfer->rx_num; + usart->info->status.rx_busy = 0U; + + // Enable RXNE interrupt to detect RX overrun + usart->reg->CR1 |= USART_CR1_RXNEIE; + + if (usart->info->cb_event && event) { usart->info->cb_event (event); } +} +#endif + + + +#ifdef MX_USART1 +// USART1 Driver Wrapper functions +static ARM_USART_CAPABILITIES USART1_GetCapabilities (void) { return USART_GetCapabilities (&USART1_Resources); } +static int32_t USART1_Initialize (ARM_USART_SignalEvent_t cb_event) { return USART_Initialize (cb_event, &USART1_Resources); } +static int32_t USART1_Uninitialize (void) { return USART_Uninitialize (&USART1_Resources); } +static int32_t USART1_PowerControl (ARM_POWER_STATE state) { return USART_PowerControl (state, &USART1_Resources); } +static int32_t USART1_Send (const void *data, uint32_t num) { return USART_Send (data, num, &USART1_Resources); } +static int32_t USART1_Receive (void *data, uint32_t num) { return USART_Receive (data, num, &USART1_Resources); } +static int32_t USART1_Transfer (const void *data_out, void *data_in, uint32_t num) { return USART_Transfer (data_out, data_in, num, &USART1_Resources); } +static uint32_t USART1_GetTxCount (void) { return USART_GetTxCount (&USART1_Resources); } +static uint32_t USART1_GetRxCount (void) { return USART_GetRxCount (&USART1_Resources); } +static int32_t USART1_Control (uint32_t control, uint32_t arg) { return USART_Control (control, arg, &USART1_Resources); } +static ARM_USART_STATUS USART1_GetStatus (void) { return USART_GetStatus (&USART1_Resources); } +static int32_t USART1_SetModemControl (ARM_USART_MODEM_CONTROL control) { return USART_SetModemControl (control, &USART1_Resources); } +static ARM_USART_MODEM_STATUS USART1_GetModemStatus (void) { return USART_GetModemStatus (&USART1_Resources); } + void USART1_IRQHandler (void) { USART_IRQHandler (&USART1_Resources); } + +#ifdef MX_USART1_TX_DMA_Instance + void USART1_TX_DMA_Handler (uint32_t events) { USART_TX_DMA_Complete(&USART1_Resources); } +#endif +#ifdef MX_USART1_RX_DMA_Instance + void USART1_RX_DMA_Handler (uint32_t events) { USART_RX_DMA_Complete(&USART1_Resources); } +#endif + +// USART1 Driver Control Block +ARM_DRIVER_USART Driver_USART1 = { + USARTx_GetVersion, + USART1_GetCapabilities, + USART1_Initialize, + USART1_Uninitialize, + USART1_PowerControl, + USART1_Send, + USART1_Receive, + USART1_Transfer, + USART1_GetTxCount, + USART1_GetRxCount, + USART1_Control, + USART1_GetStatus, + USART1_SetModemControl, + USART1_GetModemStatus +}; +#endif + +#ifdef MX_USART2 +// USART2 Driver Wrapper functions +static ARM_USART_CAPABILITIES USART2_GetCapabilities (void) { return USART_GetCapabilities (&USART2_Resources); } +static int32_t USART2_Initialize (ARM_USART_SignalEvent_t cb_event) { return USART_Initialize (cb_event, &USART2_Resources); } +static int32_t USART2_Uninitialize (void) { return USART_Uninitialize (&USART2_Resources); } +static int32_t USART2_PowerControl (ARM_POWER_STATE state) { return USART_PowerControl (state, &USART2_Resources); } +static int32_t USART2_Send (const void *data, uint32_t num) { return USART_Send (data, num, &USART2_Resources); } +static int32_t USART2_Receive (void *data, uint32_t num) { return USART_Receive (data, num, &USART2_Resources); } +static int32_t USART2_Transfer (const void *data_out, void *data_in, uint32_t num) { return USART_Transfer (data_out, data_in, num, &USART2_Resources); } +static uint32_t USART2_GetTxCount (void) { return USART_GetTxCount (&USART2_Resources); } +static uint32_t USART2_GetRxCount (void) { return USART_GetRxCount (&USART2_Resources); } +static int32_t USART2_Control (uint32_t control, uint32_t arg) { return USART_Control (control, arg, &USART2_Resources); } +static ARM_USART_STATUS USART2_GetStatus (void) { return USART_GetStatus (&USART2_Resources); } +static int32_t USART2_SetModemControl (ARM_USART_MODEM_CONTROL control) { return USART_SetModemControl (control, &USART2_Resources); } +static ARM_USART_MODEM_STATUS USART2_GetModemStatus (void) { return USART_GetModemStatus (&USART2_Resources); } + void USART2_IRQHandler (void) { USART_IRQHandler (&USART2_Resources); } + +#ifdef MX_USART2_TX_DMA_Instance + void USART2_TX_DMA_Handler (uint32_t events) { USART_TX_DMA_Complete(&USART2_Resources); } +#endif +#ifdef MX_USART2_RX_DMA_Instance + void USART2_RX_DMA_Handler (uint32_t events) { USART_RX_DMA_Complete(&USART2_Resources); } +#endif + +// USART2 Driver Control Block +ARM_DRIVER_USART Driver_USART2 = { + USARTx_GetVersion, + USART2_GetCapabilities, + USART2_Initialize, + USART2_Uninitialize, + USART2_PowerControl, + USART2_Send, + USART2_Receive, + USART2_Transfer, + USART2_GetTxCount, + USART2_GetRxCount, + USART2_Control, + USART2_GetStatus, + USART2_SetModemControl, + USART2_GetModemStatus +}; +#endif + +#ifdef MX_USART3 +// USART3 Driver Wrapper functions +static ARM_USART_CAPABILITIES USART3_GetCapabilities (void) { return USART_GetCapabilities (&USART3_Resources); } +static int32_t USART3_Initialize (ARM_USART_SignalEvent_t cb_event) { return USART_Initialize (cb_event, &USART3_Resources); } +static int32_t USART3_Uninitialize (void) { return USART_Uninitialize (&USART3_Resources); } +static int32_t USART3_PowerControl (ARM_POWER_STATE state) { return USART_PowerControl (state, &USART3_Resources); } +static int32_t USART3_Send (const void *data, uint32_t num) { return USART_Send (data, num, &USART3_Resources); } +static int32_t USART3_Receive (void *data, uint32_t num) { return USART_Receive (data, num, &USART3_Resources); } +static int32_t USART3_Transfer (const void *data_out, void *data_in, uint32_t num) { return USART_Transfer (data_out, data_in, num, &USART3_Resources); } +static uint32_t USART3_GetTxCount (void) { return USART_GetTxCount (&USART3_Resources); } +static uint32_t USART3_GetRxCount (void) { return USART_GetRxCount (&USART3_Resources); } +static int32_t USART3_Control (uint32_t control, uint32_t arg) { return USART_Control (control, arg, &USART3_Resources); } +static ARM_USART_STATUS USART3_GetStatus (void) { return USART_GetStatus (&USART3_Resources); } +static int32_t USART3_SetModemControl (ARM_USART_MODEM_CONTROL control) { return USART_SetModemControl (control, &USART3_Resources); } +static ARM_USART_MODEM_STATUS USART3_GetModemStatus (void) { return USART_GetModemStatus (&USART3_Resources); } + void USART3_IRQHandler (void) { USART_IRQHandler (&USART3_Resources); } + +#ifdef MX_USART3_TX_DMA_Instance + void USART3_TX_DMA_Handler (uint32_t events) { USART_TX_DMA_Complete(&USART3_Resources); } +#endif +#ifdef MX_USART3_RX_DMA_Instance + void USART3_RX_DMA_Handler (uint32_t events) { USART_RX_DMA_Complete(&USART3_Resources); } +#endif + +// USART3 Driver Control Block +ARM_DRIVER_USART Driver_USART3 = { + USARTx_GetVersion, + USART3_GetCapabilities, + USART3_Initialize, + USART3_Uninitialize, + USART3_PowerControl, + USART3_Send, + USART3_Receive, + USART3_Transfer, + USART3_GetTxCount, + USART3_GetRxCount, + USART3_Control, + USART3_GetStatus, + USART3_SetModemControl, + USART3_GetModemStatus +}; +#endif + +#ifdef MX_UART4 +// USART4 Driver Wrapper functions +static ARM_USART_CAPABILITIES USART4_GetCapabilities (void) { return USART_GetCapabilities (&USART4_Resources); } +static int32_t USART4_Initialize (ARM_USART_SignalEvent_t cb_event) { return USART_Initialize (cb_event, &USART4_Resources); } +static int32_t USART4_Uninitialize (void) { return USART_Uninitialize (&USART4_Resources); } +static int32_t USART4_PowerControl (ARM_POWER_STATE state) { return USART_PowerControl (state, &USART4_Resources); } +static int32_t USART4_Send (const void *data, uint32_t num) { return USART_Send (data, num, &USART4_Resources); } +static int32_t USART4_Receive (void *data, uint32_t num) { return USART_Receive (data, num, &USART4_Resources); } +static int32_t USART4_Transfer (const void *data_out, void *data_in, uint32_t num) { return USART_Transfer (data_out, data_in, num, &USART4_Resources); } +static uint32_t USART4_GetTxCount (void) { return USART_GetTxCount (&USART4_Resources); } +static uint32_t USART4_GetRxCount (void) { return USART_GetRxCount (&USART4_Resources); } +static int32_t USART4_Control (uint32_t control, uint32_t arg) { return USART_Control (control, arg, &USART4_Resources); } +static ARM_USART_STATUS USART4_GetStatus (void) { return USART_GetStatus (&USART4_Resources); } +static int32_t USART4_SetModemControl (ARM_USART_MODEM_CONTROL control) { return USART_SetModemControl (control, &USART4_Resources); } +static ARM_USART_MODEM_STATUS USART4_GetModemStatus (void) { return USART_GetModemStatus (&USART4_Resources); } + void UART4_IRQHandler (void) { USART_IRQHandler (&USART4_Resources); } + +#ifdef MX_UART4_TX_DMA_Instance + void UART4_TX_DMA_Handler (uint32_t events) { USART_TX_DMA_Complete(&USART4_Resources); } +#endif +#ifdef MX_UART4_RX_DMA_Instance + void UART4_RX_DMA_Handler (uint32_t events) { USART_RX_DMA_Complete(&USART4_Resources); } +#endif + +// USART4 Driver Control Block +ARM_DRIVER_USART Driver_USART4 = { + USARTx_GetVersion, + USART4_GetCapabilities, + USART4_Initialize, + USART4_Uninitialize, + USART4_PowerControl, + USART4_Send, + USART4_Receive, + USART4_Transfer, + USART4_GetTxCount, + USART4_GetRxCount, + USART4_Control, + USART4_GetStatus, + USART4_SetModemControl, + USART4_GetModemStatus +}; +#endif + +#ifdef MX_UART5 +// USART5 Driver Wrapper functions +static ARM_USART_CAPABILITIES USART5_GetCapabilities (void) { return USART_GetCapabilities (&USART5_Resources); } +static int32_t USART5_Initialize (ARM_USART_SignalEvent_t cb_event) { return USART_Initialize (cb_event, &USART5_Resources); } +static int32_t USART5_Uninitialize (void) { return USART_Uninitialize (&USART5_Resources); } +static int32_t USART5_PowerControl (ARM_POWER_STATE state) { return USART_PowerControl (state, &USART5_Resources); } +static int32_t USART5_Send (const void *data, uint32_t num) { return USART_Send (data, num, &USART5_Resources); } +static int32_t USART5_Receive (void *data, uint32_t num) { return USART_Receive (data, num, &USART5_Resources); } +static int32_t USART5_Transfer (const void *data_out, void *data_in, uint32_t num) { return USART_Transfer (data_out, data_in, num, &USART5_Resources); } +static uint32_t USART5_GetTxCount (void) { return USART_GetTxCount (&USART5_Resources); } +static uint32_t USART5_GetRxCount (void) { return USART_GetRxCount (&USART5_Resources); } +static int32_t USART5_Control (uint32_t control, uint32_t arg) { return USART_Control (control, arg, &USART5_Resources); } +static ARM_USART_STATUS USART5_GetStatus (void) { return USART_GetStatus (&USART5_Resources); } +static int32_t USART5_SetModemControl (ARM_USART_MODEM_CONTROL control) { return USART_SetModemControl (control, &USART5_Resources); } +static ARM_USART_MODEM_STATUS USART5_GetModemStatus (void) { return USART_GetModemStatus (&USART5_Resources); } + void UART5_IRQHandler (void) { USART_IRQHandler (&USART5_Resources); } + +#ifdef MX_UART5_TX_DMA_Instance + void UART5_TX_DMA_Handler (uint32_t events) { USART_TX_DMA_Complete(&USART5_Resources); } +#endif +#ifdef MX_UART5_RX_DMA_Instance + void UART5_RX_DMA_Handler (uint32_t events) { USART_RX_DMA_Complete(&USART5_Resources); } +#endif + +// USART5 Driver Control Block +ARM_DRIVER_USART Driver_USART5 = { + USARTx_GetVersion, + USART5_GetCapabilities, + USART5_Initialize, + USART5_Uninitialize, + USART5_PowerControl, + USART5_Send, + USART5_Receive, + USART5_Transfer, + USART5_GetTxCount, + USART5_GetRxCount, + USART5_Control, + USART5_GetStatus, + USART5_SetModemControl, + USART5_GetModemStatus +}; +#endif diff --git a/source/hic_hal/stm32/stm32f103xb/cmsis/USART_STM32F10x.h b/source/hic_hal/stm32/stm32f103xb/cmsis/USART_STM32F10x.h new file mode 100644 index 0000000000..fba4c03495 --- /dev/null +++ b/source/hic_hal/stm32/stm32f103xb/cmsis/USART_STM32F10x.h @@ -0,0 +1,479 @@ +/* ----------------------------------------------------------------------------- + * Copyright (c) 2013-2016 Arm Limited (or its affiliates). 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 + * + * 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. + * + * + * $Date: 29. March 2016 + * $Revision: V2.2 + * + * Project: USART Driver definitions for ST STM32F1xx + * -------------------------------------------------------------------------- */ + +#ifndef __USART_STM32F1XX_H +#define __USART_STM32F1XX_H + +#include +#include +#include + +#include "stm32f1xx.h" +#include "GPIO_STM32F10x.h" +#include "DMA_STM32F10x.h" + +#include "Driver_USART.h" + +#include "RTE_Components.h" +#include "RTE_Device.h" + +#if ((defined(RTE_Drivers_USART1) || defined(RTE_Drivers_USART2) || \ + defined(RTE_Drivers_USART3) || defined(RTE_Drivers_USART4) || \ + defined(RTE_Drivers_USART5)) \ + && (RTE_USART1 == 0) \ + && (RTE_USART2 == 0) \ + && (RTE_USART3 == 0) \ + && (RTE_UART4 == 0) \ + && (RTE_UART5 == 0)) + #error "USART not configured in RTE_Device.h!" +#endif + +// USART1 configuration definitions +#if (RTE_USART1 == 1) + #define MX_USART1 + + #if (RTE_USART1_RX_DMA == 1) + #define MX_USART1_RX_DMA_Instance DMAx_CHANNELy(RTE_USART1_RX_DMA_NUMBER, RTE_USART1_RX_DMA_CHANNEL) + #define MX_USART1_RX_DMA_Number RTE_USART1_RX_DMA_NUMBER + #define MX_USART1_RX_DMA_Channel RTE_USART1_RX_DMA_CHANNEL + #define MX_USART1_RX_DMA_Priority RTE_USART1_RX_DMA_PRIORITY + + #define USART1_RX_DMA_Handler DMAx_CHANNELy_EVENT(RTE_USART1_RX_DMA_NUMBER, RTE_USART1_RX_DMA_CHANNEL) + #endif + #if (RTE_USART1_TX_DMA == 1) + #define MX_USART1_TX_DMA_Instance DMAx_CHANNELy(RTE_USART1_TX_DMA_NUMBER, RTE_USART1_TX_DMA_CHANNEL) + #define MX_USART1_TX_DMA_Number RTE_USART1_TX_DMA_NUMBER + #define MX_USART1_TX_DMA_Channel RTE_USART1_TX_DMA_CHANNEL + #define MX_USART1_TX_DMA_Priority RTE_USART1_TX_DMA_PRIORITY + + #define USART1_TX_DMA_Handler DMAx_CHANNELy_EVENT(RTE_USART1_TX_DMA_NUMBER, RTE_USART1_TX_DMA_CHANNEL) + #endif + + #if (RTE_USART1_TX == 1) + #define MX_USART1_TX_Pin 1U + #define MX_USART1_TX_GPIOx RTE_USART1_TX_PORT + #define MX_USART1_TX_GPIO_Pin RTE_USART1_TX_BIT + #endif + + #if (RTE_USART1_RX == 1) + #define MX_USART1_RX_Pin 1U + #define MX_USART1_RX_GPIOx RTE_USART1_RX_PORT + #define MX_USART1_RX_GPIO_Pin RTE_USART1_RX_BIT + #endif + + #if (RTE_USART1_CK == 1) + #define MX_USART1_CK_Pin 1U + #define MX_USART1_CK_GPIOx RTE_USART1_CK_PORT + #define MX_USART1_CK_GPIO_Pin RTE_USART1_CK_BIT + #endif + + + #if (RTE_USART1_RTS == 1) + #define MX_USART1_RTS_Pin 1U + #define MX_USART1_RTS_GPIOx RTE_USART1_RTS_PORT + #define MX_USART1_RTS_GPIO_Pin RTE_USART1_RTS_BIT + #endif + + #if (RTE_USART1_CTS == 1) + #define MX_USART1_CTS_Pin 1U + #define MX_USART1_CTS_GPIOx RTE_USART1_CTS_PORT + #define MX_USART1_CTS_GPIO_Pin RTE_USART1_CTS_BIT + #endif + + #define MX_USART1_REMAP_DEF AFIO_USART1_NO_REMAP + #define MX_USART1_REMAP RTE_USART1_AF_REMAP + +#endif + +// USART2 configuration definitions +#if (RTE_USART2 == 1) + #define MX_USART2 + + #if (RTE_USART2_RX_DMA == 1) + #define MX_USART2_RX_DMA_Instance DMAx_CHANNELy(RTE_USART2_RX_DMA_NUMBER, RTE_USART2_RX_DMA_CHANNEL) + #define MX_USART2_RX_DMA_Number RTE_USART2_RX_DMA_NUMBER + #define MX_USART2_RX_DMA_Channel RTE_USART2_RX_DMA_CHANNEL + #define MX_USART2_RX_DMA_Priority RTE_USART2_RX_DMA_PRIORITY + + #define USART2_RX_DMA_Handler DMAx_CHANNELy_EVENT(RTE_USART2_RX_DMA_NUMBER, RTE_USART2_RX_DMA_CHANNEL) + #endif + #if (RTE_USART2_TX_DMA == 1) + #define MX_USART2_TX_DMA_Instance DMAx_CHANNELy(RTE_USART2_TX_DMA_NUMBER, RTE_USART2_TX_DMA_CHANNEL) + #define MX_USART2_TX_DMA_Number RTE_USART2_TX_DMA_NUMBER + #define MX_USART2_TX_DMA_Channel RTE_USART2_TX_DMA_CHANNEL + #define MX_USART2_TX_DMA_Priority RTE_USART2_TX_DMA_PRIORITY + + #define USART2_TX_DMA_Handler DMAx_CHANNELy_EVENT(RTE_USART2_TX_DMA_NUMBER, RTE_USART2_TX_DMA_CHANNEL) + #endif + + #if (RTE_USART2_TX == 1) + #define MX_USART2_TX_Pin 1U + #define MX_USART2_TX_GPIOx RTE_USART2_TX_PORT + #define MX_USART2_TX_GPIO_Pin RTE_USART2_TX_BIT + #endif + + #if (RTE_USART2_RX == 1) + #define MX_USART2_RX_Pin 1U + #define MX_USART2_RX_GPIOx RTE_USART2_RX_PORT + #define MX_USART2_RX_GPIO_Pin RTE_USART2_RX_BIT + #endif + + #if (RTE_USART2_CK == 1) + #define MX_USART2_CK_Pin 1U + #define MX_USART2_CK_GPIOx RTE_USART2_CK_PORT + #define MX_USART2_CK_GPIO_Pin RTE_USART2_CK_BIT + #endif + + + #if (RTE_USART2_RTS == 1) + #define MX_USART2_RTS_Pin 1U + #define MX_USART2_RTS_GPIOx RTE_USART2_RTS_PORT + #define MX_USART2_RTS_GPIO_Pin RTE_USART2_RTS_BIT + #endif + + #if (RTE_USART2_CTS == 1) + #define MX_USART2_CTS_Pin 1U + #define MX_USART2_CTS_GPIOx RTE_USART2_CTS_PORT + #define MX_USART2_CTS_GPIO_Pin RTE_USART2_CTS_BIT + #endif + + #define MX_USART2_REMAP_DEF AFIO_USART2_NO_REMAP + #define MX_USART2_REMAP RTE_USART2_AF_REMAP + +#endif + +// USART3 configuration definitions +#if (RTE_USART3 == 1) + + #if defined (STM32F10X_LD) || defined (STM32F10X_LD_VL) + #error "USART3 is not available for selected device!" + #endif + + #define MX_USART3 + + #if (RTE_USART3_RX_DMA == 1) + #define MX_USART3_RX_DMA_Instance DMAx_CHANNELy(RTE_USART3_RX_DMA_NUMBER, RTE_USART3_RX_DMA_CHANNEL) + #define MX_USART3_RX_DMA_Number RTE_USART3_RX_DMA_NUMBER + #define MX_USART3_RX_DMA_Channel RTE_USART3_RX_DMA_CHANNEL + #define MX_USART3_RX_DMA_Priority RTE_USART3_RX_DMA_PRIORITY + + #define USART3_RX_DMA_Handler DMAx_CHANNELy_EVENT(RTE_USART3_RX_DMA_NUMBER, RTE_USART3_RX_DMA_CHANNEL) + #endif + #if (RTE_USART3_TX_DMA == 1) + #define MX_USART3_TX_DMA_Instance DMAx_CHANNELy(RTE_USART3_TX_DMA_NUMBER, RTE_USART3_TX_DMA_CHANNEL) + #define MX_USART3_TX_DMA_Number RTE_USART3_TX_DMA_NUMBER + #define MX_USART3_TX_DMA_Channel RTE_USART3_TX_DMA_CHANNEL + #define MX_USART3_TX_DMA_Priority RTE_USART3_TX_DMA_PRIORITY + + #define USART3_TX_DMA_Handler DMAx_CHANNELy_EVENT(RTE_USART3_TX_DMA_NUMBER, RTE_USART3_TX_DMA_CHANNEL) + #endif + + #if (RTE_USART3_TX == 1) + #define MX_USART3_TX_Pin 1U + #define MX_USART3_TX_GPIOx RTE_USART3_TX_PORT + #define MX_USART3_TX_GPIO_Pin RTE_USART3_TX_BIT + #endif + + #if (RTE_USART3_RX == 1) + #define MX_USART3_RX_Pin 1U + #define MX_USART3_RX_GPIOx RTE_USART3_RX_PORT + #define MX_USART3_RX_GPIO_Pin RTE_USART3_RX_BIT + #endif + + #if (RTE_USART3_CK == 1) + #define MX_USART3_CK_Pin 1U + #define MX_USART3_CK_GPIOx RTE_USART3_CK_PORT + #define MX_USART3_CK_GPIO_Pin RTE_USART3_CK_BIT + #endif + + + #if (RTE_USART3_RTS == 1) + #define MX_USART3_RTS_Pin 1U + #define MX_USART3_RTS_GPIOx RTE_USART3_RTS_PORT + #define MX_USART3_RTS_GPIO_Pin RTE_USART3_RTS_BIT + #endif + + #if (RTE_USART3_CTS == 1) + #define MX_USART3_CTS_Pin 1U + #define MX_USART3_CTS_GPIOx RTE_USART3_CTS_PORT + #define MX_USART3_CTS_GPIO_Pin RTE_USART3_CTS_BIT + #endif + + #define MX_USART3_REMAP_DEF AFIO_USART3_NO_REMAP + #define MX_USART3_REMAP RTE_USART3_AF_REMAP + +#endif + +// UART4 configuration definitions +#if (RTE_UART4 == 1) + + #if !defined(STM32F10X_HD) && !defined(STM32F10X_CL) && !defined(STM32F10X_XL) && !defined(STM32F10X_HD_VL) + #error "UART4 is not available for selected device!" + #endif + + #define MX_UART4 + + #if (RTE_UART4_RX_DMA == 1) + #define MX_UART4_RX_DMA_Instance DMAx_CHANNELy(RTE_UART4_RX_DMA_NUMBER, RTE_UART4_RX_DMA_CHANNEL) + #define MX_UART4_RX_DMA_Number RTE_UART4_RX_DMA_NUMBER + #define MX_UART4_RX_DMA_Channel RTE_UART4_RX_DMA_CHANNEL + #define MX_UART4_RX_DMA_Priority RTE_UART4_RX_DMA_PRIORITY + + #define UART4_RX_DMA_Handler DMAx_CHANNELy_EVENT(RTE_UART4_RX_DMA_NUMBER, RTE_UART4_RX_DMA_CHANNEL) + #endif + #if (RTE_UART4_TX_DMA == 1) + #define MX_UART4_TX_DMA_Instance DMAx_CHANNELy(RTE_UART4_TX_DMA_NUMBER, RTE_UART4_TX_DMA_CHANNEL) + #define MX_UART4_TX_DMA_Number RTE_UART4_TX_DMA_NUMBER + #define MX_UART4_TX_DMA_Channel RTE_UART4_TX_DMA_CHANNEL + #define MX_UART4_TX_DMA_Priority RTE_UART4_TX_DMA_PRIORITY + + #define UART4_TX_DMA_Handler DMAx_CHANNELy_EVENT(RTE_UART4_TX_DMA_NUMBER, RTE_UART4_TX_DMA_CHANNEL) + #endif + + #if (RTE_UART4_TX == 1) + #define MX_UART4_TX_Pin 1U + #define MX_UART4_TX_GPIOx RTE_UART4_TX_PORT + #define MX_UART4_TX_GPIO_Pin RTE_UART4_TX_BIT + #endif + + #if (RTE_UART4_RX == 1) + #define MX_UART4_RX_Pin 1U + #define MX_UART4_RX_GPIOx RTE_UART4_RX_PORT + #define MX_UART4_RX_GPIO_Pin RTE_UART4_RX_BIT + #endif + + #define MX_UART4_REMAP_DEF AFIO_UNAVAILABLE_REMAP + #define MX_UART4_REMAP AFIO_UNAVAILABLE_REMAP + +#endif + +// UART5 configuration definitions +#if (RTE_UART5 == 1) + + #if !defined(STM32F10X_HD) && !defined(STM32F10X_CL) && !defined(STM32F10X_XL) && !defined(STM32F10X_HD_VL) + #error "UART5 is not available for selected device!" + #endif + + #define MX_UART5 + + #if (RTE_UART5_RX_DMA == 1) + #define MX_UART5_RX_DMA_Instance DMAx_CHANNELy(RTE_UART5_RX_DMA_NUMBER, RTE_UART5_RX_DMA_CHANNEL) + #define MX_UART5_RX_DMA_Number RTE_UART5_RX_DMA_NUMBER + #define MX_UART5_RX_DMA_Channel RTE_UART5_RX_DMA_CHANNEL + #define MX_UART5_RX_DMA_Priority RTE_UART5_RX_DMA_PRIORITY + + #define UART5_RX_DMA_Handler DMAx_CHANNELy_EVENT(RTE_UART5_RX_DMA_NUMBER, RTE_UART5_RX_DMA_CHANNEL) + #endif + #if (RTE_UART5_TX_DMA == 1) + #define MX_UART5_TX_DMA_Instance DMAx_CHANNELy(RTE_UART5_TX_DMA_NUMBER, RTE_UART5_TX_DMA_CHANNEL) + #define MX_UART5_TX_DMA_Number RTE_UART5_TX_DMA_NUMBER + #define MX_UART5_TX_DMA_Channel RTE_UART5_TX_DMA_CHANNEL + #define MX_UART5_TX_DMA_Priority RTE_UART5_TX_DMA_PRIORITY + + #define UART5_TX_DMA_Handler DMAx_CHANNELy_EVENT(RTE_UART5_TX_DMA_NUMBER, RTE_UART5_TX_DMA_CHANNEL) + #endif + + #if (RTE_UART5_TX == 1) + #define MX_UART5_TX_Pin 1U + #define MX_UART5_TX_GPIOx RTE_UART5_TX_PORT + #define MX_UART5_TX_GPIO_Pin RTE_UART5_TX_BIT + #endif + + #if (RTE_UART5_RX == 1) + #define MX_UART5_RX_Pin 1U + #define MX_UART5_RX_GPIOx RTE_UART5_RX_PORT + #define MX_UART5_RX_GPIO_Pin RTE_UART5_RX_BIT + #endif + + #define MX_UART5_REMAP_DEF AFIO_UNAVAILABLE_REMAP + #define MX_UART5_REMAP AFIO_UNAVAILABLE_REMAP + +#endif + +#ifdef MX_USART1 +#if (defined(MX_USART1_RX_DMA_Instance) || defined(MX_USART1_TX_DMA_Instance)) +#ifndef MX_USART1_RX_DMA_Instance + #error "USART1 using DMA requires Rx and Tx DMA channel enabled in RTE_Device.h or MX_Device.h!" +#endif +#ifndef MX_USART1_TX_DMA_Instance + #error "USART1 using DMA requires Rx and Tx DMA channel enabled in RTE_Device.h or MX_Device.h!" +#endif +#endif +#endif + +#ifdef MX_USART2 +#if (defined(MX_USART2_RX_DMA_Instance) || defined(MX_USART2_TX_DMA_Instance)) +#ifndef MX_USART2_RX_DMA_Instance + #error "USART2 using DMA requires Rx and Tx DMA channel enabled in RTE_Device.h or MX_Device.h!" +#endif +#ifndef MX_USART2_TX_DMA_Instance + #error "USART2 using DMA requires Rx and Tx DMA channel enabled in RTE_Device.h or MX_Device.h!" +#endif +#endif +#endif + +#ifdef MX_USART3 +#if (defined(MX_USART3_RX_DMA_Instance) || defined(MX_USART3_TX_DMA_Instance)) +#ifndef MX_USART3_RX_DMA_Instance + #error "USART3 using DMA requires Rx and Tx DMA channel enabled in RTE_Device.h or MX_Device.h!" +#endif +#ifndef MX_USART3_TX_DMA_Instance + #error "USART3 using DMA requires Rx and Tx DMA channel enabled in RTE_Device.h or MX_Device.h!" +#endif +#endif +#endif + +#ifdef MX_UART4 +#if (defined(MX_UART4_RX_DMA_Instance) || defined(MX_UART4_TX_DMA_Instance)) +#ifndef MX_UART4_RX_DMA_Instance + #error "UART4 using DMA requires Rx and Tx DMA channel enabled in RTE_Device.h or MX_Device.h!" +#endif +#ifndef MX_UART4_TX_DMA_Instance + #error "UART4 using DMA requires Rx and Tx DMA channel enabled in RTE_Device.h or MX_Device.h!" +#endif +#endif +#endif + +#ifdef MX_UART5 +#if (defined(MX_UART5_RX_DMA_Instance) || defined(MX_UART5_TX_DMA_Instance)) +#ifndef MX_UART5_RX_DMA_Instance + #error "UART5 using DMA requires Rx and Tx DMA channel enabled in RTE_Device.h or MX_Device.h!" +#endif +#ifndef MX_UART5_TX_DMA_Instance + #error "UART5 using DMA requires Rx and Tx DMA channel enabled in RTE_Device.h or MX_Device.h!" +#endif +#endif +#endif + +#if (defined(MX_USART1_RX_DMA_Instance) || \ + defined(MX_USART2_RX_DMA_Instance) || \ + defined(MX_USART3_RX_DMA_Instance) || \ + defined(MX_UART4_RX_DMA_Instance ) || \ + defined(MX_UART5_RX_DMA_Instance )) +#define __USART_DMA_RX +#endif +#if (defined(MX_USART1_TX_DMA_Instance) || \ + defined(MX_USART2_TX_DMA_Instance) || \ + defined(MX_USART3_TX_DMA_Instance) || \ + defined(MX_UART4_TX_DMA_Instance ) || \ + defined(MX_UART5_TX_DMA_Instance )) +#define __USART_DMA_TX +#endif +#if (defined(__USART_DMA_RX) && defined(__USART_DMA_TX)) +#define __USART_DMA +#endif + +// USART BRR macro +#define USART_DIVIDER(_PCLK_, _BAUD_) (((_PCLK_)*25)/(4*(_BAUD_))) +#define USART_DIVIDER_MANTISA(_PCLK_, _BAUD_) (USART_DIVIDER((_PCLK_), (_BAUD_))/100) +#define USART_DIVIDER_FRACTION(_PCLK_, _BAUD_) (((USART_DIVIDER((_PCLK_), (_BAUD_)) - (USART_DIVIDER_MANTISA((_PCLK_), (_BAUD_)) * 100)) * 16 + 50) / 100) +#define USART_BAUDRATE_DIVIDER(_PCLK_, _BAUD_) ((USART_DIVIDER_MANTISA((_PCLK_), (_BAUD_)) << 4)|(USART_DIVIDER_FRACTION((_PCLK_), (_BAUD_)) & 0x0F)) + +// USART flags +#define USART_FLAG_INITIALIZED ((uint8_t)(1U)) +#define USART_FLAG_POWERED ((uint8_t)(1U << 1)) +#define USART_FLAG_CONFIGURED ((uint8_t)(1U << 2)) +#define USART_FLAG_TX_ENABLED ((uint8_t)(1U << 3)) +#define USART_FLAG_RX_ENABLED ((uint8_t)(1U << 4)) + +// USART synchronous xfer modes +#define USART_SYNC_MODE_TX ( 1UL ) +#define USART_SYNC_MODE_RX ( 2UL ) +#define USART_SYNC_MODE_TX_RX (USART_SYNC_MODE_TX | \ + USART_SYNC_MODE_RX) + +// USART DMA +typedef const struct _USART_DMA { + DMA_Channel_TypeDef *instance; // Channel registry interface + uint8_t dma_num; // DMA number + uint8_t ch_num; // Channel number + uint8_t priority; // Channel priority +} USART_DMA; + +// USART pin +typedef const struct _USART_PIN { + GPIO_TypeDef *port; // Port + uint16_t pin; // Pin +} USART_PIN; + +// USART Input/Output Configuration +typedef const struct _USART_IO { + USART_PIN *tx; // TX Pin identifier + USART_PIN *rx; // RX Pin identifier + USART_PIN *ck; // CLK Pin identifier + USART_PIN *rts; // RTS Pin identifier + USART_PIN *cts; // CTS Pin identifier + AFIO_REMAP afio_def; // Default pin remapping setting + AFIO_REMAP afio; // Pin remapping information +} USART_IO; + +// USART Transfer Information (Run-Time) +typedef struct _USART_TRANSFER_INFO { + uint32_t rx_num; // Total number of receive data + uint32_t tx_num; // Total number of transmit data + uint8_t *rx_buf; // Pointer to in data buffer + uint8_t *tx_buf; // Pointer to out data buffer + uint32_t rx_cnt; // Number of data received + uint32_t tx_cnt; // Number of data sent + uint16_t dump_val; // Variable for dumping DMA data + uint16_t def_val; // Default transfer value + uint32_t sync_mode; // Synchronous mode flag + uint8_t break_flag; // Transmit break flag + uint8_t send_active; // Send active flag +} USART_TRANSFER_INFO; + +typedef struct _USART_STATUS { + uint8_t tx_busy; // Transmitter busy flag + uint8_t rx_busy; // Receiver busy flag + uint8_t tx_underflow; // Transmit data underflow detected (cleared on start of next send operation) + uint8_t rx_overflow; // Receive data overflow detected (cleared on start of next receive operation) + uint8_t rx_break; // Break detected on receive (cleared on start of next receive operation) + uint8_t rx_framing_error; // Framing error detected on receive (cleared on start of next receive operation) + uint8_t rx_parity_error; // Parity error detected on receive (cleared on start of next receive operation) +} USART_STATUS; + +// USART Information (Run-time) +typedef struct _USART_INFO { + ARM_USART_SignalEvent_t cb_event; // Event Callback + USART_STATUS status; // Status flags + uint8_t flags; // Current USART flags + uint32_t mode; // Current USART mode + uint32_t flow_control; // Flow control +} USART_INFO; + +// USART Resources definition +typedef const struct { + ARM_USART_CAPABILITIES capabilities; // Capabilities + USART_TypeDef *reg; // USART peripheral pointer + uint32_t pclk; // Peripheral clock frequency + USART_IO io; // USART Input/Output pins + IRQn_Type irq_num; // USART IRQ Number + USART_DMA *dma_tx; // Transmit stream register interface + USART_DMA *dma_rx; // Receive stream register interface + USART_INFO *info; // Run-Time Information + USART_TRANSFER_INFO *xfer; // USART transfer information +} USART_RESOURCES; + +#endif /* __USART_STM32F1XX_H */ diff --git a/source/hic_hal/stm32/stm32f103xb/uart.c b/source/hic_hal/stm32/stm32f103xb/uart.c deleted file mode 100644 index d982be84f2..0000000000 --- a/source/hic_hal/stm32/stm32f103xb/uart.c +++ /dev/null @@ -1,262 +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 "stm32f1xx.h" -#include "uart.h" -#include "gpio.h" -#include "util.h" -#include "circ_buf.h" -#include "IO_Config.h" - -// For usart -#define CDC_UART USART2 -#define CDC_UART_ENABLE() __HAL_RCC_USART2_CLK_ENABLE() -#define CDC_UART_DISABLE() __HAL_RCC_USART2_CLK_DISABLE() -#define CDC_UART_IRQn USART2_IRQn -#define CDC_UART_IRQn_Handler USART2_IRQHandler - -#define UART_PINS_PORT_ENABLE() __HAL_RCC_GPIOA_CLK_ENABLE() -#define UART_PINS_PORT_DISABLE() __HAL_RCC_GPIOA_CLK_DISABLE() - -#define UART_TX_PORT GPIOA -#define UART_TX_PIN GPIO_PIN_2 - -#define UART_RX_PORT GPIOA -#define UART_RX_PIN GPIO_PIN_3 - -#define UART_CTS_PORT GPIOA -#define UART_CTS_PIN GPIO_PIN_0 - -#define UART_RTS_PORT GPIOA -#define UART_RTS_PIN GPIO_PIN_1 - - -#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]; - -static UART_Configuration configuration = { - .Baudrate = 9600, - .DataBits = UART_DATA_BITS_8, - .Parity = UART_PARITY_NONE, - .StopBits = UART_STOP_BITS_1, - .FlowControl = UART_FLOW_CONTROL_NONE, -}; - -extern uint32_t SystemCoreClock; - - - -static void clear_buffers(void) -{ - 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) -{ - GPIO_InitTypeDef GPIO_InitStructure; - - CDC_UART->CR1 &= ~(USART_IT_TXE | USART_IT_RXNE); - clear_buffers(); - - CDC_UART_ENABLE(); - UART_PINS_PORT_ENABLE(); - - //TX pin - GPIO_InitStructure.Pin = UART_TX_PIN; - GPIO_InitStructure.Speed = GPIO_SPEED_FREQ_HIGH; - GPIO_InitStructure.Mode = GPIO_MODE_AF_PP; - HAL_GPIO_Init(UART_TX_PORT, &GPIO_InitStructure); - //RX pin - GPIO_InitStructure.Pin = UART_RX_PIN; - GPIO_InitStructure.Speed = GPIO_SPEED_FREQ_HIGH; - GPIO_InitStructure.Mode = GPIO_MODE_INPUT; - GPIO_InitStructure.Pull = GPIO_PULLUP; - HAL_GPIO_Init(UART_RX_PORT, &GPIO_InitStructure); - //CTS pin, input - GPIO_InitStructure.Pin = UART_CTS_PIN; - GPIO_InitStructure.Speed = GPIO_SPEED_FREQ_HIGH; - GPIO_InitStructure.Mode = GPIO_MODE_INPUT; - GPIO_InitStructure.Pull = GPIO_PULLUP; - HAL_GPIO_Init(UART_CTS_PORT, &GPIO_InitStructure); - //RTS pin, output low - HAL_GPIO_WritePin(UART_RTS_PORT, UART_RTS_PIN, GPIO_PIN_RESET); - GPIO_InitStructure.Pin = UART_RTS_PIN; - GPIO_InitStructure.Speed = GPIO_SPEED_FREQ_HIGH; - GPIO_InitStructure.Mode = GPIO_MODE_OUTPUT_PP; - HAL_GPIO_Init(UART_RTS_PORT, &GPIO_InitStructure); - - NVIC_EnableIRQ(CDC_UART_IRQn); - - return 1; -} - -int32_t uart_uninitialize(void) -{ - CDC_UART->CR1 &= ~(USART_IT_TXE | USART_IT_RXNE); - clear_buffers(); - return 1; -} - -int32_t uart_reset(void) -{ - const uint32_t cr1 = CDC_UART->CR1; - CDC_UART->CR1 = cr1 & ~(USART_IT_TXE | USART_IT_RXNE); - clear_buffers(); - CDC_UART->CR1 = cr1 & ~USART_IT_TXE; - return 1; -} - -int32_t uart_set_configuration(UART_Configuration *config) -{ - UART_HandleTypeDef uart_handle; - HAL_StatusTypeDef status; - - memset(&uart_handle, 0, sizeof(uart_handle)); - uart_handle.Instance = CDC_UART; - - // parity - configuration.Parity = config->Parity; - if(config->Parity == UART_PARITY_ODD) { - uart_handle.Init.Parity = HAL_UART_PARITY_ODD; - } else if(config->Parity == UART_PARITY_EVEN) { - uart_handle.Init.Parity = HAL_UART_PARITY_EVEN; - } else if(config->Parity == UART_PARITY_NONE) { - uart_handle.Init.Parity = HAL_UART_PARITY_NONE; - } else { //Other not support - uart_handle.Init.Parity = HAL_UART_PARITY_NONE; - configuration.Parity = UART_PARITY_NONE; - } - - // stop bits - configuration.StopBits = config->StopBits; - if(config->StopBits == UART_STOP_BITS_2) { - uart_handle.Init.StopBits = UART_STOPBITS_2; - } else if(config->StopBits == UART_STOP_BITS_1_5) { - uart_handle.Init.StopBits = UART_STOPBITS_2; - configuration.StopBits = UART_STOP_BITS_2; - } else if(config->StopBits == UART_STOP_BITS_1) { - uart_handle.Init.StopBits = UART_STOPBITS_1; - } else { - uart_handle.Init.StopBits = UART_STOPBITS_1; - configuration.StopBits = UART_STOP_BITS_1; - } - - //Only 8 bit support - configuration.DataBits = UART_DATA_BITS_8; - if (uart_handle.Init.Parity == HAL_UART_PARITY_ODD || uart_handle.Init.Parity == HAL_UART_PARITY_EVEN) { - uart_handle.Init.WordLength = UART_WORDLENGTH_9B; - } else { - uart_handle.Init.WordLength = UART_WORDLENGTH_8B; - } - - // No flow control - configuration.FlowControl = UART_FLOW_CONTROL_NONE; - uart_handle.Init.HwFlowCtl = UART_HWCONTROL_NONE; - - // Specified baudrate - configuration.Baudrate = config->Baudrate; - uart_handle.Init.BaudRate = config->Baudrate; - - // TX and RX - uart_handle.Init.Mode = UART_MODE_TX_RX; - - // Disable uart and tx/rx interrupt - CDC_UART->CR1 &= ~(USART_IT_TXE | USART_IT_RXNE); - - clear_buffers(); - - status = HAL_UART_DeInit(&uart_handle); - util_assert(HAL_OK == status); - status = HAL_UART_Init(&uart_handle); - util_assert(HAL_OK == status); - (void)status; - - CDC_UART->CR1 |= USART_IT_RXNE; - - return 1; -} - -int32_t uart_get_configuration(UART_Configuration *config) -{ - config->Baudrate = configuration.Baudrate; - config->DataBits = configuration.DataBits; - config->Parity = configuration.Parity; - config->StopBits = configuration.StopBits; - config->FlowControl = UART_FLOW_CONTROL_NONE; - - return 1; -} - -void uart_set_control_line_state(uint16_t ctrl_bmp) -{ -} - -int32_t uart_write_free(void) -{ - return circ_buf_count_free(&write_buffer); -} - -int32_t uart_write_data(uint8_t *data, uint16_t size) -{ - uint32_t cnt = circ_buf_write(&write_buffer, data, size); - CDC_UART->CR1 |= USART_IT_TXE; - - return cnt; -} - -int32_t uart_read_data(uint8_t *data, uint16_t size) -{ - return circ_buf_read(&read_buffer, data, size); -} - -void CDC_UART_IRQn_Handler(void) -{ - const uint32_t sr = CDC_UART->SR; - - if (sr & USART_SR_RXNE) { - uint8_t dat = CDC_UART->DR; - uint32_t free = circ_buf_count_free(&read_buffer); - if (free > RX_OVRF_MSG_SIZE) { - circ_buf_push(&read_buffer, dat); - } else if (RX_OVRF_MSG_SIZE == free) { - circ_buf_write(&read_buffer, (uint8_t*)RX_OVRF_MSG, RX_OVRF_MSG_SIZE); - } else { - // Drop character - } - } - - if (sr & USART_SR_TXE) { - if (circ_buf_count_used(&write_buffer) > 0) { - CDC_UART->DR = circ_buf_pop(&write_buffer); - } else { - CDC_UART->CR1 &= ~USART_IT_TXE; - } - } -}