This blog was written by Mike Szczys of Golioth and was originally published in the blog section of the Golioth website.
Here is an abstract of the blog “West Commands Every Zephyr User Should Know”.
West is Zephyr’s meta tool, described as a Swiss army knife for wrapping many commands and tools. The blog highlights essential west commands like west build
, west flash
, west debug
, and west attach
, which are commonly used for building, flashing, and debugging projects. Newer commands such as west sdk install
simplify SDK installation and management. The post also covers west build -t menuconfig
for Kconfig editing, west boards
for listing board definitions, and west flash --context
for retrieving runner information. Manifest management is detailed with commands like west manifest --path
and west manifest --freeze
. The blog describes the depth of west’s functionality and its adaptability through custom commands.
Read the original blog below:
West is the meta tool used by Zephyr to wrap myriad commands and tools. Zephyr calls west a Swiss army knife, and just like its namesake, there are some west commands you have available but likely have never used.
Today we’ll survey useful west commands that you may not know about. But let’s start with the obvious ones!
West commands you already know
1. west 2. west build 3. west flash 4. west debug 5. west attach
These are the go-to’s that should already be at the tips of your fingers. A simple west
without anything else prints out usage where you’ll see all of the commands covered in the rest of the post.
The west build
command will rebuild a project, but you will need to specify the board and path the first time to get things set up. Programming the board is handled by west flash
, and depending on the runner, you can open a debugging session with west attach
or west debug
.
Installing toolchains
1. west sdk
Another one of those you should always have under your fingers, west is used to launch the ncurses-style menuconfig editor for working with Kconfig symbols. Once inside, use /
to search, or navigate the menu system. You can use the ?
to bring up help information on any symbol currently highlighted.
Working with Boards
1. west boards 2. west boards -n 52840
List every board definition in the Zephyr tree with a simple west boards
command. However, the search option using -n
is likely more useful. The command above will return (almost) every board that is built on an nRF52840 chip. I found that it does not search the SoC of the Hardware Model v2 naming scheme, so rak5010
wasn’t returned in the search even though its more verbose rak5010/nrf52840
name is .
Working with runners
1. west flash –context
This one is a bit obscure, but absolutely crucial when you need it. Zephyr uses the concept of runners to flash and debug targets. Using the context flag pulls up a ton of useful information. Bear with me while I paste a really long example output so we can discuss.
1. ➜ west flash --context 2. -- west flash: rebuilding 3. ninja: no work to do. 4. build configuration: 5. build directory: /home/mike/golioth-compile/golioth-firmware-sdk/modules/lib/golioth-firmware-sdk/build 6. board: mimxrt1024_evk/mimxrt1024 7. runners.yaml: /home/mike/golioth-compile/golioth-firmware-sdk/modules/lib/golioth-firmware-sdk/build/zephyr/runners.yaml 8. zephyr runners which support "west flash": 9. blackmagicprobe, nrfutil, arc-nsim, dediprog, uf2, dfu-util, xsdb, 10. teensy, ezflashcli, linkserver, nrfjprog, silabs_commander, esp32, 11. spi_burn, pyocd, stm32cubeprogrammer, native, mdb-nsim, gd32isp, 12. nios2, intel_adsp, canopen, openocd, probe-rs, hifive1, stm32flash, 13. misc-flasher, bossac, trace32, intel_cyclonev, jlink, mdb-hw 14. 15. Note: not all may work with this board and build directory. 16. Available runners are listed below. 17. available runners in runners.yaml: 18. linkserver, jlink, pyocd 19. default runner in runners.yaml: 20. linkserver 21. common runner configuration: 22. - build_dir: /home/mike/golioth-compile/golioth-firmware-sdk/modules/lib/golioth-firmware-sdk/build 23. - board_dir: /home/mike/golioth-compile/golioth-firmware-sdk/zephyr/boards/nxp/mimxrt1024_evk 24. - elf_file: /home/mike/golioth-compile/golioth-firmware-sdk/modules/lib/golioth-firmware-sdk/build/zephyr/zephyr.elf 25. - exe_file: None 26. - hex_file: /home/mike/golioth-compile/golioth-firmware-sdk/modules/lib/golioth-firmware-sdk/build/zephyr/zephyr.hex 27. - bin_file: /home/mike/golioth-compile/golioth-firmware-sdk/modules/lib/golioth-firmware-sdk/build/zephyr/zephyr.bin 28. - uf2_file: None 29. - file: None 30. - file_type: FileType.OTHER 31. - gdb: /home/mike/zephyr-sdk-0.17.0/arm-zephyr-eabi/bin/arm-zephyr-eabi-gdb-py 32. - openocd: /home/mike/zephyr-sdk-0.17.0/sysroots/x86_64-pokysdk-linux/usr/bin/openocd 33. - openocd_search: ['/home/mike/zephyr-sdk-0.17.0/sysroots/x86_64-pokysdk-linux/usr/share/openocd/scripts'] 34. - rtt_address: None 35. runner-specific context: 36. linkserver capabilities: 37. RunnerCaps(commands={'debugserver', 'flash', 'debug', 'attach'}, dev_id=True, flash_addr=True, erase=True, reset=False, extload=False, tool_opt=True, file=True, hide_load_files=False, rtt=False) 38. linkserver options: 39. -i DEV_ID, --dev-id DEV_ID 40. Device identifier. Use it to select which debugger, device, node or instance to target when multiple ones are available or connected. 41. --dt-flash {Y,y,N,n,yes,no,YES,NO} 42. If 'yes', try to use flash address information from devicetree when flash addresses are unknown (e.g. when flashing a .bin) 43. -f FILE, --file FILE path to binary file 44. -t FILE_TYPE, --file-type FILE_TYPE 45. type of binary file 46. --elf-file FILE Deprecated, use -f/--file instead. 47. --hex-file FILE Deprecated, use -f/--file instead. 48. --bin-file FILE Deprecated, use -f/--file instead. 49. --erase, --no-erase mass erase flash before loading, or don't. Default action depends on each specific runner. 50. -O TOOL_OPT, --tool-opt TOOL_OPT 51. Option to pass on to the underlying tool used by this runner. This can be given multiple times; the resulting arguments will be given to the tool in the order they appear on the 52. command line. 53. --device DEVICE device name 54. --core CORE core of the device 55. --probe PROBE interface to use (index, or serial number, default is #1 56. --tui if given, GDB uses -tui 57. --gdb-port GDB_PORT gdb port to open, defaults to 3333 58. --semihost-port SEMIHOST_PORT 59. semihost port to open, defaults to the empty string and runs a gdb server 60. --linkserver LINKSERVER 61. LinkServer executable, default is LinkServer 62. --override OVERRIDE configuration overrides as defined bylinkserver. Example: /device/memory/0/location=0xcafecafe 63. linkserver arguments from runners.yaml: 64. --dt-flash=y 65.--device=MIMXRT1024xxxxx:MIMXRT1024-EVK 66. jlink capabilities: 67. RunnerCaps(commands={'debugserver', 'rtt', 'debug', 'flash', 'attach'}, dev_id=True, flash_addr=True, erase=True, reset=True, extload=False, tool_opt=True, file=True, hide_load_files=False, rtt=True) 68. jlink options: 69. -i DEV_ID, --dev-id DEV_ID 70. Device identifier. Use it to select the J-Link Serial Number of the device connected over USB. If the J-Link is connected over ip, the Device identifier is the ip. 71. --dt-flash {Y,y,N,n,yes,no,YES,NO} 72. If 'yes', try to use flash address information from devicetree when flash addresses are unknown (e.g. when flashing a .bin) 73. -f FILE, --file FILE path to binary file 74. -t FILE_TYPE, --file-type FILE_TYPE 75. type of binary file 76. --elf-file FILE Deprecated, use -f/--file instead. 77. --hex-file FILE Deprecated, use -f/--file instead. 78. --bin-file FILE Deprecated, use -f/--file instead. 79. --erase, --no-erase mass erase flash before loading, or don't. Default action depends on each specific runner. 80. --reset, --no-reset reset device after flashing, or don't. Default action depends on each specific runner. 81. -O TOOL_OPT, --tool-opt TOOL_OPT 82. Additional options for JLink Commander, e.g. '-autoconnect 1' 83. --rtt-address RTT_ADDRESS 84. address of RTT control block. If not supplied, it will be autodetected if possible 85. --device DEVICE device name 86.--loader LOADER specifies a loader type 87. --id DEV_ID obsolete synonym for -i/--dev-id 88. --iface IFACE interface to use, default is swd 89. --speed SPEED interface speed, default is autodetect 90. --tui if given, GDB uses -tui 91. --gdbserver GDBSERVER 92. GDB server, default is JLinkGDBServer 93. --gdb-host GDB_HOST custom gdb host, defaults to the empty string and runs a gdb server 94. --gdb-port GDB_PORT pyocd gdb port, defaults to 2331 95. --commander COMMANDER 96. J-Link Commander, default is JLinkExe 97. --reset-after-load, --no-reset-after-load 98. obsolete synonym for --reset/--no-reset 99. --rtt-client RTT_CLIENT 100. RTT client, default is JLinkRTTClient 101. --rtt-port RTT_PORT jlink rtt port, defaults to 19021 102. jlink arguments from runners.yaml: 103. --dt-flash=y 104. --device=MIMXRT1024xxx5A 105. pyocd capabilities: 106. RunnerCaps(commands={'debugserver', 'rtt', 'debug', 'flash', 'attach'}, dev_id=True, flash_addr=True, erase=True, reset=False, extload=False, tool_opt=True, file=False, hide_load_files=False, rtt=True) 107. pyocd options: 108. -i DEV_ID, --dev-id DEV_ID 109. Device identifier. Use it to select the probe's unique ID or substring thereof. 110. --dt-flash {Y,y,N,n,yes,no,YES,NO} 111. If 'yes', try to use flash address information from devicetree when flash addresses are unknown (e.g. when flashing a .bin) 112. --elf-file FILE path to zephyr.elf 113. --hex-file FILE path to zephyr.hex 114. --bin-file FILE path to zephyr.bin 115. --erase, --no-erase mass erase flash before loading, or don't. Default action depends on each specific runner. 116. -O TOOL_OPT, --tool-opt TOOL_OPT 117. Additional options for pyocd commander, e.g. '--script=user.py' 118. --rtt-address RTT_ADDRESS 119. address of RTT control block. If not supplied, it will be autodetected if possible 120. --target TARGET target override 121. --daparg DAPARG Additional -da arguments to pyocd tool 122. --pyocd PYOCD path to pyocd tool, default is pyocd 123. --flash-opt FLASH_OPT 124. Additional options for pyocd flash, e.g. --flash-opt="-e=chip" to chip erase 125 --frequency FREQUENCY 126. SWD clock frequency in Hz 127. --gdb-port GDB_PORT pyocd gdb port, defaults to 3333 128. --telnet-port TELNET_PORT 129. pyocd telnet port, defaults to 4444 130. --tui if given, GDB uses -tui 131. --board-id DEV_ID obsolete synonym for -i/--dev-id 132. pyocd arguments from runners.yaml: 133. --dt-flash=y 134. --target=mimxrt1024 135. 136. Note: use -r RUNNER to limit information to one runner.
You can see so many helpful tidbits when running the west flash --context
command after a successful build. First up, you get a list of what runners are currently supported for this board (line 17), along with all of the runners available to Zephyr (line 8). Not able to flash your chip? Perhaps the default runner (line 19) is different from the the programmer you have connected. This is the case for me with the mimxrt1024_evk board, so adding --runner jlink
to all flash/attach commands is how I work with this board.
The rest of the output covers runner-specific configuration. Most of the time the defaults work great. But when you need to pass a different GDB port, or make some other tweak, this is where to go for help.
Managing Manifests
1. west manifest --path 2. west config manifest.file my-custom-manifest.yml 3. west manifest --resolve 4. west manifest --freeze
Manifests are near and dear to my heart. I think they are among the best features of the Zephyr ecosystem!
The Golioth Firmware SDK is an interesting use case for multiple distinct manifest files. We have one for projects that build on Zephyr, and another for projects that build on Nordic’s nrfConnect SDK (NCS). On workspaces installed with the Golioth SDK as the main manifest, I can switch between the two types of installations using west config manifest.file west-zephyr.yml
.
When you just want to know where your manifest file is located, reach for west manifest --path
. During development you might want to know what versions are being pulled in from inherited manifests. The west manifest --resolve
will print that info out for you. When you’re getting to the end of the project, use west manifest --freeze
to generate your manifest file with commit hashes for versions (locking in any branch names you used).
This tool goes deep
The west meta tool wraps up an incredible amount of functionality. Most of the time, you’ll find west can already do the things you want, it just takes a little digging to discover the syntax.
If west does fall short of your needs, you can always add your own custom commands. We do that here at Golioth, but Zephyr also does it to enable most of the commands mentioned above. But that’s a story best saved for a future blog post.