I added the line UART_EnableInterrupts(DEMO_UART, kUART_IdleLineInterruptEnable); before the call to UART_TransferStartRingBuffer().
After UART_UserCallback() kStatus_UART_RxHardwareOverrun, I checked the registers.
UART1 C2.ILIE is 1
UART1 S1.IDLE is 0
See registers below.

See code below.
Since C2.ILIE is set, why would UART_UserCallback() never got called with kStatus_UART_RxIdle?
Thanks,
Bruce
// File: uart_interrupt_rb_transfer.c
#include "board.h"
#include "fsl_uart.h"
#include "pin_mux.h"
#include "clock_config.h"
#include <stdio.h>
#include <ctype.h>
/*******************************************************************************
* Definitions
******************************************************************************/
/* UART instance and clock */
#define DEMO_UART UART1
#define DEMO_UART_CLKSRC BUS_CLK
#define DEMO_UART_CLK_FREQ CLOCK_GetFreq(BUS_CLK)
#define RX_RING_BUFFER_SIZE 20U
#define ECHO_BUFFER_SIZE 8U
/*******************************************************************************
* Prototypes
******************************************************************************/
/* UART user callback */
void UART_UserCallback(UART_Type *base, uart_handle_t *handle, status_t status, void *userData);
/*******************************************************************************
* Variables
******************************************************************************/
uart_handle_t g_uartHandle;
uint8_t g_rxRingBuffer[RX_RING_BUFFER_SIZE] = {0}; /* RX ring buffer. */
uint8_t g_rxBuffer[ECHO_BUFFER_SIZE] = {0};
uint8_t g_txBuffer[] = "ATE0\n";
volatile bool bProcessRx = false;
volatile bool bGotTxIdle = false;
volatile bool bRxMessageReceived = false;
char szDummyObj[] = "Hello";
/*******************************************************************************
* Code
******************************************************************************/
/* UART user callback */
void UART_UserCallback(UART_Type *base, uart_handle_t *handle, status_t status, void *userData)
{
assert(0 == strcmp(szDummyObj, (char*) userData));
switch(status)
{
case kStatus_UART_TxIdle:
printf("\r\nISR: Tx Idle\r\n");
bGotTxIdle = true;
break;
case kStatus_UART_RxIdle:
printf("\r\nISR: Rx Idle\r\n");
bProcessRx = true;
break;
case kStatus_UART_RxRingBufferOverrun:
printf("\r\nISR: Rx Ring Buffer Overrun\r\n");
bProcessRx = true;
break;
case kStatus_UART_RxHardwareOverrun:
printf("\r\nISR: Rx Hardware Overrun\r\n");
bProcessRx = true;
break;
case kStatus_UART_NoiseError:
printf("\r\nISR: Noise Error\r\n");
break;
case kStatus_UART_FramingError:
printf("\r\nISR: Framing Error\r\n");
bProcessRx = true;
break;
default:
printf("\r\nISR: status: %d\r\n", status);
break;
}
if (bProcessRx)
{
bProcessRx = false;
}
}
// output
#define BOARD_CELL_PWRKEY_GPIO GPIOE // PTE20
#define BOARD_CELL_PWRKEY_PORT PORTE
#define BOARD_CELL_PWRKEY_GPIO_PIN 20U
void delay(int iMillisec)
{
int iLoops = iMillisec * 4400;
//printf("delay(%d)\r\n", iMillisec);
for (int i = 0; i < iLoops; ++i)
{
}
}
/*
* Purpose: Cycling PWRKEY will turn the modem on or off.
*/
void cycleModemPWRKEY(void)
{
// modem did not respond, so wake it up
printf("\tEC21 Pulse PWRKEY low for at least 500ms\r\n");
printf("\tEC21 PWRKEY - High\r\n");
GPIO_WritePinOutput(BOARD_CELL_PWRKEY_GPIO, BOARD_CELL_PWRKEY_GPIO_PIN, 1);
printf("\tEC21 Delay 100 ms\r\n");
delay(100);
printf("\tEC21 PWRKEY - Low\r\n");
GPIO_WritePinOutput(BOARD_CELL_PWRKEY_GPIO, BOARD_CELL_PWRKEY_GPIO_PIN, 0);
printf("\tEC21 Delay 800 ms - minimum pulse width is 500ms\r\n");
delay(800);
printf("\tEC21 PWRKEY - High\r\n");
GPIO_WritePinOutput(BOARD_CELL_PWRKEY_GPIO, BOARD_CELL_PWRKEY_GPIO_PIN, 1);
}
/*!
* @brief Main function
*/
int main(void)
{
uart_config_t config;
uart_transfer_t sendXfer;
printf("starting\r\n");
BOARD_InitPins();
BOARD_BootClockRUN();
cycleModemPWRKEY();
/*
* config.baudRate_Bps = 115200U;
* config.parityMode = kUART_ParityDisabled;
* config.stopBitCount = kUART_OneStopBit;
* config.txFifoWatermark = 0;
* config.rxFifoWatermark = 1;
* config.enableTx = false;
* config.enableRx = false;
*/
UART_GetDefaultConfig(&config);
config.baudRate_Bps = BOARD_DEBUG_UART_BAUDRATE;
config.enableTx = true;
config.enableRx = true;
UART_Init(DEMO_UART, &config, DEMO_UART_CLK_FREQ);
UART_TransferCreateHandle(DEMO_UART, &g_uartHandle, UART_UserCallback, szDummyObj);
UART_EnableInterrupts(DEMO_UART, kUART_IdleLineInterruptEnable); // ADDED PER NXP COMMUNITY SUGGESTION
UART_TransferStartRingBuffer(DEMO_UART, &g_uartHandle, g_rxRingBuffer, RX_RING_BUFFER_SIZE);
sendXfer.data = g_txBuffer;
sendXfer.dataSize = strlen((char*)g_txBuffer);
// call to UART_TransferReceiveNonBlocking() enables kStatus_UART_RxIdle event
char szRxTemp[100] = {0};
int iCount = 0;
char szLastMessage[100];
size_t receivedCount;
uart_transfer_t receiveXfer;
while(1)
{
printf("UART_TransferReceiveNonBlocking()\r\n");
bRxMessageReceived = false;
receiveXfer.data = (uint8_t*)szRxTemp;
receiveXfer.dataSize = sizeof(szRxTemp);
do
{
UART_TransferReceiveNonBlocking(DEMO_UART, &g_uartHandle, &receiveXfer, &receivedCount);
if (receivedCount)
{
// done when \n (end of string) is received
if (NULL != strstr(szRxTemp, "\n"))
{
strcpy(szLastMessage, szRxTemp);
bRxMessageReceived = true;
memset(szRxTemp, 0, sizeof(szRxTemp));
iCount = 0;
}
else
{
iCount += receivedCount;
assert(iCount < sizeof(szRxTemp));
receiveXfer.data = (uint8_t*)&szRxTemp[iCount];
receiveXfer.dataSize = sizeof(szRxTemp) - iCount;
}
}
} while (!bRxMessageReceived);
// print to debug console, with hex for not printable chars
char szTemp[100] = {0};
for(int i = 0; i < strlen(szLastMessage); ++i)
{
int iLength = strlen(szTemp);
if (isprint(szLastMessage[i]))
sprintf(&szTemp[iLength], "%c", szLastMessage[i]);
else
sprintf(&szTemp[iLength], "<0x%02X>", szLastMessage[i]);
}
printf("LastMessage: %s\r\n", szTemp);
}
while (1)
{
while(!bRxMessageReceived)
{
}
printf("TX: %s", g_txBuffer);
bGotTxIdle = false;
UART_TransferSendNonBlocking(DEMO_UART, &g_uartHandle, &sendXfer);
while (!bGotTxIdle)
{
}
printf("\r\n");
}
}