Switching board

Using ARM architecture

It is easy to switch to a new board in Zephyr. For example, instead of qemu_x86 which emulates a PC, we will emulate a Cortex-M3 based system using qemu_cortex_m3.

Recompile and run your application for the qemu_cortex_m3 board and check that everything still works as expected. If you run the command file build/zephyr/zephyr.elf, you should see that it is indeed an ARM application.

Using a real physical board

We will now use a IoT node board as we did in the SE203 class. This board has a number of sensors and effectors that can be useful in the future.

You can see the list of supported boards using west boards. The board we are interested in is the disco_l475_iot1. Compile your application for this board.

⚠️ If you use Telecom Paris computer lab, you must place the following directory at the beginning of your PATH: /comelec/softs/opt/Segger/JLink_current/. You should update your shell configuration file to do so each time you log in.

Our boards are configured to use Segger JLink tools. We can flash the program and reset the board by using:

$ west flash --runner jlink --reset

(if you don't use west, you can use ninja -C build flash provided that you set the BOARD_FLASH_RUNNER variable to jlink at cmake time, see this page for more information)

You can now connect to the /dev/ttyACM0 (for Linux, other systems do have equivalent names) and interact with the shell:

$ tio /dev/ttyACM0
(Zephyr) 

Note how Zephyr was able to use the serial port on your board without you telling it explicitly. In build/zephyr/zephyr.dts you will have access to the application device tree. The device tree describes the hardware and interacts with the right device drivers.

Note the following fragments:

/ {
        chosen {
                zephyr,console = &usart1;
                zephyr,shell-uart = &usart1;
        };

        soc {
                usart1: serial@40013800 {
                        compatible = "st,stm32-usart", "st,stm32-uart";
                        reg = < 0x40013800 0x400 >;
                        clocks = < &rcc 0x60 0x4000 >;
                        resets = < &rctl 0x80e >;
                        interrupts = < 0x25 0x0 >;
                        status = "okay";
                        current-speed = < 0x1c200 >;
                        pinctrl-0 = < &usart1_tx_pb6 &usart1_rx_pb7 >;
                        pinctrl-names = "default";
                };
        };
};

You can notice that the console (printf()) and the shell both opted to choose the device whose alias is usart1 (the serial port connected to the JLink compatible chip on the board, accessible under /dev/ttyACM0 or a similar name). Also, you can see how usart1 is defined and require the use of the st,stm32-usart and st,stm32-uart device drivers.

Using RTT for the shell instead of the UART

Since we use the Segger JLink tools, we can request the use of Segger RTT instead of a serial port for the shell. By adding the following line to prj.conf you can indicate that the shell must use a RTT interface instead of a shell:

CONFIG_USE_SEGGER_RTT=y
CONFIG_SHELL_PROMPT_RTT="(Zephyr) "
CONFIG_SHELL_BACKEND_SERIAL=n
CONFIG_SHELL_BACKEND_RTT=y

You will get a warning about the now unused CONFIG_SHELL_PROMPT_UART: this is due to the fact that the serial backend for the shell is no longer used.

Flash and run the application on the board. You should notice that only the "Hello, world!" arrives through the serial port when you reset the board. Launch JLink RTT logger after flashing the board:

$ JLinkRTTLogger -device STM32L475VG -RTTChannel 1 -if SWD -Speed 4000

and connect to port 19021 using nc:

$ nc localhost 19021

You can now type command in the nc window and interact with the shell.

Now revert your changes as we will keep the shell on the serial port for now.