Skip to content

Commit d425ec5

Browse files
author
Cruz Monrreal
authored
Merge pull request #9197 from OpenNuvoton/nuvoton_fix_uart-flow-control
Nuvoton: Fix UART flow control CTS/RTS
2 parents 8493c61 + 17fb5b7 commit d425ec5

File tree

5 files changed

+122
-56
lines changed

5 files changed

+122
-56
lines changed

targets/TARGET_NUVOTON/TARGET_M2351/serial_api.c

Lines changed: 23 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -361,10 +361,7 @@ void serial_set_flow_control(serial_t *obj, FlowControl type, PinName rxflow, Pi
361361
{
362362
UART_T *uart_base = (UART_T *) NU_MODBASE(obj->serial.uart);
363363

364-
// First, disable flow control completely.
365-
uart_base->INTEN &= ~(UART_INTEN_ATORTSEN_Msk | UART_INTEN_ATOCTSEN_Msk);
366-
367-
if ((type == FlowControlRTS || type == FlowControlRTSCTS) && rxflow != NC) {
364+
if (rxflow != NC) {
368365
// Check if RTS pin matches.
369366
uint32_t uart_rts = pinmap_peripheral(rxflow, PinMap_UART_RTS);
370367
MBED_ASSERT(uart_rts == obj->serial.uart);
@@ -378,14 +375,24 @@ void serial_set_flow_control(serial_t *obj, FlowControl type, PinName rxflow, Pi
378375
uart_base->MODEM |= UART_MODEM_RTSACTLV_Msk;
379376
// NOTE: Added in M480/M2351. After configuring RTSACTLV, re-enable TX/RX.
380377
uart_base->FUNCSEL &= ~UART_FUNCSEL_TXRXDIS_Msk;
381-
378+
// Configure RTS trigger level to 8 bytes
382379
uart_base->FIFO = (uart_base->FIFO & ~UART_FIFO_RTSTRGLV_Msk) | UART_FIFO_RTSTRGLV_8BYTES;
383-
384-
// Enable RTS
385-
uart_base->INTEN |= UART_INTEN_ATORTSEN_Msk;
380+
381+
if (type == FlowControlRTS || type == FlowControlRTSCTS) {
382+
// Enable RTS
383+
uart_base->INTEN |= UART_INTEN_ATORTSEN_Msk;
384+
} else {
385+
// Disable RTS
386+
uart_base->INTEN &= ~UART_INTEN_ATORTSEN_Msk;
387+
/* Drive nRTS pin output to low-active. Allow the peer to be able to send data
388+
* even though its CTS is still enabled. */
389+
uart_base->MODEM &= ~UART_MODEM_RTS_Msk;
390+
}
386391
}
387392

388-
if ((type == FlowControlCTS || type == FlowControlRTSCTS) && txflow != NC) {
393+
/* If CTS is disabled, we don't need to configure CTS. But to be consistent with
394+
* RTS code above, we still configure CTS. */
395+
if (txflow != NC) {
389396
// Check if CTS pin matches.
390397
uint32_t uart_cts = pinmap_peripheral(txflow, PinMap_UART_CTS);
391398
MBED_ASSERT(uart_cts == obj->serial.uart);
@@ -400,8 +407,13 @@ void serial_set_flow_control(serial_t *obj, FlowControl type, PinName rxflow, Pi
400407
// NOTE: Added in M480/M2351. After configuring CTSACTLV, re-enable TX/RX.
401408
uart_base->FUNCSEL &= ~UART_FUNCSEL_TXRXDIS_Msk;
402409

403-
// Enable CTS
404-
uart_base->INTEN |= UART_INTEN_ATOCTSEN_Msk;
410+
if (type == FlowControlCTS || type == FlowControlRTSCTS) {
411+
// Enable CTS
412+
uart_base->INTEN |= UART_INTEN_ATOCTSEN_Msk;
413+
} else {
414+
// Disable CTS
415+
uart_base->INTEN &= ~UART_INTEN_ATOCTSEN_Msk;
416+
}
405417
}
406418
}
407419

targets/TARGET_NUVOTON/TARGET_M451/serial_api.c

Lines changed: 25 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -313,33 +313,48 @@ void serial_format(serial_t *obj, int data_bits, SerialParity parity, int stop_b
313313
void serial_set_flow_control(serial_t *obj, FlowControl type, PinName rxflow, PinName txflow)
314314
{
315315
UART_T *uart_base = (UART_T *) NU_MODBASE(obj->serial.uart);
316-
317-
// First, disable flow control completely.
318-
uart_base->INTEN &= ~(UART_INTEN_ATORTSEN_Msk | UART_INTEN_ATOCTSEN_Msk);
319316

320-
if ((type == FlowControlRTS || type == FlowControlRTSCTS) && rxflow != NC) {
317+
if (rxflow != NC) {
321318
// Check if RTS pin matches.
322319
uint32_t uart_rts = pinmap_peripheral(rxflow, PinMap_UART_RTS);
323320
MBED_ASSERT(uart_rts == obj->serial.uart);
324321
// Enable the pin for RTS function
325322
pinmap_pinout(rxflow, PinMap_UART_RTS);
326323
// nRTS pin output is low level active
327324
uart_base->MODEM |= UART_MODEM_RTSACTLV_Msk;
325+
// Configure RTS trigger level to 8 bytes
328326
uart_base->FIFO = (uart_base->FIFO & ~UART_FIFO_RTSTRGLV_Msk) | UART_FIFO_RTSTRGLV_8BYTES;
329-
// Enable RTS
330-
uart_base->INTEN |= UART_INTEN_ATORTSEN_Msk;
327+
328+
if (type == FlowControlRTS || type == FlowControlRTSCTS) {
329+
// Enable RTS
330+
uart_base->INTEN |= UART_INTEN_ATORTSEN_Msk;
331+
} else {
332+
// Disable RTS
333+
uart_base->INTEN &= ~UART_INTEN_ATORTSEN_Msk;
334+
/* Drive nRTS pin output to low-active. Allow the peer to be able to send data
335+
* even though its CTS is still enabled. */
336+
uart_base->MODEM &= ~UART_MODEM_RTS_Msk;
337+
}
331338
}
332-
333-
if ((type == FlowControlCTS || type == FlowControlRTSCTS) && txflow != NC) {
339+
340+
/* If CTS is disabled, we don't need to configure CTS. But to be consistent with
341+
* RTS code above, we still configure CTS. */
342+
if (txflow != NC) {
334343
// Check if CTS pin matches.
335344
uint32_t uart_cts = pinmap_peripheral(txflow, PinMap_UART_CTS);
336345
MBED_ASSERT(uart_cts == obj->serial.uart);
337346
// Enable the pin for CTS function
338347
pinmap_pinout(txflow, PinMap_UART_CTS);
339348
// nCTS pin input is low level active
340349
uart_base->MODEMSTS |= UART_MODEMSTS_CTSACTLV_Msk;
341-
// Enable CTS
342-
uart_base->INTEN |= UART_INTEN_ATOCTSEN_Msk;
350+
351+
if (type == FlowControlCTS || type == FlowControlRTSCTS) {
352+
// Enable CTS
353+
uart_base->INTEN |= UART_INTEN_ATOCTSEN_Msk;
354+
} else {
355+
// Disable CTS
356+
uart_base->INTEN &= ~UART_INTEN_ATOCTSEN_Msk;
357+
}
343358
}
344359
}
345360

targets/TARGET_NUVOTON/TARGET_M480/serial_api.c

Lines changed: 23 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -348,31 +348,38 @@ void serial_set_flow_control(serial_t *obj, FlowControl type, PinName rxflow, Pi
348348
{
349349
UART_T *uart_base = (UART_T *) NU_MODBASE(obj->serial.uart);
350350

351-
// First, disable flow control completely.
352-
uart_base->INTEN &= ~(UART_INTEN_ATORTSEN_Msk | UART_INTEN_ATOCTSEN_Msk);
353-
354-
if ((type == FlowControlRTS || type == FlowControlRTSCTS) && rxflow != NC) {
351+
if (rxflow != NC) {
355352
// Check if RTS pin matches.
356353
uint32_t uart_rts = pinmap_peripheral(rxflow, PinMap_UART_RTS);
357354
MBED_ASSERT(uart_rts == obj->serial.uart);
358355
// Enable the pin for RTS function
359356
pinmap_pinout(rxflow, PinMap_UART_RTS);
360-
357+
361358
// NOTE: Added in M480. Before configuring RTSACTLV, disable TX/RX.
362359
uart_base->FUNCSEL |= UART_FUNCSEL_TXRXDIS_Msk;
363360
while (uart_base->FIFOSTS & UART_FIFOSTS_TXRXACT_Msk);
364361
// nRTS pin output is low level active
365362
uart_base->MODEM |= UART_MODEM_RTSACTLV_Msk;
366363
// NOTE: Added in M480. After configuring RTSACTLV, re-enable TX/RX.
367364
uart_base->FUNCSEL &= ~UART_FUNCSEL_TXRXDIS_Msk;
368-
365+
// Configure RTS trigger level to 8 bytes
369366
uart_base->FIFO = (uart_base->FIFO & ~UART_FIFO_RTSTRGLV_Msk) | UART_FIFO_RTSTRGLV_8BYTES;
370367

371-
// Enable RTS
372-
uart_base->INTEN |= UART_INTEN_ATORTSEN_Msk;
368+
if (type == FlowControlRTS || type == FlowControlRTSCTS) {
369+
// Enable RTS
370+
uart_base->INTEN |= UART_INTEN_ATORTSEN_Msk;
371+
} else {
372+
// Disable RTS
373+
uart_base->INTEN &= ~UART_INTEN_ATORTSEN_Msk;
374+
/* Drive nRTS pin output to low-active. Allow the peer to be able to send data
375+
* even though its CTS is still enabled. */
376+
uart_base->MODEM &= ~UART_MODEM_RTS_Msk;
377+
}
373378
}
374379

375-
if ((type == FlowControlCTS || type == FlowControlRTSCTS) && txflow != NC) {
380+
/* If CTS is disabled, we don't need to configure CTS. But to be consistent with
381+
* RTS code above, we still configure CTS. */
382+
if (txflow != NC) {
376383
// Check if CTS pin matches.
377384
uint32_t uart_cts = pinmap_peripheral(txflow, PinMap_UART_CTS);
378385
MBED_ASSERT(uart_cts == obj->serial.uart);
@@ -387,8 +394,13 @@ void serial_set_flow_control(serial_t *obj, FlowControl type, PinName rxflow, Pi
387394
// NOTE: Added in M480. After configuring CTSACTLV, re-enable TX/RX.
388395
uart_base->FUNCSEL &= ~UART_FUNCSEL_TXRXDIS_Msk;
389396

390-
// Enable CTS
391-
uart_base->INTEN |= UART_INTEN_ATOCTSEN_Msk;
397+
if (type == FlowControlCTS || type == FlowControlRTSCTS) {
398+
// Enable CTS
399+
uart_base->INTEN |= UART_INTEN_ATOCTSEN_Msk;
400+
} else {
401+
// Disable CTS
402+
uart_base->INTEN &= ~UART_INTEN_ATOCTSEN_Msk;
403+
}
392404
}
393405
}
394406

targets/TARGET_NUVOTON/TARGET_NANO100/serial_api.c

Lines changed: 26 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -274,36 +274,50 @@ void serial_format(serial_t *obj, int data_bits, SerialParity parity, int stop_b
274274
void serial_set_flow_control(serial_t *obj, FlowControl type, PinName rxflow, PinName txflow)
275275
{
276276
UART_T *uart_base = (UART_T *) NU_MODBASE(obj->serial.uart);
277-
278-
// First, disable flow control completely.
279-
UART_DisableFlowCtrl(uart_base);
280277

281-
if ((type == FlowControlRTS || type == FlowControlRTSCTS) && rxflow != NC) {
278+
if (rxflow != NC) {
282279
// Check if RTS pin matches.
283280
uint32_t uart_rts = pinmap_peripheral(rxflow, PinMap_UART_RTS);
284281
MBED_ASSERT(uart_rts == obj->serial.uart);
285282
// Enable the pin for RTS function
286283
pinmap_pinout(rxflow, PinMap_UART_RTS);
287284
// nRTS pin output is low level active
288285
uart_base->MCSR |= UART_MCSR_LEV_RTS_Msk;
289-
// Set RTS Trigger Level as 8 bytes
286+
// Configure RTS trigger level to 8 bytes
290287
uart_base->TLCTL = (uart_base->TLCTL & ~UART_TLCTL_RTS_TRI_LEV_Msk) | UART_TLCTL_RTS_TRI_LEV_8BYTES;
291-
// Set RX Trigger Level as 8 bytes
288+
// Configure RX Trigger Level to 8 bytes
292289
uart_base->TLCTL = (uart_base->TLCTL & ~UART_TLCTL_RFITL_Msk) | UART_TLCTL_RFITL_8BYTES;
293-
// Enable RTS
294-
uart_base->CTL |= UART_CTL_AUTO_RTS_EN_Msk;
290+
291+
if (type == FlowControlRTS || type == FlowControlRTSCTS) {
292+
// Enable RTS
293+
uart_base->CTL |= UART_CTL_AUTO_RTS_EN_Msk;
294+
} else {
295+
// Disable RTS
296+
uart_base->CTL &= ~UART_CTL_AUTO_RTS_EN_Msk;
297+
/* Drive nRTS pin output to low-active. Allow the peer to be able to send data
298+
* even though its CTS is still enabled. */
299+
/* NOTE: NOT SUPPORT on NANO130 */
300+
}
295301
}
296-
297-
if ((type == FlowControlCTS || type == FlowControlRTSCTS) && txflow != NC) {
302+
303+
/* If CTS is disabled, we don't need to configure CTS. But to be consistent with
304+
* RTS code above, we still configure CTS. */
305+
if (txflow != NC) {
298306
// Check if CTS pin matches.
299307
uint32_t uart_cts = pinmap_peripheral(txflow, PinMap_UART_CTS);
300308
MBED_ASSERT(uart_cts == obj->serial.uart);
301309
// Enable the pin for CTS function
302310
pinmap_pinout(txflow, PinMap_UART_CTS);
303311
// nCTS pin input is low level active
304312
uart_base->MCSR |= UART_MCSR_LEV_CTS_Msk;
305-
// Enable CTS
306-
uart_base->CTL |= UART_CTL_AUTO_CTS_EN_Msk;
313+
314+
if (type == FlowControlCTS || type == FlowControlRTSCTS) {
315+
// Enable CTS
316+
uart_base->CTL |= UART_CTL_AUTO_CTS_EN_Msk;
317+
} else {
318+
// Disable CTS
319+
uart_base->CTL &= ~UART_CTL_AUTO_CTS_EN_Msk;
320+
}
307321
}
308322
}
309323

targets/TARGET_NUVOTON/TARGET_NUC472/serial_api.c

Lines changed: 25 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -343,35 +343,48 @@ void serial_format(serial_t *obj, int data_bits, SerialParity parity, int stop_b
343343
void serial_set_flow_control(serial_t *obj, FlowControl type, PinName rxflow, PinName txflow)
344344
{
345345
UART_T *uart_base = (UART_T *) NU_MODBASE(obj->serial.uart);
346-
347-
// First, disable flow control completely.
348-
uart_base->INTEN &= ~(UART_INTEN_ATORTSEN_Msk | UART_INTEN_ATOCTSEN_Msk);
349346

350-
if ((type == FlowControlRTS || type == FlowControlRTSCTS) && rxflow != NC) {
347+
if (rxflow != NC) {
351348
// Check if RTS pin matches.
352349
uint32_t uart_rts = pinmap_peripheral(rxflow, PinMap_UART_RTS);
353350
MBED_ASSERT(uart_rts == obj->serial.uart);
354351
// Enable the pin for RTS function
355352
pinmap_pinout(rxflow, PinMap_UART_RTS);
356353
// nRTS pin output is low level active
357354
uart_base->MODEM |= UART_MODEM_RTSACTLV_Msk;
358-
uart_base->MODEM &= ~UART_MODEM_RTS_Msk;
359-
355+
// Configure RTS trigger level to 8 bytes
360356
uart_base->FIFO = (uart_base->FIFO & ~UART_FIFO_RTSTRGLV_Msk) | UART_FIFO_RTSTRGLV_8BYTES;
361-
// Enable RTS
362-
uart_base->INTEN |= UART_INTEN_ATORTSEN_Msk;
357+
358+
if (type == FlowControlRTS || type == FlowControlRTSCTS) {
359+
// Enable RTS
360+
uart_base->INTEN |= UART_INTEN_ATORTSEN_Msk;
361+
} else {
362+
// Disable RTS
363+
uart_base->INTEN &= ~UART_INTEN_ATORTSEN_Msk;
364+
/* Drive nRTS pin output to low-active. Allow the peer to be able to send data
365+
* even though its CTS is still enabled. */
366+
uart_base->MODEM &= ~UART_MODEM_RTS_Msk;
367+
}
363368
}
364-
365-
if ((type == FlowControlCTS || type == FlowControlRTSCTS) && txflow != NC) {
369+
370+
/* If CTS is disabled, we don't need to configure CTS. But to be consistent with
371+
* RTS code above, we still configure CTS. */
372+
if (txflow != NC) {
366373
// Check if CTS pin matches.
367374
uint32_t uart_cts = pinmap_peripheral(txflow, PinMap_UART_CTS);
368375
MBED_ASSERT(uart_cts == obj->serial.uart);
369376
// Enable the pin for CTS function
370377
pinmap_pinout(txflow, PinMap_UART_CTS);
371378
// nCTS pin input is low level active
372379
uart_base->MODEMSTS |= UART_MODEMSTS_CTSACTLV_Msk;
373-
// Enable CTS
374-
uart_base->INTEN |= UART_INTEN_ATOCTSEN_Msk;
380+
381+
if (type == FlowControlCTS || type == FlowControlRTSCTS) {
382+
// Enable CTS
383+
uart_base->INTEN |= UART_INTEN_ATOCTSEN_Msk;
384+
} else {
385+
// Disable CTS
386+
uart_base->INTEN &= ~UART_INTEN_ATOCTSEN_Msk;
387+
}
375388
}
376389
}
377390

0 commit comments

Comments
 (0)