From 258db6867b305970313ab0413b3e37213456df6c Mon Sep 17 00:00:00 2001 From: jflyper Date: Sat, 6 Jul 2019 21:32:44 +0900 Subject: [PATCH] [G4] UART support --- src/main/drivers/serial_uart.c | 18 +- src/main/drivers/serial_uart_hal.c | 40 ++- src/main/drivers/serial_uart_impl.h | 19 +- src/main/drivers/serial_uart_stm32g4xx.c | 323 +++++++++++++++++++++++ 4 files changed, 385 insertions(+), 15 deletions(-) create mode 100644 src/main/drivers/serial_uart_stm32g4xx.c diff --git a/src/main/drivers/serial_uart.c b/src/main/drivers/serial_uart.c index 7d788c08f..842849634 100644 --- a/src/main/drivers/serial_uart.c +++ b/src/main/drivers/serial_uart.c @@ -46,18 +46,24 @@ #include "pg/serial_uart.h" #if defined(STM32H7) -#define UART_BUFFER_ATTRIBUTE DMA_RAM // D2 SRAM +#define UART_TX_BUFFER_ATTRIBUTE DMA_RAM // D2 SRAM +#define UART_RX_BUFFER_ATTRIBUTE DMA_RAM // D2 SRAM +#elif defined(STM32G4) +#define UART_TX_BUFFER_ATTRIBUTE DMA_RAM_W // SRAM MPU NOT_BUFFERABLE +#define UART_RX_BUFFER_ATTRIBUTE DMA_RAM_R // SRAM MPU NOT CACHABLE #elif defined(STM32F7) -#define UART_BUFFER_ATTRIBUTE FAST_RAM_ZERO_INIT // DTCM RAM +#define UART_TX_BUFFER_ATTRIBUTE FAST_RAM_ZERO_INIT // DTCM RAM +#define UART_RX_BUFFER_ATTRIBUTE FAST_RAM_ZERO_INIT // DTCM RAM #elif defined(STM32F4) || defined(STM32F3) || defined(STM32F1) -#define UART_BUFFER_ATTRIBUTE // NONE +#define UART_TX_BUFFER_ATTRIBUTE // NONE +#define UART_RX_BUFFER_ATTRIBUTE // NONE #else -#error Undefined UART_BUFFER_ATTRIBUTE for this MCU +#error Undefined UART_{TX,RX}_BUFFER_ATTRIBUTE for this MCU #endif #define UART_BUFFERS(n) \ - UART_BUFFER(UART_BUFFER_ATTRIBUTE, n, R); \ - UART_BUFFER(UART_BUFFER_ATTRIBUTE, n, T); struct dummy_s + UART_BUFFER(UART_TX_BUFFER_ATTRIBUTE, n, T); \ + UART_BUFFER(UART_RX_BUFFER_ATTRIBUTE, n, R); struct dummy_s #ifdef USE_UART1 UART_BUFFERS(1); diff --git a/src/main/drivers/serial_uart_hal.c b/src/main/drivers/serial_uart_hal.c index 224be9408..06a56f8c1 100644 --- a/src/main/drivers/serial_uart_hal.c +++ b/src/main/drivers/serial_uart_hal.c @@ -78,6 +78,11 @@ void uartReconfigure(uartPort_t *uartPort) uartPort->Handle.Init.HwFlowCtl = UART_HWCONTROL_NONE; uartPort->Handle.Init.OneBitSampling = UART_ONE_BIT_SAMPLE_DISABLE; uartPort->Handle.Init.Mode = 0; +#if defined(STM32G4) || defined(STM32H7) + if (uartPort->Handle.Instance == LPUART1) { + uartPort->Handle.Init.ClockPrescaler = UART_PRESCALER_DIV8; + } +#endif if (uartPort->port.mode & MODE_RX) uartPort->Handle.Init.Mode |= UART_MODE_RX; @@ -108,7 +113,7 @@ void uartReconfigure(uartPort_t *uartPort) if (uartPort->rxDMAResource) { uartPort->rxDMAHandle.Instance = (DMA_ARCH_TYPE *)uartPort->rxDMAResource; -#if !defined(STM32H7) +#if !(defined(STM32H7) || defined(STM32G4)) uartPort->rxDMAHandle.Init.Channel = uartPort->rxDMAChannel; #else uartPort->txDMAHandle.Init.Request = uartPort->rxDMAChannel; @@ -119,10 +124,12 @@ void uartReconfigure(uartPort_t *uartPort) uartPort->rxDMAHandle.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE; uartPort->rxDMAHandle.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE; uartPort->rxDMAHandle.Init.Mode = DMA_CIRCULAR; +#if defined(STM32F4) || defined(STM32F7) || defined(STM32H7) uartPort->rxDMAHandle.Init.FIFOMode = DMA_FIFOMODE_DISABLE; uartPort->rxDMAHandle.Init.FIFOThreshold = DMA_FIFO_THRESHOLD_1QUARTERFULL; uartPort->rxDMAHandle.Init.PeriphBurst = DMA_PBURST_SINGLE; uartPort->rxDMAHandle.Init.MemBurst = DMA_MBURST_SINGLE; +#endif uartPort->rxDMAHandle.Init.Priority = DMA_PRIORITY_MEDIUM; @@ -156,7 +163,7 @@ void uartReconfigure(uartPort_t *uartPort) #ifdef USE_DMA if (uartPort->txDMAResource) { uartPort->txDMAHandle.Instance = (DMA_ARCH_TYPE *)uartPort->txDMAResource; -#if !defined(STM32H7) +#if !(defined(STM32H7) || defined(STM32G4)) uartPort->txDMAHandle.Init.Channel = uartPort->txDMAChannel; #else uartPort->txDMAHandle.Init.Request = uartPort->txDMAChannel; @@ -167,10 +174,13 @@ void uartReconfigure(uartPort_t *uartPort) uartPort->txDMAHandle.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE; uartPort->txDMAHandle.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE; uartPort->txDMAHandle.Init.Mode = DMA_NORMAL; +#if !defined(STM32G4) + // G4's DMA is channel based, and does not have FIFO uartPort->txDMAHandle.Init.FIFOMode = DMA_FIFOMODE_DISABLE; uartPort->txDMAHandle.Init.FIFOThreshold = DMA_FIFO_THRESHOLD_1QUARTERFULL; uartPort->txDMAHandle.Init.PeriphBurst = DMA_PBURST_SINGLE; uartPort->txDMAHandle.Init.MemBurst = DMA_MBURST_SINGLE; +#endif uartPort->txDMAHandle.Init.Priority = DMA_PRIORITY_MEDIUM; @@ -206,6 +216,7 @@ void uartTryStartTxDMA(uartPort_t *s) HAL_UART_StateTypeDef state = HAL_UART_GetState(&s->Handle); if ((state & HAL_UART_STATE_BUSY_TX) == HAL_UART_STATE_BUSY_TX) { + // UART is still transmitting return; } @@ -239,7 +250,24 @@ static void handleUsartTxDma(uartPort_t *s) void uartDmaIrqHandler(dmaChannelDescriptor_t* descriptor) { uartPort_t *s = &(((uartDevice_t*)(descriptor->userParam))->port); + HAL_DMA_IRQHandler(&s->txDMAHandle); + +#ifdef STM32G4 + // G4's DMA HAL turns on half transfer interrupt. + // Only detect the transfer complete interrupt by checking remaining transfer count. + // XXX TODO Consider using HAL's XferCpltCallback facility to do this. + + if (s->txDMAHandle.Instance->CNDTR == 0) { + + // Unlike other stream based DMA implementations (F4, F7 and H7), + // G4's DMA implementation does not clear EN bit upon completion of a transfer, + // and it is neccesary to clear the EN bit explicitly here for IS_DMA_ENABLED macro + // used in uartTryStartTxDMA() to continue working with G4. + + __HAL_DMA_DISABLE(&s->txDMAHandle); + } +#endif } #endif @@ -284,7 +312,8 @@ void uartIrqHandler(uartPort_t *s) __HAL_UART_CLEAR_IT(huart, UART_CLEAR_OREF); } - /* UART in mode Transmitter ------------------------------------------------*/ + // UART transmitter in interrupting mode, tx buffer empty + if ( #ifdef USE_DMA !s->txDMAResource && @@ -307,7 +336,8 @@ void uartIrqHandler(uartPort_t *s) } } - /* UART in mode Transmitter (transmission end) -----------------------------*/ + // UART transmitter in DMA mode, transmission completed + if ((__HAL_UART_GET_IT(huart, UART_IT_TC) != RESET)) { HAL_UART_IRQHandler(huart); #ifdef USE_DMA @@ -317,6 +347,8 @@ void uartIrqHandler(uartPort_t *s) #endif } + // UART reception idle detected + if (__HAL_UART_GET_IT(huart, UART_IT_IDLE)) { if (s->port.idleCallback) { s->port.idleCallback(); diff --git a/src/main/drivers/serial_uart_impl.h b/src/main/drivers/serial_uart_impl.h index 6c4482ddf..81b3e248b 100644 --- a/src/main/drivers/serial_uart_impl.h +++ b/src/main/drivers/serial_uart_impl.h @@ -67,6 +67,15 @@ #ifndef UART_TX_BUFFER_SIZE #define UART_TX_BUFFER_SIZE 256 #endif +#elif defined(STM32G4) +#define UARTDEV_COUNT_MAX 6 +#define UARTHARDWARE_MAX_PINS 3 +#ifndef UART_RX_BUFFER_SIZE +#define UART_RX_BUFFER_SIZE 128 +#endif +#ifndef UART_TX_BUFFER_SIZE +#define UART_TX_BUFFER_SIZE 256 +#endif #else #error unknown MCU family #endif @@ -125,7 +134,7 @@ typedef struct uartPinDef_s { ioTag_t pin; -#if defined(STM32F7) || defined(STM32H7) +#if defined(STM32F7) || defined(STM32H7) || defined(STM32G4) uint8_t af; #endif } uartPinDef_t; @@ -137,7 +146,7 @@ typedef struct uartHardware_s { #ifdef USE_DMA dmaResource_t *txDMAResource; dmaResource_t *rxDMAResource; - // For H7, {tx|rx}DMAChannel are DMAMUX input index for peripherals (DMA_REQUEST_xxx); RM0433 Table 110. + // For H7 and G4, {tx|rx}DMAChannel are DMAMUX input index for peripherals (DMA_REQUEST_xxx); H7:RM0433 Table 110, G4:RM0440 Table 80. // For F4 and F7, these are 32-bit channel identifiers (DMA_CHANNEL_x). uint32_t txDMAChannel; uint32_t rxDMAChannel; @@ -146,7 +155,7 @@ typedef struct uartHardware_s { uartPinDef_t rxPins[UARTHARDWARE_MAX_PINS]; uartPinDef_t txPins[UARTHARDWARE_MAX_PINS]; -#if defined(STM32F7) || defined(STM32H7) +#if defined(STM32F7) || defined(STM32H7) || defined(STM32G4) uint32_t rcc_ahb1; rccPeriphTag_t rcc_apb2; rccPeriphTag_t rcc_apb1; @@ -158,7 +167,7 @@ typedef struct uartHardware_s { uint8_t af; #endif -#if defined(STM32F7) || defined(STM32H7) +#if defined(STM32F7) || defined(STM32H7) || defined(STM32G4) uint8_t txIrq; uint8_t rxIrq; #else @@ -203,7 +212,7 @@ void uartConfigureDma(uartDevice_t *uartdev); void uartDmaIrqHandler(dmaChannelDescriptor_t* descriptor); -#if defined(STM32F3) || defined(STM32F7) || defined(STM32H7) +#if defined(STM32F3) || defined(STM32F7) || defined(STM32H7) || defined(STM32G4) #define UART_REG_RXD(base) ((base)->RDR) #define UART_REG_TXD(base) ((base)->TDR) #elif defined(STM32F1) || defined(STM32F4) diff --git a/src/main/drivers/serial_uart_stm32g4xx.c b/src/main/drivers/serial_uart_stm32g4xx.c new file mode 100644 index 000000000..fff82d3eb --- /dev/null +++ b/src/main/drivers/serial_uart_stm32g4xx.c @@ -0,0 +1,323 @@ +/* + * This file is part of Cleanflight and Betaflight. + * + * Cleanflight and Betaflight are free software. You can redistribute + * this software and/or modify this software under the terms of the + * GNU General Public License as published by the Free Software + * Foundation, either version 3 of the License, or (at your option) + * any later version. + * + * Cleanflight and Betaflight are distributed in the hope that they + * will be useful, but WITHOUT ANY WARRANTY; without even the implied + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this software. + * + * If not, see . + * + * Author: jflyper + */ + +#include +#include + +#include "platform.h" + +#ifdef USE_UART + +#include "drivers/system.h" +#include "drivers/dma.h" +#include "drivers/io.h" +#include "drivers/nvic.h" +#include "drivers/rcc.h" + +#include "drivers/serial.h" +#include "drivers/serial_uart.h" +#include "drivers/serial_uart_impl.h" + +#ifndef UART1_TX_DMA_CHANNEL +#define UART1_TX_DMA_CHANNEL NULL +#endif +#ifndef UART1_RX_DMA_CHANNEL +#define UART1_RX_DMA_CHANNEL NULL +#endif +#ifndef UART2_TX_DMA_CHANNEL +#define UART2_TX_DMA_CHANNEL NULL +#endif +#ifndef UART2_RX_DMA_CHANNEL +#define UART2_RX_DMA_CHANNEL NULL +#endif +#ifndef UART3_TX_DMA_CHANNEL +#define UART3_TX_DMA_CHANNEL NULL +#endif +#ifndef UART3_RX_DMA_CHANNEL +#define UART3_RX_DMA_CHANNEL NULL +#endif +#ifndef UART4_TX_DMA_CHANNEL +#define UART4_TX_DMA_CHANNEL NULL +#endif +#ifndef UART4_RX_DMA_CHANNEL +#define UART4_RX_DMA_CHANNEL NULL +#endif +#ifndef UART5_TX_DMA_CHANNEL +#define UART5_TX_DMA_CHANNEL NULL +#endif +#ifndef UART5_RX_DMA_CHANNEL +#define UART5_RX_DMA_CHANNEL NULL +#endif +#ifndef UART6_TX_DMA_CHANNEL +#define UART6_TX_DMA_CHANNEL NULL +#endif +#ifndef UART6_RX_DMA_CHANNEL +#define UART6_RX_DMA_CHANNEL NULL +#endif + +const uartHardware_t uartHardware[UARTDEV_COUNT] = { +#ifdef USE_UART1 + { + .device = UARTDEV_1, + .reg = USART1, +#ifdef USE_DMA + .rxDMAChannel = DMA_REQUEST_USART1_RX, + .rxDMAResource = (dmaResource_t *)UART1_RX_DMA_CHANNEL, + .txDMAChannel = DMA_REQUEST_USART1_TX, + .txDMAResource = (dmaResource_t *)UART1_TX_DMA_CHANNEL, +#endif + .rxPins = { + { DEFIO_TAG_E(PA10), GPIO_AF7_USART1 }, + { DEFIO_TAG_E(PB7), GPIO_AF7_USART1 }, + { DEFIO_TAG_E(PC5), GPIO_AF7_USART1 }, + }, + .txPins = { + { DEFIO_TAG_E(PA9), GPIO_AF7_USART1 }, + { DEFIO_TAG_E(PB6), GPIO_AF7_USART1 }, + { DEFIO_TAG_E(PC4), GPIO_AF7_USART1 }, + }, + .rcc_apb2 = RCC_APB2(USART1), + .rxIrq = USART1_IRQn, + .txPriority = NVIC_PRIO_SERIALUART1_TXDMA, + .rxPriority = NVIC_PRIO_SERIALUART1, + .txBuffer = uart1TxBuffer, + .rxBuffer = uart1RxBuffer, + .txBufferSize = sizeof(uart1TxBuffer), + .rxBufferSize = sizeof(uart1RxBuffer), + }, +#endif + +#ifdef USE_UART2 + { + .device = UARTDEV_2, + .reg = USART2, +#ifdef USE_DMA + .rxDMAChannel = DMA_REQUEST_USART2_RX, + .rxDMAResource = (dmaResource_t *)UART2_RX_DMA_CHANNEL, + .txDMAChannel = DMA_REQUEST_USART2_TX, + .txDMAResource = (dmaResource_t *)UART2_TX_DMA_CHANNEL, +#endif + .rxPins = { + { DEFIO_TAG_E(PA3), GPIO_AF7_USART2 }, + { DEFIO_TAG_E(PA15), GPIO_AF7_USART2 }, + { DEFIO_TAG_E(PB4), GPIO_AF7_USART2 }, + }, + .txPins = { + { DEFIO_TAG_E(PA2), GPIO_AF7_USART2 }, + { DEFIO_TAG_E(PA14), GPIO_AF7_USART2 }, + { DEFIO_TAG_E(PB3), GPIO_AF7_USART2 }, + }, + .rcc_apb1 = RCC_APB11(USART2), + .rxIrq = USART2_IRQn, + .txPriority = NVIC_PRIO_SERIALUART2_TXDMA, + .rxPriority = NVIC_PRIO_SERIALUART2, + .txBuffer = uart2TxBuffer, + .rxBuffer = uart2RxBuffer, + .txBufferSize = sizeof(uart2TxBuffer), + .rxBufferSize = sizeof(uart2RxBuffer), + }, +#endif + +#ifdef USE_UART3 + { + .device = UARTDEV_3, + .reg = USART3, +#ifdef USE_DMA + .rxDMAChannel = DMA_REQUEST_USART3_RX, + .rxDMAResource = (dmaResource_t *)UART3_RX_DMA_CHANNEL, + .txDMAChannel = DMA_REQUEST_USART3_TX, + .txDMAResource = (dmaResource_t *)UART3_TX_DMA_CHANNEL, +#endif + .rxPins = { + { DEFIO_TAG_E(PB8), GPIO_AF7_USART3 }, + { DEFIO_TAG_E(PB11), GPIO_AF7_USART3 }, + { DEFIO_TAG_E(PC11), GPIO_AF7_USART3 }, + }, + .txPins = { + { DEFIO_TAG_E(PB9), GPIO_AF7_USART3 }, + { DEFIO_TAG_E(PB10), GPIO_AF7_USART3 }, + { DEFIO_TAG_E(PC10), GPIO_AF7_USART3 }, + }, + .rcc_apb1 = RCC_APB11(USART3), + .rxIrq = USART3_IRQn, + .txPriority = NVIC_PRIO_SERIALUART3_TXDMA, + .rxPriority = NVIC_PRIO_SERIALUART3, + .txBuffer = uart3TxBuffer, + .rxBuffer = uart3RxBuffer, + .txBufferSize = sizeof(uart3TxBuffer), + .rxBufferSize = sizeof(uart3RxBuffer), + }, +#endif + +#ifdef USE_UART4 + { + .device = UARTDEV_4, + .reg = UART4, +#ifdef USE_DMA + .rxDMAChannel = DMA_REQUEST_UART4_RX, + .rxDMAResource = (dmaResource_t *)UART4_RX_DMA_CHANNEL, + .txDMAChannel = DMA_REQUEST_UART4_TX, + .txDMAResource = (dmaResource_t *)UART4_TX_DMA_CHANNEL, +#endif + .rxPins = { + { DEFIO_TAG_E(PC11), GPIO_AF5_UART4 }, + }, + .txPins = { + { DEFIO_TAG_E(PC10), GPIO_AF5_UART4 }, + }, + .rcc_apb1 = RCC_APB11(UART4), + .rxIrq = UART4_IRQn, + .txPriority = NVIC_PRIO_SERIALUART4_TXDMA, + .rxPriority = NVIC_PRIO_SERIALUART4, + .txBuffer = uart4TxBuffer, + .rxBuffer = uart4RxBuffer, + .txBufferSize = sizeof(uart4TxBuffer), + .rxBufferSize = sizeof(uart4RxBuffer), + }, +#endif + +#ifdef USE_UART5 + { + .device = UARTDEV_5, + .reg = UART5, +#ifdef USE_DMA + .rxDMAChannel = DMA_REQUEST_UART5_RX, + .rxDMAResource = (dmaResource_t *)UART5_RX_DMA_CHANNEL, + .txDMAChannel = DMA_REQUEST_UART5_TX, + .txDMAResource = (dmaResource_t *)UART5_TX_DMA_CHANNEL, +#endif + .rxPins = { + { DEFIO_TAG_E(PD2), GPIO_AF5_UART5 }, + }, + .txPins = { + { DEFIO_TAG_E(PC12), GPIO_AF5_UART5 }, + }, + .rcc_apb1 = RCC_APB11(UART5), + .rxIrq = UART5_IRQn, + .txPriority = NVIC_PRIO_SERIALUART5_TXDMA, + .rxPriority = NVIC_PRIO_SERIALUART5, + .txBuffer = uart5TxBuffer, + .rxBuffer = uart5RxBuffer, + .txBufferSize = sizeof(uart5TxBuffer), + .rxBufferSize = sizeof(uart5RxBuffer), + }, +#endif + +#ifdef USE_UART6 + // On G474, UART6 is implemented as LPUART1 + { + .device = UARTDEV_6, + .reg = LPUART1, +#ifdef USE_DMA + .rxDMAChannel = DMA_REQUEST_LPUART1_RX, + .rxDMAResource = (dmaResource_t *)UART6_RX_DMA_CHANNEL, + .txDMAChannel = DMA_REQUEST_LPUART1_TX, + .txDMAResource = (dmaResource_t *)UART6_TX_DMA_CHANNEL, +#endif + .rxPins = { + { DEFIO_TAG_E(PA3), GPIO_AF12_LPUART1 }, + { DEFIO_TAG_E(PB10), GPIO_AF8_LPUART1 }, + { DEFIO_TAG_E(PC0), GPIO_AF8_LPUART1 }, + }, + .txPins = { + { DEFIO_TAG_E(PA2), GPIO_AF12_LPUART1 }, + { DEFIO_TAG_E(PB11), GPIO_AF8_LPUART1 }, + { DEFIO_TAG_E(PC1), GPIO_AF8_LPUART1 }, + }, + .rcc_apb1 = RCC_APB12(LPUART1), + .rxIrq = LPUART1_IRQn, + .txPriority = NVIC_PRIO_SERIALUART6_TXDMA, + .rxPriority = NVIC_PRIO_SERIALUART6, + .txBuffer = uart6TxBuffer, + .rxBuffer = uart6RxBuffer, + .txBufferSize = sizeof(uart6TxBuffer), + .rxBufferSize = sizeof(uart6RxBuffer), + }, +#endif +}; + + +// XXX Should serialUART be consolidated? + +uartPort_t *serialUART(UARTDevice_e device, uint32_t baudRate, portMode_e mode, portOptions_e options) +{ + uartDevice_t *uartdev = uartDevmap[device]; + if (!uartdev) { + return NULL; + } + + uartPort_t *s = &(uartdev->port); + + s->port.vTable = uartVTable; + + s->port.baudRate = baudRate; + + const uartHardware_t *hardware = uartdev->hardware; + + s->USARTx = hardware->reg; + + s->port.rxBuffer = hardware->rxBuffer; + s->port.txBuffer = hardware->txBuffer; + s->port.rxBufferSize = hardware->rxBufferSize; + s->port.txBufferSize = hardware->txBufferSize; + +#ifdef USE_DMA + uartConfigureDma(uartdev); +#endif + + s->Handle.Instance = hardware->reg; + + IO_t txIO = IOGetByTag(uartdev->tx.pin); + IO_t rxIO = IOGetByTag(uartdev->rx.pin); + + if ((options & SERIAL_BIDIR) && txIO) { + ioConfig_t ioCfg = IO_CONFIG( + ((options & SERIAL_INVERTED) || (options & SERIAL_BIDIR_PP)) ? GPIO_MODE_AF_PP : GPIO_MODE_AF_OD, + GPIO_SPEED_FREQ_HIGH, + ((options & SERIAL_INVERTED) || (options & SERIAL_BIDIR_PP)) ? GPIO_PULLDOWN : GPIO_PULLUP + ); + + IOInit(txIO, OWNER_SERIAL_TX, RESOURCE_INDEX(device)); + IOConfigGPIOAF(txIO, ioCfg, uartdev->tx.af); + } else { + if ((mode & MODE_TX) && txIO) { + IOInit(txIO, OWNER_SERIAL_TX, RESOURCE_INDEX(device)); + IOConfigGPIOAF(txIO, IOCFG_AF_PP, uartdev->tx.af); + } + + if ((mode & MODE_RX) && rxIO) { + IOInit(rxIO, OWNER_SERIAL_RX, RESOURCE_INDEX(device)); + IOConfigGPIOAF(rxIO, IOCFG_AF_PP, uartdev->rx.af); + } + } + +#ifdef USE_DMA + if (!s->rxDMAResource) +#endif + { + HAL_NVIC_SetPriority(hardware->rxIrq, NVIC_PRIORITY_BASE(hardware->rxPriority), NVIC_PRIORITY_SUB(hardware->rxPriority)); + HAL_NVIC_EnableIRQ(hardware->rxIrq); + } + + return s; +} +#endif // USE_UART