Enabling UART on nRF9161 DK for application use?

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.

Parents
  • Hello,

    The error shows an invalid entry point. 

    This type of error can occur in TrustZone enables devices when there is an issue with secure/non-secure transitions. SECURE_UART1 is enabled by default when building TF-M on nRF9161 DK, so the secure firmware console output is available via USART1. You can try to set UART0 as non-secure (CONFIG_NRF_UARTE0_SECURE=n) as you are trying to run the non-secure application. Nordic nRF9161 

  • Since I want logs on UART0 (RTT is super finicky for me), in the sample I posted above, I added the following:

    CONFIG_UART_ASYNC_API=y
    CONFIG_NRF_UARTE1_SECURE=n
    CONFIG_TFM_SECURE_UART=n
    CONFIG_TFM_LOG_LEVEL_SILENCE=y

    I'm still getting the same error:

    [00:00:00.274,261] <err> os: ***** SECURE FAULT *****
    [00:00:00.280,059] <err> os: Invalid entry point
    [00:00:00.285,614] <err> os: r0/a1: 0x000465dc r1/a2: 0x2001c052 r2/a3: 0x00000064
    [00:00:00.294,403] <err> os: r3/a4: 0xffffffff r12/ip: 0x00000000 r14/lr: 0x0001a4e1
    [00:00:00.303,161] <err> os: xpsr: 0x00000000
    [00:00:00.308,471] <err> os: s[ 0]: 0x00000000 s[ 1]: 0x0003dfcb s[ 2]: 0x20012974 s[ 3]: 0x00000000
    [00:00:00.319,030] <err> os: s[ 4]: 0x00000000 s[ 5]: 0x00000000 s[ 6]: 0x00000000 s[ 7]: 0x0001b4c5
    [00:00:00.329,589] <err> os: s[ 8]: 0x00000001 s[ 9]: 0x00037619 s[10]: 0x00037619 s[11]: 0x20023d08
    [00:00:00.340,148] <err> os: s[12]: 0x00037619 s[13]: 0x0001d6e0 s[14]: 0x0001d6e0 s[15]: 0x0001d6e0
    [00:00:00.350,677] <err> os: fpscr: 0x0001d6e0
    [00:00:00.355,957] <err> os: Faulting instruction address (r15/pc): 0x00000000
    [00:00:00.363,952] <err> os: >>> ZEPHYR FATAL ERROR 38: Unknown error on CPU 0
    [00:00:00.371,948] <err> os: Current thread: 0x20011ec8 (unknown)
    [00:00:00.378,814] <err> os: Halting system

  • I managed to solve it. I had CONFIG_UART_INTERRUPT_DRIVEN=y set, which was conflicting with the async API I presume. After removing it, everything started working, along with the additions I mentioned above.

Reply Children
Related