Skip to content

Commit 2a64163

Browse files
ghent360fpistm
authored andcommitted
First version of half-duplex support.
Implement suggestions from fpistm. Fix style issues.
1 parent 6808f06 commit 2a64163

File tree

4 files changed

+70
-3
lines changed

4 files changed

+70
-3
lines changed

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: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -143,12 +143,24 @@ 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+
{
150+
setRx(NC);
151+
}
152+
inline bool isHalfDuplex() const
153+
{
154+
return _serial.pin_rx == NC;
155+
}
156+
146157
friend class STM32LowPower;
147158

148159
// Interrupt handlers
149160
static void _rx_complete_irq(serial_t *obj);
150161
static int _tx_complete_irq(serial_t *obj);
151162
private:
163+
bool _rx_enabled;
152164
uint8_t _config;
153165
unsigned long _baud;
154166
void init(void);

cores/arduino/stm32/uart.c

Lines changed: 35 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -131,7 +131,7 @@ void uart_init(serial_t *obj, uint32_t baudrate, uint32_t databits, uint32_t par
131131
USART_TypeDef *uart_rx = pinmap_peripheral(obj->pin_rx, PinMap_UART_RX);
132132

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

289289
/* Configure UART GPIO pins */
290290
pinmap_pinout(obj->pin_tx, PinMap_UART_TX);
291-
pinmap_pinout(obj->pin_rx, PinMap_UART_RX);
291+
if (uart_rx != NP) {
292+
pinmap_pinout(obj->pin_rx, PinMap_UART_RX);
293+
}
292294

293295
/* Configure uart */
294296
uart_handlers[obj->index] = huart;
@@ -359,7 +361,11 @@ void uart_init(serial_t *obj, uint32_t baudrate, uint32_t databits, uint32_t par
359361
}
360362
#endif
361363

362-
if (HAL_UART_Init(huart) != HAL_OK) {
364+
if (uart_rx == NP) {
365+
if (HAL_HalfDuplex_Init(huart) != HAL_OK) {
366+
return;
367+
}
368+
} else if (HAL_UART_Init(huart) != HAL_OK) {
363369
return;
364370
}
365371
}
@@ -732,6 +738,32 @@ void uart_attach_tx_callback(serial_t *obj, int (*callback)(serial_t *))
732738
HAL_NVIC_EnableIRQ(obj->irq);
733739
}
734740

741+
/**
742+
* Enable transmitter for half-duplex mode. NOOP in full-fuplex mode
743+
*
744+
* @param obj : pointer to serial_t structure
745+
* @retval none
746+
*/
747+
void uart_enable_tx(serial_t *obj)
748+
{
749+
if (obj != NULL && obj->pin_rx == NC) {
750+
HAL_HalfDuplex_EnableTransmitter(uart_handlers[obj->index]);
751+
}
752+
}
753+
754+
/**
755+
* Enable receiver for half-duplex mode. NOOP in full-fuplex mode
756+
*
757+
* @param obj : pointer to serial_t structure
758+
* @retval none
759+
*/
760+
void uart_enable_rx(serial_t *obj)
761+
{
762+
if (obj != NULL && obj->pin_rx == NC) {
763+
HAL_HalfDuplex_EnableReceiver(uart_handlers[obj->index]);
764+
}
765+
}
766+
735767
/**
736768
* @brief Return index of the serial handler
737769
* @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)