[Nuvoton] Fix UART flow control CTS/RTS

Configure RTS pin outout to active low when RTS is disabled. This allows the peer to be able
to send data if its CTS is still enabled.
pull/9197/head
ccli8 2018-12-24 18:25:53 +08:00
parent 70956ee9bb
commit 17fb5b7ff2
5 changed files with 122 additions and 56 deletions

View File

@ -361,10 +361,7 @@ void serial_set_flow_control(serial_t *obj, FlowControl type, PinName rxflow, Pi
{
UART_T *uart_base = (UART_T *) NU_MODBASE(obj->serial.uart);
// First, disable flow control completely.
uart_base->INTEN &= ~(UART_INTEN_ATORTSEN_Msk | UART_INTEN_ATOCTSEN_Msk);
if ((type == FlowControlRTS || type == FlowControlRTSCTS) && rxflow != NC) {
if (rxflow != NC) {
// Check if RTS pin matches.
uint32_t uart_rts = pinmap_peripheral(rxflow, PinMap_UART_RTS);
MBED_ASSERT(uart_rts == obj->serial.uart);
@ -378,14 +375,24 @@ void serial_set_flow_control(serial_t *obj, FlowControl type, PinName rxflow, Pi
uart_base->MODEM |= UART_MODEM_RTSACTLV_Msk;
// NOTE: Added in M480/M2351. After configuring RTSACTLV, re-enable TX/RX.
uart_base->FUNCSEL &= ~UART_FUNCSEL_TXRXDIS_Msk;
// Configure RTS trigger level to 8 bytes
uart_base->FIFO = (uart_base->FIFO & ~UART_FIFO_RTSTRGLV_Msk) | UART_FIFO_RTSTRGLV_8BYTES;
// Enable RTS
uart_base->INTEN |= UART_INTEN_ATORTSEN_Msk;
if (type == FlowControlRTS || type == FlowControlRTSCTS) {
// Enable RTS
uart_base->INTEN |= UART_INTEN_ATORTSEN_Msk;
} else {
// Disable RTS
uart_base->INTEN &= ~UART_INTEN_ATORTSEN_Msk;
/* Drive nRTS pin output to low-active. Allow the peer to be able to send data
* even though its CTS is still enabled. */
uart_base->MODEM &= ~UART_MODEM_RTS_Msk;
}
}
if ((type == FlowControlCTS || type == FlowControlRTSCTS) && txflow != NC) {
/* If CTS is disabled, we don't need to configure CTS. But to be consistent with
* RTS code above, we still configure CTS. */
if (txflow != NC) {
// Check if CTS pin matches.
uint32_t uart_cts = pinmap_peripheral(txflow, PinMap_UART_CTS);
MBED_ASSERT(uart_cts == obj->serial.uart);
@ -400,8 +407,13 @@ void serial_set_flow_control(serial_t *obj, FlowControl type, PinName rxflow, Pi
// NOTE: Added in M480/M2351. After configuring CTSACTLV, re-enable TX/RX.
uart_base->FUNCSEL &= ~UART_FUNCSEL_TXRXDIS_Msk;
// Enable CTS
uart_base->INTEN |= UART_INTEN_ATOCTSEN_Msk;
if (type == FlowControlCTS || type == FlowControlRTSCTS) {
// Enable CTS
uart_base->INTEN |= UART_INTEN_ATOCTSEN_Msk;
} else {
// Disable CTS
uart_base->INTEN &= ~UART_INTEN_ATOCTSEN_Msk;
}
}
}

View File

@ -313,11 +313,8 @@ void serial_format(serial_t *obj, int data_bits, SerialParity parity, int stop_b
void serial_set_flow_control(serial_t *obj, FlowControl type, PinName rxflow, PinName txflow)
{
UART_T *uart_base = (UART_T *) NU_MODBASE(obj->serial.uart);
// First, disable flow control completely.
uart_base->INTEN &= ~(UART_INTEN_ATORTSEN_Msk | UART_INTEN_ATOCTSEN_Msk);
if ((type == FlowControlRTS || type == FlowControlRTSCTS) && rxflow != NC) {
if (rxflow != NC) {
// Check if RTS pin matches.
uint32_t uart_rts = pinmap_peripheral(rxflow, PinMap_UART_RTS);
MBED_ASSERT(uart_rts == obj->serial.uart);
@ -325,12 +322,24 @@ void serial_set_flow_control(serial_t *obj, FlowControl type, PinName rxflow, Pi
pinmap_pinout(rxflow, PinMap_UART_RTS);
// nRTS pin output is low level active
uart_base->MODEM |= UART_MODEM_RTSACTLV_Msk;
// Configure RTS trigger level to 8 bytes
uart_base->FIFO = (uart_base->FIFO & ~UART_FIFO_RTSTRGLV_Msk) | UART_FIFO_RTSTRGLV_8BYTES;
// Enable RTS
uart_base->INTEN |= UART_INTEN_ATORTSEN_Msk;
if (type == FlowControlRTS || type == FlowControlRTSCTS) {
// Enable RTS
uart_base->INTEN |= UART_INTEN_ATORTSEN_Msk;
} else {
// Disable RTS
uart_base->INTEN &= ~UART_INTEN_ATORTSEN_Msk;
/* Drive nRTS pin output to low-active. Allow the peer to be able to send data
* even though its CTS is still enabled. */
uart_base->MODEM &= ~UART_MODEM_RTS_Msk;
}
}
if ((type == FlowControlCTS || type == FlowControlRTSCTS) && txflow != NC) {
/* If CTS is disabled, we don't need to configure CTS. But to be consistent with
* RTS code above, we still configure CTS. */
if (txflow != NC) {
// Check if CTS pin matches.
uint32_t uart_cts = pinmap_peripheral(txflow, PinMap_UART_CTS);
MBED_ASSERT(uart_cts == obj->serial.uart);
@ -338,8 +347,14 @@ void serial_set_flow_control(serial_t *obj, FlowControl type, PinName rxflow, Pi
pinmap_pinout(txflow, PinMap_UART_CTS);
// nCTS pin input is low level active
uart_base->MODEMSTS |= UART_MODEMSTS_CTSACTLV_Msk;
// Enable CTS
uart_base->INTEN |= UART_INTEN_ATOCTSEN_Msk;
if (type == FlowControlCTS || type == FlowControlRTSCTS) {
// Enable CTS
uart_base->INTEN |= UART_INTEN_ATOCTSEN_Msk;
} else {
// Disable CTS
uart_base->INTEN &= ~UART_INTEN_ATOCTSEN_Msk;
}
}
}

View File

@ -348,16 +348,13 @@ void serial_set_flow_control(serial_t *obj, FlowControl type, PinName rxflow, Pi
{
UART_T *uart_base = (UART_T *) NU_MODBASE(obj->serial.uart);
// First, disable flow control completely.
uart_base->INTEN &= ~(UART_INTEN_ATORTSEN_Msk | UART_INTEN_ATOCTSEN_Msk);
if ((type == FlowControlRTS || type == FlowControlRTSCTS) && rxflow != NC) {
if (rxflow != NC) {
// Check if RTS pin matches.
uint32_t uart_rts = pinmap_peripheral(rxflow, PinMap_UART_RTS);
MBED_ASSERT(uart_rts == obj->serial.uart);
// Enable the pin for RTS function
pinmap_pinout(rxflow, PinMap_UART_RTS);
// NOTE: Added in M480. Before configuring RTSACTLV, disable TX/RX.
uart_base->FUNCSEL |= UART_FUNCSEL_TXRXDIS_Msk;
while (uart_base->FIFOSTS & UART_FIFOSTS_TXRXACT_Msk);
@ -365,14 +362,24 @@ void serial_set_flow_control(serial_t *obj, FlowControl type, PinName rxflow, Pi
uart_base->MODEM |= UART_MODEM_RTSACTLV_Msk;
// NOTE: Added in M480. After configuring RTSACTLV, re-enable TX/RX.
uart_base->FUNCSEL &= ~UART_FUNCSEL_TXRXDIS_Msk;
// Configure RTS trigger level to 8 bytes
uart_base->FIFO = (uart_base->FIFO & ~UART_FIFO_RTSTRGLV_Msk) | UART_FIFO_RTSTRGLV_8BYTES;
// Enable RTS
uart_base->INTEN |= UART_INTEN_ATORTSEN_Msk;
if (type == FlowControlRTS || type == FlowControlRTSCTS) {
// Enable RTS
uart_base->INTEN |= UART_INTEN_ATORTSEN_Msk;
} else {
// Disable RTS
uart_base->INTEN &= ~UART_INTEN_ATORTSEN_Msk;
/* Drive nRTS pin output to low-active. Allow the peer to be able to send data
* even though its CTS is still enabled. */
uart_base->MODEM &= ~UART_MODEM_RTS_Msk;
}
}
if ((type == FlowControlCTS || type == FlowControlRTSCTS) && txflow != NC) {
/* If CTS is disabled, we don't need to configure CTS. But to be consistent with
* RTS code above, we still configure CTS. */
if (txflow != NC) {
// Check if CTS pin matches.
uint32_t uart_cts = pinmap_peripheral(txflow, PinMap_UART_CTS);
MBED_ASSERT(uart_cts == obj->serial.uart);
@ -387,8 +394,13 @@ void serial_set_flow_control(serial_t *obj, FlowControl type, PinName rxflow, Pi
// NOTE: Added in M480. After configuring CTSACTLV, re-enable TX/RX.
uart_base->FUNCSEL &= ~UART_FUNCSEL_TXRXDIS_Msk;
// Enable CTS
uart_base->INTEN |= UART_INTEN_ATOCTSEN_Msk;
if (type == FlowControlCTS || type == FlowControlRTSCTS) {
// Enable CTS
uart_base->INTEN |= UART_INTEN_ATOCTSEN_Msk;
} else {
// Disable CTS
uart_base->INTEN &= ~UART_INTEN_ATOCTSEN_Msk;
}
}
}

View File

@ -274,11 +274,8 @@ void serial_format(serial_t *obj, int data_bits, SerialParity parity, int stop_b
void serial_set_flow_control(serial_t *obj, FlowControl type, PinName rxflow, PinName txflow)
{
UART_T *uart_base = (UART_T *) NU_MODBASE(obj->serial.uart);
// First, disable flow control completely.
UART_DisableFlowCtrl(uart_base);
if ((type == FlowControlRTS || type == FlowControlRTSCTS) && rxflow != NC) {
if (rxflow != NC) {
// Check if RTS pin matches.
uint32_t uart_rts = pinmap_peripheral(rxflow, PinMap_UART_RTS);
MBED_ASSERT(uart_rts == obj->serial.uart);
@ -286,15 +283,26 @@ void serial_set_flow_control(serial_t *obj, FlowControl type, PinName rxflow, Pi
pinmap_pinout(rxflow, PinMap_UART_RTS);
// nRTS pin output is low level active
uart_base->MCSR |= UART_MCSR_LEV_RTS_Msk;
// Set RTS Trigger Level as 8 bytes
// Configure RTS trigger level to 8 bytes
uart_base->TLCTL = (uart_base->TLCTL & ~UART_TLCTL_RTS_TRI_LEV_Msk) | UART_TLCTL_RTS_TRI_LEV_8BYTES;
// Set RX Trigger Level as 8 bytes
// Configure RX Trigger Level to 8 bytes
uart_base->TLCTL = (uart_base->TLCTL & ~UART_TLCTL_RFITL_Msk) | UART_TLCTL_RFITL_8BYTES;
// Enable RTS
uart_base->CTL |= UART_CTL_AUTO_RTS_EN_Msk;
if (type == FlowControlRTS || type == FlowControlRTSCTS) {
// Enable RTS
uart_base->CTL |= UART_CTL_AUTO_RTS_EN_Msk;
} else {
// Disable RTS
uart_base->CTL &= ~UART_CTL_AUTO_RTS_EN_Msk;
/* Drive nRTS pin output to low-active. Allow the peer to be able to send data
* even though its CTS is still enabled. */
/* NOTE: NOT SUPPORT on NANO130 */
}
}
if ((type == FlowControlCTS || type == FlowControlRTSCTS) && txflow != NC) {
/* If CTS is disabled, we don't need to configure CTS. But to be consistent with
* RTS code above, we still configure CTS. */
if (txflow != NC) {
// Check if CTS pin matches.
uint32_t uart_cts = pinmap_peripheral(txflow, PinMap_UART_CTS);
MBED_ASSERT(uart_cts == obj->serial.uart);
@ -302,8 +310,14 @@ void serial_set_flow_control(serial_t *obj, FlowControl type, PinName rxflow, Pi
pinmap_pinout(txflow, PinMap_UART_CTS);
// nCTS pin input is low level active
uart_base->MCSR |= UART_MCSR_LEV_CTS_Msk;
// Enable CTS
uart_base->CTL |= UART_CTL_AUTO_CTS_EN_Msk;
if (type == FlowControlCTS || type == FlowControlRTSCTS) {
// Enable CTS
uart_base->CTL |= UART_CTL_AUTO_CTS_EN_Msk;
} else {
// Disable CTS
uart_base->CTL &= ~UART_CTL_AUTO_CTS_EN_Msk;
}
}
}

View File

@ -343,11 +343,8 @@ void serial_format(serial_t *obj, int data_bits, SerialParity parity, int stop_b
void serial_set_flow_control(serial_t *obj, FlowControl type, PinName rxflow, PinName txflow)
{
UART_T *uart_base = (UART_T *) NU_MODBASE(obj->serial.uart);
// First, disable flow control completely.
uart_base->INTEN &= ~(UART_INTEN_ATORTSEN_Msk | UART_INTEN_ATOCTSEN_Msk);
if ((type == FlowControlRTS || type == FlowControlRTSCTS) && rxflow != NC) {
if (rxflow != NC) {
// Check if RTS pin matches.
uint32_t uart_rts = pinmap_peripheral(rxflow, PinMap_UART_RTS);
MBED_ASSERT(uart_rts == obj->serial.uart);
@ -355,14 +352,24 @@ void serial_set_flow_control(serial_t *obj, FlowControl type, PinName rxflow, Pi
pinmap_pinout(rxflow, PinMap_UART_RTS);
// nRTS pin output is low level active
uart_base->MODEM |= UART_MODEM_RTSACTLV_Msk;
uart_base->MODEM &= ~UART_MODEM_RTS_Msk;
// Configure RTS trigger level to 8 bytes
uart_base->FIFO = (uart_base->FIFO & ~UART_FIFO_RTSTRGLV_Msk) | UART_FIFO_RTSTRGLV_8BYTES;
// Enable RTS
uart_base->INTEN |= UART_INTEN_ATORTSEN_Msk;
if (type == FlowControlRTS || type == FlowControlRTSCTS) {
// Enable RTS
uart_base->INTEN |= UART_INTEN_ATORTSEN_Msk;
} else {
// Disable RTS
uart_base->INTEN &= ~UART_INTEN_ATORTSEN_Msk;
/* Drive nRTS pin output to low-active. Allow the peer to be able to send data
* even though its CTS is still enabled. */
uart_base->MODEM &= ~UART_MODEM_RTS_Msk;
}
}
if ((type == FlowControlCTS || type == FlowControlRTSCTS) && txflow != NC) {
/* If CTS is disabled, we don't need to configure CTS. But to be consistent with
* RTS code above, we still configure CTS. */
if (txflow != NC) {
// Check if CTS pin matches.
uint32_t uart_cts = pinmap_peripheral(txflow, PinMap_UART_CTS);
MBED_ASSERT(uart_cts == obj->serial.uart);
@ -370,8 +377,14 @@ void serial_set_flow_control(serial_t *obj, FlowControl type, PinName rxflow, Pi
pinmap_pinout(txflow, PinMap_UART_CTS);
// nCTS pin input is low level active
uart_base->MODEMSTS |= UART_MODEMSTS_CTSACTLV_Msk;
// Enable CTS
uart_base->INTEN |= UART_INTEN_ATOCTSEN_Msk;
if (type == FlowControlCTS || type == FlowControlRTSCTS) {
// Enable CTS
uart_base->INTEN |= UART_INTEN_ATOCTSEN_Msk;
} else {
// Disable CTS
uart_base->INTEN &= ~UART_INTEN_ATOCTSEN_Msk;
}
}
}