I know this is an incredibly long questions but ive posted as much detail so I can give the most context and hopefully make it easier to answer.
I am currently creating a program to receive messages via UART from another device and then it should read and analyze the received message. I have the read and analyze functions working properly, but right now when I am trying to implement UART Rx interrupts I am having trouble calling other functions within the interrupt handler. It gives me the below error. I can build and flash with no errors, but as soon as the first message is received it throws back this :
Guru Meditation Error: Core 0 panic'ed (LoadProhibited). Exception was unhandled.
Core 0 register dump:
PC : 0x402133a2 PS : 0x00000033 A0 : 0x4021cb8c A1 : 0x3ffe8220
A2 : 0x00000000 A3 : 0x3ffe92fc A4 : 0x4021339c A5 : 0x00000003
A6 : 0x00000000 A7 : 0x00000000 A8 : 0x00000000 A9 : 0x00000000
A10 : 0x00000000 A11 : 0x00000000 A12 : 0x00000000 A13 : 0x00000020
A14 : 0x00000020 A15 : 0x3ffe8c0c SAR : 0x0000001b EXCCAUSE: 0x0000001c
Backtrace: 0x402133a2:0x3ffe8220 0x4021cb8c:0x3ffe8230 0x40100552:0x3ffe8240 0x40100a7c:0x3ffe8260
For context I am using Espressif's RTOS SDK to code onto an ESP8266 NodeMCU. Ive tried numerous ways to implement the handler function (the only way that worked was by changing a global volatile variable *1, but that brings up other problems which I will explain below), but most are to no avail. I know generally you're not supposed to create other static variables or call blocking functions within the handler, but within the source code for RTOS SDK line520 I I found what looked to be the default UART Rx handler the driver comes with and it uses a lot of things which I tried to mimic *2:
// internal isr handler for default driver code. (line 520)
uart_obj_t *p_uart = (uart_obj_t *) param;
uint8_t uart_num = p_uart->uart_num;
uart_dev_t *uart_reg = UART[uart_num];
int rx_fifo_len = uart_reg->status.rxfifo_cnt;
uint8_t buf_idx = 0;
uint32_t uart_intr_status = UART[uart_num]->int_st.val;
uart_event_t uart_event;
BaseType_t task_woken = 0;
while (uart_intr_status != 0x0) { //if an interrupt is trigger
/// many lines later .... (line 636) ///
//checks it the RX Timeout or Rx Buffer Filled interrupt are triggered
} else if ((uart_intr_status & UART_RXFIFO_TOUT_INT_ST_M)
|| (uart_intr_status & UART_RXFIFO_FULL_INT_ST_M)
) {
rx_fifo_len = uart_reg->status.rxfifo_cnt; //stores the length of buffered data
if (p_uart->rx_buffer_full_flg == false) {
// We have to read out all data in RX FIFO to clear the interrupt signal
while (buf_idx < rx_fifo_len) {
p_uart->rx_data_buf[buf_idx++] = uart_reg->fifo.rw_byte;
}
// Get the buffer from the FIFO
// After Copying the Data From FIFO ,Clear intr_status
uart_clear_intr_status(uart_num, UART_RXFIFO_TOUT_INT_CLR_M | UART_RXFIFO_FULL_INT_CLR_M);
uart_event.type = UART_DATA;
uart_event.size = rx_fifo_len;
p_uart->rx_stash_len = rx_fifo_len;
First I will paste my UART Rx Interrupt configuration settings :
/// UART Interrupt Configurations ///
uart_intr_config_t uartConfig = {
.intr_enable_mask = UART_RXFIFO_TOUT_INT_ENA,//which interrupts to enable
.rx_timeout_thresh = 1, //how much time to wait to trigger after last byte has been sent to Rx
.txfifo_empty_intr_thresh = 1, //How many bytes in Tx buffer to be left
.rxfifo_full_thresh = 10, //How many bytes within Rx buffer before interrupt is called
};
uart_intr_config(UART_NUM_0, &uartConfig); //configures UART interrupt using the above mask and paramaters
uart_isr_register(UART_NUM_0, uart_intr_handle, NULL); //registers which function to call
1* When creating a volatile int variable and then changing the value within the handler function it seemed to work without any errors. I would be fine using this method but a problem with using UART Rx interrupts with RTOS SDK is that to clear the interrupt mask I need to read the function. Unfortunately I cannot read the function using the uart_read_bytes() function because that results in an error. If I flush the input buffer within the interrupt handler, then when I try to read the buffer inside the main or wherever else I read I presume there wont be anything to read after the flush which is why I dont want to use this volatile flag method. uart_flush_input() and uart_clear_intr_status() function given by RTOS SDK seem to work, but not other functions which make me even more confused.
void uart_intr_handle(void *arg){
//changes flag value. Inside main a loop will check change it to 0 if it is 1
flag = 1;
uart_flush_input(UART_NUM_0); //I need to flush because I cant use any function to read
//clear the bits
uart_clear_intr_status(UART_NUM_0, UART_RXFIFO_TOUT_INT_CLR );
}
*2 Instead of relying on the functions seen in the RTOS SDK API guide I decided to try and copy the way they do it in the source code. I didnt get all the way through, but even with the small amount of code I have so far, I am able to build and flash and then once again when the first message is received it throws back the guru mediation error.
void uart_intr_handle(void *arg){
//first we create the defintions we use
uart_obj_t *p_uart = (uart_obj_t *) arg; //uart_obj_t is a struct which holds lots of info
uint8_t uart_num = p_uart->uart_num; //holds which uart is being used
uart_dev_t *uart_reg = UART[uart_num]; //idk
int rx_fifo_len = uart_reg->status.rxfifo_cnt; //holds the length of data in the rx buffer
uint8_t buf_idx = 0; //will indicate the buffer index value when populating the reference buffer
uint32_t uart_intr_status = UART[uart_num]->int_st.val; //holds the intr status mask
uart_event_t uart_event; //maybe I can delete this
BaseType_t task_woken = 0; //prob I can delete this too
//Havent implemented the second part yet
uart_flush_input(UART_NUM_0);
uart_clear_intr_status(UART_NUM_0, UART_RXFIFO_TOUT_INT_CLR );
}
Any help and insights you may have are greatly appreciated
argis a copy of the pointer passed touart_isr_register()but you have not shown that. Seems likely to me that pointer is invalid or does not point to validuart_obj_t.rxfifo_full_thresh = 10, //How many bytes within Rx buffer before interrupt is calledWhat happens if you get a message shorter than 10 bytes? Wait forever?rx_timeout_thresh=1deals with that. After a one character break, the interrupt occurs regardless of FIFO threshold.