[{"element_type":"text","content":"\n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n        \u003cp class=\"p1\"\u003eLike Linux, Zephyr can route serial console streams to various hardware interfaces. This guide shows how to run the Zephyr Shell sample program on a QT Py ESP32-S3 using either USB serial or BLE with the Adafruit Bluefruit Connect app.\u003c/p\u003e\n      \n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n","metadata":{}},{"element_type":"user_image","content":"https://cdn-learn.adafruit.com/user_assets/assets/000/001/507/original/5_version_device_list.jpeg?1736820346","metadata":{"caption":""}},{"element_type":"text","content":"\n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n        \u003ch1 class=\"p1\"\u003ePrerequisites\u003c/h1\u003e\n\u003cp class=\"p1\"\u003eTo follow along with this guide, you will need:\u003c/p\u003e\n\u003col class=\"ol1\"\u003e\n\u003cli class=\"li2\"\u003eLinux computer running Debian 12, Ubuntu 22 LTS, Ubuntu 24 LTS, or similar\u003c/li\u003e\n\u003cli class=\"li2\"\u003eZephyr workspace including west and the Zephyr SDK's esp32-s3 toolchain (my \u003ca href=\"https://adafruit-playground.com/u/SamBlenny/pages/getting-started-with-zephyr-on-linux\" target=\"_blank\"\u003eGetting Started with Zephyr on Linux\u003c/a\u003e Playground guide explains how to set this up)\u003c/li\u003e\n\u003cli class=\"li2\"\u003eAdafruit QT Py ESP32-S3 dev board (8flash/nopsram) with Zephyr bootloader (or you can use the ESP32 BOOT+RESET procedure to flash the Zephyr bootloader for the first time)\u003c/li\u003e\n\u003cli class=\"li2\"\u003eiPhone with the \u003ca href=\"https://learn.adafruit.com/bluefruit-le-connect/ios-setup\" target=\"_blank\"\u003eAdafruit Bluefruit Connect\u003c/a\u003e iOS app.\u003c/li\u003e\n\u003c/ol\u003e\n      \n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n","metadata":{}},{"element_type":"product","content":"https://www.adafruit.com/product/5426","metadata":{}},{"element_type":"text","content":"\n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n        \u003ch1 class=\"p1\"\u003eWhat is the Zephyr Shell?\u003c/h1\u003e\n\u003cp class=\"p1\"\u003eThe main Zephyr repository on GitHub comes with \u003ca href=\"https://github.com/zephyrproject-rtos/zephyr/tree/main/samples\" target=\"_blank\"\u003emany sample programs\u003c/a\u003e. This guide uses the \u003ca href=\"https://github.com/zephyrproject-rtos/zephyr/tree/main/samples/subsys/shell/shell_module\" target=\"_blank\"\u003ezephyr/samples/subsys/shell/shell_module/\u003c/a\u003e sample which is commonly referred to in the Zephyr community as \"the shell\".\u003c/p\u003e\n\u003cp class=\"p1\"\u003eThe \u003ca href=\"https://docs.zephyrproject.org/latest/services/shell/index.html\" target=\"_blank\"\u003eZephyr shell\u003c/a\u003e works like a typical serial console REPL, providing interactive commands that are useful for exploring supported features on Zephyr boards. You can send the \u003ccode\u003ehelp\u003c/code\u003e\u0026nbsp;command to get a list of available commands. Also, similar to Linux, Zephyr allows for routing the console's serial stream to different \"backend\" hardware interfaces.\u003c/p\u003e\n\u003cp class=\"p1\"\u003eThe QT Py ESP32-S3 board definition uses USB serial by default, so you can easily access the Zephyr console by running \u003ccode\u003ewest espressif monitor\u003c/code\u003e. With some small changes to the code and build command, it is also possible to route the console over Bluetooth LE Nordic UART Service (BLE NUS), which works with Adafruit's Bluefruit Connect iOS app.\u003c/p\u003e\n      \n\n\n\n\n\n\n\n\n\n\n\n","metadata":{}},{"element_type":"text","content":"\n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n        \u003ch1\u003eUSB Serial Shell\u003c/h1\u003e\n\u003cp\u003eThis is easy because Zephyr's QT Py ESP32-S3 board definition is set up to use USB serial for its console.\u003c/p\u003e\n\u003ch2\u003eBuild and Flash the USB Shell\u003c/h2\u003e\n\u003cp\u003eTo build and flash the shell firmware configured to use USB serial, run these commands in a Debian 12 terminal:\u003c/p\u003e\n      \n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n","metadata":{}},{"element_type":"code","content":"cd ~/code/zephyr-workspace/\nsource .venv/bin/activate\ncd zephyr/\nwest build -p always -b adafruit_qt_py_esp32s3/esp32s3/procpu samples/subsys/shell/shell_module/\nwest flash","metadata":{"language":"terminal","linenums":false}},{"element_type":"text","content":"\n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n        \u003ch2 class=\"p1\"\u003eRun USB Shell Commands\u003c/h2\u003e\n\u003cp\u003eThis is an example USB serial monitor session with \u003ccode\u003ewest espressif monitor\u003c/code\u003e demonstrating how to run some shell commands. I've edited out normal the serial monitor startup messages so it's easier to see the shell stuff:\u003c/p\u003e\n      \n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n","metadata":{}},{"element_type":"code","content":"(.venv) $ west espressif monitor\n[...lots of startup messages edited out]\n\nuart:~$\nuart:~$ help\nPlease press the \u003cTab\u003e button to see all available commands.\nYou can also use the \u003cTab\u003e button to prompt or auto-complete all commands or its subcommands.\nYou can try to call commands with \u003c-h\u003e or \u003c--help\u003e parameter for more information.\nShell supports following meta-keys:\n  Ctrl + (a key from: abcdefklnpuw)\n  Alt  + (a key from: bf)\nPlease refer to shell documentation for more details.\nAvailable commands:\n  bypass              : Bypass shell\n  clear               : Clear screen.\n  date                : Date commands\n  demo                : Demo commands\n  device              : Device commands\n  devmem              : Read/write physical memory\n                        Usage:\n                        Read memory at address with optional width:\n                        devmem \u003caddress\u003e [\u003cwidth\u003e]\n                        Write memory at address with mandatory width and value:\n                        devmem \u003caddress\u003e \u003cwidth\u003e \u003cvalue\u003e\n  dynamic             : Demonstrate dynamic command usage.\n  help                : Prints the help message.\n  history             : Command history.\n  kernel              : Kernel commands\n  log                 : Commands for controlling logger\n  log_test            : Log test\n  rem                 : Ignore lines beginning with 'rem '\n  resize              : Console gets terminal screen size or assumes default in\n                        case the readout fails. It must be executed after each\n                        terminal width change to ensure correct text display.\n  retval              : Print return value of most recent command\n  section_cmd         : Demo command using section for subcommand registration\n  shell               : Useful, not Unix-like shell commands.\n  shell_uart_release  : Uninitialize shell instance and release uart, start\n                        loopback on uart. Shell instance is reinitialized when\n                        'x' is pressed\n  stats               : Stats commands\n  version             : Show kernel version\nuart:~$ stats\nstats - Stats commands\nSubcommands:\n  list  : List stats\nuart:~$ version\nZephyr version 4.0.99\nuart:~$ date\ndate - Date commands\nSubcommands:\n  set  : [Y-m-d] \u003cH:M:S\u003e\n  get  : [none]\nuart:~$ device\ndevice - Device commands\nSubcommands:\n  list  : List configured devices\nuart:~$ device list\ndevices:\n- rtc@60021000 (READY)\n  DT node labels: rtc\n- gpio@60004800 (READY)\n  DT node labels: gpio1\n- gpio@60004000 (READY)\n  DT node labels: gpio0\n- uart@60038000 (READY)\n  DT node labels: usb_serial\n- uart@60000000 (READY)\n  DT node labels: uart0 xiao_serial\nuart:~$","metadata":{"language":"terminal","linenums":false}},{"element_type":"text","content":"\n  \n  \n  \n  \n  \n  \n  \n  \n  \n        \u003ch1 class=\"p1\"\u003eBLE Nordic UART Service (NUS) Shell\u003c/h1\u003e\n\u003cp class=\"p2\"\u003eBuilding the shell for BLE serial is a little more complicated because the ESP32-S3 HAL code expects to have its console using USB serial. But, that's easy to fix with a minor patch.\u003c/p\u003e\n\u003cp class=\"p2\"\u003eFor background and context on the \u003ccode\u003e-S nus-console\u003c/code\u003e west build option to re-route the console stream, you might want to check out:\u003c/p\u003e\n\u003cul\u003e\n\u003cli class=\"p2\"\u003eVideo: \u003ca href=\"https://www.youtube.com/watch?v=qJyr1rhVP8o\" target=\"_blank\"\u003eOpen-Source Contribution Update: Shell Over BLE - Luis Ubieda, Croxel, Inc.\u003c/a\u003e\n\u003c/li\u003e\n\u003cli class=\"p2\"\u003eSource code: \u003ca href=\"https://github.com/zephyrproject-rtos/zephyr/tree/main/snippets/nus-console\" target=\"_blank\"\u003ehttps://github.com/zephyrproject-rtos/zephyr/tree/main/snippets/nus-console\u003c/a\u003e\n\u003c/li\u003e\n\u003cli class=\"p2\"\u003eSnippet docs: \u003ca href=\"https://docs.zephyrproject.org/latest/snippets/nus-console/README.html\" target=\"_blank\"\u003ehttps://docs.zephyrproject.org/latest/snippets/nus-console/README.html\u003c/a\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2 class=\"p1\"\u003ePatch the ESP32-S3 SoC Init Code\u003c/h2\u003e\n\u003cp\u003eCurrently (Jan 13, 2025), if you try this with the unpatched ESP32-S3 init code, it doesn't work:\u003c/p\u003e\n\u003cp\u003e\u003ccode\u003ewest build -p always -b adafruit_qt_py_esp32s3/esp32s3/procpu -S nus-console samples/subsys/shell/shell_module/\u003c/code\u003e\u003c/p\u003e\n\u003cp\u003eWhen I tried it, I got this error:\u003c/p\u003e\n\u003cp\u003e\u003ccode\u003eFAILED: zephyr/zephyr_pre0.elf zephyr/zephyr_pre0.map [...lots of stuff edited out...]\u003c/code\u003e\u003cbr\u003e\u003ccode\u003e/home/sam/code/zephyr-workspace/zephyr/soc/espressif/esp32s3/hw_init.c:53: undefined reference to `esp_console_init'\u003c/code\u003e\u0026nbsp;\u003c/p\u003e\n\u003cp\u003eThe error is happening because \u003ca href=\"https://github.com/zephyrproject-rtos/zephyr/blob/51efc600871ac69c75d0de852d65c8cae3143288/soc/espressif/esp32s3/hw_init.c#L60-L62\" target=\"_blank\"\u003ezephyrproject-rtos/zephyr/soc/espressif/esp32s3/hw_init.c\u003c/a\u003e unconditionally makes a call to\u0026nbsp; \u0026nbsp;\u003ccode\u003eesp_console_init()\u003c/code\u003e, while the definition of\u0026nbsp;\u003ccode\u003eesp_console_init()\u003c/code\u003e happens inside of an \u003ccode\u003e#ifdef CONFIG_ESP_CONSOLE_UART\u003c/code\u003e block in \u003ca href=\"https://github.com/zephyrproject-rtos/hal_espressif/blob/zephyr/zephyr/common/console_init.c#L36-L53\" target=\"_blank\"\u003ezephyrproject-rtos/hal_espressif/zephyr/common/console_init.c\u003c/a\u003e. When you specify the nus-console snippet option, it turns off that definition block, so the linker can't find \u003ccode\u003eesp_console_init()\u003c/code\u003e.\u003c/p\u003e\n\u003cp\u003eOne easy fix is to use your favorite editor to add an ifdef block around the \u003ccode\u003eesp_console_init()\u003c/code\u003e call in \u003ccode\u003ezephyr/soc/espressif/esp32s3/hw_init.c\u003c/code\u003e, so it looks like this:\u003c/p\u003e\n\u003cp\u003e\u0026nbsp;\u003c/p\u003e\n      \n\n\n\n\n\n\n\n\n","metadata":{}},{"element_type":"code","content":"(.venv) $ git diff\ndiff --git a/soc/espressif/esp32s3/hw_init.c b/soc/espressif/esp32s3/hw_init.c\nindex 97ffb0ef..15cbb9dc 100644\n--- a/soc/espressif/esp32s3/hw_init.c\n+++ b/soc/espressif/esp32s3/hw_init.c\n@@ -58,7 +58,9 @@ int hardware_init(void)\n        bootloader_clock_configure();\n \n        /* initialize console, from now on, we can log */\n+#ifdef CONFIG_ESP_CONSOLE_UART\n        esp_console_init();\n+#endif /* CONFIG_ESP_CONSOLE_UART */\n        print_banner();\n \n        spi_flash_init_chip_state();","metadata":{"language":"terminal","linenums":false}},{"element_type":"text","content":"\n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n        \u003ch2 class=\"p1\"\u003eBuild and Flash BLE NUS Shell\u003c/h2\u003e\n\u003cp\u003eOnce the code is patched, you can build and flash the shell with BLE NUS console using these commands in a Debian 12 terminal:\u003c/p\u003e\n      \n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n","metadata":{}},{"element_type":"code","content":"west build -p always -b adafruit_qt_py_esp32s3/esp32s3/procpu -S nus-console samples/subsys/shell/shell_module/\nwest flash","metadata":{"language":"terminal","linenums":false}},{"element_type":"text","content":"\n        \u003ch2 class=\"p1\"\u003eRun Shell Commands with Bluefruit Connect\u003c/h2\u003e\n\u003cp\u003eNow that the console is re-routed to the Bluetooth LE Nordic UART Service, \u003ccode\u003ewest espressif monitor\u003c/code\u003e won't work anymore. Instead, we can use the Adafruit Bluefruit Connect iOS app.\u003c/p\u003e\n\u003cp\u003eFirst, you need to install the app, enable bluetooth, and so on. If you need more instructions, you can check out the\u0026nbsp;\u003ca href=\"https://learn.adafruit.com/bluefruit-le-connect/ios-setup\"\u003eBluefruit LE Connect for iOS and Android\u003c/a\u003e learn guide.\u003c/p\u003e\n\u003cp\u003eNext open the app. On the Select Device screen, enable the \"Must have UART Service\" option, then reset the ESP32-S3 board so it will send an advertisement. You should see a \"Zephyr\" device, like this:\u003c/p\u003e\n      ","metadata":{}},{"element_type":"user_image","content":"https://cdn-learn.adafruit.com/user_assets/assets/000/001/508/original/1_Bluefruit_Connect_Scan.jpeg?1736825177","metadata":{"caption":""}},{"element_type":"text","content":"\n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n        \u003cp\u003eTap the Connect button. You should see a screen like this:\u003c/p\u003e\n      \n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n","metadata":{}},{"element_type":"user_image","content":"https://cdn-learn.adafruit.com/user_assets/assets/000/001/509/original/2_Select_UART_Screen.jpeg?1736825242","metadata":{"caption":""}},{"element_type":"text","content":"\n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n        \u003cp\u003ePick the UART option to open the UART terminal screen. When the UART terminal first opens, it may be in \"timestamp\" mode, where each BLE UART message goes on its own line with a timestamp on the left. If that happens, the first screen of output from the Zephyr shell will look pretty confusing. Don't worry though, because it's easy to fix.\u003c/p\u003e\n\u003cp\u003eTo fix the terminal display, tap the gear icon to open settings, then select \"Terminal\" from the \"Display Mode\" list, like this:\u003c/p\u003e\n      \n\n\n\n\n\n\n\n\n\n\n","metadata":{}},{"element_type":"user_image","content":"https://cdn-learn.adafruit.com/user_assets/assets/000/001/510/original/3_Settings_Display_Mode_Terminal.jpeg?1736825523","metadata":{"caption":""}},{"element_type":"text","content":"\n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n        \u003cp\u003eOnce you've set the display mode to terminal, you should see about a half-screen of output from the Zephyr shell. It will probably be difficult to read because of garbage characters from ANSI escape codes.\u003c/p\u003e\n\u003cp\u003eYou can send the \u003ccode\u003eshell colors off\u003c/code\u003e command to turn off the ANSI escape codes. Once you do that, the shell output should be much easier to read, like this:\u003c/p\u003e\n      \n\n\n\n\n\n\n\n\n\n","metadata":{}},{"element_type":"user_image","content":"https://cdn-learn.adafruit.com/user_assets/assets/000/001/511/original/4_shell_colors_off.jpeg?1736825822","metadata":{"caption":""}},{"element_type":"text","content":"\n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n        \u003cp\u003eOnce you turn off the escape codes, it's much more comfortable to try other commands and explore a bit. For example, the \u003ccode\u003edevice list\u003c/code\u003e command shows information about the current firmware's Devicetree configuration:\u003c/p\u003e\n      \n\n\n\n\n\n\n\n\n\n\n\n\n\n\n","metadata":{}},{"element_type":"user_image","content":"https://cdn-learn.adafruit.com/user_assets/assets/000/001/512/original/5_version_device_list.jpeg?1736826052","metadata":{"caption":""}}]