diff --git a/cores/arduino/HardwareSerial.cpp b/cores/arduino/HardwareSerial.cpp index 1cdf446e7a..0feec314b6 100644 --- a/cores/arduino/HardwareSerial.cpp +++ b/cores/arduino/HardwareSerial.cpp @@ -347,6 +347,11 @@ void HardwareSerial::begin(unsigned long baud, byte config) } uart_init(&_serial, (uint32_t)baud, databits, parity, stopbits); + if (isHalfDuplex()) { + // Start half duplex communication in receive mode. + _rx_enabled = true; + uart_enable_rx(&_serial); + } uart_attach_rx_callback(&_serial, _rx_complete_irq); } @@ -377,6 +382,15 @@ int HardwareSerial::peek(void) int HardwareSerial::read(void) { + if (isHalfDuplex()) { + // In half duplex mode we have to wait for all TX characters to + // be transmitted before we can receive data. + flush(); + if (!_rx_enabled) { + _rx_enabled = true; + uart_enable_rx(&_serial); + } + } // if the head isn't ahead of the tail, we don't have any characters if (_serial.rx_head == _serial.rx_tail) { return -1; @@ -417,6 +431,12 @@ void HardwareSerial::flush() size_t HardwareSerial::write(uint8_t c) { _written = true; + if (isHalfDuplex()) { + if (_rx_enabled) { + _rx_enabled = false; + uart_enable_tx(&_serial); + } + } tx_buffer_index_t i = (_serial.tx_head + 1) % SERIAL_TX_BUFFER_SIZE; diff --git a/cores/arduino/HardwareSerial.h b/cores/arduino/HardwareSerial.h index a16a4e5d4e..6f9dd98ee2 100644 --- a/cores/arduino/HardwareSerial.h +++ b/cores/arduino/HardwareSerial.h @@ -143,12 +143,24 @@ class HardwareSerial : public Stream { void setRx(PinName _rx); void setTx(PinName _tx); + // Enable half-duplex mode by setting the Rx pin to NC + // This needs to be done before the call to begin() + inline void setHalfDuplex() + { + setRx(NC); + } + inline bool isHalfDuplex() const + { + return _serial.pin_rx == NC; + } + friend class STM32LowPower; // Interrupt handlers static void _rx_complete_irq(serial_t *obj); static int _tx_complete_irq(serial_t *obj); private: + bool _rx_enabled; uint8_t _config; unsigned long _baud; void init(void); diff --git a/cores/arduino/stm32/uart.c b/cores/arduino/stm32/uart.c index 338d486a4a..7eb7f35f99 100644 --- a/cores/arduino/stm32/uart.c +++ b/cores/arduino/stm32/uart.c @@ -131,7 +131,7 @@ void uart_init(serial_t *obj, uint32_t baudrate, uint32_t databits, uint32_t par USART_TypeDef *uart_rx = pinmap_peripheral(obj->pin_rx, PinMap_UART_RX); /* Pins Rx/Tx must not be NP */ - if (uart_rx == NP || uart_tx == NP) { + if ((obj->pin_rx != NC && uart_rx == NP) || uart_tx == NP) { core_debug("ERROR: at least one UART pin has no peripheral\n"); return; } @@ -288,7 +288,9 @@ void uart_init(serial_t *obj, uint32_t baudrate, uint32_t databits, uint32_t par /* Configure UART GPIO pins */ pinmap_pinout(obj->pin_tx, PinMap_UART_TX); - pinmap_pinout(obj->pin_rx, PinMap_UART_RX); + if (uart_rx != NP) { + pinmap_pinout(obj->pin_rx, PinMap_UART_RX); + } /* Configure uart */ uart_handlers[obj->index] = huart; @@ -359,7 +361,11 @@ void uart_init(serial_t *obj, uint32_t baudrate, uint32_t databits, uint32_t par } #endif - if (HAL_UART_Init(huart) != HAL_OK) { + if (uart_rx == NP) { + if (HAL_HalfDuplex_Init(huart) != HAL_OK) { + return; + } + } else if (HAL_UART_Init(huart) != HAL_OK) { return; } } @@ -732,6 +738,32 @@ void uart_attach_tx_callback(serial_t *obj, int (*callback)(serial_t *)) HAL_NVIC_EnableIRQ(obj->irq); } +/** + * Enable transmitter for half-duplex mode. NOOP in full-fuplex mode + * + * @param obj : pointer to serial_t structure + * @retval none + */ +void uart_enable_tx(serial_t *obj) +{ + if (obj != NULL && obj->pin_rx == NC) { + HAL_HalfDuplex_EnableTransmitter(uart_handlers[obj->index]); + } +} + +/** + * Enable receiver for half-duplex mode. NOOP in full-fuplex mode + * + * @param obj : pointer to serial_t structure + * @retval none + */ +void uart_enable_rx(serial_t *obj) +{ + if (obj != NULL && obj->pin_rx == NC) { + HAL_HalfDuplex_EnableReceiver(uart_handlers[obj->index]); + } +} + /** * @brief Return index of the serial handler * @param UartHandle pointer on the uart reference diff --git a/cores/arduino/stm32/uart.h b/cores/arduino/stm32/uart.h index 5a8d037769..e8e8f29bbc 100644 --- a/cores/arduino/stm32/uart.h +++ b/cores/arduino/stm32/uart.h @@ -181,6 +181,9 @@ void uart_attach_tx_callback(serial_t *obj, int (*callback)(serial_t *)); uint8_t serial_tx_active(serial_t *obj); uint8_t serial_rx_active(serial_t *obj); +void uart_enable_tx(serial_t *obj); +void uart_enable_rx(serial_t *obj); + size_t uart_debug_write(uint8_t *data, uint32_t size); #endif /* HAL_UART_MODULE_ENABLED */