Skip to content

Commit e2f4e05

Browse files
committed
First version of half-duplex support.
1 parent 21d3d5c commit e2f4e05

4 files changed

Lines changed: 75 additions & 4 deletions

File tree

cores/arduino/HardwareSerial.cpp

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -347,6 +347,11 @@ void HardwareSerial::begin(unsigned long baud, byte config)
347347
}
348348

349349
uart_init(&_serial, (uint32_t)baud, databits, parity, stopbits);
350+
if (isHalfDuplex()) {
351+
// Start half duplex communication in receive mode.
352+
_rx_enabled = true;
353+
uart_enable_rx(&_serial);
354+
}
350355
uart_attach_rx_callback(&_serial, _rx_complete_irq);
351356
}
352357

@@ -377,6 +382,15 @@ int HardwareSerial::peek(void)
377382

378383
int HardwareSerial::read(void)
379384
{
385+
if (isHalfDuplex()) {
386+
// In half duplex mode we have to wait for all TX characters to
387+
// be transmitted before we can receive data.
388+
flush();
389+
if (!_rx_enabled) {
390+
_rx_enabled = true;
391+
uart_enable_rx(&_serial);
392+
}
393+
}
380394
// if the head isn't ahead of the tail, we don't have any characters
381395
if (_serial.rx_head == _serial.rx_tail) {
382396
return -1;
@@ -417,6 +431,12 @@ void HardwareSerial::flush()
417431
size_t HardwareSerial::write(uint8_t c)
418432
{
419433
_written = true;
434+
if (isHalfDuplex()) {
435+
if (_rx_enabled) {
436+
_rx_enabled = false;
437+
uart_enable_tx(&_serial);
438+
}
439+
}
420440

421441
tx_buffer_index_t i = (_serial.tx_head + 1) % SERIAL_TX_BUFFER_SIZE;
422442

cores/arduino/HardwareSerial.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -143,12 +143,22 @@ class HardwareSerial : public Stream {
143143
void setRx(PinName _rx);
144144
void setTx(PinName _tx);
145145

146+
// Enable half-duplex mode by setting the Rx pin to NC
147+
// This needs to be done before the call to begin()
148+
inline void setHalfDuplex() {
149+
setRx(NC);
150+
}
151+
inline bool isHalfDuplex() const {
152+
return _serial.pin_rx == NC;
153+
}
154+
146155
friend class STM32LowPower;
147156

148157
// Interrupt handlers
149158
static void _rx_complete_irq(serial_t *obj);
150159
static int _tx_complete_irq(serial_t *obj);
151160
private:
161+
bool _rx_enabled;
152162
uint8_t _config;
153163
unsigned long _baud;
154164
void init(void);

cores/arduino/stm32/uart.c

Lines changed: 42 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -128,10 +128,14 @@ void uart_init(serial_t *obj, uint32_t baudrate, uint32_t databits, uint32_t par
128128

129129
/* Determine the U(S)ART peripheral to use (USART1, USART2, ...) */
130130
USART_TypeDef *uart_tx = pinmap_peripheral(obj->pin_tx, PinMap_UART_TX);
131-
USART_TypeDef *uart_rx = pinmap_peripheral(obj->pin_rx, PinMap_UART_RX);
131+
USART_TypeDef *uart_rx = NP;
132+
133+
if (obj->pin_rx != NC) {
134+
uart_rx = pinmap_peripheral(obj->pin_rx, PinMap_UART_RX);
135+
}
132136

133137
/* Pins Rx/Tx must not be NP */
134-
if (uart_rx == NP || uart_tx == NP) {
138+
if ((obj->pin_rx != NC && uart_rx == NP) || uart_tx == NP) {
135139
core_debug("ERROR: at least one UART pin has no peripheral\n");
136140
return;
137141
}
@@ -288,7 +292,9 @@ void uart_init(serial_t *obj, uint32_t baudrate, uint32_t databits, uint32_t par
288292

289293
/* Configure UART GPIO pins */
290294
pinmap_pinout(obj->pin_tx, PinMap_UART_TX);
291-
pinmap_pinout(obj->pin_rx, PinMap_UART_RX);
295+
if (uart_rx != NP) {
296+
pinmap_pinout(obj->pin_rx, PinMap_UART_RX);
297+
}
292298

293299
/* Configure uart */
294300
uart_handlers[obj->index] = huart;
@@ -359,7 +365,11 @@ void uart_init(serial_t *obj, uint32_t baudrate, uint32_t databits, uint32_t par
359365
}
360366
#endif
361367

362-
if (HAL_UART_Init(huart) != HAL_OK) {
368+
if (uart_rx == NP) {
369+
if (HAL_HalfDuplex_Init(huart) != HAL_OK) {
370+
return;
371+
}
372+
} else if (HAL_UART_Init(huart) != HAL_OK) {
363373
return;
364374
}
365375
}
@@ -732,6 +742,34 @@ void uart_attach_tx_callback(serial_t *obj, int (*callback)(serial_t *))
732742
HAL_NVIC_EnableIRQ(obj->irq);
733743
}
734744

745+
/**
746+
* Enable transmitter for half-duplex mode. NOOP in full-fuplex mode
747+
*
748+
* @param obj : pointer to serial_t structure
749+
* @retval none
750+
*/
751+
void uart_enable_tx(serial_t *obj)
752+
{
753+
if (obj == NULL || obj->pin_rx != NC) {
754+
return;
755+
}
756+
HAL_HalfDuplex_EnableTransmitter(uart_handlers[obj->index]);
757+
}
758+
759+
/**
760+
* Enable receiver for half-duplex mode. NOOP in full-fuplex mode
761+
*
762+
* @param obj : pointer to serial_t structure
763+
* @retval none
764+
*/
765+
void uart_enable_rx(serial_t *obj)
766+
{
767+
if (obj == NULL || obj->pin_rx != NC) {
768+
return;
769+
}
770+
HAL_HalfDuplex_EnableReceiver(uart_handlers[obj->index]);
771+
}
772+
735773
/**
736774
* @brief Return index of the serial handler
737775
* @param UartHandle pointer on the uart reference

cores/arduino/stm32/uart.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -181,6 +181,9 @@ void uart_attach_tx_callback(serial_t *obj, int (*callback)(serial_t *));
181181
uint8_t serial_tx_active(serial_t *obj);
182182
uint8_t serial_rx_active(serial_t *obj);
183183

184+
void uart_enable_tx(serial_t *obj);
185+
void uart_enable_rx(serial_t *obj);
186+
184187
size_t uart_debug_write(uint8_t *data, uint32_t size);
185188

186189
#endif /* HAL_UART_MODULE_ENABLED */

0 commit comments

Comments
 (0)