On-demand start of uart shell and dynamic pin control.

Hi!

We have three different uart applications (two for production use, and the uart shell backend) and three different hardware output paths, but nRF52840 features just two uart controllers. So we would like to be able to pick any two out of the three applications, and run them on the two controllers using dynamic pin control. We would like to be able to do so dynamically during boot.

So far I can re-route our uarts using the pinctrl_update_states and pinctrl_apply_states.

A problem comes with the uart shell, as we need to dynamically either start it or not, where by not starting I mean to not make it even claim the uart controller.

The minimum config that allows me to compile seems to be:
```
CONFIG_SHELL=y
CONFIG_SHELL_AUTOSTART=n
CONFIG_SHELL_BACKEND_SERIAL=y
CONFIG_UART_CONSOLE=n
```

Now when I set `CONFIG_SHELL_BACKEND_SERIAL=y` and reassign the pins using the pinctrl_* functions then: 

-  I can start the shell on demand with `shell_start(shell_backend_uart_get_ptr());`
-  but when I hook a logic analyzer, I don't see any traffic on the line where I had redirected the production app traffic to. This line and controller is also specified as the dts "chosen" zephyr,shell-uart. 

When I set `CONFIG_SHELL_BACKEND_SERIAL=n` and remove all code that relies on it:

-  then redirecting the traffic to the other set of lines works fine - I see there the traffic using a logic analyzer
-  but I loose the ability to start the shell on uart, since `shell_backend_uart_get_ptr()` is not compiled in without CONFIG_SHELL_BACKEND_SERIAL

I assume that it is because while the shell didn't autostart, the shell backend was automatically initialized at startup and claimed the pins.

How do we compile zephyr in such way that uart shell support is compiled in, but doesn't claim any controller unless told to?

Thanks!
Karel

Parents
  • Well, it seems that the trouble is incompatibility of the interrupt uart driver (that is default for uart shell) with the async uart driver (that is used by our app). 
    When I enable: 
    ```
    CONFIG_UART_0_ASYNC=y
    CONFIG_UART_0_INTERRUPT_DRIVEN=n
    ```
    the uart application starts magically working even despite CONFIG_SHELL_BACKEND_SERIAL=y. Of course at this point shell doesn't work when enabled instead of our app.

    It looks like a solution might be adding:
    ```
    CONFIG_SHELL_BACKEND_SERIAL_API_ASYNC=y
    ```
    Current state of affairs: an attempt to call to pm_device_action_run(&uart0, PM_DEVICE_ACTION_RESUME) results in a crash.

    I will continue digging.

  • It sounds like you have made good progress. Regarding the crash, do you have logging over UART (another instance) or RTT so you can get a crashlog?

  • Not at the moment. The changes have broken both our logging backends. Will dig later. Just wanted to let you know about the progress so that you don't burn time on it ;-). 

  • Crashlog is here

    ```
    ASSERTION FAIL @ WEST_TOPDIR/zephyr/drivers/serial/uart_nrfx_uarte.c:2124
    [00:00:07.173,767] <err> os: r0/a1:  0x00000004  r1/a2:  0x0000084c  r2/a3:  0x20012030
    [00:00:07.173,797] <err> os: r3/a4:  0x00000004 r12/ip:  0x2000f568 r14/lr:  0x00066dcf
    [00:00:07.173,797] <err> os:  xpsr:  0x01000000
    [00:00:07.173,828] <err> os: r4/v1:  0x40002000  r5/v2:  0x000823fc  r6/v3:  0x00088308
    [00:00:07.173,858] <err> os: r7/v4:  0x20002f70  r8/v5:  0x00000000  r9/v6:  0x00000000
    [00:00:07.173,858] <err> os: r10/v7: 0x00000000  r11/v8: 0x00000000    psp:  0x200376b8
    [00:00:07.173,889] <err> os: EXC_RETURN: 0x0
    [00:00:07.173,889] <err> os: Faulting instruction address (r15/pc): 0x000781e0
    [00:00:07.173,919] <err> os: >>> ZEPHYR FATAL ERROR 4: Kernel panic on CPU 0
    [00:00:07.173,980] <err> os: Current thread: 0x20012030 (main)
    ```

    Or: 

    ```
    static void uarte_pm_suspend(const struct device *dev)
    {
        NRF_UARTE_Type *uarte = get_uarte_instance(dev);
        const struct uarte_nrfx_config *cfg = dev->config;
        struct uarte_nrfx_data *data = dev->data;

        (void)data;
    #ifdef UARTE_ANY_ASYNC
        if (data->async) {
            /* Entering inactive state requires device to be no
             * active asynchronous calls.
             */
            __ASSERT_NO_MSG(!data->async->rx.enabled); // <- here
    ```

    I am not explicitly enabling uart anywhere before this call site (not that I know of anyways).

    The related configs that come to mind are:

    ```
    CONFIG_CONSOLE=y
    CONFIG_UART_CONSOLE=y

    CONFIG_SERIAL=y
    CONFIG_SHELL=y
    CONFIG_SHELL_BACKEND_SERIAL=y
    CONFIG_SHELL_AUTOSTART=n

    # Also tried without success, while also commenting out the zephyr,console in the dts chosen section:
    #CONFIG_UART_CONSOLE=n 
    #CONFIG_CONSOLE=n
    ```

    Any ideas?

Reply
  • Crashlog is here

    ```
    ASSERTION FAIL @ WEST_TOPDIR/zephyr/drivers/serial/uart_nrfx_uarte.c:2124
    [00:00:07.173,767] <err> os: r0/a1:  0x00000004  r1/a2:  0x0000084c  r2/a3:  0x20012030
    [00:00:07.173,797] <err> os: r3/a4:  0x00000004 r12/ip:  0x2000f568 r14/lr:  0x00066dcf
    [00:00:07.173,797] <err> os:  xpsr:  0x01000000
    [00:00:07.173,828] <err> os: r4/v1:  0x40002000  r5/v2:  0x000823fc  r6/v3:  0x00088308
    [00:00:07.173,858] <err> os: r7/v4:  0x20002f70  r8/v5:  0x00000000  r9/v6:  0x00000000
    [00:00:07.173,858] <err> os: r10/v7: 0x00000000  r11/v8: 0x00000000    psp:  0x200376b8
    [00:00:07.173,889] <err> os: EXC_RETURN: 0x0
    [00:00:07.173,889] <err> os: Faulting instruction address (r15/pc): 0x000781e0
    [00:00:07.173,919] <err> os: >>> ZEPHYR FATAL ERROR 4: Kernel panic on CPU 0
    [00:00:07.173,980] <err> os: Current thread: 0x20012030 (main)
    ```

    Or: 

    ```
    static void uarte_pm_suspend(const struct device *dev)
    {
        NRF_UARTE_Type *uarte = get_uarte_instance(dev);
        const struct uarte_nrfx_config *cfg = dev->config;
        struct uarte_nrfx_data *data = dev->data;

        (void)data;
    #ifdef UARTE_ANY_ASYNC
        if (data->async) {
            /* Entering inactive state requires device to be no
             * active asynchronous calls.
             */
            __ASSERT_NO_MSG(!data->async->rx.enabled); // <- here
    ```

    I am not explicitly enabling uart anywhere before this call site (not that I know of anyways).

    The related configs that come to mind are:

    ```
    CONFIG_CONSOLE=y
    CONFIG_UART_CONSOLE=y

    CONFIG_SERIAL=y
    CONFIG_SHELL=y
    CONFIG_SHELL_BACKEND_SERIAL=y
    CONFIG_SHELL_AUTOSTART=n

    # Also tried without success, while also commenting out the zephyr,console in the dts chosen section:
    #CONFIG_UART_CONSOLE=n 
    #CONFIG_CONSOLE=n
    ```

    Any ideas?

Children
Related