I am trying to enable RTS/CTS flow control on LP FLEXCOMM2 UART on a FRDM-MCXN947 with the fsl_lpuart_freertos driver but I am getting kStatus_LPUART_RxRingBufferOverrun.
I believe the pin_mux configuration (below) I have is correct but the logic analyzer never shows change to the RTS line.
/* FUNCTION ************************************************************************************************************
*
* Function Name : UART_Pins
* Description : Configures pin routing and optionally pin electrical features.
*
* END ****************************************************************************************************************/
void UART_Pins(void)
{
/* Enables the clock for PORT4: Enables clock */
CLOCK_EnableClock(kCLOCK_Port4);
/* PORT4_0 (pin P1) is configured as FC2_P0 */
PORT_SetPinMux(UART_PINS_FC2_RX_PORT, UART_PINS_FC2_RX_PIN, kPORT_MuxAlt2);
PORT4->PCR[0] = ((PORT4->PCR[0] &
/* Mask bits to zero which are setting */
(~(PORT_PCR_IBE_MASK)))
/* Input Buffer Enable: Enables. */
| PORT_PCR_IBE(PCR_IBE_ibe1));
/* PORT4_1 (pin P2) is configured as FC2_P1 */
PORT_SetPinMux(UART_PINS_FC2_TX_PORT, UART_PINS_FC2_TX_PIN, kPORT_MuxAlt2);
PORT4->PCR[1] = ((PORT4->PCR[1] &
/* Mask bits to zero which are setting */
(~(PORT_PCR_IBE_MASK)))
/* Input Buffer Enable: Enables. */
| PORT_PCR_IBE(PCR_IBE_ibe1));
/* PORT4_16 (pin R8) is configured as FC2_P2 */
PORT_SetPinMux(UART_PINS_FC2_RTS_PORT, UART_PINS_FC2_RTS_PIN, kPORT_MuxAlt2);
PORT4->PCR[16] = ((PORT4->PCR[16] &
/* Mask bits to zero which are setting */
(~(PORT_PCR_IBE_MASK)))
/* Input Buffer Enable: Enables. */
| PORT_PCR_IBE(PCR_IBE_ibe1));
/* PORT4_17 (pin R9) is configured as FC2_P3 */
PORT_SetPinMux(UART_PINS_FC2_CTS_PORT, UART_PINS_FC2_CTS_PIN, kPORT_MuxAlt2);
PORT4->PCR[17] = ((PORT4->PCR[17] &
/* Mask bits to zero which are setting */
(~(PORT_PCR_IBE_MASK)))
/* Input Buffer Enable: Enables. */
| PORT_PCR_IBE(PCR_IBE_ibe1));
}
Here is the flexcomm configuration in peripherals.c
/***********************************************************************************************************************
* LP_FLEXCOMM2 initialization code
**********************************************************************************************************************/
/* clang-format off */
/* TEXT BELOW IS USED AS SETTING FOR TOOLS *************************************
instance:
- name: 'LP_FLEXCOMM2'
- type: 'lpflexcomm_lpuart'
- mode: 'freertos'
- custom_name_enabled: 'false'
- type_id: 'lpflexcomm_lpuart_2.3.0'
- functional_group: 'BOARD_InitPeripherals'
- peripheral: 'LP_FLEXCOMM2'
- config_sets:
- fsl_lpuart_freertos:
- lpuart_rtos_configuration:
- timingConfig:
- clockSource: 'LPFLEXCOMMFunctionClock'
- lpuartSrcClkFreq: 'BOARD_BootClockPLL150M'
- baudRateBpsStr: '115200'
- parity: 'kLPUART_ParityDisabled'
- stopbits: 'kLPUART_OneStopBit'
- buffer_size: '512'
- enableRxRTS: 'true'
- enableTxCTS: 'true'
- txCtsSource: 'kLPUART_CtsSourcePin'
- txCtsConfig: 'kLPUART_CtsSampleAtStart'
- rx_timeout_constant_ms: '0'
- rx_timeout_multiplier_ms: '0'
- tx_timeout_constant_ms: '0'
- tx_timeout_multiplier_ms: '0'
- interrupt_rx_tx:
- IRQn: 'LP_FLEXCOMM2_IRQn'
- enable_priority: 'false'
- priority: '0'
* BE CAREFUL MODIFYING THIS COMMENT - IT IS YAML SETTINGS FOR TOOLS **********/
/* clang-format on */
lpuart_rtos_handle_t LP_FLEXCOMM2_rtos_handle;
lpuart_handle_t LP_FLEXCOMM2_lpuart_handle;
uint8_t LP_FLEXCOMM2_background_buffer[LP_FLEXCOMM2_BACKGROUND_BUFFER_SIZE];
lpuart_rtos_config_t LP_FLEXCOMM2_rtos_config = {
.base = LP_FLEXCOMM2_PERIPHERAL,
.srcclk = LP_FLEXCOMM2_CLOCK_SOURCE,
.baudrate = 115200UL,
.parity = kLPUART_ParityDisabled,
.stopbits = kLPUART_OneStopBit,
.buffer = LP_FLEXCOMM2_background_buffer,
.buffer_size = 512UL,
.enableRxRTS = true,
.enableTxCTS = true,
.txCtsSource = kLPUART_CtsSourcePin,
.txCtsConfig = kLPUART_CtsSampleAtStart,
.rx_timeout_constant_ms = 0UL,
.rx_timeout_multiplier_ms = 0UL,
.tx_timeout_constant_ms = 0UL,
.tx_timeout_multiplier_ms = 0UL
};
If RTS is working correctly then shouldn't the driver never overflow?
I'm saying the RTS flow control is not compatible with the ring buffer configuration since the reading doesn't stop when the ring is full.
If the ring is full and flow control is enabled, the reading from the UART FIFO (read data register) should stop instead of overwriting the oldest data in the ring buffer.
Hi @koj
1. First, i think you can refer to the MCX Nx4x Reference Manual Chapter 66.5.2.3.3
Hardware flow control.
2. Then Check RTS/CTS Functionality with Logic Analyzer
Since your logic analyzer does not show RTS toggling. So you can use a simple test where you manually set/clear RTS.
3. Test with Bare-Metal Code
You can test the SDK lpuart_polling example.
This demo has FSL_FEATURE_LPUART_HAS_MODEM_SUPPORT feature.
You can config the RTS/CTS pin and test this demo.
BR
Harry
After taking the time to debug this I see that the fsl_lpuart_freertos.c uses the fsl_lpuart.c ring buffer feature and the LPUART_TransferHandleIRQ doesn't stop reading from the UART->DATA when the ring buffer is full. The IRQ Handler just reports an overrun, which the LPUART_RTOS_Callback() uses to eventually abort the Receive, and overwrites the the oldest data instead.
Since the DATA is always read the RTS line is never deasserted because the STAT[RDRF] is never 1.
The fsl_lpuart.c driver only sets the MODIR[RXRTSE] during init, and doesn't consider flow control fully.
Hi @koj
"The fsl_lpuart.c driver only sets the MODIR[RXRTSE] during init, and doesn't consider flow control fully."
If you enable the RxRTS and TxCTS in the LPUART_Init.
/* Set the CTS configuration/TX CTS source. */
base->MODIR |= LPUART_MODIR_TXCTSC(config->txCtsConfig) | LPUART_MODIR_TXCTSSRC(config->txCtsSource);
if (true == config->enableRxRTS)
{
/* Enable the receiver RTS(request-to-send) function. */
base->MODIR |= LPUART_MODIR_RXRTSE_MASK;
}
if (true == config->enableTxCTS)
{
/* Enable the CTS(clear-to-send) function. */
base->MODIR |= LPUART_MODIR_TXCTSE_MASK;
}
Do you mean this won't work?
BR
Harry