Step 5 : Shell on Zephyr with QEMU

  • In this program, you are going to learn

  • What configurations needs to be added to enable shell?

  • How to do pre-build and post-build checks ?

  • How to execute commands on Zephyr shell?

  • How to add our own commands to execute in shell?

  • Add the following configurations in prj.conf to enable the shell on Zephyr build.

(.venv) test:zephyr$ pwd
$HOME/zephyrproject/zephyr
(.venv) test:zephyr$ vi samples/hello_world/prj.conf
CONFIG_SHELL=y
CONFIG_SHELL_BACKEND_SERIAL=y
CONFIG_SHELL_HISTORY=y
CONFIG_SHELL_CMDS_RESIZE=y
  • In this section we will see how to do pre-build checks.

  • Check whether the configurations required to enable shell for zephyr is added or not in prj.conf

CONFIG_SHELL=y
CONFIG_SHELL_BACKEND_SERIAL=y
CONFIG_SHELL_HISTORY=y
CONFIG_SHELL_CMDS_RESIZE=y
  • Check for the location of location in zephyr-sdk-0.16.4 directory

(.venv) test:zephyr$ ls -l $HOME/zephyr-sdk-0.16.4/aarch64-zephyr-elf/aarch64-zephyr-elf/bin/
total 17000
-rwxr-xr-x 2 test test 1357336 Nov 15 16:40 ar
-rwxr-xr-x 2 test test 2500544 Nov 15 16:40 as
-rwxr-xr-x 4 test test 2019136 Nov 15 16:40 ld
-rwxr-xr-x 4 test test 2019136 Nov 15 16:40 ld.bfd
-rwxr-xr-x 2 test test 1346128 Nov 15 16:40 nm
-rwxr-xr-x 2 test test 1467888 Nov 15 16:40 objcopy
-rwxr-xr-x 2 test test 2876656 Nov 15 16:40 objdump
-rwxr-xr-x 2 test test 1357368 Nov 15 16:40 ranlib
-rwxr-xr-x 2 test test  977144 Nov 15 16:40 readelf
-rwxr-xr-x 2 test test 1467888 Nov 15 16:40 strip
  • run west build command to build the application.

(.venv) test:zephyr$ pwd
$HOME/zephyrproject/zephyr


(.venv) test:zephyr$ west build -b qemu_x86 samples/hello_world
[1/125] Preparing syscall dependency handling

[3/125] Generating include/generated/version.h
-- Zephyr version: 3.5.99 (/home/test/zephyr_with_qemu/zephyrproject/zephyr), build: zephyr-v3.5.0-4596-g8556ae5afece
[124/125] Linking C executable zephyr/zephyr.elf
Memory region         Used Size  Region Size  %age Used
      RAM:            143392 B     31 MB      0.44%
      IDT_LIST:       0 GB         2 KB       0.00%
Generating files from /home/test/zephyr_with_qemu/zephyrproject/zephyr/build/zephyr/zephyr.elf for board: qemu_x86
[125/125] cd /home/test/zephyr_with_qemu/zephyrproject/zephyr/build/zephyr && /home/test/zephyr_with...it_priorities.py --elf-file=/home/test/zephyr_with_qemu/zephyrproject/zephyr/build/zephyr/zephyr.elf
  • In this section we will see how to do post-build checks

  • Here we will see how to do static post build checks

  • Lets check for the location of the final application target image to make sure the build is completed successfully without any errors.

(.venv) test:zephyr$ ls -l build/zep build/zephyr/
-rw-rw-r-- 1 test test    4178 Jan 23 17:02 zephyr.dts
-rw-rw-r-- 1 test test     597 Jan 23 17:06 zephyr.dts.d
-rw-rw-r-- 1 test test    5767 Jan 23 17:06 zephyr.dts.pre
-rwxrwxr-x 1 test test 1009028 Jan 24 11:59 zephyr.elf
-rw-rw-r-- 1 test test  308505 Jan 24 11:59 zephyr_final.map
-rw-rw-r-- 1 test test  308505 Jan 24 11:59 zephyr.map
-rwxrwxr-x 1 test test 1009096 Jan 24 11:59 zephyr_pre0.elf
-rw-rw-r-- 1 test test  310164 Jan 24 11:59 zephyr_pre0.map
-rw-rw-r-- 1 test test    3930 Jan 24 11:59 zephyr.stat
  • Here we will see how to do runtime post-build checks

  • Run the image using the west command.

(.venv) test:zephyr$ west build -t run
-- west build: running target run
[0/1] To exit from QEMU enter: CTRL+a, x[QEMU] CPU: qemu32,+nx,+pae
SeaBIOS (version zephyr-v1.0.0-0-g31d4e0e-dirty-20200714_234759-fv-az50-zephyr)
Booting from ROM..
  • We can confirm the application is successfully loaded without any errors if the prompt is displayed on the virtual environment.

uart:~$
  • In this section, we will see about zephyr shell commands in detail.

  • “cycles” subcommand is used to give information about the kernel cycles.

uart:~$ kernel cycles
cycles: 976922951 hw cycles
  • “stacks” subcommand is used to list the thread stack usage.

uart:~$ kernel stacks
0x1177c0 sysworkq                         (real size 1024):     unused  688     usage  336 / 1024 (32 %)
0x10d000 shell_uart                       (real size 2048):     unused  896     usage 1152 / 2048 (56 %)
0x10d540 idle                             (real size  320):     unused  184     usage  136 /  320 (42 %)
0x11c358 IRQ 00                           (real size 2048):     unused 1624     usage  424 / 2048 (20 %)
  • “threads” subcommand is used to list kernel threads along with various information like priority, state and stack size.

uart:~$ kernel threads
Scheduler: 806822 since last call
Threads:
 0x1177c0 sysworkq
        options: 0x0, priority: -1 timeout: 0
        state: pending, entry: 0x109091
        stack size 1024, unused 688, usage 336 / 1024 (32 %)

*0x10d000 shell_uart
        options: 0x0, priority: 14 timeout: 0
        state: queued, entry: 0x1035fd
        stack size 2048, unused 896, usage 1152 / 2048 (56 %)

 0x10d540 idle
        options: 0x1, priority: 15 timeout: 0
        state: , entry: 0x10838c
        stack size 320, unused 184, usage 136 / 320 (42 %)
  • “list” subcommand is used to list the configured devices.

uart:~$ device list
devices:
- ioapicfec00000 (READY)
- loapicfee00000 (READY)
- uart2f8 (READY)
- uart3f8 (READY)






  • In this section we will see how to see our own command in zephyr shell.

  • Add the following instructions in main.c

(.venv) test:zephyr$ pwd
$HOME/zephyrproject/zephyr
(.venv) test:zephyr$ vi samples/hello_world/src/main.c
#include <zephyr/kernel.h>
#include <zephyr/shell/shell.h>

static int hello_cmd_handler(const struct shell *shell, size_t argc, char **argv)
{
    ARG_UNUSED(argc);
    ARG_UNUSED(argv);

    shell_print(shell, "Hello, World!");
    return 0;
}

SHELL_CMD_REGISTER(hello, NULL, "Prints 'Hello, World!'", hello_cmd_handler);
static int hello_cmd_handler(const struct shell *shell, size_t argc, char **argv)
{
        ARG_UNUSED(argc);
        ARG_UNUSED(argv);

        shell_print(shell, "Hello, World!");
        return 0;
}
  • This defines a function named hello_cmd_handler, which will be the handler for the custom shell command.

  • The function does not use the argc and argv parameters, so “ARG_UNUSED(argc)” and “ARG_UNUSED(argv)” are used to avoid compiler warnings about unused parameters.

  • “shell_print” is used to print the “Hello, World!” message to the shell.

SHELL_CMD_REGISTER(hello, NULL, "Prints 'Hello, World!'", hello_cmd_handler);
  • This line registers the hello command with the Zephyr shell.

  • The SHELL_CMD_REGISTER macro takes four parameters:

    • hello: The name of the command. Users will type this command in the shell.

    • NULL: The subcommands. In this case, there are no subcommands, so it’s set to NULL.

    • “Prints ‘Hello, World!’”: A description of the command, which will be displayed when users type help in the shell.

    • hello_cmd_handler: The function that will handle the command.

  • run west build to build the application.

(.venv) test:zephyr$ west build -b qemu_x86 samples/hello_world


-- west build: generating a build system
Loading Zephyr default modules (Zephyr base).
-- Application: /home/test/zephyr_with_qemu/zephyrproject/zephyr/samples/hello_world
-- CMake version: 3.24.2
-- Found Python3: /home/test/zephyr_with_qemu/zephyrproject/.venv/bin/python3 (found suitable version "3.10.7", minimum required is "3.8") found components: Interpreter
-- Cache files will be written to: /home/test/.cache/zephyr
-- Zephyr version: 3.5.99 (/home/test/zephyr_with_qemu/zephyrproject/zephyr)
-- Found west (found suitable version "1.2.0", minimum required is "0.14.0")
-- Board: qemu_x86
-- ZEPHYR_TOOLCHAIN_VARIANT not set, trying to locate Zephyr SDK
-- Found host-tools: zephyr 0.16.4 (/home/test/double_thread_zephyr_build/zephyr-sdk-0.16.4)
-- Found toolchain: zephyr 0.16.4 (/home/test/double_thread_zephyr_build/zephyr-sdk-0.16.4)
-- Found Dtc: /home/test/double_thread_zephyr_build/zephyr-sdk-0.16.4/sysroots/x86_64-pokysdk-linux/usr/bin/dtc (found suitable version "1.6.0", minimum required is "1.4.6")
-- Found BOARD.dts: /home/test/zephyr_with_qemu/zephyrproject/zephyr/boards/x86/qemu_x86/qemu_x86.dts
-- Generated zephyr.dts: /home/test/zephyr_with_qemu/zephyrproject/zephyr/build/zephyr/zephyr.dts
-- Generated devicetree_generated.h: /home/test/zephyr_with_qemu/zephyrproject/zephyr/build/zephyr/include/generated/devicetree_generated.h
-- Including generated dts.cmake file: /home/test/zephyr_with_qemu/zephyrproject/zephyr/build/zephyr/dts.cmake
Parsing /home/test/zephyr_with_qemu/zephyrproject/zephyr/Kconfig
Loaded configuration /home/test/zephyr_with_qemu/zephyrproject/zephyr/boards/x86/qemu_x86/qemu_x86_defconfig
Merged configuration /home/test/zephyr_with_qemu/zephyrproject/zephyr/samples/hello_world/prj.conf
Configuration saved to /home/test/zephyr_with_qemu/zephyrproject/zephyr/build/zephyr/.config
Kconfig header saved to /home/test/zephyr_with_qemu/zephyrproject/zephyr/build/zephyr/include/generated/autoconf.h
-- Found GnuLd: /home/test/double_thread_zephyr_build/zephyr-sdk-0.16.4/x86_64-zephyr-elf/bin/../lib/gcc/x86_64-zephyr-elf/12.2.0/../../../../x86_64-zephyr-elf/bin/ld.bfd (found version "2.38")
-- The C compiler identification is GNU 12.2.0
-- The CXX compiler identification is GNU 12.2.0
-- The ASM compiler identification is GNU
-- Found assembler: /home/test/double_thread_zephyr_build/zephyr-sdk-0.16.4/x86_64-zephyr-elf/bin/x86_64-zephyr-elf-gcc
CMake Warning at /home/test/zephyr_with_qemu/zephyrproject/zephyr/subsys/random/CMakeLists.txt:12 (message):


      Warning: CONFIG_TIMER_RANDOM_GENERATOR is not a truly random generator.
      This capability is not secure and it is provided for testing purposes only.
      Use it carefully.


-- Using ccache: /usr/bin/ccache
-- Configuring done
-- Generating done
-- Build files have been written to: /home/test/zephyr_with_qemu/zephyrproject/zephyr/build
-- west build: building application
[1/125] Preparing syscall dependency handling

[3/125] Generating include/generated/version.h
-- Zephyr version: 3.5.99 (/home/test/zephyr_with_qemu/zephyrproject/zephyr), build: zephyr-v3.5.0-4596-g8556ae5afece
[124/125] Linking C executable zephyr/zephyr.elf
Memory region         Used Size  Region Size  %age Used
             RAM:      143392 B        31 MB      0.44%
        IDT_LIST:          0 GB         2 KB      0.00%
Generating files from /home/test/zephyr_with_qemu/zephyrproject/zephyr/build/zephyr/zephyr.elf for board: qemu_x86
[125/125] cd /home/test/zephyr_with_qemu/zephyrproject/zephyr/build/zephyr && /home/test/zephyr_with...it_priorities.py --elf-file=/home/test/zephyr_with_qemu/zephyrproject/zephyr/build/zephyr/zephyr.elf
  • run “west” command to run the application.

(.venv) wifi:zephyr$ west build -t run
-- west build: running target run
[0/1] To exit from QEMU enter: CTRL+a, x[QEMU] CPU: qemu32,+nx,+pae
SeaBIOS (version zephyr-v1.0.0-0-g31d4e0e-dirty-20200714_234759-fv-az50-zephyr)
Booting from ROM..
*** Booting Zephyr OS build zephyr-v3.5.0-4596-g8556ae5afece ***

uart:~$
  • run “hello” to execute our own zephyr shell command.

uart:~$ hello
Hello, World!