Hello,
I am working with S32K146 and see a issue with UART when we run for long time.
I see the UART ISR running very frequently(System view), and please let me know if I did any mistake in initialization.
Do I need to clear ISR flags in call back function in case Error?
Why the UART ISR running very frequently?
Please give any example code to work with UART using interrupts and call back function.
I have give UART ISR priority is 14. Does bigger number has high priority?
Call back
------------
static void uart_callback(void *driver_state, uart_event_t event, void *user_data)
{
(void) driver_state;
(void) user_data;
if(event == UART_EVENT_RX_FULL){
OS_MAILBOX_Put1(&g_uart_rx_mb, (char*)g_uart_rx_buf);
LPUART_DRV_SetRxBuffer(INST_UART0, g_uart_rx_buf, 1);
}
}
Init
-----------
/*! uart0 configuration structure */
const lpuart_user_config_t uart0_InitConfig0 = {
.transferType = LPUART_USING_INTERRUPTS,
.baudRate = 115200U,
.parityMode = LPUART_PARITY_DISABLED,
.stopBitCount = LPUART_ONE_STOP_BIT,
.bitCountPerChar = LPUART_8_BITS_PER_CHAR,
.rxDMAChannel = 0U,
.txDMAChannel = 0U,
};
typedef enum
{
UART_IRQ_PRIO = 14u,
FLEXCAN_IRQ_PRIO = 10,
SPI2_IRQ_PRIO = 9u,
QCA_IRQ_PRIO = 9u,
FTM_IRQ_PRIO = 8u
} interrupt_priorities_t;
void uart_init()
{
OS_MAILBOX_Create(&g_uart_rx_mb, 1, UART_RX_MB_BUFFER_SIZE, g_uart_rx_mb_buffer);
OS_QUEUE_Create(&g_uart_uds_queue, &g_uart_qu_buffer, sizeof(g_uart_qu_buffer));
OS_MUTEX_Create(&g_uart_tx_mutex);
INT_SYS_SetPriority(s_lpuartRxTxIrqId[INST_UART0], UART_IRQ_PRIO);
LPUART_DRV_Init(INST_UART0, &uart0_State, &uart0_InitConfig0);
LPUART_DRV_InstallRxCallback(INST_UART0, uart_callback, NULL);
debug_log_print(LL_DEV, MOD_UART, "Init OK\n");
}
In task
-------------
rb_init(&g_uart_rx_rb, g_uart_rx_rb_data, UART_RX_RB_SIZE);
status_t rx_status = STATUS_SUCCESS;
do{
OS_Delay(10);
rx_status = LPUART_DRV_ReceiveData(INST_UART0, g_uart_rx_buf, 1);
}while(rx_status != STATUS_SUCCESS);
debug_log_print(LL_DEV, MOD_UART, "RX Receiving Started\n");
while(1)
{
uart_set_diagnosis_mode();
uint32_t bytes_remaining = 0;
status_t s = LPUART_DRV_GetReceiveStatus(INST_UART0, &bytes_remaining);
if(s != STATUS_BUSY){
debug_log_print(LL_ERR, MOD_UART, "RX Failed with code %i\n", s);
s = LPUART_DRV_ReceiveData(INST_UART0, g_uart_rx_buf, 1);
debug_log_print(LL_INFO, MOD_UART, "RX Restarted with code %i\n", s);
}
uint8_t data = 0;
if(OS_MAILBOX_GetTimed1(&g_uart_rx_mb, (char*) &data, UART_RX_IDLE_TO) != 0)
continue;
Thanks,
Sai
Hi @VaneB
I see the major issue with LPUART_DRV_TxCompleteIrqHandler(instance); and LPUART_DRV_TxEmptyIrqHandler(instance);
1. Some times calling function LPUART_DRV_TxCompleteIrqHandler when txSize not equal to 0
2. Sometimes calling function LPUART_DRV_TxEmptyIrqHandler when txSize is equal to 0
The controller is hanging in the above scenarios. I did not get why it is happening.
I am working with embos RTOS. The sending done in one task and receiving done in other tasks and both tasks working parallel.
Do you think some synchronization problem with NXP os_if Semaphores and our RTOS scheduling(Embos)?
Can I also send and receive data in parallel tasks ? (Is this situation handled in SDK semaphore)
Best Regards,
Sai
I am afraid that S32K1 devices only support FreeRTOS, so I cannot say how the software will interact with EmbOS. Could you test the UART without using EmbOS and see if the same behavior is present?
Hi @VaneB
I also see strange behavior with controller.
1. The Status register showing setting Flags TC and TDRE.
2. IRQ handler calling LPUART_DRV_TxCompleteIrqHandler(instance);
3. But the transfer not Finished and see lpuartState->txSize not eual to 0 (It has value 18= 0x12)
4. The controller hanging and keep on calling the LPUART_DRV_TxEmptyIrqHandler
Attached screenshots for your reference.
Does the LPUART_DRV_SendDataBlocking function has any issues?
Why the controller generating interrupt without finishing the actual transmission?
How can I fix this issue?
Best Regards,
Sai
@ PetrS
HI @VaneB
Thank you very much for the information,
In general, it is working fine, But not working when need to send and receive bulk data. The ISR running continuously and hangs after some time.
The UART ISR completely blocked the controller and not allowing the task switching even the scheduler.
I also assigned lower priority(120) for the interrupt, still ISR running continuously.
Is it good to disable interrupt for every 100msec some thing like that?
One the ISR is blocked controller , I can not even disable the interrupt because no other tasks are running(attached the screenshots).
Best Regards,
Sai
There are 16 priority levels configurable in the 4 most significant bits in IRQn fields in NVIC IPRn registers. The lower the priority number is set, the higher the priority. So priority 0 is the highest priority level.
Preemption: An interrupt with a higher priority level preempts an interrupt with a lower priority level.
If multiple pending interrupts have the same priority, the pending interrupt with the lowest exception number is executed first.
Subpriority:
Priority grouping is configurable in the AIRCR[PRIGROUP] register (refer to Cortex -M4 Devices Generic User Guide, Chapter 4.3.5 Application Interrupt and Reset Control Register).
A number written to the PRIGROUP divides the IPRn[IRQn] into bits that configure the preemption and subpriorities.
Since the S32K14x implements only 16 priority levels, configurable in the 4 most significant bits of IRQn, the PRIGROUP must be set to a number greater or equal to 4.
Then, if PRIGROUP = 4, the IRQn[7-5] bits configure all preemptive interrupt levels and the IRQn[4] bit configures subpriority levels.
Regarding the available UART examples, we provide examples for both available software, Real-Time Drivers for S32K1 and S32 SDK for S32K1xx.
B.R.
VaneB
Hi @VaneB ,
Thank you very much the information.
I am not implementing my UART on register level so, I used S32K SDK. The SDK should fill the necessary registers in LPUART_DRV_Init.
My issue is the UART ISR is running so, fast and it is faster than Systick timer it self.
Is this because there is huge data it is receiving ? or configured it high priority?
LPUART_DRV_Init(INST_UART0, &uart0_State, &uart0_InitConfig0);
LPUART_DRV_InstallRxCallback(INST_UART0, uart_callback, NULL);
INT_SYS_SetPriority(s_lpuartRxTxIrqId[INST_UART0], 120);
Can I set IRQ priority after calling the UART Init ?
What is the number for lowest priority for UART ISR?
static void uart_callback(void *driver_state, uart_event_t event, void *user_data)
{
(void) driver_state;
(void) user_data;
if(event == UART_EVENT_RX_FULL){
OS_MAILBOX_Put1(&g_uart_rx_mb, (char*)g_uart_rx_buf);
LPUART_DRV_SetRxBuffer(INST_UART0, g_uart_rx_buf, 1);
}
}
typedef enum
{
UART_EVENT_RX_FULL = 0x00U, /*!< Rx buffer is full */
UART_EVENT_TX_EMPTY = 0x01U, /*!< Tx buffer is empty */
UART_EVENT_END_TRANSFER = 0x02U, /*!< The current transfer is ending */
UART_EVENT_ERROR = 0x03U, /*!< An error occured during transfer */
} uart_event_t;
The code is hanging when we get the UART_EVENT_ERROR in UART ISR. It keep on triggering and not giving time for other tasks.
Do I need to clear the UART_EVENT_ERROR in call back function or It will clear automatically?
I also attached Systemview screenshots while error occured.
Best Regards,
Sai
I recommend testing a simple example. Check the following thread.