Illegal use of the EPSR - uart fault

Hi, 

i have some code thats based off of the uart_async_adapter.c example code. I'm getting a `usage fault` which i've traced to uart_irq_handler. it happens when i try to send a single byte 7F over the uart. 

the strange thing is that after that fault it resets then it always works the second time. 

uart_async_adapter.c:  irq_handler

static void uart_irq_handler(const struct device *target_dev, void *context)
{
	const struct device *dev = context;
	struct uart_async_adapter_data *data = access_dev_data(dev);

	__ASSERT(target_dev == data->target,
		"IRQ handler called with a context that seems uninitialized.");
	LOG_DBG("irq_handler: Enter");
	if (uart_irq_update(target_dev) && uart_irq_is_pending(target_dev)) {
		if (data->tx.enabled && uart_irq_tx_ready(target_dev)) {
			on_tx_ready(dev, data);
		}
		if (data->tx.enabled && uart_irq_tx_complete(target_dev)) {
			on_tx_complete(dev, data);
		}
		if (data->rx.enabled && uart_irq_rx_ready(target_dev)) {
			on_rx_ready(dev, data);
		}

		/* Check errors only after all the data is received from the device */
		int rx_err = uart_err_check(target_dev);

		if (rx_err < 0) {
			rx_err = 0;
		}
		if (data->rx.enabled && rx_err) {
			on_error(dev, data, rx_err);
		}
	}
	LOG_DBG("irq_handler: Exit");
}

i get the "Notification: UART_RX_BUF_RELEASED" in the switch_rx_buffer() function, just before the crash. 

- uart_irq_handler
   - on_rx_ready(dev, data)
      - switch_rx_buffer(dev, true)
          - notify_rx_buffer_req(dev)

RTT Log:

D: tx(async_adapter, 0x2000b2dc, 1, -1)
D: tx: sending
D: irq_handler: Enter
D: on_tx_ready: Enter(async_adapter) (left: 1)
D: Pushed 1 characters
D: on_tx_ready: Exit
D: on_error: Enter(async_adapter) 12
D: Notification: UART_RX_BUF_RELEASED
E: ***** USAGE FAULT *****
E:   Illegal use of the EPSR
E: r0/a1:  0x0003b348  r1/a2:  0x20009cd4  r2/a3:  0x00030102
E: r3/a4:  0x0000e100 r12/ip:  0x200053cc r14/lr:  0x0002174f
E:  xpsr:  0x60000012
E: Faulting instruction address (r15/pc): 0x0000e100
E: >>> ZEPHYR FATAL ERROR 35: Unknown error on CPU 0
E: Fault during interrupt handling

I modified the log_dbg message in the on_error() function to include the rx_err code, which is `12`.  i think this means UART_ERROR_FRAMING & UART_BREAK

not sure if its because the other end of the uart (another mcu) is being configured to enable its uart, before sending the data, and so causing some noise.  is there a way to basically clear any pending interrupts and rx buffer in the nrf device? 

sorry hope that makes some sense, i can provide more details if needed. 

many thanks,

michael.

Parents
  • Hi,

    The driver handles clearing of interrupts etc, and there is no high level API for that nor should it be neeeded. It would be good to understand a bit more about this issue first.

    You write that you try to send a byte over UART, do then mean to the nRF, so that it is receiving? I ask just to confirm, as a framing error or break error would be related to reception/input and that match the other informaiton here. Also, can you elaborate more on what you do and the configuration? Are you using flow control? If not, does flow control help?

    PS: Sometimes it can be a problem with UART fi you have a inaccurate HF clock, so it could be worth enabling the HFXO and seeing if that makes a difference (as mentionned here).

  • Hi Einar,

    Thanks for the reply and apologies for the delay replying.


    For the single byte, no i mean from the nRF to the other MCU.  this is the basic structure: 

    | TABLET |<----- ble ----->| nRF MCU |<----- uart & spi ----->| ST MCU |


    Normally the ST and the nRF are communicating via spi, but for bootloading the ST uses a specific uart.  So we send a special cmd to restart into it bootloader, which then looks for an initial byte on its uart.  Then the nrf can do the bootloading over uart.

    The issue seems to be that I've configured any unused pins to input high-z on the ST (including the uart tx pin). so when the ST resets itself to bootloader, this flicks that TX pin to output causing noise on the line which is picked up as the error.

    I got a fix which was to make sure the ST has its uart TX pin always set to output high in normal application mode, which has solved it. but would still be nice to know why the nRF cant handle that error gracefully and continue.

    will look into the HFXO as well.

    cheers!

  • Hi,

    Thank you for the epxlanation.

    michaelmac said:
    I got a fix which was to make sure the ST has its uart TX pin always set to output high in normal application mode

    I see. This could make sense. The error you described in the initial post are related to UART Rx only, and is what you would see if there is an invalid UART character received (framing error). So if the nRF is receiving and the Tx pin from the other MCU is not driven, this means that the Rx pin is floating, and this is expected. Solving this by making sure the ST sets it's Tx pin high when idle is the appropriate fix.

    michaelmac said:
    but would still be nice to know why the nRF cant handle that error gracefully and continue.

    Yes, I am suprised that you get a fault at this point, as you should normally be able to recover from a UART error. I would start by checking the Faulting instruction address (PC) from the error with addr2line to see where in your code this is? Can you learn anything else from debugging? What does the stack trace look like?

Reply
  • Hi,

    Thank you for the epxlanation.

    michaelmac said:
    I got a fix which was to make sure the ST has its uart TX pin always set to output high in normal application mode

    I see. This could make sense. The error you described in the initial post are related to UART Rx only, and is what you would see if there is an invalid UART character received (framing error). So if the nRF is receiving and the Tx pin from the other MCU is not driven, this means that the Rx pin is floating, and this is expected. Solving this by making sure the ST sets it's Tx pin high when idle is the appropriate fix.

    michaelmac said:
    but would still be nice to know why the nRF cant handle that error gracefully and continue.

    Yes, I am suprised that you get a fault at this point, as you should normally be able to recover from a UART error. I would start by checking the Faulting instruction address (PC) from the error with addr2line to see where in your code this is? Can you learn anything else from debugging? What does the stack trace look like?

Children
No Data
Related