From 3d2bebde0c2f1f5b8fa4e0a8d249edc22b7f6826 Mon Sep 17 00:00:00 2001 From: Przemyslaw Stekiel Date: Thu, 29 Aug 2019 11:02:22 +0200 Subject: [PATCH] STM32 serial driver: Add explicit pinmap support --- .../TARGET_STM/TARGET_STM32F4/serial_device.c | 76 +++++++++++++------ targets/TARGET_STM/serial_api.c | 68 +++++++++++------ 2 files changed, 96 insertions(+), 48 deletions(-) diff --git a/targets/TARGET_STM/TARGET_STM32F4/serial_device.c b/targets/TARGET_STM/TARGET_STM32F4/serial_device.c index 42296cdd60..52af77dcdf 100644 --- a/targets/TARGET_STM/TARGET_STM32F4/serial_device.c +++ b/targets/TARGET_STM/TARGET_STM32F4/serial_device.c @@ -725,57 +725,87 @@ void serial_rx_abort_asynch(serial_t *obj) * Set HW Control Flow * @param obj The serial object * @param type The Control Flow type (FlowControlNone, FlowControlRTS, FlowControlCTS, FlowControlRTSCTS) - * @param rxflow Pin for the rxflow - * @param txflow Pin for the txflow + * @param pinmap Pointer to strucure which holds static pinmap */ -void serial_set_flow_control(serial_t *obj, FlowControl type, PinName rxflow, PinName txflow) +#if EXPLICIT_PINMAP_READY +#define SERIAL_SET_FC_DIRECT serial_set_flow_control_direct +void serial_set_flow_control_direct(serial_t *obj, FlowControl type, const serial_fc_pinmap_t *pinmap) +#else +#define SERIAL_SET_FC_DIRECT _serial_set_flow_control_direct +static void _serial_set_flow_control_direct(serial_t *obj, FlowControl type, const serial_fc_pinmap_t *pinmap) +#endif { struct serial_s *obj_s = SERIAL_S(obj); - // Checked used UART name (UART_1, UART_2, ...) - UARTName uart_rts = (UARTName)pinmap_peripheral(rxflow, PinMap_UART_RTS); - UARTName uart_cts = (UARTName)pinmap_peripheral(txflow, PinMap_UART_CTS); - if (((UARTName)pinmap_merge(uart_rts, obj_s->uart) == (UARTName)NC) || ((UARTName)pinmap_merge(uart_cts, obj_s->uart) == (UARTName)NC)) { - MBED_ASSERT(0); - return; - } - if (type == FlowControlNone) { // Disable hardware flow control obj_s->hw_flow_ctl = UART_HWCONTROL_NONE; } if (type == FlowControlRTS) { // Enable RTS - MBED_ASSERT(uart_rts != (UARTName)NC); + MBED_ASSERT(pinmap->rx_flow_pin != (UARTName)NC); obj_s->hw_flow_ctl = UART_HWCONTROL_RTS; - obj_s->pin_rts = rxflow; + obj_s->pin_rts = pinmap->rx_flow_pin; // Enable the pin for RTS function - pinmap_pinout(rxflow, PinMap_UART_RTS); + pin_function(pinmap->rx_flow_pin, pinmap->rx_flow_function); + pin_mode(pinmap->rx_flow_pin, PullNone); } if (type == FlowControlCTS) { // Enable CTS - MBED_ASSERT(uart_cts != (UARTName)NC); + MBED_ASSERT(pinmap->tx_flow_pin != (UARTName)NC); obj_s->hw_flow_ctl = UART_HWCONTROL_CTS; - obj_s->pin_cts = txflow; + obj_s->pin_cts = pinmap->tx_flow_pin; // Enable the pin for CTS function - pinmap_pinout(txflow, PinMap_UART_CTS); + pin_function(pinmap->tx_flow_pin, pinmap->tx_flow_function); + pin_mode(pinmap->tx_flow_pin, PullNone); } if (type == FlowControlRTSCTS) { // Enable CTS & RTS - MBED_ASSERT(uart_rts != (UARTName)NC); - MBED_ASSERT(uart_cts != (UARTName)NC); + MBED_ASSERT(pinmap->rx_flow_pin != (UARTName)NC); + MBED_ASSERT(pinmap->tx_flow_pin != (UARTName)NC); obj_s->hw_flow_ctl = UART_HWCONTROL_RTS_CTS; - obj_s->pin_rts = rxflow; - obj_s->pin_cts = txflow; + obj_s->pin_rts = pinmap->rx_flow_pin;; + obj_s->pin_cts = pinmap->tx_flow_pin;; // Enable the pin for CTS function - pinmap_pinout(txflow, PinMap_UART_CTS); + pin_function(pinmap->tx_flow_pin, pinmap->tx_flow_function); + pin_mode(pinmap->tx_flow_pin, PullNone); // Enable the pin for RTS function - pinmap_pinout(rxflow, PinMap_UART_RTS); + pin_function(pinmap->rx_flow_pin, pinmap->rx_flow_function); + pin_mode(pinmap->rx_flow_pin, PullNone); } init_uart(obj); } +/** + * Set HW Control Flow + * @param obj The serial object + * @param type The Control Flow type (FlowControlNone, FlowControlRTS, FlowControlCTS, FlowControlRTSCTS) + * @param rxflow Pin for the rxflow + * @param txflow Pin for the txflow + */ +void serial_set_flow_control(serial_t *obj, FlowControl type, PinName rxflow, PinName txflow) +{ + struct serial_s *obj_s = SERIAL_S(obj); + + UARTName uart_rts = (UARTName)pinmap_peripheral(rxflow, PinMap_UART_RTS); + UARTName uart_cts = (UARTName)pinmap_peripheral(txflow, PinMap_UART_CTS); + + if (((UARTName)pinmap_merge(uart_rts, obj_s->uart) == (UARTName)NC) || ((UARTName)pinmap_merge(uart_cts, obj_s->uart) == (UARTName)NC)) { + MBED_ASSERT(0); + return; + } + + int peripheral = (int)pinmap_merge(uart_rts, uart_cts); + + int tx_flow_function = (int)pinmap_find_function(txflow, PinMap_UART_CTS); + int rx_flow_function = (int)pinmap_find_function(rxflow, PinMap_UART_RTS); + + const serial_fc_pinmap_t explicit_uart_fc_pinmap = {peripheral, txflow, tx_flow_function, rxflow, rx_flow_function}; + + SERIAL_SET_FC_DIRECT(obj, type, &explicit_uart_fc_pinmap); +} + #endif /* DEVICE_SERIAL_FC */ #endif /* DEVICE_SERIAL */ diff --git a/targets/TARGET_STM/serial_api.c b/targets/TARGET_STM/serial_api.c index fe33165d03..2521c3c20c 100644 --- a/targets/TARGET_STM/serial_api.c +++ b/targets/TARGET_STM/serial_api.c @@ -47,27 +47,20 @@ extern uint32_t serial_irq_ids[]; HAL_StatusTypeDef init_uart(serial_t *obj); int8_t get_uart_index(UARTName uart_name); -void serial_init(serial_t *obj, PinName tx, PinName rx) +#if EXPLICIT_PINMAP_READY +#define SERIAL_INIT_DIRECT serial_init_direct +void serial_init_direct(serial_t *obj, const serial_pinmap_t *pinmap) +#else +#define SERIAL_INIT_DIRECT _serial_init_direct +static void _serial_init_direct(serial_t *obj, const serial_pinmap_t *pinmap) +#endif { struct serial_s *obj_s = SERIAL_S(obj); - uint8_t stdio_config = 0; - - // Determine the UART to use (UART_1, UART_2, ...) - UARTName uart_tx = (UARTName)pinmap_peripheral(tx, PinMap_UART_TX); - UARTName uart_rx = (UARTName)pinmap_peripheral(rx, PinMap_UART_RX); // Get the peripheral name (UART_1, UART_2, ...) from the pin and assign it to the object - obj_s->uart = (UARTName)pinmap_merge(uart_tx, uart_rx); + obj_s->uart = (UARTName)pinmap->peripheral; MBED_ASSERT(obj_s->uart != (UARTName)NC); - if ((tx == STDIO_UART_TX) || (rx == STDIO_UART_RX)) { - stdio_config = 1; - } else { - if (uart_tx == pinmap_peripheral(STDIO_UART_TX, PinMap_UART_TX)) { - error("Error: new serial object is using same UART as STDIO"); - } - } - // Reset and enable clock #if defined(USART1_BASE) if (obj_s->uart == UART_1) { @@ -164,19 +157,19 @@ void serial_init(serial_t *obj, PinName tx, PinName rx) MBED_ASSERT(obj_s->index >= 0); // Configure UART pins - pinmap_pinout(tx, PinMap_UART_TX); - pinmap_pinout(rx, PinMap_UART_RX); + pin_function(pinmap->tx_pin, pinmap->tx_function); + pin_function(pinmap->rx_pin, pinmap->rx_function); - if (tx != NC) { - pin_mode(tx, PullUp); + if (pinmap->tx_pin != NC) { + pin_mode(pinmap->tx_pin, PullUp); } - if (rx != NC) { - pin_mode(rx, PullUp); + if (pinmap->rx_pin != NC) { + pin_mode(pinmap->rx_pin, PullUp); } // Configure UART obj_s->baudrate = 9600; // baudrate default value - if (stdio_config) { + if (pinmap->stdio_config) { #if MBED_CONF_PLATFORM_STDIO_BAUD_RATE obj_s->baudrate = MBED_CONF_PLATFORM_STDIO_BAUD_RATE; // baudrate takes value from platform/mbed_lib.json #endif /* MBED_CONF_PLATFORM_STDIO_BAUD_RATE */ @@ -193,18 +186,43 @@ void serial_init(serial_t *obj, PinName tx, PinName rx) obj_s->hw_flow_ctl = UART_HWCONTROL_NONE; #endif - obj_s->pin_tx = tx; - obj_s->pin_rx = rx; + obj_s->pin_tx = pinmap->tx_pin; + obj_s->pin_rx = pinmap->rx_pin; init_uart(obj); /* init_uart will be called again in serial_baud function, so don't worry if init_uart returns HAL_ERROR */ // For stdio management in platform/mbed_board.c and platform/mbed_retarget.cpp - if (stdio_config) { + if (pinmap->stdio_config) { stdio_uart_inited = 1; memcpy(&stdio_uart, obj, sizeof(serial_t)); } } +void serial_init(serial_t *obj, PinName tx, PinName rx) +{ + uint32_t uart_tx = pinmap_peripheral(tx, PinMap_UART_TX); + uint32_t uart_rx = pinmap_peripheral(rx, PinMap_UART_RX); + + int peripheral = (int)pinmap_merge(uart_tx, uart_rx); + + int tx_function = (int)pinmap_find_function(tx, PinMap_UART_TX); + int rx_function = (int)pinmap_find_function(rx, PinMap_UART_RX); + + uint8_t stdio_config = false; + + if ((tx == STDIO_UART_TX) || (rx == STDIO_UART_RX)) { + stdio_config = true; + } else { + if (uart_tx == pinmap_peripheral(STDIO_UART_TX, PinMap_UART_TX)) { + error("Error: new serial object is using same UART as STDIO"); + } + } + + const serial_pinmap_t explicit_uart_pinmap = {peripheral, tx, tx_function, rx, rx_function, stdio_config}; + + SERIAL_INIT_DIRECT(obj, &explicit_uart_pinmap); +} + void serial_free(serial_t *obj) { struct serial_s *obj_s = SERIAL_S(obj);