Feature : Shell
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?
Topics in this section,
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 rpi4b samples/hello_world/
-- west build: making build dir /home/wifi/zephyr_with_rpi4/zephyrproject/zephyr/build pristine
-- west build: generating a build system
Loading Zephyr default modules (Zephyr base).
-- Application: /home/wifi/zephyr_with_rpi4/zephyrproject/zephyr/samples/hello_world
-- CMake version: 3.24.2
-- Found Python3: /home/wifi/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/wifi/.cache/zephyr
-- Zephyr version: 3.6.0-rc2 (/home/wifi/zephyr_with_rpi4/zephyrproject/zephyr)
-- Found west (found suitable version "1.2.0", minimum required is "0.14.0")
-- Board: rpi_4b
-- ZEPHYR_TOOLCHAIN_VARIANT not set, trying to locate Zephyr SDK
-- Found host-tools: zephyr 0.16.4 (/home/wifi/double_thread_zephyr_build/zephyr-sdk-0.16.4)
-- Found toolchain: zephyr 0.16.4 (/home/wifi/double_thread_zephyr_build/zephyr-sdk-0.16.4)
-- Found Dtc: /home/wifi/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/wifi/zephyr_with_rpi4/zephyrproject/zephyr/boards/arm64/rpi_4b/rpi_4b.dts
-- Generated zephyr.dts: /home/wifi/zephyr_with_rpi4/zephyrproject/zephyr/build/zephyr/zephyr.dts
-- Generated devicetree_generated.h: /home/wifi/zephyr_with_rpi4/zephyrproject/zephyr/build/zephyr/include/generated/devicetree_generated.h
-- Including generated dts.cmake file: /home/wifi/zephyr_with_rpi4/zephyrproject/zephyr/build/zephyr/dts.cmake
Parsing /home/wifi/zephyr_with_rpi4/zephyrproject/zephyr/Kconfig
Loaded configuration /home/wifi/zephyr_with_rpi4/zephyrproject/zephyr/boards/arm64/rpi_4b/rpi_4b_defconfig
Merged configuration /home/wifi/zephyr_with_rpi4/zephyrproject/zephyr/samples/hello_world/prj.conf
Configuration saved to /home/wifi/zephyr_with_rpi4/zephyrproject/zephyr/build/zephyr/.config
Kconfig header saved to /home/wifi/zephyr_with_rpi4/zephyrproject/zephyr/build/zephyr/include/generated/autoconf.h
-- Found GnuLd: /home/wifi/double_thread_zephyr_build/zephyr-sdk-0.16.4/aarch64-zephyr-elf/bin/../lib/gcc/aarch64-zephyr-elf/12.2.0/../../../../aarch64-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/wifi/double_thread_zephyr_build/zephyr-sdk-0.16.4/aarch64-zephyr-elf/bin/aarch64-zephyr-elf-gcc
-- Using ccache: /usr/bin/ccache
-- Configuring done
-- Generating done
-- Build files have been written to: /home/wifi/zephyr_with_rpi4/zephyrproject/zephyr/build
-- west build: building application
[1/119] Preparing syscall dependency handling
[2/119] Generating include/generated/version.h
-- Zephyr version: 3.6.0-rc2 (/home/wifi/zephyr_with_rpi4/zephyrproject/zephyr), build: v3.6.0-rc2-104-g793c507209eb
[118/119] Linking C executable zephyr/zephyr.elf
Memory region Used Size Region Size %age Used
FLASH: 0 GB 0 GB
RAM: 155652 B 512 KB 29.69%
IDT_LIST: 0 GB 32 KB 0.00%
Generating files from /home/wifi/zephyr_with_rpi4/zephyrproject/zephyr/build/zephyr/zephyr.elf for board: rpi_4b
[119/119] cd /home/wifi/zephyr_with_rpi4/zephyrproject/zephyr/build/zephyr && /home/wifi/zephyrproject/....k_init_priorities.py --elf-file=/home/wifi/zephyr_with_rpi4/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/
-rwxrwxr-x 1 test test 39190 Jan 24 18:38 zephyr.bin
-rw-rw-r-- 1 test test 23193 Jan 24 18:38 zephyr.dts
-rw-rw-r-- 1 test test 3011 Jan 24 18:38 zephyr.dts.d
-rw-rw-r-- 1 test test 97435 Jan 24 18:38 zephyr.dts.pre
-rwxrwxr-x 1 test test 1023460 Jan 24 18:38 zephyr.elf
-rw-rw-r-- 1 test test 399931 Jan 24 18:38 zephyr_final.map
-rw-rw-r-- 1 test test 110346 Jan 24 18:38 zephyr.hex
-rw-rw-r-- 1 test test 399931 Jan 24 18:38 zephyr.map
-rwxrwxr-x 1 test test 1024056 Jan 24 18:38 zephyr_pre0.elf
-rw-rw-r-- 1 test test 400481 Jan 24 18:38 zephyr_pre0.map
-rw-rw-r-- 1 test test 4675 Jan 24 18:38 zephyr.stat
Here we will see how to do runtime post-build checks
Go to main directory
$ cd $HOME
$ mkdir Zephyr_flash
$ cd Zephyr_flash
Download and place these files using web link:
Alternatively download using wget command,
$ wget https://raw.githubusercontent.com/raspberrypi/firmware/master/boot/bcm2711-rpi-4-b.dtb
$ wget https://raw.githubusercontent.com/raspberrypi/firmware/master/boot/bootcode.bin
$ wget https://raw.githubusercontent.com/raspberrypi/firmware/master/boot/start4.elf
Create the config.txt file and copy the below lines and save the file
$ vi config.txt
Place the following contents in
config.txt
file.
kernel=zephyr.bin
arm_64bit=1
enable_uart=1
uart_2ndstage=1
Copy the zephyr.bin file to Zephyr_flash directory
$ cp /home/test/zephyrproject/zephyr/build/zephyr/zephyr.bin /home/Zephyr_flash
Copy all the below files to TF card(SD card)
bcm2711-rpi-4-b.dtb
bootcode.bin
start4.elf
config.txt
zephyr.bin
Copy using
cp
command,
$ cp Zephyr_flash/bcm2711-rpi-4-b.dtb /mnt/boot/
$ cp Zephyr_flash/bootcode.bin /mnt/boot/
$ cp Zephyr_flash/start4.elf /mnt/boot/
$ cp Zephyr_flash/config.txt /mnt/boot/
$ cp Zephyr_flash/zephyr.bin /mnt/boot/
Disconnect the micro SD Card reader from Linux Desktop machine.
Insert SD Card to the RPI Board
Then, use serial usb cable to connect the RPI board and Linux Desktop machine.
After connecting, check whether
/dev/ttyUSB0
created or not.
$ ls /dev/ttyUSB0
Run minicom to access RPI board
$ sudo minicom -D /dev/ttyUSB0 -b 115200
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: 541874435 hw cycles
“stacks” subcommand is used to list the thread stack usage.
uart:~$ kernel stacks
0x20000430 sysworkq (real size 1024): unused 816 usage 208 / 1024 (20 %)
0x20000100 shell_uart (real size 2048): unused 872 usage 1176 / 2048 (57 %)
0x200002a0 idle (real size 256): unused 168 usage 88 / 256 (34 %)
0x200011a0 IRQ 00 (real size 2048): unused 1652 usage 396 / 2048 (19 %)
“threads” subcommand is used to list kernel threads along with various information like priority, state and stack size.
uart:~$ kernel threads
Scheduler: 1529 since last call
Threads:
0x20000430 sysworkq
options: 0x0, priority: -1 timeout: 0
state: pending, entry: 0x8005681
stack size 1024, unused 816, usage 208 / 1024 (20 %)
*0x20000100 shell_uart
options: 0x0, priority: 14 timeout: 0
state: queued, entry: 0x8001d81
stack size 2048, unused 872, usage 1176 / 2048 (57 %)
0x200002a0 idle
options: 0x1, priority: 15 timeout: 0
state: , entry: 0x800782f
stack size 256, unused 168, usage 88 / 256 (34 %)
“list” subcommand is used to list the configured devices.
uart:~$ device list
devices:
- rcc40021000 (READY)
- reset-controller (READY)
- interrupt-controller40021800 (READY)
- gpio50001400 (READY)
- gpio50001000 (READY)
- gpio50000c00 (READY)
- gpio50000800 (READY)
- gpio50000400 (READY)
- gpio50000000 (READY)
- serial40004400 (READY)
- serial40013800 (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 its 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 rpi_4b samples/hello_world/
Go to main directory
$ cd $HOME
$ mkdir Zephyr_flash
$ cd Zephyr_flash
Download and place these files using web link:
Alternatively download using wget command,
$ wget https://raw.githubusercontent.com/raspberrypi/firmware/master/boot/bcm2711-rpi-4-b.dtb
$ wget https://raw.githubusercontent.com/raspberrypi/firmware/master/boot/bootcode.bin
$ wget https://raw.githubusercontent.com/raspberrypi/firmware/master/boot/start4.elf
Create the config.txt file and copy the below lines and save the file
$ vi config.txt
Place the following contents in
config.txt
file.
kernel=zephyr.bin
arm_64bit=1
enable_uart=1
uart_2ndstage=1
Copy the zephyr.bin file to Zephyr_flash directory
$ cp /home/test/zephyrproject/zephyr/build/zephyr/zephyr.bin /home/Zephyr_flash
Copy all the below files to TF card(SD card)
bcm2711-rpi-4-b.dtb
bootcode.bin
start4.elf
config.txt
zephyr.bin
Copy using
cp
command,
$ cp Zephyr_flash/bcm2711-rpi-4-b.dtb /mnt/boot/
$ cp Zephyr_flash/bootcode.bin /mnt/boot/
$ cp Zephyr_flash/start4.elf /mnt/boot/
$ cp Zephyr_flash/config.txt /mnt/boot/
$ cp Zephyr_flash/zephyr.bin /mnt/boot/
Disconnect the micro SD Card reader from Linux Desktop machine.
Insert SD Card to the RPI Board
Then, use serial usb cable to connect the RPI board and Linux Desktop machine.
After connecting, check whether
/dev/ttyUSB0
created or not.
$ ls /dev/ttyUSB0
Run minicom to access RPI board
$ sudo minicom -D /dev/ttyUSB0 -b 115200
run “hello” on the minicom console to execute our own command.
uart:~$ hello
Hello, World!