From what I can see in the documentation, UART0 is used by default for "non-secure" / application logs and UART1 is used for "secure" app logs. I am needing to interface with another MCU using UART, but I'm having a hard time figuring out how to enable my non-secure portion of the app access this peripheral.
To start with, I disabled UART0 for app logging, switching to J-Link RTT:
CONFIG_SERIAL=y CONFIG_UART_ASYNC_API=y CONFIG_LOG_BACKEND_RTT=y CONFIG_USE_SEGGER_RTT=y CONFIG_RTT_CONSOLE=y CONFIG_LOG_BACKEND_RTT=y CONFIG_LOG_BACKEND_UART=n
With the above, I am able to use the J-Link RTT Viewer to view my app logs instead of the VCOM0 / UART for logs.
I then added the following to my device tree overlay:
&pinctrl { uart0_default: uart0_default { group1 { psels = <NRF_PSEL(UART_TX, 0, 27)>, <NRF_PSEL(UART_RTS, 0, 14)>; }; group2 { psels = <NRF_PSEL(UART_RX, 0, 26)>, <NRF_PSEL(UART_CTS, 0, 15)>; bias-pull-up; }; }; uart0_sleep: uart0_sleep { group1 { psels = <NRF_PSEL(UART_TX, 0, 27)>, <NRF_PSEL(UART_RX, 0, 26)>, <NRF_PSEL(UART_RTS, 0, 14)>, <NRF_PSEL(UART_CTS, 0, 15)>; low-power-enable; }; }; }; &uart0 { status = "okay"; current-speed = <115200>; pinctrl-0 = <&uart0_default>; pinctrl-1 = <&uart0_sleep>; pinctrl-names = "default", "sleep"; hw-flow-control; };
I am setting it up like so:
#define UART_DEV DEVICE_DT_GET(DT_NODELABEL(uart0)) static void uart_cb(const struct device *dev, struct uart_event *evt, void *user_data) { LOG_INF("GOT UART FRAME!"); switch (evt->type) { case UART_RX_RDY: // do stuff (truncated) break; case UART_RX_DISABLED: // RX buffer got full or RX stopped, re-enable to continue receiving uart_rx_enable(UART_DEV, rx_buf, sizeof(rx_buf), SYS_FOREVER_MS); break; case UART_RX_STOPPED: LOG_ERR("UART RX stopped unexpectedly!"); uart_rx_enable(UART_DEV, rx_buf, sizeof(rx_buf), SYS_FOREVER_MS); break; default: break; } } int uart_setup(void) { LOG_INF("Setting up UART..."); if (!device_is_ready(UART_DEV)) { LOG_ERR("Device not ready for UART"); return -1; } LOG_INF("Setting up UART callback..."); uart_callback_set(UART_DEV, uart_cb, NULL); LOG_INF("Enabling UART transmission..."); uart_rx_enable(UART_DEV, rx_buf, sizeof(rx_buf), SYS_FOREVER_MS); return 0; }
When that uart_rx_enable() function is called, I get a SECURE FAULT:
[00:00:09.517,822] <inf> testapp: Setting up UART... [00:00:09.518,188] <inf> testapp: Setting up UART callback... [00:00:09.518,554] <inf> testapp: Enabling UART transmission... [00:00:09.521,484] <err> os: ***** SECURE FAULT ***** [00:00:09.521,850] <err> os: Invalid entry point [00:00:09.522,216] <err> os: r0/a1: 0x00059638 r1/a2: 0x2001d333 r2/a3: 0x00000320 [00:00:09.522,796] <err> os: r3/a4: 0xffffffff r12/ip: 0x00000000 r14/lr: 0x0001e3d3 [00:00:09.523,315] <err> os: xpsr: 0x00000000 [00:00:09.523,712] <err> os: s[ 0]: 0x00000000 s[ 1]: 0x2002cc04 s[ 2]: 0x00000000 s[ 3]: 0x0004772b [00:00:09.524,444] <err> os: s[ 4]: 0x2002cc00 s[ 5]: 0x00000002 s[ 6]: 0x00000001 s[ 7]: 0x0002e0c9 [00:00:09.525,146] <err> os: s[ 8]: 0x00000010 s[ 9]: 0x00000000 s[10]: 0x2001ce90 s[11]: 0x0003fe03 [00:00:09.525,848] <err> os: s[12]: 0x0000002a s[13]: 0x00000020 s[14]: 0x00000000 s[15]: 0x00000000 [00:00:09.526,519] <err> os: fpscr: 0x00000000 [00:00:09.526,916] <err> os: Faulting instruction address (r15/pc): 0x00000000 [00:00:09.527,374] <err> os: >>> ZEPHYR FATAL ERROR 38: Unknown error on CPU 0 [00:00:09.527,862] <err> os: Current thread: 0x20013088 (unknown) [00:00:09.528,289] 31m<err> os: Halting system[0m
Any ideas? I am nearly at a point now where I'm about to just switch to I2C or something else between the two MCUs.