[S32K144, UART PAL] I am receiving a UART_EVENT_RX_FULL event followed by an overrun error

キャンセル
次の結果を表示 
表示  限定  | 次の代わりに検索 
もしかして: 

[S32K144, UART PAL] I am receiving a UART_EVENT_RX_FULL event followed by an overrun error

730件の閲覧回数
shishir-dey
Contributor II

My rx_fifo buffer shows only 1 byte, but the other side is sending more. Am I using the APIs correctly?

 

 

#include "uart.h"

#define UART_RX_FIFO_SIZE 512
#define UART_RX_BLOCK_SIZE 1

static uint8_t rx_fifo[UART_RX_FIFO_SIZE];
static volatile uint16_t head = 0;
static volatile uint16_t tail = 0;

static void (*user_rx_callback)(void) = NULL;

static inline bool uart_buffer_full(void){
    uint16_t next_head = (head + UART_RX_BLOCK_SIZE) % UART_RX_FIFO_SIZE;
    return (next_head == tail);
}

static inline bool uart_buffer_empty(void){
    return head == tail;
}

bool uart_read_byte(uint8_t *byte){
    if (uart_buffer_empty()) {
        return false;
    }
    *byte = rx_fifo[tail];
    tail = (tail + 1) % UART_RX_FIFO_SIZE;
    return true;
}

bool uart_init(void){
    status_t status = UART_Init(&uart_pal1_instance, &uart_pal1_Config0);
    if (status == STATUS_SUCCESS) {
        status = UART_ReceiveData(&uart_pal1_instance, &rx_fifo[head], UART_RX_BLOCK_SIZE);
        if (status == STATUS_SUCCESS) {
            return true;
        }
    }
    return false;
}

bool uart_send_data(const uint8_t *data, uint32_t length){
    if (data == NULL || length == 0) {
        return false;
    }
    status_t status = UART_SendData(&uart_pal1_instance, data, length);
    return (status == STATUS_SUCCESS);
}

bool uart_receive_data(uint8_t *data, uint32_t length){
    if (data == NULL || length == 0) {
        return false;
    }
    uint32_t i;
    for (i = 0; i < length; i++) {
        if (!uart_read_byte(&data[i])) {
            break;
        }
    }
    return (i > 0);
}

void uart_register_rx_callback(void (*callback)(void)){
    user_rx_callback = callback;
}

void uart0_rx_callback(void *driverState, uart_event_t event, void *userData){
    (void)driverState;
    (void)userData;
    switch(event) {
    case UART_EVENT_RX_FULL: {
        uint16_t next_head = (head + UART_RX_BLOCK_SIZE) % UART_RX_FIFO_SIZE;
        UART_SetRxBuffer(&uart_pal1_instance, &rx_fifo[next_head], UART_RX_BLOCK_SIZE);
        head = next_head;
        if (head == tail) {
            tail = (tail + UART_RX_BLOCK_SIZE) % UART_RX_FIFO_SIZE;
        }
        if (user_rx_callback != NULL) {
            user_rx_callback();
        }
    }
    break;
    case UART_EVENT_END_TRANSFER:
        break;
    case UART_EVENT_ERROR:
        head = tail = 0;
        UART_SetRxBuffer(&uart_pal1_instance, &rx_fifo[head], UART_RX_BLOCK_SIZE);
        break;
    default:
        break;
    }
}

 

 

 

タグ(3)
0 件の賞賛
返信
4 返答(返信)

698件の閲覧回数
RomanVR
NXP Employee
NXP Employee

Hello @shishir-dey 

While reviewing your code, I noticed that in the functions "UART_SetBuffer(&uart_pal1_instance, &rx_fifo[next_head], UART_RX_BLOCK_SIZE);" and  "UART_ReceiveData(&uart_pal1_instance, &rx_fifo[head], UART_RX_BLOCK_SIZE);" you are passing as the length of the buffer "UART_RX_BLOCK_SIZE" which is defined as 1, as a result, your receiving buffer is always configured to receive 1 byte only, to receive more data you should increase the value of UART_RX_BLOCK_SIZE to match the expected payload size.

Please let me know if this information was helpful to solve your issue.

- RomanVR.

Best Regards!
0 件の賞賛
返信

648件の閲覧回数
shishir-dey
Contributor II
I found that "UART_RX_BLOCK_SIZE" isn’t the issue—the problem is actually an overrun. My UART baud rate is 2 Mbps, and the overrun occurs when the UART clock source is 8 MHz or 48 MHz. The UART interrupt is already set to the highest priority among all interrupts. For now, I’ve added a small delay after each byte on the other side as a temporary fix.

Can you suggest better ways to gracefully handle this overrun error?
0 件の賞賛
返信

639件の閲覧回数
RomanVR
NXP Employee
NXP Employee

Hi @shishir-dey.

Could you please share your project so I can further analyze the issue? Additionally, please refer to the following community post where an RX Overrun issue was solved by moving the "SendData" function into the RxCallback function: uart_pal_s32k144w status = STATUS_UART_RX_OVERRUN.

Let me know if the solution works for you and I will be waiting for your answer.

- RomanVR.

Best Regards!
0 件の賞賛
返信

630件の閲覧回数
shishir-dey
Contributor II
Got it. Instead of using blocking "uart_send_data" at multiple points in the program, I should trigger a send and handle the rest in "uart0_tx_callback", similar to how I did for receive. I’ll give it a try and update you.
0 件の賞賛
返信