Skip to content

Commit 657c5e5

Browse files
committed
Enhance half-duplex support
Signed-off-by: Frederic Pillon <[email protected]>
1 parent dc51f12 commit 657c5e5

File tree

4 files changed

+107
-49
lines changed

4 files changed

+107
-49
lines changed

cores/arduino/HardwareSerial.cpp

+88-35
Original file line numberDiff line numberDiff line change
@@ -108,115 +108,137 @@ void serialEventLP1() __attribute__((weak));
108108
// Constructors ////////////////////////////////////////////////////////////////
109109
HardwareSerial::HardwareSerial(uint32_t _rx, uint32_t _tx)
110110
{
111-
_serial.pin_rx = digitalPinToPinName(_rx);
112-
_serial.pin_tx = digitalPinToPinName(_tx);
113-
init();
111+
init(digitalPinToPinName(_rx), digitalPinToPinName(_tx));
114112
}
115113

116114
HardwareSerial::HardwareSerial(PinName _rx, PinName _tx)
117115
{
118-
_serial.pin_rx = _rx;
119-
_serial.pin_tx = _tx;
120-
init();
116+
init(_rx, _tx);
121117
}
122118

123-
HardwareSerial::HardwareSerial(void *peripheral)
119+
HardwareSerial::HardwareSerial(void *peripheral, bool halfDuplex)
124120
{
121+
// If PIN_SERIALy_RX is not defined assume half-duplex
122+
_serial.pin_rx = NC;
125123
// If Serial is defined in variant set
126124
// the Rx/Tx pins for com port if defined
127-
#if defined(Serial) && defined(PIN_SERIAL_RX) && defined(PIN_SERIAL_TX)
125+
#if defined(Serial) && defined(PIN_SERIAL_TX)
128126
if ((void *)this == (void *)&Serial) {
127+
#if defined(PIN_SERIAL_RX)
129128
setRx(PIN_SERIAL_RX);
129+
#endif
130130
setTx(PIN_SERIAL_TX);
131131
} else
132132
#endif
133-
#if defined(PIN_SERIAL1_RX) && defined(PIN_SERIAL1_TX) && defined(USART1_BASE)
133+
#if defined(PIN_SERIAL1_TX) && defined(USART1_BASE)
134134
if (peripheral == USART1) {
135+
#if defined(PIN_SERIAL1_RX)
135136
setRx(PIN_SERIAL1_RX);
137+
#endif
136138
setTx(PIN_SERIAL1_TX);
137139
} else
138140
#endif
139-
#if defined(PIN_SERIAL2_RX) && defined(PIN_SERIAL2_TX) && defined(USART2_BASE)
141+
#if defined(PIN_SERIAL2_TX) && defined(USART2_BASE)
140142
if (peripheral == USART2) {
143+
#if defined(PIN_SERIAL2_RX)
141144
setRx(PIN_SERIAL2_RX);
145+
#endif
142146
setTx(PIN_SERIAL2_TX);
143147
} else
144148
#endif
145-
#if defined(PIN_SERIAL3_RX) && defined(PIN_SERIAL3_TX) && defined(USART3_BASE)
149+
#if defined(PIN_SERIAL3_TX) && defined(USART3_BASE)
146150
if (peripheral == USART3) {
151+
#if defined(PIN_SERIAL3_RX)
147152
setRx(PIN_SERIAL3_RX);
153+
#endif
148154
setTx(PIN_SERIAL3_TX);
149155
} else
150156
#endif
151-
#if defined(PIN_SERIAL4_RX) && defined(PIN_SERIAL4_TX) &&\
157+
#if defined(PIN_SERIAL4_TX) &&\
152158
(defined(USART4_BASE) || defined(UART4_BASE))
153159
#if defined(USART4_BASE)
154160
if (peripheral == USART4)
155161
#elif defined(UART4_BASE)
156162
if (peripheral == UART4)
157163
#endif
158164
{
165+
#if defined(PIN_SERIAL4_RX)
159166
setRx(PIN_SERIAL4_RX);
167+
#endif
160168
setTx(PIN_SERIAL4_TX);
161169
} else
162170
#endif
163-
#if defined(PIN_SERIAL5_RX) && defined(PIN_SERIAL5_TX) &&\
171+
#if defined(PIN_SERIAL5_TX) &&\
164172
(defined(USART5_BASE) || defined(UART5_BASE))
165173
#if defined(USART5_BASE)
166174
if (peripheral == USART5)
167175
#elif defined(UART5_BASE)
168176
if (peripheral == UART5)
169177
#endif
170178
{
179+
#if defined(PIN_SERIAL5_RX)
171180
setRx(PIN_SERIAL5_RX);
181+
#endif
172182
setTx(PIN_SERIAL5_TX);
173183
} else
174184
#endif
175-
#if defined(PIN_SERIAL6_RX) && defined(PIN_SERIAL6_TX) && defined(USART6_BASE)
185+
#if defined(PIN_SERIAL6_TX) && defined(USART6_BASE)
176186
if (peripheral == USART6) {
187+
#if defined(PIN_SERIAL6_RX)
177188
setRx(PIN_SERIAL6_RX);
189+
#endif
178190
setTx(PIN_SERIAL6_TX);
179191
} else
180192
#endif
181-
#if defined(PIN_SERIAL7_RX) && defined(PIN_SERIAL7_TX) &&\
193+
#if defined(PIN_SERIAL7_TX) &&\
182194
(defined(USART7_BASE) || defined(UART7_BASE))
183195
#if defined(USART7_BASE)
184196
if (peripheral == USART7)
185197
#elif defined(UART7_BASE)
186198
if (peripheral == UART7)
187199
#endif
188200
{
201+
#if defined(PIN_SERIAL7_RX)
189202
setRx(PIN_SERIAL7_RX);
203+
#endif
190204
setTx(PIN_SERIAL7_TX);
191205
} else
192206
#endif
193-
#if defined(PIN_SERIAL8_RX) && defined(PIN_SERIAL8_TX) &&\
207+
#if defined(PIN_SERIAL8_TX) &&\
194208
(defined(USART8_BASE) || defined(UART8_BASE))
195209
#if defined(USART8_BASE)
196210
if (peripheral == USART8)
197211
#elif defined(UART8_BASE)
198212
if (peripheral == UART8)
199213
#endif
200214
{
215+
#if defined(PIN_SERIAL8_RX)
201216
setRx(PIN_SERIAL8_RX);
217+
#endif
202218
setTx(PIN_SERIAL8_TX);
203219
} else
204220
#endif
205-
#if defined(PIN_SERIAL9_RX) && defined(PIN_SERIAL9_TX) && defined(UART9)
221+
#if defined(PIN_SERIAL9_TX) && defined(UART9)
206222
if (peripheral == UART9) {
223+
#if defined(PIN_SERIAL9_RX)
207224
setRx(PIN_SERIAL9_RX);
225+
#endif
208226
setTx(PIN_SERIAL9_TX);
209227
} else
210228
#endif
211-
#if defined(PIN_SERIAL10_RX) && defined(PIN_SERIAL10_TX) && defined(UART10)
229+
#if defined(PIN_SERIAL10_TX) && defined(UART10)
212230
if (peripheral == UART10) {
231+
#if defined(PIN_SERIAL10_RX)
213232
setRx(PIN_SERIAL10_RX);
233+
#endif
214234
setTx(PIN_SERIAL10_TX);
215235
} else
216236
#endif
217-
#if defined(PIN_SERIALLP1_RX) && defined(PIN_SERIALLP1_TX) && defined(LPUART1_BASE)
237+
#if defined(PIN_SERIALLP1_TX) && defined(LPUART1_BASE)
218238
if (peripheral == LPUART1) {
239+
#if defined(PIN_SERIALLP1_RX)
219240
setRx(PIN_SERIALLP1_RX);
241+
#endif
220242
setTx(PIN_SERIALLP1_TX);
221243
} else
222244
#endif
@@ -225,11 +247,30 @@ HardwareSerial::HardwareSerial(void *peripheral)
225247
_serial.pin_rx = pinmap_pin(peripheral, PinMap_UART_RX);
226248
_serial.pin_tx = pinmap_pin(peripheral, PinMap_UART_TX);
227249
}
228-
init();
250+
if (halfDuplex) {
251+
_serial.pin_rx = NC;
252+
}
253+
init(_serial.pin_rx, _serial.pin_tx);
229254
}
230255

231-
void HardwareSerial::init(void)
256+
HardwareSerial::HardwareSerial(uint32_t _rxtx)
232257
{
258+
init(NC, digitalPinToPinName(_rxtx));
259+
}
260+
261+
HardwareSerial::HardwareSerial(PinName _rxtx)
262+
{
263+
init(NC, _rxtx);
264+
}
265+
266+
void HardwareSerial::init(PinName _rx, PinName _tx)
267+
{
268+
if (_rx == _tx) {
269+
_serial.pin_rx = NC;
270+
} else {
271+
_serial.pin_rx = _rx;
272+
}
273+
_serial.pin_tx = _tx;
233274
_serial.rx_buff = _rx_buffer;
234275
_serial.rx_head = 0;
235276
_serial.rx_tail = 0;
@@ -347,11 +388,7 @@ void HardwareSerial::begin(unsigned long baud, byte config)
347388
}
348389

349390
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-
}
391+
enableHalfDuplexRx();
355392
uart_attach_rx_callback(&_serial, _rx_complete_irq);
356393
}
357394

@@ -382,15 +419,7 @@ int HardwareSerial::peek(void)
382419

383420
int HardwareSerial::read(void)
384421
{
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-
}
422+
enableHalfDuplexRx();
394423
// if the head isn't ahead of the tail, we don't have any characters
395424
if (_serial.rx_head == _serial.rx_tail) {
396425
return -1;
@@ -475,4 +504,28 @@ void HardwareSerial::setTx(PinName _tx)
475504
{
476505
_serial.pin_tx = _tx;
477506
}
507+
508+
void HardwareSerial::setHalfDuplex(void)
509+
{
510+
_serial.pin_rx = NC;
511+
}
512+
513+
bool HardwareSerial::isHalfDuplex(void) const
514+
{
515+
return _serial.pin_rx == NC;
516+
}
517+
518+
void HardwareSerial::enableHalfDuplexRx(void)
519+
{
520+
if (isHalfDuplex()) {
521+
// In half-duplex mode we have to wait for all TX characters to
522+
// be transmitted before we can receive data.
523+
flush();
524+
if (!_rx_enabled) {
525+
_rx_enabled = true;
526+
uart_enable_rx(&_serial);
527+
}
528+
}
529+
}
530+
478531
#endif // HAL_UART_MODULE_ENABLED

cores/arduino/HardwareSerial.h

+7-10
Original file line numberDiff line numberDiff line change
@@ -103,7 +103,9 @@ class HardwareSerial : public Stream {
103103
public:
104104
HardwareSerial(uint32_t _rx, uint32_t _tx);
105105
HardwareSerial(PinName _rx, PinName _tx);
106-
HardwareSerial(void *peripheral);
106+
HardwareSerial(void *peripheral, bool halfDuplex = false);
107+
HardwareSerial(uint32_t _rxtx);
108+
HardwareSerial(PinName _rxtx);
107109
void begin(unsigned long baud)
108110
{
109111
begin(baud, SERIAL_8N1);
@@ -145,14 +147,9 @@ class HardwareSerial : public Stream {
145147

146148
// Enable half-duplex mode by setting the Rx pin to NC
147149
// 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-
}
150+
void setHalfDuplex(void);
151+
bool isHalfDuplex(void) const;
152+
void enableHalfDuplexRx(void);
156153

157154
friend class STM32LowPower;
158155

@@ -163,7 +160,7 @@ class HardwareSerial : public Stream {
163160
bool _rx_enabled;
164161
uint8_t _config;
165162
unsigned long _baud;
166-
void init(void);
163+
void init(PinName _rx, PinName _tx);
167164
void configForLowPower(void);
168165
};
169166

cores/arduino/stm32/uart.c

+9-4
Original file line numberDiff line numberDiff line change
@@ -130,9 +130,14 @@ void uart_init(serial_t *obj, uint32_t baudrate, uint32_t databits, uint32_t par
130130
USART_TypeDef *uart_tx = pinmap_peripheral(obj->pin_tx, PinMap_UART_TX);
131131
USART_TypeDef *uart_rx = pinmap_peripheral(obj->pin_rx, PinMap_UART_RX);
132132

133-
/* Pins Rx/Tx must not be NP */
134-
if ((obj->pin_rx != NC && uart_rx == NP) || uart_tx == NP) {
135-
core_debug("ERROR: at least one UART pin has no peripheral\n");
133+
/* Pin Tx must not be NP */
134+
if (uart_tx == NP) {
135+
core_debug("ERROR: [U(S)ART] Tx pin has no peripheral!\n");
136+
return;
137+
}
138+
/* Pin Rx must not be NP if not half-duplex */
139+
if ((obj->pin_rx != NC) && (uart_rx == NP)) {
140+
core_debug("ERROR: [U(S)ART] Rx pin has no peripheral!\n");
136141
return;
137142
}
138143

@@ -143,7 +148,7 @@ void uart_init(serial_t *obj, uint32_t baudrate, uint32_t databits, uint32_t par
143148
obj->uart = pinmap_merge_peripheral(uart_tx, uart_rx);
144149

145150
if (obj->uart == NP) {
146-
core_debug("ERROR: U(S)ART pins mismatch\n");
151+
core_debug("ERROR: [U(S)ART] Rx and Tx pins peripherals mismatch!\n");
147152
return;
148153
}
149154

keywords.txt

+3
Original file line numberDiff line numberDiff line change
@@ -269,6 +269,9 @@ PIN_WIRE_SCL LITERAL1
269269
HardwareSerial KEYWORD2
270270
setRX KEYWORD2
271271
setTX KEYWORD2
272+
setHalfDuplex KEYWORD2
273+
isHalfDuplex KEYWORD2
274+
enableHalfDuplexRx KEYWORD2
272275
Serial4 KEYWORD1
273276
Serial5 KEYWORD1
274277
Serial6 KEYWORD1

0 commit comments

Comments
 (0)