[{"content":"","date":"2 April 2026","externalUrl":null,"permalink":"/authors/alexey-lapshin/","section":"Developer Portal Authors","summary":"","title":"Alexey Lapshin","type":"authors"},{"content":"","date":"2 April 2026","externalUrl":null,"permalink":"/authors/","section":"Developer Portal Authors","summary":"","title":"Developer Portal Authors","type":"authors"},{"content":"","date":"2 April 2026","externalUrl":null,"permalink":"/tags/esp-idf/","section":"Tags","summary":"","title":"ESP-IDF","type":"tags"},{"content":"Starting with ESP-IDF v6.0, the default C library is now PicolibC instead of Newlib.\nAlthough PicolibC is a fork of Newlib, its evolution has focused on better memory efficiency, which is especially important for embedded systems. The choice of libc influences code size, stack use, heap pressure, compatibility with existing components, and how standard streams behave across tasks.\nThis article explains what changes in practice, where PicolibC is better, where Newlib still fits, and what to check before migrating existing code. It also reports measured binary size, stack usage, and heap usage on ESP32-C3 for stdio workload, comparing Newlib and PicolibC side by side.\nShort version: PicolibC usually gives you a smaller binary and lower runtime memory use, especially for stdio-heavy applications. Newlib remains available when compatibility is more important than memory savings. At a glance # Quick comparison # Topic Newlib PicolibC Role in ESP-IDF v6.0 Available as an option Default libc Code size Larger in typical stdio-heavy builds Usually smaller Stack and heap use in stdio paths Higher Lower Standard stream behavior Historically more flexible for task-local redirection in ESP-IDF integrations POSIX-style shared global streams Compatibility with older assumptions around struct reent Best match Requires compatibility layer for some legacy code Best fit Third-party compatibility New projects, memory-limited applications, stdio-heavy firmware Why ESP-IDF switches the default # For ESP32-class SoCs, RAM and flash are always finite resources. Many firmware images are not limited by application logic alone, but by support code such as logging, formatting, console I/O, and parsing.\nThat is exactly where PicolibC helps most. In ESP-IDF v6.0, using PicolibC by default improves the out-of-the-box experience for applications that make heavy use of formatted I/O, especially logging and console output.\nIn those cases, the switch typically reduces binary size, stack usage, and heap usage without forcing application-level code changes.\nWhat changes technically # What are Newlib and PicolibC # Newlib has been the traditional C library for many bare-metal and RTOS-based embedded toolchains. It provides the usual C and POSIX-like interfaces expected by embedded developers, and it has a long track record across architectures and SDKs.\nPicolibC started as a fork of Newlib with a strong focus on embedded systems that need the same APIs with tighter memory budgets. Its most visible difference is a rewritten stdio implementation designed to use less RAM while keeping behavior familiar for most applications. That layer began from AVR libc\u0026rsquo;s stdio, but it was changed so extensively that it is no longer recognizable as the same code.\nSo this is not a comparison between a \u0026ldquo;full desktop libc\u0026rdquo; and a \u0026ldquo;tiny compatibility shim.\u0026rdquo; Both are real embedded C libraries. The key difference is that PicolibC prioritizes memory efficiency and runtime performance.\nThe biggest practical difference: stdio # If there\u0026rsquo;s one key difference to remember between Newlib and PicolibC in ESP-IDF, it\u0026rsquo;s this: their standard I/O behavior differs.\nWith PicolibC, stdin, stdout, and stderr are global shared streams, which matches POSIX expectations. That means you should treat them as process-wide resources rather than per-task objects.\nIf your application relied on redefining stdin, stdout, or stderr separately for individual FreeRTOS tasks, that approach does not carry over to PicolibC. This matters most in advanced applications that redirect console output in task-specific ways, or in codebases that depend on Newlib internals rather than public libc APIs.\nCompatibility mode and its limits # To ease migration, ESP-IDF enables CONFIG_LIBC_PICOLIBC_NEWLIB_COMPATIBILITY by default.\nThis option provides limited compatibility for common Newlib assumptions by supplying:\nthread-local copies of stdin, stdout, and stderr a getreent() implementation for code expecting Newlib-style reentrancy hooks That said, this is a compatibility bridge, not a guarantee that all Newlib-specific behavior is safe forever.\nIf a library was built against Newlib headers and directly manipulates internal fields of struct reent, PicolibC compatibility mode may not be enough. In practice, code that depends on those internals should be reviewed carefully because assumptions that were safe with Newlib may break under PicolibC compatibility mode and lead to incorrect behavior or memory corruption. Accessing those internal fields is generally something only the C library itself should do, but some low-level or legacy components may still depend on it.\nIf your project does not link against external libraries built around Newlib internals, you can disable CONFIG_LIBC_PICOLIBC_NEWLIB_COMPATIBILITY and save a small additional amount of memory.\nMigration guidance # When migration is usually straightforward # For most code that sticks to normal libc interfaces, switching is straightforward and beneficial. Projects that mainly care about flash size, stack size, and heap size are typically good candidates for the default PicolibC setup.\nWhen to review code more carefully # Migration deserves more scrutiny if third-party libraries were built against Newlib headers, if those libraries rely on Newlib-specific internal behavior, or if the codebase redirects standard streams per task. Another edge case is code that invokes libc from interrupt handlers and must keep IRAM usage minimal, because with PicolibC that code may need to be placed in IRAM.\nHow to switch back to Newlib # Newlib is still available in ESP-IDF toolchains.\nTo use it instead of PicolibC, open menuconfig and go to Component config -\u0026gt; LibC, then select CONFIG_LIBC_NEWLIB.\nThe parent menu is CONFIG_LIBC, so teams can explicitly choose the libc implementation per project if needed.\nMeasured differences on ESP32-C3 # Benchmark workload # The following synthetic example stresses formatted I/O, which is where the difference between the two libraries is easiest to see:\nFILE *f = fopen(\u0026#34;/dev/console\u0026#34;, \u0026#34;w\u0026#34;); for (int i = 0; i \u0026lt; 10; i++) { fprintf(f, \u0026#34;hello world %s\\n\u0026#34;, \u0026#34;🤖\u0026#34;); fprintf(f, \u0026#34;%.1000f\\n\u0026#34;, 3.141592653589793); fprintf(f, \u0026#34;%1000d\\n\u0026#34;, 42); } Results # Compiled for ESP32-C3, the same test produced these results:\nMetric Newlib PicolibC Difference Binary size (bytes) 280,128 224,656 -19.80% Stack usage (bytes) 1,748 802 -54.12% Heap usage (bytes) 1,652 376 -77.24% Performance (CPU cycles) 278,232,026 279,823,800 +0.59% How to interpret the numbers # The main takeaway is that PicolibC achieves a substantial reduction in memory cost while keeping runtime performance effectively in the same range for this workload. As with any microbenchmark, the exact numbers depend on the chip, ESP-IDF revision, configuration, and toolchain details, but the trend is representative of stdio-heavy code paths.\nThat result is notable because Newlib already benefits from ROM-provided libc code: typically on the order of 15-20 KB depending on the chip and configuration, so that portion does not contribute to the application flash image. Even with that ROM offload for Newlib, PicolibC still wins the size comparison in this test. Looking ahead, future chips may also place some PicolibC functionality in ROM, which would make the resulting application image even smaller.\nEven when CONFIG_LIBC_NEWLIB_NANO_FORMAT is enabled in Newlib, PicolibC still produces a smaller image in this workload: 224,592 bytes vs 239,888 bytes, or about 6% smaller. Choosing between PicolibC and Newlib # PicolibC is usually the right default when # Projects starting on ESP-IDF v6.0 Tight flash and RAM budgets Heavy logging or formatted I/O Newlib is still safer when # Third-party libraries were built against Newlib headers Those libraries rely on Newlib-specific internal behavior The codebase redirects standard streams per task Migration risk must stay low for a mature product libc is invoked from interrupt handlers and IRAM usage must stay minimal, and moving that code into IRAM would be undesirable In other words, PicolibC is the better default for efficiency, while Newlib remains the better fallback for compatibility-sensitive systems.\nConclusion # The move from Newlib to PicolibC in ESP-IDF v6.0 is not just a housekeeping change. It reflects a shift toward a libc that is better aligned with the memory constraints of modern embedded firmware.\nIf your code uses standard libc APIs in a conventional way, PicolibC will likely give you smaller and leaner builds with no effort. If your project depends on legacy Newlib behavior or low-level integration details, Newlib is still there when compatibility matters more than optimization.\nThis is not the end of the story. The comparison above reflects current ESP targets, where PicolibC is linked from flash while some Newlib functionality is already provided from ROM. If PicolibC is placed in ROM in the future chips, the size tradeoff could shift again, and the flash savings could become even greater.\n","date":"2 April 2026","externalUrl":null,"permalink":"/blog/2026/04/esp-idf-6-default-libc-picolibc/","section":"Blog","summary":"ESP-IDF v6.0 switches the default C library from Newlib to PicolibC. This article compares both libraries in terms of memory usage, stdio behavior, compatibility, and migration tradeoffs, and explains when keeping Newlib still makes sense.","title":"ESP-IDF v6.0: Default libc Switches from Newlib to PicolibC","type":"blog"},{"content":"\u0026ldquo;Welcome to the Espressif Systems Developer Portal—your official hub for all good things, such as the ESP32 and more. Explore our extensive collection of articles, workshops, and tutorials to enhance your development journey with the latest tools and insights.\u0026rdquo;\nFeatured Articles # Announcing ESP-IDF v6.0 20 March 2026\u0026middot;10 mins ESP-IDF Release IoT We\u0026rsquo;re excited to announce the long-awaited release of ESP-IDF 6.0! This article highlights the key changes and improvements not only to ESP-IDF itself, but also to the broader ESP-IDF tooling ecosystem, all designed to enhance your developer experience. Staying Ahead with ESP32 Security Updates 5 March 2026\u0026middot;5 mins Security Esp32 ESP-IDF IoT This article explains how manufacturers can use the ESP32 ecosystem to build and maintain secure firmware over time, especially in light of new regulations like the EU Cyber Resilience Act. It highlights tools such as vulnerability dashboards, Long-Term Support branches, and secure OTA updates to ensure ongoing compliance and device security. More Articles Workshop Highlights # Dive into our latest workshops and master the skills you need to maximize the power of the ESP32.\nESP-IDF Advanced Workshop 5 August 2025\u0026middot;4 mins This workshop is about advanced features of ESP-IDF and focuses on modular development, event loops, core dumps, size analysis and flash encryption. More Workshops Upcoming Events # Embedded World 2026 1 min Event Ew25 Meet Espressif at Embedded World 2026 in Nuremberg from March 10 to 12 to explore live demos and the latest developments in connectivity, graphics, AIoT, and edge computing, and connect directly with our team. More Events ","date":"2 April 2026","externalUrl":null,"permalink":"/","section":"Espressif Developer Portal","summary":"","title":"Espressif Developer Portal","type":"page"},{"content":"","date":"2 April 2026","externalUrl":null,"permalink":"/tags/libc/","section":"Tags","summary":"","title":"Libc","type":"tags"},{"content":"","date":"2 April 2026","externalUrl":null,"permalink":"/tags/migration/","section":"Tags","summary":"","title":"Migration","type":"tags"},{"content":"","date":"2 April 2026","externalUrl":null,"permalink":"/tags/newlib/","section":"Tags","summary":"","title":"Newlib","type":"tags"},{"content":"","date":"2 April 2026","externalUrl":null,"permalink":"/tags/picolibc/","section":"Tags","summary":"","title":"PicolibC","type":"tags"},{"content":"Assign tags to your content following the guidelines in Tagging content.\n","date":"2 April 2026","externalUrl":null,"permalink":"/tags/","section":"Tags","summary":"","title":"Tags","type":"tags"},{"content":"Last updated: Loading... This page lists the projects in which the ESP32-H4 is supported.\nTo show the status of features, the following icons are used:\n:white_check_mark: Supported feature :hourglass_flowing_sand: Unsupported feature (IDF-1234) \u0026quot;IDF-1234\u0026quot; indicates an internal issue reference to help us keep this list up to date :question: Support status unknown Such status issues will be checked and fixed shortly This page will be periodically updated to reflect the current support status for the ESP32-H4.\nSome links provided below might appear invalid due to being generated as placeholders for documents to be added later. ESP-IDF # Now the master branch contains the latest preview support for ESP32-H4. Until a full support version is released, please update to the HEAD of master branch to develop with ESP32-H4 chips.\nIf you have an issue to report about any of the ESP32-H4 features, please create an issue in the ESP-IDF GitHub issue tracker.\nLoading... Other Projects # If you have an issue to report about any of the ESP32-H4 features, please create an issue in the issue tracker of a respective project.\nLoading... ","date":"26 March 2026","externalUrl":null,"permalink":"/hardware/esp32h4/","section":"Hardware","summary":"","title":"ESP32-H4 status","type":"hardware"},{"content":"Last updated: Loading... This page lists the projects in which the ESP32-S31 is supported.\nTo show the status of features, the following icons are used:\n:white_check_mark: Supported feature :hourglass_flowing_sand: Unsupported feature (IDF-1234) \u0026quot;IDF-1234\u0026quot; indicates an internal issue reference to help us keep this list up to date :question: Support status unknown Such status issues will be checked and fixed shortly This page will be periodically updated to reflect the current support status for the ESP32-S31.\nSome links provided below might appear invalid due to being generated as placeholders for documents to be added later. ESP-IDF # Now the master branch contains the latest preview support for ESP32-S31. Until a full support version is released, please update to the HEAD of master branch to develop with ESP32-S31 chips.\nIf you have an issue to report about any of the ESP32-S31 features, please create an issue in the ESP-IDF GitHub issue tracker.\nLoading... Other Projects # If you have an issue to report about any of the ESP32-S31 features, please create an issue in the issue tracker of a respective project.\nLoading... ","date":"26 March 2026","externalUrl":null,"permalink":"/hardware/esp32s31/","section":"Hardware","summary":"","title":"ESP32-S31 status","type":"hardware"},{"content":"","date":"23 March 2026","externalUrl":null,"permalink":"/tags/beginner/","section":"Tags","summary":"","title":"Beginner","type":"tags"},{"content":"","date":"23 March 2026","externalUrl":null,"permalink":"/tags/filesystem/","section":"Tags","summary":"","title":"Filesystem","type":"tags"},{"content":" Introduction # Storing files on flash—configuration, web assets, or firmware data—is common in embedded applications. Based on the original SPIFFS project, the SPIFFS component in ESP-IDF provides a lightweight filesystem for SPI NOR flash: it supports wear levelling, consistency checks, and integrates with the rest of ESP-IDF so you can use familiar C and POSIX file APIs.\nThis article introduces the SPIFFS component, how it collaborates with the VFS (Virtual File System) component and with tools like SPIFFSgen, and points you to a working example.\nSPIFFS comes bundled with ESP-IDF rather than being distributed via the Component Registry. You use it by mounting a SPIFFS partition through VFS, then reading and writing files via fopen, fprintf, fread, and similar functions.\nKey Features # The SPIFFS component offers:\nStandard file I/O API: Use familiar C and POSIX calls—fopen, fread, fwrite, fprintf, stat, unlink, rename, and the like—so you can read and write SPIFFS files without any filesystem-specific API. This is provided via the VFS layer once SPIFFS is mounted. Partition-based: You define a SPIFFS partition in your partition table; the component uses that partition for all file data. Wear levelling: Helps extend flash lifetime by spreading writes across the partition. File system consistency checks: You can run an explicit integrity check (and repair) via the esp_spiffs_check() function; see Discussion: integrity check below. Format-on-mount option: format_if_mount_failed lets you automatically format the partition if mount fails (e.g. first boot or after erase). SPIFFS is flat meaning it doesn\u0026rsquo;t offer real directories—path segments become part of the file name. It reliably uses about 75% of the partition space. Under low space, garbage collection can take noticeable time; see the SPIFFS documentation for configuration and behavior. Application use cases # SPIFFS is often used for:\nWeb server assets: HTML, CSS, JavaScript for an ESP32 web server Configuration and calibration: Device config or calibration data in files, updated without reflashing the whole app Scripts and data: Lua scripts, JSON config, or small datasets read at runtime OTA and assets: Firmware metadata or asset packs updated separately from the main app Security note: The SPIFFS lightweight implementation does not offer data encryption. To keep sensitive data safe, ESP-IDF offers other storage components that support data encryption. These include FATFS, LittleFS, and NVS. A quick comparison of features can be found on the File System Considerations page in the ESP-IDF documentation. Basic example: mount, write, and read # The storage/spiffs example in ESP-IDF shows the minimal flow: register SPIFFS with VFS, write a file, rename it, then read it back. No special hardware is required; any board with a SPIFFS partition in the partition table will work.\nWhat the example does # Prepares a compile-time partition layout that includes a SPIFFS partition labeled storage. Calls esp_vfs_spiffs_register() to initialize SPIFFS, mount it, and register it with VFS at a path prefix (e.g. /spiffs). Creates a file with fopen and writes a line with fprintf. Renames the file (after checking for an existing destination with stat and removing it with unlink if needed). Opens the renamed file, reads the line back with fgets, and prints it to the console. Unregisters SPIFFS with esp_vfs_spiffs_unregister(). Partition size and label are defined in partitions_example.csv in the example. You can run it with idf.py -p PORT flash monitor. To erase the SPIFFS partition and start fresh, run idf.py erase-flash before flashing again.\nPrerequisites # A project with a partition table that includes a SPIFFS partition (see the example’s partitions_example.csv). No special hardware; the example runs on any supported target (ESP32, ESP32-C3, etc.). Step 1: Prepare partition table at compile time # Before mounting SPIFFS in code, make sure your build uses a partition table that contains a SPIFFS partition with the label used by your code (here: storage).\nIn idf.py menuconfig:\nGo to Partition Table. Set Partition Table to Custom partition table CSV. Set Custom partition CSV file to your file (for example, partitions_example.csv). The ESP-IDF example uses the following partitions_example.csv:\n# Name, Type, SubType, Offset, Size, Flags # Note: if you have increased the bootloader size, make sure to update the offsets to avoid overlap nvs, data, nvs, 0x9000, 0x6000, phy_init, data, phy, 0xf000, 0x1000, factory, app, factory, 0x10000, 1M, storage, data, spiffs, , 0xF0000, The key line for SPIFFS is:\nstorage, data, spiffs, , 0xF0000, At build time, ESP-IDF compiles this CSV into the partition table binary and flashes it with your app.\nStep 2: Include and configure # Include the SPIFFS/VFS header and set the partition label and mount path:\n#include \u0026#34;esp_vfs_spiffs.h\u0026#34; static const char *TAG = \u0026#34;example\u0026#34;; #define PARTITION_LABEL \u0026#34;storage\u0026#34; #define BASE_PATH \u0026#34;/spiffs\u0026#34; Step 3: Register SPIFFS with VFS # In app_main() (or after NVS/other init), fill the configuration and register:\nesp_vfs_spiffs_conf_t conf = { .base_path = BASE_PATH, .partition_label = PARTITION_LABEL, .max_files = 5, .format_if_mount_failed = true }; esp_err_t ret = esp_vfs_spiffs_register(\u0026amp;conf); if (ret != ESP_OK) { ESP_LOGE(TAG, \u0026#34;Failed to initialize SPIFFS (%s)\u0026#34;, esp_err_to_name(ret)); return; } Setting format_if_mount_failed to true formats the partition on first use or when mount fails, which is convenient for development.\nStep 4: Use standard file APIs # Once mounted, use C library functions with paths under BASE_PATH:\nFILE *f = fopen(\u0026#34;/spiffs/hello.txt\u0026#34;, \u0026#34;w\u0026#34;); if (f != NULL) { fprintf(f, \u0026#34;Hello World!\\n\u0026#34;); fclose(f); } // Later: open for read, rename with stat/unlink as needed, etc. All of this goes through VFS to the SPIFFS driver; no SPIFFS-specific read/write calls are needed.\nStep 5: Unregister when done # Before shutting down or if you need to remount:\nesp_vfs_spiffs_unregister(PARTITION_LABEL); The example also demonstrates getting partition info with esp_spiffs_info() and, optionally, running an integrity check with esp_spiffs_check() — we discuss that option and alternatives in Integrity check.\nComplete source code # The full example is in the ESP-IDF repository:\nesp-idf/examples/storage/spiffs For embedding files with SPIFFSgen in the build (an alternative to creating files only at runtime):\nesp-idf/examples/storage/spiffsgen Discussion: options in the example and alternatives # The example above uses a small set of SPIFFS and VFS options. This section walks through those choices and the alternatives the component offers so you can adapt them to your project.\nRegistration, base_path, and partition_label # The example registers SPIFFS with base_path = \u0026quot;/spiffs\u0026quot; and partition_label = \u0026quot;storage\u0026quot;. Those two values answer different questions: where the file data lives on flash, and how your application refers to it by path.\npartition_label — \u0026ldquo;Which region of flash?\u0026rdquo; (esp_partition) # Your partition table divides flash into named regions. Each region has a label (e.g. storage or spiffs). When you set partition_label to \u0026quot;storage\u0026quot;, the SPIFFS component uses the esp_partition API under the hood: it looks up the partition by that label and gets the offset and size of that region in flash. SPIFFS then uses that region exclusively for all file data. So partition_label is the link between your config and the physical flash layout. If you have two SPIFFS partitions (e.g. storage and assets), register each with its own label; each gets its own region of flash.\nAs an alternative, you can pass partition_label = NULL to use the first SPIFFS partition in the table (the example’s code can use NULL; the snippet above uses \u0026quot;storage\u0026quot; for clarity). Useful when you have only one SPIFFS partition and don’t care about the name.\nbase_path — \u0026ldquo;How do I name files in code?\u0026rdquo; (VFS) # The base_path (e.g. /spiffs) is the mount point in the VFS layer. VFS routes path-based calls to the driver that registered with that prefix. When you call fopen(\u0026quot;/spiffs/hello.txt\u0026quot;, \u0026quot;r\u0026quot;), VFS hands the request to the SPIFFS driver registered with base_path = \u0026quot;/spiffs\u0026quot;; the driver sees the relative part (hello.txt) and uses the partition it already knows from partition_label. So base_path is a naming convention: the “directory” under which all files for this SPIFFS instance appear. It doesn’t change where data is stored.\nAs an alternative, you can set base_path to any path that doesn’t clash with another mount point (e.g. /data, /assets). The example uses /spiffs by convention.\nHow they work together: partition_label selects which flash partition holds the data (via esp_partition); base_path selects which path prefix in VFS points to that data. Both are needed at registration so VFS can route requests and the driver can use the right partition.\nformat_if_mount_failed and max_files # The example sets format_if_mount_failed = true and max_files = 5.\nformat_if_mount_failed: If mount fails (e.g. unformatted or corrupted partition), the component will format the partition and try again. Convenient for development and first boot; you can set it to false in production if you prefer to handle mount failure yourself (e.g. call esp_spiffs_format() or esp_spiffs_check() and retry). max_files: Maximum number of files open at the same time. The example uses 5; increase this if your application opens more files concurrently. The esp_vfs_spiffs_conf_t struct has no other fields—only base_path, partition_label, max_files, and format_if_mount_failed.\nIntegrity check # SPIFFS can be corrupted if power is lost during a write. The component does not run an automatic integrity check at mount time; it exposes a function you call when you need it.\nWhat the example does: The storage/spiffs example can run esp_spiffs_check(partition_label) in two situations:\nOptional check on start: The example’s menuconfig (“SPIFFS Example” menu) has Perform SPIFFS consistency check on start (CONFIG_EXAMPLE_SPIFFS_CHECK_ON_START). When enabled, the example calls esp_spiffs_check(conf.partition_label) once after a successful mount, before any file I/O. Recovery when info is inconsistent: If esp_spiffs_info() reports used \u0026gt; total, the example calls esp_spiffs_check() as a recovery path (independent of the menuconfig option). esp_spiffs_check(partition_label) This function must be called manually on an already mounted partition. It scans the filesystem to repair corrupted files and clean up unreferenced pages (for example, after a power loss), returning ESP_OK, ESP_ERR_INVALID_STATE (if not mounted), or ESP_FAIL. Note that this check is expensive, requiring multiple full scans—on large partitions, it can introduce noticeable delays. Unlike some filesystems, esp_vfs_spiffs_conf_t does not include an automatic \u0026ldquo;check on mount\u0026rdquo; flag; you control when the check runs.\nAlternatives: In your own project you can: call esp_spiffs_check() after mount only when you want a boot-time check (like the example option); call it only when you detect a problem (e.g. used \u0026gt; total or after detected power loss); or run it as periodic maintenance. Trade-off: better recovery vs. longer, blocking boot on large partitions. The SPIFFS FAQ has more detail on when to run the check.\nPopulating the partition: SPIFFSgen # The example creates files only at runtime (e.g. with fprintf). To embed host files (HTML, config, assets) into the SPIFFS partition and flash them with the app, the recommended tool is SPIFFSgen (spiffsgen.py).\nspiffsgen.py is a write-only Python tool that builds a SPIFFS image from a host directory. It is part of the spiffs component and you can use it standalone or via the build system.\nStandalone:\npython spiffsgen.py \u0026lt;image_size\u0026gt; \u0026lt;base_dir\u0026gt; \u0026lt;output_file\u0026gt; The image can be flashed with esptool or parttool.py. Run python spiffsgen.py --help for optional arguments (page size, block size, etc.).\nBuild system:\nInvoke it from CMake so the image is built (and optionally flashed) with your app:\nspiffs_create_partition_image(\u0026lt;partition\u0026gt; \u0026lt;base_dir\u0026gt; [FLASH_IN_PROJECT] [DEPENDS dep dep ...]) Use the partition name from your partition table; image size is taken from the table. With FLASH_IN_PROJECT, idf.py flash will flash the SPIFFS image together with the app. The storage/spiffsgen example demonstrates this workflow.\nOther tools: mkspiffs can create and unpack SPIFFS images; use it when you need to unpack an image or when Python is not available. There is no built-in ESP-IDF build integration for mkspiffs. The SPIFFS documentation describes when to prefer SPIFFSgen vs mkspiffs.\nWhether files are created at runtime or embedded with SPIFFSgen, you use the same VFS file API (fopen, fread, etc.) to read and write them.\nConclusion # The SPIFFS component gives you a simple, partition-based filesystem for SPI NOR flash, with wear levelling and optional consistency checks. By registering SPIFFS with the VFS layer, you use standard C and POSIX file APIs for all read/write operations. The example shows the minimal mount–write–read flow; the discussion above outlines the options it uses and alternatives (partition_label/base_path, integrity check, SPIFFSgen for embedded files) so you can adapt SPIFFS to your project.\nLearn More # How to use custom partition tables on ESP32 — define partitions including SPIFFS Using Lua as ESP-IDF component with ESP32 — uses SPIFFS to store Lua scripts Resources # SPIFFS Filesystem (ESP-IDF documentation) Virtual Filesystem (VFS) Partition Tables storage/spiffs example storage/spiffsgen example spiffsgen.py in ESP-IDF ","date":"23 March 2026","externalUrl":null,"permalink":"/blog/2026/03/introducing-spiffs-component/","section":"Blog","summary":"Learn what the ESP-IDF SPIFFS component is, how it works with the VFS layer and standard C file APIs, and how to use the SPIFFSgen tool to embed files. This article is a practical guide with references to the official example.","title":"Introducing the SPIFFS component","type":"blog"},{"content":"","date":"23 March 2026","externalUrl":null,"permalink":"/authors/radek-tandler/","section":"Developer Portal Authors","summary":"","title":"Radek Tandler","type":"authors"},{"content":"","date":"23 March 2026","externalUrl":null,"permalink":"/tags/spiffs/","section":"Tags","summary":"","title":"SPIFFS","type":"tags"},{"content":"","date":"23 March 2026","externalUrl":null,"permalink":"/tags/storage/","section":"Tags","summary":"","title":"Storage","type":"tags"},{"content":"","date":"23 March 2026","externalUrl":null,"permalink":"/tags/tutorial/","section":"Tags","summary":"","title":"Tutorial","type":"tags"},{"content":" What\u0026rsquo;s New in ESP-IDF 6.0: The Next Step Forward # ESP-IDF 6.0 introduces improvements across the full development workflow, from easier installation and more flexible tooling to library updates, security changes, and broader hardware support. In this article, we\u0026rsquo;ll walk through the most important highlights of the release and point out a few key breaking changes to keep in mind when upgrading from v5.x.\nUpgrading from v5.x?\nESP-IDF 6.0 includes breaking changes: removed legacy drivers, compiler warnings treated as errors, and a new crypto API layer. See the Breaking Changes section before upgrading.\nWe have prepared a Migration Guide to help you through the transition.\nHere are the key changes and improvements.\nGetting Started Just Got Easier: ESP-IDF Installation Manager # For new ESP-IDF users, setting up a development environment is now easier than ever. The new ESP-IDF Installation Manager (EIM) is a unified cross-platform tool that simplifies the entire setup process for ESP-IDF and your preferred IDE.\nEIM offers both a graphical interface for those who prefer visual workflows and a full-featured CLI for automation and CI/CD pipelines. Install it using familiar package managers, WinGet on Windows, Homebrew on macOS, or APT/RPM on Linux, and you\u0026rsquo;re ready to go.\nKey features include:\nMultiple version management: Install and switch between different ESP-IDF versions from a single dashboard Offline installation: Set up your environment in offline environments using pre-downloaded archives CI/CD integration: Headless installation mode and a GitHub Actions integration make automated builds straightforward Automatic prerequisites: On Windows, EIM detects and installs missing dependencies automatically, on Linux and macOS the package managers will take care of it Note that export.sh and its siblings is no longer needed, EIM replaces it with version-specific activation scripts, making environment setup consistent across all platforms.\nFor a full walkthrough of EIM\u0026rsquo;s features, see the EIM v0.8 release article or jump straight to the EIM documentation.\nSmaller and Faster: Picolibc Replaces Newlib # The default C library has changed from Newlib to Picolibc. Designed specifically for embedded systems, Picolibc offers a smaller memory footprint and better performance characteristics for resource-constrained devices. Benchmarks will vary depending on which functonality is used, and if Newlib or Newlib Nano is available in ROM on your chip, but for one such comparision see Newlib vs Picolibc comparison.\nFor most applications, this change is transparent, your code will compile and run without modification. If you encounter any issues, you can switch back to the Newlib implementation using the CONFIG_LIBC_NEWLIB Kconfig option.\nSecurity First: PSA Crypto API # ESP-IDF 6.0 upgrades MbedTLS to version 4.x and migrates cryptographic operations to the PSA Crypto API (Platform Security Architecture). This industry-standard API provides a cleaner, more portable interface for cryptographic operations and future-proofs your security implementations.\nApplications relying on legacy mbedtls_* cryptographic primitives will need to migrate to PSA Crypto APIs. While this requires changes, the resulting code is more maintainable and is compliant with security standards. The migration guide provides detailed guidance for updating your crypto implementations.\nBuild System and Tooling Improvements # ESP-IDF 6.0 brings several improvements to the build system and developer tooling, ranging from a next-generation CMake architecture to more flexible configuration management.\nNew CMake Build System (Preview) # ESP-IDF Build System v2 is now available in Technical Preview, introducing a more modern and flexible CMake-based architecture that addresses key limitations of the current v1 system while remaining backward compatible with most existing components. By aligning more closely with standard CMake practices, v2 makes it easier to integrate ESP-IDF into larger CMake-based projects and supports native CMake component definitions using familiar commands like add_library() and target_link_libraries().\nThe major architectural shift in v2 is the removal of v1\u0026rsquo;s early component evaluation phase, allowing components to be evaluated on demand and to declare dependencies conditionally using Kconfig variables. This enables more dynamic, configuration-driven builds and simplifies the overall build process by discovering and evaluating components in a single pass. While most v1 components will work unchanged, those relying on v1-specific behaviors may need updates.\nFor more details, including a migration guide, see the Build System v2 documentation. We welcome your feedback on the new build system at GitHub issue #17833.\nCustom idf.py Extensions # ESP-IDF v6.0 adds a new extension system for idf.py that lets you embed your own commands and tools right into the standard ESP-IDF CLI. Instead of juggling separate scripts, you can now define custom subcommands that behave like built-ins and use shared options such as --port or --build-dir.\nThere are two ways to extend it: component-based extensions (project-specific tools via an idf_ext.py file) and Python package extensions (reusable tools installed into your Python environment). Both approaches integrate seamlessly with idf.py --help and task ordering.\nFor more details, see the Developer Portal article Extending idf.py: Create custom commands for your ESP-IDF workflow.\nImproved Kconfig Default Value Handling # ESP-IDF v6.0 changes how default configuration values are tracked in sdkconfig. Previously, all values were written to sdkconfig without any distinction between user-set values and defaults, which could cause stale defaults to persist silently after a component update or Kconfig change.\nIn v6.0, the configuration system marks each default value with a # default: annotation in sdkconfig, allowing it to re-evaluate defaults dynamically when dependencies change, for example when running idf.py menuconfig. This means that if a Kconfig condition changes, the affected options will correctly reflect the new default rather than silently retaining the old one.\nFor a deep dive into how this works and what it means when upgrading components, see the full article on the Developer Portal Changes in the Configuration System in ESP-IDF v6: Default Values.\nBuild Configuration Presets # Managing multiple build configurations (development, production, size-optimized, testing) has traditionally meant remembering long idf.py command lines with multiple -D flags and -B directories. ESP-IDF v6.0 adds support for CMake Presets, letting you define all your build configurations declaratively in a CMakePresets.json file and reference them by name:\n# Before idf.py -B build_prod -D SDKCONFIG_DEFAULTS=\u0026#34;sdkconfig.defaults.production\u0026#34; build # After idf.py --preset production build Each preset can specify its own build directory, sdkconfig location, SDKCONFIG_DEFAULTS chain, and other build settings such as IDF_TARGET or additional CMake cache variables. This allows multiple configurations coexist without cross-contamination. A default preset can also be set for your shell session via the IDF_PRESET environment variable, which is handy for CI/CD pipelines.\nFor a full walkthrough including examples and migration tips, see the Developer Portal article Manage multiple ESP-IDF build configurations with ease.\nAI Integration: MCP Server # ESP-IDF 6.0 ships with a built-in MCP (Model Context Protocol) server, enabling AI assistants to interact directly with your ESP-IDF project through a standardized protocol. The server exposes tools for the most common development operations: building, flashing, setting the target, and cleaning, as well as resources to query the current project configuration, build status, and connected devices.\nThe recommended way to launch the server is via eim run, which uses the ESP-IDF Installation Manager (EIM) to spawn a new process with the ESP-IDF environment already set up:\neim run \u0026#34;idf.py mcp-server\u0026#34; This feature is particularly useful for IDE-based AI agents like VS Code Copilot or Cursor, which run outside an active ESP-IDF environment.\nTo add the MCP server to your IDE, use the following configuration:\nVS Code Cursor Add the following to your mcp.json:\n{ \u0026#34;servers\u0026#34;: { \u0026#34;esp-idf-eim\u0026#34;: { \u0026#34;command\u0026#34;: \u0026#34;eim\u0026#34;, \u0026#34;args\u0026#34;: [ \u0026#34;run\u0026#34;, \u0026#34;idf.py mcp-server\u0026#34; ], \u0026#34;env\u0026#34;: { \u0026#34;IDF_MCP_WORKSPACE_FOLDER\u0026#34;: \u0026#34;${workspaceFolder}\u0026#34; } } } } Add the following to your mcp.json:\n{ \u0026#34;mcpServers\u0026#34;: { \u0026#34;esp-idf-eim\u0026#34;: { \u0026#34;command\u0026#34;: \u0026#34;eim\u0026#34;, \u0026#34;args\u0026#34;: [ \u0026#34;run\u0026#34;, \u0026#34;idf.py mcp-server\u0026#34; ], \u0026#34;env\u0026#34;: { \u0026#34;IDF_MCP_WORKSPACE_FOLDER\u0026#34;: \u0026#34;${workspaceFolder}\u0026#34; } } } } The mcp feature must be installed via EIM. A dedicated developer portal article with a full walkthrough is coming soon.\nFor more information about how to install and use the MCP server, see IDF Programming Guide\nWi-Fi Enhancements # ESP-IDF 6.0 expands Wi-Fi capabilities with new proximity-based service discovery and improved WPA3 support, making it easier to build modern, standards-compliant wireless applications.\nUnsynchronized Service Discovery (USD) # ESP-IDF 6.0 adds support for Wi-Fi Aware Unsynchronized Service Discovery (USD), a lightweight proximity-based service discovery mechanism defined in the Wi-Fi Aware specification. Unlike the existing synchronized NAN support, where devices must first join a cluster and align discovery windows, USD lets devices advertise and find services by exchanging Wi-Fi Action frames directly, with no AP and no cluster synchronization required. Unlike synchronised NAN, USD protocol does not support NAN datapath.\nA Publisher broadcasts a service on all channels it supports and permitted by the regulatory domain. A Subscriber - which is typically stationed on a fixed channel - discovers the Publisher and the two devices can exchange communication payloads via Action frames. USD is well-suited for proximity-based discovery and short communication mechanisms such as device commissioning, configuration and status exchange. One of the primary use cases for USD is Wi-Fi based commissioning for Matter devices.\nNote that USD is marked as an experimental feature in v6.0. The existing synchronized NAN configuration has also been renamed (wifi_nan_config_t → wifi_nan_sync_config_t, CONFIG_ESP_WIFI_NAN_ENABLE → CONFIG_ESP_WIFI_NAN_SYNC_ENABLE) to cleanly separate the two modes, so check the migration guide if you use NAN today.\nWPA3 Compatible Mode # For access points that need to serve both WPA2 and WPA3 clients simultaneously, v6.0 adds a new wpa3_compatible_mode flag to wifi_ap_config_t and a disable_wpa3_compatible_mode flag to wifi_sta_config_t. When enabled, the AP advertises WPA3 SAE capabilities via RSN Override vendor IEs (per the Wi-Fi Alliance WPA3™ Specification Version 3.4) while continuing to accept WPA2-PSK connections. WPA3-capable clients which support RSN override (compatibility mode) negotiate SAE automatically; legacy clients connect as usual. On the station side, disable_wpa3_compatible_mode controls whether the device can connect to WPA3-Personal RSN override (compatibility mode) APs. This is a standards-based alternative to the existing WIFI_AUTH_WPA2_WPA3_PSK mixed mode for deployments that want cleaner WPA2→WPA3 migration\nSafe Bootloader OTA Updates # One of the most requested features for field-deployed devices is the ability to update the bootloader over-the-air. Traditionally, this has been a risky operation, if power is lost during the update, the device could become unbootable.\nESP-IDF 6.0 introduces recovery bootloader support on ESP32-C5 and ESP32-C61. On these chips, the ROM bootloader can fall back to a recovery partition if the primary bootloader fails to load. Before updating the bootloader, your application creates a backup in a dedicated recovery partition. If the update fails or power is lost mid-write, the device boots from the recovery bootloader instead of bricking.\nThe workflow is straightforward:\nEnable CONFIG_BOOTLOADER_RECOVERY_ENABLE and configure the recovery partition offset Define both primary and recovery bootloader partitions in your partition table Use the esp_https_ota APIs to download and install the new bootloader For chips without ROM-level recovery support, bootloader OTA is still possible but carries inherent risk, there\u0026rsquo;s no fallback if the final write is interrupted. The new partitions_ota example demonstrates both safe and unsafe update paths, along with OTA for the partition table and storage partitions.\nRelease Notes Database # Starting from v6.0, ESP-IDF release notes are published using our new release notes database. This provides:\nA better viewing experience for release notes The ability to compare releases and see all changes between them, helpful when planning an upgrade from an older version to v6.0 New Chip and Hardware Support # ESP-IDF 6.0 continues to expand hardware coverage, with two chips graduating to full support, two new chips getting preview support and several new silicon revisions across the portfolio.\nChip Status ESP32-C5 Newly fully supported (graduated from preview) ESP32-C61 Newly fully supported (graduated from preview) ESP32-H21 Preview ESP32-H4 Preview Breaking Changes: Know Before You Upgrade # ESP-IDF 6.0 is a cleanup release that removes deprecated functionality. Key changes include:\nLegacy drivers removed: ADC, DAC, I2S, Timer Group, PCNT, MCPWM, RMT, and Temperature Sensor legacy drivers have been removed. Migrate to the new driver APIs. Warnings as errors: Default compiler warnings are now treated as errors. Disable with CONFIG_COMPILER_DISABLE_DEFAULT_ERRORS if needed during migration. Component relocations: Several components have moved to the ESP Component Registry, including wifi_provisioning (now network_provisioning), cJSON, and esp-mqtt. Crypto API changes: Legacy MbedTLS crypto APIs are being phased out in favor of PSA Crypto. We highly recommend consulting the migration guide when upgrading from v5.x.\nGet Started with ESP-IDF 6.0 # ESP-IDF v6.0 is available now. We encourage you to try it out and share your feedback through GitHub issues.\nESP-IDF v6.0 Documentation Full Release Notes Migration Guide Conclusion # ESP-IDF 6.0 is out now. Whether you\u0026rsquo;re starting a new project or upgrading an existing one, we hope you find something useful and interesting in this release. As always—we\u0026rsquo;re excited to see what you\u0026rsquo;ll build with it.\n","date":"20 March 2026","externalUrl":null,"permalink":"/blog/2026/03/idf-v6-0-release/","section":"Blog","summary":"We\u0026rsquo;re excited to announce the long-awaited release of ESP-IDF 6.0! This article highlights the key changes and improvements not only to ESP-IDF itself, but also to the broader ESP-IDF tooling ecosystem, all designed to enhance your developer experience.","title":"Announcing ESP-IDF v6.0","type":"blog"},{"content":"","date":"20 March 2026","externalUrl":null,"permalink":"/tags/iot/","section":"Tags","summary":"","title":"IoT","type":"tags"},{"content":" VS Code Installation # Go to the VS Code download site Download and install the Linux version (.deb for Ubuntu) This guide uses the latest LTS version of Ubuntu, 24.04. Once the file is downloaded, check the file name (referred to as \u0026lt;file\u0026gt;.deb below)\nOpen the terminal (CTRL+ALT+T) and type:\nsudo apt install ./\u0026lt;file\u0026gt;.deb After installation, create a folder and try opening VS Code from the terminal:\nmkdir tmp cd tmp code . You should now see the VS Code interface\nVS Code may ask whether you trust the author of the folder. This is important when working with git repositories, but for now it doesn’t matter. Click “Yes.” Installing Prerequisites # To install and configure the ESP-IDF toolchain, you need to have Python and git installed.\nPython # To install the ESP-IDF toolchain, Python version 3.12 or higher is required.\nTo check your Python version:\nOpen a terminal (CTRL+ALT+T)\nType python3 --version\nThe result on Ubuntu 24.04 should be:\nespressif@Ubuntu24:~$ python3 --version Python 3.12.3 This satisfies the prerequisite.\nIf for some reason it doesn\u0026rsquo;t, you can follow this guide git # ESP-IDF development is based on git, the version control tool also used for Linux kernel development. git is the foundation upon which GitHub is built.\nTo install git:\nOpen a terminal (CTRL+ALT+T)\nUpdate the repositories:\nsudo apt-get update Install git:\nsudo apt-get install git Answer Y when prompted:\nespressif@Ubuntu24:~$ sudo apt-get install git Reading package lists... Done Building dependency tree... Done Reading state information... Done The following additional packages will be installed: git-man liberror-perl Suggested packages: git-daemon-run | git-daemon-sysvinit git-doc git-email git-gui gitk gitweb git-cvs git-mediawiki git-svn The following NEW packages will be installed: git git-man liberror-perl 0 upgraded, 3 newly installed, 0 to remove and 70 not upgraded. Need to get 4,806 kB of archives. After this operation, 24.5 MB of additional disk space will be used. Do you want to continue? [Y/n] Verify that git was installed correctly:\n\u0026gt; git --version \u0026gt; git version 2.43.0 ESP-IDF Prerequisites # To use the ESP-IDF toolchain, you need to install some additional tools.\nOn Ubuntu, you can install them all with the following command:\nsudo apt-get install git wget flex bison gperf python3 python3-pip python3-venv cmake ninja-build ccache libffi-dev libssl-dev dfu-util libusb-1.0-0 Next Steps # Continue with the next step.\n","date":"20 March 2026","externalUrl":null,"permalink":"/workshops/esp-idf-setup/installation-linux/","section":"Workshops","summary":"This guide outlines the preliminary steps to set up your work environment and follow the workshops.","title":"Linux prerequisites 🐧","type":"workshops"},{"content":"","date":"20 March 2026","externalUrl":null,"permalink":"/authors/marius-vikhammer/","section":"Developer Portal Authors","summary":"","title":"Marius Vikhammer","type":"authors"},{"content":"","date":"20 March 2026","externalUrl":null,"permalink":"/tags/release/","section":"Tags","summary":"","title":"Release","type":"tags"},{"content":" VS Code Installation # Go to the VS Code download site Download and install the Windows version This guide uses Windows 11. Once the .exe file is downloaded, double-click it and follow the installation steps. After installation, there are two ways to open VS Code:\nOpen VS Code from the Start menu Open VS Code from a folder Since it\u0026rsquo;s often useful to open the editor directly from a folder, we\u0026rsquo;ll use the second method.\nOpen VS Code from a Folder # Create a new folder called tmp Right-click inside the folder in File Explorer From the menu, select Show more options Click on Open with Code You should now see the VS Code interface VS Code may ask whether you trust the author of the folder. This is important when using git repositories, but for now it doesn’t matter. Click “Yes.” Installing Prerequisites # No additional prerequisites need to be installed. These will be handled automatically during the setup of the ESP-IDF extension.\nNext Steps # Continue with the next step.\n","date":"20 March 2026","externalUrl":null,"permalink":"/workshops/esp-idf-setup/installation-windows/","section":"Workshops","summary":"This guide outlines the preliminary steps to set up your work environment and follow the workshops.","title":"Windows prerequisites 🪟","type":"workshops"},{"content":" Introduction # In this guide, we\u0026rsquo;ll walk set up the development environment to work on projects based on the ESP-IDF toolchain.\nWe\u0026rsquo;ll use the open-source IDE VS Code and the ESP-IDF extension for VS Code, which allows you to configure the toolchain, build projects, and flash the memory of Espressif modules.\nIf you don\u0026rsquo;t have an Espressif development kit available, you can still complete all the steps in this guide except for the last one.\nFor the final step, you’ll need a physical board with an Espressif SoC, for example, the ESP32-S3-DevKitC-1.\nThe term ESP-IDF is used to refer to both the toolchain itself and the VS Code extension. In this guide, we\u0026rsquo;ll explicitly use ESP-IDF toolchain for the former and ESP-IDF extension for the latter. The guide is divided into 5 parts:\nInstalling VS Code and prerequisites Installing the ESP-IDF extension for VS Code Configuring the ESP-IDF toolchain via Espressif Installation Manager (EIM) Building the first project Flashing the module Installing VS Code and Prerequisites # This step depends on your operating system. Follow the appropriate guide below:\n🐧 Linux: Installing VS Code and prerequisites 🪟 Windows: Installing VS Code 🍎 macOS: Installing VS Code and prerequisites Installing the ESP-IDF Extension for VS Code # Once all prerequisites are installed, we can add the ESP-IDF extension to VS Code. Using the ESP-IDF extension, we\u0026rsquo;ll then install and configure the ESP-IDF toolchain.\nOpen VS Code\nClick the Extensions icon (four squares) on the left In the search bar, type esp-idf Click “Install” on the first result, ESP-IDF\nIf prompted, click “Accept and Install” Configuring the ESP-IDF Toolchain via EIM # Once the ESP-IDF extension is installed, we need to install the toolchain. This is done through the Installation Manager.\nOpen the Command Palette by pressing F1 and type\n\u0026gt; ESP-IDF: Open ESP-IDF Installation Manager Click on the drop down menu item\nWhen asked about the mirror, choose Github\nAfter a few seconds, the installation manager GUI will appear.\nClick on Easy Installation\nYou\u0026rsquo;ll be presented with a welcome screen. Click on Start Installation Choose the latest stable release (v5.5.3 as of today) Wait for the installation to finish. This will take some time. You can monitor the progress using the progress bar. Once finished, click on Go to Dashboard to verify the installation You should see v5.5.3 among the installed versions You can now close the Espressif Installation Manager GUI\nBuilding the First Project # Now that the extension and toolchain are installed, it’s time to test building a project. We’ll create a new project based on one of the examples included with the ESP-IDF toolchain.\nCreate a Project from an Example # Open the Command Palette (F1 or CTRL+SHIFT+P)\nType ESP-IDF: New Project and select it\nIn the dropdown menu, select ESP-IDF v5.5.3 In the New Project tab, expand the ESP-IDF Examples menu Expand get-started and choose hello_world\nClick Create project using template hello_world In the project details, choose the Espressif SoC you will be using (you can change it later if required) In the next screen, click Open project to open a new VS Code window with the newly created project You should now see the files for the hello_world example project in the right panel If you don’t see the files, make sure the first icon on the left (two overlapping sheets) is selected. Specify the Target # To build and flash the project to your Espressif module, you must tell the compiler which SoC you’re targeting.\nIn the previous step, we already chose the target, so no further steps are required.\nHowever, if you need to change the target, you can:\nOpen the command palette (F1 or CTRL+SHIFT+P) and type\nESP-IDF: Set Espressif Device Target In the following dropdown → select ESP32-S3 chip (via builtin USB-JTAG) Build the Project # Now, let\u0026rsquo;s build the project.\nOpen the command palette (F1 or CTRL+SHIFT+P) Type ESP-IDF: Build Your Project A terminal will open at the bottom showing build messages When the build finishes, you’ll see the memory usage summary If you see the summary screen, both the toolchain and extension were installed correctly.\nIf you have an Espressif development board, proceed to the next section to verify USB connectivity.\nFlashing the Module # Once the project is built, it’s time to flash the module. The ESP-IDF extension for VS Code provides the command: \u0026gt; ESP-IDF: Flash (UART) Your Project\nHowever, the most commonly used command is:\n\u0026gt; ESP-IDF: Build, Flash and Start a Monitor on Your Device This command not only builds and flashes the project to the device but also starts a serial monitor directly in the editor terminal.\nTo flash the module:\nSelect the port your development board is connected to Run the command: \u0026gt; ESP-IDF: Build, Flash and Start a Monitor on Your Device On Linux, you may need to add your user to the dialout group to access serial ports without administrator privileges:\nsudo usermod -a -G dialout $USER Remember to log out and log back in for the changes to take effect.\nDevelopment board ports # Modern Espressif development board, usually have two USB ports, called UART and USB (see picture below)\nThe UART port is connected to the UART pins of the Espressif SoC via a USB→UART bridge chip. The USB port is connected directly to D+ and D- pins of the Espressif SoC. To program the module, connect your computer to the UART port.\nSelect the port to which the development board is connected # Connect the board to your computer via USB If VS Code is closed, reopen it and open your project folder File → Open Folder or File → Open Recent Open the command palette and type: \u0026gt; ESP-IDF: Select Port to Use (COM, tty, usbserial) Select the port (Silicon Labs – the USB/UART bridge on the development board) The port name will now appear in the bottom status bar If your operating system doesn’t automatically detect the connected board, refer to the appropriate guide:\n🪟 Windows 🐧 Linux 🍎 macOS On Windows, it may be necessary to install the drivers for the USB-UART Bridge (CP2101N). You can download the driver here. After downloading, unzip the file and follow the installation steps using the Device Manager procedure. Flash the Module and Start the Monitor # Open the command palette and type: \u0026gt; ESP-IDF: Build, Flash and Start a Monitor on Your Device From the dropdown → select UART Wait for the flashing process to complete and for the monitor to start In the terminal, you’ll see the boot messages and the “hello world!” output If you see the message in the terminal, your setup is working correctly and you\u0026rsquo;re ready for the workshop and to start developing projects based on ESP-IDF.\nConclusion # In this guide, we covered how to install VS Code, the ESP-IDF extension, and the ESP-IDF toolchain. We also went through how to create, build, and flash a project to your development board. Your development environment is now ready to use.\n","date":"19 March 2026","externalUrl":null,"permalink":"/workshops/esp-idf-setup/","section":"Workshops","summary":"This guide outlines the preliminary steps to set up your work environment and follow the workshops.","title":"ESP-IDF workshop - Preliminary setup","type":"workshops"},{"content":"","date":"17 March 2026","externalUrl":null,"permalink":"/authors/aditya-patwardhan/","section":"Developer Portal Authors","summary":"","title":"Aditya Patwardhan","type":"authors"},{"content":"","date":"17 March 2026","externalUrl":null,"permalink":"/tags/compliance/","section":"Tags","summary":"","title":"Compliance","type":"tags"},{"content":"","date":"17 March 2026","externalUrl":null,"permalink":"/tags/esp32/","section":"Tags","summary":"","title":"Esp32","type":"tags"},{"content":" The RED Delegated Act is now in effect. If you\u0026rsquo;re selling wireless products in the EU market, you must demonstrate EN 18031 compliance — and the clock is ticking. Starting August 2025, all new products placed on the EU market need to meet these cybersecurity requirements. The RED DA will remain applicable until the Cyber Resilience Act (CRA) takes over in December 2027, after which the CRA will set the new baseline for cybersecurity compliance across the EU.\nThe compliance process typically involves weeks of manual documentation — mapping security features to standards, writing risk assessments, and preparing declarations of conformity. The RED DA Assessment Tool reduces this to a single guided session. Upload your ESP-IDF project files, answer a questionnaire (mostly pre-filled from your configuration), and download a complete, submission-ready compliance package.\nTry it now at red-da-assessment-tool.security.espressif.com\nWhat does the tool do? # The RED DA Assessment Tool is a web application that automates the self-assessment process for RED Delegated Act (EN 18031) compliance. It directly supports the Self-Declaration Using Espressif Templates pathway described in our RED DA compliance guide.\nHere\u0026rsquo;s what it handles for you:\nReads your ESP-IDF configuration and automatically maps security features to EN 18031 requirements Pre-fills the security questionnaire based on your sdkconfig.json — no need to manually look up what\u0026rsquo;s enabled Scans your SBOM for known vulnerabilities and structures the risk assessment Generates a complete compliance package — product risk assessment, EN 18031 mapping, technical specs, and a Declaration of Conformity template No installation required — just open your browser, sign in, and start your assessment.\nBefore You Start: What You\u0026rsquo;ll Need # Gather these files from your ESP-IDF project:\nRequired Files # sdkconfig.json - Your project\u0026rsquo;s configuration file project_sbom_report.json - Software Bill of Materials report product_info.json - Product information template (optional - you can upload this file or fill the form manually) Optional Files (Enhance Your Report) # Product images - Photos of your device, packaging, labels PCB schematics - Circuit diagrams and layout files How to Generate Required Files # If you don\u0026rsquo;t have these files yet, here\u0026rsquo;s how to create them:\nGenerate sdkconfig.json # # 1. Go to your project directory cd your_esp_idf_project # 2. Configure your project as per your requirements idf.py menuconfig # 3. Build your project (this generates sdkconfig.json) idf.py build # 4. The sdkconfig.json file will be available at: # project_name/build/config/sdkconfig.json Make sure to configure your project security settings in menuconfig before building to ensure accurate compliance assessment. Need a reference? You can download an example sdkconfig.json file.\nGenerate project_sbom_report.json # Follow these steps in your project directory:\n# 1. First go to your project directory cd your_esp_idf_project # 2. Build your project idf.py build # 3. Install the SBOM tool pip install esp-idf-sbom # 4. Create the SBOM file esp-idf-sbom create -o project_sbom.spdx build/project_description.json # 5. Generate the JSON report esp-idf-sbom check project_sbom.spdx --format json \u0026gt;\u0026gt; project_sbom_report.json This will generate the SBOM (Software Bill of Materials) report required for compliance assessment. Need a reference? You can download an example project_sbom_report.json file.\nCreate product_info.json (Optional) # Two ways to provide product information: You can either upload a product_info.json file or fill out the product details form directly in the tool. If you prefer to prepare the file in advance, you can download a product_info_template.json file (which contains detailed example content) or create your own with this basic structure:\nClick to expand product_info.json template { \u0026#34;manufacturer_name\u0026#34;: \u0026#34;Your Company Ltd.\u0026#34;, \u0026#34;manufacturer_address\u0026#34;: \u0026#34;Your full business address\u0026#34;, \u0026#34;equipment_model\u0026#34;: \u0026#34;ESP32-C3-WROOM-02\u0026#34;, \u0026#34;equipment_description\u0026#34;: \u0026#34;2.4 GHz Wi-Fi \u0026amp; Bluetooth LE IoT Module\u0026#34;, \u0026#34;hardware_version\u0026#34;: \u0026#34;V1.0\u0026#34;, \u0026#34;software_version\u0026#34;: \u0026#34;ESP-IDF v5.4.1\u0026#34;, \u0026#34;radio_equipment_name\u0026#34;: \u0026#34;ESP32-C3 Wi-Fi \u0026amp; Bluetooth LE Module\u0026#34;, \u0026#34;technical_documentation\u0026#34;: \u0026#34;Links to datasheets and technical docs\u0026#34;, \u0026#34;operational_environment\u0026#34;: \u0026#34;Indoor IoT applications, smart home devices\u0026#34;, \u0026#34;operating_conditions\u0026#34;: \u0026#34;-40°C to +85°C, 5% to 95% RH\u0026#34;, \u0026#34;radio_equipment_images\u0026#34;: \u0026#34;Description of product photos and layouts\u0026#34;, \u0026#34;pcb_schematics\u0026#34;: \u0026#34;Description of circuit designs and layouts\u0026#34;, \u0026#34;declaration_place\u0026#34;: \u0026#34;Your City, Country\u0026#34;, \u0026#34;signatory_name\u0026#34;: \u0026#34;Your Name\u0026#34;, \u0026#34;signatory_function\u0026#34;: \u0026#34;Your Title\u0026#34; } The downloadable template file contains more detailed example content to help guide you through each field. Step-by-step guide # Step 1: Sign in # Visit red-da-assessment-tool.security.espressif.com and sign in using your GitHub, Google, or Apple account. This is a one-time step — once signed in, you can access the tool directly on subsequent visits.\nSign in with your preferred account\nStep 2: Choose Your Starting Point # You have two options:\nStart New Assessment - Begin a fresh assessment Import Previous Session - Upload your previous assessment zip package to continue or modify an existing assessment Using Import Previous Session: If you completed an assessment before, you received a zip package with all your assessment data. Upload this zip file to:\nJump to any step to update specific information (company details, questionnaire answers, etc.) Generate updated reports with new information while keeping your previous work Create variations for similar products by modifying existing assessments RED DA Assessment Tool Home Page\nStep 3: Provide product details # This step combines your company information and file uploads on a single page.\nFill in company information # Whether you uploaded a product_info.json file or not, you can review and complete your company details:\nCompany name Business address Contact information Authorized representative details Upload Your Files # The same page has a drag-and-drop interface for uploading your files:\nUpload sdkconfig.json - Drag your configuration file to the upload area Upload project_sbom_report.json - Add your SBOM report Upload product_info.json (optional) - Skip this if you prefer to fill the form manually Add images (optional) - Upload product photos or PCB images You can upload files one at a time or all together. The tool will automatically recognize what each file is.\nNeed example files to get started quickly? You can download ready-to-use template files: sdkconfig.json, project_sbom_report.json, and product_info_template.json. These are pre-configured examples that you can customize with your actual product information and upload directly to the tool. Product Details Animation\nStep 4: Select applicable articles # Before diving into the security questionnaire, you need to identify which EN 18031 articles apply to your specific product. This is done by answering relevant questions about your product features and capabilities.\nThe tool will ask you about:\nYour product\u0026rsquo;s connectivity features Data handling capabilities User interaction methods Network communication protocols Security-sensitive functionalities Based on your answers, the tool determines which specific EN 18031 requirements are applicable to your device, ensuring you only address relevant compliance areas.\nStep 5: Complete the Security Questionnaire # The questionnaire is simple and straightforward. It already comes prefilled based on the sdkconfig.json file you uploaded, but you need to validate it carefully and answer all remaining questions.\nThe tool automatically:\nPre-fills answers based on your ESP-IDF security configuration Shows only questions relevant to your selected applicable articles Highlights any questions that need your attention While most answers are automatically filled, you must carefully review each one to ensure accuracy and complete any remaining questions that require manual input. Step 6: Vulnerability Assessment # In this section, you need to provide explanations for all known vulnerabilities against your project. This information is obtained from the project_sbom_report.json file that you uploaded.\nThe tool will:\nAutomatically identify vulnerabilities from your SBOM report Present each vulnerability with its details (CVE ID, severity, affected components) Require you to provide explanations for how each vulnerability is addressed or mitigated Allow you to document your risk assessment and mitigation strategies If no vulnerabilities are found in your SBOM report, this step will be skipped automatically. Vulnerability Assessment\nStep 7: Review and Download Your Compliance Package # After completing the vulnerability assessment, the tool generates your complete self-assessment documentation package. You can review it, go back to any previous step to make changes, regenerate, and download when ready.\nYour compliance package downloads as a comprehensive bundle containing:\nMain Assessment Report (ESP32-C3_RED-DA_Assessment_2025-11-01.xlsx):\nProduct Risk Assessment: Security risk analysis for Article 3.3(d) compliance EN 18031 Standards Mapping: Detailed compliance statements for each applicable requirement Technical Specifications: Complete device configuration and security features Declaration of Conformity Template: Ready for your signature and submission This package provides everything needed for the self-declaration pathway, as described in our compliance guide.\nDownload Compliance Package\nUnderstanding Your Self-Assessment Documentation # The generated compliance package aligns with the documentation requirements for RED DA self-assessment:\nProduct Risk Assessment # Identified security risks related to Article 3.3(d) network protection Risk mitigation strategies based on your ESP32 configuration Compliance mapping to EN 18031-1 requirements EN 18031 Standards Compliance # The tool automatically determines which EN 18031 standards apply based on your article selection:\nEN 18031-1:2024 for Article 3.3(d) - Network protection requirements EN 18031-2:2024 for Article 3.3(e) - Personal data protection requirements EN 18031-3:2024 for Article 3.3(f) - Financial fraud protection requirements Your compliance package includes:\nSecurity requirement category mapping (ACM, AUM, SUM, SSM, SCM, etc.) Evidence of how your ESP32 configuration meets each requirement Technical Specifications # Complete hardware and software configuration details Security features enabled in your ESP-IDF project Radio parameters and operational characteristics Declaration of Conformity Template # Pre-filled DoC template ready for your signature Compliant with EU regulatory format requirements Suitable for self-declaration submission Common Issues and Solutions # \u0026ldquo;Configuration file not recognized\u0026rdquo; # Make sure you\u0026rsquo;re uploading sdkconfig.json, not sdkconfig Verify the file was generated with a recent ESP-IDF version \u0026ldquo;Missing required information\u0026rdquo; # Check that your product_info.json has all required fields Ensure company information is complete \u0026ldquo;SBOM report parsing failed\u0026rdquo; # Your SBOM file might have multiple JSON objects - this is normal The tool handles this automatically, but very large files might take time \u0026ldquo;Some questions not pre-filled\u0026rdquo; # This is normal for custom configurations Review these sections carefully and fill in manually RED DA and the Cyber Resilience Act (CRA) # The RED Delegated Act is the current regulatory requirement, but it\u0026rsquo;s not the end of the road. The Cyber Resilience Act (CRA) — a broader EU regulation covering all products with digital elements — will become applicable in December 2027. Once the CRA takes effect, it will supersede the RED DA for cybersecurity requirements.\nWhat this means for you:\nNow through December 2027: RED DA (EN 18031) compliance is mandatory for wireless products in the EU From December 2027: The CRA will set the new cybersecurity baseline, with its own conformity assessment procedures Your RED DA documentation is still valuable: The security measures and documentation you prepare now will form a strong foundation for CRA compliance Starting your compliance journey now with the RED DA Assessment Tool puts you ahead — both for current market access and for the transition to the CRA.\nWhat happens next? # After generating your self-assessment documentation:\nReview your compliance package - Verify all technical details and risk assessments Sign the Declaration of Conformity - Complete the DoC template provided Maintain documentation - Keep all records for 10 years as required by regulation Apply CE marking - Mark your compliant products for EU market entry Monitor for updates - Ensure ongoing compliance with any firmware updates Some products may require Notified Body assessment if they allow users to choose not to set passwords, have compatibility issues with parental controls (toys/childcare), or handle financial transactions requiring additional authentication. Get Started # The RED DA Assessment Tool is available now. Upload your files, generate your compliance package, and get your ESP32 product ready for the EU market.\nStart your assessment at red-da-assessment-tool.security.espressif.com\nHave questions or feedback? Reach out to us through the Espressif Developer Portal.\n","date":"17 March 2026","externalUrl":null,"permalink":"/blog/2026/03/red_da_assessment_tool_overview/","section":"Blog","summary":"The RED DA Assessment Tool simplifies the process of achieving cybersecurity compliance for ESP32 devices in line with the EU\u0026rsquo;s EN 18031 standards. This article explains how the tool helps you gather, validate, and generate all necessary documentation for RED Delegated Act self-assessment, including uploading configuration and SBOM files, completing risk assessments, mapping technical requirements, and preparing a declaration of conformity—making self-declaration fast, accurate, and accessible for IoT developers.","title":"RED DA Assessment Tool: Streamline Your ESP32 Cybersecurity Compliance","type":"blog"},{"content":"","date":"17 March 2026","externalUrl":null,"permalink":"/tags/red-directive/","section":"Tags","summary":"","title":"RED Directive","type":"tags"},{"content":"","date":"17 March 2026","externalUrl":null,"permalink":"/tags/regulatory/","section":"Tags","summary":"","title":"Regulatory","type":"tags"},{"content":"","date":"16 March 2026","externalUrl":null,"permalink":"/authors/sachin-billore/","section":"Developer Portal Authors","summary":"","title":"Sachin Billore","type":"authors"},{"content":"","date":"16 March 2026","externalUrl":null,"permalink":"/tags/security/","section":"Tags","summary":"","title":"Security","type":"tags"},{"content":" Introduction to the Cyber Resilience Act (CRA) # The European Union’s Cyber Resilience Act (CRA) represents a fundamental shift in how cybersecurity is regulated for connected products placed on the EU market. Like the RED Delegated Act clarified cybersecurity expectations for radio equipment, the CRA establishes horizontal cybersecurity requirements for a broad range of digital products — including IoT devices and digital products built on ESP32 SoCs and modules, as well as related software frameworks (such as ESP-IDF), companion mobile applications, and associated cloud offering as part of the overall product solution.\nAs an EU Regulation, it becomes directly binding law across all Member States once it enters into force. The same legal text applies uniformly across the entire EU, ensuring consistent cybersecurity obligations in every country.\nFor manufacturers, this means the CRA creates a single, harmonized cybersecurity framework for the entire EU market. Product manufacturers can follow one common compliance plan for the entire EU instead of preparing different plans for each country.\nScope of the CRA # The CRA applies broadly to:\nHardware and software products with digital elements (e.g., smart home hubs, network-connected printers) IoT devices and connectivity modules (e.g., smart thermostats, Wi-Fi or BLE modules integrated into consumer devices) Embedded systems with network interfaces (e.g., industrial controllers, smart meters) Firmware and software components supplied with the product (e.g., device operating systems, companion mobile applications provided with the device and cloud deployment) Products already regulated under sector-specific EU frameworks (e.g., medical devices, automotive under UNECE, aviation) may have partial or full exemptions where equivalent cybersecurity requirements already exist.\nFor typical ESP32-based designs — such as smart home devices, industrial sensors, wearables, gateways, and consumer IoT products — the CRA is applicable.\nCRA Timeline # The CRA was politically agreed in 2023 and has entered into force in December 2024.\nKey milestones:\nEntry into force: 10 December 2024 (20 days after publication in the Official Journal of the EU) Vulnerability reporting obligations apply from: 11 September 2026 (21 months after entry into force) Full application of core CRA requirements from: 11 December 2027 (36 months after entry into force) Manufacturers placing products on the EU market should begin gap analysis and implementation planning early.\nEssential CRA Requirements # The CRA defines essential cybersecurity requirements that manufacturers must meet before placing products on the EU market. These obligations extend beyond firmware design. They impact provisioning flows, lifecycle management, update strategy, documentation, and post-market processes.\nCybersecurity Requirements for Products with Digital Elements # Annex I Part I of the CRA defines a set of baseline cybersecurity requirements that must be implemented in the design and development of products with digital elements. In simple terms, manufacturers must ensure that products are built with security in mind from the beginning.\nKey high-level requirements include:\nSecure-by-design and secure-by-default development Cybersecurity risk assessment at product level Protection against unauthorized access and misuse Secure update mechanisms Vulnerability handling and coordinated disclosure processes Data protection and minimization principles Logging and monitoring capabilities (where relevant) Transparency obligations (security documentation and instructions) Vulnerability Handling Requirements # Annex I PART II of the CRA also defines requirements for how manufacturers must handle vulnerabilities discovered during the product lifecycle.\nManufacturers must establish processes to identify, manage, and remediate vulnerabilities affecting their products. In particular, the CRA introduces two reportable security conditions:\n- Actively exploited vulnerability – a vulnerability that is currently being exploited in the product\n- Severe incident – a security incident that significantly impacts the security of a product or its users\nTo address these situations, manufacturers are expected to:\nMaintain a vulnerability handling and coordinated disclosure process Monitor and assess vulnerabilities reported by researchers, customers, or internal teams Provide vulnerability fixes and security updates for the declared support period of the product Inform users about available security updates and mitigation measures Maintain communication channels for vulnerability reporting Establish processes to assess and report actively exploited vulnerabilities and severe incident Submit reports through the Single Reporting Platform (SRP) designated under the CRA. The SRP forwards the notifications to ENISA and the relevant national CSIRTs and market surveillance authorities, ensuring coordinated incident handling across the EU Follow CRA vulnerability notification timelines: For more details on managing security lifecycle in ESP32 products, please see the related blog.\nCRA Compliance Process # The CRA introduces a structured conformity assessment framework.\nStep 1: Product Classification # Under the CRA (see Annex III \u0026amp; Annex IV), products are categorized as:\nDefault (non-critical) products Important products (Class I and Class II) Critical products (subject to stricter conformity assessment) Most ESP32-based IoT products are expected to fall under the Default or Important Class I category, depending on functionality and risk profile.\nStep 2: Conformity Assessment # Manufacturers must:\nPerform cybersecurity risk assessment Implement required technical and organizational measures Prepare technical documentation Draft an EU Declaration of Conformity Affix CE marking (including CRA compliance) Certain product categories may require third-party conformity assessment by a Notified Body.\nCRA Product Classes and Compliance Process # Step 3: Post-Market Obligations # Compliance does not end at market entry. Manufacturers must:\nMonitor vulnerabilities Issue security updates Maintain vulnerability handling procedures Notify ENISA of actively exploited vulnerabilities The CRA establishes lifecycle-based cybersecurity accountability.\nObligations: OEM vs. Platform Vendor # OEM (Product Manufacturer) Obligations # The OEM placing the final product on the EU market is legally considered the manufacturer under the CRA. As per CRA Article 13 and Article 14, manufacturers are responsible for:\nConducting product-level cybersecurity risk assessment Ensuring compliance with the CRA essential cybersecurity requirements Maintaining vulnerability management and disclosure processes Providing required CRA compliance and technical documentation (including user cybersecurity information, support period, update policy, and vulnerability contact) Defining support period and update policy Preparing technical documentation and EU Declaration of Conformity Even when using certified modules or open-source frameworks, responsibility for final product compliance remains with the OEM.\nPlatform Vendor Obligations # Platform vendors supply components, platforms, or software frameworks that are integrated by manufacturers into final products. While the OEM placing the product on the EU market remains the legal manufacturer, platform vendors are expected to support the security posture of the ecosystem.\nTypical responsibilities of a platform vendor include:\nDesigning hardware and software platforms with built‑in security capabilities Providing documentation of available security features and recommended secure configurations Maintaining a vulnerability handling and disclosure process for the platform Informing downstream manufacturers about vulnerabilities that may affect their products Providing security update or vulnerability fixes for supported platform components Publishing security advisories and guidance when vulnerabilities are identified These practices help manufacturers integrate the platform securely and meet their CRA obligations.\nHow Espressif Will Support OEM Customers for CRA Compliance # Espressif is committed to supporting customers in meeting CRA cybersecurity requirements across the full product lifecycle — from secure design to post-market vulnerability management.\nCybersecurity Requirements # Espressif provides platform capabilities and guidance that help OEMs address CRA essential cybersecurity requirements (Annex I Part I) across design, development, and deployment:\nSecure hardware capabilities hardware root-of-trust, secure boot, flash encryption, secure key storage (eFuse), and cryptographic accelerators and other proprietary security peripherals to provide a secure hardware foundation for the product\nSecure software framework (ESP-IDF) as an open-source, actively maintained platform with regular security patches, secure OTA update mechanisms, industry-standard cryptographic libraries, and coordinated vulnerability disclosure\nDocumentation and compliance guidance including security application notes, production configuration guidelines, reference architectures for secure provisioning, and alignment with CRA requirements and future harmonized standards\nCollaboration and customer support including secure configuration guidance, lifecycle management best practices, and support for certification activities\nEspressif maintains a comprehensive product security program. More details please refer Espressif Product Security page.\nVulnerability Management # Espressif provides processes, supported by transparent mechanisms and tools, to help OEMs implement vulnerability handling requirements (Annex I Part II) aligned with CRA:\nSBOM (Software Bill of Materials) support to track third-party components and assess vulnerability impact\nESP-IDF Security Dashboard to monitor vulnerabilities, affected components, and fixes\nEspressif Security Incident Response Process with coordinated disclosure practices and publish security advisories\nLong-Term Support (LTS) releases with sustained security updates and maintenance over defined support lifecycles, aligned with Espressif support policy and defined maintenance periods\nSecure OTA update mechanisms to enable authenticated, integrity-protected, and reliable delivery of security patches throughout the product lifecycle\nFor additional details on vulnerability management and the security lifecycle for ESP32 products, see the related blog.\nFinal Thoughts # The Cyber Resilience Act represents a structural evolution in EU product regulation. Cybersecurity is no longer optional or market-driven — it is a legal requirement spanning the entire product lifecycle.\nFor OEMs building on ESP32 platforms, early preparation is critical:\nConduct a gap analysis Define update and vulnerability handling processes Enable hardware security features in production Maintain comprehensive technical documentation Espressif Systems remains committed to delivering secure SoCs, secure software frameworks, and transparent security practices to help customers confidently place CRA-compliant products on the EU market.\nCybersecurity is not just regulatory compliance — it is product quality, customer trust, and long-term sustainability.\nFor assistance, customers can contact sales@espressif.com.\nFrequently Asked Questions (FAQ) # Q1: Does the CRA apply only to connected IoT devices?\nA: No. The CRA applies to all \u0026ldquo;products with digital elements,\u0026rdquo; which includes hardware, embedded software, standalone software, and digital services supplied as part of a product solution.\nQ2: When will harmonized standards supporting the CRA be available?\nA: Most harmonized standards expected to start publishing by end of the year 2026.\nQ3: Should a product comply with both the CRA and RED Delegation Act after CRA comes into the force?\nA: The CRA will also apply to the same categories of radio equipment currently covered by the RED DA. These products must follow RED DA cybersecurity rules if placed on the market between 1 August 2025 and December 2027 and will follow CRA rules if placed on the market from December 2027 onward. Even after the RED DA is repealed, market surveillance will continue to check compliance for products sold during that earlier period.\nQ4: For how long must a manufacturer provide security updates?\nA: Manufacturers must provide security updates for the declared support period, aligned with the product’s expected lifetime. As a general rule, this period should be at least 5 years from when the product is placed on the market, unless a shorter period is justified by the product’s intended use or lifecycle. The support period and update commitments must be clearly communicated to users at the time of purchase.\nQ5: Do products already placed on the market need to comply with the CRA?\nA: Products placed on the EU market before the CRA’s full application date (11 December 2027) are generally not retroactively affected. Products placed on the market after that date must fully comply with the CRA requirements. However, any product placed on the market after 11 September 2026 must already follow the vulnerability reporting obligations under Article 14 of the CRA.\nQ6: How should OEMs handle vulnerabilities in ESP32-based products?\nA: OEMs should establish a structured vulnerability management process aligned with CRA requirements. This includes monitoring Espressif security advisories and the ESP-IDF Security Dashboard, assessing impact using SBOM data, applying fixes or mitigations, and deploying updates through secure OTA mechanisms. OEMs should also maintain internal tracking, coordinate disclosure where required, and ensure timely reporting of actively exploited vulnerabilities or severe incidents in line with CRA Article 14 obligations.\nReferences # Cyber Resilience Act (Regulation (EU) 2024/2847) Cyber Resilience Act implementation - Frequently asked questions ","date":"16 March 2026","externalUrl":null,"permalink":"/blog/2026/03/esp32-cra-compliance/","section":"Blog","summary":"The EU Cyber Resilience Act introduces mandatory cybersecurity requirements for products with digital elements placed on the EU market. This blog outlines what the CRA means for ESP32-based products, the obligations for OEM manufacturers, and how Espressif will support customers in achieving compliance.","title":"Understanding the EU Cyber Resilience Act (CRA)","type":"blog"},{"content":"","date":"5 March 2026","externalUrl":null,"permalink":"/authors/mahavir-jain/","section":"Developer Portal Authors","summary":"","title":"Mahavir Jain","type":"authors"},{"content":"The world of connected devices is evolving rapidly, and so are the expectations. With regulations like the EU Cyber Resilience Act (CRA) coming into effect, the industry is shifting its focus from just delivering products to also maintaining them throughout their lifecycle.\nFor product manufacturers, this presents a new challenge: How do we build firmware that is not only secure at launch but remains compliant for years? This post explores how the ESP32 ecosystem supports this lifecycle through specific tools, LTS branches, and vulnerability management strategies.\nContinuous Security # Continuous vigilance is now a regulatory requirement. As threats evolve, so must your firmware. Under emerging regulations like the CRA, it is not enough to launch with secure firmware — you must ensure:\nVulnerabilities are identified throughout the device lifecycle. Fixes are promptly delivered via secure OTA updates. Firmware remains actively maintained and supported. To support developers on this path, Espressif maintains a transparent posture through its vulnerability management processes.\nEspressif\u0026rsquo;s Approach to Vulnerability Management # Transparency is a core part of Espressif\u0026rsquo;s security posture. When vulnerabilities are discovered, Espressif follows a well-defined Security Incident Response Process to assess, communicate, and remediate issues promptly.\nEspressif encourages coordinated vulnerability disclosure and maintains strict confidentiality during the investigation and remediation process. Public advisories are published on the official website or respective software framework repository (e.g., ESP-IDF Repository) as applicable. But how can a developer quickly determine if their specific device is affected?\nKnow Your Exposure: Security Dashboard \u0026amp; SBOM # Use the ESP-IDF Security Dashboard — a public vulnerability database that maps all known CVEs to their impacted ESP-IDF versions. This dashboard is your go-to for:\nQuickly identifying affected releases Tracking patched versions Performing periodic firmware audits While the dashboard provides visibility into known ESP-IDF vulnerabilities, understanding your full exposure requires a complete inventory of your firmware components. The esp-idf-sbom tool generates a Software Bill of Materials (SBOM) for your project, enabling you to cross-reference your actual dependencies against the dashboard data. For a detailed guide on generating and managing SBOMs, see the Software Bill of Materials blog post.\nThis visibility is essential for ongoing vulnerability management required under CRA, RED-DA and similar global frameworks. Once a vulnerability is identified via the dashboard, the next step is obtaining a stable, secure patch.\nLeveraging Long-Term Support (LTS) # Espressif helps maintaining the product lifecycle through a clearly defined support policy that includes:\nLong-Term Support (LTS) branches: Receive critical security fixes for at least 30 months. Security-Only maintenance: Past the feature freeze, only vulnerability patches are delivered to ensure continued protection. Transparent release cadence: The ESP-IDF version table helps you plan your maintenance and upgrades confidently. Shipping with an LTS version means building on a foundation designed for long-term regulatory compliance. These fixes, however, are only effective if they can be reliably deployed to devices already in the field.\nThe Role of Over-the-Air (OTA) Updates # Even if the product is free from any known vulnerability, new vulnerabilities may be discovered later. An effective Over-the-Air (OTA) update mechanism is the primary defense for devices in the field, acting as the delivery vehicle for the patches provided in the LTS branches.\nESP-IDF includes the esp_https_ota component, which supports:\nSecure Upgrades: Using HTTPS and digital signatures. Rollback Protection: Preventing the device from being downgraded to a vulnerable version. Anti-rollback: Ensuring that a device cannot be updated to an older, insecure firmware version. For a deep dive into the OTA updates framework internals including partition layout, rollback, and anti-rollback mechanisms, see the OTA Updates Framework blog post.\nImplementing these features ensures that when a patch is ready, it can be deployed safely and reliably.\nSecure Product Lifecycle in Practice # To help your organization stay compliant and build resilient products, you may consider this security maintenance loop:\nPre-Launch: Verify Before You Ship # Run a final security audit using esp-idf-sbom to generate an up-to-date SBOM. Check against known CVEs for the selected ESP-IDF version using the security dashboard. Confirm no known vulnerabilities are present in your release firmware. Post-Launch: Monitor and Mitigate # Periodically scan the SBOM and compare against the latest ESP-IDF security dashboard data. When a vulnerability is found, roll out secure OTA update using secure update mechanisms supported by ESP-IDF. Leverage LTS branches for critical patches without needing major upgrades. Maintain Compliance Across the Lifecycle # Continue assessments and updates throughout the support period of the product. Maintain your SBOM, overall Vulnerability Disclosure Program (VDP), update policy, and remediation plan — regulatory bodies will look for these during audits. For detailed guidance on meeting RED-DA (EN 18031) requirements, refer to the compliance guide series: Part 1 and Part 2. Conclusion # Security compliance requires ongoing discipline across the entire lifecycle of product.\nBy using ESP-IDF\u0026rsquo;s long-term support policy, staying updated via the vulnerability dashboard, and embracing secure OTA mechanisms, you\u0026rsquo;re not just protecting your devices — you\u0026rsquo;re building trust, resilience, and regulatory readiness into every product you ship.\nEspressif\u0026rsquo;s commitment to security extends beyond software. Alignment with programs like PSA Certified and the CSA Product Security Certification further validates the security foundations available to product developers in the ESP32 ecosystem.\nFor questions about product security or compliance readiness, please browse through our Product Security Portal or reach out to us at sales@espressif.com\n","date":"5 March 2026","externalUrl":null,"permalink":"/blog/2026/03/esp32-security-updates/","section":"Blog","summary":"This article explains how manufacturers can use the ESP32 ecosystem to build and maintain secure firmware over time, especially in light of new regulations like the EU Cyber Resilience Act. It highlights tools such as vulnerability dashboards, Long-Term Support branches, and secure OTA updates to ensure ongoing compliance and device security.","title":"Staying Ahead with ESP32 Security Updates","type":"blog"},{"content":"","date":"2 March 2026","externalUrl":null,"permalink":"/tags/eim/","section":"Tags","summary":"","title":"EIM","type":"tags"},{"content":" Introducing ESP-IDF Installation Manager v0.8 # The ESP-IDF Installation Manager (EIM) is a cross-platform tool designed to simplify the installation and management of the Espressif IoT Development Framework. Version 0.8 introduces several notable enhancements, and in this article we will focus on:\nNative package manager EIM installation methods ESP-IDF offline installation Improved ESP-IDF environment activation CI/CD integration Version management EIM addresses a common pain point in embedded development: configuring toolchains and dependencies across different operating systems. Whether you\u0026rsquo;re a developer working on a single project or part of a team requiring reproducible builds, EIM provides a consistent experience across Windows, macOS, and Linux.\nEIM installation methods # EIM 0.8 offers multiple installation options to suit different workflows and preferences.\nPackage Manager Installation (Recommended) # The simplest way to install EIM is through your platform\u0026rsquo;s native package manager.\nWindows (winget) macOS (brew) Linux (deb) Linux (rpm) # Install GUI version winget install Espressif.EIM # Install CLI version only winget install Espressif.EIM-CLI # First add the EIM tap brew tap espressif/eim # Install GUI version brew install --cask eim-gui # Or install CLI version only brew install eim # Add the EIM APT repository echo \u0026#34;deb [trusted=yes] https://dl.espressif.com/dl/eim/apt/ stable main\u0026#34; | \\ sudo tee /etc/apt/sources.list.d/espressif.list # Update package lists sudo apt update # Install CLI version sudo apt install eim-cli # Or install GUI version sudo apt install eim # Download and install the RPM repository configuration sudo dnf install https://dl.espressif.com/dl/eim/rpm/eim-repo-latest.noarch.rpm # Install CLI version sudo dnf install eim-cli # Or install GUI version sudo dnf install eim Portable Binary Installation # For users who prefer self-contained binaries or lack package manager access, visit the EIM downloads page for platform-specific binaries and detailed installation instructions.\nESP-IDF offline installation # For air-gapped environments, networks with restricted access, or simply when you want the fastest and most reliable installation experience, EIM supports fully offline installation through pre-built archives.\nPre-packaged offline archives for every supported ESP-IDF version and platform are available at https://dl.espressif.com/dl/eim/?tab=offline.\nDownload the appropriate archive for your platform and ESP-IDF version, then install using:\n# Install from a downloaded archive eim install --use-local-archive /path/to/archive.zip Offline installation is also available directly through the GUI for users who prefer a visual interface.\nWhy choose offline installation?\nFastest method: Skip all downloads and verification steps—everything is already included Most reliable: No network issues, no server timeouts, no corrupted downloads Tested and verified: Each archive is pre-built and tested before publication Fail-safe solution: When other installation methods encounter issues, offline archives almost always succeed In areas with restricted or slow Internet: Windows users should consider using offline archives for the most consistent experience. This method is particularly valuable for:\nIndustrial environments with restricted network access CI/CD runners in private networks Team environments requiring consistent tool versions Users in regions with network connectivity challenges Improved ESP-IDF environment activation # Traditional ESP-IDF installation methods used install.sh and export.sh scripts from the IDF repository. EIM replaces these with a modern, cross-platform approach.\nInstallation is Now Simpler # The install.sh script from the ESP-IDF repository is no longer needed. EIM handles all toolchain and dependency installation automatically through the commands described above.\nActivation Scripts Replace export.sh # The export.sh script has been replaced by version-specific activation scripts. After installing ESP-IDF with EIM, activate the environment by sourcing the activation script:\n# Activate a specific ESP-IDF version source ~/.espressif/tools/activate_idf_v5.3.2.sh To find the activation script path for any installed version, use:\neim select This command displays all installed versions along with their activation script paths.\nOpening the IDF Shell # Across all platforms, you can open the IDF Shell from the EIM GUI: go to the Version Manager view and click “Open IDF Shell” next to the version you want. This launches a terminal with the ESP-IDF environment already activated.\nOn Windows, EIM also adds an IDF Shell shortcut to your desktop and an entry in the Windows Terminal dropdown menu for quick access.\nCI/CD Integration # EIM enables seamless automation in CI/CD pipelines, allowing you to install ESP-IDF and set up projects consistently across different environments.\nHeadless installation # The EIM supports headless mode for automated installations. Actually the install command runs in non-interactive (headless) mode by default. You can configure params of the headless instllation by CLI commands like:\n# Install specific version eim install -i v5.3.2 # Custom installation path eim install -p /opt/esp-idf or if this gets too complex for your need you can use configuration file. All the detailed information about this can be found in the documentaion.\nGitHub Actions # For GitHub workflows, use the official install-esp-idf-action for GitHub workflows:\nsteps: - uses: actions/checkout@v4 - name: Install ESP-IDF uses: espressif/install-esp-idf-action@v1 with: version: \u0026#34;v5.0\u0026#34; path: \u0026#34;/custom/path/to/esp-idf\u0026#34; tools-path: \u0026#34;/custom/path/to/tools\u0026#34; Docker Integration # For Docker and containerized build environments, you can find comprehensive examples in the Headless Usage documentation.\nCustom Repository Configuration # For organizations using ESP-IDF forks with custom modifications:\n# For GitHub repositories eim install -i v5.3.2 --repo-stub my-github-user/my-custom-idf # For GitLab or self-hosted repositories eim install -i v5.3.2 --mirror https://gitlab.example.com --repo-stub my-gitlab-user/my-custom-idf Version Management # EIM makes it easy to manage multiple ESP-IDF versions on a single system. Switch between versions instantly without reinstalling tools.\nYou can quickly select your preferred ESP-IDF version from the GUI, as illustrated in the image below.\nDocumentation and Resources # EIM Documentation: https://docs.espressif.com/projects/idf-im-ui/en/latest/ EIM Repository: https://github.com/espressif/idf-im-ui EIM Downloads: https://dl.espressif.com/dl/eim/ ESP-IDF Documentation: https://docs.espressif.com/projects/esp-idf/en/latest/ Conclusion # EIM 0.8 simplifies ESP-IDF installation across all major platforms through native package managers, supports offline deployments for restricted environments, and integrates seamlessly with CI/CD pipelines. Whether you\u0026rsquo;re setting up a new development machine or configuring automated builds, EIM provides a consistent and reliable installation experience.\n","date":"2 March 2026","externalUrl":null,"permalink":"/blog/2026/03/esp-idf-installation-manager/","section":"Blog","summary":"The ESP-IDF Installation Manager (EIM) v0.8 introduces simplified installation across Windows, macOS, and Linux through native package managers. This article covers the new release features, installation methods, offline capabilities, and headless usage for CI/CD pipelines.","title":"ESP-IDF Installation Manager v0.8: Streamlined Setup for ESP-IDF Development","type":"blog"},{"content":"","date":"2 March 2026","externalUrl":null,"permalink":"/tags/esp-idf-tool/","section":"Tags","summary":"","title":"ESP-IDF Tool","type":"tags"},{"content":"","date":"2 March 2026","externalUrl":null,"permalink":"/tags/installation/","section":"Tags","summary":"","title":"Installation","type":"tags"},{"content":"","date":"2 March 2026","externalUrl":null,"permalink":"/authors/petr-gadorek/","section":"Developer Portal Authors","summary":"","title":"Petr Gadorek","type":"authors"},{"content":"","date":"18 February 2026","externalUrl":null,"permalink":"/tags/community-software/","section":"Tags","summary":"","title":"Community Software","type":"tags"},{"content":"","date":"18 February 2026","externalUrl":null,"permalink":"/tags/esp-idf-component/","section":"Tags","summary":"","title":"ESP-IDF Component","type":"tags"},{"content":"","date":"18 February 2026","externalUrl":null,"permalink":"/tags/gpio/","section":"Tags","summary":"","title":"GPIO","type":"tags"},{"content":" Introduction # Buttons are fundamental input elements in embedded systems, yet handling them properly requires careful attention to debouncing, event detection, and timing. Today, we\u0026rsquo;re excited to introduce the button component, a robust and feature-rich button driver for ESP-IDF that simplifies button handling in your projects.\nThe button component provides a comprehensive solution for managing physical buttons in your ESP32 projects, supporting both GPIO-based buttons and ADC-based button matrices.\nThe button component is one of many components available on the ESP component registry.\nThe ESP Component Registry is a centralized platform that hosts reusable software components for ESP-IDF projects. It simplifies development by providing pre-built, tested libraries that can be easily integrated into an application, helping developers accelerate their projects by leveraging community‑tested solutions. Key Features # The button component offers several powerful features:\nMultiple Button Types: Support for GPIO buttons and ADC button matrices Event Detection: Comprehensive event handling including press, release, long press, and repeat press Debouncing: Built-in software debouncing to eliminate false triggers Low Power Support: Optimized for battery-powered applications Callback System: Easy-to-use callback mechanism for button events Thread-Safe: Safe to use in multi-threaded applications Rich Event Types: Supports 11 different button events including: Button pressed, released, and press repeat Single click, double click, and multiple click detection Long press start, hold, and release events Press repeat done and press end notifications Application Examples # The button component enables developers to create responsive and reliable button-based interfaces across various use cases:\nSmart Light Controls: Implement single click for on/off, double click for brightness adjustment, and long press for color selection Device Menu Navigation: Use button events to navigate through device settings and menus with intuitive multi-tap interactions IoT Gateway Configuration: Trigger Wi-Fi provisioning mode with a long press, or reset settings with specific button combinations Wearable Interfaces: Handle button inputs in space-constrained devices with multiple functions mapped to single button Industrial Control Panels: Implement fail-safe button handling with debouncing for reliable machine control Home Automation Hubs: Manage complex automation scenes with simple button interactions and customizable timing Basic Example # Here\u0026rsquo;s a practical example demonstrating how to set up the button component with GPIO button handling. We\u0026rsquo;ll break it down into steps to understand each part.\nThis example creates a button application that detects multiple button events on GPIO pin 9. The code initializes the button hardware, configures timing parameters for different press types, and registers callback functions that execute when specific button events are detected. When you interact with the button, the appropriate callback function is triggered, logging the event type to the console for monitoring and debugging purposes.\nThis example uses the ESP32-C3-DevKit-RUST-2 development board. GPIO pin 9 is the button pin on this board, but you can adapt the GPIO pin number to match your specific hardware configuration. Hardware # The ESP32-C3-DevKit-RUST-2 board features a built-in button connected to GPIO9. This button is connected between the GPIO pin and ground with an external 10kΩ pull-up resistor, configuring it as an active-low input. When pressed, the button pulls GPIO9 to ground (logic low), and when released, the pull-up resistor brings the pin back to VCC (logic high).\nButton Schematic on the ESP32-C3-DevKit-RUST-2 Note: GPIO9 on the ESP32-C3 is a boot strapping pin used for download mode. Avoid pressing the button during boot to prevent entering download mode unintentionally.\nComponent Installation # You can easily add the button component to your ESP-IDF project using the IDF Component Manager:\nidf.py add-dependency \u0026#34;espressif/button=*\u0026#34; This command will install the latest available version of the button component.\nOr manually add it to your idf_component.yml file:\ndependencies: espressif/button: \u0026#34;^4.1.5\u0026#34; Note: At the time of this article\u0026rsquo;s publication, the current version is 4.1.5. The ^4.1.5 version specification means the dependency will use version 4.1.5 or any newer compatible release if available. Step 1: Include Required Headers # First, include the necessary headers for button handling:\n#include \u0026#34;iot_button.h\u0026#34; #include \u0026#34;button_gpio.h\u0026#34; Step 2: Define GPIO and Configuration # Set the GPIO pin and configure logging:\n// Define button GPIO and active level #define BUTTON_IO_NUM 9 // GPIO number for the button #define BUTTON_ACTIVE_LEVEL 0 // Active level for the button (0 for active low, 1 for active high) static const char *TAG = \u0026#34;BUTTON\u0026#34;; Step 3: Create Event Callback Functions # Define callback functions that will be triggered when button events occur:\n// Callback functions for button events static void button_single_click_event_cb(void *arg, void *data) { ESP_LOGI(TAG, \u0026#34;Button single click!\u0026#34;); } static void button_double_click_event_cb(void *arg, void *data) { ESP_LOGI(TAG, \u0026#34;Button double click!\u0026#34;); } static void button_long_press_event_cb(void *arg, void *data) { ESP_LOGI(TAG, \u0026#34;Button long press!\u0026#34;); } static void button_repeat_event_cb(void *arg, void *data) { ESP_LOGI(TAG, \u0026#34;Button press repeat!\u0026#34;); } These callback functions are invoked automatically by the button component when their respective button events are detected. In this example, each callback simply logs a message to the console for demonstration purposes. In your actual application, you should replace these log statements with your application-specific logic—for example, toggling an LED in the single click callback, adjusting brightness levels in the double click callback, or triggering Wi-Fi provisioning in the long press callback. The arg parameter can be used to pass user-defined context data to the callback, while the data parameter provides event-specific information from the button component.\nStep 4: Configure Button Timing # In the app_main() function, create the button configuration with timing parameters:\nvoid app_main(void) { // Create button configurations const button_config_t btn_cfg = { .long_press_time = 5000, // Long press time in milliseconds .short_press_time = 200, // Short press time in milliseconds }; The timing configuration defines how the component distinguishes between different button press types. The short_press_time parameter sets the minimum duration (in milliseconds) that a button must be pressed to register as a valid press, effectively serving as the debounce threshold—in this example, 200ms filters out mechanical bounce and accidental touches. The long_press_time parameter determines how long a button must be held before triggering a long press event—here set to 5000ms (5 seconds). These timing values can be adjusted based on your application requirements: shorter values for more responsive interfaces, or longer values for applications requiring deliberate user interaction to prevent accidental triggers.\nStep 5: Configure GPIO Settings # Set the GPIO-specific configuration for your button:\nconst button_gpio_config_t btn_gpio_cfg = { .gpio_num = BUTTON_IO_NUM, .active_level = BUTTON_ACTIVE_LEVEL, .disable_pull = false, }; The active_level parameter determines the logic level that indicates a button press. With active low (0), the button pulls the GPIO to ground when pressed, which is the most common configuration using pull-up resistors. In this case, the GPIO reads low (0) when pressed and high (1) when released. With active high (1), the button connects the GPIO to VCC when pressed, typically used with pull-down resistors, where the GPIO reads high (1) when pressed and low (0) when released. The disable_pull setting controls whether the internal pull-up or pull-down resistor is disabled—setting it to false enables the internal pull resistor, which is recommended for most applications to ensure a defined logic level when the button is not pressed.\nStep 6: Create the Button Device # Initialize the button device using the configurations:\n// Button handle button_handle_t btn; // Create a new button device esp_err_t ret = iot_button_new_gpio_device(\u0026amp;btn_cfg, \u0026amp;btn_gpio_cfg, \u0026amp;btn); Step 7: Register Event Callbacks # Register the callback functions for different button events:\n// Register callback for button press ret = iot_button_register_cb(btn, BUTTON_SINGLE_CLICK, NULL, button_single_click_event_cb, NULL); ESP_ERROR_CHECK(ret); ret = iot_button_register_cb(btn, BUTTON_DOUBLE_CLICK, NULL, button_double_click_event_cb, NULL); ESP_ERROR_CHECK(ret); ret = iot_button_register_cb(btn, BUTTON_LONG_PRESS_UP, NULL, button_long_press_event_cb, NULL); ESP_ERROR_CHECK(ret); ret = iot_button_register_cb(btn, BUTTON_PRESS_REPEAT, NULL, button_repeat_event_cb, NULL); ESP_ERROR_CHECK(ret); } This example demonstrates several important aspects of button configuration and handling. GPIO 9 is configured with active-low logic, meaning the button pulls the GPIO low when pressed. The timing parameters are set to detect a long press after 5 seconds and a short press after 200 milliseconds, providing flexibility for different interaction patterns.\nThe component handles multiple event types including single clicks, double clicks, long presses, and repeated presses, all managed through the callback system. Your application-specific code for handling each button interaction should be implemented inside the respective callback functions—for instance, toggling an LED in the single click callback or triggering Wi-Fi provisioning in the long press callback. Error checking with ESP_ERROR_CHECK() ensures each callback registration succeeds, while logging in each event callback provides clear console output for easy debugging and verification of button behavior.\nComplete Source Code # The full source code for this example is available in the developer-portal-codebase repository.\nConclusion # If you plan to use buttons in your next ESP-IDF project, consider integrating the espressif/button component. This will help you focus on your application logic instead of low-level button management.\nThe component\u0026rsquo;s comprehensive event detection system, including support for single clicks, double clicks, long presses, and repeat presses, provides the flexibility needed for modern embedded applications. With built-in debouncing, thread-safe operation, and support for both GPIO and ADC button matrices, you can implement sophisticated button interfaces without reinventing the wheel.\nWhether you\u0026rsquo;re building a smart home device, an IoT gateway, or an industrial control panel, the espressif/button component handles the complexity of reliable button input detection so you can concentrate on creating great user experiences. Available through the ESP Component Registry, it\u0026rsquo;s easy to integrate and comes with the reliability and support of an official Espressif component.\nLearn More # To deepen your understanding of GPIO fundamentals and how they work with button components, check out our tutorial:\nESP-IDF tutorial series: GPIO get started - Part 1 ESP-IDF tutorial series: GPIO get started - Part 2 Resources # button Component on ESP Component Registry ESP Component Registry Documentation ESP32-C3-DevKit-RUST-2 Documentation What is the ESP Component Registry? GitHub - button Repository ","date":"18 February 2026","externalUrl":null,"permalink":"/blog/2026/02/component-introduction-button/","section":"Blog","summary":"Learn how to use the ESP-IDF button component to handle GPIO buttons with event detection, debouncing, and callbacks. A step-by-step guide with practical code examples.","title":"Introducing ESP-IDF button component","type":"blog"},{"content":"","date":"18 February 2026","externalUrl":null,"permalink":"/authors/pedro-minatel/","section":"Developer Portal Authors","summary":"","title":"Pedro Minatel","type":"authors"},{"content":"","date":"18 February 2026","externalUrl":null,"permalink":"/tags/practitioner/","section":"Tags","summary":"","title":"Practitioner","type":"tags"},{"content":" Introduction # General-purpose input/output (GPIO) pins are one of the core interfaces on Espressif SoCs, allowing the device to interact with external components and signals. In the first part of this series, we explored how a GPIO can be configured and used as an output\nIn this second part, we will see how to use a GPIO as an input, how to deal with its high impedance, and which strategies are available to read its value.\nInput configuration # When configuring a GPIO as an input, you don\u0026rsquo;t need to set parameters like driving strength. GPIO inputs present high impedance, meaning they draw very little current from connected circuits. This is ideal for interfacing with sensors, as it minimizes the load on them.\nHowever, this high impedance creates a challenge when reading digital signals. For example, if you connect a GPIO directly to a button without any additional components (see Fig.1) the voltage at the pin is undefined when the button is not pressed. Reading this undefined voltage can produce random values.\nFig.1 - Undefined input value\nFor this reason, a pull-up or pull-down resistor is usually added to the circuit. This way, when the button is not pressed, the resistor defines the idle voltage: with a pull-up the pin is held close to VDD (see Fig.2), while with a pull-down it is held close to GND.\nFig.2 - Pull-up resistor\nModern microcontrollers offer internal pull-up or pull-down resistors that can be configured via firmware.\nIn ESP-IDF, the function used for this is aptly named gpio_set_pull_mode.\nWe can now move to the reading strategies: polling and event-driven callbacks.\nPolling # The simplest way to read a GPIO is to read its value directly using the function gpio_get_level.\nSuppose we want to write a firmware to print \u0026ldquo;Button pressed\u0026rdquo; using this function and the boot button on a DevKit. In the ESP32-C61-DevKitC, it is connected to GPIO9.\nAfter including the library (as shown in Part 1), we need to configure it.\nWe need to:\nDefine the boot button GPIO #define BUTTON_GPIO 9 // GPIO9 on most DevKits Set the direction as input gpio_set_direction(BUTTON_GPIO, GPIO_MODE_INPUT); Set the pull mode to pull-up gpio_set_pull_mode(BUTTON_GPIO, GPIO_PULLUP_ONLY); The boot button is connected to the ground, so we need a pull-up resistor as shown Fig.2. If the button were connected to VDD, then we should have selected the pull-down option. Create an infinite loop to read the button value The main function looks like this:\nvoid app_main(void) { gpio_set_direction(BUTTON_GPIO, GPIO_MODE_INPUT); gpio_set_pull_mode(BUTTON_GPIO, GPIO_PULLUP_ONLY); while (1) { int level = gpio_get_level(BUTTON_GPIO); if (level == 0) { printf(\u0026#34;Button pressed\\n\u0026#34;); } else { printf(\u0026#34;Button released\\n\u0026#34;); } vTaskDelay(pdMS_TO_TICKS(200)); // required to avoid WDT timeout } } The output is:\n[...] Button released Button released Button pressed Button released [...] This strategy is called polling: you keep asking the relevant resource about its status.\nIt works, but it\u0026rsquo;s highly inefficient. It would be better if the GPIO input pin could notify the firmware when the button is pressed.\nThis is what it\u0026rsquo;s called an event-driven strategy.\nEvent-driven strategy # A smarter way to detect button presses is using interrupts and callback functions. To illustrate these concepts, we will use the same application as in the previous section.\nBut first, let\u0026rsquo;s see what are an interrupt and an interrupt service routine (ISR).\nWhat is an interrupt # An interrupt is a hardware or software signal that tells a microcontroller to pause its current task and immediately handle an important event. When an interrupt occurs, the MCU saves its current state and runs a special function called an ISR. After the ISR finishes, the MCU returns to whatever it was doing before the interrupt happened.\nInterrupt sources include timers expiring, GPIO events, PWM events, and many others.\nWe will focus on the interrupts generated by GPIOs.\nGPIO interrupt types # A GPIO input can have a value of one or zero and switch between these two values. A signal at a GPIO input is represented by a pulse like the one in Fig. 3.\nFig.3 - GPIO interrupt types\nESP-IDF can trigger an interrupt at different points of the pulse. The complete list is in the following table.\nInterrupt type Description GPIO_INTR_DISABLE Interrupt disabled GPIO_INTR_POSEDGE Trigger on rising edge GPIO_INTR_NEGEDGE Trigger on falling edge GPIO_INTR_ANYEDGE Trigger on both edges GPIO_INTR_LOW_LEVEL Trigger on low level GPIO_INTR_HIGH_LEVEL Trigger on high level You can specify the interrupt type associated with a GPIO using the function:\ngpio_set_intr_type(BUTTON_GPIO, GPIO_INTR_NEGEDGE); ISR callback function # Once an interrupt is triggered, an ISR is called. You can define a callback function using the signature static void IRAM_ATTR function_name(void * arg).\nIRAM_ATTR is an ESP-IDF macro that places a function in instruction RAM (IRAM) instead of flash, allowing it to execute faster. In our example, we want to print the same output as before.\nstatic void IRAM_ATTR button_isr_handler(void *arg) { ESP_EARLY_LOGI(TAG, \u0026#34;Button pressed\u0026#34;); } ISRs should be as short as possible to avoid blocking the main execution. For this reason, some specific fast functions are available for use inside ISRs. One of these is ESP_EARLY_LOGI, which is the recommended alternative to ESP_LOGI.\nIf you\u0026rsquo;re interested in learning more about the logging system, check out the article ESP-IDF tutorial series: logging. To attach this ISR to the GPIO interrupt, we need to:\nInitialize the ISR service: gpio_install_isr_service(ESP_INTR_FLAG_DEFAULT); Add the handler function we created to the button interrupt itself: gpio_isr_handler_add(BUTTON_GPIO, button_isr_handler, NULL); Now the main loop becomes very simple. while (1) { vTaskDelay(pdMS_TO_TICKS(1000)); } Putting it all together # The main function becomes more compact and robust.\nvoid app_main(void) { gpio_set_direction(BUTTON_GPIO, GPIO_MODE_INPUT); gpio_set_pull_mode(BUTTON_GPIO, GPIO_PULLUP_ONLY); gpio_set_intr_type(BUTTON_GPIO, GPIO_INTR_NEGEDGE); gpio_install_isr_service(ESP_INTR_FLAG_DEFAULT); gpio_isr_handler_add(BUTTON_GPIO, button_isr_handler, NULL); while (1) { vTaskDelay(pdMS_TO_TICKS(1000)); } } When the button is pressed, the output is:\nI (3183) button_example: Button pressed You can find the complete code on the developer portal codebase.\nConclusion # In this article, we explored how to configure GPIO pins as inputs in ESP-IDF. We discussed the importance of using pull-up or pull-down resistors to avoid undefined voltage levels when reading inputs, and demonstrated two different approaches for reading GPIO values: polling and event-driven interrupts. We also covered how to configure interrupt types and implement Interrupt Service Routines (ISRs) using the ESP-IDF GPIO API.\nIn the next article, we will explore the GPIO matrix and the opportunities it offers.\n","date":"13 February 2026","externalUrl":null,"permalink":"/blog/2026/02/esp-idf-tutorial-gpio-get-started-2/","section":"Blog","summary":"In this article, we explore how to configure GPIO pins as inputs in ESP-IDF and discuss the importance of pull-up/pull-down resistors. We will try two approaches for reading GPIO values: polling and event-driven interrupts, showing how to implement each method effectively.","title":"ESP-IDF tutorial series: GPIO get started - Part 2","type":"blog"},{"content":"","date":"13 February 2026","externalUrl":null,"permalink":"/authors/francesco-bez/","section":"Developer Portal Authors","summary":"","title":"Francesco Bez","type":"authors"},{"content":"","date":"13 February 2026","externalUrl":null,"permalink":"/tags/interrupt/","section":"Tags","summary":"","title":"Interrupt","type":"tags"},{"content":"","date":"9 February 2026","externalUrl":null,"permalink":"/authors/abhik-roy/","section":"Developer Portal Authors","summary":"","title":"Abhik Roy","type":"authors"},{"content":"","date":"9 February 2026","externalUrl":null,"permalink":"/tags/dns/","section":"Tags","summary":"","title":"DNS","type":"tags"},{"content":"","date":"9 February 2026","externalUrl":null,"permalink":"/tags/how-to/","section":"Tags","summary":"","title":"How-To","type":"tags"},{"content":"","date":"9 February 2026","externalUrl":null,"permalink":"/tags/networking/","section":"Tags","summary":"","title":"Networking","type":"tags"},{"content":" Introduction # Your ESP32 device just queried DNS. Did anyone see it?\nEvery ESP32 device that connects to the internet relies on DNS to resolve domain names. But traditional DNS operates in plaintext—meaning anyone on your network can see which domains your device queries. If they wish, they can can intercept those queries and redirect them, or inject malicious responses.\nThe ESP DNS component solves this by bringing DNS security to ESP32 devices. With support for DNS over TLS (DoT) and DNS over HTTPS (DoH), you can protect your applications with just a few lines of code—no complex infrastructure or protocol changes required. See the component documentation for detailed API reference and configuration options.\nIn this guide, you\u0026rsquo;ll learn:\nWhy DNS Security Matters for IoT devices How ESP DNS component makes implementation simple DNSSEC vs. Transport Security: The Practical Choice Step-by-step code examples to get started Why DNS Security Matters for IoT devices # DNS translates domain names like api.example.com into IP addresses. When your ESP32 device needs to connect to a server, it queries a DNS server to get the IP address.\nTraditional DNS queries are sent in plaintext over UDP or TCP, making them visible to anyone monitoring the network. The Vulnerabilities # No Encryption: Anyone on the network can see which domains your device is querying, revealing what services it uses and how it behaves.\nNo Authentication: There\u0026rsquo;s no way to verify that a DNS response actually came from a legitimate server. Attackers can inject fake responses.\nNo Integrity Protection: DNS responses can be modified in transit without detection, redirecting your device to malicious servers.\nReal-World Attack Scenarios # Attack Type Impact Example DNS Spoofing Credential theft, malware injection Public Wi-Fi redirects to fake login pages Man-in-the-Middle Firmware compromise, data interception Compromised router redirects updates Privacy Violations Behavior profiling, data selling ISP monitors DNS queries for analytics DNS Hijacking Mass surveillance, service disruption Compromised DNS server redirects all queries For IoT devices, these attacks can mean complete compromise: attackers could redirect firmware updates, intercept sensor data, or gain control of entire systems.\nHow ESP DNS component makes implementation simple # Key Benefits:\n✅ Multi-protocol support (UDP, TCP, DoT, DoH) ✅ Minimal code changes—just initialize the component ✅ Flexible certificate management ✅ Production-ready security The ESP DNS component brings secure DNS resolution to ESP32 devices with minimal effort. Here\u0026rsquo;s what makes it powerful:\nMulti-Protocol Support # Choose the right protocol for your needs:\nUDP DNS: Traditional unencrypted DNS for compatibility TCP DNS: Reliable DNS over TCP for larger responses DNS over TLS (DoT): Encrypted DNS using TLS on port 853 DNS over HTTPS (DoH): Encrypted DNS using HTTPS on port 443 Seamless Integration # Transparent Operation: Once initialized, the component automatically intercepts DNS resolution requests and routes them through your configured secure protocol. No changes to your application code are required.\nStandard Interface: Your existing code continues to work unchanged. Applications use the standard getaddrinfo() function—the component handles secure DNS resolution behind the scenes.\nSecurity Features # TLS Encryption: Both DoT and DoH use TLS encryption to protect DNS queries and responses, preventing eavesdropping and tampering.\nCertificate Validation: Flexible certificate management supports:\nCertificate Bundle: Use ESP-IDF\u0026rsquo;s certificate bundle for popular DNS providers (Google, Cloudflare, Quad9) Custom PEM Certificates: Provide your own certificates for private or enterprise DNS servers MITM Protection: TLS certificate validation ensures queries go to legitimate DNS servers, preventing man-in-the-middle attacks.\nQuery Privacy: Encrypted queries prevent network observers from seeing which domains are resolved, protecting user privacy and preventing DNS-based tracking.\nWhy It\u0026rsquo;s Developer-Friendly # Minimal Code Changes: Your existing getaddrinfo() calls work without modification, whether from your application code or any other library. Just initialize the component and you\u0026rsquo;re done.\nEasy Configuration: Simple configuration structure with sensible defaults. Choose your protocol, DNS server, and certificate method.\nFlexible Deployment: Use public DoT/DoH servers or deploy your own. Easy to switch between providers or protocols.\nHow It Works # lwIP Hook Integration: The component integrates transparently with ESP-IDF\u0026rsquo;s networking stack through lwIP hooks. Once initialized, it automatically intercepts DNS resolution requests and routes them through your configured secure protocol. This integration happens at the network stack level, ensuring all DNS queries from your application are automatically secured without requiring changes to individual DNS resolution calls.\nDNSSEC vs. Transport Security: The Practical Choice # DNSSEC (DNS Security Extensions) provides cryptographic authentication for DNS responses, but it\u0026rsquo;s complex to implement:\nRequires complex key management across DNS infrastructure Needs significant computational resources for validation Doesn\u0026rsquo;t encrypt queries—privacy remains unprotected Limited support in embedded systems Transport-layer security protocols like DNS over TLS (DoT) and DNS over HTTPS (DoH) offer a more practical solution:\nDoT (RFC 7858): Wraps DNS queries in TLS-encrypted connections on port 853 DoH (RFC 8484): Sends DNS queries as HTTPS POST requests on port 443 Why DNSSEC Support is Limited on ESP32 # DNSSEC validation faces significant challenges on ESP32 due to resource constraints:\nMemory: ESP32 variants have limited SRAM (320-520KB depending on the model) that must be shared across application, networking, and cryptographic operations. DNSSEC requires caching additional records (RRSIG, DNSKEY), increasing memory usage by ~10%. In contrast, DoT/DoH typically require storing only a resolver certificate chain, which is already supported and optimized in existing TLS stacks.\nCPU: Signature verification is computationally intensive. ESP32 variants use different CPU architectures (Xtensa LX6/LX7 or RISC-V) with clock speeds ranging from 160-240MHz. Multiple signature verifications per response significantly increase CPU load and power consumption—critical for battery-powered devices. While DoT/DoH also verify certificate signatures (RSA/ECDSA), this occurs only during TLS session establishment and can be amortized across many DNS queries. DNSSEC requires repeated signature validation for every DNS response.\nlwIP Limitations: ESP32\u0026rsquo;s lwIP DNS client prioritizes simplicity and minimal resources. It doesn\u0026rsquo;t support DNSSEC validation, complex query types, or advanced DNS features.\nZone Size: DNSSEC-signed zones can be up to 5x larger than unsigned zones, requiring more memory for caching and processing.\nPractical Solution: Use DoT/DoH with trusted DNS resolvers (Google, Cloudflare, Quad9) that perform DNSSEC validation on your behalf. This offloads the computational burden while providing both transport-layer encryption and DNSSEC protection.\nDNSSEC vs. DoT/DoH: Quick Comparison # Feature DNSSEC DoT/DoH Encryption ❌ No ✅ Yes Authentication ✅ Yes ✅ Yes Privacy Protection ❌ No ✅ Yes Implementation Complexity 🔴 High 🟢 Low ESP32 Support 🔴 Limited 🟢 Full Infrastructure Requirements 🔴 Complex 🟢 Simple For ESP32 developers, DoT/DoH are the practical choice: Strong security with manageable complexity, leveraging infrastructure already available in ESP-IDF.\nStep-by-step code examples to get started # Getting started with ESP DNS is straightforward, requiring minimal code changes to existing applications.\nQuick Start Guide # 1. Add ESP DNS Component to Your Project\nThe ESP DNS component is available in the ESP Component Registry.\nAdd it using the Component Manager:\nidf.py add-dependency \u0026#34;espressif/esp_dns^0.1.0\u0026#34; Or manually add to main/idf_component.yml:\ndependencies: espressif/esp_dns: \u0026#34;^0.1.0\u0026#34; Then run idf.py reconfigure to download the component.\n2. Enable Custom DNS Resolution\nEnable the lwIP hook in your sdkconfig or sdkconfig.defaults:\nCONFIG_LWIP_HOOK_NETCONN_EXT_RESOLVE_CUSTOM=y Or configure through menuconfig:\nNavigate to Component config → lwIP → Hooks → Netconn external resolve Hook Select Custom implementation 3. Initialize DNS Component\nChoose your protocol and initialize:\n#include \u0026#34;esp_dns.h\u0026#34; // Configure DNS over HTTPS esp_dns_config_t dns_config = { .dns_server = \u0026#34;dns.google\u0026#34;, // DNS server hostname .port = ESP_DNS_DEFAULT_DOH_PORT, // Port 443 for HTTPS .timeout_ms = ESP_DNS_DEFAULT_TIMEOUT_MS, // 10 second timeout .tls_config = { .crt_bundle_attach = esp_crt_bundle_attach, // Use certificate bundle }, .protocol_config.doh_config = { .url_path = \u0026#34;/dns-query\u0026#34;, // DoH endpoint path } }; // Initialize DoH esp_dns_handle_t dns_handle = esp_dns_init_doh(\u0026amp;dns_config); if (dns_handle == NULL) { ESP_LOGE(TAG, \u0026#34;Failed to initialize DNS\u0026#34;); return; } 4. Use Standard DNS Functions\nYour existing code continues to work unchanged:\nstruct addrinfo hints = { .ai_family = AF_UNSPEC, .ai_socktype = SOCK_STREAM, }; struct addrinfo *res; int err = getaddrinfo(\u0026#34;www.example.com\u0026#34;, \u0026#34;80\u0026#34;, \u0026amp;hints, \u0026amp;res); if (err != 0) { ESP_LOGE(TAG, \u0026#34;DNS lookup failed: %s\u0026#34;, gai_strerror(err)); return; } // Use resolved addresses... freeaddrinfo(res); 5. Cleanup\nWhen done, clean up resources:\nint ret = esp_dns_cleanup_doh(dns_handle); if (ret != 0) { ESP_LOGE(TAG, \u0026#34;Failed to cleanup DNS\u0026#34;); } Complete Working Example # Here\u0026rsquo;s a complete example showing initialization, usage, and cleanup:\n#include \u0026#34;esp_dns.h\u0026#34; #include \u0026#34;esp_log.h\u0026#34; static const char *TAG = \u0026#34;dns_example\u0026#34;; void app_main(void) { // Configure DNS over HTTPS esp_dns_config_t dns_config = { .dns_server = \u0026#34;dns.google\u0026#34;, .port = ESP_DNS_DEFAULT_DOH_PORT, .timeout_ms = ESP_DNS_DEFAULT_TIMEOUT_MS, .tls_config = { .crt_bundle_attach = esp_crt_bundle_attach, }, .protocol_config.doh_config = { .url_path = \u0026#34;/dns-query\u0026#34;, } }; // Initialize DoH esp_dns_handle_t dns_handle = esp_dns_init_doh(\u0026amp;dns_config); if (dns_handle == NULL) { ESP_LOGE(TAG, \u0026#34;Failed to initialize DNS\u0026#34;); return; } ESP_LOGI(TAG, \u0026#34;DNS initialized successfully\u0026#34;); // Use DNS resolution struct addrinfo hints = { .ai_family = AF_UNSPEC, .ai_socktype = SOCK_STREAM, }; struct addrinfo *res; int err = getaddrinfo(\u0026#34;www.example.com\u0026#34;, \u0026#34;80\u0026#34;, \u0026amp;hints, \u0026amp;res); if (err != 0) { ESP_LOGE(TAG, \u0026#34;DNS lookup failed: %s\u0026#34;, gai_strerror(err)); } else { ESP_LOGI(TAG, \u0026#34;DNS resolution successful\u0026#34;); // Use resolved addresses... freeaddrinfo(res); } // Cleanup esp_dns_cleanup_doh(dns_handle); } Configuration Examples # DNS over TLS (DoT)\nesp_dns_config_t dns_config = { .dns_server = \u0026#34;1dot1dot1dot1.cloudflare-dns.com\u0026#34;, // Use hostname for certificate validation .port = ESP_DNS_DEFAULT_DOT_PORT, // Port 853 for TLS .timeout_ms = 5000, // 5 second timeout .tls_config = { .crt_bundle_attach = esp_crt_bundle_attach, } }; esp_dns_handle_t dns_handle = esp_dns_init_dot(\u0026amp;dns_config); Custom Certificate for Private Server\nconst char *custom_cert_pem = \u0026#34;-----BEGIN CERTIFICATE-----\\n\u0026#34; \u0026#34;MIIF...\\n\u0026#34; // Your certificate here \u0026#34;-----END CERTIFICATE-----\\n\u0026#34;; esp_dns_config_t dns_config = { .dns_server = \u0026#34;dns.internal.company.com\u0026#34;, .port = ESP_DNS_DEFAULT_DOT_PORT, .timeout_ms = ESP_DNS_DEFAULT_TIMEOUT_MS, .tls_config = { .cert_pem = custom_cert_pem, // Custom certificate } }; esp_dns_handle_t dns_handle = esp_dns_init_dot(\u0026amp;dns_config); TCP DNS (Unencrypted)\nesp_dns_config_t dns_config = { .dns_server = \u0026#34;8.8.8.8\u0026#34;, // Google DNS .port = ESP_DNS_DEFAULT_TCP_PORT, // Port 53 .timeout_ms = ESP_DNS_DEFAULT_TIMEOUT_MS, }; esp_dns_handle_t dns_handle = esp_dns_init_tcp(\u0026amp;dns_config); Certificate Setup Options # Using Certificate Bundle (Recommended for Public Servers)\nThe certificate bundle approach is simplest for public DNS servers:\nNo certificate management required Automatically validates popular DNS providers Handles certificate updates automatically .tls_config = { .crt_bundle_attach = esp_crt_bundle_attach, } Using Custom PEM Certificate\nFor private or enterprise DNS servers:\nProvide certificate as PEM-formatted string Certificate must match the DNS server\u0026rsquo;s certificate Note: Only PEM format is supported; DER format is not supported .tls_config = { .cert_pem = server_root_cert_pem_start, // PEM certificate string } Important: If both crt_bundle_attach and cert_pem are provided, crt_bundle_attach takes precedence.\nChoosing the Right Protocol # Protocol Use When Trade-offs UDP DNS Maximum compatibility, no security needed Fastest, but vulnerable TCP DNS Larger responses, reliability needed Slightly slower, still vulnerable DoT Security + performance balance Moderate latency, good security, may be blocked by some firewalls DoH Maximum security, firewall-friendly Highest latency, best security Performance Considerations # Memory Usage\nUDP DNS: Minimal memory impact (~96 bytes) TCP DNS: Moderate memory impact (~13 KB) DoT DNS: TLS operations temporarily use ~60 KB during handshakes, then recover DoH DNS: Similar to DoT, temporarily uses ~63 KB during HTTPS handshakes Memory cleanup: Proper cleanup observed; final memory usage remains close to initial Consider available RAM when choosing protocol, especially for TLS-based protocols Latency\nUDP DNS: Fastest, but least secure TCP DNS: Slightly slower due to connection establishment DoT: Moderate latency due to TLS handshake DoH: Typically highest latency due to HTTPS overhead, but offers best security Network Bandwidth\nEncrypted protocols add overhead (TLS/HTTPS headers) DoH may have slightly more overhead than DoT Consider bandwidth constraints in low-power or metered networks DoH is firewall-friendly, since it runs over standard HTTPS (port 443) and typically passes through restrictive networks more easily than DoT. Troubleshooting # Common Issues:\nDNS initialization fails\nVerify CONFIG_LWIP_HOOK_NETCONN_EXT_RESOLVE_CUSTOM=y is set Check certificate bundle is enabled: CONFIG_MBEDTLS_CERTIFICATE_BUNDLE=y Ensure network is connected before initializing DNS DNS resolution timeout\nIncrease timeout_ms value Check network connectivity Verify DNS server hostname is resolvable Certificate validation fails\nFor custom certificates, ensure the PEM format is correct Verify the certificate matches the DNS server Check certificate expiration date Conclusion # DNS security is essential for protecting IoT applications, but implementing it doesn\u0026rsquo;t have to be complex. The ESP DNS component provides DNS security with minimal code changes, supporting multiple protocols and flexible certificate management.\nNext Steps:\nEnable CONFIG_LWIP_HOOK_NETCONN_EXT_RESOLVE_CUSTOM=y in your project Initialize ESP DNS component with your preferred protocol Test DNS resolution with your existing getaddrinfo() calls Monitor performance and adjust timeout/configuration as needed Whether you\u0026rsquo;re building smart home devices, industrial IoT systems, or medical devices, securing DNS resolution should be part of your security strategy. The ESP DNS component makes this achievable with just a few lines of code, protecting your devices from DNS-based attacks while maintaining simplicity and performance.\nReady to secure your ESP32 applications? Get started today with the ESP DNS component.\n","date":"9 February 2026","externalUrl":null,"permalink":"/blog/2026/02/secure-dns-for-esp32-quick-guide-esp-dns-component/","section":"Blog","summary":"This article introduces the ESP DNS component and explains why securing DNS resolution is essential for ESP32-based IoT devices. It shows how DNS over TLS (DoT) and DNS over HTTPS (DoH) can be enabled transparently in ESP-IDF with minimal code changes, using standard DNS APIs. Practical examples and guidance help developers choose the right protocol while balancing security, performance, and resource constraints.","title":"Secure DNS for ESP32: A Quick Guide to ESP DNS Component","type":"blog"},{"content":"Meet Espressif at Embedded World 2026!\nWe’re heading to Embedded World 2026 in Nuremberg! Join us to explore Espressif’s latest developments across connectivity, graphics, AIoT, and edge computing.\nStop by to see live demos and connect with the Espressif team.\nRegister Now to book a meeting:\nRegister :calendar: Dates: 10–12 March 2026 :round_pushpin: Location: Hall 3A - 528 Messe Nürnberg, Messezentrum, Nuremberg, Bavaria, DE, 90471 Event on LinkedIn: Join and share! Resources and Materials # Resources Downloads # Espressif SoC Portfolio 2026 Espressif Brochure Embedded World 2026 Flyers # Download ESP-IDF Download Arduino Download NuttX Download Rust Download Zephyr ","date":"6 February 2026","externalUrl":null,"permalink":"/events/embedded-world-2026/","section":"Events","summary":"Meet Espressif at Embedded World 2026 in Nuremberg from March 10 to 12 to explore live demos and the latest developments in connectivity, graphics, AIoT, and edge computing, and connect directly with our team.","title":"Embedded World 2026","type":"events"},{"content":"","date":"6 February 2026","externalUrl":null,"permalink":"/tags/event/","section":"Tags","summary":"","title":"Event","type":"tags"},{"content":"","date":"6 February 2026","externalUrl":null,"permalink":"/tags/ew25/","section":"Tags","summary":"","title":"Ew25","type":"tags"},{"content":"","date":"5 February 2026","externalUrl":null,"permalink":"/authors/eren-terzioglu/","section":"Developer Portal Authors","summary":"","title":"Eren Terzioğlu","type":"authors"},{"content":"","date":"5 February 2026","externalUrl":null,"permalink":"/tags/low-power/","section":"Tags","summary":"","title":"Low Power","type":"tags"},{"content":"","date":"5 February 2026","externalUrl":null,"permalink":"/tags/nuttx/","section":"Tags","summary":"","title":"NuttX","type":"tags"},{"content":"","date":"5 February 2026","externalUrl":null,"permalink":"/tags/posix/","section":"Tags","summary":"","title":"POSIX","type":"tags"},{"content":"","date":"5 February 2026","externalUrl":null,"permalink":"/tags/power-management/","section":"Tags","summary":"","title":"Power Management","type":"tags"},{"content":" What is power management # Power management is the process of controlling energy consumption in devices to optimize efficiency, balance performance, and reduce costs. It is especially important in embedded systems, where many applications must operate for long periods on limited power sources. By reducing power consumption—often by entering sleep modes or shutting down unused parts of the chip—devices can significantly extend operating life and improve overall efficiency.\nPower Modes on Espressif Devices # Espressif microcontrollers support several predefined power modes designed to optimize power consumption for a wide range of use cases:\nActive mode: The HP CPU, RF circuits, and all peripherals are powered on, offering maximum performance with the highest power consumption.\nModem‑sleep mode: The HP CPU remains on while its clock frequency may be reduced. The RF circuits are periodically switched on when required by internal operation to keep active wireless connections running. This mode is available only on Wi‑Fi or radio‑capable devices.\nLight‑sleep mode: Digital peripherals, most RAM, and CPUs are clock‑gated with reduced supply voltage. Internal state is preserved, enabling fast wakeup with moderate power savings.\nDeep‑sleep mode: Only the ULP coprocessor and RTC fast memory stay powered on. Wakeup requires a full restart, making it ideal for long idle periods.\nThese modes can be reconfigured if needed. More details and useful links can be found in the power management sections of chip datasheets and technical reference manuals. As an example, for ESP32-C6, see its chip datasheet and technical reference manual.\nFor a deeper understanding of what the ULP coprocessor is and what it does, see also the article Building low power applications on Espressif chips: Ultra-Low-Power (ULP) coprocessor.\nNuttX Power Management System # This section provides an overview of NuttX power manager internals. It will help understand how to get the device into different power consumption modes. For more detailed information, feel free to check the NuttX Power Management documentation.\nPower Management States # NuttX power management (PM) logic has the following states:\nNORMAL: This is the full‑power operating state. IDLE: Very similar to NORMAL, this state has limited trivial optimizations allowed that do not interfere with normal operation. A simple example is dimming a screen backlight when the system is idle. STANDBY: This state allows deeper power savings, CPU clock reductions. In this state, the system should still be able to resume normal activity almost immediately. SLEEP: The lowest power consumption mode. Wakeup requires more time (some MCUs require a full restart). This state is appropriate for long idle periods. Espressif power modes compare to NuttX power states as follows:\nEspressif Power Mode NuttX Power State Active state NORMAL Active state IDLE Light sleep STANDBY Deep sleep SLEEP Note: Modem-sleep mode has no equivalent in Espressif’s NuttX power management implementation.\nPower Management Governors # NuttX utilizes a power management system involving power‑management “governors”. A governor is a handler that automatically selects the appropriate power state based on the system condition. The active governor is chosen during system initialization through configuration options.\nGreedy Governor: Always selects the lowest‑power state available. This method is suitable for systems where aggressive power saving is more important than activity tracking or avoiding frequent state changes. Enabled with the CONFIG_PM_GOVERNOR_GREEDY configuration option.\nStability Governor: Works like the greedy governor but adds a time‑based stability check to prevent rapid transitions between states. This method is suitable for systems that need predictable power‑state behavior. Enabled with the CONFIG_PM_GOVERNOR_STABILITY configuration option.\nActivity Governor: Uses activity reports from drivers to determine the appropriate power state. This method is better for systems with dynamic workloads that need a balance between responsiveness and efficiency. Enabled with the CONFIG_PM_GOVERNOR_ACTIVITY configuration option.\nHow NuttX Power Management System Works # The NuttX power management system is built around a simple idea: each power state has a “stay count” and these counts determine how far the system is allowed to drop into lower‑power modes. A governor monitors these counts and chooses the deepest power state permitted.\nHere are the core concepts:\nPower State Counts: The power manager defines four power states: NORMAL, IDLE, STANDBY, and SLEEP. Each state has a count that indicates that state to remain active. The governor uses this information to decide on the next power state. Modifying Power State Counts: Peripheral drivers or applications can “hold” a state (increase its count) or “release” it (decrease its count). Counts may be changed by drivers—for example, the UART driver may keep the system out of sleep while active—or manually via the pmconfig shell command or application calls.\nGovernor Logic (State Transition): When a power state count changes, the state transition system \u0026ndash; the governor \u0026ndash; re‑evaluates which states are allowed. The rule is basically the system may enter a power state only if all higher‑power states have a count of zero.\nExamples:\nIf NORMAL reaches zero → system may enter IDLE. If NORMAL and IDLE reach zero → system may enter STANDBY (light sleep). If NORMAL, IDLE, and STANDBY reach zero → system may enter SLEEP (deep sleep). All in all, power state control is based on modifying power state counts.\nQuery current state counts to see which power states are active. Decrease a state count (relax) transitions to lower power consuming states. Increase a state count (stay) to keep the system in a higher‑power state. How to Use Power States # In this section, we will show how to enter different power states with the Greedy governor using the NuttX shell and a custom application.\nThis section assumes that the NuttX development environment is already set up. If you need installation instructions, please refer to the article Getting Started with NuttX and ESP32 . To use power manager, we need to enable certain configuration options. The default pm defconfigs, available for all Espressif boards supported by NuttX, already include the necessary power‑management configuration options. So we will use them.\nAlso worth to mention that this article will not touch into wake up modes from sleep. To get information about wakeup modes please refer to related NuttX docs\nTo build and flash NuttX with power‑management support on the ESP32‑C6, use the following commands:\nmake distclean \u0026amp;\u0026amp; ./tools/configure.sh esp32c6-devkitc:pm \u0026amp;\u0026amp; make \u0026amp;\u0026amp; make flash ESPTOOL_PORT=/dev/ttyUSB0 ESPTOOL_BINDIR=./ \u0026amp;\u0026amp; The pm configuration used in this article enables the Greedy power‑management governor and sets CONFIG_PM_GOVERNOR_EXPLICIT_RELAX = -1. This prevents NuttX from automatically entering lower‑power states at boot, ensuring that all transitions occur only when explicitly triggered by the shell or your application. This makes testing and demonstrations predictable and easier to follow.\nWhen reducing stay counts to allow deeper power states, it is best to relax them starting from the least power‑consuming state. This avoids the system briefly entering unintended intermediate states during the transition.\nEntering Sleep Modes from NuttX Shell # Before changing the power state, you should first check the current state counts to determine the correct number of required state transitions. The pmconfig command displays the stay counts for all power states. For example:\nnsh\u0026gt; pmconfig Last state 0, Next state 0 [...] /proc/pm/wakelock0: DOMAIN0 STATE COUNT TIME system normal 2 8s system idle 1 8s system standby 1 8s system sleep 1 8s [...] To change the count of a power state, use the following commands:\nDecrease the count: pmconfig relax \u0026lt;STATE_NAME\u0026gt; Increase the count: pmconfig stay \u0026lt;STATE_NAME\u0026gt; Changing the count of a power state # According to the output above, the STANDBY power state count is 1. Let\u0026rsquo;s decrease the state count by running this command:\nnsh\u0026gt; pmconfig relax standby To make sure that the above command has decreased the STANDBY power state count to 0, let\u0026rsquo;s query the power states again:\nnsh\u0026gt; pmconfig # Output Last state 0, Next state 0 [...] /proc/pm/wakelock0: DOMAIN0 STATE COUNT TIME system normal 2 25s system idle 1 25s system standby 0 25s system sleep 1 25s [...] According to the output above, the IDLE power state count is 1. Let\u0026rsquo;s increase the state count by running this command:\nnsh\u0026gt; pmconfig stay idle Now the IDLE power state count needs to be 2:\nnsh\u0026gt; pmconfig # Output Last state 0, Next state 0 [...] /proc/pm/wakelock0: DOMAIN0 STATE COUNT TIME system normal 2 60s system idle 2 60s system standby 0 60s system sleep 1 60s [...] Changing the power state # Assuming that the system just booted up, here is the system state counts:\nnsh\u0026gt; pmconfig Last state 0, Next state 0 [...] /proc/pm/wakelock0: DOMAIN0 STATE COUNT TIME system normal 2 8s system idle 1 8s system standby 1 8s system sleep 1 8s [...] Let\u0026rsquo;s put the device into light sleep:\nnsh\u0026gt; pmconfig relax idle nsh\u0026gt; pmconfig relax normal nsh\u0026gt; pmconfig relax normal nsh\u0026gt; up_idlepm: newstate= 2 oldstate=0 up_idlepm: newstate= 0 oldstate=2 nsh\u0026gt; Let\u0026rsquo;s put the device into deep sleep:\nTo achieve this, the standby state must be removed in addition to the required steps for light sleep. The following example assumes that the system has just booted up. The power state counts for a freshly booted up system can be checked above.\nnsh\u0026gt; pmconfig relax standby nsh\u0026gt; pmconfig relax idle nsh\u0026gt; pmconfig relax normal nsh\u0026gt; pmconfig relax normal nsh\u0026gt; up_idlepm: newstate= 3 oldstate=0 ESP-ROM:esp32c6-20220919 Build:Sep 19 2022 rst:0x5 (DSLEEP),boot:0xc (SPI_FAST_FLASH_BOOT) SPIWP:0xee mode:DIO, clock div:2 load:0x40800000,len:0x7ee4 load:0x40807ef0,len:0xff0 SHA-256 comparison failed: Calculated: a2d5509f5471c59fa78a97c6f2cd7b2b4468a3a523ae330348591699de2bc9a1 Expected: 00000000f0700000000000000000000000000000000000000000000000000000 Attempting to boot anyway... entry 0x40807b9c *** Booting NuttX *** dram: lma 0x00000020 vma 0x40800000 len 0x7ee4 (32484) dram: lma 0x00007f0c vma 0x40807ef0 len 0xff0 (4080) padd: lma 0x00008f08 vma 0x00000000 len 0x70f0 (28912) imap: lma 0x00010000 vma 0x42020000 len 0xb200 (45568) padd: lma 0x0001b208 vma 0x00000000 len 0x4df0 (19952) imap: lma 0x00020000 vma 0x42000000 len 0x1f7e8 (129000) total segments stored 6 NuttShell (NSH) NuttX-10.4.0 nsh\u0026gt; When the device enters any sleep mode, it sleeps for a predefined duration by default. This duration can be modified during system configuration. The relevant configuration options are:\nLight sleep: The device sleeps for the sum of CONFIG_PM_ALARM_SEC seconds and CONFIG_PM_ALARM_NSEC nanoseconds. Deep sleep: The device sleeps for the sum of CONFIG_PM_SLEEP_WAKEUP_SEC seconds and CONFIG_PM_SLEEP_WAKEUP_NSEC nanoseconds. Other wakeup modes can be found in the related NuttX documentation. As an example, see the ESP32-C6 power management document.\nEntering Sleep Modes from Application # As mentioned on previous sections pm defconfig will be used for required configs to use power manager. Below is a snippet that lets the device to enter sleep modes by decreasing power state counts. To increase a power state count, in boardctl call, use the action BOARDIOC_PM_STAY instead of BOARDIOC_PM_RELAX.\n#include \u0026lt;nuttx/config.h\u0026gt; #include \u0026lt;nuttx/power/pm.h\u0026gt; #include \u0026lt;sys/boardctl.h\u0026gt; #include \u0026lt;sys/ioctl.h\u0026gt; static void remove_state(enum pm_state_e state) { int count; struct boardioc_pm_ctrl_s ctrl = { }; ctrl.action = BOARDIOC_PM_RELAX; count = pm_staycount(PM_IDLE_DOMAIN, state); for (int i = 0; i \u0026lt; count; i++) { ctrl.state = state; boardctl(BOARDIOC_PM_CONTROL, (uintptr_t)\u0026amp;ctrl); } } int main(int argc, char *argv[]) { if (deep_sleep) { /* Entering deep sleep */ remove_state(PM_STANDBY); } /* Entering light sleep */ remove_state(PM_IDLE); remove_state(PM_NORMAL); return 0; } For more information about custom applications on NuttX, please check the following documents.\nNuttX official custom apps guide, Integrating External Libraries into NuttX Applications Building Applications on NuttX: Understanding the Build System articles. Power Consumption Measurements # Test Benches # pm config used for all devices (e.g esp32c6-devkitc:pm). This config does not enable any RF circuitry.\nUSB power meter connected to the microcontroller and commands send through built in USB-UART converter. Microcontroller is powered through a multimeter for power measurement, while UART communication is handled separately via a USB-UART converter. Results # Device/Power State NORMAL STANDBY SLEEP ESP32 (esp32-devkitc) 42.3 mA 1.4 mA 1 mA ESP32-S2 (esp32s2-saola-1) 26 mA 2.1 mA 1.24 mA ESP32-S3 (esp32s3-devkitc) 46 mA 4.3 mA 1.24 mA ESP32-C3 (esp32c3-devkit) 18 mA 1 mA 815 μA ESP32-C6 (esp32c6-devkitc) 26 mA 1.32 mA 540 μA* ESP32-H2 (esp32h2-devkit) 14 mA 880 μA 510 μA** *: Overall board consumtion, module consumption is 48 μA\n**: Overall board consumtion, module consumption is 8 μA\nThese results are not optimized numbers and should not be considered as reference values.\nApplying these numbers to an application, a battery-powered embedded system with a 2000 mAh battery (a typical 18650 cell has capacity around 2500 mAh) could, in theory, extend its operating time from approximately 77 hours (about 3 days) to up to 3,703 hours (around 154 days) when using the esp32c6-devkitc, without any hardware changes. This is a purely theoretical estimate; in practice, actual gains will vary.\nConclusion # In this article, we explored the NuttX power management system and demonstrated how to use light sleep and deep sleep modes on Espressif microcontrollers, both from the NuttX shell and within NuttX applications.\nResources # Espressif sleep modes docs NuttX PM docs Getting Started with NuttX and ESP32 article Integrating External Libraries into NuttX Applications article Building Applications on NuttX: Understanding the Build System article NuttX Custom Apps How-to doc Building low power applications on Espressif chips: Ultra-Low-Power (ULP) coprocessor article ","date":"5 February 2026","externalUrl":null,"permalink":"/blog/2026/02/power-management-in-nuttx/","section":"Blog","summary":"This article walks through Espressif power modes and NuttX power states, then explains how they map to each other. Then it introduces NuttX’s power management system and the concept of governors. The how-to part shows how to control sleep modes from the shell and a custom application. Finally, you will see real power‑consumption measurements across multiple ESP chips to illustrate the practical impact using power states.","title":"Power Management in NuttX","type":"blog"},{"content":" Introduction # General Purpose Input/Output (GPIO) pins are fundamental interfaces on Espressif SoCs, enabling direct interaction with the physical world. They allow your device to read signals from sensors and switches, control LEDs and motors, and connect to a wide range of peripherals. Mastering GPIO usage is essential for building responsive and reliable embedded systems.\nAs with most modern architectures, these pins can be mapped to different functions. A GPIO can operate as a general-purpose digital pin or be assigned to a digital peripheral like SPI or UART. This configuration is handled transparently by the internal GPIO matrix.\nAs their name implies, GPIOs can function as both inputs and outputs. In this first article, we’ll focus on configuring and controlling an output GPIO pin.\nOutput configuration # All modern microcontrollers offer several ways to configure an output GPIO. We will discuss the two main options:\nPush-pull Open-drain Push-pull # The push pull configuration is shown in Fig.1.\nFig.1 - Push pull configuration\nIn this configuration, the output level is always well-defined because the internal MOSFETs actively drive the pin both high and low. The GPIO can both source current (when driving high) and sink current (when driving low), making it the most common configuration for general-purpose digital outputs.\nOpen Drain # The open drain configuration is shown in Fig.2. Fig.2 - Open drain configurations\nIn this configuration, the GPIO only sinks current and must be connected to an external power supply through a resistor. The output can actively drive a strong LOW, while the HIGH level is provided by the pull-up resistor.\nHistorically, this configuration was used to interface with higher voltages. An open-drain output allowed a low-voltage logic device to safely control or signal a higher-voltage system without ever driving that higher voltage internally. The device would only pull the line LOW, while the external pull-up defined the HIGH level.\nSince Espressif GPIOs have a maximum output voltage of 3.6 V, this configuration is now mainly used to share a bus among multiple devices, as in I²C communication. You can connect many output drain pins to the same node, while you can\u0026rsquo;t do the same with push-pull outputs.\nMaximum output current # When you drive a pin HIGH or LOW, and the pin is connected to a load, you must supply enough current to maintain the desired logic level. Consider a simple 330 Ω resistor connected to your GPIO:\nFig. 3 - GPIO output load\nFor Espressif modules, a digital value of one corresponds to a voltage of 3.3 V. To maintain this voltage across a 330 Ω resistor, the SoC must supply 10 mA. In Espressif documentation, the maximum output current is referred to as drive capability. You can configure this value for each GPIO, and the default setting is 20 mA. This means you cannot reliably drive a load with an equivalent resistance lower than 165 Ω.\nEspressif GPIO peripheral # To use any peripheral, you should follow three steps:\nInclude the peripheral driver. Configure the peripheral. Use the peripheral. Let’s look at each of these steps for the GPIO peripheral.\nInclude the peripheral driver # The instructions for including a library can be found in the ESP-IDF Programming Guide, under the relevant peripheral API reference, in the Header File section.\nFor example, the GPIO API reference shows that the GPIO peripheral is managed through the driver/gpio.h library, which must be included as:\n#include \u0026#34;driver/gpio.h\u0026#34; If you are using it inside the main component, which by default already depends on all ESP-IDF components, no additional actions are needed. For other components, you must add one of the following to its CMakeLists.txt:S\nREQUIRES esp_driver_gpio or\nPRIV_REQUIRES esp_driver_gpio Configure the library # To use a GPIO as an output, we need to specify:\nDirection (output) Mode (push-pull) In Espressif, both direction and mode are managed through the gpio_mode_t enum and are therefore set together using the gpio_set_direction function.\nMode name gpio_mode_t Description Disable GPIO_MODE_DISABLE Disables the GPIO completely. Both input and output functions are turned off, leaving the pin inactive. Input GPIO_MODE_INPUT Configures the GPIO as input only, allowing it to read external logic levels without driving the pin. Output (Push-Pull) GPIO_MODE_OUTPUT Configures the GPIO as output only in push-pull mode, actively driving both HIGH and LOW levels. Output (Open-Drain) GPIO_MODE_OUTPUT_OD Configures the GPIO as output only in open-drain mode. The pin can pull the line LOW and requires a pull-up for HIGH. Input / Output (Open-Drain) GPIO_MODE_INPUT_OUTPUT_OD Enables both input and output in open-drain mode, typically used for shared or bidirectional lines such as I²C. Input / Output (Push-Pull) GPIO_MODE_INPUT_OUTPUT Enables both input and output in push-pull mode, useful when the pin must both drive and read a signal. For example, to set GPIO5 as a push-pull output we can use\ngpio_set_direction(5,GPIO_MODE_OUTPUT); There are additional functions for adjusting the GPIO configuration, such as gpio_od_enable and gpio_od_disable, which enable and disable open-drain mode respectively. The complete list of available APIs can be found in the GPIO section of the programming guide’s API reference Check the configuration # To inspect the configuration of all GPIOs, ESP-IDF provides the function gpio_dump_io_configuration.\nIf we only call gpio_set_direction(5, GPIO_MODE_OUTPUT);, the dump for GPIO 5 looks like this:\nIO[5] - Pullup: 0, Pulldown: 0, DriveCap: 2 InputEn: 0, OutputEn: [periph_sig_ctrl], OpenDrain: 0 FuncSel: 1 (GPIO) GPIO Matrix SigOut ID: 256 (simple GPIO output) SleepSelEn: 0 From this output, you can see:\nDriveCap \u0026ndash; shows the configured drive capability OpenDrain: 0 \u0026ndash; open-drain mode is disabled meaning that the pin is set up for standard GPIO output A complete GPIO configuration dump is shown below.\nShow full GPIO dump ================IO DUMP Start================ IO[0] - Pullup: 0, Pulldown: 0, DriveCap: 2 InputEn: 0, OutputEn: [periph_sig_ctrl], OpenDrain: 0 FuncSel: 1 (GPIO) GPIO Matrix SigOut ID: 256 (simple GPIO output) SleepSelEn: 0 IO[1] - Pullup: 0, Pulldown: 0, DriveCap: 2 InputEn: 0, OutputEn: [periph_sig_ctrl], OpenDrain: 0 FuncSel: 1 (GPIO) GPIO Matrix SigOut ID: 256 (simple GPIO output) SleepSelEn: 0 IO[2] - Pullup: 0, Pulldown: 0, DriveCap: 2 InputEn: 0, OutputEn: [periph_sig_ctrl], OpenDrain: 0 FuncSel: 1 (GPIO) GPIO Matrix SigOut ID: 256 (simple GPIO output) SleepSelEn: 0 IO[3] - Pullup: 0, Pulldown: 0, DriveCap: 2 InputEn: 1, OutputEn: [periph_sig_ctrl], OpenDrain: 0 FuncSel: 0 (IOMUX) SleepSelEn: 0 IO[4] - Pullup: 0, Pulldown: 0, DriveCap: 2 InputEn: 1, OutputEn: [periph_sig_ctrl], OpenDrain: 0 FuncSel: 0 (IOMUX) SleepSelEn: 0 IO[5] - Pullup: 0, Pulldown: 0, DriveCap: 2 InputEn: 0, OutputEn: [periph_sig_ctrl], OpenDrain: 0 FuncSel: 1 (GPIO) GPIO Matrix SigOut ID: 256 (simple GPIO output) SleepSelEn: 0 IO[6] - Pullup: 0, Pulldown: 0, DriveCap: 2 InputEn: 1, OutputEn: [periph_sig_ctrl], OpenDrain: 0 FuncSel: 0 (IOMUX) SleepSelEn: 0 IO[7] - Pullup: 0, Pulldown: 0, DriveCap: 2 InputEn: 1, OutputEn: [periph_sig_ctrl], OpenDrain: 0 FuncSel: 1 (GPIO) GPIO Matrix SigOut ID: 256 (simple GPIO output) GPIO Matrix SigIn ID: (simple GPIO input) SleepSelEn: 0 IO[8] - Pullup: 0, Pulldown: 0, DriveCap: 2 InputEn: 1, OutputEn: [periph_sig_ctrl], OpenDrain: 0 FuncSel: 1 (GPIO) GPIO Matrix SigOut ID: 256 (simple GPIO output) GPIO Matrix SigIn ID: (simple GPIO input) SleepSelEn: 0 IO[9] - Pullup: 1, Pulldown: 0, DriveCap: 2 InputEn: 1, OutputEn: [periph_sig_ctrl], OpenDrain: 0 FuncSel: 1 (GPIO) GPIO Matrix SigOut ID: 256 (simple GPIO output) GPIO Matrix SigIn ID: (simple GPIO input) SleepSelEn: 0 IO[10] - Pullup: 1, Pulldown: 0, DriveCap: 2 InputEn: 1, OutputEn: [periph_sig_ctrl], OpenDrain: 0 FuncSel: 0 (IOMUX) SleepSelEn: 0 IO[11] - Pullup: 1, Pulldown: 0, DriveCap: 2 InputEn: 1, OutputEn: [periph_sig_ctrl], OpenDrain: 0 FuncSel: 0 (IOMUX) SleepSelEn: 0 IO[12] - Pullup: 0, Pulldown: 0, DriveCap: 3 InputEn: 1, OutputEn: [periph_sig_ctrl], OpenDrain: 0 FuncSel: 1 (GPIO) GPIO Matrix SigOut ID: 256 (simple GPIO output) GPIO Matrix SigIn ID: (simple GPIO input) SleepSelEn: 0 IO[13] - Pullup: 0, Pulldown: 0, DriveCap: 3 InputEn: 1, OutputEn: [periph_sig_ctrl], OpenDrain: 0 FuncSel: 1 (GPIO) GPIO Matrix SigOut ID: 256 (simple GPIO output) GPIO Matrix SigIn ID: (simple GPIO input) SleepSelEn: 0 IO[14] - Pullup: 1, Pulldown: 0, DriveCap: 2 InputEn: 1, OutputEn: [periph_sig_ctrl], OpenDrain: 0 FuncSel: 1 (GPIO) GPIO Matrix SigOut ID: 256 (simple GPIO output) GPIO Matrix SigIn ID: (simple GPIO input) SleepSelEn: 0 IO[15] **RESERVED** - Pullup: 1, Pulldown: 0, DriveCap: 1 InputEn: 1, OutputEn: [periph_sig_ctrl], OpenDrain: 0 FuncSel: 0 (IOMUX) SleepSelEn: 0 IO[16] **RESERVED** - Pullup: 1, Pulldown: 0, DriveCap: 1 InputEn: 1, OutputEn: [periph_sig_ctrl], OpenDrain: 0 FuncSel: 0 (IOMUX) SleepSelEn: 0 IO[17] **RESERVED** - Pullup: 1, Pulldown: 0, DriveCap: 1 InputEn: 1, OutputEn: [periph_sig_ctrl], OpenDrain: 0 FuncSel: 1 (GPIO) GPIO Matrix SigOut ID: 256 (simple GPIO output) GPIO Matrix SigIn ID: (simple GPIO input) SleepSelEn: 0 IO[18] - Pullup: 0, Pulldown: 0, DriveCap: 2 InputEn: 0, OutputEn: [periph_sig_ctrl], OpenDrain: 0 FuncSel: 1 (GPIO) GPIO Matrix SigOut ID: 256 (simple GPIO output) SleepSelEn: 0 IO[19] **RESERVED** - Pullup: 1, Pulldown: 0, DriveCap: 1 InputEn: 1, OutputEn: [periph_sig_ctrl], OpenDrain: 0 FuncSel: 1 (GPIO) GPIO Matrix SigOut ID: 256 (simple GPIO output) GPIO Matrix SigIn ID: (simple GPIO input) SleepSelEn: 0 IO[20] **RESERVED** - Pullup: 1, Pulldown: 0, DriveCap: 1 InputEn: 1, OutputEn: [periph_sig_ctrl], OpenDrain: 0 FuncSel: 0 (IOMUX) SleepSelEn: 0 IO[21] **RESERVED** - Pullup: 1, Pulldown: 0, DriveCap: 1 InputEn: 1, OutputEn: [periph_sig_ctrl], OpenDrain: 0 FuncSel: 0 (IOMUX) SleepSelEn: 0 IO[22] - Pullup: 0, Pulldown: 0, DriveCap: 2 InputEn: 1, OutputEn: [periph_sig_ctrl], OpenDrain: 0 FuncSel: 1 (GPIO) GPIO Matrix SigOut ID: 256 (simple GPIO output) GPIO Matrix SigIn ID: (simple GPIO input) SleepSelEn: 0 IO[23] - Pullup: 0, Pulldown: 0, DriveCap: 2 InputEn: 1, OutputEn: [periph_sig_ctrl], OpenDrain: 0 FuncSel: 1 (GPIO) GPIO Matrix SigOut ID: 256 (simple GPIO output) GPIO Matrix SigIn ID: (simple GPIO input) SleepSelEn: 0 IO[24] - Pullup: 0, Pulldown: 0, DriveCap: 2 InputEn: 0, OutputEn: [periph_sig_ctrl], OpenDrain: 0 FuncSel: 1 (GPIO) GPIO Matrix SigOut ID: 256 (simple GPIO output) SleepSelEn: 0 IO[25] - Pullup: 0, Pulldown: 0, DriveCap: 2 InputEn: 1, OutputEn: [periph_sig_ctrl], OpenDrain: 0 FuncSel: 1 (GPIO) GPIO Matrix SigOut ID: 256 (simple GPIO output) GPIO Matrix SigIn ID: (simple GPIO input) SleepSelEn: 0 IO[26] - Pullup: 0, Pulldown: 0, DriveCap: 2 InputEn: 1, OutputEn: [periph_sig_ctrl], OpenDrain: 0 FuncSel: 1 (GPIO) GPIO Matrix SigOut ID: 256 (simple GPIO output) GPIO Matrix SigIn ID: (simple GPIO input) SleepSelEn: 0 IO[27] - Pullup: 0, Pulldown: 0, DriveCap: 2 InputEn: 1, OutputEn: [periph_sig_ctrl], OpenDrain: 0 FuncSel: 1 (GPIO) GPIO Matrix SigOut ID: 256 (simple GPIO output) GPIO Matrix SigIn ID: (simple GPIO input) SleepSelEn: 0 IO[28] - Pullup: 0, Pulldown: 0, DriveCap: 2 InputEn: 1, OutputEn: [periph_sig_ctrl], OpenDrain: 0 FuncSel: 1 (GPIO) GPIO Matrix SigOut ID: 256 (simple GPIO output) GPIO Matrix SigIn ID: (simple GPIO input) SleepSelEn: 0 IO[29] - Pullup: 0, Pulldown: 0, DriveCap: 2 InputEn: 0, OutputEn: [periph_sig_ctrl], OpenDrain: 0 FuncSel: 1 (GPIO) GPIO Matrix SigOut ID: 256 (simple GPIO output) SleepSelEn: 0 =================IO DUMP End================= Use the library # For an output GPIO, the only required function is to set the output level to low or high. The function is gpio_set_level.\ngpio_set_level(5, 0); // GPIO 5 set to 0 gpio_set_level(5, 1); // GPIO 5 set to 1 Choose the right pin # Espressif modules include multiple pins labelled GPIOs. Before using a GPIO in your application, make sure the pin:\nDoes not function as a strapping pin Supports output, not just input Is not internally connected to the module’s flash or PSRAM You can verify this in the Pin Overview cheatsheet. For more details, find a chip datasheet for your chip and go to the Pins section.\nPractical example # To demonstrate this, we will develop a simple blinking application from scratch. In this example, we will use an ESP32-C61-DevKitC-1, but any Espressif module and EVK can be used. We will use VS Code and ESP-IDF Extension for VS Code.\nConnect the LED # Most modern Espressif DevKits do not have a simple onboard LED (also called a GPIO LED) and typically feature RGB LEDs instead. For this reason, we need to connect an external LED to a GPIO. We will use GPIO5.\nThe connection is shown in Fig.4. Fig.4 - Connections\nIn the schematic, a 100 Ohm resistor is chosen based on an LED forward voltage of 2.7V and a forward current of 6mA. If you use an LED with different specifications, adjust the resistor value accordingly. Create a new empty project # Open VS Code \u0026gt; ESP-IDF: Create a New Empty Project → name it led-test Click on the pop-up asking to open the new project Include the library # In main.c, include the libraries for GPIO, FreeRTOS (for the delay), and the logging library for output. You can remove stdio.h since its functions will not be used.\n#include \u0026#34;esp_log.h\u0026#34; #include \u0026#34;driver/gpio.h\u0026#34; #include \u0026#34;freertos/FreeRTOS.h\u0026#34; #include \u0026#34;freertos/task.h\u0026#34; Configure the library # For this simple application, we only need to set GPIO5 as an output. To keep things organized, we will define its value after the includes. In the same place, we also define the TAG string for logging. For more on tags and logging, make sure to check out the article ESP-IDF tutorial series: Logging.\n#define LED_GPIO 5 static const char *TAG = \u0026#34;LED_TEST\u0026#34;; In the app_main function we can configure it as:\ngpio_set_direction(LED_GPIO,GPIO_MODE_OUTPUT); Use the library # Next, we need to create the loop that will handle the LED driving.\nuint32_t led_state = 0; // keep track of the led state while (1) { // Toggle the LED state led_state = !led_state; // Drive the led gpio_set_level(LED_GPIO, led_state); // Feedback on terminal ESP_LOGI(TAG,\u0026#34;Status:%s\u0026#34;, led_state? \u0026#34;ON\u0026#34;:\u0026#34;OFF\u0026#34;); // Delay of 0.5s vTaskDelay(pdMS_TO_TICKS(500)); } In the log we used the C ternary opeartor to show the string \u0026ldquo;ON\u0026rdquo; and \u0026ldquo;OFF\u0026rdquo; instead of one and zero.\nThe vTaskDelay function takes the number of ticks as its argument. To work with milliseconds instead of ticks, we can use the pdMS_TO_TICKS macro, which converts a given millisecond value to the corresponding number of ticks. Example code main.c\n#include \u0026#34;esp_log.h\u0026#34; #include \u0026#34;driver/gpio.h\u0026#34; #include \u0026#34;freertos/FreeRTOS.h\u0026#34; #include \u0026#34;freertos/task.h\u0026#34; #define LED_GPIO 5 static const char * TAG = \u0026#34;LED_TEST\u0026#34;; void app_main(void) { ESP_LOGI(TAG,\u0026#34;** GPIO get started tutorial ** \u0026#34;); gpio_set_direction(LED_GPIO,GPIO_MODE_OUTPUT); uint32_t led_state = 0; while (1) { // Toggle the LED state led_state = !led_state; // Drive the led gpio_set_level(LED_GPIO, led_state); // Feedback on terminal ESP_LOGI(TAG,\u0026#34;Status:%s\u0026#34;, led_state? \u0026#34;ON\u0026#34;:\u0026#34;OFF\u0026#34;); // Delay of 0.5s vTaskDelay(pdMS_TO_TICKS(500)); } } Conclusion # In this article, we went through a practical introduction to GPIO programming. We explored how to configure and control an output GPIO on Espressif SoCs, set up a blinking LED, and used FreeRTOS for timing.\nIn the next article, we will explore how to use a GPIO as an input.\nGo to Part 2\n","date":"2 February 2026","externalUrl":null,"permalink":"/blog/2026/02/esp-idf-tutorial-gpio-get-started/","section":"Blog","summary":"This article explains how to configure and control GPIO pins on Espressif SoCs, covering push-pull and open-drain output modes, drive capability, and library usage. It then provides a hands-on example of blinking an LED using \u003ccode\u003egpio_set_direction\u003c/code\u003e and \u003ccode\u003egpio_set_level\u003c/code\u003e on a ESP32-C61-DevKitC.","title":"ESP-IDF tutorial series: GPIO get started - Part 1","type":"blog"},{"content":"","date":"2 February 2026","externalUrl":null,"permalink":"/tags/led/","section":"Tags","summary":"","title":"LED","type":"tags"},{"content":" Introduction # Today we\u0026rsquo;re excited to announce the ESP-IDF port of the Amazon KVS WebRTC SDK, bringing enterprise-grade WebRTC video streaming capabilities to Espressif\u0026rsquo;s microcontrollers. This port includes significant optimizations for ESP32 devices, enabling real-time audio and video streaming with features like STUN/TURN ICE servers, two-way audio/video streaming, data channel support, and WebRTC ingestion for ingesting video to KVS.\nEspressif\u0026rsquo;s adaptation goes beyond a simple port—it introduces revolutionary features like WebRTC Split Mode for battery-powered devices, memory footprint optimizations, and a simplified API that makes WebRTC integration straightforward for developers.\nAs a demonstration of the SDK\u0026rsquo;s capabilities, we\u0026rsquo;re also announcing ESP RainMaker Camera—a production-ready camera solution built on top of the KVS WebRTC SDK. ESP RainMaker is already trusted across a wide range of IoT devices, and now with camera support, developers can build secure, low-latency streaming solutions with minimal effort.\nAmazon KVS WebRTC SDK For ESP # The Amazon KVS WebRTC SDK for ESP is a complete ESP-IDF adaptation of Amazon\u0026rsquo;s WebRTC SDK, specifically optimized for Espressif\u0026rsquo;s resource-constrained microcontrollers. This port enables real-time audio and video streaming on ESP32 devices with enterprise-grade features.\nKey Adaptations and Enhancements # Memory Footprint Optimizations # The ESP port introduces several memory optimizations critical for microcontroller deployments:\nAlternative WebSocket Client: Option to use esp_websocket_client as an alternative to libwebsockets, reducing memory footprint Dynamic Memory Allocations: By default, KVS uses static allocation of large buffers (~20KB) for each signaling message. The ESP port implements dynamic allocation strategies, allowing all messages to fit within the same memory footprint SPIRAM Integration: Modified memory allocation APIs to use SPIRAM (external RAM) wherever possible, preserving precious internal SRAM for critical operations WebRTC Split Mode # One of the most significant innovations is the WebRTC Split Mode architecture:\nDual-Device Architecture: Split mode distributes WebRTC functionality across two processors: Media Processor (e.g., ESP32-P4): Handles video/audio capture, encoding, and streaming Network Processor (e.g., ESP32-C6 or ESP32-C5): Handles network connectivity and signaling with AWS KVS Power Optimization: The media processor can enter deep sleep when not streaming, while the network processor maintains connectivity in light sleep mode Instant Wake-up: Shared network stack enables immediate IP address acquisition after wake-up, eliminating connection delays Battery-Powered Applications: This architecture enables battery-powered camera devices with significantly reduced power consumption Simplified API with Smart Defaults # The SDK provides a simplified high-level API that reduces configuration complexity. This architecture allows developers to mix and match components based on their specific requirements, whether building a simple single-device solution or a complex multi-device system.\nDeployment Architectures # The SDK supports multiple deployment architectures, each optimized for different use cases:\nSplit Mode - Dual Chip Solution (e.g., ESP32-P4 Function EV Board or C5 Core Board):\nDeployment Architecture (Option 1) Standalone Mode\nDual Chip Solution (e.g., ESP32-P4 Function EV Board with network adapter). (Refer option 2) Single Chip Solution (e.g., ESP32-S3-EYE). (Refer option 3). Deployment Architecture (Option 2 and Option 3) Examples by Espressif # The KVS WebRTC SDK ESP port includes comprehensive examples demonstrating different deployment scenarios. Each example showcases specific capabilities and use cases:\nExample Comparison # Example Signaling Peer Connection Hardware Power Profile Best For webrtc_classic/ KVS KVS Single ESP32 Standard Learning, AWS integration esp_camera/ AppRTC KVS Single ESP32 Standard Browser testing, no AWS split_mode/ Battery-powered 2-chip Camera Implementation with 2 firmwares from the following rows: split_mode/streaming_only/ Bridge KVS ESP32-P4 Deep sleep capable Battery-powered streaming split_mode/signaling_only/ KVS Bridge ESP32-C6/C5 Light sleep Always-on connectivity Note: streaming_only and signaling_only work together as a pair for split mode deployments. They are typically used together on dual-chip boards like the ESP32-P4 Function EV Board (ESP32-P4 + ESP32-C6) or ESP32-P4-C5 Core Board (ESP32-P4 + ESP32-C5).\nFor detailed setup instructions and API documentation, see the esp_port README and API_USAGE.md.\nESP RainMaker Camera - Production Use-Case # ESP RainMaker Camera demonstrates a production-ready camera solution built on top of the KVS WebRTC SDK. It showcases how the SDK\u0026rsquo;s features can be integrated with ESP RainMaker\u0026rsquo;s device management ecosystem to create a complete, secure camera solution.\nThe demonstration below shows the ESP RainMaker Camera in action:\nRainMaker Camera Demonstration\nHow RainMaker Camera Leverages KVS SDK # It leverages several key SDK features:\nSimplified API: Uses the SDK\u0026rsquo;s 4-line configuration approach with smart defaults Split Mode Architecture: Implements the split mode for battery-powered deployments Credential Management: Integrates RainMaker\u0026rsquo;s streamlined AWS credential API with the SDK\u0026rsquo;s credential callback mechanism Pluggable Interfaces: Uses KVS signaling and peer connection interfaces seamlessly RainMaker Camera Components # ESP RainMaker consists of 3 main components:\nCloud Backend Open Source Phone apps: Android and iOS Open Source Firmware SDK Camera support has been added to all components, enabling developers to start using it immediately with no custom development required.\nESP RainMaker Camera Architecture Overview Architecture # RainMaker Camera follows the same deployment architectures as the KVS WebRTC SDK, supporting both standalone and split mode configurations. The standalone mode can run on a single chip (e.g., ESP32-S3-EYE) or use a dual-chip setup with a network adapter, while split mode distributes signaling and streaming across two processors for optimal power efficiency. The architecture diagrams shown in the Amazon KVS WebRTC SDK For ESP section above illustrate these deployment patterns.\nKey Capabilities # ESP32-P4 Performance: Takes full advantage of the ESP32-P4\u0026rsquo;s processing power, enabling smooth 1080p@30fps audio and video streaming. The ESP32-P4 provides MIPI-CSI support for camera capture and hardware H.264 encoding, making it ideal for next-generation connected camera applications.\nBattery-Powered Operation: RainMaker Camera is the first WebRTC camera running on microcontrollers that supports battery-powered operation. It uses the SDK\u0026rsquo;s split mode architecture:\nSignaling and streaming are split across two different chips ESP32-P4 handles streaming and can enter deep sleep when idle ESP32-C6 or ESP32-C5 maintains connectivity in light sleep mode Both devices wake up only when streaming is requested After streaming ends, both devices return to sleep, saving significant power Security and Privacy: Delivers strong security and privacy safeguards that modern regulations require, ensuring safe and compliant remote viewing. RainMaker securely stores device certificates and provides APIs for obtaining security tokens used by the KVS signaling connection.\nDeveloper Experience: Building a RainMaker Camera feels like building any other RainMaker device. Developers keep the familiar ESP-IDF workflow, add camera support, and stay aligned with ESP-RainMaker\u0026rsquo;s philosophy of simple and flexible APIs. Signaling and credentials are managed transparently without requiring developers to handle the details.\nEnd-User Experience: Provisioning happens through the RainMaker app, live streaming is just a click away, and security is backed by Espressif hardware and the ESP-IDF community.\nBusiness Value: Provides a low-cost, full-fledged solution that enables rapid prototyping and faster time-to-market, built on robust ecosystem support.\nChoosing the Right Hardware # The KVS WebRTC SDK ESP port supports a range of ESP32 development boards. The same hardware can be used with different examples depending on your use case. Here\u0026rsquo;s a unified guide to help you choose:\nBoard Video Encoding Compatible Examples Power Profile Best For ESP32‑P4‑Function EV 1080p@30fps Hardware H.264 webrtc_classic, esp_camera, streaming_only+signaling_only (split mode), RainMaker Camera (standalone or split) Standard or Battery-powered Production streaming, power optimization ESP32‑P4‑C5 Core Board 1080p@30fps Hardware H.264 webrtc_classic, esp_camera, streaming_only+signaling_only (split mode), RainMaker Camera (standalone or split) Standard or Battery-powered Premium performance, 5GHz Wi-Fi ESP32‑S3‑EYE QVGA@5-10FPS Software only webrtc_classic, esp_camera, RainMaker Camera (standalone) Standard Development, testing, prototyping Hardware Details:\nESP32‑P4‑Function EV Board: Production-grade board with hardware H.264 encoder. Has both ESP32-P4 and ESP32-C6 onboard, enabling standalone or split mode deployments. Docs ESP32‑P4‑C5 Core Board: Premium solution similar to Function EV Board, but with ESP32-C5 (instead of C6) for network processing. Features 5GHz Wi-Fi connectivity and supports both standalone and split mode deployments. ESP32‑S3‑EYE: Built-in camera and microphone, ideal for development/testing. Guide Important Notes:\nFor standalone mode (webrtc_classic, esp_camera, or RainMaker Camera standalone) on dual-chip boards (ESP32-P4 Function EV or C5 Core Board), the network processor (ESP32-C6 or ESP32-C5) must be flashed with the network_adapter firmware, which acts as a Wi-Fi modem. The network processor transparently forwards network traffic to the main processor. For split mode (streaming_only + signaling_only), both the ESP32-P4 Function EV Board and ESP32-P4-C5 Core Board are ideal as they have both processors onboard. The Function EV Board has ESP32-P4 (for streaming) and ESP32-C6 (for signaling), while the C5 Core Board has ESP32-P4 (for streaming) and ESP32-C5 (for signaling with 5GHz Wi-Fi). The network processor handles signaling while the P4 handles streaming and can sleep when not in use, enabling battery-powered camera applications. Getting Started with Examples # We provide two sets of examples, based on what you intend to do.\nExamples with AWS KVS WebRTC SDK: These are available in the AWS KVS repository. These examples demonstrate the core SDK capabilities and provide a foundation for building your own WebRTC applications. If you have an existing solutions with AWS KVS, or are building one from scratch, prefer this to get started with. Examples with ESP RainMaker Camera: These are available in the RainMaker Camera repository. These examples demonstrate an end-to-end usecase facilitated with our free ESP RainMaker deployment. If you want to try and end-to-end camera demonstration quickly, prefer this to get started with. Upcoming features # Support For New Dev Board: Support for more development kits out of the box Activity detection: Detecting different kinds of activity using AI and vision capabilities to take smart actions Clip Storage: Local Storage: Storing the feed to local storage for viewing later Cloud Storage: Optionally uploading of important clips to the RainMaker cloud for later viewing Multi-client: More robust streaming for concurrent viewing Two-way Audio+Video: For certain use-cases like video doorbells Do give it a try and let us know what you build! Feedback is welcome.\nNOTE\nStarting from version 3.4.0, camera support is available for private deployments. Please contact Espressif for the details. ","date":"30 January 2026","externalUrl":null,"permalink":"/blog/2026/01/kvs-webrtc-sdk-esp-announcement/","section":"Blog","summary":"This article announces the ESP-IDF port of \u003ca\n  href=\"https://github.com/awslabs/amazon-kinesis-video-streams-webrtc-sdk-c/tree/beta-reference-esp-port\"\n    target=\"_blank\"\n  \u003eAmazon KVS WebRTC SDK\u003c/a\u003e, featuring memory optimizations, split mode power savings, and a simplified API. We also showcase ESP RainMaker Camera as a production-ready use-case built on this SDK.","title":"Amazon KVS WebRTC SDK for Espressif Chipsets and ESP RainMaker Camera","type":"blog"},{"content":"","date":"30 January 2026","externalUrl":null,"permalink":"/tags/aws/","section":"Tags","summary":"","title":"AWS","type":"tags"},{"content":"","date":"30 January 2026","externalUrl":null,"permalink":"/tags/camera/","section":"Tags","summary":"","title":"Camera","type":"tags"},{"content":"","date":"30 January 2026","externalUrl":null,"permalink":"/tags/esp-rainmaker/","section":"Tags","summary":"","title":"ESP-Rainmaker","type":"tags"},{"content":"","date":"30 January 2026","externalUrl":null,"permalink":"/tags/esp32p4/","section":"Tags","summary":"","title":"ESP32P4","type":"tags"},{"content":"","date":"30 January 2026","externalUrl":null,"permalink":"/tags/espressif/","section":"Tags","summary":"","title":"Espressif","type":"tags"},{"content":"","date":"30 January 2026","externalUrl":null,"permalink":"/tags/kvs/","section":"Tags","summary":"","title":"KVS","type":"tags"},{"content":" ESP RainMaker is a complete, yet light-weight, AIoT solution that enables private Cloud deployment for your business in a simple, cost-effective and efficient manner.\nQuick Links Here you can find the relevant links:\nDocumentation FAQ Dashboard RainMaker Related Articles ","date":"30 January 2026","externalUrl":null,"permalink":"/tags/rainmaker/","section":"Tags","summary":"","title":"RainMaker","type":"tags"},{"content":"","date":"30 January 2026","externalUrl":null,"permalink":"/authors/vikram-dattu/","section":"Developer Portal Authors","summary":"","title":"Vikram-Dattu","type":"authors"},{"content":"","date":"30 January 2026","externalUrl":null,"permalink":"/tags/webrtc/","section":"Tags","summary":"","title":"WebRTC","type":"tags"},{"content":"","date":"21 January 2026","externalUrl":null,"permalink":"/tags/announcement/","section":"Tags","summary":"","title":"Announcement","type":"tags"},{"content":"","date":"21 January 2026","externalUrl":null,"permalink":"/tags/esp32-p4/","section":"Tags","summary":"","title":"ESP32-P4","type":"tags"},{"content":"Today, we are excited to announce Matter-based camera support for Espressif SoCs: the industry’s first implementation for MCU-based camera devices.\nIn November 2025, the Connectivity Standards Alliance launched camera support in Matter 1.5. This enables device makers to build interoperable camera devices that work across any Matter ecosystem without requiring custom applications or interfaces. The Matter specification uses the widely adopted WebRTC framework to enable this functionality.\nCamera enables a variety of related device types in Matter 1.5: Video Doorbell – A camera and a generic switch to provide a doorbell with video and audio streaming Audio Doorbell - A camera that is paired with a generic switch for audio streaming Floodlight - A camera and light primarily used in security use cases Snapshot camera - Support retrieving still images on-demand Intercom - Provides two-way on demand communication facilities between devices Chime - Play a range of pre-installed sounds, usually paired with a doorbell. This is not directly a camera device type, but can be integrated with it. Matter camera support delivers the following advantages:\nFor remote viewing of the feed, Matter provides the ability for the controllers (or ecosystems) to configure the STUN/TURN servers on the cameras. This is a major benefit for the camera device manufacturers, who won\u0026rsquo;t explicitly need to manage NAT traversal on their own. Allows the use of Secure Frame (SFrame) to enable end-to-end encrypted live camera streaming in complex, multi-device ecosystems where streams may be forwarded to multiple users. Supports recorded media upload using the standard Common Media Application Format (CMAF), with optional encryption. Includes a two dimensional cartesian zone feature to define the areas for privacy masking or motion detection in the video stream. It also facilitates the digital Pan-Tilt-Zoom (PTZ) feature through which the camera can cover multiple zones Technical Overview # The following diagram showcases the high-level architecture of Matter cameras: Matter Camera Architecture\nDetailed Workflow # A Matter enabled controller (like a phone app) commissions the camera device into the Matter fabric. Thereafter, when an user requests a video stream, the process begins with the Camera AV Stream Management cluster. It validates the request, checks for compatible stream configurations, and ensures that sufficient resources are available by querying the underlying camera device hardware.\nThen the Matter controller initiates a WebRTC session by sending Session Description Protocol (SDP) offer to the camera device using the WebRTC Transport Provider and Requestor clusters. It creates a new WebRTC transport, sets the remote description with the offer, and requests allocation of the necessary audio and video streams.\nOnce the streams are successfully allocated, the camera device generates SDP answer and sends it back to the controller. Next, the controller provides Interactive Connectivity Establishment (ICE) candidates to establish network connectivity. The camera device adds these remote candidates to the transport, gathers candidates, and delivers them back to the client. Once ICE negotiation completes, the WebRTC session is established and the P2P live audio/video streaming begins.\nCamera - Data Model # The camera capabilities are built on top of the following clusters in Matter - Camera AV Stream Management - This cluster provides the standardized interface for managing, controlling, and configuring audio, video, and snapshot streams on a camera device. It defines attributes and commands to negotiate stream resources (such as video/audio codecs, resolutions, and multiple concurrent stream usages like live view, recording, or analytics), allocate and release stream sessions, and coordinate priorities between them. Camera AV Settings User Level Management - This cluster defines user-level attributes and commands for controlling a camera’s audio and video settings, including resolution, frame rate, bitrate, and PTZ (Pan-Tilt-Zoom) related parameters. It provides a standardized interface for reading and updating camera capture and streaming behavior. Push AV Stream Transport - This cluster defines standardized mechanisms for cameras to push audio/video stream data to a remote transport endpoint (such as a cloud ingest server or recorder) in response to triggers or events. It can allocate, configure, modify, and deallocate stream transport connections, manage transport options (like trigger conditions and metadata), and report transport status and events back to a controller. This enables event‑driven media uploads (e.g., motion‑activated clip delivery) WebRTC Transport Provider - This cluster defines the interface that a camera device uses to provide WebRTC‑based transport endpoints for real‑time audio and video streams. It includes commands and attributes for negotiating WebRTC sessions, exchanging SDP offers/answers, handling ICE candidates and connection state, and managing secure, low‑latency media transport using established WebRTC mechanisms. By leveraging mature WebRTC technologies for NAT traversal and media negotiation. Zone Management - This Matter cluster provides a standardized way for devices (such as cameras and sensors) to define and manage logical zones—distinct regions of interest within a device’s field of view or coverage area. It defines attributes and commands to create, modify, and query zone configurations, including shape, size, and behavioral associations (e.g., motion detection or privacy masking). By standardizing zone definitions and interactions, this cluster enables controllers to consistently understand and control region‑based behavior. Espressif Matter Camera # While most cameras run Linux-based systems, our ESP32-P4 based MCU camera is first of its kind. It offers significant advantages over traditional Linux-based camera solutions, making it a smarter choice for both device makers and end users.\nBattery-Powered Operation: We use a split-mode WebRTC architecture that splits the streaming and signaling parts across two SoCs.The streaming is directly handled by the ESP32-P4, while the signaling is handled by the ESP32-C5/C6.This enables true battery-powered camera implementations. The ESP32-P4 can operate in Deep-sleep mode when not actively streaming, consuming minimal power, while the ESP32-C5/C6 maintains Wi-Fi connectivity in Light-sleep mode. This power-efficient design allows cameras to run on battery power for extended periods. The ESP32-P4 only wakes up when streaming is actively requested, drastically reducing overall power consumption.\nEnhanced Security: MCU-based cameras offer a significantly smaller attack surface compared to Linux-based systems. Without a full operating system, complex package managers, or numerous running services, the potential attack vectors are substantially reduced. This minimalist approach means fewer vulnerabilities and a more secure device overall.\nCost-Effective Design: MCU-based solutions eliminate the need for expensive application processors, large memory modules, and complex power management systems required by Linux-based cameras. This enables device manufacturers to offer competitive pricing while maintaining high-quality video streaming capabilities.\nFaster Boot Times: MCU-based systems boot in milliseconds rather than seconds, enabling near-instantaneous camera activation and reducing the delay between power-on and first video frame capture.\nThe Espressif Matter Camera is built on top of the Matter SDK and provides a complete implementation of the Camera device type.\nHardware Architecture # ESP32-P4: The ESP32-P4 is a powerful dual-core SoC by Espressif Systems. It provides MIPI-CSI support for camera capture and the hardware H.264 encoder for real-time 1080p @30fps. This SoC interfaces directly with the camera sensor, microphone, and speaker peripherals. ESP32-C5/ESP32-C6: The ESP32-C5 or ESP32-C6 provide Wi-Fi connectivity to the cameras, with the ESP32-C5 supporting dual-band (2.4 GHz and 5 GHz) and the ESP32-C6 supporting 2.4 GHz. The Matter application runs on this SoC. Hardware Overview\nCurrent Features # Full HD (1920x1080) video capture at 1080p @30fps, with built-in H.264 hardware encoding Real-time audio and video streaming using WebRTC Two-way talk support Low power cameras that enable battery powered design through the split mode architecture Multiple simultaneous video streams support Try It Out # Hardware Setup:\nESP32-P4 Function EV development board with MIPI-CSI camera support Camera module compatible with ESP32-P4 (MIPI-CSI interface) Matter-enabled phone app or host-based Matter camera controller Software Setup:\nFollow the steps in the Camera example to build, flash, and test. Upcoming Features # Snapshot Capture: JPEG snapshot functionality for on-demand image capture Security: Record and upload media using CMAF along with the encryption Privacy: Cartesian zone and PTZ support As Matter 1.5 continues to gain adoption across the smart home ecosystem, MCU-based cameras powered by Espressif SoCs will play a crucial role in bringing interoperable, secure, and affordable camera solutions to market, shaping the future of connected camera devices.\n","date":"21 January 2026","externalUrl":null,"permalink":"/blog/2026/01/introducing-esp-matter-camera/","section":"Blog","summary":"This article describes the Matter camera features introduced in Matter 1.5 and discusses camera support for the ESP32 series of SoCs using Espressif Matter SDK","title":"Espressif - Introducing Matter Cameras","type":"blog"},{"content":"","date":"21 January 2026","externalUrl":null,"permalink":"/tags/matter/","section":"Tags","summary":"","title":"Matter","type":"tags"},{"content":"","date":"21 January 2026","externalUrl":null,"permalink":"/authors/sayon-deep/","section":"Developer Portal Authors","summary":"","title":"Sayon-Deep","type":"authors"},{"content":"","date":"13 January 2026","externalUrl":null,"permalink":"/pages/","section":"","summary":"","title":"","type":"pages"},{"content":"","date":"13 January 2026","externalUrl":null,"permalink":"/tags/contribute/","section":"Tags","summary":"","title":"Contribute","type":"tags"},{"content":"","date":"13 January 2026","externalUrl":null,"permalink":"/authors/kirill-chalov/","section":"Developer Portal Authors","summary":"","title":"Kirill Chalov","type":"authors"},{"content":"This article is split into the following parts:\nGuidelines for assigning tags \u0026ndash; gives you some background information How to assign tags \u0026ndash; instructs you on how to and what tags to assign Guidelines for assigning tags # In this section, you will find the following guidelines:\nChoosing tags Spelling tags Once you familiarize yourself with these guidelines, go to How to assign tags.\nChoosing tags # Choose tags that clearly indicate who the article is for and what it covers, following How to assign tags. Choose the correct abstraction level. Avoid overly generic or umbrella tags: Tags such as Espressif or IoT don\u0026rsquo;t add value in highlighting key topics. If a suggested higher-level term is too broad and multiple articles share a distinct topic, introduce a more specific tag. For example, if several articles focus on face recognition, introduce face recognition instead of using only machine vision. Avoid overly narrow tags when the content applies to a broader category For content applicable to both Zephyr and NuttX, consider using the broader tag RTOS. For content applicable to multiple Espressif SoCs, don\u0026rsquo;t add specific tags, such as ESP32 or ESP32-C3. Keep the taxonomy sustainable. Avoid creating tags that will only apply to one or two articles. If ESP32-C3-DevKit-RUST-1 is a key topic but no additional articles are expected, use the broader tag DevKit. If an article covers the ESP-Audio-Effects component and no further articles are planned, use ESP-IDF component. If important topics are not represented in the current tagging system, provide feedback for improvement. Spelling tags # Use lower case letters.\nExceptions: Capitalize proper nouns and established terms, such as: Product names: ESP32-P4, ESP-IDF, NuttX Terms, protocols, and features: SoC, Ethernet, WebRTC Abbreviations: IDE, LED, LLVM Use tags in singular.\nExceptions: Singular (uncountable) words that end in s: Mass nouns: graphics, robotics Established terms: ESP Insights, DevOps Use spaces to separate words.\nExceptions: Use hyphens only in established terms: Compound terms: ESP32-C3, esp-idf-kconfig, Wi-Fi Loading... ","date":"13 January 2026","externalUrl":null,"permalink":"/pages/contribution-guide/tagging-content/","section":"","summary":"","title":"Tagging content","type":"pages"},{"content":"","date":"12 January 2026","externalUrl":null,"permalink":"/tags/ai/","section":"Tags","summary":"","title":"AI","type":"tags"},{"content":"","date":"12 January 2026","externalUrl":null,"permalink":"/tags/esp-dl/","section":"Tags","summary":"","title":"ESP DL","type":"tags"},{"content":"With the advancement of AI technology in recent years, the robotics field has entered the era of embodied intelligence, enabling robots to learn and perceive their environment. The ESP32-P4 high-performance MCU, with its powerful computing capabilities and rich peripheral interfaces, provides an ideal platform for building intelligent robotic arm control solutions. Specifically, this article presents the robotic arm solution with the following advantages:\nOnboard Kinematics: The onboard kinematics library implements forward and inverse kinematics using an iterative method based on the robotic arm\u0026rsquo;s D-H parameters, eliminating the need for external computing platforms. Onboard Vision: With USB camera and color-detect model, combined with a calibration matrix, the robotic arm can accurately grasp colored blocks. Additionally, esp-dl provides lightweight models such as yolo11n and esp-detection, enabling custom object grasping. Remote Control: By operating a small robotic arm of the same configuration, joint data is wirelessly forwarded to the ESP32-P4 via ESP-NOW (using the onboard ESP32-C6 chip on the ESP32-P4-Function-EV-Board), enabling remote control. This article provides a detailed guide covering mechanical assembly, motor control, vision calibration, and system integration for both the leader arm and follower arm. It covers the fundamental principles of robotics and visual applications. Additionally, leveraging the powerful performance of the ESP32-P4, the robotic arm can be extended to various application scenarios.\nTo prevent personal injury or property damage caused by unexpected movement of the robotic arm during operation, please verify all motion parameters before formal operation and keep the emergency stop button within easy reach so that the equipment can be immediately shut down in an emergency. Leader and Follower Robotic Arm System Architecture Leader Robotic Arm (TRLC DK1) # The leader robotic arm is used only for remote control of the follower robotic arm and does not involve any robotics kinematics-related functionality. The follower robotic arm can operate independently with onboard kinematics and vision-based grasping capabilities. If remote control functionality is not needed, you can start reading directly from the Follower Robotic Arm (Ragtime Panthera) section. The leader robotic arm is derived from the leader section of trlc-dk1. It should be noted that the leader has been updated to v0.2.0 structure, but this article uses the initial version structure. You can download the initial version 3D files here.\nThe full leader project is available here, which primarily implements position control and torque‑switching for the XL330_M077 bus servo.\nTRLC DK1 Leader Mechanical Assembly # XL330_M077 Bus Servo Configuration # Before the formal assembly, configure the 7 XL330_M077 bus servos using DYNAMIXEL Protocol 2.0. Prepare the bus servo driver board in advance (which converts the standard serial signals into the DATA signals for the bus servos). Refer to the following circuit or the official debugging circuit for the XL330-M077.\nBus Servo Circuit If using the above circuit, connect the TX of the USB-to-TTL converter to the TX of the driver board, and the RX to the RX of the driver board. Ensure the connections are not reversed. After connecting the bus servos, driver board, and USB-to-TTL converter, click the Scan button in the menu bar of the DYNAMIXEL Protocol 2.0 application to search for the servos on the bus:\nBus Servo Scan In order to ensure consistency with the servo parameters in the leader project, configure the servos according to the following requirements:\nID: Set the servo IDs from 1 to 7 Baud rate: Set the baud rate of all servos to 115200 Operating mode: Set the mode of all servos to position control Initial angle: Set the starting angle of all servos to 180 degrees (2045) Leader Servo Setting Leader Servo ID The choice of 180 degrees as the initial angle is because if the angle is set to 0 degrees as the starting point, there is a possibility that the angle may become 360 degrees at power-up, which could affect subsequent position reading and control. Structural Assembly # After printing all the structures, assemble all XL330_M077 servos at the initial angle of 180 degrees. The screws required for the structure are provided in the XL330_M077 packaging box.\nLeader Assembly ESP32-C3 Driver Board Installation and Debugging # The ESP32-C3 driver board integrates the ESP32-C3 with the bus-servo circuitry into a complete driver module. It supports powering both the XL330_M077 and the ESP32-C3 from an external 5 V supply; ensure the external 5 V source can deliver at least 1 A. In addition, by connecting to the onboard Micro-USB port, the ESP32-C3 can be directly flashed and debugged. Download the PCB Gerber files for PCB prototyping here.\nESP32-C3 Driver Board Before building the leader project, set up the ESP-IDF Release v5.5 environment. Refer to Get Started to install and configure ESP-IDF v5.5.\nNext, clone esp-iot-solution locally, activate the ESP-IDF v5.5 environment, and enter the leader directory to build, flash, and monitor:\ngit clone git@github.com:espressif/esp-iot-solution.git cd esp-iot-solution/examples/robot/ragtime_panthera/leader idf.py set-target esp32c3 # Replace /dev/ttyACM0 with your actual port # Enter `ls /dev/ttyACM*` to view available ports idf.py -p /dev/ttyACM0 build flash monitor For additional configuration, run idf.py menuconfig and navigate to (Top) → Example Configuration:\nLeader Menuconfig Hardware Configuration includes the basic configuration for XL330_M077 bus servos, including baud rate, TX/RX pins, initial position, and angle tolerance:\nLeader Hardware Config The configurations required are as follows:\nXL330_M077 Configuration: To change the UART settings or communication pins, modify XL330_M077 communication speed, XL330_M077 RXD pin number, and XL330_M077 init position. Initial angle: By default, the program defines the zero position as the current angle minus the configured initial angle; this depends on the angles set during mechanical assembly. Angle tolerance: After power-on, the program commands all servos to return to their initial positions. Due to inertia, multiple position-write cycles may be required to reach the target. When the difference between the target angle and the current angle is less than the angle tolerance, the program considers the servo to have reached the target. ESP-NOW Configuration includes configuration for channel, primary master key, and slave MAC address:\nLeader ESP-NOW Config The configurations required are as follows:\nChannel: Defaults to 1; no change needed unless required. Primary master key: Defaults to bot12345678901234; no change needed unless required. Slave MAC address: Defaults to 9c:9e:6e:52:f8:b8; update it to the receiver\u0026rsquo;s MAC address used in the follower project. Note: ESP-NOW is a wireless communication protocol defined by Espressif, which enables the direct, quick and low-power control of smart devices, without the need for a router. ESP-NOW can work with Wi-Fi and Bluetooth LE, and supports the ESP8266, ESP32, ESP32-S and ESP32-C series of SoCs. It\u0026rsquo;s widely used in smart-home appliances, remote controlling, sensors, etc.\nFollower Robotic Arm (Ragtime Panthera) # The follower robotic arm project originates from the Ragtime_Panthera project, which uses DM joint motors to drive the arm and provides complete ROS and Python codebases. In addition, the follower arm is structurally identical to the leader arm, so the follower can be directly teleoperated via the leader.\nTo avoid structural differences between this project and the Ragtime_Panthera project due to updates, refer to the forked version. Kinematics # In the Ragtime_Panthera project, the robotic arm is described using URDF (an XML-based robot description format). However, on MCU platforms there is no support for URDF and kinematics libraries. Therefore, on the ESP32-P4 we describe the Ragtime_Panthera arm with Denavit–Hartenberg (D-H) parameters and implement inverse kinematics using an iterative method.\nBefore debugging, use robotics-toolbox-python to pre‑validate the Denavit–Hartenberg (D-H) parameters and study the basics of forward and inverse kinematics (it is the Python version of the MATLAB Robotics Toolbox):\npip3 install roboticstoolbox-python Next, view the follower robotic arm in the simulation environment:\nimport numpy as np from roboticstoolbox import DHRobot, RevoluteDH robot = DHRobot( [ RevoluteDH(a=0.0, d=0.1005, alpha=-np.pi / 2, offset=0.0), RevoluteDH(a=0.18, d=0.0, alpha=0.0, offset=np.deg2rad(180)), RevoluteDH(a=0.188809, d=0.0, alpha=0.0, offset=np.deg2rad(162.429)), RevoluteDH(a=0.08, d=0.0, alpha=-np.pi / 2, offset=np.deg2rad(17.5715)), RevoluteDH(a=0.0, d=0.0, alpha=np.pi / 2, offset=np.deg2rad(90)), RevoluteDH(a=0.0, d=0.184, alpha=np.pi / 2, offset=np.deg2rad(-90)), ], name=\u0026#34;Ragtime_Panthera\u0026#34; ) robot.teach(np.array([0, 0, 0, 0, 0, 0])) Follower Roboticstoolbox Initial Position Forward Kinematics # Forward kinematics refers to calculating the end-effector\u0026rsquo;s position and orientation from input joint angles. Use the following code to test the forward kinematics:\nimport matplotlib.pyplot as plt import numpy as np from roboticstoolbox import DHRobot, RevoluteDH robot = DHRobot( [ RevoluteDH(a=0.0, d=0.1005, alpha=-np.pi / 2, offset=0.0), RevoluteDH(a=0.18, d=0.0, alpha=0.0, offset=np.deg2rad(180)), RevoluteDH(a=0.188809, d=0.0, alpha=0.0, offset=np.deg2rad(162.429)), RevoluteDH(a=0.08, d=0.0, alpha=-np.pi / 2, offset=np.deg2rad(17.5715)), RevoluteDH(a=0.0, d=0.0, alpha=np.pi / 2, offset=np.deg2rad(90)), RevoluteDH(a=0.0, d=0.184, alpha=np.pi / 2, offset=np.deg2rad(-90)), ], name=\u0026#34;Ragtime_Panthera\u0026#34; ) state = np.deg2rad([0, 30, -36, 65, 0, 0]) T1 = robot.fkine(state) print(\u0026#34;T1:\\n{}\u0026#34;.format(T1)) robot.plot(state, jointaxes=True, eeframe=True, block=True) plt.show() Follower Roboticstoolbox Forward Test T1: 0.8572 0.515 0 0.1531 0 0 1 0 0.515 -0.8572 0 0.03971 0 0 0 1 Using the fkine function, the end-effector\u0026rsquo;s position and orientation at the current joint angles can be quickly calculated.\nInverse Kinematics # Inverse kinematics refers to calculating the required rotation angle for each joint from the input end-effector position and orientation. Use the following code to test inverse kinematics:\nimport matplotlib.pyplot as plt import numpy as np from roboticstoolbox import DHRobot, RevoluteDH robot = DHRobot( [ RevoluteDH(a=0.0, d=0.1005, alpha=-np.pi / 2, offset=0.0), RevoluteDH(a=0.18, d=0.0, alpha=0.0, offset=np.deg2rad(180)), RevoluteDH(a=0.188809, d=0.0, alpha=0.0, offset=np.deg2rad(162.429)), RevoluteDH(a=0.08, d=0.0, alpha=-np.pi / 2, offset=np.deg2rad(17.5715)), RevoluteDH(a=0.0, d=0.0, alpha=np.pi / 2, offset=np.deg2rad(90)), RevoluteDH(a=0.0, d=0.184, alpha=np.pi / 2, offset=np.deg2rad(-90)), ], name=\u0026#34;Ragtime_Panthera\u0026#34; ) state = np.deg2rad([0, 30, -36, 65, 0, 0]) T1 = robot.fkine(state) print(\u0026#34;T1:\\n{}\u0026#34;.format(T1)) T2 = np.array(T1) T2[0, 3] = T2[0, 3] + 0.1 print(\u0026#34;T2:\\n{}\u0026#34;.format(T2)) sol = robot.ikine_LM(T2, q0=state, ilimit=100, mask=[1, 1, 1, 1, 1, 0], joint_limits=True) print(sol) T3 = robot.fkine(sol.q) print(\u0026#34;T3:\\n{}\u0026#34;.format(T3)) robot.plot(sol.q, jointaxes=True, eeframe=True, block=True) plt.show() Follower Roboticstoolbox Inverse Test In this example, based on the initial pose, we attempt to move the end-effector 0.1 m in the positive X direction and solve for the joint angles sol.q at the current pose. We then verify the result by applying forward kinematics:\nT1: 0.8572 0.515 0 0.1531 0 0 1 0 0.515 -0.8572 0 0.03971 0 0 0 1 T2: [[ 8.57171795e-01 5.15030595e-01 1.04973270e-16 2.53139272e-01] [-1.54001208e-16 5.24866348e-17 1.00000000e+00 1.49891524e-17] [ 5.15030595e-01 -8.57171795e-01 1.24305397e-16 3.97085648e-02] [ 0.00000000e+00 0.00000000e+00 0.00000000e+00 1.00000000e+00]] IKSolution: q=[0, 1.161, -0.8568, 0.725, 0, 0], success=True, iterations=4, searches=1, residual=4.59e-10 T3: 0.8572 0.515 0 0.2531 0 0 1 0 0.515 -0.8572 0 0.03971 0 0 0 1 From the test results, the inverse kinematics calculation is valid, and the forward kinematics result from the inverse solution matches the expected pose.\nWorkspace Testing Based on Forward and Inverse Kinematics # Since the current project does not support pose estimation, we need to consider changing the end-effector position at a fixed orientation to determine the robotic arm\u0026rsquo;s workspace boundaries and avoid moving the arm to regions where inverse kinematics cannot be solved:\nimport numpy as np from roboticstoolbox import DHRobot, RevoluteDH robot = DHRobot( [ RevoluteDH(a=0.0, d=0.1005, alpha=-np.pi / 2, offset=0.0), RevoluteDH(a=0.18, d=0.0, alpha=0.0, offset=np.deg2rad(180)), RevoluteDH(a=0.188809, d=0.0, alpha=0.0, offset=np.deg2rad(162.429)), RevoluteDH(a=0.08, d=0.0, alpha=-np.pi / 2, offset=np.deg2rad(17.5715)), RevoluteDH(a=0.0, d=0.0, alpha=np.pi / 2, offset=np.deg2rad(90)), RevoluteDH(a=0.0, d=0.184, alpha=np.pi / 2, offset=np.deg2rad(-90)), ], name=\u0026#34;Ragtime_Panthera\u0026#34; ) state = np.deg2rad([0, 30, -36, 65, 0, 0]) T1 = robot.fkine(state) print(\u0026#34;T1:\\n{}\u0026#34;.format(T1)) x_range = np.linspace(0, 23, 30) y_range = np.linspace(-15, 15, 30) for dx in x_range: for dy in y_range: T_test = np.array(T1).copy() T_test[0, 3] += dx / 100 T_test[1, 3] += dy / 100 sol = robot.ikine_LM(T_test, q0=state) if sol.success: pass else: print(f\u0026#34;Failed in dx: {dx:.4f} cm, dy: {dy:.4f} cm\u0026#34;) print(\u0026#34;Test Done\u0026#34;) Follower Roboticstoolbox Workspace Test In this example, based on the initial pose, we attempt to solve inverse kinematics at a fixed orientation within a 23 cm × 30 cm region. From the test results, all points within this region can be successfully solved using inverse kinematics.\nThe current project does not support pose estimation. Therefore, workspace testing is performed with a fixed end-effector pose. ESP32-P4 Onboard Kinematics Testing # To enable the ESP32-P4 to independently control the robotic arm, onboard kinematics is essential. Inspired by Matrix_and_Robotics_on_STM32, we attempted to port and deploy it on the ESP32 platform. The kinematic component can be introduced in a separate project and tested. Note that this project only ports the kinematics part and does not yet support dynamics.\nTaking Inverse Kinematics as an example, after setting up the ESP-IDF v5.5 environment, test it in the examples/robot/ragtime_panthera/follower project. The project has already added kinematic as a component:\n#include \u0026lt;stdio.h\u0026gt; #include \u0026lt;iostream\u0026gt; #include \u0026#34;kinematic.h\u0026#34; extern \u0026#34;C\u0026#34; void app_main(void) { Kinematic kinematic; Joint j1 = Joint(0.0, DEG2RAD(30.0), DEG2RAD(-36.0), DEG2RAD(65.0), 0.0, 0.0); TransformMatrix t1; kinematic.solve_forward_kinematics(j1, t1); std::cout \u0026lt;\u0026lt; \u0026#34;t1: \u0026#34; \u0026lt;\u0026lt; std::endl; t1.print(); TransformMatrix t2 = t1; t2(0, 3) += 0.1f; std::cout \u0026lt;\u0026lt; \u0026#34;t2: \u0026#34; \u0026lt;\u0026lt; std::endl; t2.print(); Joint j2 = j1; kinematic.solve_inverse_kinematics(t2, j2); std::cout \u0026lt;\u0026lt; \u0026#34;j2: \u0026#34; \u0026lt;\u0026lt; std::endl; for (int i = 0; i \u0026lt; 6; i++) { std::cout \u0026lt;\u0026lt; j2[i] \u0026lt;\u0026lt; \u0026#34; \u0026#34;; } std::cout \u0026lt;\u0026lt; std::endl; TransformMatrix t3; kinematic.solve_forward_kinematics(j2, t3); std::cout \u0026lt;\u0026lt; \u0026#34;t3: \u0026#34; \u0026lt;\u0026lt; std::endl; t3.print(); } t1: Transform Matrix: [ 0.8572, 0.5150, -0.0000, 0.1531] [ 0.0000, -0.0000, 1.0000, -0.0000] [ 0.5150, -0.8572, -0.0000, 0.0397] [ 0.0000, 0.0000, 0.0000, 1.0000] t2: Transform Matrix: [ 0.8572, 0.5150, -0.0000, 0.2531] [ 0.0000, -0.0000, 1.0000, -0.0000] [ 0.5150, -0.8572, -0.0000, 0.0397] [ 0.0000, 0.0000, 0.0000, 1.0000] j2: -4.71993e-13 1.1615 -0.856673 0.724918 -2.53619e-13 -4.4205e-13 t3: Transform Matrix: [ 0.8572, 0.5150, -0.0000, 0.2531] [ 0.0000, -0.0000, 1.0000, -0.0000] [ 0.5150, -0.8572, -0.0000, 0.0397] [ 0.0000, 0.0000, 0.0000, 1.0000] From the test results, the ESP32-P4 Onboard Kinematics results are consistent with the Inverse Kinematics test results.\nURDFly (Optional) # URDF (Unified Robot Description Format) is an XML-based standard for describing a robot’s kinematic structure and basic dynamic properties. It is used to define links, joints, inertial parameters, joint limits, as well as collision and visual geometries. URDF is widely adopted in robotics as the common model format in the ROS ecosystem, and is natively supported by mainstream simulation and motion-planning tools such as Gazebo, RViz, and MoveIt.\nHowever, URDF is relatively complex on MCU platforms, and it is more suitable to use D-H parameters to describe the robotic arm and perform forward and inverse kinematics. Use URDFly or other similar tools to parse URDF into D-H parameters.\nTaking Ragtime_Panthera as an example, after cloning URDFly and installing all dependencies according to the README, follow these steps to visualize and convert the Ragtime_Panthera URDF:\nReplace package://panther_description in the URDF file with ../ Ragtime Panthera URDF Modify Open URDFly and load the modified URDF file (urdfly) PS D:\\project\\github\\URDFly\u0026gt; python .\\main.py Open URDF URDFly Main Window Drag the sliders on the right to move each joint. Click the buttons on the left to obtain MDH parameters and other information.\nJoint Motor Debugging # Before officially starting to debug DM motors, refer to the DM Motor Getting Started Guide to understand the DM motor control process. Download the DM Debug Tool v.1.6.8.6 here.\nWhen opening the DM motor kit (using DM4310-24V as an example), the following components are included:\nDM Motor kit Connect all components in the kit according to the wiring diagram below, provide 24 V power to the power adapter board, and connect the PC to the USB-to-CAN module via a USB Type-C cable:\nDM Motor Connect Next, open the DM debug tool and test it. Select the correct serial port and try to read parameters in the Parameter Settings tab:\nDM Debug Tool When the parameters are successfully read, it indicates that the motor connection is successful. Try position mode testing in the Debug tab:\nDM Position Control DM Motor Operation Mechanical Assembly # After gaining a preliminary understanding of the kinematics and DM motors mentioned above, follow the steps below to assemble the follower robotic arm. Before that, prepare the following materials:\nESP32-P4-Function-EV-Board: Consists of the ESP32-P4 development board and a 7-inch MIPI DSI capacitive touchscreen (1024 × 600) CAN module: Used to connect the ESP32-P4 with DM motors USB camera: The resolution selected for this project is 640 × 480. Confirm that the selected USB camera supports this resolution XT30 2+2 dual-end cables: Used to connect the motors together. Prepare at least 6 cables Various CNC and sheet metal structural components: This will be detailed in the structural assembly section 24 V power supply: Used to power the DM motors DM motors: 4x DM4340, 2x DM4310, and 1x DMH3510 Note: In the original Ragtime_Panthera project, a combination of 3x DM4310, 3x DM4340, and 1x DMH3510 was used, where DM4310 was used for base_link rotation. However, during actual operation, due to the large inertia of the robotic arm when extended, the base_link DM4310 was eventually replaced with DM4340. No additional structural modifications are required.\nOverall View DM Motor Configuration # Before installing the motors into the mechanical structure, use the DM debug tool to preset the Master ID and CAN ID for each motor:\nID Setting Structural Assembly # Before assembly, refer to the BOM to prepare the required materials in advance, such as screws, nuts, fixing plates, sliders, rails, wires, etc. In addition, due to the variety of materials involved, they need to be processed using different manufacturing methods:\nSheet Metal Fabrication\nJoint 1-2 connector: The machining holes require threads. See here. Choose stainless steel 304 material Joint 2-3 link: The machining holes require threads. See here. Choose stainless steel 304 material Joint 3-4 link: The machining holes require threads. See here. Choose stainless steel 304 material Joint 4-5 connector: No thread requirement. Choose aluminum alloy 5052 material Joint 5-6 connector: No thread requirement. Choose aluminum alloy 5052 material CNC Machining\nBase plate: No thread requirement. Choose aluminum alloy 6061 material You can use online machining suppliers such as JLC for processing. In addition, the remaining materials can be 3D printed.\nAll Assembly Components ESP32-P4-Function-EV-Board Installation and Debugging # Since the follower project uses the ESP32-P4-Function-EV-Board kit, install the LCD screen on the ESP32-P4-Function-EV in advance. Refer to the User Guide for initial hardware and software testing:\nLCD Adapter Board ESP32-P4-Function-EV J3 header MIPI DSI connector RST_LCD pin of J6 header GPIO27 pin of J1 header PWM pin of J6 header GPIO26 pin of J1 header 5 V pin of J6 header 5 V pin of J1 header GND pin of J6 header GND pin of J1 header Hardware Connection and Project Compilation # After cloning the follower project, use idf.py menuconfig to enter (Top) → Panthera Follower Configuration to configure the project, such as CAN TX/RX pins, C6 firmware flashing pins, etc.\ngit clone git@github.com:espressif/esp-iot-solution.git cd esp-iot-solution/examples/robot/ragtime_panthera/follower idf.py set-target esp32p4 idf.py menuconfig idf.py build Follower Menuconfig Direct control robot arm via console: Enable this option. When using idf.py monitor, the follower can be directly controlled in the terminal using commands Hardware Configuration: Used to configure the connection between ESP32-P4 and the CAN module. By default, TX is GPIO24 and RX is GPIO25 Leader and Follower Gripper Mapping: Used to configure the gripper angle mapping relationship between the leader and follower robotic arms. By default, it uses radians and is multiplied by 100 Leader and Follower Angle Inversion: Used to configure whether the angles between the leader and follower robotic arms need to be inverted. Due to differences in mechanical structure installation, the positive direction of joint rotation may differ. Use the right-hand rule to determine the positive rotation direction of each joint and set whether the corresponding joint needs to be inverted Receiver Serial Flash Config: Used to configure the ESP-NOW receiver for the follower. Since the current esp-hosted-mcu does not support ESP-NOW, the project independently implements ESP-NOW packet reception on the ESP32-C6 side and uses esp-serial-flasher to download the firmware to ESP32-C6. By default, the ESP32-C6 RX, TX, Reset, and Boot pins are connected to GPIO6, GPIO5, GPIO54, and GPIO53, respectively: ESP32-P4 Pin Connection Description GPIO24 Connect to CAN module TX GPIO25 Connect to CAN module RX GPIO6 Connect to ESP32-C6 U0RXD GPIO5 Connect to ESP32-C6 U0TXD GPIO54 Connect to ESP32-C6 EN GPIO53 Connect to ESP32-C6 BOOT ESP32-P4-Function-EV-Board Hardware Connection IMPORTANT: For the first firmware compilation, enable the Direct control robot arm via console and Enable update C6 Flash options, and complete the wiring according to the default configuration.\nFlashing and Running # Taking Linux as an example, after completing the compilation, connect the ESP32-P4 to the PC. The system will automatically generate a serial port device node (e.g., /dev/ttyUSB0), which can then be used for firmware download and serial port log debugging:\nidf.py -p /dev/ttyUSB0 flash monitor After flashing is complete, test console commands in the terminal. The following commands are currently supported:\nCommand Description Usage panthera_enable Enable or disable all motors panthera_enable \u0026lt;on|off\u0026gt; panthera_goto_zero Move all joints to zero position panthera_goto_zero panthera_set_zero Set current position as zero for all motors panthera_set_zero panthera_goto_position Move end-effector to specified Cartesian coordinates panthera_goto_position -x \u0026lt;x\u0026gt; -y \u0026lt;y\u0026gt; -z \u0026lt;z\u0026gt; panthera_set_vision_matrix Set the vision calibration matrix panthera_set_vision_matrix -1 \u0026lt;m1\u0026gt; -2 \u0026lt;m2\u0026gt; ... -9 \u0026lt;m9\u0026gt; panthera_get_vision_matrix Read and display the current calibration matrix panthera_get_vision_matrix panthera_read_position Read all joints position info panthera_read_position After flashing the firmware for the first time, execute the panthera_read_position command to verify whether motor communication is normal. Under normal circumstances, the angle information of all added motors should be obtained. When executing panthera_enable on, all motors should light up with green LEDs, and when executing panthera_enable off, all motors will return to red LEDs. Additionally, adjust the follower robotic arm to the structural zero position and enter panthera_set_zero to align the structural zero with the motor zero.\nFollower Screen You can directly start all motors, execute grasping actions (provided that the vision calibration matrix has been calibrated), return to zero, and set zero on the screen.\nFor the DMH3510 motor, set the DMH3510 zero point in the closed state after installing the clamping structure. In addition, before powering on the DMH3510, ensure that its angle range is between 0 and 360°. If the DMH3510 angle is moved beyond 360° while powered off, the DMH3510 zero point will change. Therefore, ensure that the DMH3510 remains near the zero point before powering on. Vision Calibration # For vision calibration, this article adopts an eye-to-hand configuration, where both the camera and robotic arm positions are fixed, which is much simpler compared to eye-in-hand configurations. Before formal calibration, move the robotic arm to specific positions and record the corresponding pixel coordinates at those positions. To simplify the calibration process, create a separate calibration board and place AprilTag markers at specific positions, which can then be recognized by a PC to directly generate the calibration matrix:\nFollower Apriltag Vision Calibration Refer to the approach shown in the figure above: place the robotic arm on a 300 mm × 300 mm plate, fix the camera on one side of a 300 mm × 600 mm plate, and use the following script for calibration:\nimport numpy as np A = np.array([[170, 250, 331, 332, 246, 247], [232, 227, 228, 375, 377, 291]]) B = np.array([[0.4431, 0.4431, 0.4431, 0.17, 0.17, 0.3277], [0.15, 0, -0.15, -0.15, 0, -0.1], [0.0397, 0.0397, 0.0397, 0.0397, 0.0397, 0.0397]]) A_hom = np.vstack([A, np.ones(A.shape[1])]) M = np.zeros((3, 3)) for i in range(3): m_i, _, _, _ = np.linalg.lstsq(A_hom.T, B[i, :], rcond=None) M[i, :] = m_i print(repr(M)) flat = M.flatten() print_str = \u0026#39;panthera_set_vision_matrix\u0026#39; for idx, val in enumerate(flat, start=1): print_str += f\u0026#39; -{idx} {val:.6f}\u0026#39; print(print_str) for i in range(A.shape[1]): a = np.array([0, 0, 1]) a[0] = A[0][i] a[1] = A[1][i] b = M @ a print(repr(b)) The results from the above script cannot be directly used as the calibration results for the project, as they depend on the position and angle of the camera installation. Use the panthera_set_vision_matrix command to move the robotic arm end-effector to each point in B, record the pixel coordinates of these points, and replace A. Alternatively, attach AprilTag markers at these points to facilitate PC recognition of pixel positions.\nAfter calibration is complete, directly input the output command into the idf monitor terminal, and the calibration data will be automatically saved to NVS.\nObject Detection # This article uses the color_detect model by default to detect green blocks as targets for the robotic arm to grasp:\nRagtime Panthera Follower Color Detect Additionally, esp-dl provides many other AI models. Visit esp-dl to access more on-board AI models.\nTarget Grasping # After completing the calibration, correctly saving the parameters to NVS, and properly inserting the USB camera into the high-speed USB port of the ESP32-P4-Function-EV-Board, the LCD screen will display the camera feed. Place a green block to check whether it is correctly detected on the screen, and click the Grasp button to attempt grasping.\nRagtime Panthera Follower Grasp Note: The current follower project only integrates green color detection. In future maintenance, we will attempt to support recognition of more objects.\nLeader and Follower Robotic Arm Synchronization # The leader and follower robotic arms communicate via ESP-NOW (currently only supporting one-way transmission from leader to follower). Use the leader robotic arm to synchronize joint angle information to the follower robotic arm via ESP-NOW to achieve remote control. Click the Sync and Enable switches on the screen to enable synchronization.\nThe data packet for the leader\u0026rsquo;s servo angles is structured as follows: a header (2 bytes), 7 servo joint data items (7*2 bytes), and a CRC check (2 bytes):\nField Size (bytes) Description Notes / Encoding Header 2 Fixed header indicating start of packet Always 0xFF 0xFF Joint Data 14 (7×2) Seven servo joint angles Each angle in radians × 100, converted to uint16; stored as low byte then high CRC 2 CRC check over the entire packet (excluding CRC field itself) CRC16, little-endian output, initial value UINT16_MAX If synchronization issues are encountered, check for the following problems:\nESP32-C6 firmware issue: Check whether the ESP32-C6 firmware for the follower has been downloaded. Open the follower project, run idf.py menuconfig, then navigate to (Top) → Panthera Follower Configuration → Receiver Serial Flash Config, and enable Enable update C6 Flash to complete the initial firmware download. After the download is complete, disable Enable update C6 Flash to save startup time. ESP-NOW communication issue: Check whether the receiver MAC address configured in the leader project is correct. Enter the MAC address of the ESP32-C6 in the ESP32-P4-Function-EV-Board. Leader and Follower Synchronization Summary # This article introduces the complete process of implementing a robotic arm project on ESP32-P4, including the fundamentals of kinematics, vision calibration, and remote communication, demonstrating the feasibility of ESP32-P4 in industrial robotic arm applications. Based on this article, you can explore the application boundaries of ESP32-P4.\nFeel free to try these examples, implement your own applications, and share your experience!\nResources # Follower_Project: A complete grasping project including DM motor control, kinematics, and vision. Leader_Project: XL330_M077 bus servo control and ESP-NOW communication. Ragtime_Panthera: Original follower robotic arm project Trlc_Dk1: Original leader robotic arm project Matrix_and_Robotics_on_STM32: Reference implementation of kinematics for the follower robotic arm. URDFly: Convert URDF parameters to MDH parameters. Robotics-Toolbox-Python: Python version of the MATLAB Robotics Toolbox. ESP_DL: Includes models such as color detection, YOLO, and face detection. ","date":"12 January 2026","externalUrl":null,"permalink":"/blog/2026/01/esp32p4-robotic-arm-design/","section":"Blog","summary":"This article demonstrates how to implement an independently controllable robotic arm project based on the ESP32-P4 high-performance MCU. It covers complete kinematics, visual detection, and remote control, showcasing the great potential of ESP32-P4 in industrial applications.","title":"Intelligent Robotic Arm Design Based on ESP32-P4 for Industrial Applications","type":"blog"},{"content":"","date":"12 January 2026","externalUrl":null,"permalink":"/tags/kinematics/","section":"Tags","summary":"","title":"Kinematics","type":"tags"},{"content":"","date":"12 January 2026","externalUrl":null,"permalink":"/tags/robotic-arm/","section":"Tags","summary":"","title":"Robotic Arm","type":"tags"},{"content":"","date":"12 January 2026","externalUrl":null,"permalink":"/tags/visual-detection/","section":"Tags","summary":"","title":"Visual Detection","type":"tags"},{"content":"","date":"12 January 2026","externalUrl":null,"permalink":"/authors/yan-ke/","section":"Developer Portal Authors","summary":"","title":"Yan Ke","type":"authors"},{"content":"","date":"9 January 2026","externalUrl":null,"permalink":"/authors/almir-okato/","section":"Developer Portal Authors","summary":"","title":"Almir Okato","type":"authors"},{"content":"","date":"9 January 2026","externalUrl":null,"permalink":"/tags/bootloader/","section":"Tags","summary":"","title":"Bootloader","type":"tags"},{"content":"","date":"9 January 2026","externalUrl":null,"permalink":"/tags/mcuboot/","section":"Tags","summary":"","title":"MCUboot","type":"tags"},{"content":" Introduction # This is a translated and updated version of my original article on the Embarcados website. In the embedded world, firmware updates are essential and increasingly important. As IoT solutions grow exponentially in numbers and complexity, so does the concern to make devices secure and updatable in the field efficiently.\nSome years ago, MCUboot emerged as an open source bootloader project for small and low-cost systems, designed to simplify and provide a standard in this field. It started as an Apache Mynewt subproject when developers decided to separate the bootloader from OS development. Later, it was ported to Zephyr RTOS and became its default bootloader.\nEspressif Systems has been broadening support for additional third-party RTOSes such as Zephyr and NuttX, offering developers more choices for its SoCs. For this reason, a port for Espressif SoCs has been created within the MCUboot project.\nThis article shows how to get started with MCUboot on your ESP32-based project. It covers what MCUboot is, how to set the environment and configure the application side, then how to build the MCUboot Espressif Port bootloader and flash it onto the device. We will use the ESP32 DevKitC board in this guide.\nThe MCUboot-compatible application in this guide can be either a NuttX or Zephyr RTOS application built for Espressif SoCs with MCUboot compatibility configuration enabled.\nThis guide assumes that you are familiar with building and configuring the chosen RTOS.\nWhat is MCUboot? # MCUboot is an open source secure bootloader for 32-bit microcontrollers. The project defines a common infrastructure for secure boot and it mainly covers:\nFault-tolerant updates: MCUboot defines a clear flash layout. It uses slots to store the main bootable image and the update image in separate flash regions. A scratch area (see the table about areas below) supports swapping images during firmware updates. This design ensures updates are reliable and allows MCUboot to recover or revert if any issues occur.\nSecurity: MCUboot validates firmware images by checking hashes and verifying signatures using asymmetric key algorithms such as RSA 2048/3072, ECDSA, and ed25519. These mechanisms ensure the integrity and authenticity of the images.\nThe project aims to standardize these aspects comprehensively. MCUboot core features are independent from any operating system and hardware, relying on hardware porting layers from the target host OS.\nImage and flash organization # To track the general information, swap and update states from an application image, MCUboot requires specific data added by imgtool. This tool is provided within the MCUboot project and it formats the image binary adding the expected header and trailer, the signature, and can also generate signing keys.\nMCUboot defines a flash organization where a flash area can contain multiple executable images depending on its boot and update configuration. Each image area contains two image slots: primary and secondary. By default, the bootloader only runs an image from the primary slot. The secondary slot is where an incoming image for firmware update is staged prior to being installed; then its content will be either swapped to the primary slot or overwritten during the update.\nWe can identify four types of flash areas in the layout:\nAREA ID DESCRIPTION Bootloader 0 Bootloader region (MCUboot) Primary Slot 1 Main bootable image, code always runs from there Secondary Slot 2 Staging area for firmware updates, it stores the incoming image and, after the swap, stores the original image to enable recovery if needed Scratch 3 Temporary area used for helping the image swap when updating As explained in Application Startup Flow, Espressif SoCs have a ROM bootloader (or First Stage Bootloader) which, as the name suggests, runs from the Read-Only Memory after reset and it is not modifiable, thus the MCUboot Espressif Port bootloader is the Second Stage Bootloader. MCUboot also supports multiple images, allowing you to define additional image areas with their own primary and secondary slots.\nFor the MCUboot Espressif Port the layout information is stored in the \u0026lt;MCUBOOT_DIR\u0026gt;/boot/espressif/port/\u0026lt;ESP_SOC\u0026gt;/bootloader.conf file. Addresses and sizes can be modified, but the following rules must be followed:\nBootloader address must be kept since it\u0026rsquo;s where the ROM bootloader looks for a valid Second Stage Bootloader to start. None of the slots must overlap. Primary and Secondary slots must be the same size. Scratch area must be large enough to store at least the largest flash sector that will be swapped. Both MCUboot and the application must be aware of this layout for correct operation. Flash organization is configurable and must match between MCUboot and the application being booted to ensure proper operation. High-level overview of the boot process # The following diagram shows the basic boot execution flow:\nflowchart TB %% Nodes A[Reset] B[Boot start] C[Bring-up] D[MCUboot routines] E{Is previousswap in progress?} F[Finish swap] G{Check imageconfirmation} H{Is Primaryslot valid?} X[Boot error,halt] I{Is Secondaryslot valid?} J[Swap images] K[Erase secondary slot] L[Revert image] Z[Boot primaryslot image] %% Flow A --\u003e B --\u003e C --\u003e D --\u003e E E -- No --\u003e G E -- Yes --\u003e F --\u003e Z G -- Confirmed --\u003e H H -- No --\u003e X H -- Yes --\u003e Z G -- Swap requested --\u003e I I -- Yes --\u003e J --\u003e Z I -- No --\u003e K --\u003e Z G -- Not confirmed --\u003e L --\u003e Z %% Styling classDef process fill:#efe7ff,stroke:#7b5cff,stroke-width:2px,color:#000 classDef decision fill:#fff3c4,stroke:#c9a227,stroke-width:2px,color:#000 classDef success fill:#d6f5d6,stroke:#2e8b57,stroke-width:2px,color:#000 classDef error fill:#f7c6c6,stroke:#c0392b,stroke-width:2px,color:#000 %% Class assignments class A,B,C,D,F,J,K,L process class E,G,H,I decision class Z success class X error Notice that the bootloader verifies both slots in the process, but only boots the image from the Primary Slot:\nMCUboot boot process overview\nThe boot process and organization presented here are related to the Espressif Port current support to MCUboot. See more at the official MCUboot documentation. Setting the environment # First, prepare the development environment. This guide assumes the use of Linux (Ubuntu 20.04.2 LTS or later).\nEnsure you have git, Python3, pip, CMake and Ninja installed. If you don\u0026rsquo;t, you can run the following (this step is optional):\nsudo apt update sudo apt upgrade sudo apt install git python3 python3-pip cmake ninja-build MCUboot Espressif Port HAL # The MCUboot Espressif Port relies on HAL (Hardware Abstraction Layer) sources provided by ESP-IDF. To build the project, you should have one of the following:\nInstall ESP-IDF, which allows building the project standalone Use Zephyr HAL source from Espressif (hal_espressif) Use NuttX HAL source from Espressif (esp-hal-3rdparty) For Zephyr and NuttX HAL sources, it is recommended to only use them within their respective RTOS build systems, as the source revisions may not match the expected versions.\nInstalling ESP-IDF v5.1.6\ngit clone --recursive https://github.com/espressif/esp-idf.git cd \u0026lt;IDF_PATH\u0026gt; git checkout v5.1.6 \u0026lt;IDF_PATH\u0026gt;/install.sh . \u0026lt;IDF_PATH\u0026gt;/export.sh More information about ESP-IDF installation can be found here.\nClone and set up MCUboot # Clone the repository into a directory of your choice (other than ESP-IDF installation):\ngit clone https://github.com/mcu-tools/mcuboot.git cd mcuboot Install the additional dependencies needed by MCUboot:\npip3 install -r scripts/requirements.txt Update the MbedTLS submodule required by MCUboot:\ngit submodule update --init --recursive ext/mbedtls Any images you plan to boot with MCUboot must be formatted and signed using imgtool. You can find imgtool at \u0026lt;MCUBOOT_DIR\u0026gt;/scripts/imgtool.py (where \u0026lt;MCUBOOT_DIR\u0026gt; is the path to the cloned repository), or optionally, you can install it as follows:\npip3 install imgtool MCUboot repository includes some sample cryptographic keys for signing and testing the secure boot verification. It is crucial that you never use these sample keys in production since the private key is available in the MCUboot repository. See how to generate and manage cryptographic keys at the imgtool documentation. Building and flashing MCUboot on ESP32 # With everything set, let\u0026rsquo;s configure, build and flash the MCUboot Espressif Port bootloader.\nFirstly set the flash layout organization in the \u0026lt;MCUBOOT_DIR\u0026gt;/boot/espressif/port/esp32/bootloader.conf file, it must match the same flash organization as the chosen RTOS. For example:\nCONFIG_ESP_FLASH_SIZE=4MB CONFIG_ESP_BOOTLOADER_SIZE=0xF000 CONFIG_ESP_BOOTLOADER_OFFSET=0x1000 CONFIG_ESP_IMAGE0_PRIMARY_START_ADDRESS=0x20000 CONFIG_ESP_APPLICATION_SIZE=0x150000 CONFIG_ESP_IMAGE0_SECONDARY_START_ADDRESS=0x170000 CONFIG_ESP_SCRATCH_OFFSET=0x3E0000 CONFIG_ESP_SCRATCH_SIZE=0x1F000 Compile and generate the ELF:\ncd \u0026lt;MCUBOOT_DIR\u0026gt;/boot/espressif cmake -DCMAKE_TOOLCHAIN_FILE=tools/toolchain-esp32.cmake -DMCUBOOT_TARGET=esp32 -DESP_HAL_PATH=\u0026lt;IDF_PATH\u0026gt; -DMCUBOOT_FLASH_PORT=/dev/ttyUSB0 -B build -GNinja ninja -C build/ Erase the device\u0026rsquo;s flash:\nesptool.py -p \u0026lt;PORT\u0026gt; erase_flash Flash MCUboot Espressif Port bootloader to your board:\nninja -C build/ flash Alternatively:\nesptool.py -p /dev/ttyUSB0 -b 921600 --before default_reset --after hard_reset --chip esp32 write_flash --flash_mode dio --flash_size detect --flash_freq 40m 0x1000 build/mcuboot_esp32.bin You may adjust the USB port (-p /dev/ttyUSB0) and baud rate (-b 921600) according to your board connection. Check the serial monitor on the UART port (the same port used to flash) and reset your ESP32 board. This guide uses picocom tool, but any serial monitor tool can be used:\npicocom -b 115200 /dev/ttyUSB0 Since no image has been flashed yet, you will see MCUboot waiting for an application image in the primary slot.\n[esp32] [INF] *** Booting MCUboot build v2.3.0-rc2-3-g234c66e6 *** [esp32] [INF] [boot] chip revision: v3.0 [esp32] [INF] [boot.esp32] SPI Speed : 40MHz [esp32] [INF] [boot.esp32] SPI Mode : DIO [esp32] [INF] [boot.esp32] SPI Flash Size : 4MB [esp32] [INF] [boot] Enabling RNG early entropy source... [esp32] [INF] Primary image: magic=unset, swap_type=0x1, copy_done=0x3, image_ok=0x3 [esp32] [INF] Scratch: magic=unset, swap_type=0x1, copy_done=0x3, image_ok=0x3 [esp32] [INF] Boot source: primary slot [esp32] [INF] Image index: 0, Swap type: none [esp32] [ERR] Unable to find bootable image Preparing and flashing an application # You can use applications from either Zephyr or NuttX, ensuring MCUboot compatibility is enabled in whichever RTOS you use.\nThis section briefly outlines the required Kconfigs for configuring a NuttX or Zephyr application for MCUboot compatibility. It assumes you are already familiar with building and configuring your chosen RTOS.\nNuttX RTOS # Set the menuconfig options:\nEnable the CONFIG_ESP32_APP_FORMAT_MCUBOOT option Match the SPI Flash Configuration with the slots configuration in \u0026lt;MCUBOOT_DIR\u0026gt;/boot/espressif/port/esp32/bootloader.conf In this guide’s example, menuconfig was set as follows:\nSystem Type -\u0026gt; Bootloader and Image Configuration-\u0026gt; Enable MCUboot-bootable format (CONFIG_ESP32_APP_FORMAT_MCUBOOT): y System Type -\u0026gt; SPI Flash Configuration -\u0026gt; Application image primary slot offset (CONFIG_ESP32_OTA_PRIMARY_SLOT_OFFSET): 0x20000 Application image secondary slot offset (CONFIG_ESP32_OTA_SECONDARY_SLOT_OFFSET): 0x170000 Application image slot size (in bytes) (CONFIG_ESP32_OTA_SLOT_SIZE): 0x150000 Scratch partition offset (CONFIG_ESP32_OTA_SCRATCH_OFFSET): 0x3E0000 Scratch partition size (CONFIG_ESP32_OTA_SCRATCH_SIZE): 0x1F000 Zephyr RTOS # Enable the CONFIG_BOOTLOADER_MCUBOOT configuration and check if the flash partitions on the DTS from your board matches what was set in the \u0026lt;MCUBOOT_DIR\u0026gt;/boot/espressif/port/esp32/bootloader.conf. For this example it is possible to set an overlay file with the following content:\n\u0026amp;flash0 { partitions { boot_partition: partition@0 { label = \u0026#34;mcuboot\u0026#34;; reg = \u0026lt;0x0 DT_SIZE_K(64)\u0026gt;; }; slot0_partition: partition@20000 { label = \u0026#34;image-0\u0026#34;; reg = \u0026lt;0x20000 DT_SIZE_K(1344)\u0026gt;; }; slot1_partition: partition@170000 { label = \u0026#34;image-1\u0026#34;; reg = \u0026lt;0x170000 DT_SIZE_K(1344)\u0026gt;; }; storage_partition: partition@3b0000 { label = \u0026#34;storage\u0026#34;; reg = \u0026lt;0x3B0000 DT_SIZE_K(192)\u0026gt;; }; scratch_partition: partition@3e0000 { label = \u0026#34;image-scratch\u0026#34;; reg = \u0026lt;0x3E0000 DT_SIZE_K(124)\u0026gt;; }; }; }; Signing and Flashing the Application # Before flashing, sign the application binary using scripts/imgtool.py with python3. Replace \u0026lt;APP_BIN\u0026gt; with your application binary (e.g., nuttx.hex or zephyr.bin), and signed.bin will be the output signed image:\npython3 scripts/imgtool.py sign --align 4 -v 0 -H 32 --pad-header -S 0x00150000 \u0026lt;APP_BIN\u0026gt; signed.bin Alternatively, using imgtool (if you installed imgtool through pip):\nimgtool sign --align 4 -v 0 -H 32 --pad-header -S 0x00150000 \u0026lt;APP_BIN\u0026gt; signed.bin A Zephyr image with MCUboot compatibility doesn\u0026rsquo;t need the --pad-header parameter. Here is a quick look into what these imgtool sign parameters do:\n--align 4: Specify the flash device alignment as 4 bytes (32-bit word). -v 0: Specify the image version (in this case, 0). -H 32: Specify the MCUboot header size to be added to the image binary. --pad-header: Indicates to imgtool to add the MCUboot header into the beginning of the image binary, instead of overwritting it (the Zephyr build for some platforms already pads the binary beginning with 0s and may not need this parameter). -S 0x00150000: Indicates the slot size so the tool can add the MCUboot trailer properly. This step just adds the basic required header, however notice that we didn\u0026rsquo;t add any cryptographic key for security verification yet. It will be covered in the following parts of this MCUboot guide series. Refer to the imgtool documentation for more information. Flash the signed image to the device at the primary slot address:\nesptool.py -p /dev/ttyUSB0 -b 921600 --before default_reset --after hard_reset --chip esp32 write_flash --flash_mode dio --flash_size detect --flash_freq 40m 0x20000 signed.bin Checking the serial monitor, MCUboot should now successfully load and boot the application from the primary slot.\nNuttX\u0026rsquo;s nsh:\n[esp32] [INF] *** Booting MCUboot build v2.3.0-rc2-3-g234c66e6 *** [esp32] [INF] [boot] chip revision: v3.0 [esp32] [INF] [boot.esp32] SPI Speed : 40MHz [esp32] [INF] [boot.esp32] SPI Mode : DIO [esp32] [INF] [boot.esp32] SPI Flash Size : 4MB [esp32] [INF] [boot] Enabling RNG early entropy source... [esp32] [INF] Primary image: magic=unset, swap_type=0x1, copy_done=0x3, image_ok=0x3 [esp32] [INF] Scratch: magic=unset, swap_type=0x1, copy_done=0x3, image_ok=0x3 [esp32] [INF] Boot source: primary slot [esp32] [INF] Image index: 0, Swap type: none [esp32] [INF] Disabling RNG early entropy source... [esp32] [INF] br_image_off = 0x20000 [esp32] [INF] ih_hdr_size = 0x20 [esp32] [INF] Loading image 0 - slot 0 from flash, area id: 1 [esp32] [INF] DRAM segment: start=0x250a4, size=0xce4, vaddr=0x3ffb2010 [esp32] [INF] IRAM segment: start=0x20080, size=0x5024, vaddr=0x40080000 [esp32] [INF] start=0x40082048 IROM segment aligned lma 0x00040000 vma 0x400d0000 len 0x012afc (76540) DROM segment aligned lma 0x00030000 vma 0x3f410000 len 0x003060 (12384) NuttShell (NSH) NuttX-10.4.0 nsh\u0026gt; Zephyr\u0026rsquo;s hello world:\n[esp32] [INF] *** Booting MCUboot build v2.3.0-rc2-3-g234c66e6 *** [esp32] [INF] [boot] chip revision: v3.0 [esp32] [INF] [boot.esp32] SPI Speed : 40MHz [esp32] [INF] [boot.esp32] SPI Mode : DIO [esp32] [INF] [boot.esp32] SPI Flash Size : 4MB [esp32] [INF] [boot] Enabling RNG early entropy source... [esp32] [INF] Primary image: magic=unset, swap_type=0x1, copy_done=0x3, image_ok=0x3 [esp32] [INF] Scratch: magic=unset, swap_type=0x1, copy_done=0x3, image_ok=0x3 [esp32] [INF] Boot source: primary slot [esp32] [INF] Image index: 0, Swap type: none [esp32] [INF] Disabling RNG early entropy source... [esp32] [INF] br_image_off = 0x20000 [esp32] [INF] ih_hdr_size = 0x20 [esp32] [INF] Loading image 0 - slot 0 from flash, area id: 1 [esp32] [INF] DRAM segment: start=0x25f10, size=0x1110, vaddr=0x3ffb0000 [esp32] [INF] IRAM segment: start=0x20080, size=0x5e90, vaddr=0x40080000 [esp32] [INF] start=0x400830e0 I (327) boot: IROM : lma=00040000h vma=400d0000h size=036D8h ( 14040) map I (327) boot: DROM : lma=00030000h vma=3f400000h size=00E94h ( 3732) map I (343) boot: libc heap size 182 kB. I (343) spi_flash: detected chip: generic I (343) spi_flash: flash io: dio *** Booting Zephyr OS build v4.3.0-rc2-65-g03ce83a18fd5 *** Hello World! esp32_devkitc/esp32/procpu Conclusion # MCUboot provides a solid structure and defines a standard flow for firmware updates and secure boot. These features are already implemented in the bootloader and can be easily enabled without many modifications when developing firmware.\nFurthermore, as an open source project, MCUboot benefits from development by an interested and diverse community, resulting in faster issue resolution and active development.\nIn this guide, we covered how to build MCUboot bootloader for ESP32, how to sign an image, and how to organize flash properly. For more detailed information, refer to the official MCUboot documentation.\nThe next step for this series is to understand how updates work in the MCUboot and use this feature appropriately.\nResources # Original article (PT-BR language) MCUboot design documentation MCUboot Espressif Port documentation MCUboot Walkthrough and Porting Guide ","date":"9 January 2026","externalUrl":null,"permalink":"/blog/2026/01/mcuboot-getting-started/","section":"Blog","summary":"This guide provides a practical getting‑started walkthrough for using MCUboot on ESP32. It covers step-by-step environment setup, bootloader building, application configuration, and flashing. It also gives an overview of MCUboot\u0026rsquo;s execution flow.","title":"MCUboot - Getting Started Guide for ESP32","type":"blog"},{"content":"","date":"9 January 2026","externalUrl":null,"permalink":"/tags/zephyr/","section":"Tags","summary":"","title":"Zephyr","type":"tags"},{"content":"","date":"7 January 2026","externalUrl":null,"permalink":"/tags/component/","section":"Tags","summary":"","title":"Component","type":"tags"},{"content":"","date":"7 January 2026","externalUrl":null,"permalink":"/authors/david-cermak/","section":"Developer Portal Authors","summary":"","title":"David Cermak","type":"authors"},{"content":"","date":"7 January 2026","externalUrl":null,"permalink":"/tags/fuzzing/","section":"Tags","summary":"","title":"Fuzzing","type":"tags"},{"content":" Introduction # Fuzzing is one of the highest-leverage testing techniques you can add to an embedded codebase, especially for components that parse or generate data “from the outside world”: network packets, file formats, configuration blobs, discovery protocols, or any user-controlled input. Instead of crafting one “good” test vector at a time, a fuzzer repeatedly mutates inputs and feeds them into your code at high speed, looking for crashes, hangs, and sanitizer findings that indicate memory safety bugs, logic errors, or unhandled edge cases.\nIn embedded work we often assume fuzzing is “too heavy” because the target runs on a microcontroller. In practice, the trick is to fuzz on the host whenever possible. You compile a small slice of the component for Linux (or macOS/Windows), add sanitizers (ASan/UBSan), and fuzz the parsing/handling logic in a tight loop. This moves the expensive part—millions of iterations—off the device, while still finding real vulnerabilities that would manifest on hardware.\nThis article gives you a practical, repeatable workflow. We’ll start with a minimal “hello world” demonstration using a black-box mutator, then move to a coverage-guided campaign with AFL++, and finally outline how to design a fuzz harness for a protocol component.\nPrinciples and types # At a high level, fuzzing is “dynamic testing with adversarial inputs.” The key idea is simple: your code should be able to reject malformed inputs safely, without crashes or resource exhaustion. Fuzzing operationalizes this by continuously generating malformed inputs and observing whether the program misbehaves.\nThere are three common approaches, which differ mainly in how they generate inputs and how much feedback they use:\nBlack-box fuzzing (e.g., radamsa): Treats your program as a function that either succeeds or fails. The fuzzer mutates inputs without any feedback from the program. This is quick to set up and surprisingly effective for parsers, but it may plateau because it doesn’t “know” which inputs explore new code paths.\nGrey-box fuzzing (e.g., AFL++): Uses lightweight runtime feedback (usually code coverage) to guide mutations. When a new input reaches new code paths, it’s kept as an interesting seed. Over time this builds a corpus that explores deeper state machines and corner cases. Grey-box fuzzing is often the sweet spot for C/C++ embedded components compiled for host execution.\nWhite-box techniques (e.g., angr / symbolic execution): Try to reason about paths and constraints to generate inputs that reach specific program states. This can work without source code, but setup and scaling are harder; it’s commonly used in research and specialized audits rather than as a day-to-day pipeline.\nTwo concepts make fuzzing dramatically more productive:\nSanitizers: Build your harness with ASan/UBSan (and optionally MSan/TSan) so “silent” memory corruption becomes an immediate, actionable crash with a stack trace. A focused harness: Fuzz the smallest slice of code that processes untrusted data. If your harness needs networking, threads, or timers, fuzzing throughput collapses and results become noisy. Hello world (radamsa) # Before jumping to full coverage-guided fuzzing, it’s useful to internalize what fuzzing is doing with a tiny, concrete example. Consider a program that prints a greeting using a command-line argument. A common C mistake is accidentally treating user input as a format string—something that may “work” during normal testing but becomes dangerous under adversarial inputs.\nHere’s the contrived pattern:\nprintf(\u0026#34;Hello \u0026#34;); printf(argv[1]); // correct would be: printf(\u0026#34;%s\u0026#34;, argv[1]); printf(\u0026#34;!\\n\u0026#34;); Why is this a problem? Because sequences like %s, %n, or %p are interpreted by printf as format specifiers. With the wrong input, the program may read (or even write) memory it shouldn’t. On many systems it won’t reliably crash without instrumentation, which is exactly why fuzzing and sanitizers pair so well.\nBlack-box fuzzing with radamsa is an easy way to explore this. You start with a seed input (“David”), let radamsa mutate it many times, and execute the program repeatedly. The key is to compile with sanitizers so you turn undefined behavior into a reproducible, diagnosable failure.\nclang -O1 -g -fsanitize=address -fno-omit-frame-pointer hello.c -o hello echo \u0026#34;David\u0026#34; | radamsa -n 1000 | xargs -I{} ./hello \u0026#34;{}\u0026#34; What you’re practicing here is the core workflow you’ll reuse later:\nDefine a small entry point (the “device under test”). Feed it mutated inputs at high speed. Make failures loud (sanitizers) and actionable (stack traces). Once this clicks, you’re ready for grey-box fuzzing where the tool actively discovers deeper program behavior.\nmDNS example # Now scale the same mindset to a real embedded component: something that parses network packets and processes semi-structured data. mDNS is a great example because it’s widely deployed and has many edge cases: variable-length fields, compressed names, multiple record types, and “optional” lists that are easy to mishandle. The mDNS test harness is located in esp-protocols repository and a quick fuzzing campain runs in GitHub CI workflows.\nThe practical approach is to fuzz on the host:\nExtract the packet parsing/handling logic you care about (or compile the component for Linux with minimal shims). Build a fuzz harness that takes a raw byte buffer and calls into the parser as if it came from the network. Compile with sanitizers and run a fuzzer that can drive the harness millions of times. With AFL++, you get coverage-guided exploration. In plain terms: AFL++ mutates your input corpus, runs the harness, and keeps inputs that reach new code. When a crash happens, AFL++ stores the minimal reproducer and you can triage it deterministically.\nIn a real campaign, you’ll usually see multiple “crash types.” Some will be duplicates, some will be timeouts, and some will be genuine memory safety issues (use-after-free, invalid free, buffer overflow). The most useful habit is to treat each crash as a data point that answers two questions:\nCan an external party realistically deliver this input to the device? (e.g., multicast packet on the local network) What is the impact? (reset loop, memory corruption, denial of service, or potential code execution) Once you have a reproducer, fixing is often straightforward: validate lengths, harden list processing, avoid trusting pointers derived from malformed input, and ensure ownership rules are consistent. The bigger win is the lesson learned: a 15–30 minute host fuzz run can reveal issues that traditional unit tests rarely hit, especially in rarely-exercised error paths and boundary conditions.\nWalkthrough (MQTT example) # For protocol components such as MQTT clients, effective fuzzing requires generating protocol-plausible inputs and driving the implementation through relevant state transitions in a deterministic harness.\nIf you want to see a full working example, here’s an MQTT fuzz harness you can use as a reference: 0xFFFFE examples/10_afl_mqtt.\nHere’s a workflow you can reuse for almost any network-facing ESP-IDF component:\n1. Assess the component (pick the risk surface) # Start by mapping untrusted inputs and privilege:\nUntrusted input: network packets, broker responses, topics/payloads, properties, auth data, configuration blobs. Parser boundaries: where bytes turn into structs/strings/lists. State machine edges: reconnect, partial reads, timeouts, oversized fields, invalid UTF-8, and “optional” fields. A useful heuristic is the “rule of two”: if at least two of these are true—implemented in an unsafe language (C/C++), exposed to external input, or runs with high privilege/availability requirements—then fuzzing is likely worth it.\nExample: keep the client connected while feeding input # When fuzzing protocol state machines, a useful pattern is to “pin” the component in a meaningful state (e.g., connected) and repeatedly execute a single processing step per input. The exact APIs vary, but the harness shape often looks like this (pseudo-code):\nint esp_mqtt_client_fuzz_step(esp_mqtt_client_handle_t client /*, ... */) { // Ensure a valid transport is selected (inject fuzz transport for host runs). if (client-\u0026gt;transport == NULL \u0026amp;\u0026amp; client-\u0026gt;config \u0026amp;\u0026amp; client-\u0026gt;config-\u0026gt;transport) { client-\u0026gt;transport = client-\u0026gt;config-\u0026gt;transport; } // Initial connect if needed (mocked / shimmed in a host harness). if (client-\u0026gt;state == MQTT_STATE_INIT || client-\u0026gt;state == MQTT_STATE_DISCONNECTED) { // ... perform mock connect / set up state ... } // Process \u0026#34;incoming data\u0026#34; once. if (client-\u0026gt;state == MQTT_STATE_CONNECTED \u0026amp;\u0026amp; client-\u0026gt;transport) { int recvd = mqtt_message_receive(client, read_poll_timeout_ms); // ... decode/validate/state transitions ... return recvd; } return 0; } 2. Build a fuzz target (small, fast, deterministic) # Your goal is a harness that:\nCompiles and runs on Linux (or in a container) with sanitizers enabled. Invokes only the layers you want to test (e.g., decoding/validation/state transitions), not full networking stacks. Avoids threads, timers, and blocking I/O. Context switches and sleeps destroy fuzzing throughput and make failures nondeterministic. If the real component expects “socket reads,” simulate them with an in-memory buffer and a tiny shim.\nExample: mock/fuzz transport layer # If the component reads from a socket/transport, you can provide a transport that reads from the current fuzz input buffer:\n// Prepare a custom transport wrapping the current input. esp_transport_handle_t fuzz_transport = esp_transport_fuzz_init(data, size, g_autopilot, g_mode, g_frag); // handle errors esp_mqtt_client_config_t cfg = {0}; // Use direct transport mode (no real sockets). cfg.broker.address.transport = MQTT_TRANSPORT_UNKNOWN; cfg.network.transport = fuzz_transport; // ... initialize the client with cfg ... 3. Seed with valid-ish inputs (don’t start from pure noise) # Fuzzers work best when they can mutate inputs that are already close to valid. Build a small seed corpus:\nCaptured real traffic (sanitized) Manually crafted minimal messages Generated examples (including LLM-generated “valid” messages), then validated by your parser Optionally, add a few unit/property tests to encode invariants (“never crash,” “never allocate unbounded memory,” “reject invalid lengths”).\nExample seed generator: gen_seeds.py\n# Largely generate by LLM to exercise edge cases def gen_publish(out: str) -\u0026gt; None: ... # QoS 0 with retain and dup flags name = \u0026#34;publish_qos0_retain.bin\u0026#34;; pkt = pkt_publish(topic, b\u0026#34;retain\u0026#34;, qos=0, dup=False, retain=True) write_seed(out, name, pkt); write_dynamic_seed(out, 0x01, name, pkt) ... # QoS 1/2 variants ... # Boundary tests around Remaining Length varint (keep files modest) # Use short topic to keep payload sizes manageable. short_topic = \u0026#34;t\u0026#34; # For QoS0: RL = 2+len(topic) + payload_len vh_len_q0 = 2 + len(short_topic) # Choose total RL near 127 and 128 boundaries. for rl in (127, 128, 129): payload_len = max(0, rl - vh_len_q0) pl = bytes([0xAA]) * payload_len name = f\u0026#34;publish_qos0_rl{rl}.bin\u0026#34;; pkt = pkt_publish(short_topic, pl, qos=0) write_seed(out, name, pkt); write_dynamic_seed(out, 0x01, name, pkt) # For QoS1: RL = 2+len(topic) + 2(pkt id) + payload ... ... def main() -\u0026gt; None: ... gen_connack(out_dir) gen_publish(out_dir) gen_qos_acks(out_dir) gen_subacks(out_dir) gen_misc(out_dir) 4. Run fuzzing (iterate on harness + corpus) # Run AFL++ (or another engine) locally or in CI. If you use AFL++, you can run it in a container so you don’t need to install anything on your host:\n$ podman images REPOSITORY TAG IMAGE ID CREATED SIZE docker.io/aflplusplus/aflplusplus dev 020c3086c031 3 months ago 6.26 GB $ podman run -it --rm -v \u0026#34;$LOCAL_HARNESS_DIR:/fuzz\u0026#34; 020c3086c031 bash # Inside the container [AFL++ 3a7d79187853]$ afl-fuzz -i seeds -o findings -- ./mqtt_client_fuzz --mode=mqtt5 Expect to iterate: when coverage stalls, add seeds, simplify code paths, and remove unnecessary dependencies.\n5. Triage results (make it actionable) # For each unique crash:\nReproduce it with the saved input and the same build flags. Determine reachability on-device (can the attacker deliver it?). Patch, add a regression test, and keep the reproducer in the corpus so the bug stays dead. This loop—risk surface → minimal harness → good seeds → fuzz → triage—is the core skill. Once you have it, applying it to ESP-MQTT becomes mostly a matter of selecting the right entry points and modeling component state.\nIf using AFL++, inspect the findings/default directory. The tool saves crashes and hangs into the corresponding subdirectories as binary inputs:\n$ ls -la findings/default/crashes/ -rw------- 1 david david 557 Dec 30 15:00 README.txt -rw------- 1 david david 28 Dec 30 15:00 id:000000,sig:04,src:000008,time:234,execs:1292,op:flip32,pos:6 -rw------- 1 david david 28 Dec 30 15:00 id:000001,sig:04,src:000008,time:1284,execs:2761,op:havoc,rep:1 ... Then rebuild the harness without AFL++ instrumentation (still with sanitizers) and rerun it on the saved inputs to confirm and debug the issue (undefined behavior, timeouts, exceptions, etc.).\nConclusion # Fuzzing is not “random testing.” Done well, it’s a disciplined way to continuously pressure-test the parts of embedded systems that most often fail under real-world conditions: parsers, protocol handlers, and error paths. The practical recipe is consistent:\nFuzz on the host with sanitizers to get fast, diagnosable failures. Keep harnesses small and deterministic so throughput stays high. Seed with realistic inputs so the fuzzer can explore deeper states. Treat triage as part of development: reproduce, assess impact, fix, and lock in regressions. You don’t need a massive infrastructure to start. A single harness and a short weekly CI job can catch memory safety bugs and denial-of-service issues long before they show up on hardware or in production networks. As you expand beyond basic fuzzing, consider integrating property-based tests (to encode “correct behavior” beyond “does it crash?”) and exploring more advanced techniques when your threat model demands it.\nReport issues # This article provides step-by-step guidelines for fuzzing ESP-IDF components, and we encourage users to test and exercise their own components as well as internal/core SDK components. If you discover a security issue in ESP-IDF or an Espressif-managed component, please report it via Espressif Advisories.\n","date":"7 January 2026","externalUrl":null,"permalink":"/blog/2026/01/fuzzing/","section":"Blog","summary":"This article introduces fuzzing — a technique for finding vulnerabilities — and demonstrates practical workflows and lessons learned for ESP-IDF components and embedded libraries in general.","title":"Introduction to Fuzzing ESP-IDF components","type":"blog"},{"content":"","date":"7 January 2026","externalUrl":null,"permalink":"/tags/vulnerability/","section":"Tags","summary":"","title":"Vulnerability","type":"tags"},{"content":"","date":"6 January 2026","externalUrl":null,"permalink":"/tags/border-router/","section":"Tags","summary":"","title":"Border Router","type":"tags"},{"content":"","date":"6 January 2026","externalUrl":null,"permalink":"/tags/m5stack/","section":"Tags","summary":"","title":"M5Stack","type":"tags"},{"content":"","date":"6 January 2026","externalUrl":null,"permalink":"/authors/shu-chen/","section":"Developer Portal Authors","summary":"","title":"Shu Chen","type":"authors"},{"content":"","date":"6 January 2026","externalUrl":null,"permalink":"/tags/thread/","section":"Tags","summary":"","title":"Thread","type":"tags"},{"content":"Thread Credentials Sharing is an important feature introduced in Thread 1.4. It\u0026rsquo;s a secure procedure that allows sharing administrative access to an existing Thread network and extracting its network credentials. This feature enables new Thread Border Routers and devices to join an existing Thread network, creating a unified, scalable, and interoperable mesh without recreating a new network.\nWhat is Thread Network Credentials # Thread network credentials are a set of security and operational parameters required for a device to be part of a Thread network. It\u0026rsquo;s usually called the Operational Dataset and includes the following items:\nActive Timestamp: 1 Channel: 14 Wake-up Channel: 21 Channel Mask: 0x07fff800 Ext PAN ID: 02784020fbd06377 Mesh Local Prefix: fd2c:c3b9:f1fa:5de9::/64 Network Key: c3d8c8cf8a427b13facf757d2bab1249 Network Name: ESP-BR-4760 PAN ID: 0xfc30 PSKc: 8001219ca519cdf7103bb5c814fbf320 Security Policy: 672 onrc 0 The corresponding binary format (TLV-encoded Operational Dataset) is a compact hexadecimal representation:\n0e080000000000010000000300000e4a0300001535060004001fffe0020802784020fbd063770708fd2cc3b9f1fa5de90510c3d8c8cf8a427b13facf757d2bab1249030b4553502d42522d343736300102fc3004108001219ca519cdf7103bb5c814fbf3200c0402a0f7f8 Unlike Wi-Fi SSID and password, Thread credentials are not easy for humans to remember and type into mobile apps. A secure and user-friendly approach is desired, and the Thread Credentials Sharing feature addresses this need.\nWhy Thread Credentials Sharing is Important # Thread Credentials Sharing addresses several critical challenges in Thread network deployment and management:\nAvoiding network fragmentation: Credentials sharing allows Thread devices to join a single Thread network, reducing fragmentation and improving the overall mesh efficiency. Better coverage: By allowing Thread routers to join the same network, you can extend coverage and improve network reliability through redundancy. Cross-ecosystem interoperability: Thread Border Routers and devices from different ecosystems and device makers can all work in a single network, sharing the same Thread network infrastructure. Seamless device migration: Devices can be easily operated among different ecosystems without network reconfiguration. Improved user experience: Credentials sharing simplifies the onboarding process for new devices and network migration. Typical usage scenarios include:\nOnboarding new devices: When you want to onboard a new Thread device, but your app doesn\u0026rsquo;t know the credentials of the existing Thread network in your home. Ecosystem migration: When there are multiple Thread networks from different ecosystems in your home, and you want to migrate them into a single network to provide better network connectivity. Enabling Multi-Admin Environments: There could be multiple admin roles to onboard new devices on the same network (e.g., Matter protocol). They should share the same network credentials. How Thread Credentials Sharing Works # Thread Credentials Sharing involves three key participants:\nUser: The human user who initiates and facilitates the credentials sharing process Border Router: Strictly speaking, it\u0026rsquo;s the Border Agent role of the network, holding the existing Thread network credentials and sharing them Commissioner Candidate: Typically a mobile app that receives the credentials and onboards new devices or manages the network The procedure follows these steps:\nStart Credential Sharing: The user starts the Credentials Sharing process on the Border Router. It can be triggered in various ways, for example:\nThe Border Router\u0026rsquo;s display screen (if available) The Border Router\u0026rsquo;s vendor-specific mobile app Generate One-Time Passcode (OTPC): The Border Router generates a one-time passcode (OTPC) and advertises a MeshCoP-ePSKc DNS-SD service (_meshcop-e._udp).\nDisplay / Get OTPC: The user retrieves the OTPC from the Border Router, either from its display screen or mobile app.\nInput OTPC: The user inputs the OTPC into the Commissioner Candidate (typically a mobile app).\nDerive ePSKc: The Commissioner Candidate derives the ePSKc (Ephemeral Pre-Shared Key) from the OTPC.\nDiscover Border Router: The Commissioner Candidate discovers the Border Router operating in ePSKc mode via DNS-SD (mDNS).\nEstablish Secure Session: The Commissioner Candidate establishes a secure DTLS session with the Border Router using the derived ePSKc.\nExtract Credential: The Border Router securely transfers the Thread network credentials to the Commissioner Candidate.\nUse the Credential: Once the Credentials Sharing procedure is complete, the Commissioner Candidate can use the credentials to:\nCommission new devices to the same Thread network Migrate or restore existing Thread networks Securely store the credentials in the phone\u0026rsquo;s keychain for reuse by other apps Production Considerations # Credentials Sharing is a mandatory feature for Thread 1.4 Border Routers. Every Thread 1.4 (and later) certified Border Router must support this feature to ensure interoperability and seamless network management across different ecosystems and platforms.\nDemo using M5Stack Thread Border Router and Samsung SmartThings app # The M5Stack Thread Border Router is a Thread 1.4 certified Border Router that supports the Credentials Sharing feature. It provides a practical example of how Credentials Sharing works in real-world deployments.\nThe Samsung SmartThings ecosystem also supports the Thread 1.4 Credentials Sharing feature. For more details, see SmartThings release notes.\nIn this demo, we start with two separate Thread networks: one hosted by Samsung SmartThings and another by the M5Stack Thread Border Router. We then demonstrate using the SmartThings app to extract Thread credentials from the M5Stack Thread Border Router and migrate the SmartThings Thread Border Router to the M5Stack network. This demonstrates how the two networks can be migrated into a single unified network.\nSet up M5Stack Thread Border Router # You can either get an M5Stack Thread Border Router with pre-flashed firmware, or set it up yourself by building and flashing the example from the Espressif Thread BR repository.\nFirst Boot: On first boot, the device will start in SoftAP mode and provide a Wi-Fi configuration web service.\nConfigure Wi-Fi:\nJoin the SoftAP network (SSID: ESP-ThreadBR-xxx) from your phone or PC Visit http://192.168.4.1 to configure Wi-Fi SSID and password Once configured, the device does the following:\nConnects to the configured Wi-Fi network Forms a Thread network Acts as a Thread Border Router Perform Credentials Sharing using SmartThings App # The steps to perform Credentials Sharing using the SmartThings app:\nSet up SmartThings Hub: Using the SmartThings app, set up a SmartThings hub with Thread Border Router capability.\nGenerate OTPC: Click the Share Thread Network Credential button on the M5Stack Thread Border Router screen. The device will generate an OTPC and display it on the screen, along with a QR code for easy scanning.\nNavigate to Thread Network Settings: In the SmartThings app, navigate to Settings → Manage Thread Network → Unify Thread network → Join this hub to another service\u0026rsquo;s Thread network → Choose the discovered network. (please ensure the Phone is on the same Wi-Fi network as the M5Stack Thread Border Router)\nEnter OTPC: On the Join another Thread network page, input the OTPC or scan the QR code from the M5Stack screen.\nComplete Migration: The credentials sharing process will happen automatically. Once complete, you will find that the SmartThings hub has migrated itself to the M5Stack Thread Border Router\u0026rsquo;s network.\nSome key screenshots from step 3 and 4 are shown below:\nWhen the SmartThings Border Router migrates to the M5Stack network, the Thread devices that were previously connected to the original SmartThings network need to update their network configuration. This process is handled automatically through Thread\u0026rsquo;s Pending Dataset mechanism:\nPending Dataset Distribution: After the Border Router adopts the new network credentials, it distributes a Pending Operational Dataset to all devices in its network. This dataset contains the new network parameters (network key, PAN ID, channel, etc.) that will replace the current Active Operational Dataset.\nSynchronized Transition: Along with the Pending Dataset, there is a corresponding Delay Timer, ensuring all devices receive the update and can synchronize the transition. When the timer expires, all devices simultaneously switch to the new Active Operational Dataset. Throughout the transition, device connectivity is maintained, ensuring a seamless user experience.\nThis mechanism ensures that all devices smoothly transition to the unified network without becoming orphaned or requiring manual reconfiguration.\nThe credential sharing and network migration process is now complete, and devices from both the SmartThings and M5Stack networks are operating seamlessly within a unified Thread network.\nThis demo shows how Credentials Sharing simplifies the process of adding new Border Routers or migrating between ecosystems, making Thread networks more user-friendly and interoperable. The M5Stack Thread Border Router serves as an excellent example of how Thread 1.4 features can be implemented in practical, developer-friendly hardware.\nOther Credentials Sharing Methods # The method described above is the standardized Thread credentials sharing mechanism defined in the Thread Specification, there are other methods available depending on the platform and ecosystem.\nOS-Level APIs # As mentioned in the procedure section, once the Commissioner Candidate receives the credentials, it can store them in the phone\u0026rsquo;s keychain for future use. The same credentials can be read by other phone apps running on the same device. Both iOS and Android mobile operating systems provide native APIs for Thread credentials management:\niOS Thread Network Framework: Apple provides the Thread Network framework that allows apps to store and retrieve Thread credentials securely in the system keychain. This enables seamless credentials sharing between apps and system services. The framework includes the Thread Network Credentials API for managing credentials.\nAndroid Google Home APIs: Google provides Thread credentials management through the Google Home APIs, allowing Android apps to access and share Thread network credentials. Similar to iOS, this provides high-level APIs for managing credentials.\nThese OS-level APIs provide a secure and straightforward way for applications to access Thread credentials and share them among apps from different ecosystems.\nApplication-Level Protocols # Some application protocols implement credentials sharing mechanisms over the application layer secure session:\nMatter: The Matter specification includes a Thread Border Router Management Cluster that can be used for Thread network management, including credentials operations. Matter controllers can use this cluster to manage Thread Border Routers and retrieve network credentials. This provides an application-layer abstraction for Thread credentials management within the Matter ecosystem, enabling seamless integration with Matter-based smart home systems.\nESP RainMaker: Espressif\u0026rsquo;s RainMaker over Thread solution provides a Thread Border Router service that includes credentials management capabilities. This allows RainMaker apps to share and manage Thread credentials for devices in the RainMaker ecosystem.\nREST APIs # Some Thread Border Router implementations provide local REST APIs that allow authorized applications to retrieve network credentials. These are typically secured using local network access control and provide a web-based interface for Thread network management. For example:\nOpenThread Border Router (OTBR/ot-br-posix): Provides REST APIs as defined in the openapi.yaml Espressif Thread Border Router SDK: Provides compatible REST APIs as documented in the Thread REST APIs guide Conclusion # Thread Credential Sharing is a pivotal feature that addresses key challenges in Thread network deployment and management. By enabling secure sharing of network credentials, it prevents network fragmentation, enables cross-ecosystem interoperability, and significantly simplifies device onboarding and migration.\nRelated Resources # Thread 1.4 Features White Paper - Official Thread Group documentation on Thread 1.4 features Apple Thread Network framework - iOS Thread Network framework documentation Google Home APIs for Thread - Android Thread credentials management APIs M5Stack Thread Border Router - M5Stack Thread Border Router documentation Espressif Thread Border Router - Espressif\u0026rsquo;s Thread Border Router solution OpenThread - Open-source Thread stack implementation ","date":"6 January 2026","externalUrl":null,"permalink":"/blog/2026/01/thread-credential-sharing/","section":"Blog","summary":"This article introduces the Thread Credentials Sharing feature, explains why it is important, how it works, and provides a demo using M5Stack Thread Border Router and SmartThings app.","title":"Thread Network Credentials Sharing","type":"blog"},{"content":" Introduction # ESP-IDF allows users to control many aspects of the build process and behavior of the resulting application. In other words, it allows you to configure even the finest details of the project. Configuration, especially in frameworks such as ESP-IDF, is a complex task consisting of several steps.\nWe will first explain how configuration works in ESP-IDF v5, which has been a standard for a long time. We also demonstrate how default values are managed in ESP-IDF v5 and specify what is the issue with the current solution and how we can overcome it.\nThen, we will move to the new process of managing default values, which is available in the ESP-IDF v6.0. We will learn how this configuration system handles default values and how their behavior differs from the previous version when idf.py menuconfig is executed. We will also explain what is a default value conflict and how to resolve it with the idf.py refresh-config command, available in ESP-IDF v6.1+ and what are the alternatives for ESP-IDF v6.0.\nCurrently (January of 2026), ESP-IDF v6.1 is not released yet and v6.0 is a beta/pre-release. However, you can still try and test features described in this article by using ESP_IDF master branch from Github. Configuration in ESP-IDF v5 and Older # Let\u0026rsquo;s briefly explain how configuration worked in ESP-IDF v5 and older and we actually mean by the term \u0026ldquo;configuration\u0026rdquo;.\nIn our context, configuration is a way how to:\nDefine config options. Assign values to them. Expose the resulting mappings (CONFIG_NAME=current_config_value) to the rest of the project (e.g. C/C++ code or CMake). The first step is handled through a Kconfig file, the second step is realized via idf.py menuconfig (or automatically during the build) and the third is achieved via sdkconfig file.\nKconfig File # The Kconfig file contains the definitions of config options: their names and other properties, such as default values, which are especially relevant in this context.\nEvery config option is identified by its name, which written in capital letters and directly follows the config keyword. Default values are specified on lines starting with the default keyword, followed by the value itself and, optionally, a condition introduced by the if keyword.\nWe are covering only the Kconfig basics needed for this article. For the full syntax, see the Kconfig language description. Let\u0026rsquo;s see an example:\nconfig OPTION int \u0026#34;Config option demonstrating default values\u0026#34; help This config option helps us understand default values in ESP-IDF configuration. default 1 if CONDITIONAL_OPTION default 0 config CONDITIONAL_OPTION bool \u0026#34;Config option to condition of the default values\u0026#34; default y Default Value Evaluation # Default values are used for config options that have not been explicitly set by the user (they don\u0026rsquo;t have a user-set value). When you build a fresh project for the first time, all config options are initialized to their default values. These values can later be adjusted using a configuration tool (such as idf.py menuconfig).\nLet\u0026rsquo;s explain the process how configuration system evaluates which default value should be assigned to given config option for both example config options (OPTION and CONDITIONAL_OPTION).\nWe will start with the OPTION config option, which has two rows defining default values:\ndefault 1 if CONDITIONAL_OPTION default 0 Rules to decide which default value will be used are quite simple. Configuration system analyzes rows from top to bottom and checks whether the condition for each default value is true. If the condition is true or a default value has no condition, we use that line immediately:\nStarting with default 1 if CONDITIONAL_OPTION, the condition which is needed to be evaluated is simply CONDITIONAL_OPTION. In order to evaluate the condition, it is needed to evaluate the (default) value of CONDITIONAL_OPTION. There is only one default value ofr CONDITIONAL_OPTION, default y. It has no condition, so the configuration system uses the value y for CONDITIONAL_OPTION. The y symbol is just a Kconfig way how to denote true. Condition for the line default 1 if CONDITIONAL_OPTION is evaluated as y/true. Condition is therefore met and the default value for our OPTION should be 1. Sdkconfig File # When we build fresh project for the first time, configuration system collects all the Kconfig files relevant for our project and assigns default value to each config option as we described in the previous section. This creates the mapping CONFIG_NAME=current_config_value, which is then stored into the sdkconfig file.\nBased on the sdkconfig file, format-specific files are also created, such as sdkconfig.h and sdkconfig.cmake, exposing these mappings to the rest of the project. The mappings are the same there, only adjusted for given application format. For the example Kconfig file we have seen in the previous section, the content of the corresponding sdkconfig file will be:\nCONFIG_CONDITIONAL_OPTION=y CONFIG_OPTION=1 All the config options got a CONFIG_ prefix. This helps distinguish between a config option and other types of variables when using them e.g. in the C/C++ code. This means that OPTION in Kconfig and CONFIG_OPTION in sdkconfig file are the same config option.\nThe configuration system behaved according to the algorithm described in the previous section and assigned set our OPTION to 1.\nDuring the first configuration run in ESP-IDF v5, default values from Kconfig files are stored in sdkconfig file.\nHowever, an essential part of the configuration is the ability to change the values of config options. In ESP-IDF, there are several ways how to achieve this, one of the most straightforward is being menuconfig.\nWhen the idf.py menuconfig command (or project build) is run this time, the configuration system loads both the Kconfig files and the sdkconfig file, initializing all the config options to the values stored in there.\nIf CONDITIONAL_OPTION gets disabled in menuconfig, the sdkconfig file will look like this:\n# CONFIG_CONDITIONAL_OPTION is not set CONFIG_OPTION=1 If you look at the definition of the OPTION config option from the Kconfig, you can spot a certain \u0026ldquo;inconsistency\u0026rdquo;; even though CONDITIONAL_OPTION is disabled, OPTION is still set to 1.\nAs said before, configuration system saves the values for all config options in the sdkconfig file. However, when it loads those values back, it \u0026ldquo;locks\u0026rdquo; config options on those values \u0026ndash; meaning their default values (as we saw them in Kconfig file) will no longer be in use and only user-made changed will be applied. This can lead to confusing situations, like the one just described.\nHow menuconfig loads and saves values in ESP-IDF v5.x\nConfiguration in ESP-IDF v6 # The new configuration system, which is available in ESP-IDF v6.0 and newer, solves this problem by storing not only the value for every config option, but also the information whether the value is user-set or default. Let\u0026rsquo;s go through the process again and explain the differences.\nWhen a fresh project is built for the first time, configuration system loads the relevant Kconfig files and saves default values to the sdkconfig file like before, but this time it adds additional # default: marks:\n# default: CONFIG_CONDITIONAL_OPTION=y # default: CONFIG_OPTION=1 All config options with default values are now marked with a # default: mark right above them. The configuration system now knows which config options should be re-evaluated during the menuconfig session, because their default values may change.\nStarting with ESP-IDF v6, sdkconfig also stores information whether given option is default or not for every config option.\nLet\u0026rsquo;s run menuconfig once again, disable CONDITIONAL_OPTION and save it:\n# CONFIG_CONDITIONAL_OPTION is not set # default: CONFIG_OPTION=0 The CONDITIONAL_OPTION option no longer have the # default: mark, which is expected since we manually assigned user-set value to it. What is noteworthy is that OPTION registered this change; the original condition for the first default value is no longer valid, so the system now applies the second default value instead.\nHow menuconfig loads and saves values in ESP-IDF v6.x\nDefault Value Conflicts # Default value obtained from the Kconfig file can be different than the one saved in sdkconfig for some config options in certain situations. We will explain how these situations occur and how to resolve them.\nLet\u0026rsquo;s suppose OPTION was a part of a component. In the new release of the component, its definition (namely the default value) has changed:\nconfig OPTION int \u0026#34;Prompt for config option\u0026#34; help New version of OPTION. default 99 # different from the previous version! If the component version inside the project is updated, the next time the project is rebuilt or menuconfig is run, the configuration system will have two contradicting pieces of information:\nKconfig file says that the default value for OPTION is 99. sdkconfig file says that it is 0. The configuration system handles this by first notifying the user:\ninfo: Default value for OPTION in sdkconfig is 0 but it is 99 according to Kconfig. Then, configuration system chooses one of those values based on its policy, which specifies the \u0026ldquo;preferred source\u0026rdquo; for default values. Depending on the policy, configuration system can either prefer the sdkconfig default value, Kconfig default value or let the user interactively decide which value to use for every config option individually.\nBy default, the policy is set to favor sdkconfig. It is a backward compatible behavior ensuring the same values will be passed to build system if configuration was not changed by the user, even after e.g. component update.\nBut we may want to use the new default value from Kconfig (new component version relies on that value or it is just favorable for us). Or, if there is not only one config option that has changed, but several, we want to choose which default value to use separately for each config option.\nidf.py refresh-config # The idf.py refresh-config command, which is available in ESP-IDF v6.1+, solves default value conflicts in respect to the policy specified by --policy argument, which can have following values:\nsdkconfig: default values from sdkconfig file will be used. In our case, the OPTION config option would have default value 0. kconfig: default values from Kconfig file will be used. That means the OPTION config option would have the value 99. interactive: this option allows the user to choose the source of default value for each affected config option manually. This command is not planned to be available in ESP-IDF v6.0. You will still be notified in a default value mismatch occurs, but the recommended procedure is to set given config option manually to a desired value in menuconfig. How idf.py refresh-config works based on defaults policy chosen\nConclusion # In this article, we explained:\nHow default values work in ESP-IDF v5 and the limitations of the current approach The new default value management system introduced in ESP-IDF v6.1 What default value conflicts are and how they can occur during component updates How to resolve conflicts using the new idf.py refresh-config command with different policies The new configuration system in ESP-IDF v6 provides more intuitive behavior for default values while maintaining backward compatibility. ESP-IDF v6.1 also provides users with control over how conflicts are resolved.\nFurther Reading # Kconfig language description: https://docs.espressif.com/projects/esp-idf-kconfig/en/latest/kconfiglib/language.html Migration guide for the configuration system (esp-idf-kconfig): https://docs.espressif.com/projects/esp-idf-kconfig/en/latest/developer-guide/migration-guide.html In-depth default value explanation: https://docs.espressif.com/projects/esp-idf-kconfig/en/latest/kconfiglib/defaults.html ESP-IDF Project Configuration Guide: https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-guides/kconfig/index.html ESP-IDF Component Configuration Guide: https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-guides/kconfig/component-configuration-guide.html ","date":"22 December 2025","externalUrl":null,"permalink":"/blog/2025/12/configuration-in-esp-idf-6-defaults/","section":"Blog","summary":"This article explains what are the default values in the ESP-IDF configuration and how they are managed in the configuration system in the upcoming ESP-IDF v6. The purpose and behavior of default values are described. This article also explains what is a conflict in default values and how to resolve it with the \u0026ldquo;idf.py refresh-config\u0026rdquo; command.","title":"Changes in the Configuration System in ESP-IDF v6: Default Values","type":"blog"},{"content":"","date":"22 December 2025","externalUrl":null,"permalink":"/tags/esp-idf-kconfig/","section":"Tags","summary":"","title":"Esp-Idf-Kconfig","type":"tags"},{"content":"","date":"22 December 2025","externalUrl":null,"permalink":"/tags/idf.py/","section":"Tags","summary":"","title":"Idf.py","type":"tags"},{"content":"","date":"22 December 2025","externalUrl":null,"permalink":"/authors/jan-beran/","section":"Developer Portal Authors","summary":"","title":"Jan Beran","type":"authors"},{"content":"","date":"22 December 2025","externalUrl":null,"permalink":"/tags/overview/","section":"Tags","summary":"","title":"Overview","type":"tags"},{"content":"","date":"22 December 2025","externalUrl":null,"permalink":"/tags/sdkconfig/","section":"Tags","summary":"","title":"Sdkconfig","type":"tags"},{"content":"","date":"15 December 2025","externalUrl":null,"permalink":"/tags/arduino/","section":"Tags","summary":"","title":"Arduino","type":"tags"},{"content":"Creating custom Arduino libraries is an excellent way to organize reusable code, share functionality with others, and make your projects more modular. This article covers the process of creating an Arduino library from scratch, using a simple \u0026ldquo;Hello World\u0026rdquo; library as a working example.\nWhat is an Arduino Library? # An Arduino library is a collection of code that provides additional functionality to your sketches. Libraries encapsulate related functions, classes, and constants into reusable modules that can be easily shared and imported into different projects. Key benefits include:\nCode Reusability: Write once, use in multiple projects. Modularity: Keep your main sketch clean and focused. Shareability: Easily distribute your code to the community. Maintainability: Update the library in one place. Encapsulation: Hide implementation details and expose a clean API. Arduino libraries can range from simple utility functions to complex drivers for sensors, displays, communication protocols, and more. For ESP32 development, libraries are particularly useful for abstracting hardware-specific features like Wi-Fi, Bluetooth, GPIOs, and peripheral interfaces.\nLibrary Structure # An Arduino library follows a specific directory structure that the Arduino IDE recognizes. Here\u0026rsquo;s the usual structure of a well-organized library:\nLibrary Folder/ ├── src/ # Source code files │ ├── LibraryName.h │ └── LibraryName.cpp ├── examples/ # Example sketches showing library usage │ └── ExampleSketch/ │ └── ExampleSketch.ino ├── library.properties # Library information and metadata ├── keywords.txt # Defines syntax highlighting for library’s functions and classes ├── README.md └── LICENSE Prerequisites # To create an Arduino library for ESP32, you will need:\nArduino IDE installed on your computer Arduino Core for ESP32 installed A text editor or IDE for writing code Basic understanding of C++ programming If you haven\u0026rsquo;t installed the Arduino Core for ESP32 yet, follow the steps in the article Getting Started with ESP32 Arduino.\nCreating a \u0026ldquo;Hello World\u0026rdquo; Library # Let\u0026rsquo;s create a simple library from scratch. Our HelloWorldLib library will demonstrate the core concepts of library development with a minimal example.\nFirst, we must define what the library needs to do. In this case, we want a simple class with a few methods to print \u0026ldquo;Hello, World!\u0026rdquo; and \u0026ldquo;Hello, \u0026lt;name\u0026gt;!\u0026rdquo; to the Serial interface. We will call this class HelloWorld.\nWith the library\u0026rsquo;s purpose defined, we can start the implementation.\nStep 1: Create the Library Folder Structure # First, we need to create the folder structure for our library. The Arduino libraries folder is typically located at:\nWindows: Documents\\Arduino\\libraries\\ macOS: ~/Documents/Arduino/libraries/ Linux: ~/Arduino/libraries/ Navigate to your Arduino libraries folder and create the following structure:\nHelloWorldLib/ ├── src/ │ ├── HelloWorld.h │ └── HelloWorld.cpp ├── examples/ │ └── BasicUsage/ │ └── BasicUsage.ino ├── library.properties ├── keywords.txt ├── README.md └── LICENSE Step 2: Create HelloWorld.h # The header file (.h) serves as the public interface of our library. It declares the classes, functions, and constants that users will interact with, without exposing implementation details. When users include our library with #include \u0026lt;HelloWorld.h\u0026gt;, they\u0026rsquo;re including this file.\nFor our HelloWorldLib library, this file will declare the HelloWorld class with its three public methods (begin, sayHello, sayHelloTo) and a constant for demonstration purposes.\nHere\u0026rsquo;s our src/HelloWorld.h:\n/* * HelloWorldLib for ESP32 * A simple demonstration library for ESP32 Arduino development. */ #pragma once #include \u0026#34;Arduino.h\u0026#34; // Example of a constant for syntax highlighting #define HELLO_WORLD_LIB_STRING \u0026#34;HelloWorldLib for ESP32\u0026#34; class HelloWorld { public: // Initialize the library with the Serial interface void begin(Stream \u0026amp;serial); // Print \u0026#34;Hello, World!\u0026#34; to Serial void sayHello(); // Print \u0026#34;Hello, \u0026lt;name\u0026gt;!\u0026#34; to Serial void sayHelloTo(const char *name); private: Stream *_serial; }; Key points about the header file:\nInclude Guards: Use #pragma once to avoid multiple inclusions of the header file and prevent errors and warnings during compilation. Arduino.h: It is recommended to include Arduino.h to access Arduino core functions and types. Step 3: Create HelloWorld.cpp # The implementation file (.cpp) contains the actual logic behind the functions and methods declared in the header. This separation keeps implementation details \u0026ldquo;hidden\u0026rdquo; from the user and allows changing the internal code without affecting users, as long as the public interface stays the same.\nHere we will implement begin() to store the Stream reference, and sayHello()/sayHelloTo() to print messages using that stream.\nThe src/HelloWorld.cpp file:\n/* * HelloWorldLib for ESP32 * Implementation file. */ #include \u0026#34;HelloWorld.h\u0026#34; // Initialize the library with the Serial interface void HelloWorld::begin(Stream \u0026amp;serial) { _serial = \u0026amp;serial; } // Print \u0026#34;Hello, World!\u0026#34; to Serial void HelloWorld::sayHello() { if (_serial) { _serial-\u0026gt;println(\u0026#34;Hello, World!\u0026#34;); } } // Print \u0026#34;Hello, \u0026lt;name\u0026gt;!\u0026#34; to Serial void HelloWorld::sayHelloTo(const char *name) { if (_serial) { _serial-\u0026gt;print(\u0026#34;Hello, \u0026#34;); _serial-\u0026gt;print(name); _serial-\u0026gt;println(\u0026#34;!\u0026#34;); } } Step 4: Create the Example Sketch # Example sketches demonstrate how to use the library in practice. They appear in the Arduino IDE under File \u0026gt; Examples \u0026gt; [LibraryName] and serve as both documentation and a starting point for users. Good examples are often one of the most valuable parts of a library.\nOur BasicUsage example will show the typical workflow: include the library, create an instance, initialize it with begin(), and call the greeting methods.\nFor our examples/BasicUsage/BasicUsage.ino:\n/* * HelloWorldLib - Basic Usage Example * * This example demonstrates the basic functionality of the HelloWorldLib library. * * Compatible with all ESP32 variants. */ #include \u0026lt;HelloWorld.h\u0026gt; HelloWorld hello; void setup() { Serial.begin(115200); // Initialize the library with Serial hello.begin(Serial); // Print \u0026#34;Hello, World!\u0026#34; hello.sayHello(); // Print a personalized greeting hello.sayHelloTo(\u0026#34;ESP32\u0026#34;); } void loop() { // Nothing to do here } Expected Serial Monitor output:\nHello, World! Hello, ESP32! Step 5: Create library.properties # The library.properties file contains metadata that the Arduino IDE and Library Manager use to identify, categorize, and display the library. This file is required for the Arduino IDE to recognize the folder as a valid library.\nHere are some of the main fields that you will need to set in the library.properties file:\nField Description name The library name (must match the folder name) version Semantic versioning (MAJOR.MINOR.PATCH) author Original author(s) of the library maintainer Current maintainer responsible for updates sentence Brief one-line description (shown in Library Manager) paragraph Extended description with more details category Library category (Check the Arduino Library Specification for the list of categories) url Repository or documentation URL architectures Supported platforms (* for all, or specific like esp32 for the ESP32 series of microcontrollers) includes Header file(s) users should include For the first release of your library, choose the version based on its stability:\nPre-release versions (0.x.x): Use this for initial development when the API may still change. Start with 0.1.0 for your first working version. The 0.x.x range signals to users that the library is still evolving and breaking changes may occur. First stable release (1.0.0): Use this when your library has a stable API that you\u0026rsquo;re committed to maintaining. This tells users the library is production-ready and you\u0026rsquo;ll follow semantic versioning for future changes. Most new libraries should start with 0.1.0 and increment to 1.0.0 once the API is stable and tested. For our example library, let\u0026rsquo;s say that we are still in the initial development phase, it is only compatible with the ESP32 series of microcontrollers, and that the user should include the HelloWorld.h header file. We can add the following content to library.properties in the root folder:\nname=HelloWorldLib version=1.0.0 author=Your Name \u0026lt;your.email@example.com\u0026gt; maintainer=Your Name \u0026lt;your.email@example.com\u0026gt; sentence=A simple demonstration library for ESP32 Arduino development. paragraph=This library demonstrates how to create Arduino libraries for Espressif ESP32 microcontrollers. category=Other url=https://github.com/yourusername/HelloWorldLib architectures=esp32 includes=HelloWorld.h If your library is only compatible with the ESP32 series of microcontrollers, you should set the architectures field to esp32 no matter the SoC you are using (for example, even if you are using the ESP32-C6, the architecture should still be esp32).\nOn the other hand, if your library is independent of the architecture, setting the architectures field to * will indicate support for all architectures.\nYou can also define multiple include files and architectures by separating them with commas.\nFor more information about the library.properties file, see the Arduino Library Specification.\nStep 6: Create keywords.txt # The Arduino IDE uses syntax highlighting to color-code different elements in your sketch, making it easier to read and spot errors. Built-in functions like digitalWrite and constants like HIGH are automatically highlighted, but the IDE doesn\u0026rsquo;t know about your library\u0026rsquo;s custom classes and methods.\nThe keywords.txt file solves this by mapping your library\u0026rsquo;s identifiers to keyword types. When the IDE loads a library, it reads this file and applies the appropriate colors to matching words in the editor. While optional, it significantly improves the user experience.\nThe file uses a simple format: each line contains an identifier followed by a TAB character and a keyword type:\nKEYWORD1 — Used for classes and datatypes (e.g., HelloWorld, String) KEYWORD2 — Used for methods and functions (e.g., begin, sayHello) LITERAL1 — Used for constants (e.g., HELLO_WORLD_LIB_STRING, LED_BUILTIN) For our library, we will register HelloWorld as a KEYWORD1, our methods as KEYWORD2, and HELLO_WORLD_LIB_STRING as a LITERAL1.\nOur keywords.txt will look like this:\n####################################### # Syntax Coloring Map for HelloWorldLib Library ####################################### ####################################### # Datatypes (KEYWORD1) ####################################### HelloWorld\tKEYWORD1 ####################################### # Methods and Functions (KEYWORD2) ####################################### begin\tKEYWORD2 sayHello\tKEYWORD2 sayHelloTo\tKEYWORD2 ####################################### # Constants (LITERAL1) ####################################### HELLO_WORLD_LIB_STRING\tLITERAL1 Important: Use actual TAB characters between the keyword and its type, not spaces. The Arduino IDE will not recognize the keywords if spaces are used.\nStep 7: Create README.md # The README.md file is the first thing users see when they visit the library\u0026rsquo;s repository. It should explain what the library does, how to install it, and provide basic usage examples. A clear README reduces support questions and helps users get started quickly.\nOur README will cover installation instructions, a quick usage example, and document the available methods.\nHere\u0026rsquo;s a simple README.md for our library:\n# HelloWorldLib for ESP32 A simple demonstration library that prints \u0026#34;Hello, World!\u0026#34; and \u0026#34;Hello, \u0026lt;name\u0026gt;!\u0026#34; to the Serial interface. ## Installation ### Manual Installation 1. Download the library 2. Move the `HelloWorldLib` folder to your Arduino libraries directory: - Windows: `Documents\\Arduino\\libraries\\` - macOS: `~/Documents/Arduino/libraries/` - Linux: `~/Arduino/libraries/` 3. Restart the Arduino IDE ## Usage ```cpp #include \u0026lt;HelloWorld.h\u0026gt; HelloWorld hello; void setup() { Serial.begin(115200); hello.begin(Serial); hello.sayHello(); } void loop() {} ``` ## API Reference ### Methods - `void begin(Stream \u0026amp;serial)` - Initialize the library with a Serial interface - `void sayHello()` - Print \u0026#34;Hello, World!\u0026#34; - `void sayHelloTo(const char *name)` - Print a personalized greeting ## Compatibility This library is compatible with all ESP32 variants. ## License This library is released under the MIT License. Step 8: Create LICENSE # The LICENSE file is a file that contains the license under which the library is released. It is used to specify how others can use, modify, and distribute the library. While the license is optional, it is highly recommended to include it in your library. Without a license, others cannot legally use your code.\nCommon choices for Arduino libraries include MIT, Apache 2.0, and LGPL. You can easily create a LICENSE file using the Choose a License website.\nFor your library to be accepted by the Arduino Library Manager, it must include a valid OSI-approved license. Our LICENSE will look like this. Make sure to replace the [year] and [fullname] with the correct values:\nMIT License Copyright (c) [year] [fullname] Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the \u0026#34;Software\u0026#34;), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED \u0026#34;AS IS\u0026#34;, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. Testing the Library # After creating all the files, we can test our library:\nRestart the Arduino IDE to load the new library. Go to File \u0026gt; Examples \u0026gt; HelloWorldLib \u0026gt; BasicUsage. Select your ESP32 board from Tools \u0026gt; Board. Select the correct port from Tools \u0026gt; Port. Click Upload to flash the sketch to the ESP32. Open Serial Monitor at 115200 baud to see the output. Expected output:\nHello, World! Hello, ESP32! Best Practices for Library Development # When creating Arduino libraries, keep these best practices in mind:\nUse Meaningful Names: Choose clear, descriptive names for your library, classes, and methods. Provide a begin() Method: Always provide a begin() method that initializes the library (if applicable). Include Examples: Provide well-commented examples that demonstrate common use cases. Follow Semantic Versioning: Use semantic versioning (MAJOR.MINOR.PATCH) for releases. Minimize Dependencies: Keep dependencies to a minimum for easier installation. Publishing Your Library # Once your library is ready, you can share it with the community through GitHub and the Arduino Library Manager.\nAs mentioned before, make sure your library includes an OSI-approved license before publishing.\nIncrement the Version # Before releasing a new version, we need to decide the new version number and update the version number in your library.properties file. The new version number must follow the rules of Semantic Versioning and be updated based on the changes made to the library since the last release:\nMAJOR (1.x.x → 2.0.0): Incompatible API changes MINOR (1.0.x → 1.1.0): New features, backward compatible PATCH (1.0.0 → 1.0.1): Bug fixes, backward compatible Create a GitHub Release # Create a repository on GitHub and push your library code. Skip this step if you already have a repository for your library.\nUpdate the version in library.properties based on the semantic versioning rules. In this case, we are releasing the first stable version of the library, so the new version number is 1.0.0.\nversion=1.0.0 Commit and tag the new version:\ngit add library.properties git commit -m \u0026#34;Release version 1.0.0\u0026#34; git tag 1.0.0 git push origin main --tags Create a release on GitHub from the tag (optional but recommended).\nSubmit to the Arduino Library Manager # Now that you have a proper repository and a release, you can submit your library to the Arduino Library Manager. This is a one-time process that will make your library available to all Arduino users through the Library Manager. New versions of your library will be automatically published to the Library Manager when you release a new version.\nTo submit your library to the Arduino Library Manager:\nEnsure your library follows all Arduino Library Registry requirements.\nFork the Arduino Library Registry repository.\nAdd your library\u0026rsquo;s Git URL to the repositories.txt file:\nhttps://github.com/yourusername/HelloWorldLib Submit a pull request. An automated bot will verify your library meets the requirements.\nOnce approved and merged, your library will appear in the Arduino Library Manager within a day.\nFor detailed instructions, see the Arduino Library Registry documentation.\nFurther Improvements # As you become more comfortable with library development, you might explore:\nMultiple Source Files: Split large libraries into multiple source files (.h and .cpp) for better organization. Hardware Abstraction: Support multiple ESP32 variants with hardware abstraction layers. Unit Testing: Use frameworks like Unity and pytest-embedded for testing your library code. CI/CD: Set up GitHub Actions to automatically build and test your library on each commit. Conclusion # The HelloWorldLib we built covers all the essential components of a library: header files, implementation files, examples, metadata, and documentation. These same patterns apply to more complex libraries. The base structure remains the same regardless of complexity.\nOnce you\u0026rsquo;re comfortable with the basics, consider applying some of the suggestions above to improve your library\u0026rsquo;s quality and maintainability.\nAdditional Resources # Getting Started with ESP32 Arduino Arduino Core for ESP32 Arduino Library Specification Arduino Library Registry Arduino Library Registry FAQ Choose a License Semantic Versioning ","date":"15 December 2025","externalUrl":null,"permalink":"/blog/2025/12/arduino-library-creation/","section":"Blog","summary":"Learn how to create, structure, and publish Arduino libraries for ESP32. This step-by-step guide covers everything from understanding a library structure to submitting your library to the Arduino Library Manager.","title":"Creating an Arduino Library for ESP32","type":"blog"},{"content":"","date":"15 December 2025","externalUrl":null,"permalink":"/tags/library/","section":"Tags","summary":"","title":"Library","type":"tags"},{"content":"","date":"15 December 2025","externalUrl":null,"permalink":"/authors/lucas-vaz/","section":"Developer Portal Authors","summary":"","title":"Lucas Saavedra Vaz","type":"authors"},{"content":"","date":"9 December 2025","externalUrl":null,"permalink":"/tags/agents/","section":"Tags","summary":"","title":"Agents","type":"tags"},{"content":"","date":"9 December 2025","externalUrl":null,"permalink":"/authors/amey-inamdar/","section":"Developer Portal Authors","summary":"","title":"Amey Inamdar","type":"authors"},{"content":"","date":"9 December 2025","externalUrl":null,"permalink":"/authors/chirag-atal/","section":"Developer Portal Authors","summary":"","title":"Chirag Atal","type":"authors"},{"content":" We are proud to announce the \u0026ldquo;Private AI Agents Platform\u0026rdquo; – a self-hosted, multi-modal AI agent platform that you can deploy in your AWS account. This platform is optimized and tuned for building and managing AI Agents that can be integrated in connected devices and companion phone apps and web dashboards. In this blog post we provide an introduction to this platform.\nAI Agents and IoT # The first question we need to answer is what an AI agent is, and why it has become so relevant for IoT. An AI agent is the workflow implementation that combines large language models (LLMs) with a tool calling layer that allows to read and change device state, invoke APIs, access knowledge base and make decisions based on the context. For device makers, this unlocks a new class of capabilities such as intelligent assistants in companion apps, natural multi-lingual voice interfaces for device control, intelligent customer support that works with the combination of actual device state and authoritative product documentation, and ultimately, ambient intelligence driven by events from sensors, cloud rules and other services.\nHigh Level Architecture # Engineering such an agent implementation for IoT systems requires a careful consideration to modality (text, speech), scalability, security, cost and safety. Keeping all these considerations in mind, the Private AI Agents Platform is built on AWS cloud services using AWS Fargate as a primary application platform and Amazon Bedrock Foundation Models as backend LLM system. Espressif has made an instance of this available for a public trial. For the production cases, you can deploy the same in your own AWS account. Here is a high-level architecture of the system. Now let\u0026rsquo;s have a look at how we can create and use agents for various use-cases mentioned above.\nDefining the Agent # An Agent consists of an LLM selection, a system prompt—written in plain English—that defines its behavior, along with a set of tools that give it the ability to perform actions. The AI Agents admin dashboard, available at https://agents.espressif.com, allows you to create and configure agents using pre-built templates or by defining them entirely from scratch.\nLLM Selection # The Agent definition process allows developers to choose from a range of supported AWS Bedrock Foundation Models, giving full control over performance, cost, and behavior. Each interaction modality—voice and text—can be assigned its own LLM, enabling optimized configurations such as lightweight models for conversational voice interfaces and more capable models for complex text reasoning. This flexibility ensures that every agent can be tuned precisely to its use-case while maintaining consistent deployment and governance within the customer\u0026rsquo;s own cloud environment.\nSystem Prompt # Every agent—whether created from a template or built from scratch—includes a system prompt. The system prompt defines the agent\u0026rsquo;s behavior and establishes its persona, such as a voice controller, storyteller, or customer support assistant. When you name an agent, the dashboard can automatically generate an initial system prompt using the LLM, which you may keep, modify, or replace entirely. During interactions, the user\u0026rsquo;s query is combined with this system prompt, guiding the LLM to reason and respond in alignment with the agent\u0026rsquo;s intended role.\nTools # Tools are pluggable actions that an agent can invoke to perform specific tasks. The dashboard includes several pre-defined tools—such as ESP RainMaker control, Volume Control, and Emotion Detection—and allows you to create custom tools tailored to your application. The platform supports two categories of tools.\nRemote Tools # The Private AI Agents Platform supports the Model Context Protocol (MCP), enabling device makers to plug their agents into a much broader ecosystem of third-party MCP-compatible services and tools. With MCP servers, agents can seamlessly interact with external systems—such as querying a knowledge base, communicating to the device cloud, creating a customer ticket, or communicating with other services—without building custom integrations. This pluggability dramatically accelerates development and ensures agents can evolve as the ecosystem grows. The platform also supports OAuth authentication to the MCP servers, allowing securely logging in and getting the user context wherever required.\nLocal Tools # In addition to remote tools powered by MCP servers, the Private AI Agents Platform also supports Local Tools, which allow tool calls to be executed directly on the client—such as the IoT device itself or a companion mobile application. Local Tools enable agents to trigger real-time, device-level actions without requiring any backend integration. For example, if a smart device needs to respond to a voice command like \u0026ldquo;Turn off the bedroom fan\u0026rdquo;, the developers can simply expose a Local Tool such as toggleFan or setSpeed, and the agent will deliver the instruction directly to the device or app for immediate execution. This makes Local Tools ideal for tight device control loops, offline-capable interactions, and low-latency experiences, ensuring that agents can act as naturally and responsively as users expect.\nOnce an agent is defined, you can test it directly from the web dashboard to observe how it responds to queries and invokes tools in real time. The dashboard provides an interactive interface for trying out both text and voice modalities, making it easy to validate behavior, fine-tune prompts, and verify tool integrations before deploying the agent into your application.\nGetting Started on a Real Device: Step-by-Step # Once your agent is configured, you can run it on real hardware using any of the three supported development kits: ESP-VoCat, ESP32-S3-Box, and M5Stack Core S3. The agent client is fully compatible with all three platforms, enabling you to test voice interactions, tool execution, and end-to-end behavior exactly as users would experience it.\n1. Program the firmware # You can flash pre-compiled firmware to these boards directly from your web browser without requiring any toolchain installation. This makes it incredibly easy to get started and validate your agent in minutes. The full source code for the firmware will also be made available soon, allowing developers to explore, customize, and extend the client implementation as needed. For instructions on flashing and using the device please refer to: https://github.com/espressif/esp-agents-firmware.\nCurrently, 2 kinds of firmware are supported:\nGeneric Assistant/Friend Voice-assisted Matter Controller with Thread support 2. Provision the device using the ESP RainMaker Home app # Next, open the ESP RainMaker Home app to configure the device\u0026rsquo;s Wi-Fi credentials. The app guides you through the provisioning process, ensuring the device connects securely to your network and becomes ready to communicate with your agent.\n3. Configure a new Agent into the Device # This is an optional step, where you can change the default Agent running on the device. Once the device is online, use the same mobile app to link it to your agent. Each agent created in the dashboard has a unique Agent URL represented as a QR code. Simply scan this QR code with your phone\u0026rsquo;s camera, and the app will automatically write the correct Agent ID into the device. Note that, the device firmware has a default agent configured in it which makes it act as a \u0026ldquo;Friend\u0026rdquo; of the user.\n4. Interact with the device using voice # With provisioning and configuration complete, your device is now fully connected to the agent. Speak naturally to the device to issue commands, ask questions, or trigger actions. The agent will process your input, reason about it, and call the appropriate tools in real time.\nTrying out Phone App Chat Agent # A completely different application of the Private Agent Platform is to directly integrate AI Agent into your connected device\u0026rsquo;s companion app. The ESP RainMaker Home app also includes a built-in Chat Agent feature that demonstrates this. Any agent you create in the dashboard can be configured as the chat agent within the app, allowing you to test conversational interactions immediately with no additional development required.\nBecause the chat agent can invoke Local Tools, it can retrieve real-time device status directly from the user\u0026rsquo;s hardware, allowing support scenarios such as \u0026ldquo;Why is my purifier showing a red light?\u0026rdquo; or \u0026ldquo;Check if my fan is connected.\u0026rdquo; This combination of conversational understanding and live device context enables a much more effective and personalized support experience within the companion app.\nConclusion # In this article we introduced the Private AI Agents Platform and showed how it enabled developers to build and deploy AI agents within their own AWS environments. We outlined how agents were configured using LLMs, system prompts, and tools, and how they were tested across both device hardware and companion apps. Together, these components demonstrated how the platform supported secure and scalable AI-driven interactions for connected products.\n","date":"9 December 2025","externalUrl":null,"permalink":"/blog/2025/12/annoucing_esp_private_agents_platform/","section":"Blog","summary":"This article announces the Private AI Agent Platform","title":"Introducing Private AI Agents Platform","type":"blog"},{"content":"","date":"9 December 2025","externalUrl":null,"permalink":"/tags/llm/","section":"Tags","summary":"","title":"LLM","type":"tags"},{"content":"","date":"8 December 2025","externalUrl":null,"permalink":"/authors/anant-raj-gupta/","section":"Developer Portal Authors","summary":"","title":"Anant Raj Gupta","type":"authors"},{"content":"With the EU Radio Equipment Directive Delegated Act (RED‑DA) now in effect, all radio equipment placed on the EU market must meet the mandatory cybersecurity and update requirements defined in EN 18031.\nEspressif has integrated RED‑DA support into the ESP‑ZeroCode platform, enabling developers and product teams to generate Matter firmware and a RED‑DA‑oriented documentation package in one step. This integration reduces manual work, simplifies technical documentation, and accelerates time‑to‑market for EU‑bound Matter devices.\nAs with all RED‑DA workflows, the end‑product manufacturer remains responsible for the final Declaration of Conformity and for ensuring that the complete device (hardware + firmware + cloud/backend) meets the applicable EN 18031 requirements. What’s new: Integrated RED‑DA support in ESP‑ZeroCode # ESP‑ZeroCode now delivers a RED‑DA documentation starter package alongside the generated device firmware:\nPre‑filled compliance templates\nEspressif provides documentation aligned with EN 18031 and our RED‑DA guidance, including:\nPlatform‑level security features and defaults Network stack and secure update mechanisms Standard technical specifications for the ESP‑ZeroCode Matter platform Documentation structured for final use\nThe package is organized to match typical RED‑DA technical documentation expectations, so it can be:\nUsed directly for self‑assessment and Declaration of Conformity, or Used as input for Approved Testing Laboratories (ATLs) or Notified Bodies, when needed With this integration, developers no longer have to assemble the technical file from scratch. Platform‑level conformance is captured by Espressif’s pre‑filled content, while the manufacturer completes the remaining device‑specific sections as part of their normal product documentation flow.\nHow the integration works # Pre‑filled compliance templates # The templates provided via ESP‑ZeroCode are derived from Espressif’s RED‑DA documentation framework described in RED‑DA Compliance Part 2 and prepared in collaboration with Brightsight:\nBased on EN 18031 mappings for Article 3(3)(d)/(e)/(f), where applicable Include: Platform security configuration and defaults Secure communication and cryptography settings OTA / secure update capabilities These templates serve as a starting point for the final technical documentation package expected by Market Surveillance Authorities and Notified Bodies.\nProduct‑specific inputs by the manufacturer # The end‑product manufacturer augments the templates with device‑specific information to complete the technical file. Typical additions include:\nDetailed device description and intended use Target user group and installation environment Mechanical design and PCB schematics Power, radio, and enclosure details Application‑level behavior and any customizations that may affect security or privacy This ensures that the documentation accurately reflects the actual device, operational environment, and manufacturing setup, while still leveraging Espressif’s platform‑level content.\nDocumentation delivered with firmware # ESP‑ZeroCode exports both the production‑ready Matter firmware and the RED‑DA documentation starter package in one step:\nThe package includes Espressif’s pre‑filled sections for the ESP‑ZeroCode platform and the device type configured based on the connectivity as well as the SoC chosen Placeholders and headings make it clear where manufacturers should add their own product details Once completed, the package can be used for: RED‑DA self‑declaration (Declaration of Conformity issued by the manufacturer), or Submissions to an ATL or Notified Body, when a formal third‑party assessment is preferred or required Workflow: From device design to RED‑DA‑oriented package # Select or customize a device template in ESP‑ZeroCode.\nConfigure Matter device using the standard ESP‑ZeroCode workflow.\nCheck the EU RED-DA checkbox in the ESP-ZeroCode Benfits page.\nESP-ZeroCode Benefits\nComplete product‑specific sections in the provided templates as part of your internal documentation process.\nESP-ZeroCode RED-DA Product Details\nUse the completed package for RED‑DA self‑assessment or as input to an ATL/Notified Body, and proceed to Matter ecosystem certification if applicable.\nThis integrated workflow reduces manual documentation work and provides a clear, unified path toward EU compliance.\nBenefits for developers and product teams # Espressif’s integrated solution provides concrete advantages for any developer building Matter devices for the EU market:\nSingle‑step delivery of firmware + RED‑DA documentation starter package Reduced manual effort in preparing technical files Clear responsibility split Espressif: platform‑level documentation and security configuration Manufacturer: product‑specific details and final conformity decision Faster EU market entry with pre‑validated platform documentation Confidence in security and interoperability: templates incorporate Espressif’s EN 18031‑aligned safeguards at the platform level Simplified scaling across multiple device variants without repeating core platform compliance work Accessible for teams of any size, from solo developers to larger organizations This approach allows teams to focus on innovation and differentiation, while Espressif provides a strong regulatory foundation at the platform level.\nExample use case # A team building a Matter‑enabled smart light for the EU market can:\nUse ESP‑ZeroCode to configure the smart light profile and select an appropriate Matter device template. Generate the firmware + RED‑DA documentation starter package. Add product‑specific information such as manufacturer details, PCB schematics, operational environment, and model identifiers into the templates. Use this package for RED‑DA self‑declaration or as input to an ATL / Notified Body, depending on their chosen compliance pathway. The result: faster launch, reduced engineering effort, and RED‑DA‑oriented Matter devices with minimal manual documentation work.\nConclusion # By integrating RED‑DA support into ESP‑ZeroCode, Espressif provides a streamlined, end‑to‑end path for Matter device development targeting the EU market. Developers and product teams can now generate firmware and RED‑DA‑aligned documentation together.\nThis unified approach reduces engineering effort, minimizes compliance risk, and accelerates time‑to‑market for secure, interoperable, and EU‑ready Matter devices.\nFurther reading # Explore ESP‑ZeroCode:\nhttps://zerocode.espressif.com\nRead Espressif’s RED‑DA guides:\nPart 1 – RED‑DA (EN 18031) Certification Compliance: What You Need to Know\nhttps://developer.espressif.com/blog/2025/04/esp32-red-da-en18031-compliance-guide/ Part 2 – RED‑DA Compliance (Part 2): Espressif’s Platform Support, Templates, and Pathways for Conformity\nhttps://developer.espressif.com/blog/2025/07/esp32-red-da-en18031-compliance-guide-part2/ ","date":"8 December 2025","externalUrl":null,"permalink":"/blog/2025/12/red_da_matter_esp_zerocode/","section":"Blog","summary":"In this blog we will introduce how combining the Espressif RED-DA compliance framework along with the ESP ZeroCode platform can help accelerate your product development","title":"RED-DA Compliant Matter devices with ESP-ZeroCode","type":"blog"},{"content":"","date":"8 December 2025","externalUrl":null,"permalink":"/tags/redda/","section":"Tags","summary":"","title":"REDDA","type":"tags"},{"content":"","date":"8 December 2025","externalUrl":null,"permalink":"/tags/zerocode/","section":"Tags","summary":"","title":"ZeroCode","type":"tags"},{"content":"","date":"5 December 2025","externalUrl":null,"permalink":"/tags/build-system/","section":"Tags","summary":"","title":"Build System","type":"tags"},{"content":"","date":"5 December 2025","externalUrl":null,"permalink":"/tags/cmake/","section":"Tags","summary":"","title":"CMake","type":"tags"},{"content":"","date":"5 December 2025","externalUrl":null,"permalink":"/tags/configuration/","section":"Tags","summary":"","title":"Configuration","type":"tags"},{"content":"As ESP-IDF projects grow more sophisticated, developers often need multiple build configurations: development builds with debug symbols, optimized production releases, size-constrained builds for specific hardware, and comprehensive testing setups. While ESP-IDF has always supported these scenarios, they typically required remembering complex command-line arguments and managing multiple build directories manually.\nESP-IDF v6.0 introduces a powerful solution: reusable configuration profiles, called presets, that handle all this complexity for you. These configuration presets make switching between development, production, and testing environments effortless. This is how the command changes:\nOld: idf.py -B build_prod -D SDKCONFIG_DEFAULTS=\u0026quot;prod.cfg\u0026quot; build New: idf.py --preset production build Traditional build management # Let\u0026rsquo;s first examine the current approach to managing multiple build configurations. Consider a project that needs:\nDevelopment builds: Fast iteration with debug symbols Production builds: Optimized binaries for various hardware variants Testing builds: Special configurations for automated testing Traditionally, you might handle this with complex command lines like:\n# Development build idf.py build # Production variant 1 idf.py -B build_prod1 -D SDKCONFIG_DEFAULTS=\u0026#34;sdkconfig.prod_common;sdkconfig.prod1\u0026#34; build # Production variant 2 idf.py -B build_prod2 -D SDKCONFIG_DEFAULTS=\u0026#34;sdkconfig.prod_common;sdkconfig.prod2\u0026#34; build # Testing with custom settings idf.py -B build_test -D SDKCONFIG_DEFAULTS=\u0026#34;sdkconfig.test\u0026#34; -D SDKCONFIG=\u0026#34;build_test/sdkconfig\u0026#34; build How configuration presets work # ESP-IDF v6.0 introduces support for build configuration presets, allowing you to define reusable build settings in JSON files. This feature is built on CMake Presets, a standard CMake feature that ESP-IDF now supports. Each preset can specify:\nBuild directory location (binaryDir) CMake cache variables (including SDKCONFIG, SDKCONFIG_DEFAULTS, and optionally IDF_TARGET) Generator preferences (Ninja, Make, etc.) Human-readable metadata (display names and descriptions) The key benefit is declarative configuration: instead of remembering complex command-line arguments, you define your configurations once in a file and reference them by name.\nESP-IDF will automatically detect and use configuration presets when either CMakePresets.json or CMakeUserPresets.json is present in your project root directory. Example of how preset configuration file looks like can be found later in section Getting started with configuration presets.\nWorking with build directories # One of the biggest advantages of this feature is clean build directory management. Each preset can specify its own build directory, allowing you to maintain multiple configurations simultaneously:\nproject/ ├── CMakePresets.json ├── build/ │ ├── default/ # Development builds │ ├── release/ # Release builds │ ├── size-opt/ # Size-optimized builds │ └── testing/ # Test builds ├── sdkconfig.defaults.common ├── sdkconfig.defaults.release └── sdkconfig.defaults.size-opt This structure provides several benefits:\nParallel builds: Switch between configurations without rebuilding Clean separation: No cross-contamination between build types Easy cleanup: Remove specific build types without affecting others Flexible configuration: Presets can specify different optimization levels, debug settings, and target chips for various build scenarios Custom sdkconfig locations # By default, ESP-IDF places the sdkconfig file in your project root. With presets, you can keep configuration files organized by placing them in build directories:\n{ \u0026#34;name\u0026#34;: \u0026#34;isolated-config\u0026#34;, \u0026#34;binaryDir\u0026#34;: \u0026#34;build/isolated\u0026#34;, \u0026#34;cacheVariables\u0026#34;: { \u0026#34;SDKCONFIG\u0026#34;: \u0026#34;./build/isolated/sdkconfig\u0026#34; } } This approach provides the following advantages:\nKeeps your project root clean Prevents accidental commits of development configurations Makes it clear which sdkconfig belongs to which build Enables easier automated testing of different configurations Setting default selection with environment variable # For team workflows, you can set default preset using the environment variable IDF_PRESET, for your shell session.\nUnix:\nexport IDF_PRESET=release # bash Windows:\n$ENV:IDF_PRESET=release # PowerShell # Now these commands use the \u0026#39;release\u0026#39; preset automatically idf.py build idf.py flash monitor This is particularly useful in CI/CD pipelines:\n# GitHub Actions example - name: Build production firmware env: IDF_PRESET: release run: | idf.py build idf.py size Selection logic # ESP-IDF follows a clear precedence order for preset selection:\nCommand-line argument: idf.py --preset my-preset build Environment variable: set environmental variable IDF_PRESET. Automatic selection: If a preset named default exists, use it Otherwise, use the first preset in the preset configuration file This makes preset usage flexible while providing sensible defaults.\nGetting started with configuration presets # Step 1: Create your JSON file # Create a CMakePresets.json file in your project root directory. Here\u0026rsquo;s a comprehensive example that demonstrates multiple production variants:\n{ \u0026#34;version\u0026#34;: 3, \u0026#34;configurePresets\u0026#34;: [ { \u0026#34;name\u0026#34;: \u0026#34;default\u0026#34;, \u0026#34;binaryDir\u0026#34;: \u0026#34;build/default\u0026#34;, \u0026#34;displayName\u0026#34;: \u0026#34;Development Configuration\u0026#34;, \u0026#34;description\u0026#34;: \u0026#34;Fast builds for development and debugging\u0026#34;, \u0026#34;cacheVariables\u0026#34;: { \u0026#34;IDF_TARGET\u0026#34;: \u0026#34;esp32s3\u0026#34;, \u0026#34;SDKCONFIG\u0026#34;: \u0026#34;./build/default/sdkconfig\u0026#34; } }, { \u0026#34;name\u0026#34;: \u0026#34;release\u0026#34;, \u0026#34;binaryDir\u0026#34;: \u0026#34;build/release\u0026#34;, \u0026#34;displayName\u0026#34;: \u0026#34;Release Build\u0026#34;, \u0026#34;cacheVariables\u0026#34;: { \u0026#34;SDKCONFIG_DEFAULTS\u0026#34;: \u0026#34;sdkconfig.defaults.common;sdkconfig.defaults.release\u0026#34;, \u0026#34;SDKCONFIG\u0026#34;: \u0026#34;./build/release/sdkconfig\u0026#34; } }, { \u0026#34;name\u0026#34;: \u0026#34;size-opt\u0026#34;, \u0026#34;binaryDir\u0026#34;: \u0026#34;build/size-opt\u0026#34;, \u0026#34;displayName\u0026#34;: \u0026#34;Size Optimized Build\u0026#34;, \u0026#34;cacheVariables\u0026#34;: { \u0026#34;SDKCONFIG_DEFAULTS\u0026#34;: \u0026#34;sdkconfig.defaults.common;sdkconfig.defaults.size-opt\u0026#34;, \u0026#34;SDKCONFIG\u0026#34;: \u0026#34;./build/size-opt/sdkconfig\u0026#34; } }, { \u0026#34;name\u0026#34;: \u0026#34;testing\u0026#34;, \u0026#34;binaryDir\u0026#34;: \u0026#34;build/testing\u0026#34;, \u0026#34;displayName\u0026#34;: \u0026#34;Testing Configuration\u0026#34;, \u0026#34;cacheVariables\u0026#34;: { \u0026#34;SDKCONFIG_DEFAULTS\u0026#34;: \u0026#34;sdkconfig.defaults.testing\u0026#34;, \u0026#34;SDKCONFIG\u0026#34;: \u0026#34;./build/testing/sdkconfig\u0026#34; } } ] } Note: The version field is set to 3 to match the CMake Presets schema supported by ESP-IDF\u0026rsquo;s minimum required CMake version (3.22.1). If you\u0026rsquo;re using a newer CMake version, you can use a higher version number for additional features.\nStep 2: Create your configuration files # Alongside your JSON file, create the corresponding configuration files:\nsdkconfig.defaults.common:\n# Common settings for all build variants CONFIG_ESP_DEFAULT_CPU_FREQ_MHZ_160=y CONFIG_ESP_MAIN_TASK_STACK_SIZE=3584 CONFIG_FREERTOS_HZ=100 sdkconfig.defaults.release:\n# Release build optimizations CONFIG_COMPILER_OPTIMIZATION_SIZE=y CONFIG_LOG_DEFAULT_LEVEL_WARN=y sdkconfig.defaults.size-opt:\n# Aggressive size optimizations CONFIG_COMPILER_OPTIMIZATION_SIZE=y CONFIG_BOOTLOADER_LOG_LEVEL_NONE=y Notice how different presets use different combinations of configuration files through SDKCONFIG_DEFAULTS. The common settings are shared via sdkconfig.defaults.common, while build-specific optimizations are applied through additional files like sdkconfig.defaults.release or sdkconfig.defaults.size-opt. Additionally, the default preset shows how to set the IDF_TARGET variable to specify the target chip, which is optional but helps maintain a consistent development target.\nsdkconfig.defaults.testing:\n# Testing and debugging settings CONFIG_LOG_DEFAULT_LEVEL_DEBUG=y CONFIG_ESP_SYSTEM_PANIC_PRINT_HALT=y CONFIG_FREERTOS_CHECK_STACKOVERFLOW_CANARY=y Step 3: Use your presets # Now you can build, flash, and monitor with clean, simple commands:\n# Development build (automatically selects \u0026#39;default\u0026#39; preset) idf.py build # Production builds with different optimizations idf.py --preset release build idf.py --preset size-opt build # Flash and monitor with specific preset idf.py --preset release -p /dev/ttyUSB0 flash monitor # Testing build idf.py --preset testing build Current limitations # There is one current limitation to be aware of: the inherits field for preset inheritance isn\u0026rsquo;t currently supported. If you try to use it, ESP-IDF will show a warning and the inheritance will be ignored.\nMigrating from manual build configurations # If you\u0026rsquo;re currently using complex build scripts or manual command-line arguments, here\u0026rsquo;s how to migrate:\nStep 1: Audit your current configurations # List all the different ways you currently build your project:\n# Current manual commands idf.py build # Development idf.py -B build_prod -D SDKCONFIG_DEFAULTS=\u0026#34;sdkconfig.defaults.production\u0026#34; # Production idf.py -B build_test -D SPECIAL_FLAG=1 # Testing Step 2: Extract common patterns # Identify shared settings and create defaults files:\nsdkconfig.defaults (development - already exists) sdkconfig.defaults.production sdkconfig.defaults.testing Step 3: Create equivalent presets # Convert each command pattern to an equivalent entry:\n{ \u0026#34;version\u0026#34;: 3, \u0026#34;configurePresets\u0026#34;: [ { \u0026#34;name\u0026#34;: \u0026#34;default\u0026#34;, \u0026#34;binaryDir\u0026#34;: \u0026#34;build\u0026#34;, \u0026#34;displayName\u0026#34;: \u0026#34;Development\u0026#34; }, { \u0026#34;name\u0026#34;: \u0026#34;production\u0026#34;, \u0026#34;binaryDir\u0026#34;: \u0026#34;build_prod\u0026#34;, \u0026#34;cacheVariables\u0026#34;: { \u0026#34;SDKCONFIG_DEFAULTS\u0026#34;: \u0026#34;sdkconfig.defaults.production\u0026#34; } }, { \u0026#34;name\u0026#34;: \u0026#34;testing\u0026#34;, \u0026#34;binaryDir\u0026#34;: \u0026#34;build_test\u0026#34;, \u0026#34;cacheVariables\u0026#34;: { \u0026#34;SDKCONFIG_DEFAULTS\u0026#34;: \u0026#34;sdkconfig.defaults.testing\u0026#34;, \u0026#34;SPECIAL_FLAG\u0026#34;: \u0026#34;1\u0026#34; } } ] } Step 4: Update documentation and scripts # Replace build instructions:\nOld: \u0026ldquo;Run idf.py -B build_prod -D SDKCONFIG_DEFAULTS=\u0026quot;sdkconfig.defaults.production\u0026quot; build\u0026rdquo; New: \u0026ldquo;Run idf.py --preset production build\u0026rdquo; Conclusion # Configuration presets transform ESP-IDF build management from a manual, error-prone process into a declarative, maintainable system. By defining your build configurations once in CMakePresets.json, you can:\nEliminate command-line complexity with simple preset names Maintain multiple configurations without cross-contamination Standardize team workflows with shared preset definitions Integrate seamlessly with IDEs and CI/CD pipelines Scale as your project grows more complex Whether you\u0026rsquo;re managing a simple project with development and production builds, or a complex system with different optimization levels and testing configurations, this approach provides the structure and simplicity you need to focus on building great products instead of wrestling with build systems.\nWhat\u0026rsquo;s next? # Explore the ESP-IDF multi-config example for hands-on practice Check out the CMake Presets documentation for advanced features Consider contributing preset examples for common ESP-IDF use cases Start small with a simple development/production split, then expand your build configurations as your workflow matures. Your future self (and your teammates) will thank you for the clarity and consistency that configuration presets brings to your ESP-IDF projects.\n","date":"5 December 2025","externalUrl":null,"permalink":"/blog/2025/12/cmake_presets/","section":"Blog","summary":"Tired of juggling complex command-line arguments with endless \u003ccode\u003eidf.py\u003c/code\u003e flags? ESP-IDF v6.0 introduces a new feature, letting you switch between multiple build configuration. Learn how to structure your project, isolate sdkconfig files, and migrate from ad-hoc commands to clean, declarative builds.","title":"Manage multiple ESP-IDF build configurations with ease","type":"blog"},{"content":"","date":"5 December 2025","externalUrl":null,"permalink":"/authors/marek-fiala/","section":"Developer Portal Authors","summary":"","title":"Marek Fiala","type":"authors"},{"content":" Introducing the ESP RainMaker Phone App Development Kit # Espressif is excited to announce the ESP RainMaker Phone App Development Kit, a complete toolkit that makes it faster and easier than ever to deliver production-ready mobile apps based on ESP RainMaker backend solutions.\nThis new development kit combines our cross-platform SDK, Central Data Framework (CDF), and a reference home app into one cohesive package. Developers can begin with a production-ready reference app and easily update branding and UI elements to align with their product line. When needed, the architecture also allows expanding or modifying control interfaces, workflows, and user journeys without reworking the core logic.\nBy building on the proven ESP RainMaker backend, the kit ensures developers don’t need to reinvent device provisioning, secure communication, or state management. Instead, they can focus on creating polished, branded experiences for their customers—while relying on Espressif’s robust cloud and device management infrastructure.\nPurpose # Espressif has always provided ready-to-use ESP RainMaker Phone Apps, available on both iOS and Android app stores. To give developers full flexibility, the source code for these apps has always been open-sourced on GitHub, allowing customisations to match specific requirements.\nHowever, in practice, the process of integrating and maintaining these custom apps has proven cumbersome:\nSeparate native codebases for iOS and Android had to be maintained. No unified Phone App SDK existed, making feature development inconsistent. UI and business logic were tightly coupled, reducing flexibility. Any new feature or stability update from Espressif required customers to rebase their custom forks, a process many found time-consuming and error-prone. As a result, many customers avoided upgrading unless absolutely necessary, which led to fragmented user experiences across different RainMaker-powered apps.\nThe ESP RainMaker Phone App Development Kit is created to solve these challenges. By providing a cross-platform SDK, a Central Data Framework, and a reference app, it allows developers to:\nEnsure consistency across apps with a shared SDK and predictable APIs. Simplify maintenance and upgrades, since future Espressif improvements flow seamlessly into customer apps. Guarantee quality and security, with a unified baseline maintained by Espressif. Together, these benefits help customers accelerate time-to-market with pre-built, production-ready components.\nCore Components # This kit brings together three key elements:\nThe Phone App Development Kit is built around three connected layers, designed to simplify development while ensuring long-term maintainability:\n1. RainMaker Base SDK # A cross-platform, TypeScript-based SDK that exposes RainMaker\u0026rsquo;s core APIs in a clean, consistent way. It absorbs the complexity of networking, security, and platform differences so Espressif can roll out backend or protocol updates once, and all apps benefit instantly. Instead of reinventing onboarding, provisioning, or cloud flows for each platform, developers get a unified, type-safe API that they can drop into iOS, Android, or even web apps. This reduces boilerplate and accelerates app delivery.\nFor more details, see the RainMaker Base SDK Documentation.\n2. RainMaker Base CDF (Central Data Framework) # A reusable framework that sits between the SDK and the UI. It intercepts API calls, manages device/user/group state, and provides a reactive data store, ensuring smooth, scalable performance even as devices or features grow. Developers no longer need to manually manage state synchronization or performance optimizations. The CDF handles the heavy lifting, making apps more responsive and reliable with less code.\nFor more details, see the RainMaker CDF Documentation.\n3. RainMaker Home App (Reference Application) # A production-ready showcase demonstrating how the SDK and CDF work together in a real-world app. It acts as both a validation tool for Espressif\u0026rsquo;s architecture and a starter template for customers. Instead of starting from a blank screen, developers can use the Home App as a blueprint, customizing branding, UI, or features while inheriting proven patterns. This dramatically shortens time to market and lowers development risk.\nFor more details, see the RainMaker Home App Documentation.\nTechnology \u0026amp; Architecture # TypeScript at the Core # TypeScript is widely adopted across the industry, allowing teams to onboard quickly while maintaining consistency and predictability across features and releases.\nFlow Diagram\nOverall Architecture at a Glance # Business logic layer – RainMaker Base SDK services, leveraging TypeScript\u0026rsquo;s static typing to safely interface with the RainMaker backend.\nNative modules – Platform-specific integrations (Bluetooth, Wi-Fi) exposed to the React Native layer through adapter modules.\nCloud backend – ESP RainMaker cloud services handling device management, provisioning and secure communication.\nOur Reference App, Powered by React Native # The reference app is built with React Native, a framework embraced by the open-source community for delivering high-quality mobile apps. With a single codebase producing native experiences for both iOS and Android, React Native reduces engineering overhead while accelerating feature delivery.\nA vibrant plugin ecosystem and strong community support make it easy to extend functionality, while lightweight native adapters give seamless access to platform-specific capabilities like Bluetooth and Wi-Fi provisioning.\nThis combination, TypeScript at the core and React Native at the app layer, ensures that Espressif can innovate quickly while giving customers a development experience that is modern, efficient, and production-ready.\nFeatures at a Glance # The ESP RainMaker Phone App Development Kit ships with a rich set of production-ready features, so developers can spend less time reinventing the basics and more time creating differentiated user experiences.\nSecure by design – Built-in user authentication and account management.\nEffortless onboarding – Wi-Fi provisioning and device setup in just a few taps.\nAlways in sync – Real-time device status, control, and seamless OTA firmware updates.\nSmart living features – Configurable scenes, schedules, and automations to match user lifestyles.\nStay connected – Push notifications to keep users informed and engaged.\nEasy Customisation for Your Brand # We know every product needs its own identity. This kit makes customisation simple without adding engineering overhead.\nBrand alignment – Update colors, fonts, and logos to reflect your product line.\nFlexible extension – Add custom screens, features, or device types without disrupting the core flow.\nAccelerated delivery – Reuse proven, production-grade logic while focusing only on what makes your product unique.\nLocalisation support – Adapt language and region-specific behaviour to align with market requirements, without restructuring app flows.\nCustomer-ID based device discovery – Enable Bluetooth advertising and device discovery workflows using customer identifiers, allowing apps to detect and provision only the devices intended for their ecosystem.\nOther enhancements – Support for custom deployment configurations, and app-level theming ensures the solution can scale to different product variations and ecosystem requirements.\nCustom Deployment Configurations # For teams building across multiple models, markets, or release cycles, the Phone App Development Kit provides deeper configuration controls that help manage how the app evolves and interacts with the broader product ecosystem.\nEnvironment-aware builds – Switch between development, staging, and production environments through centralized configuration, ensuring clean environment management without duplicating codebases.\nUI layouts and custom workflows – Define feature-specific UI layouts, user journeys, and interaction flows directly within the configuration model, enabling teams to adapt the app experience for different markets, device categories, or product-tier requirements.\nProvisioning flow customisation – Tailor onboarding sequences, fallback logic, and device pairing behaviour to suit different product lines or deployment strategies.\nFeature development guides – Access structured, feature-focused development guides that document patterns, API usage, UI recommendations, and integration rules, helping teams implement product-specific capabilities in a consistent and scalable way.\nScale across product families – Manage multiple device variants and configurations through structured config files, enabling ecosystem growth without architectural rewrites.\nFor comprehensive guidance on building your own app, see the Phone App Development Documentation.\nRoadmap \u0026amp; What’s Next # The kit is designed as a living platform—today it covers the essentials, tomorrow it evolves with the smart home ecosystem. Coming soon:\nRicher experiences – Time-series data visualization and integrations with Alexa and Google Assistant.\nMatter-ready – Native support for Matter devices, ensuring your app works seamlessly with the latest IoT standards.\nDeveloper-first tooling – CLI-based configuration for theming, setup, and faster onboarding.\nSmarter notifications – Customizable delivery channels, priority settings, and styles for maximum flexibility.\nReference Links\nESP RainMaker Typescript Base SDK :- https://www.npmjs.com/package/@espressif/rainmaker-base-sdk ESP RainMaker Typescript Base CDF :- https://www.npmjs.com/package/@espressif/rainmaker-base-cdf ","date":"2 December 2025","externalUrl":null,"permalink":"/blog/2025/12/esp-rainmaker-phone-app-dev-kit/","section":"Blog","summary":"Espressif announces the ESP RainMaker Phone App Development Kit, a comprehensive cross-platform toolkit combining a TypeScript SDK, Central Data Framework (CDF), and React Native reference app. This production-ready kit enables developers to rapidly build branded mobile applications with customisable UI and workflows, whilst leveraging Espressif\u0026rsquo;s robust RainMaker cloud infrastructure for device management and secure communication.","title":"Introducing the ESP RainMaker Phone App Development Kit","type":"blog"},{"content":"","date":"2 December 2025","externalUrl":null,"permalink":"/authors/ninad-kheratkar/","section":"Developer Portal Authors","summary":"","title":"Ninad-Kheratkar","type":"authors"},{"content":"","date":"2 December 2025","externalUrl":null,"permalink":"/tags/phone-app/","section":"Tags","summary":"","title":"Phone App","type":"tags"},{"content":"","date":"2 December 2025","externalUrl":null,"permalink":"/tags/sdk/","section":"Tags","summary":"","title":"SDK","type":"tags"},{"content":"","date":"2 December 2025","externalUrl":null,"permalink":"/tags/typescript/","section":"Tags","summary":"","title":"TypeScript","type":"tags"},{"content":"","date":"28 November 2025","externalUrl":null,"permalink":"/tags/esp32-c2/","section":"Tags","summary":"","title":"ESP32-C2","type":"tags"},{"content":"","date":"28 November 2025","externalUrl":null,"permalink":"/authors/he-xin-lin/","section":"Developer Portal Authors","summary":"","title":"He-Xin-Lin","type":"authors"},{"content":"","date":"28 November 2025","externalUrl":null,"permalink":"/tags/memory-management/","section":"Tags","summary":"","title":"Memory Management","type":"tags"},{"content":" Overview # This article is largely based on the ESP Memory Usage Optimization document. If differences appear in the future due to updates, please consider the document as the most accurate source. The ESP32-C2 chip provides 256 KB of available physical RAM, making it an excellent cost-effective solution for IoT applications. However, when testing with default ESP-IDF configuration, running the BLE + Wi-Fi coexistence example leaves only 24 KB of free memory—which is insufficient for developing complex applications.\nThe root cause of this issue is that ESP32-C2\u0026rsquo;s default configuration prioritizes performance, compiling many core components into IRAM to improve execution speed. For cost-sensitive applications that primarily require simple control operations, the memory usage can be significantly optimized. With deep optimization, it\u0026rsquo;s possible to free up more than 100 KB of additional memory.\nThis article documents RAM optimization for ESP32-C2 based on ESP-IDF v5.5, explaining the impact of each optimization and how to enable them.\nSome optimization methods listed in this article may reduce system performance and stability. After implementing RAM optimizations, thorough performance and stability testing should be conducted to ensure the application meets all requirements. ESP32-C2 Memory Map Overview # ESP32-C2 features 256 KB of on-chip RAM, which is separate from the ROM used for boot and system code—ROM is not counted within these 256 KB. The memory map for ESP32-C2 closely resembles those of other ESP chips: RAM is allocated for data, stack, heap, and code execution, while certain regions are reserved by the system and peripherals.\nEven though not specifically about ESP32-C2, the article ESP32 Memory Map 101 provides a useful primer on how memory is typically organized on ESP chips. The overall memory region concepts (dedicated areas for instruction and data, reserved and shared buffers, etc.) are similar across the ESP family, even if exact sizes or addresses differ.\nChecking Current Free Memory # Before optimizing memory, it\u0026rsquo;s essential to understand the current memory usage. To analyze memory consumption for static memory, you can compile your application and then use the commands idf.py size and idf.py size-components.\nFor runtime memory usage, the functions esp_get_free_heap_size() and esp_get_minimum_free_heap_size() can retrieve the current free heap memory and the minimum free heap size since system startup, respectively. For more details, refer to the ESP-IDF Heap Memory Documentation.\nESP32-C2 Memory Test Results # The following data shows the amount of free memory on the ESP32-C2 using ESP-IDF tag v5.5-beta1, tested with default configuration (after idf.py set-target esp32c2) versus various optimization configurations.\nTest Scenario Descriptions # Wi-Fi station: Following the Wi-Fi station example. Print free memory after the device successfully obtains an IP address (GOT_IP event). WiFi station + 1TLS(MQTTS): Using the mqtt/ssl example and print free memory after the MQTT_EVENT_DATA event is triggered. bleprph_wifi_coex: Following the BLE + Wi-Fi coexistence example, after the WiFi GOT_IP event is triggered, initialize nimble and enable BLE advertising, then print free memory. bleprph_wifi_coex + mbedtls + power_save: Based on bleprph_wifi_coex, integrate https_mbedtls and power_save functionality, then print free memory after connecting to the HTTPS server. For the demo implementation and optimization configuration files, refer to this repository. Default Configuration Memory Usage Comparison # Test Senario Default Config (KB free) Optimized Config (KB free) WiFi station 95 169 WiFi station + 1TLS(MQTTS) 55 152 bleprph_wifi_coex 24 125 bleprph_wifi_coex + mbedtls + power_save Insufficient 115 This data focuses on ESP32-C2 memory optimization processes and results. For more comprehensive memory usage statistics across different chips and scenarios, refer to the ESP Memory Usage Optimization documentation. Optimization Strategies # The optimization strategies in this article are based on a custom test case combining bleprph_wifi_coex + mbedtls + power_save, which includes common scenarios: Wi-Fi + BLE + HTTPS + power save auto-sleep. For the demo implementation and optimization configuration files, refer to this repository. Without any optimizations, this scenario triggers a reset due to insufficient runtime memory.\nOptimization Approach Comparison # Optimization Approach v5.4.1 (bytes) v5.5 (bytes) Description No optimization Insufficient Insufficient Default configuration after idf.py set-target esp32c2 Basic optimization 62,840 60,212 Follows the ESP Memory Usage Optimization guide (see below) Advanced optimization 91,976 90,576 On top of basic optimization Deep optimization 118,096 On top of advanced optimization, suitable for v5.5.x and newer No optimization # Default configuration after idf.py set-target esp32c2, ensuring only basic functionality (e.g., enabling Bluetooth, PM), with no memory-specific optimizations. See the default configuration file.\nBasic Optimization # Follows ESP Memory Usage Optimization guide, involving IRAM heap memory optimization.\nKey optimization items include:\nMoving FreeRTOS functions from IRAM to flash Moving Wi-Fi functions from IRAM to flash Reducing Wi-Fi static buffers Optimizing lwIP memory usage Optimizing mbedTLS configuration Through these optimization configurations (see sdkconfig.defaults.opt.1), available memory can be increased to 62 KB after all functions are executed.\nAdvanced Optimization # Based on basic optimization, further deep optimization. This represents the \u0026ldquo;final optimization\u0026rdquo; result for v5.4.x and earlier versions.\nAdvanced optimization mainly includes:\nEnable CONFIG_BT_CTRL_RUN_IN_FLASH_ONLY\nAfter enabling CONFIG_SPI_FLASH_AUTO_SUSPEND, enabling CONFIG_BT_CTRL_RUN_IN_FLASH_ONLY places all Bluetooth controller code in flash, freeing approximately 20 KB of memory.\nEnable Compiler Optimization Options\nCONFIG_COMPILER_OPTIMIZATION_SIZE CONFIG_COMPILER_SAVE_RESTORE_LIBCALLS\nThese compiler optimizations can free approximately 8 KB of additional memory. For the complete advanced optimization configuration file, refer to sdkconfig.defaults.opt.2. With all the above configurations enabled (basic + advanced optimization), available memory increases to 90 KB.\nDeep Optimization # Continues optimization beyond advanced optimization, but only effective on ESP-IDF v5.5 and later.\nThis optimization leverages new features (such as flash suspend) in ESP-IDF v5.5 to place more code in flash, thereby freeing IRAM and minimizing memory usage, especially when CONFIG_SPI_FLASH_AUTO_SUSPEND is enabled. For a detailed list of all such configurations, refer to sdkconfig.flash_auto_suspend_iram_reduction.\nFor the complete deep optimization configuration file, refer to sdkconfig.defaults.opt.3.\nWith all these configurations enabled on ESP-IDF v5.5 can save an additional 20 KB of memory compared to v5.4.2.\nWith v5.5, available memory after connecting to an HTTPS server can reach 118 KB, with IRAM .text section occupying only 10,050 bytes.\nIn contrast, with v5.4.2 using the same configuration, available memory after connecting to an HTTPS server is 95 KB, with IRAM .text section occupying 31,206 bytes.\nIRAM Text Section Comparison # IRAM .text section memory consumption data obtained using the idf.py size command:\nOptimization Approach v5.4.1 (bytes) v5.5 (bytes) No optimization 93,592 100,616 Basic optimization 56,384 60,088 Advanced optimization 36,130 35,912 v5.5 deep optimization N/A 9,742 The significant reduction in IRAM usage (from ~36 KB to ~10 KB) demonstrates the effectiveness of v5.5\u0026rsquo;s deep optimization features.\n","date":"28 November 2025","externalUrl":null,"permalink":"/blog/2025/11/esp32c2-ram-optimization/","section":"Blog","summary":"ESP32-C2 has 256 KB of physical RAM, but with default configurations, only 24 KB remains free in typical Wi-Fi + BLE scenarios. This article explores comprehensive memory optimization strategies that can free up over 100 KB of RAM, making complex applications viable on this cost-effective chip.","title":"Optimizing RAM Usage on ESP32-C2","type":"blog"},{"content":"","date":"28 November 2025","externalUrl":null,"permalink":"/authors/zheng-zhong/","section":"Developer Portal Authors","summary":"","title":"Zheng Zhong","type":"authors"},{"content":" Introduction # In the previous article, \u0026ldquo;Porting a library to an ESP-IDF component\u0026rdquo;, we covered the basics of converting an external library into a reusable ESP-IDF component using the simple tinyexpr library as an example. We learned how to create a component structure, handle basic compatibility issues, and suppress compiler warnings at the component level.\nHowever, when porting larger, more complex libraries—especially those originally designed for Linux or other POSIX-compliant systems—you\u0026rsquo;ll encounter additional challenges that require more advanced techniques. This article builds on the fundamentals from the previous article and explores advanced porting strategies used in real-world library ports such as:\nasio - Asynchronous I/O library mosquitto - MQTT broker and client library libssh - SSH library libwebsockets - WebSockets library When porting a library, it\u0026rsquo;s helpful to follow a structured approach:\nAssess what to reuse and what to change - Identify which parts of the original library can be used as-is and which need adaptation Compose the build system - Create or adapt the CMakeLists.txt to reference the original library sources while integrating port-specific functionality Create the port folder - Set up a dedicated port/ directory structure for adapted functionality that bridges the library and ESP-IDF Adjust functionality - Use advanced techniques like header injection, linker wrapping, and the sock_utils component to adapt the port layer Fine-tune - Manage compiler warnings at the file level and make final adjustments for optimal integration Now, we will go through these techniques in detail and look at practical examples from real-world ports to help you successfully port complex libraries to ESP-IDF.\nStep 1: Assess what to reuse and what to change # Before writing any port code, decide what can remain unmodified and what needs adaptation for ESP-IDF. Often, you can keep most of the upstream sources intact and adapt behavior via configuration and thin port layers.\nCompile Definitions and Configuration # Libraries often use compile-time definitions to enable or disable features, configure behavior, or adapt to different platforms.\nFeature Flags and config.h # Many libraries use a config.h file generated by autotools or CMake that contains feature detection results. When porting, you\u0026rsquo;ll need to:\nIdentify which defines are needed Convert them to target_compile_definitions() Make them conditional based on ESP-IDF configuration when appropriate The asio port demonstrates this pattern:\ntarget_compile_definitions(${COMPONENT_LIB} PUBLIC SA_RESTART=0x01 SA_NOCLDSTOP=0x2 SA_NOCLDWAIT=0x4 ASIO_DISABLE_SERIAL_PORT ASIO_SEPARATE_COMPILATION ASIO_STANDALONE ASIO_HAS_PTHREADS OPENSSL_NO_ENGINE ASIO_DETAIL_IMPL_POSIX_EVENT_IPP) Some definitions, which are useful for our component to be configurable by Kconfg system could be defined in CMake as conditionals:\nif(NOT CONFIG_COMPILER_CXX_EXCEPTIONS) target_compile_definitions(${COMPONENT_LIB} PUBLIC ASIO_NO_EXCEPTIONS) endif() if(NOT CONFIG_COMPILER_RTTI) target_compile_definitions(${COMPONENT_LIB} PUBLIC ASIO_NO_TYPEID) endif() This ensures the library adapts to ESP-IDF\u0026rsquo;s configuration, disabling features that aren\u0026rsquo;t available (like C++ exceptions or Run-time Type Information \u0026ndash; RTTI) when they\u0026rsquo;re disabled in the project.\nHandling Platform Differences # Libraries often use #ifdef HAVE_FEATURE patterns to conditionally compile code based on detected features. When porting:\nIdentify which features are available on ESP-IDF Define the appropriate HAVE_* macros Provide implementations or stubs for missing features For example these macros are used in the mosquitto port:\ntarget_compile_definitions(${COMPONENT_LIB} PRIVATE HAVE_PTHREADS=1 HAVE_SOCKETPAIR=1 HAVE_PIPE=1) Step 2: Compose the build system # Different libraries use different build systems, and you\u0026rsquo;ll need to adapt them to ESP-IDF\u0026rsquo;s CMake-based build system.\nCreating Custom CMakeLists.txt # Most of the time, you\u0026rsquo;ll create your own CMakeLists.txt that integrates the library into ESP-IDF\u0026rsquo;s build system. However, there are different approaches depending on the library:\nFrom Scratch # For libraries without CMake support, or when the original CMake is too complex, create a custom CMakeLists.txt that:\nLists all source files explicitly Sets up include directories Configures compile definitions Manages dependencies The mosquitto port is an example of this approach.\nInclude Original CMake # Some libraries already have well-structured CMake that can be included directly. The fmt library is an example where the original CMake can be included with minimal modifications:\nadd_subdirectory(fmt) Include and Modify Original CMake # For libraries with CMake that needs modifications, you can include the original but override specific settings. The mbedtls component uses this approach, including the original CMake but customizing it for ESP-IDF.\nHandling Different Build Systems # GNU Make # Libraries using GNU Make typically require:\nConverting Makefile variables to CMake variables Translating build rules to CMake add_library() or idf_component_register() Handling conditional compilation manually Autotools # Autotools-based libraries (using configure scripts) are more complex:\nYou\u0026rsquo;ll need to replicate the configuration logic in CMake Convert config.h defines to CMake target_compile_definitions() Handle feature detection manually CMake # Libraries already using CMake are the easiest:\nInclude the original CMake if possible Or extract the source lists and recreate the build logic Source File Management # You may need to conditionally include or exclude source files based on ESP-IDF configuration:\nset(m_srcs ${m_lib_dir}/memory_mosq.c ${m_lib_dir}/util_mosq.c # ... more sources ) if(CONFIG_MOSQ_ENABLE_SYS) list(APPEND m_srcs ${m_src_dir}/sys_tree.c) endif() idf_component_register(SRCS ${m_srcs} ...) You can also replace sources for testing, as shown in the pre-include example earlier, where test versions of source files replace the originals during unit testing.\nStep 3: Create the port folder # Create a dedicated port/ directory for adapted functionality that bridges the library with ESP-IDF.\nPort-Specific Header Directories\nA common pattern in ported libraries is to organize port-specific headers in dedicated directories:\nport/include/ - Public headers that extend or wrap library functionality port/priv_include/ - Private headers used only within the port implementation Both asio and mosquitto use this structure. For example, in the asio port:\nidf_component_register(SRCS ${asio_sources} INCLUDE_DIRS \u0026#34;port/include\u0026#34; \u0026#34;asio/asio/include\u0026#34; PRIV_INCLUDE_DIRS ${asio_priv_includes} PRIV_REQUIRES ${asio_requires}) This allows the port to provide custom headers that override or extend the original library\u0026rsquo;s headers without modifying the upstream source.\nStep 4: Adjust functionality (port layer) # Header Injection and Pre-inclusion Techniques # When porting libraries, you often need to inject custom headers or modify include behavior without changing the original source code. This section covers several techniques for achieving this.\ninclude_next Directive\nThe include_next directive is a GCC/Clang extension (not C++ specific—it works with C too) that allows you to include the next header in the search path. This is useful for:\nWrapping or extending standard headers Providing compatibility layers Adding platform-specific extensions For example, if you need to extend a standard header:\n// port/include/sys/socket.h #include_next \u0026lt;sys/socket.h\u0026gt; // Add ESP-IDF specific extensions int esp_socketpair(int domain, int type, int protocol, int sv[2]); The include_next directive will find the original sys/socket.h in the system include path and include it, then your custom code adds additional definitions.\nInjecting Headers in the Same Directory\nSome libraries use old-style include guards that allow you to inject headers in the same directory. This technique works when the library uses patterns like:\n#ifndef __timeval_h__ #define __timeval_h__ ... #endif By placing a header file with the same name in the same directory (or earlier in the include path), you can intercept the include and provide custom definitions. However, this technique is fragile and only works with old-style guards—modern #pragma once headers cannot be intercepted this way.\nPre-include Method\nNote: The pre-include method is not recommended in general and should only be used as a last resort when other dependency injection techniques are not feasible.\nAnother approach to dependency injection is the pre-include method, which uses the -include compiler flag to automatically include a header before every source file is compiled. This technique can be useful for injecting dependency definitions, providing platform-specific macros, or replacing standard library functions, but it comes with significant drawbacks that make it less desirable than other methods.\nThe pre-include method works by instructing the compiler to include a header file before processing each source file, effectively injecting code at the top of every compilation unit. This can be particularly useful in test scenarios where you need to mock dependencies across multiple files.\nFor example, an mDNS test implementation uses pre-inclusion to inject test dependencies. In a Makefile, this might look like:\nMDNS_C_DEPENDENCY_INJECTION=-include mdns_di.h mdns.o: ../../mdns.c @echo \u0026#34;[CC] $\u0026lt;\u0026#34; @$(CC) $(CFLAGS) -include mdns_mock.h $(MDNS_C_DEPENDENCY_INJECTION) -c $\u0026lt; -o $@ The equivalent in CMake:\nset(MDNS_C_DEPENDENCY_INJECTION \u0026#34;-include mdns_di.h\u0026#34;) set_source_files_properties( ${CMAKE_CURRENT_SOURCE_DIR}/../../mdns.c PROPERTIES COMPILE_FLAGS \u0026#34;-include mdns_mock.h ${MDNS_C_DEPENDENCY_INJECTION}\u0026#34; ) In both cases, the pattern defines a variable containing the pre-include flag for dependency injection and uses it in the compilation command along with other pre-includes. This ensures that the dependency injection header is included before the source file is compiled, allowing mock implementations to be injected seamlessly. However, because this affects every compilation unit and can lead to unexpected side effects, it should be considered a last resort when cleaner dependency injection methods are not available.\nLinker Wrapping # Linker wrapping is a powerful technique that allows you to override functions without modifying the source code. It uses the --wrap linker flag to redirect function calls to wrapper implementations.\nHow It Works # When you wrap a function function_name, the linker will:\nRedirect calls to function_name() to __wrap_function_name() Make the original function available as __real_function_name() This allows you to:\nIntercept function calls Add ESP-IDF specific behavior Call the original function when needed Completely replace the function if desired When to use linker wrapping:\nOverriding library functions that need ESP-IDF specific behavior Intercepting calls to standard library functions (malloc, free, time, etc.) When you want to avoid modifying the original source code As an alternative to source-level function replacement Limitations:\nOnly works with functions (not macros or inline functions) Requires implementing the wrapper function The wrapped function must be linked (not inlined) Real-World Example: libwebsockets # The libwebsockets (lws) port uses linker wrapping to override functions that need ESP-IDF specific behavior. Here\u0026rsquo;s the CMakeLists.txt pattern:\nset(WRAP_FUNCTIONS mbedtls_ssl_handshake_step lws_adopt_descriptor_vhost) foreach(wrap ${WRAP_FUNCTIONS}) target_link_libraries(${COMPONENT_LIB} INTERFACE \u0026#34;-Wl,--wrap=${wrap}\u0026#34;) endforeach() The wrapped functions are then implemented in port/lws_port.c:\nextern int __real_mbedtls_ssl_handshake_step(mbedtls_ssl_context *ssl); int __wrap_mbedtls_ssl_handshake_step(mbedtls_ssl_context *ssl) { int ret = 0; while (ssl-\u0026gt;MBEDTLS_PRIVATE(state) != MBEDTLS_SSL_HANDSHAKE_OVER) { ret = __real_mbedtls_ssl_handshake_step(ssl); if (ret == MBEDTLS_ERR_SSL_WANT_READ || ret == MBEDTLS_ERR_SSL_WANT_WRITE) { continue; } if (ret != 0) { break; } } return ret; } In this example, the wrapper:\nCalls the original function via __real_mbedtls_ssl_handshake_step() Handles WANT_READ/WANT_WRITE errors by retrying Continues until the handshake is complete Socket Utilities (sock_utils) - Deep Dive # When porting Linux/Unix libraries to ESP-IDF, you\u0026rsquo;ll often encounter POSIX socket APIs that aren\u0026rsquo;t directly available. The sock_utils component provides a compatibility layer that implements common POSIX socket functions using ESP-IDF\u0026rsquo;s lwIP and esp_netif components.\nsock_utils is especially useful when porting libraries that rely on:\nPOSIX socket APIs (socketpair, pipe) Network interface enumeration (ifaddrs) Address resolution (getnameinfo, gai_strerror) Hostname resolution (gethostname) API Description Limitations Declared in ifaddrs() Retrieves interface addresses using esp_netif IPv4 addresses only ifaddrs.h socketpair() *) Creates a pair of connected sockets using lwIP loopback stream sockets IPv4 sockets only socketpair.h, sys/socket.h **) pipe() *) Wraps socketpair() to provide unidirectional pipe-like functionality Uses bidirectional sockets in place of true pipes socketpair.h, unistd.h ***) getnameinfo() Converts IP addresses to human-readable form using lwIP\u0026rsquo;s inet_ntop() IPv4 only; supports NI_NUMERICHOST and NI_NUMERICSERV flags only getnameinfo.h, netdb.h in ESP-IDF gai_strerror() Returns error code as a string Simple numeric string representation only gai_strerror.h, netdb.h **) gethostname() Returns lwip netif hostname Not a system-wide hostname, but interface specific hostname gethostname.h, unistd.h in ESP-IDF Notes:\n*) socketpair() and pipe() are built on top of lwIP TCP sockets, inheriting the same characteristics. For instance, the maximum transmit buffer size is based on the TCP_SND_BUF setting. **) socketpair() and gai_strerror() are declared in sock_utils header files. From ESP-IDF v5.5 onwards, these declarations are automatically propagated to the official header files. If you\u0026rsquo;re using an older IDF version, you need to manually pre-include the related header files from the sock_utils public include directory. ***) pipe() is declared in the compiler\u0026rsquo;s sys/unistd.h. Integration Methods # For ESP-IDF versions before 5.5, you need to manually ensure the sock_utils headers are included. This can be done by:\nAdding sock_utils to your component\u0026rsquo;s REQUIRES or PRIV_REQUIRES: idf_component_register(SRCS ${sources} PRIV_REQUIRES sock_utils) Pre-including the headers if needed: target_compile_options(${COMPONENT_LIB} PRIVATE \u0026#34;-include\u0026#34; \u0026#34;socketpair.h\u0026#34;) From ESP-IDF v5.5 onwards, the sock_utils declarations are automatically available in the standard headers when you include sock_utils as a dependency. Simply add it to your component:\nidf_component_register(SRCS ${sources} PRIV_REQUIRES sock_utils) Real-World Example: ASIO Using socketpair() # The asio library uses socketpair() from sock_utils for its pipe-interrupter implementation. The pipe-interrupter is used to wake up the event loop when needed. Here\u0026rsquo;s how it\u0026rsquo;s integrated:\nThe asio component includes sock_utils as a dependency: set(asio_requires lwip sock_utils) idf_component_register(SRCS ${asio_sources} PRIV_REQUIRES ${asio_requires}) The asio code can then use socketpair() directly, and it will resolve to the sock_utils implementation. Dependencies\nsock_utils requires:\nlwIP - For socket functionality esp_netif - For network interface management These are automatically pulled in when you add sock_utils as a dependency.\nOverride Functions # When porting libraries, you\u0026rsquo;ll often need to provide implementations for functions that aren\u0026rsquo;t available on ESP-IDF, or override functions to provide ESP-IDF-specific behavior.\nLibraries often need to override standard functions:\nmalloc/free - To use ESP-IDF\u0026rsquo;s memory management Time functions - To use ESP-IDF\u0026rsquo;s time APIs Random number generation - To use ESP-IDF\u0026rsquo;s RNG These can be implemented as:\nSource-level replacements (providing the function in your port code) Linker-wrapped functions (as discussed earlier) Pre-included headers that define macros Stub Function Implementations # Some functions may not be needed on ESP-IDF but are required by the library\u0026rsquo;s API. In these cases, you can provide stub implementations.\nThe asio port provides a stub for the pause() system call:\nextern \u0026#34;C\u0026#34; int pause(void) { while (true) { ::sleep(UINT_MAX); } } This stub is placed in port/src/asio_stub.cpp and provides a minimal implementation that satisfies the library\u0026rsquo;s requirements.\nStep 5: Fine-tune (Compiler Warnings) # Component-Level Suppression # As covered in the basic porting article, you can suppress compiler warnings for an entire component using target_compile_options():\ntarget_compile_options(${COMPONENT_LIB} PRIVATE -Wno-char-subscripts) This approach works well when the warning applies broadly across the component, but it can be too broad when only specific files trigger warnings.\nFile-Level Suppression # For more granular control, ESP-IDF allows you to suppress warnings on a per-file basis using set_source_files_properties(). This is particularly useful when:\nOnly a few files in a large library trigger warnings You want to keep strict warnings enabled for the rest of the component Different files need different warning suppressions The mosquitto library provides a good example of this technique. Some mosquitto source files unconditionally define _GNU_SOURCE, which collides with the ESP-IDF build system and produces redefinition warnings. Instead of suppressing this warning for the entire component, we can target only the offending files:\n# Some mosquitto source unconditionally define `_GNU_SOURCE` which collides with IDF build system # producing warning: \u0026#34;_GNU_SOURCE\u0026#34; redefined # This workarounds this issue by undefining the macro for the selected files set(sources_that_define_gnu_source ${m_src_dir}/loop.c ${m_src_dir}/mux_poll.c) foreach(offending_src ${sources_that_define_gnu_source}) set_source_files_properties(${offending_src} PROPERTIES COMPILE_OPTIONS \u0026#34;-U_GNU_SOURCE\u0026#34;) endforeach() You can also use this technique to suppress specific warnings for individual files:\n# Suppress format warnings for specific files set_source_files_properties(${m_src_dir}/logging.c PROPERTIES COMPILE_OPTIONS \u0026#34;-Wno-format\u0026#34;) Or combine multiple options:\nset_source_files_properties(${m_src_dir}/file.c PROPERTIES COMPILE_OPTIONS \u0026#34;-Wno-format;-Wno-unused-variable\u0026#34;) License Considerations # When porting external libraries, always consider license compatibility:\nCheck the library\u0026rsquo;s license - Ensure it\u0026rsquo;s compatible with your use case Maintain attribution - Include license files and copyright notices Document modifications - If you modify the library, document the changes Consider license of dependencies - Ensure all dependencies are compatible Most ported libraries maintain the original license and add Espressif\u0026rsquo;s copyright notice for port-specific code.\nReal-World Case Study: ASIO Port # The ASIO (Asynchronous I/O) library port demonstrates several advanced techniques working together. Let\u0026rsquo;s examine the key changes and techniques used.\nThe ASIO port switched to using the upstream ASIO library directly, reducing maintenance burden while providing a robust asynchronous I/O implementation for ESP-IDF.\nKey techniques used:\nSwitching to Upstream Instead of maintaining a fork, the port now uses the upstream ASIO library directly, making it easier to stay current with updates and bug fixes.\nUsing socketpair() from sock_utils ASIO\u0026rsquo;s pipe-interrupter implementation uses socketpair() to create a communication channel for waking the event loop. The port uses sock_utils to provide this POSIX function:\nset(asio_requires lwip sock_utils) Pipe-Interrupter Implementation The pipe-interrupter is a critical component for ASIO\u0026rsquo;s event loop. By using socketpair() from sock_utils, the port provides a working implementation without modifying ASIO\u0026rsquo;s source code.\nLocal pause() Stub ASIO requires the pause() system call, which isn\u0026rsquo;t available on ESP-IDF. The port provides a stub implementation in port/src/asio_stub.cpp:\nextern \u0026#34;C\u0026#34; int pause(void) { while (true) { ::sleep(UINT_MAX); } } POSIX Event Customization The port replaces ASIO\u0026rsquo;s default posix_event constructor with an ESP-IDF-compatible version that avoids pthread_condattr_t operations that aren\u0026rsquo;t available on all IDF versions:\n// This replaces asio\u0026#39;s posix_event constructor // since the default POSIX version uses pthread_condattr_t operations (init, setclock, destroy), // which are not available on all IDF versions posix_event::posix_event() : state_(0) { int error = ::pthread_cond_init(\u0026amp;cond_, nullptr); asio::error_code ec(error, asio::error::get_system_category()); asio::detail::throw_error(ec, \u0026#34;event\u0026#34;); } This is implemented in port/src/asio_stub.cpp and enabled via the ASIO_DETAIL_IMPL_POSIX_EVENT_IPP compile definition.\nFor more details on the ASIO port changes, see ESP-Protocols PR #717.\nConclusion # Porting complex libraries to ESP-IDF requires a combination of techniques:\nCompiler warning management - Use file-level suppression for granular control Header injection - Pre-include, include_next, and port directories for seamless integration Linker wrapping - Override functions without modifying source code sock_utils - Leverage POSIX compatibility for socket-based libraries Build system adaptation - Create custom CMake or adapt existing build systems Function overrides and stubs - Provide ESP-IDF-specific implementations Compile definitions - Configure libraries to work with ESP-IDF\u0026rsquo;s feature set The key is to minimize modifications to the original library source code, making it easier to:\nStay synchronized with upstream updates Maintain the port over time Share the port with the community By using these advanced techniques, you can successfully port even complex libraries like ASIO, mosquitto, and libwebsockets to ESP-IDF while maintaining clean, maintainable code.\nFor more examples, explore the implementations in the ESP-Protocols repository, which contains many ported libraries demonstrating these techniques in practice.\n","date":"24 November 2025","externalUrl":null,"permalink":"/blog/2025/11/advanced-porting-libraries-as-components/","section":"Blog","summary":"This article follows up on the article \u0026lsquo;Porting a library to an ESP-IDF component\u0026rsquo; and shows some advanced tips and tricks when porting larger libraries into ESP-IDF components.","title":"Advanced techniques for porting libraries to ESP-IDF components","type":"blog"},{"content":"","date":"24 November 2025","externalUrl":null,"permalink":"/tags/linux/","section":"Tags","summary":"","title":"Linux","type":"tags"},{"content":"","date":"24 November 2025","externalUrl":null,"permalink":"/tags/porting/","section":"Tags","summary":"","title":"Porting","type":"tags"},{"content":"","date":"19 November 2025","externalUrl":null,"permalink":"/tags/cross-compilation/","section":"Tags","summary":"","title":"Cross-Compilation","type":"tags"},{"content":"","date":"19 November 2025","externalUrl":null,"permalink":"/authors/filipe-cavalcanti/","section":"Developer Portal Authors","summary":"","title":"Filipe Cavalcanti","type":"authors"},{"content":" Introduction # When moving your application to NuttX, you may need to add your existing codebase to the NuttX build environment. That is a common scenario where the user application contains mostly hardware-independent logic (such as data processing and analysis) that was originally developed on a POSIX compliant system. Those applications are usually tested on an x86 machine and adapted to run on an RTOS, or, in the case of NuttX, it should not need changes if the codebase is already POSIX compliant.\nThis article shows how to build NuttX with your custom application without moving your entire stack to the NuttX directory. You use a static library and cross-compilation to achieve this.\nThis article is divided into four parts. The first part introduces an example library and builds it on x86. Then, the second part describes how to add the library to the NuttX simulation environment. The third part cross-compiles to RISC-V and runs the example on the ESP32-C6. Finally, the fourth part concludes the article.\nUsing an example library # For demonstration purposes, we will use an example application library that converts a hexadecimal color string to RGB with the following structure:\nhex-converter/ ├── src/ │ ├── hex_to_rgb.h │ └── hex_to_rgb.c ├── main.c ├── test.c ├── Makefile └── README.md The reference project is available in this repository.\nThe hex-converter library exposes one single function called hex_to_rgb. The user provides a pointer to a string representing the hex color and a pointer to an array where the R, G, and B values are copied. It is a simple application but very useful as an example.\nNow, let\u0026rsquo;s use the library on our x86 machine and see how it operates.\nClone the repository Build the library according to the steps in the README file Execute the provided main example program: $ ./main \u0026#34;#1A2B3C\u0026#34; Input: #1A2B3C RGB: (26, 43, 60) At this point, the directory should contain a static library called libhex_to_rgb.a.\nTesting on NuttX Simulation # As a user, you might want to use this library in an application. The first solution might be to copy the entire hex-converter repository to the NuttX application directory and add it entirely to the build system. That works but is complicated, not user-friendly, and causes a Makefile mess.\nIf you are new to NuttX, you can read the Getting Started with NuttX and ESP32, which shows how to setup the NuttX development environment.\nThe simplest way to test this library on NuttX is to modify the ready-to-use Hello World example in the NuttX Apps repository, which could in fact be any application.\nWith your NuttX environment ready, follow these steps:\nClone the example repository and build libhex_to_rgb.a as discussed in Using an example library Copy libhex_to_rgb.a to apps/examples/hello (the Hello World example directory) In apps/hello/Make.defs, add the hex library, library path, and include path The Make.defs file should look like this:\nifneq ($(CONFIG_EXAMPLES_HELLO),) CONFIGURED_APPS += $(APPDIR)/examples/hello EXTRA_LIBS += -lhex_to_rgb EXTRA_LIBPATHS += -L$(APPDIR)/examples/hello CFLAGS += ${INCDIR_PREFIX}/home/user/hex-converter/src endif To use the library, we edit the hello_main.c file to look like this:\n/**************************************************************************** * Included Files ****************************************************************************/ #include \u0026lt;nuttx/config.h\u0026gt; #include \u0026lt;stdio.h\u0026gt; #include \u0026lt;stdlib.h\u0026gt; #include \u0026#34;hex_to_rgb.h\u0026#34; /**************************************************************************** * Public Functions ****************************************************************************/ /**************************************************************************** * hello_main ****************************************************************************/ int main(int argc, FAR char *argv[]) { int rgb[3]; int result; if (argc != 2) { return EXIT_FAILURE; } printf(\u0026#34;Input: %s\\n\u0026#34;, argv[1]); result = hex_to_rgb(argv[1], rgb); if (result == HEX_TO_RGB_SUCCESS) { printf(\u0026#34;RGB: (%d, %d, %d)\\n\u0026#34;, rgb[0], rgb[1], rgb[2]); } else { printf(\u0026#34;Error: %d\\n\u0026#34;, result); } return result; } After all changes are done, build the NuttX simulation:\n./tools/configure.sh sim:nsh make Execute: ./nuttx Call the hello program. This executes the HEX to RGB conversion:\nuser@desktop:~/nxsupport/nuttx$ ./nuttx NuttShell (NSH) NuttX-12.8.0 nsh\u0026gt; hello \u0026#34;#1a2b3c\u0026#34; Input: #1a2b3c RGB: (26, 43, 60) nsh\u0026gt; Success! We can compile our library externally, link it to a NuttX application, and use it.\nNow that simulation works, let\u0026rsquo;s look into a real use case that requires the same code to work on hardware.\nUsing the library on the ESP32-C6 # This section shows how to prepare the library for an actual target device—in this case, the ESP32-C6. To do this, we first cross-compile the example library for the RISC-V architecture and then integrate the resulting static library into the Hello World Example that will be executed on our target.\nCross-compilation # Clear the environment to delete the x86 build and rebuild for RISC-V:\nmake clean make TARGET=riscv32 When you set the TARGET variable in the hex-converter Makefile, the CC instruction changes from gcc to riscv-none-elf-gcc.\nThe same libhex_to_rgb.a library is ready, but now it can be used on RISC-V devices. This can be verified easily:\n$ file main main: ELF 32-bit LSB executable, UCB RISC-V, RVC, soft-float ABI, version 1 (SYSV), statically linked, not stripped Test on target # Clean the NuttX environment with make distclean and configure it for the nsh example of ESP32-C6.\nCopy the new libhex_to_rgb.a to the hello example directory. Then configure and build the project:\nmake distclean ./tools/configure.sh esp32c6-devkitc:nsh On menuconfig, enable Hello World example (Application Configuration → Examples \u0026gt; \u0026ldquo;Hello World\u0026rdquo; Example) make Flash the board and try the hello example using the serial console:\n[...] SHA-256 comparison failed: Calculated: d07603736784dd3c56754d4d27366ffd0c2a32aebaddea7e6c0a153ad774ba15 Expected: 00000000009d0000000000000000000000000000000000000000000000000000 Attempting to boot anyway... entry 0x40805496 pmu_param(dbg): blk_version is less than 3, act dbias not burnt in efuse *** Booting NuttX *** [...] NuttShell (NSH) NuttX-12.8.0 nsh\u0026gt; hello \u0026#34;#1a2b3c\u0026#34; Input: #1a2b3c RGB: (26, 43, 60) nsh\u0026gt; With a simple change of compiler and no changes to the NuttX build system, we were able to have the same example running on an ESP32-C6.\nConclusion # This article demonstrates how to integrate external libraries into NuttX applications using static libraries and cross-compilation. The process involves three main steps: building the library on x86, integrating it into the NuttX simulation environment, and cross-compiling for the target hardware.\nThe static library approach offers several advantages. You can develop and test your code on an x86 machine without flashing the target device. The same library works across different architectures with minimal changes, requiring only a recompilation step. This workflow saves development time and simplifies the porting process.\nBy following these steps, you can add existing applications to NuttX without moving your entire codebase into the NuttX directory structure. This approach maintains separation between your application code and the RTOS, making maintenance and updates easier.\nRelated Resources # NuttX ESP32 Documentation Getting Started with NuttX and ESP32 ","date":"19 November 2025","externalUrl":null,"permalink":"/blog/2025/11/nuttx-external-lib/","section":"Blog","summary":"This guide demonstrates how to integrate external libraries into NuttX applications using static libraries and cross-compilation. Learn how to build a library on x86, integrate it into the NuttX simulation environment, and cross-compile for RISC-V targets like the ESP32-C6, all without moving your entire codebase into the NuttX directory structure.","title":"Integrating External Libraries into NuttX Applications","type":"blog"},{"content":"","date":"19 November 2025","externalUrl":null,"permalink":"/tags/risc-v/","section":"Tags","summary":"","title":"RISC-V","type":"tags"},{"content":"Welcome to the basic ESP-IDF workshop!\nIntroduction # In this workshop, you will gain a solid understanding of the ESP-IDF framework, learning how to effectively use Visual Studio Code (VS Code) and Espressif’s official ESP-IDF extension for VS Code.\nThe workshop is divided into three parts. In the first part, we’ll verify that your development environment is properly set up by using the classic hello world example as a starting point. In the second part, we’ll dive into the network stack and build a simple HTTP server together. The third part will focus on two very common peripherals: GPIO and I2C.\nWe’ll also explore the component system and the component registry, which allows you to use libraries without manually managing dependencies or build system settings.\nAs a final exercise, we’ll combine everything to create a simple sensor gateway, integrating connectivity and peripheral control into a single project.\nBy the end of the workshop, you’ll have the basic skills needed to start developing your own applications based on ESP-IDF.\nEstimated duration: 3 hours. Agenda # The workshop is divided into three parts, each lasting for about one hour.\nPart 1: Welcome and introduction\nLesson 1 – Introduction to ESP-IDF and the ESP-IDF extension for VS Code. Assignment 1.1 – Verify your ESP-IDF and VS Code installation by compiling and flashing the hello_world example. Modify the example’s output text. Assignment 1.2 – Create a new project starting from the blink example Part 2: HTTP Connectivity\nLesson 2 – Connectivity: HTTP protocol, HTML, and REST APIs\nAssignment 2.1 – Create an HTTP server that handles the GET request /index.html/ and returns \u0026lt;h1\u0026gt;Hello LED Control\u0026lt;/h1\u0026gt;\nAssignment 2.2 – Add the following routes to the HTTP server:\nGET /led/on → turns on the LED and returns the JSON {\u0026quot;led\u0026quot;: \u0026quot;on\u0026quot;} GET /led/off → turns off the LED and returns the JSON {\u0026quot;led\u0026quot;: \u0026quot;off\u0026quot;} POST /led/blink → accepts a JSON { \u0026quot;times\u0026quot;: int, \u0026quot;interval_ms\u0026quot;: int } and makes the LED blink the specified number of times at the given interval Assignment 2.3 – (Optional) Add the following route:\nPOST /led/flash → accepts the JSON {\u0026quot;periods\u0026quot;: [int], \u0026quot;duty_cycles\u0026quot;: [int]} and, for each element, calculates on/off durations to drive the LED accordingly Part 3: Peripherals and Integration\nLesson 3 – GPIO, I2C, and the component registry\nAssignment 3.1 – Create a new component to control the LED\nAssignment 3.2 – Add a component to read the onboard environmental sensor\nAssignment 3.3 – (Optional) Add the route:\nGET /environment/ → returns the sensor reading. Choose the most appropriate JSON format to represent the data. Prerequisites # To follow this workshop, make sure you meet the prerequisites listed below.\nRequired Software # VS Code installed on your computer (v1.108+) ESP-IDF extension for VS Code added to VS Code (v1.11+) ESP-IDF installed on your machine (v5.5+) It can be installed via VS Code or by using the ESP-IDF Installation Manager Required Hardware # ESP-C3-DevKit-RUST-1 or ESP-C3-DevKit-RUST-2 board\n(if the activity is in person, the board will be provided during the workshop)\nIt’s also possible to use an ESP32-C3-DevKit-M/C board, but you’ll need to adapt the GPIO configuration accordingly. If the event is held in person, please complete the following before the workshop:\nInstall VS Code Install ESP-IDF externsion for VS COde If any issues arise, there will be a short window during the first exercise to complete the installation.\nBasic Knowledge # Basic electronics Resistors, capacitors, DC/DC power supplies Reading an electrical schematic Basic embedded programming Flash memory Difference between compiling and flashing firmware Understanding of common microcontroller peripherals (mainly GPIO and I2C) Basic C language knowledge Header files Compiler/linker concepts Use of define, struct, and typedef JSON and YAML data formats HTML and its main tags (\u0026lt;html\u0026gt;, \u0026lt;body\u0026gt;, \u0026lt;h1\u0026gt;, \u0026lt;h2\u0026gt;, \u0026lt;p\u0026gt;) Basic understanding of HTTP request methods (GET, POST) and the concept of URI and routes Next Step # The next step is Lesson 1.\nConclusion # Congratulations! You’ve reached the end of this workshop. We hope it has been a valuable experience and the beginning of a deeper journey into Espressif’s tools.\nYou are now able to create, compile, and flash new projects, use external libraries and components, create your own components, and control everything through an HTTP interface.\nYou’ve therefore acquired the fundamental skills to develop an IoT application.\n","date":"12 November 2025","externalUrl":null,"permalink":"/workshops/esp-idf-basic/","section":"Workshops","summary":"This workshop explores the basics of the ESP-IDF. You will build and flash basic programs, create your own components and build a REST API HTTP server.","title":"ESP-IDF Workshop: Basic","type":"workshops"},{"content":" VS Code Installation # Go to the VS Code download site Download and install the macOS version This guide uses macOS Sequoia. Once the file is downloaded, install VS Code Press CTRL+SPACE and search for Code. Click on the VS Code icon You should now see the VS Code interface VS Code may ask whether you trust the author of the folder. This is important when using git repositories, but for now it doesn’t matter. Click “Yes.” Installing Prerequisites # To install and configure the ESP-IDF toolchain, you need to have Python and git installed. In this guide, we’ll use the homebrew package manager (brew).\nInstalling homebrew\nTo install homebrew:\nOpen a terminal\nType:\n/bin/bash -c \u0026#34;$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)\u0026#34; Python # The ESP-IDF toolchain uses the system version of Python. You can check the Python version by typing in the terminal:\npython3 --version If Python is not already installed, you can install it with the following command from the terminal:\nbrew install python3 git # ESP-IDF development is based on git, the version control tool used, among others, for Linux kernel development. git is the foundation upon which GitHub is built.\nTo install git:\nOpen a terminal\nInstall git:\nsudo brew install git Verify that git was installed correctly:\n\u0026gt; git --version \u0026gt; git version 2.43.0 Installing Additional Prerequisites # To use the ESP-IDF toolchain, you need to install the remaining tools.\nOpen a terminal\nType:\nbrew install cmake ninja dfu-util During the installation process, you may encounter some issues. Refer to the Troubleshooting section to see if your error is listed there.\nNext Steps # Continue with the next step.\nTroubleshooting # During the installation process, you may encounter some common errors. Below are the most frequent ones, along with their causes and solutions.\nXcode Command Line Tools Not Installed # Error\nxcrun: error: invalid active developer path (/Library/Developer/CommandLineTools), missing xcrun at: /Library/Developer/CommandLineTools/usr/bin/xcrun Cause The Xcode command-line tools are not installed or not properly configured.\nSolution\nxcode-select --install Toolchain Not Found (xtensa-esp32-elf) # Error\nWARNING: directory for tool xtensa-esp32-elf version esp-2021r2-patch3-8.4.0 is present, but tool was not found ERROR: tool xtensa-esp32-elf has no installed versions. Please run \u0026#39;install.sh\u0026#39; to install it. Cause On macOS systems with Apple Silicon architecture, some binary tools require Rosetta 2 to work.\nSolution\n/usr/sbin/softwareupdate --install-rosetta --agree-to-license “Bad CPU type in executable” Error # Error\nzsh: bad CPU type in executable: ~/.espressif/tools/xtensa-esp32-elf/esp-2021r2-patch3-8.4.0/xtensa-esp32-elf/bin/xtensa-esp32-elf-gcc Cause The executable requires Rosetta 2 to run on macOS M1/M2/M3 systems.\nSolution\n/usr/sbin/softwareupdate --install-rosetta --agree-to-license ","date":"12 November 2025","externalUrl":null,"permalink":"/workshops/esp-idf-setup/installation-macos/","section":"Workshops","summary":"This guide outlines the preliminary steps to set up your work environment and follow the workshops.","title":"macOS prerequisites 🍎","type":"workshops"},{"content":"In February this year, we announced the first esp-hal 1.0 beta release. Since then we\u0026rsquo;ve been hard at work, polishing and preparing for the full release. Today, the Rust team at Espressif is excited to announce the official 1.0.0 release for esp-hal, the first vendor-backed Rust SDK!\nWhat We\u0026rsquo;re Stabilizing Today # We\u0026rsquo;ve spent many years researching and experimenting to get to this stage (check out the esp-hal 1.0 beta blog post for the longer story!). However, to get a stable foundation to build from, the experimentation eventually needs to make way for stability. To achieve this, we\u0026rsquo;ve decided to limit the scope of 1.0 stabilization to:\nInitializing the HAL, esp_hal::init and the relevant configuration associated with that. Four \u0026ldquo;core\u0026rdquo; drivers to start: GPIO UART SPI I2C Async and Blocking modes for the aforementioned drivers. Our Async drivers are compatible with many executors, including Embassy\u0026rsquo;s. The time module, which provides Instant, Duration, and Rate. A couple of miscellaneous system APIs (SoC reset, etc.). #[main] macro. Additional configuration mechanisms beyond feature flags (esp-config). With the exception of the list above, everything else in esp-hal is now feature-gated behind the unstable feature. With the scope limited, post 1.0 we can incrementally stabilize drivers, much like the Rust project itself does, building on 1.0\u0026rsquo;s foundation.\nWhat Does Unstable Mean for Drivers? # Unstable in this case refers to API stability. There is varying levels of functionality for unstable drivers, however, they are suitable for most common use cases. Using them, reporting feedback, and/or contributing to improving them will aid their stabilization.\nWhat About the Other esp-* Crates? # esp-hal is the foundation of many of the ecosystem crates. esp-radio (previously known as esp-wifi) is our next stabilization target, which will enable the use of Wi-Fi, Bluetooth, ESP-NOW and IEEE802.15.4 on the ESP32 family of devices. The end goal is of course to have every esp-* crate with a 1.0+ release eventually.\nGetting Started # The first step is to read our specially curated book, which explains the ecosystem, tooling and some key embedded concepts for esp-hal.\nAs part of getting to 1.0, we\u0026rsquo;ve created our own project generation tool, esp-generate to bootstrap a project. This is explained fully in the book, but getting something running today should be as simple as:\ncargo install esp-generate --locked Then run\nesp-generate to launch the interactive project generation terminal user interface.\nOnce you\u0026rsquo;ve generated your project, connect your ESP32 and run cargo run --release from your new project directory!\nTo start building from your baseline project, check out our API documentation at docs.espressif.com/projects/rust.\nWhat’s Next? # This is just the start. We plan on stabilizing all esp-hal related crates, next up is esp-radio. We\u0026rsquo;ll continue developing esp-hal; over time we\u0026rsquo;ll stabilize more drivers beyond the core set that we\u0026rsquo;re starting with today. We\u0026rsquo;ll continue to add support for new devices, such as the newly released ESP32-C5, as they go into mass production.\nThis release would not have been possible without the help from the Rust community, the embedded working group, and of course the ESP community and contributors which have heavily impacted how we’ve developed our Rust offering. I would also like to thank Espressif, and in particular the Rust team for their hard work in getting us to where we are today!\nIf you\u0026rsquo;re a company using (or considering using) Rust on our devices, please do contact sales@espressif.com, we\u0026rsquo;d love to hear from you!\n","date":"30 October 2025","externalUrl":null,"permalink":"/blog/2025/10/esp-hal-1/","section":"Blog","summary":"Announcing esp-hal 1.0, the first Rust SDK for embedded devices.","title":"esp-hal 1.0.0 release announcement","type":"blog"},{"content":"","date":"30 October 2025","externalUrl":null,"permalink":"/tags/riscv/","section":"Tags","summary":"","title":"RISCV","type":"tags"},{"content":"","date":"30 October 2025","externalUrl":null,"permalink":"/tags/rust/","section":"Tags","summary":"","title":"Rust","type":"tags"},{"content":"","date":"30 October 2025","externalUrl":null,"permalink":"/authors/scott-mabin/","section":"Developer Portal Authors","summary":"","title":"Scott Mabin","type":"authors"},{"content":"","date":"30 October 2025","externalUrl":null,"permalink":"/tags/xtensa/","section":"Tags","summary":"","title":"Xtensa","type":"tags"},{"content":"","date":"24 October 2025","externalUrl":null,"permalink":"/tags/ci/cd/","section":"Tags","summary":"","title":"CI/CD","type":"tags"},{"content":"","date":"24 October 2025","externalUrl":null,"permalink":"/tags/debugging/","section":"Tags","summary":"","title":"Debugging","type":"tags"},{"content":" Introduction # Porting graphics libraries to embedded systems often involves subtle bugs that are hard to diagnose - especially when dealing with color formats, endianness, and framebuffer handling. This article describes how we used Wokwi simulation combined with Warp\u0026rsquo;s AI capabilities to iteratively solve a color mapping bug in the raylib ESP-IDF component, turning what could have been hours of trial-and-error into an efficient debugging workflow.\nThe Challenge: Porting Raylib to ESP32 # Raylib is a popular game programming library that recently gained software rendering support, making it suitable for embedded devices without GPUs. We were porting it to ESP32 devices (specifically the ESP32-S3-BOX-3) using ESP-IDF, wrapping the upstream raylib library as an ESP-IDF component.\nThe initial port compiled and ran, but there was a problem: instead of showing solid colors, the display showed vertical yellow/blue stripes.\nThe framebuffer format was clearly wrong, but determining exactly where and how required multiple iterations.\nEnter Wokwi: Hardware Simulation for Bug Hunting # Rather than flash to physical hardware for every test, we used Wokwi - a powerful hardware simulator that can emulate ESP32 boards with displays. Wokwi is particularly valuable for bug hunting in embedded graphics applications because it provides:\nScreenshot Capability: Capture display output as PNG files at any point in execution - crucial for visual debugging Integrated Debugger: Step through code, set breakpoints, and inspect variables without physical hardware Fast Iteration Cycles: No need to physically flash devices between tests Reproducible Testing: Same simulation conditions every time, eliminating hardware variability IDE Integration: Works seamlessly with VS Code and CLion for professional development workflows CI/CD Ready: Automated testing in GitHub Actions with screenshot validation Our Wokwi setup included:\nESP32-S3-BOX-3 board definition (320x240 ILI9341 display) Custom firmware with Raylib Hello example Automated screenshot capture at specific timestamps wokwi-cli \\ --diagram-file diagram.json \\ --screenshot-part esp \\ --screenshot-time 5000 \\ --screenshot-file screenshot.png \\ --timeout 6000 \\ boards/esp-box-3 The AI-Assisted Debugging Loop # Here\u0026rsquo;s where it got interesting. Instead of manually analyzing each screenshot and making educated guesses, we used Warp\u0026rsquo;s AI agent with vision capabilities to create a feedback loop:\n1. Initial Problem Identification # Developer: \u0026ldquo;The screen should have a red background, but as you can see, it\u0026rsquo;s not true. It has some kind of Yellow, blue, vertical line patterns.\u0026rdquo;\nAI Action: Read the screenshot, identified the vertical stripe pattern indicating likely color format mismatch or byte-order issues.\n2. Hypothesis Generation # The AI analyzed the code and proposed several theories:\nRGB565 color format mismatch Endianness issues (big-endian vs little-endian) Incorrect framebuffer copy method RGBA vs RGB internal format confusion 3. Iterative Testing with Wokwi # For each hypothesis, we followed this pattern:\n1. AI proposes code change 2. Build firmware 3. Run Wokwi simulation with screenshot capture 4. AI reads the screenshot to verify if colors improved 5. Adjust based on results This tight feedback loop was possible because:\nWokwi provided consistent, reproducible screenshots Warp AI could read images directly Build times were reasonable (~30 seconds) No physical hardware connection needed 4. The AI iterations: Direct Framebuffer Access # Since we established AI feedback loop, the AI was able to iterate over the problem. Thanks to provided feedback from developer, it was able to drive several iterations of the debugging process.\nThe AI discovered that the original code used rlCopyFramebuffer(), which performed:\nRGB565 → RGBA8888 → RGB565 This double conversion was corrupting colors. The debug process:\nIteration 1: Added debug logging to print pixel values\nESP_LOGI(\u0026#34;RAYLIB\u0026#34;, \u0026#34;First pixel = 0x%04X (should be RED=0xF800)\u0026#34;, framebuffer[0]); Wokwi serial output showed: 0x28E6 (wrong!) instead of 0xF800 (red)\nIteration 2: Switch to direct framebuffer access using swGetColorBuffer()\nuint16_t *sw_framebuffer = (uint16_t *)swGetColorBuffer(\u0026amp;sw_width, \u0026amp;sw_height); memcpy(framebuffer, sw_framebuffer, screen_width * screen_height * sizeof(uint16_t)); New pixel values: 0xE147 (closer, but still wrong)\nIteration 3: Add byte-swapping for SPI LCD endianness\nfor (int i = 0; i \u0026lt; total_pixels; i++) { uint16_t pixel = framebuffer[i]; framebuffer[i] = (pixel \u0026gt;\u0026gt; 8) | (pixel \u0026lt;\u0026lt; 8); // Swap bytes } Screenshot verification: Wokwi showed solid green (test was at 5 seconds when green was displayed) ✅\nThe Complete Workflow in Action # Here\u0026rsquo;s what a typical debugging iteration looked like. Note the iterative loop - we went through this cycle multiple times before finding the correct solution:\nThe key insight is the feedback loop (highlighted in yellow): AI proposes changes → build → Wokwi captures screenshot → AI verifies → if not fixed, iterate again. This cycle ran multiple times, with each iteration getting closer to the solution.\nKey Insights # Why This Worked Well # Visual Feedback is Critical: Color bugs can\u0026rsquo;t be debugged with logs alone - you need to see the actual output. Wokwi\u0026rsquo;s screenshot capability made this trivial Wokwi\u0026rsquo;s Debugging Power: The integrated debugger would have allowed stepping through framebuffer operations if screenshots weren\u0026rsquo;t sufficient Wokwi\u0026rsquo;s Consistency: Same simulation every time meant we could isolate variables and prove fixes definitively AI Vision + Code Understanding: The AI could correlate visual output with code changes by reading Wokwi screenshots Fast Iteration: ~2 minutes per cycle (build + simulate + analyze) vs. hours with physical hardware Professional Development Environment: Wokwi\u0026rsquo;s VS Code and CLion integration meant we could debug just like with physical hardware Limitations We Hit # Screenshot Timing: Had to carefully time captures to match test sequence (red at 2.7s, green at 3.9s, etc.). The alternative approach is to use Wokwi Scenario files, which allows triggering screenshot based on the log message Endianness Assumptions: Even AI made wrong guesses about byte order initially, requiring multiple iterations Lessons for Embedded Development # 1. Simulation-First Development with Wokwi # Don\u0026rsquo;t wait until hardware is available. Wokwi provides a simulated of MCUs:\nScreenshot capture for visual debugging - essential for graphics bugs Integrated debugger with breakpoints and variable inspection IDE integration with VSCode and CLion for professional workflows Test display output without physical devices Capture exact visual state for comparison and regression testing CI/CD integration for automated visual testing 2. AI as Debugging Partner # The AI helped in ways that went beyond code completion:\nPattern recognition: Spotted vertical stripes → byte alignment issues Cross-reference: Connected pixel values to RGB565 bit packing Hypothesis testing: Proposed specific code changes to test theories Visual verification: Confirmed fixes by reading screenshots 3. Structured Debugging Workflow # The key was having a repeatable process:\nObserve → Hypothesize → Code → Build → Simulate → Capture → Verify → Repeat Each step was automated or AI-assisted, keeping developer focus on problem-solving. Wokwi\u0026rsquo;s screenshot capability was the key enabler - without it, we\u0026rsquo;d need physical hardware and manual camera captures for each test.\nThe Complete Solution # The final fix involved three key changes:\n// 1. Direct framebuffer access (no conversion) extern void *swGetColorBuffer(int *w, int *h); uint16_t *sw_framebuffer = (uint16_t *)swGetColorBuffer(\u0026amp;sw_width, \u0026amp;sw_height); // 2. Direct memory copy (RGB565 → RGB565) memcpy(framebuffer, sw_framebuffer, screen_width * screen_height * sizeof(uint16_t)); // 3. Byte swap for SPI LCD endianness for (int i = 0; i \u0026lt; total_pixels; i++) { uint16_t pixel = framebuffer[i]; framebuffer[i] = (pixel \u0026gt;\u0026gt; 8) | (pixel \u0026lt;\u0026lt; 8); } CI/CD Integration # Once the fix was validated, we automated the visual testing:\n# .github/workflows/test-example.yml - name: Simulate \u0026amp; take a screenshot run: | wokwi-cli \\ --screenshot-part \u0026#34;esp\u0026#34; \\ --screenshot-time 5000 \\ --screenshot-file \u0026#34;screenshot-${{ matrix.board }}.png\u0026#34; \\ \u0026#34;raylib/examples/hello/boards/${{ matrix.board }}\u0026#34; - name: Flip screenshot vertically run: | convert \u0026#34;screenshot-${{ matrix.board }}.png\u0026#34; -flip \u0026#34;screenshot-${{ matrix.board }}.png\u0026#34; - name: Upload Screenshot uses: actions/upload-artifact@v4 with: name: screenshot-${{ matrix.board }} path: screenshot-${{ matrix.board }}.png Now every commit produces screenshots showing correct color rendering across all supported boards.\n▶️ Run online Wokwi ESP32-S3-BOX-3 (320x240)\nNote: The time based approach might not be suitable for all the cases. Wokwi can watch for keyword in the log message to trigger screenshot:\nsteps: - wait-serial: \u0026#39;Display initialized\u0026#39; - wait-serial: \u0026#39;Counter: 0\u0026#39; - take-screenshot: part-id: \u0026#39;lcd\u0026#39; compare-with: \u0026#39;screenshots/counter-0.png\u0026#39; Conclusion # The combination of Wokwi simulation and AI-assisted debugging created a powerful workflow for solving a subtle embedded graphics bug. What traditionally might take days of trial-and-error with physical hardware was resolved in an afternoon through:\nVisual verification via Wokwi screenshots AI code analysis connecting visual symptoms to root causes Rapid iteration without physical hardware constraints Automated regression testing via CI/CD This approach isn\u0026rsquo;t limited to graphics - any embedded system with visual, audio, or sensor output that can be simulated could benefit from this debugging methodology.\nYou can test the final result in web browser or flash it to ESP32-S3-BOX-3 using ESP-Launchpad.\n▶️ Run online Wokwi ESP32-S3-BOX-3 (320x240)\nResources # Wokwi - ESP32 hardware simulator with CI/CD support Wokwi for VS Code Wokwi for CLion Warp - AI-powered terminal and development environment Raylib - Simple and easy-to-use programming library Raylib ESP-IDF Component Component Registry with Raylib ESP-IDF Component Component Registry with Raylib Port ESP-IDF Component Flash Raylib Hello example with ESP-Launchpad ","date":"24 October 2025","externalUrl":null,"permalink":"/blog/2025/10/debugging-embedded-graphics-with-wokwi-and-ai/","section":"Blog","summary":"Learn how Wokwi simulation and AI-assisted debugging solved a subtle RGB565 color mapping bug when porting Raylib to ESP32, turning hours of hardware debugging into an efficient iterative workflow with automated visual testing.","title":"Debugging Embedded Graphics with Wokwi and AI: Solving a Raylib Color Mapping on ESP32","type":"blog"},{"content":"","date":"24 October 2025","externalUrl":null,"permalink":"/authors/juraj-michalek/","section":"Developer Portal Authors","summary":"","title":"Juraj Michálek","type":"authors"},{"content":"","date":"24 October 2025","externalUrl":null,"permalink":"/tags/wokwi/","section":"Tags","summary":"","title":"Wokwi","type":"tags"},{"content":"","date":"20 October 2025","externalUrl":null,"permalink":"/tags/esp32c3/","section":"Tags","summary":"","title":"Esp32c3","type":"tags"},{"content":" Introduction # When developing with ESP-IDF, you may eventually need functionality that isn’t provided by its built-in components. In many cases, the solution is an open-source library from GitHub or another repository. However, these external libraries are not always structured for ESP-IDF, and simply copying their source files into your project can lead to messy integrations, difficult updates, and code that’s hard to reuse or share.\nA cleaner and more maintainable approach is to wrap the external library into a reusable ESP-IDF component. Components integrate naturally with the ESP-IDF build system, can be reused across multiple projects, and make sharing and maintaining code much easier. They also help keep your project organized and scalable over time.\nIn this article, we’ll demonstrate this approach by porting the tinyexpr library into a fully functional ESP-IDF component, ready for reuse in future applications. To keep things simple, we’ll start by manually adding the library’s source and header files into a new component structure. In a future article, we’ll extend this setup by adding the library as a git submodule, making it easier to stay synchronized with the upstream repository as new features or bug fixes are released.\nWe’ll be using an ESP32-C3-DevKitM-1 board and the ESP-IDF Extension for VS Code, though the same steps apply to other boards and SoCs.\nPrepare to create a component # To keep things straightforward, we will work with a self-contained library that does not rely on specific peripherals. A good example of such a library is tinyexpr, which we will use throughout this article.\nIntegrating an external library as an ESP-IDF component involves several steps:\nObtain library code Set up a test project in ESP-IDF Test the component Solve compatibility issues These are the steps we will follow in the rest of the article.\nObtain library code # The tinyexpr code is available on GitHub:\ncodeplea/tinyexpr tiny recursive descent expression parser, compiler, and evaluation engine for math expressions C 1874 295 We can clone the repository to inspect the files:\ngit clone https://github.com/codeplea/tinyexpr.git Although the repository contains several source files, the library itself consists of just two key files, as noted in the README:\ntinyexpr.h tinyexpr.c There are also several examples in the repo, showing how to use the library. The simplest one is example.c, so it\u0026rsquo;s a good idea to use it to test our component.\nSet up a test project in ESP-IDF # To work on the porting, we need to\nCreate a new project Create a new component Create a new project # To keep things simple and organized, we will start with a basic project using a template app. You can follow one of the two approaches below:\nESP-IDF Extension for VS Code New Project Clone basic example In VS Code command palette enter: \u0026gt; ESP-IDF: New Project You will be presented with a screen like Fig.1.\nFig.1 - Choosing the project settings\nIf you\u0026rsquo;re using the ESP32-C3-DevKitM, fill the fields as follows:\nProject name: esp_tinyexpr_test Choose ESP-IDF Target: esp32c3 Choose ESP-IDF Board: ESP32-C3 chip (via builtin USB-JTAG) Choose serial port: (e.g. COM25 or /dev/tty.usbserial-11133) Feel free to change the settings according to your platform.\nClick on Choose Template and select template_app Open the project with VS Code You should now have the following project structure:\n. ├── CMakeLists.txt ├── main │ ├── CMakeLists.txt │ └── main.c └── README.md Download the basic example code found on this github repo. Open the project with VSCode \u0026gt; ESP-IDF: Set Espressif Device target \u0026gt; ESP-IDF: Select Port to Use Create a new component # Next, we will create a new component named my_tinyexpr to hold the tinyexpr files.\nSelect \u0026gt; ESP-IDF: Create New ESP-IDF Component\nName it my_tinyexpr Your project structure now looks like this.\n. ├── CMakeLists.txt ├── components │ └── my_tinyexpr │ ├── CMakeLists.txt │ ├── include │ │ └── my_tinyexpr.h │ └── my_tinyexpr.c ├── main │ ├── CMakeLists.txt │ └── main.c ├── README.md ├── sdkconfig └── sdkconfig.old Replace my_tinyexpr.c with the downloaded tinyexpr.c Replace my_tinyexpr.h with the downloaded tinyexpr.h Since the filenames differ from the default, update the component\u0026rsquo;s CMakeLists.txt to register the correct source file:\nidf_component_register(SRCS \u0026#34;tinyexpr.c\u0026#34; INCLUDE_DIRS \u0026#34;include\u0026#34;) The build system automatically includes all files in the include directory, so no additional configuration is needed to locate tinyexpr.h. Now that we’ve created the new component, it’s time to test it.\nTest the component # To test the component we need to\nInform the build system about the new component Include the header file Call the function of the library Inform the build system about the new component # In the CMakeLists.txt of the __main__ component, add REQUIRES \u0026quot;my_tinyexpr\u0026quot; to let the build system know about the new component:\nidf_component_register(SRCS \u0026#34;main.c\u0026#34; REQUIRES \u0026#34;my_tinyexpr\u0026#34; INCLUDE_DIRS \u0026#34;.\u0026#34;) This ensures that the build system includes my_tinyexpr when compiling your project.\nInclude the header file # In your main file, include the header from the tinyexpr library:\n#include \u0026#34;tinyexpr.h\u0026#34; In general, a component’s header file does not need to match its name, and this applies broadly across ESP-IDF projects. Call a function of the library # In the tinyexpr repository, there is an example.c file that demonstrates how to use the library.\nCopy the relevant portions of example.c into your main.c file. Your app_main function should now look like this:\n#include \u0026lt;stdio.h\u0026gt; #include \u0026#34;tinyexpr.h\u0026#34; void app_main(void) { const char *c = \u0026#34;sqrt(5^2+7^2+11^2+(8-2)^2)\u0026#34;; double r = te_interp(c, 0); printf(\u0026#34;The expression:\\n\\t%s\\nevaluates to:\\n\\t%f\\n\u0026#34;, c, r); } Next, build, flash, and monitor the project:\nESP-IDF: Build, Flash and Start a Monitor on Your Device And we got and error!\nIn file included from \u0026lt;PATH\u0026gt;/tutorial-porting-tinyexpr/components/my_tinyexpr/tinyexpr.c:43: \u0026lt;PATH\u0026gt;/tutorial-porting-tinyexpr/components/my_tinyexpr/tinyexpr.c: In function \u0026#39;next_token\u0026#39;: \u0026lt;PATH\u0026gt;/tutorial-porting-tinyexpr/components/my_tinyexpr/tinyexpr.c:255:32: error: array subscript has type \u0026#39;char\u0026#39; [-Werror=char-subscripts] 255 | if (isalpha(s-\u0026gt;next[0])) { | ~~~~~~~^~~ \u0026lt;PATH\u0026gt;/tutorial-porting-tinyexpr/components/my_tinyexpr/tinyexpr.c:258:39: error: array subscript has type \u0026#39;char\u0026#39; [-Werror=char-subscripts] 258 | while (isalpha(s-\u0026gt;next[0]) || isdigit(s-\u0026gt;next[0]) || (s-\u0026gt;next[0] == \u0026#39;_\u0026#39;)) s-\u0026gt;next++; | ~~~~~~~^~~ \u0026lt;PATH\u0026gt;/tutorial-porting-tinyexpr/components/my_tinyexpr/tinyexpr.c:258:62: error: array subscript has type \u0026#39;char\u0026#39; [-Werror=char-subscripts] 258 | while (isalpha(s-\u0026gt;next[0]) || isdigit(s-\u0026gt;next[0]) || (s-\u0026gt;next[0] == \u0026#39;_\u0026#39;)) s-\u0026gt;next++; | ~~~~~~~^~~ cc1: some warnings being treated as errors ninja: build stopped: subcommand failed. There is a compatibility issue. Although the library you found is written in C and appears to work, compiler settings or library dependencies could still cause problems. Let’s investigate what is preventing the compilation.\nSolve compatibility issues # The error is in the following code.\nif (isalpha(s-\u0026gt;next[0])) { ... } while (isalpha(s-\u0026gt;next[0]) || isdigit(s-\u0026gt;next[0]) || (s-\u0026gt;next[0] == \u0026#39;_\u0026#39;)) s-\u0026gt;next++; It happens because a char is directly passed to isalpha() and isdigit(). On many platforms, char is signed, and these functions expect an int in the range of unsigned char (or EOF). Passing a signed char can trigger warnings or undefined behavior.\nESP-IDF uses very strict compilation flags and treats all warnings as errors (-Werror), which is why these warnings stop the build.\nSo we have two options, changing the code or changing the compilation flag.\nModifying the code of an external library is not recommended, as it makes it harder to keep your version synchronized with the official release and to apply future updates or bug fixes. Changing the code # A fast way to fix it is to cast the character to unsigned char:\nif (isalpha((unsigned char)s-\u0026gt;next[0])) { ... } while (isalpha((unsigned char)s-\u0026gt;next[0]) || isdigit((unsigned char)s-\u0026gt;next[0]) || (s-\u0026gt;next[0] == \u0026#39;_\u0026#39;)) s-\u0026gt;next++; Now we can build, flash, and monitor the project again.\nESP-IDF: Build, Flash and Start a Monitor on Your Device And we get the expected output.\nThe expression: sqrt(5^2+7^2+11^2+(8-2)^2) evaluates to: 15.198684 Changing the compilation flag # Alternatively, the issue can be resolved by adjusting the compilation flags instead of modifying the source code. Since the error originates from -Werror=char-subscripts, we can suppress it by adding the following line to the CMakeLists.txt file of your component:\ntarget_compile_options(${COMPONENT_LIB} PRIVATE -Wno-char-subscripts) This approach is often preferable when working with external libraries, as it allows you to keep the original source code intact. It also makes it easier to manage updates: if the library is included as a git submodule, any future improvements or security fixes can be applied by simply updating the submodule, without the need to reapply code changes.\nNow that we’ve covered the basics of creating a component and resolving common compatibility issues, the next article will build on this foundation. You’ll see how to import a component as a git submodule, integrate it into multiple projects, and share it with the community. This workflow not only helps keep your code organized and maintainable but also ensures that updates and improvements can be easily propagated across projects without modifying the original source.\nConclusion # In this article, we demonstrated how to take an existing open source library and integrate it into an ESP-IDF project as a reusable component. We located the tinyexpr library, created a new ESP-IDF project, built a dedicated component for the library, resolved compatibility details, and verified its functionality on an ESP32-C3-DevkitM-1 board. By packaging the library as a component rather than copying source files directly, we ensured cleaner integration, easier maintenance, and effortless reuse in future projects.\n","date":"20 October 2025","externalUrl":null,"permalink":"/blog/2025/10/porting-external-library-as-component/","section":"Blog","summary":"This article shows how to port an external library into an ESP-IDF project by converting it into a reusable component. Using tinyexpr as an example, it covers obtaining the source code, creating a new project, building a component, configuring the build system, and testing on hardware.","title":"Porting a library to an ESP-IDF component","type":"blog"},{"content":"","date":"17 October 2025","externalUrl":null,"permalink":"/tags/browser/","section":"Tags","summary":"","title":"Browser","type":"tags"},{"content":"","date":"17 October 2025","externalUrl":null,"permalink":"/authors/daniel-paul/","section":"Developer Portal Authors","summary":"","title":"Daniel Paul","type":"authors"},{"content":"","date":"17 October 2025","externalUrl":null,"permalink":"/tags/jupyter/","section":"Tags","summary":"","title":"Jupyter","type":"tags"},{"content":"","date":"17 October 2025","externalUrl":null,"permalink":"/tags/micropython/","section":"Tags","summary":"","title":"MicroPython","type":"tags"},{"content":"Welcome to the workshop on MicroPython Jupyter Notebooks in the browser! In this session, you will see how modern web technologies enable direct hardware programming without the need to install local development tools. You\u0026rsquo;ll learn how to flash firmware, execute code interactively, and build IoT applications using only a browser and a USB connection.\nAbout the workshop # This workshop covers both basic and advanced MicroPython programming for ESP32-C3-DevKit-RUST-2 development board through hands-on assignments:\nSetup - Flash MicroPython firmware and understand the development environment Assignment 1: Blink \u0026ndash; Control addressable LED Assignment 2: Button Input \u0026ndash; Read button presses and create interactive responses Assignment 3: ESP-NOW Communication \u0026ndash; Implement wireless Morse code communication between two ESP32-C3-DevKit-RUST-2 development boards Assignment 4: IMU Sensor and MQTT Communication \u0026ndash; Read orientation data from an IMU and publish it to MQTT broker Prerequisites # Hardware # A computer running Windows, macOS or Linux ESP32-C3-DevKit-RUST-2 board (Provided by us) USB-C cable (data + power) compatible with the board Software # Chromium-based browser (Google Chrome, Microsoft Edge, Opera, Brave, Vivaldi) Mosquitto client (Optional) Effort # Estimated time: 120 min Workshop # Without further ado, let\u0026rsquo;s dive into the exciting world of ESP microcontrollers and MicroPython! Please follow along as we explore the capabilities of this powerful platform.\nIntroduction and Setup Assignment 1 - Blink Assignment 2 - Button Input Assignment 3 - ESP-NOW Communication Assignment 4 - IMU Sensor and MQTT Communication Conclusion # You\u0026rsquo;ve learned to program ESP32-C3-DevKit-RUST-2 development board using browser-based Jupyter notebooks, covering:\nMicroPython firmware flashing and interactive development GPIO control for LEDs and button input ESP-NOW wireless communication protocol IMU sensor data acquisition and processing MQTT protocol for IoT messaging These skills form the foundation for building sophisticated IoT applications. The browser-based approach eliminates toolchain complexity while maintaining full access to MicroPython\u0026rsquo;s capabilities.\nFAQ # I have been prompted to select a kernel in Jupyter Notebook. Which one should I use? Select Embedded Kernel. How do I connect my device to the Jupyter notebook? Click on the ESP Control Panel, click Connect and select your device. Which of the devices is my ESP board? The ESP board usually appears as USB JTAG. I cannot connect to a different Jupyter notebook. Disconnect from the previous notebook and connect the new one. The notebook isn’t running my code, what should I do In the ESP Control Panel, click Disconnect device, then reopen the notebook and connect again. ","date":"17 October 2025","externalUrl":null,"permalink":"/workshops/micropython-jupyter-notebooks-in-browser/","section":"Workshops","summary":"In this workshop, you will learn how to program Espressif SoCs directly in your browser using MicroPython and Jupyter notebooks. We will primarily be using ESP32-C3-DevKit-RUST-2 development board. In the process, we will cover LED control, wireless communication, sensors, and MQTT.","title":"MicroPython Jupyter Notebooks in the Browser with ESP32-C3-DevKit-RUST-2","type":"workshops"},{"content":"","date":"17 October 2025","externalUrl":null,"permalink":"/series/","section":"Series","summary":"","title":"Series","type":"series"},{"content":"","date":"17 October 2025","externalUrl":null,"permalink":"/tags/workshop/","section":"Tags","summary":"","title":"Workshop","type":"tags"},{"content":"","date":"17 October 2025","externalUrl":null,"permalink":"/series/ws00m/","section":"Series","summary":"","title":"WS00M","type":"series"},{"content":"In this assignment you will initialize and control the onboard addressable LED in three different ways.\nUnderstanding addressable LEDs # WS2812 are individually addressable RGB LEDs. Each LED can display any color by mixing red, green, and blue values (0-255 each). The ESP32-C3-DevKit-RUST-2 board has one addressable LED on GPIO 2.\nWork through the following tasks in your Assignment 1 Jupyter notebook:\nTask 1: Initialize the addressable LED # In this task, you’ll set up the addressable LED so your code can communicate with it. The neopixel.NeoPixel(machine.Pin(2), 1) line tells the chip which pin the LED is connected to (GPIO 2) and how many LEDs are being controlled (1 in this case).\nneopixel_led = neopixel.NeoPixel(machine.Pin(2), 1) Task 2: Set the Solid Colors # Here, you’ll write helper functions to change the LED’s color. The set_color() function lets you set any RGB color by adjusting red, green, and blue brightness values from 0–255. The clear_led() function turns the LED off. You’ll then test the LED by cycling through a few example colors.\ndef set_color(r, g, b): \u0026#34;\u0026#34;\u0026#34;Set the addressable LED to a specific RGB color\u0026#34;\u0026#34;\u0026#34; neopixel_led[0] = (r, g, b) neopixel_led.write() def clear_led(): \u0026#34;\u0026#34;\u0026#34;Turn off the LED\u0026#34;\u0026#34;\u0026#34; set_color(0, 0, 0) # Try different colors set_color(255, 0, 0) # Red time.sleep(1) set_color(0, 255, 0) # Green time.sleep(1) set_color(0, 0, 255) # Blue time.sleep(1) set_color(255, 255, 0) # Yellow time.sleep(1) clear_led() Task 3: Rainbow cycle effect # This task adds a simple animation. You’ll create a rainbow_cycle() function that loops through a list of predefined colors — red, orange, yellow, green, blue, indigo, and violet — so the LED smoothly transitions through the rainbow spectrum.\ndef rainbow_cycle(): \u0026#34;\u0026#34;\u0026#34;Cycle through rainbow colors\u0026#34;\u0026#34;\u0026#34; colors = [ (255, 0, 0), # Red (255, 127, 0), # Orange (255, 255, 0), # Yellow (0, 255, 0), # Green (0, 0, 255), # Blue (75, 0, 130), # Indigo (148, 0, 211) # Violet ] for color in colors: set_color(*color) time.sleep(0.3) clear_led() rainbow_cycle() Task 4: Breathing Effect # Now you’ll create a more dynamic lighting effect. The breathing_effect() function gradually fades the LED in and out using brightness scaling, giving a “breathing” glow. You can adjust the color, duration, and smoothness by changing the parameters.\ndef breathing_effect(r, g, b, duration=2, steps=50): \u0026#34;\u0026#34;\u0026#34; Create a breathing effect with the specified color \u0026#34;\u0026#34;\u0026#34; step_delay = duration / (steps * 2) # Fade in for i in range(steps): brightness = i / steps set_color(int(r * brightness), int(g * brightness), int(b * brightness)) time.sleep(step_delay) # Fade out for i in range(steps, 0, -1): brightness = i / steps set_color(int(r * brightness), int(g * brightness), int(b * brightness)) time.sleep(step_delay) clear_led() breathing_effect(0, 100, 255) Next step # Click on the ESP Control Panel and Disconnect device the device from the Jupyter notebook. Next step: Assignment 2.\n","date":"17 October 2025","externalUrl":null,"permalink":"/workshops/micropython-jupyter-notebooks-in-browser/assignment-1/","section":"Workshops","summary":"","title":"Assignment 1: Blink - Control the addressable LED","type":"workshops"},{"content":"Navigate to workshops/2025-10-17 directory and open Assignment 2 in the MicroPython Jupyter Notebook browser interface.\nIf prompted with selecting kernel, select Embedded Kernel, click on the ESP Control Panel and connect your device.\nIn this assignment, you will learn to read button inputs and generate interactive responses with LEDs.\nYou will be configuring a boot button located on Pin 9. Understanding Pull-up Resistors # On the ESP32-C3-DevKit-RUST-2 board, pressing the boot button connects pin 9 to ground. When the button is not pressed, the pin is left floating, which leads to an undefined logic level. Pull-up resistors ensure that the pin maintains a defined logic high level when the button is released.\nIn summary:\nButton not pressed: GPIO reads HIGH (1) thanks to pull-up resistor. Button pressed: GPIO reads LOW (0) because the pin is connected to ground. The ESP32-C3-DevKit-RUST-2 has internal pull-up resistors that can be enabled in software.\nTask 1: Configure button # In this task, you’ll initialize the onboard button so your program can read its state. The pin is configured as an input (machine.Pin.IN) with an internal pull-up resistor (machine.Pin.PULL_UP).\nbutton = machine.Pin(9, machine.Pin.IN, machine.Pin.PULL_UP) Task 2: Simple Button Press Detection # Here you’ll write a function that waits until the button is pressed. The loop continuously checks the pin’s value — when it changes from HIGH to LOW, the program detects a press and prints a message.\ndef wait_for_button_press(): \u0026#34;\u0026#34;\u0026#34;Wait until button is pressed\u0026#34;\u0026#34;\u0026#34; while button.value() == 1: time.sleep(0.05) print(\u0026#34;Button pressed!\u0026#34;) Now you’ll make the LED respond to button input. Each time the button is pressed, the LED toggles between ON and OFF. A small delay is added to handle “debouncing” — preventing multiple rapid triggers from one press.\n“Bouncing” happens when you press a button and instead of sending a single clean signal, it wiggles a little and makes the system think you pressed it many times really fast. Debouncing is just a way to make the system listen to only one press, no matter how wobbly the button is.” Task 3: Toggle LED on Button Press # led_state = False while True: if button.value() == 0: # Button pressed led_state = not led_state if led_state: set_color(255, 0, 0) else: clear_led() # Wait for button release (debounce) while button.value() == 0: time.sleep(0.05) time.sleep(0.1) # Additional debounce delay Task 4: Measure Press duration # In this task, you’ll measure how long the button is held down. The program records the start time when pressed and calculates the total duration once released.\ndef measure_press_duration(): \u0026#34;\u0026#34;\u0026#34;Measure how long the button is held down\u0026#34;\u0026#34;\u0026#34; start = time.ticks_ms() while button.value() == 0: time.sleep(0.05) duration = time.ticks_diff(time.ticks_ms(), start) / 1000.0 return duration wait_for_button_press() duration = measure_press_duration() print(f\u0026#34;Button held for {duration:.2f} seconds\u0026#34;) Bonus Challenge # Create a visual feedback based on duration.\nChange LED color based on how long the button is pressed:\nShort press (\u0026lt; 1s): Blue Medium press (1-3s): Yellow Long press (\u0026gt; 3s): Red Next step # Click on the ESP Control Panel and Disconnect device the device from the Jupyter notebook. Next step: Assignment 3.\n","date":"17 October 2025","externalUrl":null,"permalink":"/workshops/micropython-jupyter-notebooks-in-browser/assignment-2/","section":"Workshops","summary":"","title":"Assignment 2: Button Input","type":"workshops"},{"content":"In this assignment, you will implement wireless Morse code communication between two ESP32-C3-DevKit-RUST-2 development boards using ESP-NOW protocol.\nYou’ll need to work with a partner: one of you will implement the Sender and the other will implement the Receiver.\nUnderstanding ESP-NOW # ESP-NOW is a connectionless communication protocol developed by Espressif that enables direct, low-power communication between ESP devices (ESP8266, ESP32, ESP32-S and ESP32-C series of SoCs) without requiring Wi-Fi router infrastructure. Key features:\nLow latency: ~10ms typical No router required: Direct device-to-device communication Long range: Up to 200m line-of-sight (depending on environment) Multiple peers: Can communicate with up to 20 peers Project Morse Code Sender and Receiver # You\u0026rsquo;ll build one of two devices: a sender that transmits Morse code or a receiver that displays the Morse code on an LED.\nMorse Code Timing:\nDot: Short press (\u0026lt; 0.3 seconds) Dash: Long press (≥ 0.3 seconds) Pick one of the following roles and proceed with your assignment:\nSender: Assignment 3 - Sender. Receiver: Assignment 3 - Receiver. ","date":"17 October 2025","externalUrl":null,"permalink":"/workshops/micropython-jupyter-notebooks-in-browser/assignment-3/","section":"Workshops","summary":"","title":"Assignment 3: ESP-NOW Communication","type":"workshops"},{"content":"Navigate to workshops/2025-10-17 directory and open Assignment 3 - Receiver in the MicroPython Jupyter Notebook browser interface.\nIf prompted with selecting kernel, select Embedded Kernel, click on the ESP Control Panel and connect your device.\nIn this assignment, you will be to receive Morse code sent by the sender and display it on an LED. To do this, you will need to initialize the ESP-NOW communication protocol and set up a callback function to handle incoming messages. The sender will need your MAC address to send the Morse code. You can obtain it by initializing your station interface and running print(sta.config('mac')) (see Task 1)\nTask 1: Initialize Receiver # In this task, you’ll set up the chip as a Wi-Fi station and retrieve its MAC address. This MAC address will be used by the sender device to target your board when sending data.\n# Setup Wi-Fi and ESP-NOW sta = network.WLAN(network.STA_IF) sta.active(True) # Get and print MAC address print(\u0026#34;My MAC address:\u0026#34;, sta.config(\u0026#39;mac\u0026#39;)) Task 2: Initialize addressable LED # Here you’ll set up the addressable LED to visualize incoming Morse code signals.\n# Setup addressable LED neopixel_led = neopixel.NeoPixel(machine.Pin(2), 1) Task 3: Initialize ESP-NOW # Now you’ll initialize the ESP-NOW communication protocol, which allows direct device-to-device messaging without Wi-Fi networking. You’ll also define timing constants that control how long each LED flash lasts.\n# Initialize ESP-NOW e = espnow.ESPNow() e.active(True) # Timing constants DOT_TIME = 0.2 # Green LED duration DASH_TIME = 0.6 # Red LED duration PAUSE = 0.2 # Gap after symbol Task 4: LED Display Functions # In this task, you’ll implement helper functions to show Morse code visually. Dots will flash green for a short time, dashes will flash red for longer, and each symbol will include a short pause after it.\ndef set_color(r, g, b): \u0026#34;\u0026#34;\u0026#34;Set the addressable LED to a specific RGB color\u0026#34;\u0026#34;\u0026#34; neopixel_led[0] = (r, g, b) neopixel_led.write() def clear_led(): \u0026#34;\u0026#34;\u0026#34;Turn off the addressable LED\u0026#34;\u0026#34;\u0026#34; set_color(0, 0, 0) def blink_dot(): \u0026#34;\u0026#34;\u0026#34;Display dot: green LED\u0026#34;\u0026#34;\u0026#34; set_color(0, 255, 0) time.sleep(DOT_TIME) clear_led() def blink_dash(): \u0026#34;\u0026#34;\u0026#34;Display dash: red LED\u0026#34;\u0026#34;\u0026#34; set_color(255, 0, 0) time.sleep(DASH_TIME) clear_led() def blink_morse_symbol(symbol): \u0026#34;\u0026#34;\u0026#34; Display the received Morse symbol with appropriate color and timing. Includes pause after each symbol. \u0026#34;\u0026#34;\u0026#34; if symbol == \u0026#34;.\u0026#34;: blink_dot() elif symbol == \u0026#34;-\u0026#34;: blink_dash() Task 5: Receive Morse Code # Finally, you’ll write the main loop that waits for incoming ESP-NOW messages. Each received symbol (dot or dash) is decoded, printed, and displayed on the LED.\nprint(\u0026#34;Morse Code Receiver ready...\u0026#34;) print(\u0026#34;Dot = Green LED, Dash = Red LED\u0026#34;) while True: host, msg = e.recv(0) # Non-blocking receive if msg: symbol = msg.decode() print(\u0026#34;Received:\u0026#34;, symbol) blink_morse_symbol(symbol) time.sleep(PAUSE) Bonus Challenge # Extend the receiver to decode complete Morse code letters and display them. You can use a dictionary mapping Morse patterns (e.g., \u0026ldquo;.-\u0026rdquo; → \u0026ldquo;A\u0026rdquo;) to actual text output.\nNext step # Click on the ESP Control Panel and Disconnect device the device from the Jupyter notebook. Next step: Assignment 4.\n","date":"17 October 2025","externalUrl":null,"permalink":"/workshops/micropython-jupyter-notebooks-in-browser/assignment-3-receiver/","section":"Workshops","summary":"","title":"Assignment 3: ESP-NOW Communication - Receiver","type":"workshops"},{"content":"Navigate to workshops/2025-10-17 directory and open Assignment 3 - Sender in the MicroPython Jupyter Notebook browser interface.\nIf prompted with selecting kernel, select Embedded Kernel, click on the ESP Control Panel and connect your device.\nIn this assignment, you will send Morse code to the receiver based on the length of the button presses. Ask your partner for their MAC address and replace \u0026lt;MAC_ADDRESS\u0026gt; with it in your code. They can get this information by initializing station interface and running print(sta.config('mac')) (see here)\nTask 1: Initialize ESP-NOW # Set up your ESP32 as a Wi-Fi station and initialize ESP-NOW communication. Add your partner’s MAC address as a peer so you can send Morse code directly to their board.\n# Create Wi-Fi station interface sta = network.WLAN(network.STA_IF) sta.active(True) # Initialize ESP-NOW e = espnow.ESPNow() e.active(True) # MAC address of receiver (replace \u0026lt;MAC_ADDRESS\u0026gt; receiver\u0026#39;s MAC!) peer_mac = b\u0026#39;\u0026lt;MAC_ADDRESS\u0026gt;\u0026#39; # Try to delete any existing peer try: e.del_peer(peer_mac) except OSError: pass e.add_peer(peer_mac) Task 2: Implement Morse Detection # Here you’ll configure the button and define functions to detect how long it’s pressed. Short presses will be interpreted as dots, long presses as dashes. Debouncing ensures that tiny accidental presses are ignored.\n# Button configuration button = machine.Pin(9, machine.Pin.IN, machine.Pin.PULL_UP) DOT_THRESHOLD = 0.3 # seconds DEBOUNCE = 0.05 def wait_for_button_press(): \u0026#34;\u0026#34;\u0026#34;Wait until button is pressed\u0026#34;\u0026#34;\u0026#34; while button.value() == 1: time.sleep(0.05) def measure_press_duration(): \u0026#34;\u0026#34;\u0026#34;Measure how long the button is held down\u0026#34;\u0026#34;\u0026#34; start = time.ticks_ms() while button.value() == 0: time.sleep(0.05) duration = time.ticks_diff(time.ticks_ms(), start) / 1000.0 return duration def determine_morse_symbol(duration): \u0026#34;\u0026#34;\u0026#34;Determine if press was dot or dash\u0026#34;\u0026#34;\u0026#34; if duration \u0026lt; DEBOUNCE: return None symbol = \u0026#39;.\u0026#39; if duration \u0026lt; DOT_THRESHOLD else \u0026#39;-\u0026#39; return symbol def send_morse_symbol(symbol): \u0026#34;\u0026#34;\u0026#34;Send morse symbol via ESP-NOW\u0026#34;\u0026#34;\u0026#34; print(\u0026#34;Sending:\u0026#34;, symbol) e.send(peer_mac, symbol.encode()) Finally, you’ll write the main loop that waits for button presses, detects the duration, determines the Morse symbol, and sends it to the receiver. The program prints each symbol for confirmation.\nTask 3: Send Morse Symbols # print(\u0026#34;Morse Code Sender Ready!\u0026#34;) print(\u0026#34;Press button: short = dot (.), long = dash (-)\u0026#34;) print(\u0026#34;Press the stop button on the toolbar to terminate the while loop.\u0026#34;) while True: # Wait for button press wait_for_button_press() # Measure duration duration = measure_press_duration() # Determine symbol symbol = determine_morse_symbol(duration) if symbol: # Send symbol via ESP-NOW send_morse_symbol(symbol) Next step # Click on the ESP Control Panel and Disconnect device the device from the Jupyter notebook. Next step: Assignment 4.\n","date":"17 October 2025","externalUrl":null,"permalink":"/workshops/micropython-jupyter-notebooks-in-browser/assignment-3-sender/","section":"Workshops","summary":"","title":"Assignment 3: ESP-NOW Communication - Sender","type":"workshops"},{"content":"Navigate to workshops/2025-10-17 directory and open Assignment 4 in the MicroPython Jupyter Notebook browser interface.\nIf prompted with selecting kernel, select Embedded Kernel, click on the ESP Control Panel and connect your device.\nIn this assignment you will read orientation data from an ICM42670 IMU sensor and publish it to an MQTT broker.\nUnderstanding IMU Sensors # An Inertial Measurement Unit (IMU) combines:\nAccelerometer: Measures linear acceleration (including gravity) Gyroscope: Measures rotational velocity Temperature sensor: Measures device temperature The ICM42670 is a 6-axis IMU (3-axis accelerometer + 3-axis gyroscope).\nFor more information about IMU sensors, visit the wiki page.\nUnderstanding MQTT # MQTT (Message Queuing Telemetry Transport) is a lightweight publish-subscribe messaging protocol ideal for IoT:\nBroker: Central server that routes messages Topics: Hierarchical message channels (e.g., sensors/imu/orientation) QoS: Quality of Service levels (0, 1, or 2) For more information about MQTT, visit the wiki page.\nSubscribing to MQTT Topic # To subscribe to a topic, you will have two options:\nHiveMQ Online MQTT Client # Navigate to HiveMQ and connect to the broker test.mosquitto.org on port 8081. Under Subscriptions click on the Add New Topic Subscription, enter esp32/orientation and click on Subscribe Mosquitto Client # Subscribe to the topic: On Linux or MacOS run command mosquitto_sub -h test.mosquitto.org -t \u0026quot;esp32/orientation\u0026quot; in your terminal to subscribe to the topic On Windows you will need to add mosquitto to your PATH environment variable or navigate to the path where the executable is located (usually C:\\Program Files\\mosquitto\\) and run mosquitto_sub.exe -h test.mosquitto.org -t \u0026quot;esp32/orientation\u0026quot; Task 1: Connect to Wi-Fi # In this task, you’ll connect the ESP32 to your Wi-Fi network so it can communicate with the MQTT broker. The code waits until the connection is established and prints the network configuration.\nSSID = \u0026#34;\u0026lt;WIFI_NAME\u0026gt;\u0026#34; PASSWORD = \u0026#34;\u0026lt;WIFI_PASSWORD\u0026gt;\u0026#34; sta = network.WLAN(network.STA_IF) sta.active(True) sta.connect(SSID, PASSWORD) while not sta.isconnected(): time.sleep(1) print(\u0026#34;Connecting to Wi-Fi...\u0026#34;) print(\u0026#34;Connected to Wi-Fi\u0026#34;) print(f\u0026#34;Network config: {sta.ifconfig()}\u0026#34;) Task 2: Initialize MQTT # Here you’ll create an MQTT client and connect it to a broker. You’ll publish orientation messages to the topic \u0026ldquo;esp32/orientation\u0026rdquo;.\nBROKER = \u0026#34;test.mosquitto.org\u0026#34; TOPIC = b\u0026#34;esp32/orientation\u0026#34; client = MQTTClient(\u0026#34;esp32client\u0026#34;, BROKER) client.connect() print(\u0026#34;Connected to MQTT broker\u0026#34;) Task 3: Initialize IMU # In this task, you’ll set up the ICM42670 IMU over I2C. You’ll configure the accelerometer and gyroscope full-scale range, data rate, and power mode for accurate measurements.\ni2c = I2C(0, scl=Pin(8), sda=Pin(7), freq=400000) # Create IMU instance imu = ICM42670(i2c) # Configure sensor imu.configure( gyro_fs=GyroFS.FS_500DPS, gyro_odr=ODR.ODR_100_HZ, accel_fs=AccelFS.FS_4G, accel_odr=ODR.ODR_100_HZ ) # Enable sensors imu.set_accel_power_mode(PowerMode.LOW_NOISE) imu.set_gyro_power_mode(PowerMode.LOW_NOISE) Task 4: Read Orientation and Publish # Finally, you’ll read accelerometer and gyroscope data, compute orientation using a complementary filter, interpret the device’s tilt, and publish it to MQTT. The main loop prints the orientation locally and continuously sends updates to the broker.\ndef publish_orientation(): \u0026#34;\u0026#34;\u0026#34;Read orientation and publish to MQTT\u0026#34;\u0026#34;\u0026#34; while True: # Read sensor data data = imu.get_all_data() accel = (data[\u0026#39;accel\u0026#39;][\u0026#39;x\u0026#39;], data[\u0026#39;accel\u0026#39;][\u0026#39;y\u0026#39;], data[\u0026#39;accel\u0026#39;][\u0026#39;z\u0026#39;]) gyro = (data[\u0026#39;gyro\u0026#39;][\u0026#39;x\u0026#39;], data[\u0026#39;gyro\u0026#39;][\u0026#39;y\u0026#39;], data[\u0026#39;gyro\u0026#39;][\u0026#39;z\u0026#39;]) # Calculate orientation using complementary filter angles = imu.complementary_filter(accel, gyro) roll = angles[\u0026#39;roll\u0026#39;] pitch = angles[\u0026#39;pitch\u0026#39;] # Interpret orientation if abs(pitch) \u0026lt; 20 and abs(roll) \u0026lt; 20: position = \u0026#34;Flat\u0026#34; elif pitch \u0026gt; 30: position = \u0026#34;Tilted Forward\u0026#34; elif pitch \u0026lt; -30: position = \u0026#34;Tilted Backward\u0026#34; elif roll \u0026gt; 30: position = \u0026#34;Tilted Right\u0026#34; elif roll \u0026lt; -30: position = \u0026#34;Tilted Left\u0026#34; else: position = \u0026#34;Diagonal\u0026#34; # Create message message = f\u0026#34;Roll: {roll:.1f}°, Pitch: {pitch:.1f}° -\u0026gt; {position}\u0026#34; print(message) # Publish to MQTT client.publish(TOPIC, position.encode()) time.sleep(0.5) publish_orientation() Next step # Congratulations! Proceed to the Conclusion.\n","date":"17 October 2025","externalUrl":null,"permalink":"/workshops/micropython-jupyter-notebooks-in-browser/assignment-4/","section":"Workshops","summary":"","title":"Assignment 4: IMU Sensor and MQTT Communication","type":"workshops"},{"content":" Introduction # As it has already been announced, this workshop will be using MicroPython and Jupyter Notebooks. Let\u0026rsquo;s quickly introduce them.\nMicroPython # MicroPython is a lean implementation of Python 3 optimized for microcontrollers. It provides an interactive REPL (Read-Eval-Print Loop) and supports most Python standard library features, making embedded development accessible to Python programmers.\nJupyter Notebook # Jupyter Notebook is a web-based interactive computing environment that allows you to create documents that contain live code, and narrative text. It is composed from a kernel, which is a program that executes the code, and a frontend, which is a user interface that allows you to interact with the kernel.\nThe code is composed of cells, which can be executed independently or sequentially, either by clicking on the cell and pressing the run button or using a keyboard shortcut Shift + Enter. If the code executes a while True loop, it can be interrupted by clicking on the stop button in the toolbar.\nWhy MicroPython Jupyter Notebooks in the Browser? # Traditional embedded development requires installing toolchains, IDEs, and drivers. Browser-based Jupyter notebooks eliminate this setup by leveraging the WebSerial API, which allows web applications to communicate directly with serial devices. This approach offers several advantages:\nZero installation: No local toolchain required Interactive development: Execute code cells individually and see immediate results Educational value: Clear separation of concepts into notebook cells Cross-platform: Works identically on Windows, macOS, and Linux Version control friendly: Notebooks can be easily shared and versioned How It Works # The browser connects to your ESP32-C3-DevKit-RUST-2 development board via USB using the WebSerial API. Jupyter notebooks send Python code to the MicroPython REPL running on the device. The device executes the code and returns output, which displays in the notebook interface.\nRelated documentation # MicroPython Documentation ESP32 MicroPython Guide ESP-NOW Protocol ESP-NOW in MicroPython Setup # Let\u0026rsquo;s start by flashing MicroPython firmware.\nFlashing MicroPython Firmware # Connect your ESP32-C3-DevKit-RUST-2 development board to your computer via USB cable Open MicroPython Jupyter Notebook in your chromium based browser Open the sidebar folder, navigate to workshops/2025-10-17/Assignment 1.ipynb and open the notebook When prompted with selecting kernel, select Embedded Kernel On the ESP Control Panel select Connect device and → ESP32C3 (USB JTAG) On the same ESP Control Panel select Flash Device and Flash Selected Firmware - this will flash MicroPython to your device Your device is now ready to run MicroPython code.\nNext step # Next step: Assignment 1\n","date":"17 October 2025","externalUrl":null,"permalink":"/workshops/micropython-jupyter-notebooks-in-browser/introduction-and-setup/","section":"Workshops","summary":"","title":"Introduction and Setup","type":"workshops"},{"content":"","date":"13 October 2025","externalUrl":null,"permalink":"/authors/alberto-spagnolo/","section":"Developer Portal Authors","summary":"","title":"Alberto Spagnolo","type":"authors"},{"content":"","date":"13 October 2025","externalUrl":null,"permalink":"/tags/esp32-c3/","section":"Tags","summary":"","title":"ESP32-C3","type":"tags"},{"content":"","date":"13 October 2025","externalUrl":null,"permalink":"/tags/esp32-s3/","section":"Tags","summary":"","title":"ESP32-S3","type":"tags"},{"content":" Introduction # When reading an Espressif SoC datasheet, you may have come across the acronym FPU. It often appears as just another item in the feature list, and while most of us have a vague idea that it relates to math, it is not always clear why it is actually useful.\nAs the name suggests, an FPU, or Floating Point Unit, is a part of the processor dedicated to working with floating-point numbers. These are the numbers with decimals that are essential for precise calculations in areas such as graphics, signal processing, or scientific workloads. On some CPUs, like the ESP32-S3, the FPU performs these operations directly in hardware, making them fast and efficient. On others, like the ESP32-C3, floating-point math is executed in software, which is slower but still accurate thanks to standard libraries.\nAdding to the confusion, discussions on forums and other resources often give conflicting answers about which Espressif cores include an FPU and which do not.\nTo understand why the presence or absence of an FPU matters, we first need to look at what floating-point numbers are, how they are represented in memory, and what makes their handling different from integers.\nUnderstanding floats and their computation # When you store an integer in memory, each bit directly represents the number’s value. For a 32-bit signed integer, the bits represent the magnitude using two’s complement. For example, 5 is stored as:\n00000000 00000000 00000000 00000101 and –5 as:\n11111111 11111111 11111111 11111011 Integers can exactly represent whole numbers, but they are limited in range. A 32-bit signed integer can only store values roughly between –2,147,483,648 and 2,147,483,647. For numbers outside this range, or for fractional values, integers are not sufficient.\nFloating-point numbers solve the limitations of integers by representing values in a format inspired by scientific notation: a combination of a sign, a scale (exponent) indicating magnitude, and precision digits (mantissa). This design allows numbers to span a wide range, including very large and very small values, as well as fractions.\nSingle precision, or float, uses 32 bits to balance range, precision, and memory usage, while double precision, or double, uses 64 bits to provide higher precision and an even wider range at the cost of additional memory.\nFloats are essential whenever calculations require decimal values or a wide dynamic range, enabling applications from physics simulations to financial computations.\nThe IEEE 754 standard # To ensure consistent floating-point behavior across platforms, the IEEE 754 standard defines exactly how floats are represented in memory. As mentioned, a single-precision float (float) uses 32 bits divided into three parts: a sign bit, an exponent, and a mantissa (also called the fraction).\nThe sign bit determines whether the number is positive or negative. A value of 0 indicates a positive number, while 1 indicates a negative number.\nThe exponent represents a power of two, determining the scale of the number. Positive exponents shift the value to larger numbers, while negative exponents allow representation of very small fractions. To encode both positive and negative exponents with unsigned bits, the standard uses a bias: the stored exponent equals the actual exponent plus a fixed bias (127 for single precision).\nThe mantissa encodes the significant digits of the number. In normalized numbers, there is an implicit leading 1 before the binary point, which is not stored. The remaining bits store the fractional part in binary. For instance, a mantissa of 10000000000000000000000 represents 1.5 because the leading 1 is implicit and the fractional part contributes 0.5 (1 × 2^-1). This scheme maximizes precision within the limited number of bits available.\nTo illustrate a complete float representation, consider the number 5.0 as a 32-bit float:\n01000000 01000000 00000000 00000000 Breaking it down:\nSign bit (0) → positive Exponent (10000001) → 129 in decimal, representing an actual exponent of 2 (129 – 127 bias = 2) Mantissa (01000000000000000000000) → encodes the significant digits 1.25 Putting all together:\n(–1)^sign × 1.mantissa × 2^(exponent–bias) = 5.0\nThis clearly illustrates how floating-point numbers differ from integers and why direct operations on their raw bits using a standard arithmetic logic unit (ALU) do not yield correct results.\nPerforming float calculations # On a CPU with an FPU, operations like addition, multiplication, or square root execute directly in hardware using specialized instructions, making them fast and simple.\nOn a CPU without an FPU, like the ESP32-C3, there are no native float instructions. To perform a floating-point operation, you must emulate it using integer arithmetic, carefully handling the sign, exponent, and mantissa according to the IEEE 754 standard. For example, adding two floats a and b in software involves steps like:\nExtract the sign, exponent, and mantissa from each number. Align the exponents by shifting the mantissa of the smaller number. Add or subtract the mantissas depending on the signs. Normalize the result and adjust the exponent if necessary. Pack the sign, exponent, and mantissa back into a 32-bit word. A highly simplified illustration in C-like pseudocode:\nuint32_t float_add(uint32_t a, uint32_t b) { int sign_a = a \u0026gt;\u0026gt; 31; int sign_b = b \u0026gt;\u0026gt; 31; int exp_a = (a \u0026gt;\u0026gt; 23) \u0026amp; 0xFF; int exp_b = (b \u0026gt;\u0026gt; 23) \u0026amp; 0xFF; uint32_t man_a = (a \u0026amp; 0x7FFFFF) | 0x800000; // implicit 1 uint32_t man_b = (b \u0026amp; 0x7FFFFF) | 0x800000; // align exponents if (exp_a \u0026gt; exp_b) man_b \u0026gt;\u0026gt;= (exp_a - exp_b); else man_a \u0026gt;\u0026gt;= (exp_b - exp_a); // add mantissas uint32_t man_r = (sign_a == sign_b) ? man_a + man_b : man_a - man_b; // normalize result (simplified) int exp_r = (exp_a \u0026gt; exp_b) ? exp_a : exp_b; while ((man_r \u0026amp; 0x800000) == 0) { man_r \u0026lt;\u0026lt;= 1; exp_r--; } return (sign_a \u0026lt;\u0026lt; 31) | ((exp_r \u0026amp; 0xFF) \u0026lt;\u0026lt; 23) | (man_r \u0026amp; 0x7FFFFF); } Even this simplified version is already much more work than a single FPU instruction, and handling all edge cases - overflow, underflow, NaNs (Not a Number), infinities, rounding - adds significant complexity.\nThis example illustrates why standard libraries provide dedicated routines for floating-point arithmetic. Libraries such as libc on Linux or musl include tested implementations of both low-level float operations and higher-level math functions, so developers don’t have to implement them manually. Espressif relies on newlibc.\nnewlibc # On embedded RISC-V systems like the ESP32-C3, newlibc provides the standard C library support for floating-point operations. It is structured in two layers:\nLow level libgcc High level libm At the low level, libgcc implements the primitive IEEE 754 operations in software. These routines use integer instructions and handle all the edge cases of floating-point arithmetic, including rounding, overflow, underflow, infinities, and NaNs. Typical routines include:\nArithmetic: __addsf3, __subsf3, __mulsf3, __divsf3 (single-precision), and __adddf3, __muldf3 (double-precision). Negation and absolute value: __negsf2, __abssf2. Comparisons: __eqsf2, __ltsf2, __gesf2, etc. Conversions: between integers and floats or doubles, e.g., __floatsisf, __fixsfsi, __fixunsdfsi. These helpers form the foundation for all floating-point operations on a CPU without an FPU, allowing higher-level routines to rely on them for correctness.\nAt a higher level, libm provides the familiar \u0026lt;math.h\u0026gt; functions, such as sinf, cosf, sqrtf, expf, and logf. These functions rely on the low-level helpers to perform their calculations correctly. For example, computing sqrtf(2.0f) on the ESP32-C3 is a software routine that uses iterative methods (like Newton–Raphson) together with integer arithmetic on the mantissa and exponent.\nFunctions in newlib like sinf, cosf, and sqrtf operate on single-precision floats (float), while the versions without the f suffix operate on doubles. With an FPU, these operations can be executed directly as hardware instructions, making them fast and efficient. Without an FPU, newlibc ensures that all floating-point operations and math functions behave correctly according to IEEE 754, freeing developers from having to implement complex routines themselves.\nFPU Performance and Precision in Espressif Cores # The main advantage of an FPU is speed. As we have seen earlier, floating-point arithmetic in software requires multiple integer operations to manipulate the sign, exponent, and mantissa of a number, whereas an FPU can produce the same result in a single instruction. This difference becomes especially significant in applications that involve lots of numerical computation, such as digital signal processing, machine learning, or 3D graphics.\nFPU Precision Support # Not all FPUs are created equal. Some processors include an FPU that handles only single-precision (float) operations, while others provide a more capable FPU that supports double-precision (double) operations.\nCores with a single-precision FPU can execute float arithmetic directly in hardware, offering a significant speed advantage for typical embedded applications and digital signal processing tasks. However, double operations on these cores must still be emulated in software, which is slower.\nCores with a full-precision FPU handle both float and double natively, delivering fast, accurate results for applications that require high numerical precision, such as scientific calculations or complex control algorithms.\nFor Espressif cores, all currently available FPUs support single-precision only. This means that while float operations benefit from hardware acceleration, any double calculations are still handled in software, which may impact performance in computation-heavy applications. Which Espressif Cores Include an FPU # Because an FPU is not essential for basic processor functionality, not all Espressif cores include one. For a quick overview, Espressif provides a SoC Product Portfolio that lists the key features of each chip, including whether an FPU is present.\nIn practice, FPUs are found on cores designed for higher computational workloads, where fast floating-point arithmetic makes a noticeable difference. These cores include the ESP32, ESP32-S3, ESP32-H4, and ESP32-P4.\nCore FPU ESP32 :white_check_mark: ESP32-S2 ESP32-S3 :white_check_mark: ESP32-C2 ESP32-C3 ESP32-C5 ESP32-C6 ESP32-C61 ESP32-H2 ESP32-H4 :white_check_mark: ESP32-P4 :white_check_mark: To demonstrate the impact of an FPU, the next section presents a benchmark comparing the execution of the same floating-point workload on two Espressif cores, one with a hardware FPU and one without. This highlights the significant speed and efficiency advantages of hardware-accelerated floating-point operations.\nBenchmark # To evaluate the performance improvement, we measure the average number of CPU cycles required by a core with an FPU and one without to execute the following functions:\nfloat_sum10 and double_sum10: add 10 to the given number float_div10 and double_div10: divide the number by 10 cosf and cos: compute the cosine of the number float_mixed and double_mixed: perform a more complex calculation involving division and trigonometry: cos(sqrtf(value / 2.3 * 0.5 / value)) Each function is executed 10,000 times in a loop, and the total cycle count is divided by 10,000 to obtain the average number of cycles per operation.\nFull benchmark code #include \u0026lt;stdio.h\u0026gt; #include \u0026lt;inttypes.h\u0026gt; #include \u0026lt;stdio.h\u0026gt; #include \u0026lt;math.h\u0026gt; #include \u0026lt;esp_cpu.h\u0026gt; #include \u0026lt;esp_system.h\u0026gt; #include \u0026lt;esp_chip_info.h\u0026gt; #include \u0026lt;esp_random.h\u0026gt; #include \u0026lt;esp_log.h\u0026gt; #define TAG \u0026#34;test\u0026#34; #define ITERATIONS 10000 static void float_test(const char* label, float seed, float (*function) (float)) { uint32_t start_cycles = esp_cpu_get_cycle_count(); for (uint32_t i = 0; i \u0026lt; ITERATIONS; i++) { seed = function(seed); } uint32_t end_cycles = esp_cpu_get_cycle_count(); printf(TAG \u0026#34;: %s %-10.10s average %\u0026#34;PRIu32 \u0026#34; cycles\\n\u0026#34;,label, \u0026#34;float:\u0026#34;, (end_cycles - start_cycles) / ITERATIONS); } static void double_test(const char* label, double seed, double (*function) (double)) { uint32_t start_cycles = esp_cpu_get_cycle_count(); for (uint32_t i = 0; i \u0026lt; ITERATIONS; i++) { seed = function(seed); } uint32_t end_cycles = esp_cpu_get_cycle_count(); printf(TAG \u0026#34;: %s %-10.10s average %\u0026#34;PRIu32 \u0026#34; cycles\\n\u0026#34;, label, \u0026#34;double:\u0026#34;, (end_cycles - start_cycles) / ITERATIONS); } typedef struct { float (*float_function) (float); double (*double_function) (double); } test_t; static void test(const char* label, test_t* test) { printf(TAG \u0026#34;: %s\\n\u0026#34;, label); double seed = 123456.789; if (test-\u0026gt;float_function != NULL) { float_test(label, (float) seed, test-\u0026gt;float_function); } if (test-\u0026gt;double_function != NULL) { double_test(label, (double) seed, test-\u0026gt;double_function); } printf(\u0026#34;\\n\u0026#34;); } /*** trivial functions ***/ static float float_sum10(float value) { return (value + 10); } static double double_sum10(double value) { return (value + 10); } static float float_div10(float value) { return (value / 10); } static double double_div10(double value) { return (value / 10); } /* * mixed calculations */ static float float_mixed(float value) { return cosf(sqrtf(value / 2.3f * 0.5f / value)); } static double double_mixed(double value) { return cos(sqrt(value / 2.3 * 0.5 / value)); } void app_main(void) { esp_chip_info_t chip_info; esp_chip_info(\u0026amp;chip_info); const char *model; switch (chip_info.model) { case CHIP_ESP32: model = \u0026#34;ESP32\u0026#34;; break; case CHIP_ESP32S2: model = \u0026#34;ESP32-S2\u0026#34;; break; case CHIP_ESP32S3: model = \u0026#34;ESP32-S3\u0026#34;; break; case CHIP_ESP32C3: model = \u0026#34;ESP32-C3\u0026#34;; break; case CHIP_ESP32H2: model = \u0026#34;ESP32-H2\u0026#34;; break; case CHIP_ESP32C2: model = \u0026#34;ESP32-C2\u0026#34;; break; case CHIP_ESP32C6: model = \u0026#34;ESP32-C6\u0026#34;; break; default: model = \u0026#34;\u0026lt;UNKNOWN\u0026gt;\u0026#34;; break; } printf(\u0026#34;\\n\u0026#34;); printf(TAG \u0026#34;: CHIP: %s\\n\u0026#34;, model); printf(\u0026#34;\\n\u0026#34;); test_t sum10 = { .float_function = float_sum10, .double_function = double_sum10, }; test(\u0026#34;SUM\u0026#34;, \u0026amp;sum10); test_t div10 = { .float_function = float_div10, .double_function = double_div10, }; test(\u0026#34;DIV\u0026#34;, \u0026amp;div10); test_t cosine = { .float_function = cosf, .double_function = cos, }; test(\u0026#34;COS\u0026#34;, \u0026amp;cosine); test_t mixed = { .float_function = float_mixed, .double_function = double_mixed, }; test(\u0026#34;MIX\u0026#34;, \u0026amp;mixed); } The results are collected in the following table.\nSUM DIV COS MIX FPU float double float double float double float double ESP32C3 :x: 100 122 102 133 2377 3560 3659 6074 ESP32S3 :white_check_mark: 25 70 69 75 121 1619 312 3886 Delta cycles -75 -52 -33 -58 -2256 -1941 -3347 -2188 Saving 75% 43% 32% 44% 95% 55% 91% 36% As expected, single precision float calculation show the biggest saving in machine cycles, with a peak of 95% reached with the cosine function. This means that if your application requires intense vector math, an FPU can come quite handy.\nConclusion # In this article, we explored floating-point numbers, how CPUs perform these calculations with and without an FPU, and which Espressif cores include one. Benchmarks showed that cores with an FPU executed operations, especially single-precision, much faster, demonstrating the clear performance advantage of hardware FPUs for computation heavy applications.\n","date":"13 October 2025","externalUrl":null,"permalink":"/blog/2025/10/cores_with_fpu/","section":"Blog","summary":"In this article, you’ll learn what an FPU is, why it’s useful, which Espressif SoCs feature one, and how it impacts performance through a benchmark.","title":"Floating-Point Units on Espressif SoCs: Why (and when) they matter","type":"blog"},{"content":"","date":"13 October 2025","externalUrl":null,"permalink":"/tags/fpu/","section":"Tags","summary":"","title":"FPU","type":"tags"},{"content":"","date":"13 October 2025","externalUrl":null,"permalink":"/tags/performance/","section":"Tags","summary":"","title":"Performance","type":"tags"},{"content":"","date":"10 October 2025","externalUrl":null,"permalink":"/tags/cli/","section":"Tags","summary":"","title":"CLI","type":"tags"},{"content":"","date":"10 October 2025","externalUrl":null,"permalink":"/tags/development-tools/","section":"Tags","summary":"","title":"Development Tools","type":"tags"},{"content":" What if you could extend idf.py with your own custom commands tailored to your specific workflow? With the ESP-IDF v6.0 and newer (to be released soon), you can do exactly that through a powerful extension system that lets you add project-specific tools or distribute reusable commands across your projects.\nBefore we dive into extensions, let’s recall what idf.py gives you out of the box. It’s the central command-line tool for ESP-IDF that allows you to:\nSet the target chip using idf.py set-target (like esp32) Tweak your project settings using idf.py menuconfig Build your application using idf.py build Flash it using idf.py -p PORT flash Watch the logs in real time using idf.py monitor For most developers, the daily cycle is simply build → flash → monitor — all streamlined under one command.\nWhy extend idf.py? # Sometimes, though, the built-in commands aren’t enough. Maybe you need a custom deployment command that packages your firmware with metadata, or perhaps you want to integrate with your CI/CD pipeline through specialized build targets. Rather than maintaining separate scripts, you can now integrate these directly into idf.py, giving you:\nUnified interface: All your tools accessible through the familiar idf.py command Consistent help system: Your commands appear in idf.py --help with proper documentation Shared options: Leverage existing global options like --port and --build-dir Dependency management: Ensure commands run in the right order automatically Two ways to extend idf.py # ESP-IDF supports two extension mechanisms, each suited for different use cases:\nComponent-based extensions Python package extensions Component-based extensions # This is the case for project-specific commands that should only be available when working with a particular project or component.\nHow it works: Place a file named idf_ext.py in your component directory. ESP-IDF automatically discovers and loads extensions from this file after the project is configured with idf.py reconfigure or idf.py build. Within the component-based extension, the name of the file is important, as idf.py searches exactly for idf_ext.py.\nNote: You may also place idf_ext.py in the project root instead of a component. This option has existed in earlier ESP-IDF versions and works the same way, but using a dedicated component is recommended for clarity and reusability.\nStep 1: Create the extension file # Create a new component (or use an existing one). Inside the component, add a file named idf_ext.py. This file must implement an action_extensions function returning a dictionary that describes your new commands, options, and callbacks. Example (sensor manager): In this example, we’ll add a new command sensor-info that prints configuration details about sensors in your project. Start by creating a component called sensor_manager:\n# Create the component using idf.py idf.py create-component -C components sensor_manager Then, inside your component directory components/sensor_manager/, create idf_ext.py Python file and place the following code:\nfrom typing import Any import click def action_extensions(base_actions: dict, project_path: str) -\u0026gt; dict: def sensor_info(subcommand_name: str, ctx: click.Context, global_args: dict, **action_args: Any) -\u0026gt; None: sensor_type = action_args.get(\u0026#39;type\u0026#39;, \u0026#39;all\u0026#39;) verbose = getattr(global_args, \u0026#39;detail\u0026#39;, False) print(f\u0026#34;Running {subcommand_name} for sensor type: {sensor_type}\u0026#34;) if verbose: print(f\u0026#34;Project path: {project_path}\u0026#34;) print(\u0026#34;Detailed sensor configuration would be displayed here...\u0026#34;) def global_callback_detail(ctx: click.Context, global_args: dict, tasks: list) -\u0026gt; None: if getattr(global_args, \u0026#39;detail\u0026#39;, False): print(f\u0026#34;About to execute {len(tasks)} task(s): {[t.name for t in tasks]}\u0026#34;) return { \u0026#34;version\u0026#34;: \u0026#34;1\u0026#34;, \u0026#34;global_options\u0026#34;: [ { \u0026#34;names\u0026#34;: [\u0026#34;--detail\u0026#34;, \u0026#34;-d\u0026#34;], \u0026#34;is_flag\u0026#34;: True, \u0026#34;help\u0026#34;: \u0026#34;Enable detailed output for all commands\u0026#34;, } ], \u0026#34;global_action_callbacks\u0026#34;: [global_callback_detail], \u0026#34;actions\u0026#34;: { \u0026#34;sensor-info\u0026#34;: { \u0026#34;callback\u0026#34;: sensor_info, \u0026#34;short_help\u0026#34;: \u0026#34;Display sensor configuration\u0026#34;, \u0026#34;help\u0026#34;: \u0026#34;Show detailed information about sensor configuration and status\u0026#34;, \u0026#34;options\u0026#34;: [ { \u0026#34;names\u0026#34;: [\u0026#34;--type\u0026#34;, \u0026#34;-t\u0026#34;], \u0026#34;help\u0026#34;: \u0026#34;Sensor type to query (temperature, humidity, pressure, or all)\u0026#34;, \u0026#34;default\u0026#34;: \u0026#34;all\u0026#34;, \u0026#34;type\u0026#34;: click.Choice([\u0026#39;temperature\u0026#39;, \u0026#39;humidity\u0026#39;, \u0026#39;pressure\u0026#39;, \u0026#39;all\u0026#39;]), } ] }, }, } Step 2: Register the component # Ensure the new component is registered in your project’s CMakeLists.txt. Further information on how to register commponents can be found in Espressif documentation. Example (sensor manager): Update your project\u0026rsquo;s main CMakeLists.txt\nidf_component_register( SRCS \u0026#34;main.c\u0026#34; INCLUDE_DIRS \u0026#34;.\u0026#34; REQUIRES \u0026#34;sensor_manager\u0026#34; # This makes the extension available ) Step 3: Load and test # Reconfigure or build the project to let ESP-IDF discover the extension. Run idf.py help to check that your new command appears. Test the new command with its options. Example (sensor manager): In our case, the extension adds the sensor-info command:\n# Configure the project to discover the extension idf.py reconfigure # Check that your command appears in help idf.py --help # Try your new command idf.py sensor-info --type temperature idf.py --detail sensor-info --type all Python package extensions # This is ideal for reusable tools that you want to share across multiple projects or distribute to your team.\nHow it works: Create a Python package with an entry point in the idf_extension group. Once installed, the extension is available globally for all projects.\nStep 1: Create the package structure # Create a new folder for your tool. Add a pyproject.toml file to describe the package. Inside the folder, create a subfolder with the same name, which will contain your Python code. Inside that subfolder, add __init__.py and a Python file for the extension (e.g., esp_ext.py). Unlike the fixed idf_ext.py in component-based extensions, the filename here is flexible because it is explicitly referenced in pyproject.toml. For clarity and consistency, it’s recommended to prefix it with your tool name and suffix it with _ext.py. The resulting structure should look like this:\nmy_sensor_tools/ ├── pyproject.toml # describe the package here ├── my_sensor_tools/ # place your Python code here │ ├── __init__.py │ └── esp_ext.py Step 2: Fill the extension file # Implement the action_extensions function inside your package’s Python file. Example (sensor manager):\nHere we simply copy the action_extensions function from the component example into my_sensor_tools/esp_ext.py.\nStep 3: Configure and install # Define the Python entry-point in your pyproject.toml under [project.entry-points.idf_extension]. Use the format name: package.module:function. Install the package (for development, use pip install -e .). The new command will now be globally available in any ESP-IDF project. Example (sensor manager):\nThe pyproject.toml file for our example could look like this:\n[project] name = \u0026#34;my-sensor-tools\u0026#34; version = \u0026#34;1.0.0\u0026#34; # Register the extension under the `idf_extension` group, # so ESP-IDF can automatically discover it [project.entry-points.idf_extension] my_sensor_tools = \u0026#34;my_sensor_tools.esp_ext:action_extensions\u0026#34; Install and use:\n# Install in development mode cd my_sensor_tools pip install -e . # Your command is now available in any ESP-IDF project cd my_sensor_tools/ idf.py sensor-info --type temperature idf.py --detail sensor-info --type all Naming conventions # Avoid conflicts: Your commands cannot override built-in idf.py commands like build, flash, or monitor Use descriptive names: Prefer sensor-info over info to avoid ambiguity Package prefixes: For Python package extensions, consider prefixing commands with your tool name Advanced features # Do you need something extra? Beyond simple commands, the extension system also gives you ways to define global options, control execution order, and build richer command-line interfaces. These features let you create tools that feel fully integrated with the rest of idf.py.\nGlobal options and callbacks # The extension system supports sophisticated features for power users:\nGlobal options: Define options that work across all commands. Can be exposed under global_args parameter.\nGlobal callbacks: Functions that run before any tasks execute, perfect for validation, logging, or injecting additional tasks based on global options.\nDependencies and order management # Ensure your commands run in the correct sequence:\n\u0026#34;actions\u0026#34;: { \u0026#34;deploy\u0026#34;: { \u0026#34;callback\u0026#34;: deploy_firmware, \u0026#34;dependencies\u0026#34;: [\u0026#34;all\u0026#34;], # Always build before deploying \u0026#34;order_dependencies\u0026#34;: [\u0026#34;flash\u0026#34;], # If flash is requested, run it before deploy \u0026#34;help\u0026#34;: \u0026#34;Deploy firmware to production servers\u0026#34; } } Rich argument support # Support complex command-line interfaces:\n\u0026#34;options\u0026#34;: [ { \u0026#34;names\u0026#34;: [\u0026#34;--config-file\u0026#34;, \u0026#34;-c\u0026#34;], \u0026#34;type\u0026#34;: click.Path(exists=True), \u0026#34;help\u0026#34;: \u0026#34;Configuration file path\u0026#34; }, { \u0026#34;names\u0026#34;: [\u0026#34;--verbose\u0026#34;, \u0026#34;-v\u0026#34;], \u0026#34;count\u0026#34;: True, # -v, -vv, -vvv for different verbosity levels \u0026#34;help\u0026#34;: \u0026#34;Increase verbosity (use multiple times)\u0026#34; } ], \u0026#34;arguments\u0026#34;: [ { \u0026#34;names\u0026#34;: [\u0026#34;targets\u0026#34;], \u0026#34;nargs\u0026#34;: -1, # Accept multiple targets \u0026#34;required\u0026#34;: True } ] For more details on the extension API and additional features, see the Click documentation for argument types and the ESP-IDF documentation for the complete extension reference.\nConclusion # The idf.py extension system opens up powerful possibilities for customizing your ESP-IDF development workflow. Whether you\u0026rsquo;re adding simple project-specific helpers or building sophisticated development tools, extensions let you integrate seamlessly with the existing ESP-IDF ecosystem.\nStart small with a component-based extension for your current project, then graduate to distributable packages as your tools mature.\nWhat\u0026rsquo;s next? # Explore the full extension API documentation for advanced features Check out existing extensions in the ESP-IDF codebase for inspiration Happy extending!\n","date":"10 October 2025","externalUrl":null,"permalink":"/blog/2025/10/idf_py_extension/","section":"Blog","summary":"Learn how to extend idf.py with custom commands for your development workflow. This guide covers both component-based extensions for project-specific tools and Python package extensions for reusable commands, with practical examples and best practices for seamless integration.","title":"Extending idf.py: Create custom commands for your ESP-IDF workflow","type":"blog"},{"content":"","date":"10 October 2025","externalUrl":null,"permalink":"/tags/extensions/","section":"Tags","summary":"","title":"Extensions","type":"tags"},{"content":" Introduction # When working with the ESP-IDF framework, you may noticed that much of its design feels object-oriented, even though it’s written in C. This is because ESP-IDF makes use of object-oriented programming (OOP) principles implemented in plain C, giving developers the benefits of structured, modular code without relying on C++.\nOf course, C by itself does not provide built-in OOP features such as classes, inheritance, or polymorphism. However, developers can emulate OOP patterns in C effectively through well-established techniques, like encapsulation using structs, function pointers to mimic polymorphism, and modular design.\nApplying OOP concepts in embedded C development brings several advantages:\nEncapsulation: Keeps implementation details hidden while exposing clean, minimal interfaces. Reusability: Encourages building reusable components rather than rewriting code. Maintainability: Makes large projects easier to extend and modify without breaking existing functionality. Scalability: Provides a clear structure for organizing complex systems. In this article, we’ll explore how ESP-IDF applies OOP concepts in C, look at the techniques it uses under the hood, and check a few API functions with these concepts in action.\nIn a later article, we\u0026rsquo;ll put these concept into practice and we\u0026rsquo;ll write our first object in C.\nWhat is OOP # Object-Oriented Programming (OOP) is a design paradigm that organizes software around objects rather than just separate functions and data. Each object represents a self-contained unit with its own state (data) and behavior (methods), making it easier to reason about complex systems as a collection of interacting parts.\nThe origins of OOP trace back to the 1960s, when Ole-Johan Dahl and Kristen Nygaard introduced the Simula language to model real-world entities for simulations. This approach was later popularized by languages like Smalltalk and eventually adopted in mainstream programming through C++ and Java.\nOOP in C # C is not an object-oriented language by design, yet it provides enough building blocks to emulate many of the same principles. By carefully combining structs, pointers, and modular design with header files, developers can achieve encapsulation, modularity, and even a form of polymorphism.\nBasic OOP in C # At the core, C offers:\nStructures (struct) to group related data together. Header files to define public interfaces while hiding implementation details in .c files. Pointers to reference data, enable dynamic allocation, and pass around objects efficiently. With these tools, you can emulate classes in C.\nConceptually, a “class” in C consists of:\nAn object type defined as a private struct, with its details hidden from the user. Methods implemented as functions, each taking a pointer to the object (my_object_t *) as the first argument. In practice, this is implemented as:\nA header file (.h) that declares the object type as an opaque pointer and its public functions (the interface). A source file (.c) that defines the private struct representing the object type and implements the functions (the implementation). An opaque pointer is a pointer to a type whose contents are hidden from the user. In the header file, you only declare typedef struct my_object_t my_object_t; without revealing the fields. This way, code using your “object” cannot directly access or modify its internal state: It must go through your provided functions. This enforces encapsulation, just like private members in a class. Error Handling # Before looking deeper at how methods are structured in C, it’s important to touch on error handling. While not strictly part of object-oriented programming, it directly affects the design of function signatures in OOP-style APIs: many “methods” return status codes instead of the actual result, leaving the caller to check and handle errors explicitly. This convention is widely used in ESP-IDF and is key to understanding how its APIs are meant to be used. For a deeper dive, see the article ESP-IDF tutorial series: Errors.\nImplementation example # Let’s look at a few snippets showing how to implement an object in C. The public interface is declared in the header file:\n// my_object.h typedef struct my_object_t my_object_t; // Opaque type typedef enum { MY_OBJECT_OK = 0, MY_OBJECT_ERR_NULL, MY_OBJECT_ERR_INVALID } my_object_error_t; // enum for errors my_object_t * my_object_create(int value); my_object_error_t my_object_set(my_object_t* obj, int value); int my_object_get(const my_object_t* obj); void my_object_destroy(my_object_t* obj); The corresponding implementation defines the private struct and includes error handling in the methods:\n// my_object.c #include \u0026#34;my_object.h\u0026#34; #include \u0026lt;stdlib.h\u0026gt; struct my_object_t { int value; // private member }; my_object_t* my_object_create(int value) { my_object_t* obj = malloc(sizeof(my_object_t)); if (obj) { obj-\u0026gt;value = value; } return obj; } my_object_error_t my_object_set(my_object_t* obj, int value) { if (!obj) return MY_OBJECT_ERR_NULL; if (value \u0026lt; 0) return MY_OBJECT_ERR_INVALID; obj-\u0026gt;value = value; return MY_OBJECT_OK; } int my_object_get(const my_object_t* obj) { return obj ? obj-\u0026gt;value : -1; } void my_object_destroy(my_object_t* obj) { free(obj); } Using the “class” in main.c then looks like this:\n#include \u0026#34;my_object.h\u0026#34; #include \u0026lt;stdio.h\u0026gt; int main(void) { my_object_t* obj = my_object_create(10); printf(\u0026#34;Initial value: %d\\n\u0026#34;, my_object_get(obj)); if (my_object_set(obj, 42) == MY_OBJECT_OK) { printf(\u0026#34;Updated value: %d\\n\u0026#34;, my_object_get(obj)); } my_object_destroy(obj); // must be freed manually! return 0; } Here the workflow is simple: create the object with my_object_create, call its “methods” by passing the object pointer, handle errors through return codes, and explicitly destroy the object with my_object_destroy.\nNote on create method # When designing a create method in C, there are two common approaches.\nReturn the object pointer directly, using NULL to signal allocation failure.\nThis keeps the call site simple but limits the ability to report detailed errors. Return an error code (e.g., my_object_error_t, esp_err_t) and pass the pointer as an output argument.\nAllows you to distinguish between multiple failure conditions. ESP-IDF consistently uses the second approach, as it integrates with its global error handling conventions, while in plain C libraries you’ll often see the simpler NULL-on-error pattern.\nHandles in ESP-IDF # Instead of exposing raw pointers, ESP-IDF returns handles, which are opaque types that internally are pointers. This hides implementation details and enforces safe access:\nspi_device_handle_t handle; spi_bus_add_device(VSPI_HOST, \u0026amp;devcfg, \u0026amp;handle); spi_device_transmit(handle, \u0026amp;trans); spi_device_handle_t is a handle representing a device. Internally, it’s a pointer to a structure but that\u0026rsquo;s hidden by the API. It\u0026rsquo;s definition is:\ntypedef struct spi_device_t * spi_device_handle_t;, You interact only via functions, not by dereferencing the pointer. A handle is essentially an opaque pointer: it references an internal object, but the structure is hidden. This design enforces encapsulation and allows the framework to safely manage memory and state, which is critical in embedded programming. Advanced OOP in C # Beyond the basics, it’s also possible to mimic inheritance (by embedding one struct inside another) and even a form of polymorphism (using function pointers stored in structs).\nIn this article, we’ll stay focused on the fundamentals of OOP in C, while acknowledging that advanced features like inheritance and polymorphism are also within reach if needed.\nComparison with Python and C++ # After exploring object-oriented patterns in C, it’s helpful to see how this compares with higher-level languages. In C, you manage both object references and memory manually, which is essential in embedded systems. Python and C++ handle these tasks automatically.\nPython\nclass MyObject: def __init__(self, value): self.value = value def set(self, value): self.value = value def get(self): return self.value obj = MyObject(10) print(obj.get()) obj.set(42) print(obj.get()) You explicitly declare self in methods, but Python automatically passes it when you call a method. Memory is managed by the garbage collector; you don’t control allocation or deallocation. C++\nclass MyObject { int value; public: MyObject(int v) : value(v) {} void set(int v) { value = v; } int get() { return value; } }; int main() { MyObject obj(10); std::cout \u0026lt;\u0026lt; obj.get() \u0026lt;\u0026lt; std::endl; obj.set(42); std::cout \u0026lt;\u0026lt; obj.get() \u0026lt;\u0026lt; std::endl; } The compiler automatically provides the hidden this pointer; you neither declare nor pass it. Memory management is manual, but higher-level features like constructors and destructors help automate initialization and cleanup. C (our example)\nmy_object_t* obj = my_object_create(10); printf(\u0026#34;%d\\n\u0026#34;, my_object_get(obj)); my_object_set(obj, 42); printf(\u0026#34;%d\\n\u0026#34;, my_object_get(obj)); my_object_destroy(obj); // manual cleanup You must declare and explicitly pass the object pointer for every function call. Memory management is fully manual with malloc and free, giving full control over resource usage. Recap\nLanguage Object reference handling Memory management Python Write self, automatically passed at call time Automatic (garbage collected) C++ this automatically injected by the compiler Manual, aided by constructors C Must write and pass pointer explicitly Fully manual, precise control By explicitly managing object pointers and memory, C requires more boilerplate and careful handling than higher-level languages, but in embedded systems this fine-grained control pays off, which is less critical in high-resource environments like laptops or desktops.\nExamples of OOP in ESP-IDF # Let’s look at a practical example of how ESP-IDF applies this approach.\nProtocol: httpd_handle_t # To manage an HTTP server instance, ESP-IDF provides the httpd_handle_t type. Server initialization begins with defining configuration parameters in an httpd_config_t structure, which simplifies setup.\nA typical workflow looks like this:\nhttpd_config_t config = [...]; httpd_handle_t server = NULL; esp_err_t result = httpd_start(\u0026amp;server, \u0026amp;config); Here, the server handle is initialized as NULL and then populated by httpd_start, so it follows the second approach mentioned in Note on create method above. The function also returns an error code, allowing you to verify success by checking result==ESP_OK. While httpd_start could have been designed to return the handle directly, this pattern ensures that error handling remains explicit.\nAlthough server is not formally a pointer type, its definition\ntypedef void * httpd_handle_t; This reveals that server is essentially a pointer under the hood. Once created, this handle is used for all server operations, such as:\nRegistering a URI handler: httpd_register_uri_handler(server, \u0026amp;hello_world_uri); Stopping the server: httpd_stop(server); Peripheral: i2c_master_bus_handle_t and i2c_master_dev_handle_t # In Espressif’s communication bus components (like i2c_bus and spi_bus), a bus and a device are treated as separate objects. The bus defines the shared interface, while each device holds specific settings, such as an address or chip select.\nTo transmit data, you first create and configure the bus, then you attach devices, and finally use the device handle for read/write operations. Proper creation and deletion of both objects are essential for stable and efficient communication.\nCreating the bus typically looks like this:\n// Define the bus handle i2c_master_bus_handle_t bus_handle; // Configure the I2C master bus i2c_master_bus_config_t i2c_mst_config = [...]; // Create the I2C master bus and get the handle esp_err_t new_master_bus_error = i2c_new_master_bus(\u0026amp;i2c_mst_config, \u0026amp;bus_handle); As with server handles, the bus handle is first declared and then populated via i2c_new_master_bus.\nSimilarly, a device is created and attached to the bus in a single step:\n// Define the device handle i2c_master_dev_handle_t dev_handle; // Configure the I2C device i2c_device_config_t dev_cfg = [...]; // Add the device to the bus and get the device handle esp_err_t bus_add_device_error = i2c_master_bus_add_device(bus_handle, \u0026amp;dev_cfg, \u0026amp;dev_handle); Once set up, the device handle is used for communication:\n// Use the device handle to transmit data i2c_master_transmit(dev_handle, data_wr, DATA_LENGTH, -1); Finally, proper cleanup involves removing the device and deleting the bus:\n// Remove the device from the bus esp_err_t rm_device_error = i2c_master_bus_rm_device(dev_handle); // Delete the I2C master bus esp_err_t del_master_error = i2c_del_master_bus(bus_handle); These examples clearly demonstrate how ESP-IDF applies OOP concepts in practice. In a later article, we’ll implement a simple object to explore these standard methods in action.\nConclusion # In this article, we explored how object-oriented programming principles can be applied in C, particularly within the ESP-IDF framework. We examined techniques such as opaque pointers, encapsulation, and manual memory management, highlighting how C can emulate classes and methods despite lacking native OOP support. The article also showed how ESP-IDF uses these OOP patterns in practice to structure its APIs and manage resources efficiently.\n","date":"3 October 2025","externalUrl":null,"permalink":"/blog/2025/10/oop_with_c/","section":"Blog","summary":"This article explains how ESP-IDF brings object-oriented programming principles into C by using \u003ccode\u003estructs\u003c/code\u003e, opaque pointers, and handles to enforce encapsulation and modularity. It shows how components like HTTP servers and I²C buses are managed through handles that represent distinct objects for configuration and operation, and compares this approach to Python and C++.","title":"ESP-IDF tutorial series: Object oriented programming in C","type":"blog"},{"content":"","date":"3 October 2025","externalUrl":null,"permalink":"/tags/oop/","section":"Tags","summary":"","title":"OOP","type":"tags"},{"content":"","date":"1 October 2025","externalUrl":null,"permalink":"/tags/getting-started/","section":"Tags","summary":"","title":"Getting Started","type":"tags"},{"content":"The ESP32 Arduino Core is a powerful development platform that brings the simplicity and accessibility of Arduino programming to Espressif\u0026rsquo;s ESP32 series of microcontrollers. This integration allows developers to leverage the familiar Arduino environment while taking advantage of the ESP32\u0026rsquo;s advanced features, including dual-core processing, built-in Wi-Fi and Bluetooth connectivity, and extensive peripheral support.\nWhat is the ESP32 Arduino Core? # The ESP32 Arduino Core is an open-source project developed by Espressif Systems that provides Arduino-compatible libraries and tools for programming ESP32 microcontrollers. It extends the Arduino platform to support the ESP32\u0026rsquo;s unique capabilities while maintaining compatibility with the vast ecosystem of Arduino libraries and sketches.\nKey Features and Capabilities # The ESP32 Arduino Core provides comprehensive support for all Espressif mass-production SoCs and unlocks their powerful features:\nMulti-SoC Support: Compatible with all Espressif mass-production SoCs including ESP32, ESP32-S2, ESP32-S3, ESP32-C3, ESP32-C5, ESP32-C6, ESP32-H2, ESP32-P4 (as of the time of writing, with new SoCs being added regularly) Built-in Connectivity Libraries: Native support for Wi-Fi (802.11 b/g/n), Ethernet, Bluetooth Low Energy (BLE), Zigbee protocols Comprehensive Peripheral Support: Extensive GPIO pins, ADC, DAC, I2C, I2S, SPI, UART, LEDC, Touch sensors, and many more peripherals Built-in Libraries: Rich ecosystem of pre-built libraries including WebServer, HTTP client, OTA updates, Matter, file system support, and more Real-Time Operating System: FreeRTOS-based multitasking capabilities for complex applications Arduino Compatibility: Seamless integration with existing Arduino libraries and code while adding ESP32-specific functionality Why Choose ESP32 Arduino Core? # The ESP32 Arduino Core is particularly beneficial for:\nRapid Prototyping: Familiar Arduino syntax and extensive library support Educational Purposes: Easy learning curve for beginners Professional Development: Powerful enough for complex applications while maintaining simplicity Huge Amount of Examples: Extensive collection of example code covering all features and use cases Community Support: Large community and extensive documentation Prerequisites # Before setting up the ESP32 Arduino Core, ensure you have:\nA computer running Windows, macOS, or Linux Arduino IDE installed (version 2.x recommended) Any ESP32 development board with a USB-to-UART interface or a USB-capable device. A good USB data cable to connect your ESP32 to your computer Installation Methods # There are two primary ways to install the ESP32 Arduino Core:\nInstalation via Arduino IDE Board Manager (Recommended for beginners) Manual Installation using Git (Advanced users and developers) We\u0026rsquo;ll cover both methods in detail.\nMethod 1: Installation via Arduino IDE Board Manager # This is the recommended method for most users as it\u0026rsquo;s straightforward and handles all dependencies automatically.\nStep 1: Add ESP32 Board Manager URL # In Arduino IDE, open Preferences:\nNavigate to File \u0026gt; Preferences (Windows/Linux) or Arduino \u0026gt; Preferences (macOS) Add Board Manager URL:\nIn the \u0026ldquo;Additional Board Manager URLs\u0026rdquo; field, add one of the following URLs: Stable Release (Recommended for most users):\nhttps://espressif.github.io/arduino-esp32/package_esp32_index.json Development Release (Latest features, pre-release versions):\nhttps://espressif.github.io/arduino-esp32/package_esp32_dev_index.json For users in China (Mirror with better download speeds): Stable Development https://jihulab.com/esp-mirror/espressif/arduino-esp32/-/raw/gh-pages/package_esp32_index_cn.json https://jihulab.com/esp-mirror/espressif/arduino-esp32/-/raw/gh-pages/package_esp32_dev_index_cn.json If you have other URLs already, add this one on a new line Click \u0026ldquo;OK\u0026rdquo; to save the settings Step 2: Install ESP32 Board Package # Open Boards Manager:\nNavigate to Tools \u0026gt; Board \u0026gt; Boards Manager\u0026hellip; or click on Boards manager icon in sidebar In the search bar, type \u0026ldquo;esp32\u0026rdquo; Look for \u0026ldquo;esp32 by Espressif Systems\u0026rdquo; in the results Click the \u0026ldquo;Install\u0026rdquo; button Wait for the installation to complete (this may take several minutes) Method 2: Manual Installation using Git # This method is recommended for advanced users who want more control over the installation or need to work with specific versions of the ESP32 Arduino Core.\nPrerequisites for Git Installation # Git installed on your system Python 3.x installed Clone ESP32 Arduino Core Repository and Install Tools and Dependencies # The following asciinema recording demonstrates the complete manual installation process:\nWhat the recording shows:\nNavigate to Arduino Directory:\ncd Documents/Arduino Create Hardware Directory Structure:\nmkdir -p hardware/espressif cd hardware/espressif Clone the Repository:\ngit clone https://github.com/espressif/arduino-esp32.git esp32 Navigate to Tools Directory:\ncd esp32/tools Run Installation Script:\npython get.py Platform Notes:\nWindows: Use Command Prompt or PowerShell instead of terminal Linux/macOS: The commands shown work directly in terminal Alternative for Windows: If Python is not available, you can run get.exe directly instead of python get.py Run your first sketch # To ensure everything is working correctly, let\u0026rsquo;s create a simple test sketch:\nOpen Arduino IDE Select Board: Go to Tools \u0026gt; Board \u0026gt; ESP32 Arduino \u0026gt; ESP32 Dev Module Select Port: Choose the correct COM port for your ESP32 Create New Sketch: Go to File \u0026gt; New Paste Test Code: void setup() { Serial.begin(115200); } void loop() { Serial.println(\u0026#34;Hello from ESP32 Arduino!\u0026#34;); delay(1000); } Upload the Sketch: Click the upload button (arrow icon) Open Serial Monitor: Go to Tools \u0026gt; Serial Monitor and set baud rate to 115200 If you see \u0026ldquo;Hello from ESP32 Arduino!\u0026rdquo; appearing every second in the Serial Monitor, your ESP32 Arduino Core installation is successful!\nUnderstanding the Serial Monitor # The Serial Monitor is a powerful debugging tool that allows you to communicate with your ESP32 board through the USB connection. It\u0026rsquo;s essential for:\nViewing Output: See text messages, sensor readings, and debug information from your ESP32 Debugging Code: Print variable values, status messages, and error information to troubleshoot your programs Interactive Communication: Send commands to your ESP32 and receive responses Key Serial Monitor Features:\nBaud Rate: Must match the Serial.begin() rate in your code (115200 in our example) Auto-scroll: Automatically shows the latest messages Clear: Button to clear the display Send: Text field to send commands to your ESP32 Timestamps: Optional feature to show when each message was received Common Serial Commands in Arduino:\nSerial.begin(115200); // Initialize serial communication at 115200 baud Serial.println(\u0026#34;Message\u0026#34;); // Print message and move to next line Serial.print(\u0026#34;Value: \u0026#34;); // Print without moving to next line Serial.println(variable); // Print variable value Serial.available(); // Check if data is available to read Serial.read(); // Read incoming data The Serial Monitor is your window into what\u0026rsquo;s happening inside your ESP32, making it an indispensable tool for learning and debugging!\nNext Steps # Now that you have the ESP32 Arduino Core installed, you can:\nTry the example to connect your ESP32 to Wi-Fi or try out any of the ESP32 examples included with the installation. These examples can be easily accessed in the Arduino IDE by going to File \u0026gt; Examples and selecting one of the ESP32 example sketches. Explore the ESP32 Arduino Core documentation If you don\u0026rsquo;t have any ESP32 boards yet, you can use the Wokwi simulator to start with ESP32 Arduino Core. Start building your first IoT project with built-in Wi-Fi and Bluetooth capabilities The ESP32 Arduino Core opens up a world of possibilities for embedded development, combining the simplicity of Arduino with the power and connectivity features of the ESP32. Happy coding!\n","date":"1 October 2025","externalUrl":null,"permalink":"/blog/2025/10/arduino-get-started/","section":"Blog","summary":"Learn how to set up the ESP32 Arduino Core development environment, including Arduino IDE installation and ESP32 board package setup using both the Board Manager and manual Git installation methods.","title":"Getting Started with ESP32 Arduino","type":"blog"},{"content":"","date":"1 October 2025","externalUrl":null,"permalink":"/authors/jan-prochazka/","section":"Developer Portal Authors","summary":"","title":"Jan Procházka","type":"authors"},{"content":"","date":"26 September 2025","externalUrl":null,"permalink":"/tags/errors/","section":"Tags","summary":"","title":"Errors","type":"tags"},{"content":" Introduction # The most straightforward way to see what your C program is doing is to drop in a few printf statements. It’s simple, immediate, and every developer knows how to use it. But as soon as your application grows beyond a toy example, printf starts to show its limits: output becomes messy, important details get buried, and managing those statements turns into a chore. Using a logging library, on the other hand, gives you structured, configurable, and context-rich feedback without scattering prints all over your code.\nIt lets you control what gets recorded, where it goes, and how it looks, all while keeping your source clean. Additionally, logging can be easily disabled in production builds via a configuration option, so you don’t have to worry about performance or leaking sensitive information. In the sections that follow, we’ll refer to the logging library simply as “logging,” and we’ll explore why it is better than printf for debugging, as well as how adopting it can make your codebase easier to maintain and scale.\nLogging library # The ESP-IDF provides its logging functionality through the log component, included via esp_log.h. You’ve probably already seen this logging in action, as it’s used extensively throughout the ESP-IDF libraries.\nESP-IDF offers two logging implementations: Log V1 and Log V2, selectable through CONFIG_LOG_VERSION. Log V1 is the simpler, default option optimized for early and DRAM logging but with higher flash usage and limited flexibility, while Log V2 reduces flash usage, adds powerful customization features, and centralizes formatting at the cost of slightly higher stack usage. In this article, we will focus on Log V1, while Log V2 will be covered in a future article.\nLet’s examine the output from the hello_world example. When you monitor your device while running hello_world, you’ll see something like:\nFig.1 - Hello World output\nLines starting with I are shown in green, while those starting with W appear in orange. These are examples of log messages: I denotes an informational message, and W denotes a warning. Although both are essentially printed messages with some extra formatting, they represent conceptually different types of messages. Their visibility can be controlled through a configuration parameter called verbosity.\nLogging core elements # To grasp how logging works in ESP-IDF, we will examine its three core elements:\nTags Logging macros Verbosity levels Tags # A tag is simply a string used to group related log messages, typically by file or component. Tags are passed to the logging macros, as demonstrated in the next section. A common convention is to define a TAG constant as a static const char * pointer. In ESP-IDF, tags are usually declared at the top of the file like this:\nstatic const char *TAG = \u0026#34;TAG_NAME\u0026#34;; The static keyword limits the symbol’s visibility to the current file, while const ensures the string is stored in read-only memory instead of consuming RAM. Logging macros # ESP-IDF offers a powerful logging system through the ESP_LOGx family of macros that are used for reporting errors, warnings, and other runtime information. These macros are task-safe, lightweight, and can be grouped per tag.\nThe available macros are:\nESP_LOGE – Error ESP_LOGW – Warning ESP_LOGI – Info ESP_LOGD – Debug ESP_LOGV – Verbose Here is a sample showing how to use one of these macros in your code:\nESP_LOGE(TAG, \u0026#34;Failed to initialize sensor: %s\u0026#34;, esp_err_to_name(ret)); Each logging macro takes two main arguments:\nTag - the label under which the log will be grouped. Message – a printf-style format string followed by variadic arguments. Verbosity # The difference between the logging macros is not just visual, it’s also tied to the verbosity level. Verbosity levels determine which messages are actually printed to the serial console.\nThe reason why it’s possible to change the verbosity is that reducing it in ESP-IDF (e.g., via CONFIG_LOG_DEFAULT_LEVEL) provides several advantages:\nSmaller binary size: Fewer log strings and logging calls reduce the compiled code size. Lower CPU load: With fewer logs generated, the CPU spends less time formatting and outputting messages, improving runtime performance. Reduced memory usage: Less memory is needed for log strings and temporary buffers, which helps applications with tight memory limits. These optimizations make logging more efficient without losing control over critical messages.\nThe esp_log component supports the following levels, from lowest to highest:\nNo output Error Warning Info Debug Verbose This order matters: for example, ESP_LOGE messages will appear even at the lowest verbosity setting that allows output, while ESP_LOGV messages are only shown when verbosity is set to the highest level.\nYou can change the default verbosity level in menuconfig:\n\u0026gt; ESP-IDF: SDK Configuration Editor (menuconfig)\n→ Component Config Log Level → Default Log Verbosity Fig.2 illustrates how different verbosity settings affect which log messages are shown. The default verbosity level is info.\nFig.2 - Logging diagram\nFiltering Logs # ESP-IDF gives you fine-grained control over log output, allowing you to filter messages by verbosity level and tag. You can do this both at runtime in your application and from the host using the IDF monitor.\nFiltering at Runtime # You can also adjust log verbosity directly within your application using the esp_log_level_set() function:\nesp_log_level_set(\u0026#34;TAG\u0026#34;, ESP_LOG_WARN); // Only warnings and errors for \u0026#34;TAG\u0026#34; esp_log_level_set(\u0026#34;TAG\u0026#34;, ESP_LOG_NONE); // Disable all logs for \u0026#34;TAG\u0026#34; This makes it possible to dynamically change log levels for specific modules or components while your program is running.\nFiltering in the IDF Monitor # When using the IDF monitor, you can control which logs are displayed by filtering them by tag and verbosity level. This can be done with the --print-filter option or by setting the ESP_IDF_MONITOR_PRINT_FILTER environment variable. All logs are still transferred to the host over the serial port, but only those that match the filter are shown.\nA filter is defined as a series of \u0026lt;tag\u0026gt;:\u0026lt;log_level\u0026gt; pairs, where \u0026lt;log_level\u0026gt; can be one of:\nN (None) E (Error) W (Warning) I (Info) D (Debug) V (Verbose) * (all) For example you can write\nidf.py monitor --print-filter=\u0026#34;tag1:W\u0026#34; Shows only warnings and errors for tag1.\nidf.py monitor --print-filter=\u0026#34;tag1:I tag2:W\u0026#34; Shows tag1 logs at Info level or less, and tag2 logs at Warning level or less.\nIf no log level is specified, the default is verbose. You can also define global filters. For instance, *:E displays only errors across all tags.\nTag names must not include spaces, asterisks *, or colons :. More details: ESP-IDF Monitor Output Filtering. Putting it all together # Let’s try out the logging system in practice. We’ll start from a bare-bones example available on this GitHub repository.\nThe main.c file for this example looks like this:\n#include \u0026lt;stdio.h\u0026gt; #include \u0026#34;sdkconfig.h\u0026#34; void app_main(void) { printf(\u0026#34;Hello tutorial!\\n\u0026#34;); } In this section we will\nAssign a tag to the logs (i.e. TAG) Log a message for each level Change verbosity level and check the output Assign a tag to the logs # When using a logging macro, the first argument is a tag that groups related log messages. You can pass a string literal directly, but it’s usually better to define a constant and reuse it throughout the same component or file.\nIn our example, we’ll use:\nstatic const char *TAG = \u0026#34;APP_MAIN\u0026#34;; Log a message for each level # Before using the log macros, include the esp_log.h header:\n#include \u0026#34;esp_log.h\u0026#34; Next, replace the app_main function with the following:\nvoid app_main(void) { printf(\u0026#34;\\n\\n\\n*** STARTING LOGS ***\\n\\n\u0026#34;); ESP_LOGE(TAG, \u0026#34;Log ERROR!\u0026#34;); ESP_LOGW(TAG, \u0026#34;Log WARNING!\u0026#34;); ESP_LOGI(TAG, \u0026#34;Log INFO!\u0026#34;); ESP_LOGD(TAG, \u0026#34;Log DEBUG!\u0026#34;); ESP_LOGV(TAG, \u0026#34;Log VERBOSE!\u0026#34;); printf(\u0026#34;\\n\\n\\n*** ENDING LOGS ***\\n\\n\\n\u0026#34;); } The printf statements are used simply to separate the logs we created from the default ESP-IDF logs. Now, build, flash, and monitor the code:\n\u0026gt; ESP-IDF: Build, Flash and Start a Monitor on Your Device The relevant output is shown in Fig. 3.\nFig.3 - Logging output - Info level\nYou can see that the error log appears in red, the warning log in yellow, and the info log in green. The debug and verbose logs are missing because the current verbosity level does not allow them to be displayed.\nChange verbosity level and check the output # Let’s inspect the current verbosity level in menuconfig:\n\u0026gt; ESP-IDF: SDK Configuration Editor (menuconfig)\n→ Component Config → Log Level → Default Log Verbosity The dropdown menu (see Fig. 4) lists all available levels. By default, it is set to info.\nFig.4 - Choosing verbosity level\nNow, let’s see what happens when we increase the verbosity:\nChange the dropdown value to verbose\nSave the configuration\nBuild, flash, and start the monitor:\n\u0026gt; ESP-IDF: Build, Flash and Start a Monitor on Your Device As expected, all log levels are now displayed, as shown in Fig. 5.\nFig.5 - Logging output - Verbose level\nNote that the ESP_LOGD and ESP_LOGV messages appear in white, similar to printf.\nFor production, logs are usually disabled. You can do this by selecting No output in the dropdown menu. Change verbosity at runtime # You can also adjust the logging verbosity while your program is running. Update your app_main function as follows:\nvoid app_main(void) { printf(\u0026#34;\\n\\n\\n*** STARTING LOGS ***\\n\\n\u0026#34;); ESP_LOGE(TAG, \u0026#34;Log ERROR!\u0026#34;); ESP_LOGW(TAG, \u0026#34;Log WARNING!\u0026#34;); ESP_LOGI(TAG, \u0026#34;Log INFO!\u0026#34;); ESP_LOGD(TAG, \u0026#34;Log DEBUG!\u0026#34;); ESP_LOGV(TAG, \u0026#34;Log VERBOSE!\u0026#34;); esp_log_level_set(\u0026#34;main\u0026#34;, ESP_LOG_WARN); ESP_LOGE(TAG, \u0026#34;Log ERROR after set level\u0026#34;); ESP_LOGW(TAG, \u0026#34;Log WARNING set level\u0026#34;); ESP_LOGI(TAG, \u0026#34;Log INFO set level\u0026#34;); ESP_LOGD(TAG, \u0026#34;Log DEBUG!\u0026#34;); ESP_LOGV(TAG, \u0026#34;Log VERBOSE!\u0026#34;); printf(\u0026#34;\\n\\n\\n*** ENDING LOGS ***\\n\\n\\n\u0026#34;); } In this example, we first print all log levels, then change the verbosity level of the main component to WARN. After that, only warnings and errors will appear in the output.\nBuild, flash, and monitor your device:\n\u0026gt; ESP-IDF: Build, Flash and Start a Monitor on Your Device Your output should now look similar to Fig.5.\nFig.5 - Runtime filtering\nAs you can see, the configuration log level is set to verbose, so in the first block all messages—including verbose—are printed. After calling esp_log_level_set, the log level for the main component is reduced to warning, so only warnings and errors are displayed from that point on.\nFiltering with esp-idf monitor # As a last step, let\u0026rsquo;s use the idf.py monitor to filter only the logs with tag \u0026ldquo;main\u0026rdquo; and just the ones with verbosity level less than info.\n\u0026gt; ESP-IDF: Open ESP-IDF Terminal In the terminal type: idf.py monitor --print-filter=\u0026quot;main:I\u0026quot; The output should look like Fig. 6.\nFig.6 - idf.py monitor filtering\nIn this case, even though the verbosity level is set to verbose, the monitor filters out all messages with the main tag below info.\nIn this example, this process is equivalent to setting the verbosity level to info in menuconfig. However, when working with multiple components, you can set a different displayed verbosity level for each one individually.\nConclusion # In this article, we explored the ESP-IDF logging system, showed how to define a module tag, used the ESP_LOGx macros for different severity levels, and adjusted verbosity to control which messages to display.\nWe also demonstrated how to change log levels at runtime and filter messages in the IDF monitor, giving developers fine-grained control over log visibility and improving both development efficiency and application performance. Unlike printf, logging provides structured, context-rich output that can be filtered by level, grouped by module, and disabled in production, making debugging and monitoring much easier.\nFurther Reading # For a deeper dive into the logging library, see the ESP-IDF Programming Guide. To explore all host-side filtering options, refer to the IDF Monitor documentation. ","date":"26 September 2025","externalUrl":null,"permalink":"/blog/2025/09/espressif_logging/","section":"Blog","summary":"This article shows how ESP-IDF’s logging system uses tags and verbosity levels to produce structured, configurable output, helping you keep code clean and debug more effectively.","title":"ESP-IDF tutorial series: Logging","type":"blog"},{"content":"","date":"23 September 2025","externalUrl":null,"permalink":"/tags/apache/","section":"Tags","summary":"","title":"Apache","type":"tags"},{"content":"","date":"23 September 2025","externalUrl":null,"permalink":"/tags/data/","section":"Tags","summary":"","title":"Data","type":"tags"},{"content":"","date":"23 September 2025","externalUrl":null,"permalink":"/tags/flash/","section":"Tags","summary":"","title":"Flash","type":"tags"},{"content":" Introduction # When developing embedded applications, one of the challenges developers may face is persistent data storage. Whether you need to store long term important information such as configuration parameters, sensor calibration data or user preferences, understanding how to utilize flash memory can be a game changer.\nEspressif SoCs come equipped with internal flash memory that can be partitioned and utilized for various storage needs beyond just program code. NuttX provides mechanisms to access and manage this flash storage.\nThis article will guide you through the different options available for storing custom user data in flash memory. First, we\u0026rsquo;ll compare flash memory across Espressif devices, followed by an analysis of some file systems available for use. Then some examples are provided for each file system. Finally, we develop an application that connects to Wi-Fi, updates the system clock and logs the current time to a file that is stored on flash.\nAbout Flash Memory # Before diving into the article, we need to understand what is flash memory and its limitations. We will refer to it as flash or SPI Flash interchangeably, since flash memory in Espressif devices is accessed via SPI bus.\nWhat is SPI Flash NOR # SPI Flash NOR memory is a type of flash memory that, unlike NAND, is not used for mass data storage, such as in flash drives or SD cards. Its main function is to store executable code, like the firmware of a device. It\u0026rsquo;s the ideal flash memory for what computers call the BIOS or the EFI (Extended Firmware Interface).\nWhy use SPI Flash NOR # SPI Flash NOR memory offers several advantages for specific applications:\nRead speed: Fast, random reading is the most important characteristic of SPI Flash NOR memory. This is crucial for systems that need to boot quickly, as the boot code must be loaded to the processor as fast as possible. Random access: In NAND memory, reading and writing are done in data blocks. If the processor needs a single bit of information, it has to read the entire block. In NOR memory, it can access the information directly, bit by bit. Reliability: NOR technology is more reliable than NAND in terms of durability and long-term data retention. Additionally, it has fewer read and write errors. Compact size: SPI Flash NOR chips are small and have few pins, which saves space on printed circuit boards. Why not use it for data storage # Despite all its advantages, SPI Flash NOR is not suitable for mass data storage for two main reasons:\nCost: The cost per bit of NOR memory is much higher than that of NAND. Storage density: NOR memory has a much lower storage density than NAND. In short, SPI Flash NOR is ideal for storing executable code that needs to be read quickly and randomly. For mass data storage, NAND memory is a better option because it is cheaper and has a higher density.\nEspressif Flash Memory Overview # Espressif devices are available with a range of SPI flash sizes, typically from 4 MB up to 16 MB, depending on the specific SoC and module variant selected.\nSoC Common SPI Flash Sizes ESP32 4 MB to 16 MB ESP32-S2 4 MB to 16 MB ESP32-C3 4 MB ESP32-S3 8 MB to 16 MB ESP32-C6 4 MB to 8 MB ESP32-H2 4 MB ESP32-P4 8 MB or 16 MB ESP32-C5 4 MB to 8 MB Flash Memory and NuttX # When using NuttX, a few addresses will define the flash partitioning depending on the bootloader used.\nSimple boot is the default bootloader used in NuttX. It is explained in detail for Zephyr in this article, however the same principles apply for NuttX.\nThe simple boot approach relies on a single binary file flashed at the beginning of flash memory (0x0000 or 0x1000 for ESP32 and ESP32-S2). There is no limit to the size of the binary except for the maximum flash size.\nThe alternative to simple boot is MCUBoot, which also adds OTA capabilities. In this case, the binary images will have maximum sizes and the flash is divided into specific partitions such as: slot 0, slot 1, scratch and bootloader.\nThis article will focus on simple boot.\nFlash Memory Layout # As an example, we\u0026rsquo;ll be using an ESP32-C3-DevKitC-02, which comes with 4 MB of SPI Flash.\nWhen a binary is generated, it contains the bootloader and application code, which in this case is the NuttX RTOS. Then, it is flashed at the starting address of 0x0000.\nThe example below illustrates what a 1.5 MB binary would look like when flashing.\nESP32-C3 Flash Memory Layout (Simple Boot) - 4MB Total Address Range | Size | Description ------------------|----------|---------------------------------- 0x000000 | | ┌─────────────────────────────────┐ | | | │ │ | | | │ Application Image │ | | ~1.5MB | │ (Bootloader + │ | | | │ NuttX RTOS + │ | | | │ User Applications) │ | | | │ │ 0x180000 | | ├─────────────────────────────────┤ | | | │ │ | | | │ │ | | ~2.5MB | │ Available Flash │ | | | │ (Unused/Future Use) │ | | | │ │ | | | │ │ 0x400000 | | └─────────────────────────────────┘ (4MB Total) Key Addresses: - Application Start: 0x000000 - Application End: ~0x180000 (varies with build size) - Total Flash Size: 0x400000 (4MB) - Available Space: ~2.5MB for user data/future use In this simple boot configuration, the entire NuttX application (including bootloader, kernel, and user applications) is contained in a single binary image. The remaining flash space can be utilized for data storage.\nReserving Flash for General Use # Now, to reserve some area for persistent data, we can enable the SPI Flash support on NuttX, which will register a Memory Technology Device (MTD) driver entry at /dev that allows access from user space.\nThe MTD base address is the flash offset for the MTD partition. This offset automatically defines what the maximum binary image size should be, this way we avoid overlapping the persistent data with the application image.\nAs an example, we can set the MTD base address to 0x110000, which means that the application image could go up to 1.1 MB. We also need a MTD partition size, which for the sake of an example will be set to 0x100000, which is 1 MB. This new layout is illustrated below.\nESP32-C3 Flash Memory Layout (Simple Boot with MTD) - 4MB Total Address Range | Size | Description ------------------|----------|---------------------------------- 0x000000 | | ┌─────────────────────────────────┐ | | | │ │ | | | │ Application Image │ | | 1.1MB | │ (Bootloader + │ | | | │ NuttX RTOS + │ | | | │ User Applications) │ | | | │ │ 0x110000 | | ├─────────────────────────────────┤ | | | │ │ | | 1MB | │ MTD Partition │ | |(0x100000)| │ (User Data Storage) │ | | | │ │ 0x210000 | | ├─────────────────────────────────┤ | | | │ │ | | ~1.9MB | │ Available Flash │ | | | │ (Unused/Future Use) │ | | | │ │ 0x400000 | | └─────────────────────────────────┘ (4MB Total) Key Addresses: - Application Start: 0x000000 - Application Limit: 0x110000 (1.1MB max) - MTD Partition: 0x110000 - 0x210000 (1MB) - Total Flash Size: 0x400000 (4MB) - Available Space: ~1.9MB for future use The MTD partition at 0x110000 provides a dedicated 1MB region accessible via /dev/mtdX for user data storage. This partition can be used with file systems like SPIFFS or LittleFS, or accessed directly for custom storage implementations.\nSetting Up SPI Flash in NuttX # The following sections describe some of the common file systems and how to enable them for SPI Flash use on NuttX.\nFile System Options # NuttX supports several file systems for flash storage, each with distinct characteristics. Three examples are presented below, which are currently supported on NuttX for Espressif devices.\nSmartFS - Sector Mapped Allocation for Really Tiny (SMART) Flash\nNuttX-specific file system optimized for embedded systems Good balance of features and resource usage Built-in journaling for power-loss protection Moderate complexity with good performance characteristics Documentation: SmartFS SPIFFS - SPI Flash File System\nLightweight, designed specifically for SPI NOR flash Good for small files and read-heavy workloads Limited wear leveling and power-loss resilience Simple implementation with minimal RAM usage Documentation: SPIFFS LittleFS\nModern file system with excellent power-loss resilience Built-in wear leveling and dynamic wear leveling Better performance for mixed read/write workloads Higher RAM usage but more robust than SPIFFS Documentation: LittleFS The documentation on ESP-IDF website can also be consulted for more detailed technical information: File System Considerations.\nSmartFS # First of all, we configure NuttX to use ESP32-C3 with a pre-configured SPI Flash scenario.\n./tools/configure.sh esp32c3-generic:spiflash Next, open menuconfig:\nNavigate to System Type \u0026gt; SPI Flash Configuration Here, you\u0026rsquo;ll find options such as Storage MTD base address in SPI Flash and Storage MTD size in SPI Flash. Set these values to match the region you reserved for general use (see the Reserving Flash for General Use section above). This ensures your file system or storage implementation uses the correct flash positioning.\nEnable auto mounting MTD partition: Main Menu \u0026gt; Board Selection \u0026gt; set Mount SPI Flash MTD on bring-up to SmartFS. You may now exit menuconfig, save the configuration, build and flash.\n$ make -j10 $ make flash ESPTOOL_BINDIR=./ ESPTOOL_PORT=/dev/ttyUSB0 Testing SmartFS # Open the serial interface and reboot the board, you should see the boot log. Two scenarios could happen now:\nYou already had SmartFS configured on this flash region and the system boots without warnings. It is the first time you boot using SmartFS and the system asks you to format the partition. The second option looks like this:\n*** Booting NuttX *** dram: lma 0x00000020 vma 0x3fc83af0 len 0x644 (1604) [...] total segments stored 6 ERROR: Failed to mount the FS volume: -19 Smartfs seems unformatted. Did you run \u0026#39;mksmartfs /dev/smart0\u0026#39;? ERROR: Failed to setup smartfs ERROR: Failed to initialize SPI Flash NuttShell (NSH) NuttX-12.8.0 nsh\u0026gt; If that is the case, run mksmartfs /dev/smart0 so the partition is properly formatted. When finalized, reboot the board and you should not see any errors, as expected in option 1.\nNow run ls / to see your file system. A directory called /data should be available and that is now your SPI Flash available for general use.\nnsh\u0026gt; ls / /: data/ dev/ proc/ To test if it works, write a hello world to a file, reboot the board and read it back:\nnsh\u0026gt; echo \u0026#39;Hello Espressif Developer Portal!\u0026#39; \u0026gt; /data/hello.txt nsh\u0026gt; ls /data /data: hello.txt Reboot the board.\nNuttShell (NSH) NuttX-12.8.0 nsh\u0026gt; ls /data /data: hello.txt nsh\u0026gt; cat /data/hello.txt Hello Espressif Developer Portal! nsh\u0026gt; SPIFFS # SPIFFS has a similar procedure, with few changes required.\nOn menuconfig:\nEnable SPIFFS on auto-mount: Board Selection \u0026gt; set Mount SPI Flash MTD on bring-up to SPIFFS. Enable BSD License support: License Setup \u0026gt; Use components that have BSD licenses Enable large file support: File Systems \u0026gt; Large File Support (CONFIG_FS_LARGEFILE) Optionally, disable SMART FS: File Systems \u0026gt; SMART File system. Repeat the make and flash procedure, and open the serial port. You should again see the /data directory available for use:\nnsh\u0026gt; ls /: data/ dev/ proc/ And the hello world is still present:\nnsh\u0026gt; cat /data/hello.txt Hello Espressif Developer Portal! LittleFS # Repeat the previous steps on the Board Selection menu by changing SPI Flash bring-up to LittleFS, then navigating to File Systems and disabling SPIFFS.\nOn menuconfig:\nEnable LittleFS on auto-mount: Board Selection \u0026gt; set Mount SPI Flash MTD on bring-up to LittleFS. Optionally, disable SPIFFS: File Systems \u0026gt; SPIFFS File System. Repeat the make and flash procedure. Now when you boot and look into /data you will see that it is empty. That is because LittleFS is not compatible with SPIFFS or SmartFS.\nWe should format the partition use it as usual. First, obtain the name of the flash device under /dev. In this example, it is /dev/espflash. Then, format the partition with flash_eraseall and reboot the board.\nnsh\u0026gt; ls /dev /dev: console espflash null random ttyS0 zero nsh\u0026gt; flash_eraseall /dev/espflash Reboot the board.\nnsh\u0026gt; echo \u0026#39;Hello Espressif Developer Portal!\u0026#39; \u0026gt; /data/hello.txt nsh\u0026gt; ls /data /data: . .. hello.txt nsh\u0026gt; cat /data/hello.txt Hello Espressif Developer Portal! Success! We can save files on our SPI Flash and have demonstrated it in three different file systems.\nPractical Application # Now that we have managed to take control of the SPI Flash, we may now create an application that makes use of this functionality.\nLet\u0026rsquo;s say our application needs to log the last time the board was reset, however we don\u0026rsquo;t have RTC but we do have Wi-Fi available. My goal is to save date and time of each reboot on flash after Wi-Fi connects, so I can monitor downtime.\nFirst, our board should connect to Wi-Fi, synchronize its clock and write the current date and time to a file.\nFor this to work, we need: functional Wi-Fi, Network Time Protocol (NTP) and some automation. The Wi-Fi part we are not going to look deep into since we have other articles on it, instead, let\u0026rsquo;s go straight to NTP and automating.\nCheck the following for instructions on wireless connectivity:\nNuttX Getting Started Wi-Fi Network Configuration for Motor Control ESP32-C3 NuttX Documentation on Wi-Fi Understanding NTP # Network Time Protocol (NTP) is a networking protocol used to synchronize the clocks of computers and embedded devices over a network. It allows devices to obtain accurate time information from NTP servers, ensuring that system clocks are consistent and correct. In embedded systems like NuttX, NTP is commonly used to set the system time after boot or network reconnection, especially when there is no real-time clock (RTC) hardware available.\nStart a new NuttX environment using the wifi defconfig:\n./tools/configure.sh esp32c3-generic:wifi Configure NTP on menuconfig:\nEnable the NTP client: Application Configuration \u0026gt; Network Utilities \u0026gt; enable NTP client Enable NTP daemon commands: Application Configuration \u0026gt; System Libraries and NSH Add-Ons \u0026gt; enable NTP Daemon Commands Now build and flash the device.\nOpen the serial port and connect to Wi-Fi. Once we are connected, we should start the NTP task, which will try to synchronize the system clock over the network.\nConnect to Wi-Fi:\nnsh\u0026gt; wapi psk wlan0 espmint123 3 3 nsh\u0026gt; wapi essid wlan0 Nuttx-IOT 1 nsh\u0026gt; renew wlan0 Start the NTP client:\nnsh\u0026gt; ntpcstart Starting NTP client... Using NTP servers: 0.pool.ntp.org;1.pool.ntp.org;2.pool.ntp.org NTP client started successfully (task ID: 10) NTP client is now running in the background Now wait a few seconds and run the date command.\nnsh\u0026gt; date Fri, Sep 05 19:34:43 2025 We should now have our system clock in perfect sync!\nAutomating Boot Time Logging # Now that we know how to synchronize the system clock to the network, we should do this automatically.\nEnable Startup Script # To achieve our automation, we enable the ROMFS and startup script. The startup script is able to run sh commands after the initial system bring-up, which we can use for automating network connection and saving the date in flash.\nOn menuconfig:\nEnable ROMFS: File Systems -\u0026gt; enable ROMFS file system (CONFIG_FS_ROMFS). Enable auto-mounting /etc: RTOS Features \u0026gt; Tasks and Scheduling \u0026gt; enable Auto-mount etc baked-in ROMFS image (CONFIG_ETC_ROMFS). Now flash the board and open the serial console. We should see two messages before the NSH banner, and the /etc file system.\ntotal segments stored 7 rc.sysinit is called! rcS file is called! NuttShell (NSH) NuttX-12.8.0 nsh\u0026gt; ls /etc/init.d /etc/init.d: . .. rc.sysinit rcS nsh\u0026gt; Success! We have a simple script that echoes a message before the shell is available.\nConnecting to Wi-Fi and Logging Date # Now we need to automate Wi-Fi and date logging. At this point, because we are using Wi-Fi, the SPI Flash support should already be enabled.\nNavigate to nuttx/boards/risc-v/esp32c3/common/src/etc/init.d and add the WAPI commands to automatically connect to Wi-Fi and log the date on the rcS file:\nwapi psk wlan0 espmint123 3 3 wapi essid wlan0 Nuttx-IOT 1 renew wlan0 ntpcstart echo \u0026#34;Wait until date is synced...\u0026#34; sleep 10 date \u0026gt;\u0026gt; /data/log.txt This will connect to Wi-Fi, start the NTP client and sleep for a while so it has time to update the date information. Then, save the date to a log file.\nBuild and flash the binary. We should now see the following on the log file:\n*** Booting NuttX *** [...] rc.sysinit is called! rcS file is called! Started the NTP daemon as PID=10 Wait until date is synced... NuttShell (NSH) NuttX-12.8.0 nsh\u0026gt; cat /data/log.txt Mon, Sep 15 12:48:58 2025 nsh\u0026gt; Rebooting the board, we should get a new line with the correct time, while still retaining in flash the previous date:\nnsh\u0026gt; cat /data/log.txt Mon, Sep 15 12:48:58 2025 Mon, Sep 15 12:51:33 2025 nsh\u0026gt; Conclusion # This article has demonstrated how to effectively utilize flash memory for persistent data storage in NuttX-based embedded systems. We\u0026rsquo;ve covered the fundamental concepts of SPI Flash NOR memory, explored different file system options (SmartFS, SPIFFS, and LittleFS), and implemented a practical application that logs system boot times to flash storage.\nThose are important takeaways:\nFlash Memory Understanding: SPI Flash NOR is ideal for storing executable code and small amounts of persistent data, but not suitable for mass storage due to cost and density limitations.\nFile System Selection: Each file system has distinct characteristics:\nSmartFS: Good balance of features with built-in journaling SPIFFS: Lightweight and simple, ideal for read-heavy workloads LittleFS: Modern with excellent power-loss resilience and wear leveling Practical Implementation: The boot time logging example demonstrates how to combine Wi-Fi connectivity, NTP synchronization, and flash storage to create a robust data logging system.\nDate Logging Example Considerations # While the example uses a simple sleep 10 approach to wait for NTP synchronization, more sophisticated implementations are possible:\nPolling-based synchronization: Instead of sleeping, implement a loop that checks if the system time has been updated by NTP Callback mechanisms: Use NTP client callbacks to trigger logging only after successful time synchronization Timeout handling: Implement proper timeout mechanisms to avoid indefinite waiting These approaches would provide more reliable and efficient date logging, especially in production environments where network conditions may change.\nRelated Resources # NuttX ESP32 Documentation ESP32 Flash Encryption ESP32-C6 Technical Reference Manual NuttX File System Documentation Getting Started with NuttX and ESP32 SPIFFS LittleFS FAT FS SmartFS NTP Daemon NTP Client ","date":"23 September 2025","externalUrl":null,"permalink":"/blog/2025/09/nuttx-storing-data-spi-flash/","section":"Blog","summary":"This guide explores how to utilize flash memory for persistent data storage in NuttX-based embedded systems, covering SPI Flash fundamentals, file system options (SmartFS, SPIFFS, LittleFS), and practical implementation of a boot time logging application with Wi-Fi and NTP synchronization.","title":"SPI Flash for Persistent Data Storage with NuttX RTOS","type":"blog"},{"content":" Overview # In recent years, the rapid evolution of IoT and AI technologies has significantly enhanced the sensing capabilities of connected devices. Camera sensors are typically used to capture images, providing devices with visual perception capabilities.\nesp-video is a camera application development component provided by Espressif, designed to provide developers with a simplified, efficient and cost-effective solution for building vision applications. Developers can use esp-video component to quickly drive various types of camera sensors. The key features of the component are:\nUse cases # The ESP32 chips can be connected to various camera sensors. The following applications have been implemented:\nImage transmission: ESP32 series of chips equipped with robust networking (Wi-Fi, BLE, Zigbee, Ethernet), these chips enable long-distance transmission of captured images and videos.\nSegmented Capture: Integrated with ESP32’s Mesh network, this feature splits tasks between low-power devices (for detection) and high-power devices (for video capture).\nAI Applications: ESP32-S and ESP32-P series of chips support on-device AI via esp-dl and esp-who, enabling features like face recognition, motion tracking, barcode scanning, and more. They also preprocess data (e.g., human detection) for cloud AI. Current applications include smart pet feeders, remote utility monitoring, automated grading, medical testing, and human presence detection.\nMulti-Camera Systems:\nDual-Focus Setup: Near-camera (close objects) + far-camera (distant objects).\nColor + Monochrome: Color imaging for detail, monochrome for enhanced night vision sensitivity.\n360° Coverage: Directional modules (e.g., conference cameras) capture all participants around a table.\nesp-video supports simultaneous connections to multiple camera sensors. The following figure shows the effect of running simple_video_server on the ESP32-P4-Function-EV-Board:\nesp-video and esp32-camera # esp32-camera is the first-generation camera application development component, which has a driver for image sensors compatible with the ESP32 series of chips. esp-video is an enhanced version of esp32-camera. The key differences are as follows:\nFeature esp-video esp32-camera Supported Chips ESP32-S3, ESP32-P/C series ESP32, ESP32S2/S3 Real-Time Performance High frame rates Standard ISP Capability Built-in (ESP32-P Series) Not supported Video Encoding H.264/JPEG (high-speed) Not supported Key design principles # esp-video focuses on the following four core strengths:\nUser-Friendly Design: The component’s API aligns with the V4L2 (Video for Linux 2) standard, enabling developers to interact with cameras as easily as handling regular files—just call open() to get started.\nHigh Performance: Optimized hardware-software integration and image processing algorithms (IPA) ensure fast startup, smooth preview, and responsive capture during photo operations.\nConsistent Functionality: Supporting chips like ESP32-S3, ESP32-P series, and ESP32-C series, the component achieves unified device control through a standardized abstraction layer for underlying interfaces. Whether it’s diverse camera sensors or system components like ISPs, codecs, and VCMs, all can be managed via ioctl(). As shown, common interfaces (MIPI-CSI, DVP, SPI, USB) share the same open() and ioctl() workflow for seamless operation.\nFlexible Expansion: Developers can customize configurations for existing cameras or add new peripheral drivers and control commands to extend functionality.\nFramework architecture # The entire camera application development framework follows a clear four-layer structure, and the esp-video component is located in the middleware layer. The main contents of each layer are:\nDriver Layer: Low-level drivers for peripherals such as MIPI-CSI, DVP, SPI, I2C, I3C, ISP, JPEG, and H.264.\nDevice Layer: Abstracts hardware variations, reducing integration complexity while ensuring broad compatibility.\nMiddleware Layer: Routes commands to the correct device, executes them, and returns results to the application.\nApplication Layer: Offers a unified API to simplify development.\nGetting started # Find supported camera sensors at esp_cam_sensor. Select a supported device from the list of supported video devices based on the hardware interface being used. Open the device using open(). Retrieve image data with ioctl(fd, VIDIOC_DQBUF, ...). Release memory after use via ioctl(fd, VIDIOC_QBUF, ...). A simple example of capturing image data from a camera sensor is capture_stream. Explore more examples at esp-video/examples.\nFinal thoughts # Looking for a quick, reliable way to build camera applications? esp-video combines an intuitive API with strong community backing—ideal for accelerating your project.\nFeel free to use esp-video and share your feedback with us!\nContact: sales@espressif.com for project evaluation or development support.\n","date":"22 September 2025","externalUrl":null,"permalink":"/blog/2025/09/esp-video-introduction/","section":"Blog","summary":"The esp-video component provides a solution to build camera applications on the ESP32 chips. This article will introduce the esp-video component, how to use it, and will give an overview of the framework around it.","title":"Building Smarter Camera Applications with esp-video","type":"blog"},{"content":"","date":"22 September 2025","externalUrl":null,"permalink":"/tags/esp32-c6/","section":"Tags","summary":"","title":"ESP32-C6","type":"tags"},{"content":"","date":"22 September 2025","externalUrl":null,"permalink":"/tags/multimedia/","section":"Tags","summary":"","title":"Multimedia","type":"tags"},{"content":"","date":"22 September 2025","externalUrl":null,"permalink":"/tags/video/","section":"Tags","summary":"","title":"Video","type":"tags"},{"content":"","date":"22 September 2025","externalUrl":null,"permalink":"/authors/wang-yu-xin/","section":"Developer Portal Authors","summary":"","title":"Wang-Yu-Xin","type":"authors"},{"content":"JPEG is a widely used image compression format, favored for its high compression ratio and good visual quality. However, running a JPEG encoder or decoder on resource-constrained embedded devices can be challenging, especially on chips without hardware JPEG support, as the encoding and decoding process often consumes significant CPU and memory resources.\nTo address this issue, Espressif has released the ESP_NEW_JPEG component, which features a highly optimized software codec and leverages SIMD instructions to enhance processing efficiency. This article provides a brief overview of the JPEG compression principles and explains how to use ESP_NEW_JPEG, along with important usage notes.\nGeneral Knowledge of JPEG # In image processing, the camera typically captures and the display screen presents raw image data. Taking a common RGB888 color image as an example, each pixel contains information from three color channels: red, green, and blue, with each channel typically occupying one byte. For an image captured from a VGA camera (640×480 pixels), the total size is calculated as width × height × bytes per pixel = 640 × 480 × 3 = 921600 bytes, or roughly 900 KB. For embedded devices with limited memory, this amount of raw image data is quite large.\nTo solve the problem of storage and transmission efficiency, the Joint Photographic Experts Group (JPEG) introduced the JPEG standard, which defines how a codec compresses image data into a byte stream and restores it during decoding. JPEG typically achieves a compression ratio of 10:1, reducing the size of the same image to just a few tens of kilobytes. This significantly saves storage space and reduces the bandwidth required for transmission.\nJPEG is widely used in various scenarios, including digital photography, network transmission, and screen image display. Here are two typical applications:\nCompressing images captured by a camera into JPEG format for storage on an SD card or transmission over a network. Decoding JPEG images into image data for screen display. JPEG compression is a lossy compression technique that makes use of the human eye\u0026rsquo;s insensitivity to color details and high-frequency information. It selectively discards parts of the image data to reduce file size without significantly affecting visual quality. Additionally, JPEG further reduces the file size using compression techniques such as entropy coding, ensuring good visual quality while significantly decreasing storage and transmission requirements.\nThe JPEG compression process can be summarized in the following steps:\nColor Space Conversion: The image is converted from the RGB color space to the YCbCr color space, separating luminance (Y) and chrominance (Cb, Cr) components. Since the human eye is more sensitive to luminance, chrominance components can be compressed at a lower resolution in subsequent steps. Image Block Division: The image is divided into small blocks, with each block processed independently to simplify calculations and improve compression efficiency. Discrete Cosine Transform (DCT): A discrete cosine transform is applied to each block, converting the image data from the spatial domain to the frequency domain. This transformation concentrates the image\u0026rsquo;s energy into the lower-frequency components. Quantization: The DCT coefficients are compressed based on a predefined quantization table. Smaller or higher-frequency coefficients are set to zero, making it easier to compress the data in the next steps. Entropy Coding: The quantized coefficients are arranged and further compressed using entropy coding techniques such as Huffman coding, resulting in the final JPEG byte stream. Introduction to ESP_NEW_JPEG # ESP_NEW_JPEG is a lightweight JPEG codec library developed by Espressif. To enhance efficiency, the JPEG encoder and decoder have been deeply optimized to reduce memory usage and improve processing performance. On ESP32-S3 chips that support SIMD instructions, these instructions are utilized to further accelerate processing. In addition, features like rotate, clipper, and scale have been integrated, allowing them to be performed simultaneously during encoding or decoding, simplifying user operations. For chips with limited memory, a block mode is introduced, enabling multiple passes over portions of the image to reduce memory loading.\nESP_NEW_JPEG supports baseline profile JPEG encoding and decoding. Features such as rotate, clipper, scale, and block mode are only effective under specific configurations. The next two sections will provide detailed information on the functions and configuration requirements of the encoder and decoder.\nFunctions of JPEG Encoder # Basic features supported by the encoder:\nSupport encoding for any width and height Support pixel formats: RGB888, RGBA, RGB565(big endian), RGB565(little endian), YCbYCr, YCbY2YCrY2, CbYCrY and GRAY When using the YCbY2YCrY2 format, only YUV420 and Gray subsampling are supported Support YUV444, YUV422, YUV420, and Gray subsampling Support quality settings in the range of 1-100 Extended features:\nSupport 0°, 90°, 180°, and 270° clockwise rotation Support dual-task encoding Support block mode encoding The dual-task encoder can be used on dual-core chips, taking full advantage of parallel encoding. The principle is that one core handles the main encoding task, while the other core is responsible for the entropy encoding part. In most cases, enabling dual-core encoding provides approximately a 1.5x performance boost. You can configure whether to enable dual-core encoding and adjust the core ID and priority for the entropy encoding task through menuconfig.\nBlock mode refers to encoding one image block at a time. After multiple passes, the entire image is encoded. In YUV420 subsampling, each block has a height of 16 rows and a width equal to the image width. For other subsampling, each block has a height of 8 rows and a width equal to the image width. Since block encoding processes smaller chunks of data at a time, the image buffer can be stored in DRAM, which improves encoding speed. The workflow for block encoding is shown in the diagram below:\nBlock mode encoder processing workflow The configuration requirements for extended features are as follows:\nThe configuration requirements of encoder When dual-task encoding is enabled, the rotation feature is not supported Block mode encoding requires the image height to be an integer multiple of the block height When rotation is enabled, only the two parameter combinations listed in the image are supported Functions of JPEG Decoder # Basic Features Supported by the Decoder:\nSupport decoding for any width and height Support both single-channel and three-channel decoding Support pixel format outputs: RGB888, RGB565 (big endian), RGB565 (little endian), CbYCrY Extended Features:\nSupport scale (with a maximum reduction ratio of 1/8) Support clipper (with the top-left corner as the origin) Support 0°, 90°, 180°, and 270° clockwise rotation Support block mode decoding The processing flow for scale, clipper, and rotate is sequential, as shown in the diagram below. The decoded JPEG data stream is first scaled, then clipped, and finally rotated before being output.\nSequential processing flow of scale, clipper, and rotate When using scale and clipper, you need to configure the corresponding parameters in jpeg_resolution_t struct defined in esp_jpeg_dec.h, and it supports processing only the width or height individually. For example, if you want to clip only the width while keeping the height unchanged, you can set clipper.height = 0. For the processing flow illustrated above, both the detailed configuration and the simplified configuration described below are supported.\n// Detailed configuration jpeg_dec_config_t config = DEFAULT_JPEG_DEC_CONFIG(); config.output_type = JPEG_PIXEL_FORMAT_RGB565_LE; config.scale.width = 320; config.scale.height = 120; config.clipper.width = 192; config.clipper.height = 120; config.rotate = JPEG_ROTATE_90D; // Simplified configuration jpeg_dec_config_t config = DEFAULT_JPEG_DEC_CONFIG(); config.output_type = JPEG_PIXEL_FORMAT_RGB565_LE; config.scale.width = 0; // keep width unchanged by setting to 0 config.scale.height = 120; config.clipper.width = 192; config.clipper.height = 0; // keep height unchanged by setting to 0 config.rotate = JPEG_ROTATE_90D; Block mode refers to decoding one image block at a time. After multiple passes, the entire image is decoded. In YUV420 subsampling, each block has a height of 16 rows and a width equal to the image width. For other subsampling, each block has a height of 8 rows and a width equal to the image width. Since block decoding processes smaller chunks of data at a time, it is more suitable for chips without PSRAM. Additionally, placing the output image buffer in DRAM can also help improve decoding speed. Block decoding can be viewed as the reverse process of block mode encoding.\nThe configuration requirements for extended features are as follows:\nThe configuration requirements of decoder When block decoding is enabled, other extended features cannot be used The width and height in the configuration parameters for scale, clipper, and rotate must each be a multiple of 8 When both scale and clipper are enabled, the clipped size must be smaller than the scaled size How to Use ESP_NEW_JPEG # The ESP_NEW_JPEG repository is hosted on GitHub. You can add ESP_NEW_JPEG to your project by entering the following command in your project directory:\nidf.py add-dependency \u0026#34;espressif/esp_new_jpeg\u0026#34; The test_app folder under the esp_new_jpeg folder contains a runnable test project, which demonstrates the relevant API call flow. Before using ESP_NEW_JPEG, it is recommended to debug this test project to get familiar with the API usage. This section will further introduce the use cases within the test_app.\nUsage of JPEG Encoder # The reference code for encoding can be found in the esp_new_jpeg/test_app/main/test_encoder.c file. The typical encoding flow can be referenced from the esp_jpeg_encode_one_picture function. The execution sequence of this function is as follows:\nCall jpeg_enc_open to create an encoder handle based on the configuration parameters. Use jpeg_enc_process to encode the image data into JPEG. Finally, call jpeg_enc_close to close the handle and release resources. Block mode is suitable for chips with limited memory resources. The function esp_jpeg_encode_one_picture_block demonstrates the usage of block mode. The simplified code is as follows:\njpeg_error_t esp_jpeg_encode_one_picture_block() { // Configure encoder jpeg_enc_config_t jpeg_enc_cfg = DEFAULT_JPEG_ENC_CONFIG(); int image_size = width * height * byte_per_pixel; // Initialize encoder jpeg_enc_handle_t jpeg_enc = NULL; jpeg_enc_open(\u0026amp;jpeg_enc_cfg, \u0026amp;jpeg_enc); // Get block_size and calculate process times int block_size = jpeg_enc_get_block_size(jpeg_enc); num_times = image_size / block_size; // Allocate input buffer to store a block of input image uint8_t *inbuf = (uint8_t *)jpeg_calloc_align(block_size, 16); // Allocate output buffer to store whole jpeg data uint8_t *outbuf = (uint8_t *)calloc(1, outbuf_size); // Encoding loop for (size_t j = 0; j \u0026lt; num_times; j++) { /* User logic: Prepare data for encoding */ // Encode a block of image ret = jpeg_enc_process_with_block(jpeg_enc, inbuf, block_size, outbuf, outbuf_size, \u0026amp;out_len); if (ret \u0026lt; JPEG_ERR_OK) { goto jpeg_example_exit; } } jpeg_example_exit: /* User logic: Finish encoding */ // Release resource jpeg_enc_close(jpeg_enc); jpeg_free_align(inbuf); free(outbuf); } Usage of JPEG Decoder # The reference code for decoding can be found in the esp_new_jpeg/test_app/main/test_decoder.c file. The typical decoding operations can be referenced from the esp_jpeg_decode_one_picture function. The decoding process is as follows:\nCall jpeg_dec_open to create a decoder handle based on the configuration parameters. Use jpeg_dec_parse_header to parse the JPEG header. Call jpeg_dec_process to decode the JPEG data into image data. Finally, call jpeg_dec_close to close the handle and release resources. Block mode is commonly used for decoding JPEG data and displaying it on an LCD screen. Using block mode, each small chunk of data can be directly decoded and output to the LCD buffer, reducing memory copying and improving decoding efficiency. You can refer to the calling logic of the esp_jpeg_decode_one_picture_block function for implementation.\nIf continuous decoding of multiple JPEG files with the same size, subsampling, and other parameters is required, such as decoding and displaying an AVI video, refer to the functions esp_jpeg_stream_open, esp_jpeg_stream_decode, and esp_jpeg_stream_close. The simplified calling logic is as follows:\nCreate a decoder handle before decoding. In each loop, call the decoding operation for continuous decoding. After decoding is completed, release the decoder resources. This method avoids allocating and releasing JPEG decoder resources with each decode, reducing unnecessary memory allocation and release operations, thereby improving efficiency. The simplified calling logic is shown below:\njpeg_error_t esp_jpeg_stream_open() { jpeg_dec_open(); } jpeg_error_t esp_jpeg_stream_decode() { jpeg_dec_parse_header(); jpeg_dec_process(); } jpeg_error_t esp_jpeg_stream_close() { jpeg_dec_close(); } void user_logic() { // Init decoder esp_jpeg_stream_open(); // Decoding jpeg while (/* Loop logic */) { esp_jpeg_stream_decode(); } // Release resource esp_jpeg_stream_close(); } ESP_NEW_JPEG vs ESP_JPEG Comparison # Two JPEG libraries are available for different use cases: ESP_NEW_JPEG and ESP_JPEG. Understanding the differences between these libraries can help you choose the most suitable one for your project.\nESP_NEW_JPEG is a feature-complete and performance-optimized JPEG codec library that supports both encoding and decoding, along with advanced image processing capabilities. ESP_JPEG is a lightweight decoder library based on the Tiny JPEG Decompressor (TJpgDec), focusing on minimal memory consumption and simplicity.\nThe following table provides a detailed comparison of the two libraries:\nFeature ESP_NEW_JPEG ESP_JPEG Encoding ✅ Supports multiple formats ❌ Not supported Decoding ✅ Advanced features (scale, clipper, rotate) ✅ Basic decoding with fixed scaling Pixel Formats RGB888, RGBA, RGB565, YCbYCr, YCbY2YCrY2, CbYCrY, GRAY RGB888, RGB565 Image Processing ✅ Scale, clipper, rotate (0°, 90°, 180°, 270°) ✅ Fixed scaling ratios (1/1, 1/2, 1/4, 1/8) Block Mode ✅ Both encoder and decoder ❌ Not supported ROM Support¹ ❌ Not available ✅ Available on ESP32, ESP32-S3, ESP32-C3, ESP32-C6, ESP32-C5, ESP32-C61 API Complexity Handle-based, more features Simple API Performance Higher throughput Lower memory footprint ¹ \u0026ldquo;ROM Support\u0026rdquo; indicates whether the JPEG library is built into the chip’s ROM. A ROM-based implementation helps reduce Flash usage.\nWhen to choose ESP_NEW_JPEG:\nYou need JPEG encoding functionality You need higher performance Your application requires advanced image processing features (rotation, custom scaling, clipper) You want to support multiple pixel formats When to choose ESP_JPEG:\nYou only need JPEG decoding functionality Memory usage is a critical constraint You\u0026rsquo;re using chips with ROM support and want to save flash space Conclusion # ESP_NEW_JPEG is a lightweight JPEG encoding and decoding library deeply optimized for the ESP32 series chips, offering efficient image compression and decompression capabilities. The library supports various features, including rotation, clipping, scaling, and block mode, enabling flexible handling of image data processing requirements in different application scenarios. We look forward to your experience with ESP_NEW_JPEG in practical applications and welcome your valuable feedback to help us continuously optimize and enhance the library\u0026rsquo;s performance and features.\n","date":"17 September 2025","externalUrl":null,"permalink":"/blog/2025/09/esp-new-jpeg-introduction/","section":"Blog","summary":"The ESP_NEW_JPEG library from Espressif enables efficient JPEG encoding and decoding on embedded devices. This article introduces the main features of ESP_NEW_JPEG \u0026ndash; including image rotation, clipping, scaling, and block mode \u0026ndash; and shares key usage tips for developers.","title":"Introducing ESP_NEW_JPEG: An Efficient JPEG Encoder and Decoder","type":"blog"},{"content":"","date":"17 September 2025","externalUrl":null,"permalink":"/tags/jpeg/","section":"Tags","summary":"","title":"JPEG","type":"tags"},{"content":"","date":"17 September 2025","externalUrl":null,"permalink":"/authors/lin-xu/","section":"Developer Portal Authors","summary":"","title":"Lin Xu","type":"authors"},{"content":"The introduction of the ESP-TEE framework for the ESP32-C6 SoC enables developers to integrate hardware-backed security directly into their connected products. By implementing a Trusted Execution Environment (TEE), ESP-TEE provides secure storage and cryptographic computations within a hardware-isolated environment that is resistant to scalable remote software attacks.\nBuilt on the RISC-V architecture, ESP-TEE on ESP32-C6 leverages specific ISA features like privilege modes, memory protection units, and custom hardware security features to establish a robust TEE. RISC-V\u0026rsquo;s open architecture and security extensions (built-in and customized) delivers the transparent, auditable foundation that regulatory-compliant IoT security demands.\nDesigned with modern IoT security standards in mind, ESP-TEE naturally aligns with the PSA Certified Level 2 (PSA-L2) profile, helping manufacturers meet rigorous certification requirements with minimal integration effort.\nMatter with ESP-TEE The ESP-TEE Security Profile # The ESP-TEE framework extends the capabilities of the ESP32 series SoCs by creating a hardware-enforced separation between critical security functions and the regular application environment (Rich Execution Environment, REE).\nResistance to Scalable Remote Attacks: Even if the user application (REE) is compromised, TEE-contained secrets remain secure, preventing large-scale remote key extraction.\nSecure Key Management: All private keys, both factory-provisioned and run-time generated, are derived and stored inside the TEE, never leave the protected environment, and are inaccessible to REE code.\nIsolated Cryptographic Operations: Signing, attestation, and key derivation execute entirely within the TEE, with the REE interacting only through controlled APIs - never accessing raw keys.\nFeature-Rich Security Services: ESP-TEE supports advanced features like TEE secure storage, secure OTA updates, and device attestation, enabling periodic verification of device identity and status through cryptographically secured tokens.\nSecuring Matter Keys with ESP-TEE # As explained in this article on the Matter Security Model, Matter devices have two primary types of keys that can be protected with ESP-TEE:\nDevice Attestation Certificate (DAC) keys - Typically programmed once per device in the factory and used during device commissioning to establish device identity and authenticity. Node Operational Certificate (NOC) keys - Generated at runtime by the device whenever it joins a Matter Fabric and used for session establishment throughout the device\u0026rsquo;s operational lifetime. Securing the Device Attestation Certificate (DAC) # According to the ESP-Matter documentation, the ESP32-C6 supports protecting the Device Attestation Certificate (DAC) private key either through secure storage or by deriving it at runtime using the hardware HMAC peripheral. In both cases, the keys are securely stored either directly in persistent storage or as a source in eFuse, but they become accessible to the user application during signing operations such as commissioning.\nESP-TEE significantly enhances these approaches by executing all DAC operations entirely within the TEE, ensuring private keys remain inaccessible to the application code and fully hardware-protected.\nSecure Storage: Stores the DAC private key in the TEE’s secure storage partition rather than in an encrypted ESP Secure Certificate Manager format partition. The TEE secure storage also provides an interface to sign the given data with the required key ID. This ensures protection from any unauthorized software modifications.\nHMAC-based PBKDF2 Derivation: Does not store the DAC private key at all. Instead, the key is computed at runtime using the ESP32-C6’s hardware HMAC peripheral (HMAC-SHA256) with PBKDF2. ESP-TEE controls access to the HMAC peripheral, so the entire key derivation process and signing happens in isolated execution environment, significantly reducing leakage risk.\nHMAC-based DAC: Standard Workflow HMAC-based DAC: Secured Workflow with ESP-TEE Securing Matter NOCs (Fabric Keys) # In non-TEE Matter deployments, fabric keys generated at runtime are stored in software-accessible memory, creating an attack surface for remote exploitation. With ESP-TEE, fabric keys are either securely stored or derived inside the TEE, and used for cryptographic operations without ever leaving the hardware-isolated environment - completely removing this vulnerability class.\nFabric Keys: Standard Workflow Fabric Keys: Secured Workflow with ESP-TEE Implementation Considerations # Incorporating ESP-TEE into ESP-Matter introduces a few system-level changes compared to a standard ESP-Matter build. These trade-offs are expected given the additional security. We have ensured that this has minimal impact to the development workflows and memory footprint characterisations of the firmware.\nIntegration is straightforward and requires only:\nEnable ESP-TEE by setting the CONFIG_SECURE_ENABLE_TEE Kconfig option.\nUpdate the partition table to include the required TEE components.\nThe rest of your development process remains unchanged - TEE firmware generation and signing are handled automatically by the build system. API compatibility is also ensured, so no modifications are required in the REE (user application).\nRefer to the ESP-TEE Usage guide for more details.\n1. Boot Flow Changes # The device boot sequence is modified when ESP-TEE is enabled. The TEE executes early in the boot process to handle all secure initialization for the system before the user application begins execution.\nDevice Boot-up flow for ESP32-C6 Device Boot-up flow for ESP32-C6 with ESP-TEE The TEE supports secure Over-The-Air (OTA) firmware updates. The REE handles the download through any transport mechanism (e.g., HTTPS, MQTT), while the TEE manages the write process and verification before activation, automatically rolling back if an update fails. Note that REE (application) updates continue to work exactly as before. Refer to the ESP-TEE OTA guide for more details.\n2. Memory Usage Impact # Enabling ESP-TEE introduces additional runtime overhead due to the TEE firmware and secure service execution. The following table shows measured heap usage before and after Matter commissioning for the light example:\nWorkflow Heap Standard (KB) with ESP-TEE (KB) △ (KB) Boot-up Free 276.35 245.19 31.16 Min. Free 276.05 244.89 31.16 After Commissioning Free 185.54 153.51 32.03 Min. Free 151.33 119.33 32.00 The memory delta represents the SRAM reserved for TEE operations, which can be managed through the CONFIG_SECURE_TEE_IRAM_SIZE and CONFIG_SECURE_TEE_DRAM_SIZE options. Also note that each secure service call incurs ~1000 CPU cycles to execute (6.25μs at 160MHz). This means commissioning and cryptographic flows will be slightly slower compared to standard implementations, but the difference is unnoticeable from an end-user perspective and system stability is not affected.\n3. Partition Table Layout # With ESP-TEE, the flash layout i.e. the partition table needs to be modified. The partition table requires four additional partitions to accommodate TEE components: two partitions for the TEE app (192 KB each - enabling secure OTA updates), one partition for the TEE OTA data, and one partition for the TEE secure storage, which consumes 448 KB of flash memory.\nWhile it is technically possible to use only one TEE app partition if TEE OTA is not required, this configuration is not recommended for production deployments. Hands-On Example: Matter Light # To illustrate the above facts, we implemented a Matter-enabled smart light on the ESP32-C6 with the DAC protection handled by ESP-TEE. While the device in this example is a light, the same security profile applies equally to any Matter device form factor - from sensors to controllers.\nNote: This example uses experimental ESP-IDF and ESP-Matter branches for demonstration purposes. The workflow may change once ESP-TEE integration is officially supported in a stable ESP-Matter release.\nPrerequisites # Ensure you have both ESP-IDF and ESP-Matter installed and configured as per the official ESP-Matter setup guide.\nTip: Set ${idf_path} and ${esp_matter_path} to your ESP-IDF and ESP-Matter directories respectively.\nESP-IDF # cd ${idf_path} git remote add demo git@github.com:laukik-hase/esp-idf.git git checkout demo/esp_matter_w_tee ESP-Matter # cd ${esp_matter_path} git remote add demo git@github.com:laukik-hase/esp-matter.git git fetch --no-recurse-submodules demo demo/esp_matter_w_tee git checkout demo/esp_matter_w_tee cd connectedhomeip/connectedhomeip git remote add demo git@github.com:laukik-hase/connectedhomeip.git git fetch --no-recurse-submodules demo demo/esp_matter_w_tee git checkout demo/esp_matter_w_tee These branches include the experimental integration of ESP-TEE secure services within the Matter Light example.\nActivating the Development Environment # export IDF_CCACHE_ENABLE=1 cd ${idf_path} source export.sh cd ${esp_matter_path}/connectedhomeip/connectedhomeip source scripts/activate.sh cd ../../ source export.sh Building and Flashing the Light Example # cd ${esp_matter_path}/examples/light idf.py set-target esp32c6 idf.py -p \u0026lt;PORT\u0026gt; build flash Flashing Test Certificates # To simulate a secure device, flash the secure partitions and certificates for a factory-provisioned setup with a valid DAC and secure storage.\nparttool.py --partition-table-offset 0xc000 erase_partition -n nvs parttool.py --partition-table-offset 0xc000 write_partition -n secure_storage --input test_certs/esp_tee_sec_stg_nvs.bin parttool.py --partition-table-offset 0xc000 write_partition -n esp_secure_cert --input test_certs/esp_secure_cert.bin parttool.py --partition-table-offset 0xc000 write_partition -n fctry --input test_certs/partition.bin Monitoring Serial Output # Use the following to check initialization logs and confirm Matter + ESP-TEE setup:\nidf.py monitor Alternative: PBKDF2-based DAC Workflow # By default, the example uses the DAC key stored in the TEE secure storage. To use the PBKDF2-based DAC workflow instead, follow the below steps.\nFirst, burn the example HMAC key to eFuse:\nespefuse.py -p PORT burn_key BLOCK_KEYx test_certs/hmac_key.bin HMAC_UP Note the eFuse key block number (x) - you\u0026rsquo;ll need this in the next step.\nConfigure ESP-TEE and Matter DAC settings with menuconfig:\nidf.py fullclean idf.py set-target esp32c6 idf.py menuconfig Navigate to (Top) → ESP-TEE (Trusted Execution Environment) → Enable the ESP-TEE framework → Secure Services and set Secure Storage: eFuse HMAC key ID for PBKDF2 key derivation to the value of x, the eFuse key block where the HMAC key was burned Navigate to (Top) → Component config → CHIP Device Layer → Commissioning options → Use Secure Cert DAC Provider → Use ESP32 TEE (Trusted Execution Environment) → TEE: DAC key source and enable PBKDF2-HMAC derivation with eFuse key Save and exit the configuration, then build, flash, and test the example:\nidf.py build flash # No need to flash the test certificates again parttool.py --partition-table-offset 0xc000 erase_partition -n nvs idf.py monitor Device Commissioning # Commission your device using the Matter controller tools, such as the chip-tool or the ESP-Rainmaker mobile app.\nConclusion # As regulatory frameworks such as the EU-CRA and RED DA come into force, and consumer expectations for security rise, ESP-TEE positions itself as a forward-looking solution for IoT. Its combination of hardware-backed protection and developer-friendly integration ensures manufacturers can meet tomorrow’s security standards today.\nBy anchoring all private keys and cryptographic operations within a hardware-isolated TEE, ESP-TEE empowers device vendors to deliver Matter products that are functional, secure and resilient against scalable, remote software attacks while achieving PSA-L2 certification readiness.\nThe convergence of Matter’s interoperability with ESP-TEE’s trusted security foundation creates a strong platform for the next generation of connected devices - where security is not an afterthought, but a core architectural principle embedded at the hardware level.\nFuture Integration: ESP ZeroCode # Looking ahead, ESP-TEE security will become seamlessly integrated with Espressif\u0026rsquo;s ESP ZeroCode platform, where enabling enterprise-grade security becomes as simple as checking a checkbox in the web interface. The TEE binary becomes a part of the system firmware, managed entirely by Espressif with automatic OTA updates for security fixes and features.\nThe rest of the development process remains exactly the same - developers simply enable ESP-TEE in the ZeroCode console and continue focusing on their device logic and product functionality while Espressif handles all underlying security infrastructure, ultimately delivering PSA-L2 certification-ready Matter devices without any additional effort.\nReferences # ESP-TEE: Documentation | Examples ESP-Matter: Documentation | Examples ","date":"12 September 2025","externalUrl":null,"permalink":"/blog/2025/09/matter_w_esp_tee_c6/","section":"Blog","summary":"As security expectations rise globally - driven by region-specific cybersecurity regulations - safeguarding device credentials has become critical for IoT manufacturers. This article explains how the ESP-TEE framework integrates with Matter and demonstrates building secure products using the Espressif RISC-V SoCs, showcasing hardware-enforced security that can resist scalable remote software attacks.","title":"Building Hardware-Enforced Trust into Matter Devices with ESP-TEE","type":"blog"},{"content":"","date":"12 September 2025","externalUrl":null,"permalink":"/tags/esp-tee/","section":"Tags","summary":"","title":"ESP-TEE","type":"tags"},{"content":"","date":"12 September 2025","externalUrl":null,"permalink":"/authors/laukik-hase/","section":"Developer Portal Authors","summary":"","title":"Laukik Hase","type":"authors"},{"content":"","date":"10 September 2025","externalUrl":null,"permalink":"/tags/devcon/","section":"Tags","summary":"","title":"Devcon","type":"tags"},{"content":"","date":"10 September 2025","externalUrl":null,"permalink":"/tags/devcon25/","section":"Tags","summary":"","title":"Devcon25","type":"tags"},{"content":" Espressif DevCon25 # Espressif DevCon25 has successfully concluded, bringing together developers, community, and innovators from around the world for two days of technical deep dives, product announcements, and hands-on insights into the latest Espressif technologies.\nFor those who were unable to attend the live sessions, all conference videos are now available on demand. This includes keynotes, technical talks, demos, covering topics such as ESP-IDF advancements, AIoT capabilities, security, connectivity, and the future of Espressif’s ecosystem.\nOfficial site: devcon.espressif.com\nDevCon25 First Day # DevCon25 Second Day # Stay in the loop # Follow @EspressifSystem on social media Join the ESP32 Forum and GitHub discussions Subscribe to our newsletter for reminders and updates Previous editions # DevCon24: Watch on YouTube here: DevCon24 Playlist DevCon23: Watch on YouTube here: DevCon23 Playlist DevCon22: Watch on YouTube here: DevCon22 Playlist ","date":"10 September 2025","externalUrl":null,"permalink":"/events/devcon25/","section":"Events","summary":"The latest edition of the Espressif DevCon has already taken place. The two days featuring 12 unique talks, streamed live online is now available on YouTube. Participants learned directly from Espressif experts and the community, gaining valuable insights to power their next projects.","title":"Espressif DevCon25","type":"events"},{"content":"For pages that change frequently, it is useful to bypass git and inject the updated content dynamically instead of creating PRs every time. As of now, this is helpful for hardware and software product support pages that can update weekly. This article will provide a workflow for injecting dynamic content focusing on the product support pages.\nPlan your page # First of all, the content on a product support page should be classified into the following types:\nStatic: Rarely changing content Committed to the git repo Stored under content/{hardware|software}/product-x/index.md Dymanic: Frequently changing content Dynamically injected into HTML pages using the dynamic-block shortcode Stored in the root of the web server under ./persist/{hardware|software}/product-x/product-x.json Updated either manually or using CI For uploading to the web server, talk to the project maintainers The dynamic content must be stored in the root of the web server under persist. All other folders are fully overwritten daily.\nArrange your content # From the hints in Plan your page, it is not hard to understand the idea:\nIn your markdown file where a dynamic part needs to be injected, you add a dynamic-block shortcode with part\u0026rsquo;s jsonKey In your JSON file, you add all dynamic parts in markdown Simplified syntax # As you can see from Example files below, raw markdown lists (feature_list) and tables (periph_support_table) are not reasonable to store in JSON. A simplified syntax provides a way to strip unnecessary characters for storing, and add them back during rendering. This way, the JSON source is easier to read and dynamic-block still renders it correctly.\nTo use simplified syntax, mark the jsonKey accordingly. In each case, the raw and simplified versions render identically:\nSimplified list \u0026ndash; append list_simple to its jsonKey\nOutput: feature_list = feature_list_simple Simplified table \u0026ndash; append table_simple to its jsonKey\nOutput: periph_support_table = periph_support_table_simple Emojis # In JSON, include emojis as Unicode characters ✅ instaed of : white_check_mark :. This considerably reduces the render time of injected content.\nExample files # Git repo: content/software/product-x/index.md\n--- title: \u0026#34;Product X\u0026#34; date: 2025-08-28 --- **Last updated:** {{\u0026lt; dynamic-block contentPath=\u0026#34;persist/software/product-x/product-x.json\u0026#34; jsonKey=\u0026#34;timestamp\u0026#34; \u0026gt;}} This is a product status page for Product X. The following features are supported as of now: {{\u0026lt; dynamic-block contentPath=\u0026#34;persist/software/product-x/product-x.json\u0026#34; jsonKey=\u0026#34;feature_list_simple\u0026#34; \u0026gt;}} ## Peripheral support table {{\u0026lt; dynamic-block contentPath=\u0026#34;persist/software/product-x/product-x.json\u0026#34; jsonKey=\u0026#34;periph_support_table_simple\u0026#34; \u0026gt;}} Web server: persist/software/product-x/product-x.json\n{ \u0026#34;timestamp\u0026#34;: \u0026#34;2025-08-28T00:07:19.716630Z\u0026#34;, \u0026#34;feature_list\u0026#34;: \u0026#34;- Supported SDKs\\n - ✅ [ESP-IDF](https://github.com/espressif/esp-idf/)\\n - ⏳ SDK 2\u0026#34;, \u0026#34;periph_support_table\u0026#34;: \u0026#34;| Peripheral | ESP32 |\\n| :--- | :---: |\\n| UART | ✅ |\\n| LCD | ❌ |\u0026#34;, \u0026#34;feature_list_simple\u0026#34;: [ \u0026#34;- Supported SDKs\u0026#34;, \u0026#34; - ✅ [ESP-IDF](https://github.com/espressif/esp-idf/)\u0026#34;, \u0026#34; - ⏳ SDK 2\u0026#34; ], \u0026#34;periph_support_table_simple\u0026#34;: [ \u0026#34;Peripheral,ESP32\u0026#34;, \u0026#34;:---,:---:\u0026#34;, \u0026#34;UART,✅\u0026#34;, \u0026#34;LCD,❌\u0026#34; ] } The final page with the dynamic content should look somewhat like this:\nProduct X\nLast updated: 28 Aug 2025, 8:07 am\nThis is a product status page for Product X.\nThe following features are supported as of now:\nSupported SDKs ✅ ESP-IDF ⏳ SDK 2 Peripheral support table\nPeripheral ESP32 UART ✅ LCD ❌ Test dynamic content # Test your .json file locally before uploading to the web server:\nIn your git repo, place your .json file at the same path as on the server: 📂 content/software/ ├── 📝 _index.md └── 📂 product-x/ ├── 📝 index.md └── 🧩 persist/software/product-x/product-x.json # remove after testing In your git repo\u0026rsquo;s layouts/shortcodes/dynamic-block.html, adjust the toggle for testing: {{ $localMode := true }} \u0026lt;!-- change to true for local --\u0026gt; After you run hugo server locally, the JSON content should be injected dynamically on your page.\nIf you update JSON, do this for the changes to show up:\nRestart hugo server Refresh your browser tab If no effect: clear the page cache ","date":"9 September 2025","externalUrl":null,"permalink":"/pages/contribution-guide/dynamic-content/","section":"","summary":"","title":"Dynamic content","type":"pages"},{"content":"","date":"5 September 2025","externalUrl":null,"permalink":"/tags/esp-hosted/","section":"Tags","summary":"","title":"Esp-Hosted","type":"tags"},{"content":"The ESP-IDF esp_wifi API powers Wi-Fi connectivity across ESP32 chips. However, the new chip series, such as ESP32-P4 or ESP32-H2 lack native Wi-Fi hardware. The esp-wifi-remote component enables the use of standard Wi-Fi APIs on ESP32 chips that natively don\u0026rsquo;t have Wi-Fi functionality. By connecting an external device that provides Wi-Fi connectivity, you can use the esp_wifi APIs like on any Wi-Fi-enabled ESP32 chip. This compatibility lets you leverage existing knowledge and codebase with minimal changes.\nAlso, esp-wifi-remote can be used with Wi-Fi-enabled ESP32 chips to create an additional Wi-Fi interface.\nTerminology # Before diving into the details, let\u0026rsquo;s establish the key terminology used throughout this post:\nBackend Solution: The communication layer that handles the transport of Wi-Fi commands, events, and data between host and slave devices. Examples include esp-hosted, eppp, and AT-based implementations. Host-side: The device running your application code (e.g., ESP32-P4, ESP32-H2, or ESP32 with Wi-Fi). Slave-side: The Wi-Fi-capable device that provides the actual Wi-Fi hardware and functionality. Understanding the Wi-Fi Experience # Let\u0026rsquo;s examine the traditional Wi-Fi experience, then see how esp-wifi-remote enables the same experience with external Wi-Fi hardware:\nTraditional Wi-Fi scenario # Users call esp_wifi_...() API to control the local Wi-Fi esp-wifi-remote with non Wi-Fi Chips # Users call esp_wifi_...() API to control the remote Wi-Fi esp-wifi-remote with Wi-Fi-capable Chips # Users call esp_wifi_...() API to control the local Wi-Fi Users call esp_wifi_remote_...() API to control the remote Wi-Fi This dual Wi-Fi scenario is useful for applications that need multiple wireless connections. It is also useful for initial exploring of esp-wifi-remote functionality with just two \u0026ldquo;common\u0026rdquo; ESP32 chips. For basic setup, you only need two evaluation boards.\nWi-Fi Remote component breakdown # esp_wifi_remote is a thin layer that translates esp_wifi API calls into the appropriate implementation. Key aspects:\nAPI Remote Wi-Fi calls: Set of esp_wifi API namespaced with esp_wifi_remote prefix Standard Wi-Fi calls: esp_wifi API directly translates to esp_wifi_remote API for targets with no Wi-Fi. Configuration: Standard Wi-Fi library Kconfig options Selection of the backend solution Wi-Fi configuration # You can configure remote Wi-Fi the same way as local Wi-Fi. Kconfig options are structured identically but located under ESP Wi-Fi Remote component.\nLocal vs. Remote Wi-Fi configuration # Kconfig option names are the same, but identifiers are prefixed differently to differentiate between local and remote Wi-Fi.\n💡 Adapt options from sdkconfig If you\u0026rsquo;re migrating your project from a Wi-Fi enabled device and used specific configuration options, please make sure the remote config options are prefixed with WIFI_RMT_ instead of ESP_WIFI_, for example:\nCONFIG_ESP_WIFI_TX_BA_WIN -\u0026gt; CONFIG_WIFI_RMT_TX_BA_WIN CONFIG_ESP_WIFI_AMPDU_RX_ENABLED -\u0026gt; CONFIG_WIFI_RMT_AMPDU_RX_ENABLED ... ⚠️ All Wi-Fi remote configuration options are available, but some of them are not directly related to the host side configuration and since these are compile time options, wifi-remote cannot automatically reconfigure the slave side in runtime. It is important to configure the options on the slave side manually and rebuild the slave application. Make sure that the host side configuration corresponds to the slave side, e.g. CONFIG_WIFI_RMT_TX_BA_WIN on the host side is equal to the CONFIG_ESP_WIFI_TX_BA_WIN on the slave side.\nThe backend solutions could perform a consistency check but cannot reconfigure the slave project.\nChoosing the backend solution # The default and recommended option as your backend solution for most use-cases is esp_hosted, providing the best performance, integration, maturity, and support.\nYou can also switch to eppp or at based implementation or implement your own backend solution. Here are the reasons you might prefer some other implementation than esp_hosted:\nYour application is not aiming for the best network throughput. Your slave (or host) device is not an ESP32 target and you want to use some standard protocol: choose eppp: it uses PPPoS protocol and works seamlessly with pppd on linux. choose at: it uses standard AT commands and integrates nicely with esp-at as a slave device. You prefer encrypted communication between host and slave devices, especially when passing Wi-Fi credentials. You might need some customization on the slave side. To choose the backend solution, go to the Wi-Fi Remote component configuration menu and select the preferred one by:\n$ idf.py menuconfig \u0026gt; (Top) → Component config → Wi-Fi Remote → Choose WiFi-remote implementation \u0026gt; (X) ESP-HOSTED \u0026gt; ( ) EPPP \u0026gt; ( ) CUSTOM Select ESP-HOSTED or EPPP for the respective backend, or CUSTOM for a custom implementation, including at based backend. To use at backend, you need to manually add wifi_remote_over_at to your project dependency list by:\nidf.py add-dependency \u0026#34;espressif/wifi_remote_over_at\u0026#34; Comparison of backend solution components # This section compares backend solutions, focusing on how different methods marshall (i.e., encode and transmit) Wi-Fi commands, events, and data to the slave device.\nPrinciple of operation\nesp-hosted uses a plain text channel to send and receive Wi-Fi API calls and events. It uses other plain text channels for data packets (Wi-Fi station, soft-AP, BT/BLE). The TCP/IP stack runs only on the host side and esp-hosted passes Ethernet frames (802.3) from host to slave, where they are queued directly to the Wi-Fi library.\nwifi_remote_over_eppp creates a point to point link between host and slave device, so each side have their IP addresses. Wi-Fi API calls and events are transmitted using SSL/TLS connection with mutual authentication. The data path uses plain text peer to peer connection by means of IP packets. Both host and slave devices run TCP/IP stack. The slave device runs network address translation (NAT) to route the host IP packets to the Wi-Fi network \u0026ndash; this is a limitation, since the host device is behind NAT, so invisible from the outside and the translation has a performance impact (to overcome this, you can enable Ethernet frames via custom channels, so the data are transmitted the same way as for esp-hosted method, using 802.3 frames).\nwifi_remote_over_at uses esp-at project as the slave device, so the host side only runs standard AT commands. It\u0026rsquo;s implemented internally with esp_modem component that handles basic Wi-Fi functionality. Note that not all configuration options provided by esp-wifi-remote are supported via AT commands, so this method is largely limited.\nPerformance\nThe best throughput is achieved with esp_hosted implementation.\nBackend Solution Maximum TCP throughput More details esp_hosted_mcu up to 50Mbps esp-hosted wifi_remote_over_eppp up to 20Mbps eppp-link wifi_remote_over_at up to 2Mbps esp-at Wi-Fi Remote internals # The esp-wifi component interface depends on Wi-Fi hardware capabilities. esp-wifi-remote follows these dependencies based on the slave Wi-Fi hardware. Some wireless and system capability flags are replaced internally with SOC_SLAVE prefix. Host-side config options are prefixed with WIFI_RMT for use in esp-wifi-remote headers. See Wi-Fi remote documentation for details.\n📝 These options and flags are only related to the host side, as esp-wifi-remote is a host side layer. For slave side options, please refer to the actual backend solution implementation.\nOther connectivity options # This blog post focuses on Wi-Fi connectivity solutions, specifically esp-wifi-remote only. We are not going to cover other wireless connectivity options like esp-extconn or custom implementations, nor do we cover Bluetooth or BLE. Below is a brief overview with references and links for those interested in exploring these alternatives.\nesp-extconn # This solution doesn\u0026rsquo;t fall into esp-wifi-remote category and needs a special target for the slave side (ESP8689), but provides the best throughput (up to 80Mbps). See esp-extconn repository\nCustom connectivity other options # You can also implement your own Wi-Fi connectivity using these components:\ncomponent Repository Brief description esp-modem esp-protocols AT command and PPP client esp-at esp-at serving AT commands on ESP32 eppp-link esp-protocols PPP/TUN connectivity engine Summary # esp-wifi-remote bridges the gap between Wi-Fi-enabled and non-Wi-Fi ESP32 chipsets, providing a seamless development experience that maintains API compatibility while extending Wi-Fi functionality to previously Wi-Fi-less devices.\nThe below tips emerge from this exploration:\n1. Use esp-hosted as your backend solution \u0026ndash; Provides optimal performance, mature integration, and comprehensive support.\n2. Consider alternative backends for specific scenarios:\nIf sending Wi-Fi commands between host and slave unencrypted is not acceptable: Check out wifi_remote_over_eppp backend or esp-extconn. If you need to use some standard communication protocol (e.g. using non-ESP slave): Check out wifi_remote_over_eppp for PPPoS protocol, or wifi_remote_over_at for AT commands. 3. Mind the Wi-Fi slave configuration \u0026ndash; esp-wifi-remote operates as a compile-time configuration system. Developers must manually configure slave-side Wi-Fi options and rebuild the slave application. When migrating from Wi-Fi-enabled devices, configuration options must be prefixed with WIFI_RMT_ instead of ESP_WIFI_.\n4. Bootstrap your experience with Wi-Fi chips \u0026ndash; To get started without the actual ESP32-P4, just connect your two common ESP chips with three wires and run the two station example (using dual Wi-Fi interfaces).\nReferences # esp-wifi-remote repository esp-wifi-remote in component registry esp-hosted esp-extconn ESP32-P4 connectivity options ","date":"5 September 2025","externalUrl":null,"permalink":"/blog/2025/09/esp-wifi-remote/","section":"Blog","summary":"This blog post introduces the \u003ccode\u003eesp-wifi-remote\u003c/code\u003e component, which extends Wi-Fi functionality to ESP32 chips that lack native Wi-Fi support. We will explore the \u003ccode\u003eesp-wifi-remote\u003c/code\u003e ecosystem, its components, architecture, and integration with \u003ccode\u003eesp-hosted\u003c/code\u003e.","title":"Transparent Wi-Fi connectivity for non-Wi-Fi ESP32 chips","type":"blog"},{"content":"","date":"5 September 2025","externalUrl":null,"permalink":"/tags/wi-fi/","section":"Tags","summary":"","title":"Wi Fi","type":"tags"},{"content":"","date":"2 September 2025","externalUrl":null,"permalink":"/authors/chen-menghua/","section":"Developer Portal Authors","summary":"","title":"Chen Menghua","type":"authors"},{"content":"","date":"2 September 2025","externalUrl":null,"permalink":"/tags/deep-sleep-wake-stub/","section":"Tags","summary":"","title":"Deep-Sleep Wake Stub","type":"tags"},{"content":"In the world of IoT devices, reducing power consumption is key to extending battery life. One of the most effective strategies to achieve this is by putting the device to sleep. The longer it stays asleep, the more power it saves. Espressif SoCs support multiple sleep modes to manage this, with Deep-sleep being the most power-efficient. But traditional Deep-sleep has a downside: every time the device wakes up, it has to go through a full boot process, even if the device only needs to perform a quick task before going back to sleep. Thus, it ends up wasting precious energy.\nThat’s where the wake stub comes in. It changes the game by letting the chip skip most of the boot sequence and jump straight into a critical task. This means the chip wakes up faster, uses less power, and only initializes the peripherals it actually needs. Whether it’s a soil sensor in smart farming or a step counter in a wearable device, this feature can greatly extend battery life.\nAlthough the ULP coprocessor can also help save power, its use cases differ from wake stubs, mainly due to the limited resources available when the HP core is in deep sleep. In Deep-sleep mode, the HP core, most of the RAM (excluding RTC/LP memory), and all HP peripherals on Espressif chips are powered off. While the ULP remains powered, its functionality and accessible memory are limited. For details on which modules remain powered during deep sleep, please refer to the Functional Block Diagram in Datasheet. In contrast, the wake stub can access all peripherals and RAM, and therefore supports more complex functionality.\nIn this article, we’ll take a closer look at how the Deep-sleep wake stub works and show how to build a Deep-sleep wake stub application on Espressif chips.\nDeep-Sleep Wake Stub Application # After SoC reset, the CPU will start running immediately to perform initialization (known as the first-stage ROM bootloader). Depending on the reset reason, the system follows different execution paths, as illustrated in the figure below.\nReset from deep sleep: After partial initialization, the CPU performs a CRC check on the RTC/LP memory to ensure the data is valid. If the check passes, the CPU jumps to the entry point of the Deep-sleep wake stub application stored in RTC/LP Memory and begins execution. Otherwise, it proceeds with SPI boot mode.\nFor power-on reset, software SoC reset, and watchdog SoC reset: The chip enters Download boot mode or SPI boot mode.\nFor software CPU reset and watchdog CPU reset: The chip directly enters SPI boot mode and runs port and system initialization. This includes setting up internal memory sections (data and BSS) and watchdog timers . It then jumps to the user application entry point—app_main().\nFrom the boot process after SoC reset, we can see that Espressif chips can skip full system initialization and directly execute the Deep-sleep wake stub application. Thus, the Deep-sleep wake stub application is particularly well-suited for the following two scenarios:\nPeriodic lightweight tasks: the wake stub can handle them without booting the entire chip, allowing it to either return to sleep quickly or continue the boot process, thereby saving power.\nTo implement such tasks using GPIO, UART, I2C, and SPI in the wake stub, see Implementation of Wake Stub Functionality.\nTasks with real-time requirements: the wake stub can execute them before continuing the boot process, greatly speeding up wake-up response and improving overall application performance.\nAn example of such use case is covered in the article Boot Secure, Restore Smart: Accelerating Device Startup on ESP32, where hardware peripherals in the ESP-IDF bootloader are manipulated to shorten device boot-up delays. This approach reduced the boot-up time of a smart lighting system from 405 ms to 85 ms. Even more impressively, using a wake stub can bring that down to just 6 ms—significantly accelerating system startup.\nThe current support status for Deep-sleep wake stub applications on Espressif chips is summarized in the table below.\nChips Support ESP32 Yes ESP32-S2 Yes ESP32-S3 Yes ESP32-C2 No* ESP32-C3 Yes ESP32-C5 Yes ESP32-C6 Yes ESP32-H2 Yes ESP32-P4 No** *The chip ESP32-C2 lacks RTC/LP Memory; therefore, all memory is powered down during deep sleep, preventing storage of wake stub code.\n**Although the chip ESP32-P4 does not support a wake stub, the LP core has its own ROM to boot itself and handle tasks while the HP core stays in deep sleep.\nImplement Wake Stub # This article takes the ESP32-C6 as an example to further explain the principles of Deep-sleep wake stub. When executing the wake stub application, the chip has not yet completed the configuration of internal memory sections or watchdog timers. Therefore, when developing a wake stub application, it is important to pay special attention to memory usage constraints and watchdog configuration.\nMemory Allocation # When executing the wake stub application, the chip has not yet completed system initialization—only RTC/LP Memory and ROM are available, while all other SRAM regions remain uninitialized and may contain random data. Therefore, all functions and data used by the wake stub must be explicitly placed in RTC/LP Memory. It is important to note, however, that although SRAM is uninitialized, it is already powered on; thus, dynamic data such as local variables can be used directly without special handling.\nESP-IDF provides dedicated methods for placing functions and data in RTC/LP Memory.\nPlacing Functions in RTC/LP Memory\nUse the RTC_IRAM_ATTR attribute to place the wake stub function in RTC/LP Memory. This method is suitable for short and simple code segments or for source files including both \u0026ldquo;normal\u0026rdquo; and \u0026ldquo;RTC\u0026rdquo; code. The function should be defined as: void RTC_IRAM_ATTR wake_stub(void) { }.\nAlternatively, place the wake stub function into any source file with such names *rtc_wake_stub*.Their contents can be automatically put into RTC/LP memory by the linker.\nPlacing Data in RTC/LP Memory\nUse the RTC_DATA_ATTR and RTC_RODATA_ATTR attributes to place writable and read-only data, respectively. Note that string constants must be declared as arrays and marked with RTC_RODATA_ATTR.\nAlternatively, place the data in any source file with such names *rtc_wake_stub*. The linker will ensure such data is placed into RTC/LP Memory.\nThe attributes RTC_FAST_ATTR and RTC_SLOW_ATTR can be used to specify data that will be force placed into RTC/LP memory and RTC slow memory respectively. However, ESP32-C6 includes RTC/LP memory only, so both these two attributes will map to this region.\nMemory Capacity # The wake stub application is constrained by the limited size of RTC/LP Memory (16 KB), which makes it infeasible to directly include full peripheral driver code (e.g., for GPIO or UART). To use such peripherals within a wake stub, you can adopt one of the following approaches:\nUse LL (Low-Level) API interfaces to control peripherals. These interfaces are typically defined in header files, with minimal code size, making them well-suited for RTC/LP Memory. The next section of this article provides programming examples for using GPIO, UART, I2C, and SPI in wake stub applications based on LL APIs. Warning!\nThe LL APIs are not guaranteed to remain stable and may change without notice in new releases. Developers are advised to use them with caution and at their own risk. IDF peripheral driver code can be stored in flash and either executed directly via MMU mapping or loaded into SRAM via the SPI interface. When using such drivers in the wake stub, you must manually initialize any required system components (e.g., clocks, interrupts), as these are not initialized. During wake-up, the RWDT and MWDT0 watchdog timers are enabled to prevent system hangs in the bootloader stage. In SPI boot mode, these watchdog timers are disabled during system initialization. However, in a wake stub application, initialization has not yet occurred, so both timers remain active. If the wake stub performs complex or time-consuming tasks, it must feed the watchdogs to avoid an unexpected reset.\nHow to Create a Deep-Sleep Wake Stub Application # This section provides a detailed guide on creating a wake stub application and demonstrates how to implement GPIO, UART, I2C, and SPI functionalities using LL-layer APIs within this application. All example code is based on the ESP-IDF v5.5 and uses the ESP32-C6 as the development platform.\nBuild System # To implement a wake stub application, we first create a directory, which contains a CMakeLists.txt file defining the build rules and a main/ subdirectory for the source code. The content of the project’s CMakeLists.txt file is as follows:\n# Set the minimum required CMake version cmake_minimum_required(VERSION 3.16) # Include other cmake files into the current file include($ENV{IDF_PATH}/tools/cmake/project.cmake) # \u0026#34;Trim\u0026#34; the build. idf_build_set_property(MINIMAL_BUILD ON) # Set the project name project(deep_sleep_wake_stub) The main/ subdirectory should also include a CMakeLists.txt file to register the wake stub application and integrate it into the build system.\nidf_component_register(SRCS \u0026#34;wake_stub_example_main.c\u0026#34; \u0026#34;rtc_wake_stub_example.c\u0026#34; INCLUDE_DIRS \u0026#34;.\u0026#34;) Register the Wake Stub Application # In the wake_stub_example_main.c file, we can write the code to be executed when the chip completes initialization. The function void app_main(void) serves as the entry point where the CPU jumps after power-on reset and SPI boot mode.\nTo enable the Deep-sleep wake stub application, we need to register the wake stub function within the app_main() function. The steps are as follows:\nConfigure Deep-sleep wakeup sources. The Deep-sleep wakeup sources for the ESP32-C6 chip include LP GPIO, Wi-Fi beacon, RTC Timer, and LP CPU. These wake-up sources can be configured by including the esp_sleep.h header file and using the relevant APIs.\nRegister the wake stub function. To execute a wake stub application after the chip wakes from deep sleep, we need to register a user-defined wake stub function by using the esp_set_deep_sleep_wake_stub function defined in esp_sleep.h. Its function prototype is as follows:\nvoid esp_set_deep_sleep_wake_stub(esp_deep_sleep_wake_stub_fn_t new_stub); Here, new_stub is a function pointer that points to a function with no parameters and no return value.\nExplicitly enter Deep-sleep mode by calling the esp_deep_sleep_start() function function defined in esp_sleep.h.\nJump to execute the registered wake stub application when the wake-up condition is met.\nHere is an example of wake_stub_example_main().\nImplementation of Wake Stub Functionality # Assume a wake stub function wake_stub_example() has been registed in the user application. Now, we introduce its typical structure.\n#include \u0026lt;inttypes.h\u0026gt; #include \u0026#34;esp_sleep.h\u0026#34; #include \u0026#34;esp_cpu.h\u0026#34; #include \u0026#34;esp_rom_sys.h\u0026#34; #include \u0026#34;esp_wake_stub.h\u0026#34; #include \u0026#34;sdkconfig.h\u0026#34; // counter value, stored in RTC memory RTC_DATA_ATTR uint32_t s_count = 0; RTC_DATA_ATTR const uint32_t s_max_count = 20; // wakeup_cause stored in RTC memory RTC_DATA_ATTR uint32_t wakeup_cause; // wakeup_time from CPU start to wake stub RTC_DATA_ATTR uint32_t wakeup_time; // wake up stub function stored in RTC memory void wake_stub_example(void) { // Get wakeup time. wakeup_time = esp_cpu_get_cycle_count() / esp_rom_get_cpu_ticks_per_us(); // Get wakeup cause. wakeup_cause = esp_wake_stub_get_wakeup_cause(); // Increment the counter. s_count++; // Print the counter value and wakeup cause. ESP_RTC_LOGI(\u0026#34;wake stub: wakeup count is %d, wakeup cause is %d, wakeup cost %ld us\u0026#34;, s_count, wakeup_cause, wakeup_time); // Implement post-wake functionality esp_wake_func(); if (s_count \u0026gt;= s_max_count) { // Reset s_count s_count = 0; // Realize the wake stub functionality. // There is a default version of this function provided in esp-idf. esp_wake_deep_sleep(); // Return from the wake stub function to continue booting the firmware. return; } // s_count is \u0026lt; s_max_count, go back to deep sleep. // Set wakeup time in stub esp_wake_stub_set_wakeup_time(5*1000000); // 5 seconds // Print status. ESP_RTC_LOGI(\u0026#34;wake stub: going to deep sleep\u0026#34;); // Set stub entry, then going to deep sleep again. esp_wake_stub_sleep(\u0026amp;wake_stub_example); } The wake_stub_example function implements a low-power cyclic wake-up mechanism as follows:\nExecute target functions upon each wake-up: The function calls esp_wake_func() to perform desired operations after waking. Within esp_wake_func(), you can implement functionality for GPIO, UART, I2C, SPI, etc. The function name and signature are user-defined.\nContinue sleeping if the wake-up count is below the specified threshold: The next wake-up time is set using esp_wake_stub_set_wakeup_time(). By registering the wake stub function again with esp_set_deep_sleep_wake_stub(), the chip re-enters Deep-sleep mode, creating a periodic wake-up low-power cycle.\nAllow SPI boot when the wake-up count reaches the limit: Once the maximum wake-up count is reached, cleanup operations can be performed by calling esp_wake_deep_sleep(). The wake stub logic ends with return, allowing the system to proceed with SPI boot mode.\nThe wake stub functionality in ESP-IDF is implemented by the function esp_wake_deep_sleep(). Since it is weakly linked to the default esp_default_wake_deep_sleep(), defining esp_wake_deep_sleep() in our application will override the default implementation.\nNext, we will specifically introduce how to implement GPIO, UART, I2C, and SPI functionalities within the esp_wake_func() function.\nGPIO # Here is an example demonstrating how to configure and control a GPIO pin’s output using LL-layer functions within a wake stub application. See the ESP32-C6 TRM GPIO Section for GPIO details.\nDetailed steps:\nInclude low-level GPIO header file and define a log color macro.\nDetails #include \u0026#34;hal/gpio_ll.h\u0026#34; #define RTC_LOG_COLOR_GREEN(fmt) \u0026#34;\\033[0;32m\u0026#34; fmt \u0026#34;\\033[0m\u0026#34; Obtain GPIO hardware instance.\nDetails RTC_DATA_ATTR gpio_dev_t * gpio_dev = GPIO_LL_GET_HW(GPIO_PORT_0); Define the target GPIO pin number.\nDetails #define gpio_num 12 The following code is performed inside the esp_wake_func() function:\nInitialize GPIO pin.\nDetails gpio_ll_output_enable(gpio_dev, gpio_num); gpio_ll_func_sel(gpio_dev, gpio_num, PIN_FUNC_GPIO); Set GPIO output level.\nDetails gpio_ll_set_level(gpio_dev, gpio_num, 1); ESP_RTC_LOGI(RTC_LOG_COLOR_GREEN(\u0026#34;GPIO %d level: %d\u0026#34;), gpio_num, 1); esp_rom_delay_us(1000*100); gpio_ll_set_level(gpio_dev, gpio_num, 0); ESP_RTC_LOGI(RTC_LOG_COLOR_GREEN(\u0026#34;GPIO %d level: %d\u0026#34;), gpio_num, 0); esp_rom_delay_us(1000*100); gpio_ll_set_level(gpio_dev, gpio_num, 1); ESP_RTC_LOGI(RTC_LOG_COLOR_GREEN(\u0026#34;GPIO %d level: %d\u0026#34;), gpio_num, 1); esp_rom_delay_us(1000*100); Flash the above program to the target ESP32-C6:\nUse a logic analyzer to capture the GPIO output signal. The results are shown below: UART # Here is an example demonstrating how to send the string \u0026ldquo;Hello world\u0026rdquo; via the UART interface using LL-layer functions within a wake stub application. See the ESP32-C6 TRM UART Section for UART details.\nDetailed steps:\nInclude low-level header files and define a log color macro.\nDetails #include \u0026#34;hal/gpio_ll.h\u0026#34; #include \u0026#34;hal/uart_ll.h\u0026#34; #include \u0026#34;esp_private/uart_share_hw_ctrl.h\u0026#34; #include \u0026#34;esp_rom_gpio.h\u0026#34; #define RTC_LOG_COLOR_GREEN(fmt) \u0026#34;\\033[0;32m\u0026#34; fmt \u0026#34;\\033[0m\u0026#34; Define UART-related configuration macros.\nDetails #define UART_TOUT_THRESH_DEFAULT 10 #define UART_BAUD_RATE 9600 #define TXD_PIN 4 #define RXD_PIN 5 Obtain hardware instances and define transmission data.\nDetails RTC_DATA_ATTR gpio_dev_t * gpio_dev = GPIO_LL_GET_HW(GPIO_PORT_0); RTC_DATA_ATTR uart_dev_t * uart_dev =UART_LL_GET_HW(UART_NUM_1); const RTC_DATA_ATTR char * const ch = \u0026#34;Hello world\u0026#34;; const RTC_DATA_ATTR uint8_t * write_buf = (const uint8_t *) ch; Define a function to calculate the total number of bits required to transmit one UART symbol.\nDetails uint8_t uart_get_symb_len(uart_dev_t * dev) { uint8_t symbol_len = 1; // number of bits per symbol including start uart_parity_t parity_mode; uart_stop_bits_t stop_bit; uart_word_length_t data_bit; uart_ll_get_data_bit_num(dev, \u0026amp;data_bit); uart_ll_get_stop_bits(dev, \u0026amp;stop_bit); uart_ll_get_parity(dev, \u0026amp;parity_mode); symbol_len += (data_bit \u0026lt; UART_DATA_BITS_MAX) ? (uint8_t)data_bit + 5 : 8; symbol_len += (stop_bit \u0026gt; UART_STOP_BITS_1) ? 2 : 1; symbol_len += (parity_mode \u0026gt; UART_PARITY_DISABLE) ? 1 : 0; return symbol_len; } The following code is performed inside the esp_wake_func() function:\nInitialize UART hardware and configure its parameters. Details ```c uart_ll_enable_bus_clock(UART_NUM_1, true); uart_ll_reset_register(UART_NUM_1); uart_ll_sclk_enable(uart_dev); uart_ll_set_mode(uart_dev, UART_MODE_UART); uart_ll_set_parity(uart_dev, UART_PARITY_DISABLE); uart_ll_set_data_bit_num(uart_dev, UART_DATA_8_BITS); uart_ll_set_stop_bits(uart_dev, UART_STOP_BITS_1); uart_ll_set_tx_idle_num(uart_dev, 0); uart_ll_set_hw_flow_ctrl(uart_dev, UART_HW_FLOWCTRL_DISABLE, 0); uart_ll_set_sclk(uart_dev, SOC_MOD_CLK_XTAL); uart_ll_set_baudrate(uart_dev, UART_BAUD_RATE, 40000000); uart_ll_rxfifo_rst(uart_dev); uart_ll_txfifo_rst(uart_dev); ``` Configure the TX pin for UART output functionality.\nDetails gpio_ll_func_sel(gpio_dev, TXD_PIN, PIN_FUNC_GPIO); esp_rom_gpio_connect_out_signal(TXD_PIN, U1TXD_OUT_IDX, false, false); Transmit data.\nDetails ESP_RTC_LOGI(RTC_LOG_COLOR_GREEN(\u0026#34;UART TX_TASK: Sending: %s\u0026#34;), write_buf); uart_ll_write_txfifo(uart_dev, write_buf, 12); while(!uart_ll_is_tx_idle(uart_dev)); To conveniently test the wake stub, we implemented a UART receive task that continuously runs to receive data sent by the transmit task. The receiver uses the UART driver, and the main function code is shown below. For more information, refer to Universal Asynchronous Receiver/Transmitter (UART).\nuart_rxtask_main.c #include \u0026#34;freertos/FreeRTOS.h\u0026#34; #include \u0026#34;freertos/task.h\u0026#34; #include \u0026#34;esp_system.h\u0026#34; #include \u0026#34;esp_log.h\u0026#34; #include \u0026#34;driver/uart.h\u0026#34; #include \u0026#34;string.h\u0026#34; #include \u0026#34;driver/gpio.h\u0026#34; static const int RX_BUF_SIZE = 1024; #define TXD_PIN (CONFIG_EXAMPLE_UART_TXD) #define RXD_PIN (CONFIG_EXAMPLE_UART_RXD) void init(void) { const uart_config_t uart_config = { .baud_rate = 9600, .data_bits = UART_DATA_8_BITS, .parity = UART_PARITY_DISABLE, .stop_bits = UART_STOP_BITS_1, .flow_ctrl = UART_HW_FLOWCTRL_DISABLE, .source_clk = SOC_MOD_CLK_XTAL, }; uart_driver_install(UART_NUM_1, RX_BUF_SIZE * 2, 0, 0, NULL, 0); uart_param_config(UART_NUM_1, \u0026amp;uart_config); uart_set_pin(UART_NUM_1, TXD_PIN, RXD_PIN, UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE); } static void rx_task(void *arg) { static const char *RX_TASK_TAG = \u0026#34;RX_TASK\u0026#34;; esp_log_level_set(RX_TASK_TAG, ESP_LOG_INFO); uint8_t* data = (uint8_t*) malloc(RX_BUF_SIZE + 1); while (1) { uart_flush_input(UART_NUM_1); const int rxBytes = uart_read_bytes(UART_NUM_1, data, RX_BUF_SIZE, 1000 / portTICK_PERIOD_MS); if (rxBytes \u0026gt; 0) { data[rxBytes] = 0; ESP_LOGI(RX_TASK_TAG, \u0026#34;Received: %s\u0026#34;, data); } } free(data); } void app_main(void) { init(); xTaskCreate(rx_task, \u0026#34;uart_rx_task\u0026#34;, 3072, NULL, configMAX_PRIORITIES - 1, NULL); } Flash the program to the ESP32-C6 acting as the transceiver: Flash the program to the ESP32-C6 acting as the receiver: I2C # Here is an example demonstrating how to send the string \u0026ldquo;Hello world\u0026rdquo; via the I2C interface using LL-layer functions within a wake stub application. See the ESP32-C6 TRM I2C Section for I2C details.\nDetailed steps:\nInclude low-level header files and define a log color macro.\nDetails #include \u0026#34;esp_rom_gpio.h\u0026#34; #include \u0026#34;hal/gpio_ll.h\u0026#34; #include \u0026#34;hal/i2c_types.h\u0026#34; #include \u0026#34;hal/i2c_ll.h\u0026#34; #include \u0026#34;hal/clk_tree_ll.h\u0026#34; #include \u0026#34;soc/periph_defs.h\u0026#34; #include \u0026#34;hal/clk_gate_ll.h\u0026#34; #include \u0026#34;soc/soc.h\u0026#34; #include \u0026#34;soc/i2c_reg.h\u0026#34; #define RTC_LOG_COLOR_GREEN(fmt) \u0026#34;\\033[0;32m\u0026#34; fmt \u0026#34;\\033[0m\u0026#34; Configure I2C-related macros.\nDetails #define I2C_MASTER_NUM I2C_NUM_0 #define I2C_SDA 5 #define I2C_SCL 4 #define FILTER_NUM 0 #define SCL_SPEED_HZ 100000 #define SCL_WAIT_US 20000 Obtain hardware instances, the 7-bit I2C slave address, and the data to be sent.\nDetails RTC_DATA_ATTR gpio_dev_t *gpio_dev = GPIO_LL_GET_HW(GPIO_PORT_0); RTC_DATA_ATTR i2c_dev_t *i2c_dev = I2C_LL_GET_HW(0); const RTC_DATA_ATTR char * const ch = \u0026#34;Hello world\u0026#34;; const RTC_DATA_ATTR uint8_t * write_buf = (const uint8_t *) ch; #define I2C_SLAVE_ADDR_7BIT 0x34 RTC_DATA_ATTR uint8_t i2c_slave_write_addr = (I2C_SLAVE_ADDR_7BIT \u0026lt;\u0026lt; 1) | 0; The following code is performed inside the esp_wake_func() function:\nEnable and reset the I2C peripheral\u0026rsquo;s bus and controller clocks.\nDetails i2c_ll_enable_bus_clock(0, true); i2c_ll_reset_register(0); i2c_ll_enable_controller_clock(i2c_dev, true); Configure SDA and SCL GPIO pins.\nDetails // SDA pin configurations gpio_ll_set_level(gpio_dev, I2C_SDA, 1); gpio_ll_input_enable(gpio_dev, I2C_SDA); gpio_ll_od_enable(gpio_dev, I2C_SDA); gpio_ll_pullup_en(gpio_dev, I2C_SDA); gpio_ll_pulldown_dis(gpio_dev, I2C_SDA); gpio_ll_func_sel(gpio_dev, I2C_SDA, PIN_FUNC_GPIO); esp_rom_gpio_connect_out_signal(I2C_SDA, I2CEXT0_SDA_OUT_IDX, 0, 0); esp_rom_gpio_connect_in_signal(I2C_SDA, I2CEXT0_SDA_IN_IDX, 0); // SCL pin configurations gpio_ll_set_level(gpio_dev, I2C_SCL, 1); gpio_ll_input_enable(gpio_dev, I2C_SCL); gpio_ll_od_enable(gpio_dev, I2C_SCL); gpio_ll_pullup_en(gpio_dev, I2C_SCL); gpio_ll_pulldown_dis(gpio_dev, I2C_SCL); gpio_ll_func_sel(gpio_dev, I2C_SCL, PIN_FUNC_GPIO); esp_rom_gpio_connect_out_signal(I2C_SCL, I2CEXT0_SCL_OUT_IDX, 0, 0); esp_rom_gpio_connect_in_signal(I2C_SCL, I2CEXT0_SCL_IN_IDX, 0); Configure I2C master mode and control parameters.\nDetails i2c_ll_set_mode(i2c_dev, I2C_BUS_MODE_MASTER); i2c_ll_enable_pins_open_drain(i2c_dev, true); i2c_ll_enable_arbitration(i2c_dev, false); i2c_ll_master_rx_full_ack_level(i2c_dev, false); i2c_ll_set_data_mode(i2c_dev, I2C_DATA_MODE_MSB_FIRST, I2C_DATA_MODE_MSB_FIRST);//MSB i2c_ll_txfifo_rst(i2c_dev); i2c_ll_rxfifo_rst(i2c_dev); i2c_ll_update(i2c_dev); Configure the I2C bus clock.\nDetails i2c_ll_set_source_clk(i2c_dev, SOC_MOD_CLK_XTAL); i2c_ll_master_set_filter(i2c_dev, FILTER_NUM); i2c_hal_clk_config_t clk_cal; i2c_ll_master_cal_bus_clk(clk_ll_xtal_load_freq_mhz() * MHZ, SCL_SPEED_HZ, \u0026amp;clk_cal); i2c_ll_master_set_bus_timing(i2c_dev, \u0026amp;clk_cal); uint32_t reg_val = i2c_ll_calculate_timeout_us_to_reg_val(clk_ll_xtal_load_freq_mhz() * MHZ, SCL_WAIT_US); i2c_ll_set_tout(i2c_dev, reg_val); i2c_ll_master_set_fractional_divider(i2c_dev, 0, 0); i2c_ll_update(i2c_dev); Construct the I2C hardware command sequence.\nDetails i2c_ll_hw_cmd_t hw_cmd[] = { { .op_code = I2C_LL_CMD_RESTART, }, { .op_code = I2C_LL_CMD_WRITE, .ack_en = true, .byte_num = 13, //The data num is 12, the address num is 1 }, { .op_code = I2C_LL_CMD_STOP, } }; Execute the I2C data transmission process.\nDetails while(i2c_ll_is_bus_busy(i2c_dev)){} i2c_ll_txfifo_rst(i2c_dev); i2c_ll_rxfifo_rst(i2c_dev); ESP_RTC_LOGI(RTC_LOG_COLOR_GREEN(\u0026#34;i2c_master: Sending: %s\u0026#34;), write_buf); i2c_ll_master_write_cmd_reg(i2c_dev, hw_cmd[0], 0); i2c_ll_write_txfifo(i2c_dev, \u0026amp;i2c_slave_write_addr, 1); i2c_ll_write_txfifo(i2c_dev, write_buf, 12); i2c_ll_master_write_cmd_reg(i2c_dev, hw_cmd[1], 1); i2c_ll_master_write_cmd_reg(i2c_dev, hw_cmd[2], 2); i2c_ll_update(i2c_dev); i2c_ll_start_trans(i2c_dev); To conveniently test the wake stub, we implemented an I2C slave task that continuously runs to receive data sent by the I2C master task. The slave uses the I2C_slave driver, and the main function code is shown below. For more information, refer to Inter-Integrated Circuit (I2C).\ni2c_slave_device_main.c #include \u0026#34;freertos/FreeRTOS.h\u0026#34; #include \u0026#34;freertos/task.h\u0026#34; #include \u0026#34;esp_log.h\u0026#34; #include \u0026#34;driver/i2c_slave.h\u0026#34; #include \u0026#34;esp_rom_sys.h\u0026#34; #define I2C_SLAVE_PORT 0 #define I2C_SLAVE_SDA_IO 5 #define I2C_SLAVE_SCL_IO 4 #define I2C_SLAVE_ADDR_7BIT 0x34 #define I2C_SLAVE_BUF_LEN 128 static const char *TAG = \u0026#34;i2c_slave\u0026#34;; static QueueHandle_t event_queue; static uint8_t *temp_data = NULL; static size_t temp_len = 0; static i2c_slave_dev_handle_t handle = NULL; typedef enum { I2C_SLAVE_EVT_RX, I2C_SLAVE_EVT_TX, } i2c_slave_event_t; static IRAM_ATTR bool i2c_slave_request_cb(i2c_slave_dev_handle_t i2c_slave, const i2c_slave_request_event_data_t *evt_data, void *arg) { BaseType_t xTaskWoken = pdFALSE; i2c_slave_event_t evt = I2C_SLAVE_EVT_TX; xQueueSendFromISR(event_queue, \u0026amp;evt, \u0026amp;xTaskWoken); return xTaskWoken; } static IRAM_ATTR bool i2c_slave_receive_cb(i2c_slave_dev_handle_t i2c_slave, const i2c_slave_rx_done_event_data_t *evt_data, void *arg) { BaseType_t xTaskWoken = pdFALSE; i2c_slave_event_t evt = I2C_SLAVE_EVT_RX; memcpy(temp_data, evt_data-\u0026gt;buffer, evt_data-\u0026gt;length); temp_len = evt_data-\u0026gt;length; xQueueSendFromISR(event_queue, \u0026amp;evt, \u0026amp;xTaskWoken); return xTaskWoken; } static void i2c_slave_task(void *arg) { i2c_slave_event_t evt; uint8_t tx_data[I2C_SLAVE_BUF_LEN]; size_t tx_len; while (1) { if (xQueueReceive(event_queue, \u0026amp;evt, portMAX_DELAY) == pdTRUE) { if (evt == I2C_SLAVE_EVT_RX) { ESP_LOGI(TAG, \u0026#34;Received %d bytes from master:\u0026#34;, temp_len); ESP_LOGI(TAG, \u0026#34;%s \u0026#34;, (char*) temp_data); } else if (evt == I2C_SLAVE_EVT_TX) { for (int i = 0; i \u0026lt; I2C_SLAVE_BUF_LEN; i++) { tx_data[i] = i; } tx_len = I2C_SLAVE_BUF_LEN; uint32_t written = 0; esp_err_t err = i2c_slave_write(handle, tx_data, tx_len, \u0026amp;written, 1000); ESP_LOGI(TAG, \u0026#34;Master read request: wrote %d bytes (err=0x%x)\u0026#34;, written, err); } } } } void i2c_slave_start(void) { esp_err_t ret; temp_data = heap_caps_malloc(I2C_SLAVE_BUF_LEN, MALLOC_CAP_DEFAULT); assert(temp_data); event_queue = xQueueCreate(4, sizeof(i2c_slave_event_t)); assert(event_queue); i2c_slave_config_t i2c_slv_config = { .i2c_port = I2C_SLAVE_PORT, .clk_source = I2C_CLK_SRC_DEFAULT, .scl_io_num = I2C_SLAVE_SCL_IO, .sda_io_num = I2C_SLAVE_SDA_IO, .slave_addr = I2C_SLAVE_ADDR_7BIT, .send_buf_depth = I2C_SLAVE_BUF_LEN, .receive_buf_depth = I2C_SLAVE_BUF_LEN, .flags.enable_internal_pullup = true, .addr_bit_len = I2C_ADDR_BIT_LEN_7, }; ret = i2c_new_slave_device(\u0026amp;i2c_slv_config, \u0026amp;handle); ESP_LOGI(TAG, \u0026#34;i2c_new_slave_device: %s\u0026#34;, esp_err_to_name(ret)); i2c_slave_event_callbacks_t cbs = { .on_receive = i2c_slave_receive_cb, .on_request = i2c_slave_request_cb, }; ret = i2c_slave_register_event_callbacks(handle, \u0026amp;cbs, NULL); ESP_LOGI(TAG, \u0026#34;i2c_slave_register_event_callbacks: %s\u0026#34;, esp_err_to_name(ret)); xTaskCreate(i2c_slave_task, \u0026#34;i2c_slave_task\u0026#34;, 2048, NULL, 10, NULL); } void app_main(void) { i2c_slave_start(); while (1) { vTaskDelay(pdMS_TO_TICKS(1000)); } } Flash the program to the ESP32-C6 acting as the I2C master: Set CONFIG_I2C_ENABLE_SLAVE_DRIVER_VERSION_2 = y and flash the program to the ESP32-C6 acting as the I2C slave: SPI # Here is an example demonstrating how to send the string \u0026ldquo;Hello world\u0026rdquo; via the SPI interface using LL-layer functions within a wake stub application. See the ESP32-C6 TRM SPI Section for SPI details.\nDetailed steps:\nInclude low-level header files and define a log color macro.\nDetails #include \u0026#34;hal/gpio_ll.h\u0026#34; #include \u0026#34;esp_rom_gpio.h\u0026#34; #include \u0026#34;hal/spi_types.h\u0026#34; #include \u0026#34;hal/spi_ll.h\u0026#34; #include \u0026#34;soc/clk_tree_defs.h\u0026#34; #include \u0026#34;hal/clk_tree_ll.h\u0026#34; #define RTC_LOG_COLOR_GREEN(fmt) \u0026#34;\\033[0;32m\u0026#34; fmt \u0026#34;\\033[0m\u0026#34; Configure SPI-related macros.\nDetails #define SPI_MISO 5 #define SPI_MOSI 4 #define SPI_CLK 6 #define SPI_CS 12 #define clock_speed_hz 1 * 1000 * 1000 // 1 MHz #define duty_cycle_pos 128 #define CS_PIN_ID 0 #define SPI_MODE 0 #define TX_BITLEN 88 #define CMD_BITLEN 0 #define ADDR_BITLEN 0 Obtain hardware instances.\nDetails RTC_DATA_ATTR gpio_dev_t * gpio_dev = GPIO_LL_GET_HW(GPIO_PORT_0); RTC_DATA_ATTR spi_dev_t * spi_dev = SPI_LL_GET_HW(SPI2_HOST); Set the transmit content.\nDetails const RTC_DATA_ATTR char * const ch = \u0026#34;Hello world\u0026#34;; const RTC_DATA_ATTR uint8_t * write_buf = (const uint8_t *) ch; The following code is performed inside the esp_wake_func() function:\nInitialize the SPI bus and configure pin functions.\nDetails spi_ll_enable_bus_clock(SPI2_HOST, true); spi_ll_reset_register(SPI2_HOST); gpio_ll_input_enable(gpio_dev, SPI_MOSI); esp_rom_gpio_connect_in_signal(SPI_MOSI, FSPID_IN_IDX, false); esp_rom_gpio_connect_out_signal(SPI_MOSI, FSPID_OUT_IDX, false, false); gpio_ll_func_sel(gpio_dev, SPI_MOSI, PIN_FUNC_GPIO); gpio_ll_input_enable(gpio_dev, SPI_MISO); esp_rom_gpio_connect_in_signal(SPI_MISO, FSPIQ_IN_IDX, false); esp_rom_gpio_connect_out_signal(SPI_MISO, FSPIQ_OUT_IDX, false, false); gpio_ll_func_sel(gpio_dev, SPI_MISO, PIN_FUNC_GPIO); esp_rom_gpio_connect_out_signal(SPI_CLK, FSPICLK_OUT_IDX, false, false); gpio_ll_func_sel(gpio_dev, SPI_CLK, PIN_FUNC_GPIO); SPI controller initialization and configuration.\nEnable clock and initialize the SPI controller. Details periph_ll_enable_clk_clear_rst(PERIPH_SPI2_MODULE); spi_ll_reset_register(SPI2_HOST); spi_ll_master_init(spi_dev); spi_ll_enable_int(spi_dev); spi_ll_set_int_stat(spi_dev); spi_ll_set_mosi_delay(spi_dev, 0, 0); spi_ll_apply_config(spi_dev); Configure SPI master clock. Details uint32_t clock_source_hz = clk_ll_xtal_load_freq_mhz() * MHZ;; spi_ll_clock_val_t reg_val; spi_ll_master_cal_clock(clock_source_hz, clock_speed_hz, duty_cycle_pos, \u0026amp;reg_val); spi_ll_master_set_clock_by_reg(spi_dev, \u0026amp;reg_val); Configure CS pin. Details esp_rom_gpio_connect_out_signal(SPI_CS, FSPICS0_OUT_IDX, false, false); gpio_ll_input_enable(gpio_dev, SPI_CS); esp_rom_gpio_connect_in_signal(SPI_CS, FSPICS0_IN_IDX, false); gpio_ll_func_sel(gpio_dev, SPI_CS, PIN_FUNC_GPIO); Configure transfer parameters. Details spi_ll_master_set_pos_cs(spi_dev, CS_PIN_ID, false); spi_ll_master_set_rx_timing_mode(spi_dev, false); spi_ll_set_rx_lsbfirst(spi_dev, false); spi_ll_set_tx_lsbfirst(spi_dev, false); spi_ll_master_set_mode(spi_dev, 0); // SPI mode 0 spi_ll_set_half_duplex(spi_dev, false); spi_ll_set_sio_mode(spi_dev, false); spi_ll_master_set_cs_setup(spi_dev, 0); // disable the setup phase spi_ll_master_set_cs_hold(spi_dev, 1); spi_ll_master_select_cs(spi_dev, CS_PIN_ID); spi_ll_set_clk_source(spi_dev, SOC_MOD_CLK_XTAL); Configure and send SPI data.\nDetails spi_line_mode_t line_mode = { .cmd_lines = 1, .addr_lines = 1, .data_lines = 1 }; spi_ll_master_set_line_mode(spi_dev, line_mode); spi_ll_set_dummy(spi_dev, 0); // disable the dummy phase spi_ll_set_mosi_bitlen(spi_dev, TX_BITLEN); spi_ll_set_addr_bitlen(spi_dev, ADDR_BITLEN); spi_ll_set_command_bitlen(spi_dev, CMD_BITLEN); spi_ll_set_command(spi_dev, 0, CMD_BITLEN, false); spi_ll_set_address(spi_dev, 0, ADDR_BITLEN, false); spi_ll_master_keep_cs(spi_dev, 0); // don\u0026#39;t keep CS activated ESP_RTC_LOGI(RTC_LOG_COLOR_GREEN(\u0026#34;SPI_MASTER: Sending: %s\u0026#34;), write_buf); spi_ll_write_buffer(spi_dev, write_buf, TX_BITLEN); spi_ll_enable_mosi(spi_dev, true); spi_ll_apply_config(spi_dev); spi_ll_user_start(spi_dev); while(!spi_ll_usr_is_done(spi_dev)); To conveniently test the wake stub, we implemented a SPI slave task that continuously runs to receive data sent by the transmit task. The receiver uses the SPI driver, and the main function code is shown below. For more information, refer to SPI Slave Driver.\nSlave_app_main.c #include \u0026lt;stdio.h\u0026gt; #include \u0026lt;string.h\u0026gt; #include \u0026#34;driver/spi_slave.h\u0026#34; #include \u0026#34;driver/gpio.h\u0026#34; #include \u0026#34;esp_log.h\u0026#34; #define PIN_NUM_MOSI 4 #define PIN_NUM_MISO 5 #define PIN_NUM_CLK 6 #define PIN_NUM_CS 12 #define RCV_BUF_SIZE 64 static const char *TAG = \u0026#34;SPI_SLAVE\u0026#34;; void app_main(void) { esp_err_t ret; spi_bus_config_t buscfg = { .mosi_io_num = PIN_NUM_MOSI, .miso_io_num = PIN_NUM_MISO, .sclk_io_num = PIN_NUM_CLK, .quadwp_io_num = -1, .quadhd_io_num = -1, .max_transfer_sz = RCV_BUF_SIZE, .flags = SPICOMMON_BUSFLAG_SLAVE | SPICOMMON_BUSFLAG_GPIO_PINS, }; spi_slave_interface_config_t slvcfg = { .spics_io_num = PIN_NUM_CS, .flags = 0, .queue_size = 3, .mode = 0, }; gpio_set_pull_mode(PIN_NUM_MOSI, GPIO_PULLUP_ONLY); gpio_set_pull_mode(PIN_NUM_CLK, GPIO_PULLUP_ONLY); gpio_set_pull_mode(PIN_NUM_CS, GPIO_PULLUP_ONLY); ret = spi_slave_initialize(SPI2_HOST, \u0026amp;buscfg, \u0026amp;slvcfg, SPI_DMA_CH_AUTO); if (ret != ESP_OK) { ESP_LOGE(TAG, \u0026#34;Failed to initialize SPI slave: %s\u0026#34;, esp_err_to_name(ret)); return; } uint8_t recv_buf[RCV_BUF_SIZE] = {0}; spi_slave_transaction_t trans = { .length = RCV_BUF_SIZE * 8, .tx_buffer = NULL, .rx_buffer = recv_buf, }; ESP_LOGI(TAG, \u0026#34;SPI slave ready to receive...\u0026#34;); while (1) { memset(recv_buf, 0, sizeof(recv_buf)); ret = spi_slave_transmit(SPI2_HOST, \u0026amp;trans, portMAX_DELAY); if (ret == ESP_OK) { ESP_LOGI(TAG, \u0026#34;Received: %s\u0026#34;, (char *)recv_buf); } else { ESP_LOGE(TAG, \u0026#34;SPI transmit failed: %s\u0026#34;, esp_err_to_name(ret)); } } spi_slave_free(SPI2_HOST); } Flash the program to the ESP32-C6 acting as the SPI master: Flash the program to the ESP32-C6 acting as the SPI slave: Wrapping up # Now you should know the basics of what the Deep-sleep wake stub application can do and how to begin developing with it.\nFor more Deep-sleep insights and updates, be sure to check back at the developer portal!\n","date":"2 September 2025","externalUrl":null,"permalink":"/blog/2025/09/deep-sleep-wake-stub-get-started/","section":"Blog","summary":"In this article, we first explain the principles behind the Deep-sleep wake stub application and then demonstrate how to implement GPIO, UART, I2C, and SPI within it.","title":"Implementing a Deep-sleep wake stub application on Espressif chips to enable power-efficient IoT devices","type":"blog"},{"content":"We are excited to announce the official release of ESP_IMAGE_EFFECTS) v1.0.0! ESP_IMAGE_EFFECTS is a high-performance image processing library tailored for embedded devices. It provides a unified API for various image effect modules, enabling efficient and flexible integration. With SIMD instruction set optimization and zero-copy memory design, ESP_IMAGE_EFFECTS delivers fast and lightweight image processing, making it ideal for real-time applications in smart homes, industrial vision, edge AI, and more.\nOverview # What is ESP_IMAGE_EFFECTS? # ESP_IMAGE_EFFECTS (esp_imgfx) is a comprehensive image processing library that brings desktop-class image manipulation capabilities to embedded systems. By leveraging hardware acceleration and memory-efficient algorithms, it enables real-time image processing on resource-constrained devices without compromising performance or quality.\nKey Advantages # 🚀 High Performance: SIMD instruction set optimization for maximum throughput 💾 Memory Efficient: Zero-copy memory design minimizes RAM usage 🔧 Flexible APIs: Modular design supports various processing pipelines 📱 Embedded Optimized: Designed specifically for microcontroller environments 🎯 Real-time Ready: Millisecond-level response for time-critical applications Core Features # Image Rotation # ESP_IMAGE_EFFECTS offers a high-performance image rotation solution that supports 1° precision for any angle rotation. It employs a memory block swapping algorithm for standard angles (90°, 180°, 270°) to achieve zero overhead processing. The use of SIMD instructions further enhances processing efficiency, making it suitable for applications like smart cameras, industrial inspection, mobile devices, and more that require real-time image rotation.\n// Rotate image by any angle esp_imgfx_rotate_cfg_t cfg = { .in_pixel_fmt = ESP_IMGFX_PIXEL_FMT_RGB888, .in_res = {.width = 1920, .height = 1080}, .degree = 45 // Any angle from 0-360° }; Color Space Conversion # ESP_IMAGE_EFFECTS offers a comprehensive color space conversion solution, supporting over 100+ RGB/YUV formats, fully compatible with BT601/BT709/BT2020 and other mainstream color space standards. With SIMD hardware acceleration technology, it achieves high-speed color space conversion processing, meeting the strict requirements of professional image processing applications for format compatibility and processing efficiency.\n// Convert image to RGB565 format esp_imgfx_convert_cfg_t cfg = { .in_pixel_fmt = ESP_IMGFX_PIXEL_FMT_RGB888, .out_pixel_fmt = ESP_IMGFX_PIXEL_FMT_RGB565, .in_res = {.width = 1920, .height = 1080}, }; Image Scaling # ESP_IMAGE_EFFECTS provides a high-performance image scaling solution, supporting real-time image scaling with high quality. It supports various scaling algorithms, including down-resampleing and bilinear, and can achieve high-quality image scaling with high performance. The solution is widely used in various scenarios, such as smart cameras, industrial inspection, mobile devices, and more that require real-time image scaling.\n// Scale image to 50% of original size esp_imgfx_scale_cfg_t cfg = { .in_pixel_fmt = ESP_IMGFX_PIXEL_FMT_RGB565, .in_res = {.width = 1920, .height = 1080}, .scale_res = {.width = 960, .height = 540}, .filter = ESP_IMGFX_SCALE_FILTER_TYPE_DOWN_RESAMPLE, }; Image Cropping # ESP_IMAGE_EFFECTS provides a high-performance image cropping solution, which can extract a rectangular area from an image with high precision and high performance. The solution supports any cropping start positions and rectangular area sizes, and can achieve high-quality image cropping with high performance. The solution is widely used in various scenarios, such as smart cameras, industrial inspection, mobile devices, and more that require real-time image cropping.\n// Crop image to a 960x540 region starting at (320, 180) esp_imgfx_crop_cfg_t cfg = { .in_pixel_fmt = ESP_IMGFX_PIXEL_FMT_RGB888, .in_res = {.width = 1920, .height = 1080}, .cropped_res = {.width = 960, .height = 540}, .x_pos = 320, .y_pos = 180, }; API Reference # A unified API for various image effect modules, designed to simplify development by providing a consistent and intuitive interface. It allows developers to apply and manage multiple image effects with minimal code changes, significantly reducing the learning curve.\nCore Functions # Function Pattern Description Example esp_imgfx_*_open Create processing handle esp_imgfx_rotate_open(\u0026amp;cfg, \u0026amp;handle) esp_imgfx_*_get_cfg Get current configuration esp_imgfx_rotate_get_cfg(handle, \u0026amp;cfg) esp_imgfx_*_set_cfg Update configuration esp_imgfx_rotate_set_cfg(handle, \u0026amp;new_cfg) esp_imgfx_*_process Execute image processing esp_imgfx_rotate_process(handle, \u0026amp;in, \u0026amp;out) esp_imgfx_*_close Release handle resources esp_imgfx_rotate_close(handle) esp_imgfx_rotate_get_rotated_resolution Get rotated resolution, only for rotation esp_imgfx_rotate_get_rotated_resolution(handle, \u0026amp;res) Utility Functions # Function Description Use Case esp_imgfx_get_bits_per_pixel Calculate BPP for format Memory allocation esp_imgfx_get_image_size Calculate image size Buffer management Getting Started # Basic Usage Example # #include \u0026#34;esp_imgfx_rotate.h\u0026#34; // Configure rotation parameters esp_imgfx_rotate_cfg_t cfg = { .in_pixel_fmt = ESP_IMGFX_PIXEL_FMT_RGB888, .in_res = {.width = 1920, .height = 1080}, .degree = 90 }; // Create handle esp_imgfx_rotate_handle_t handle; esp_imgfx_err_t ret = esp_imgfx_rotate_open(\u0026amp;cfg, \u0026amp;handle); assert(ESP_IMGFX_ERR_OK == ret); // Prepare image data esp_imgfx_data_t in_image = {.data_len = 1920 * 1080 * 3}; esp_imgfx_data_t out_image = {.data_len = 1920 * 1080 * 3}; // Allocate aligned memory for optimal performance assert(0 == posix_memalign((void **)\u0026amp;in_image.data, 128, in_image.data_len)); assert(0 == posix_memalign((void **)\u0026amp;out_image.data, 128, out_image.data_len)); // Process image ret = esp_imgfx_rotate_process(handle, \u0026amp;in_image, \u0026amp;out_image); assert(ESP_IMGFX_ERR_OK == ret); // Cleanup free(in_image.data); free(out_image.data); esp_imgfx_rotate_close(handle); Real-World Applications # Smart Access Control System # Pipeline: Camera Capture → Rotation Correction → Face Cropping → AI Inference\n// Complete preprocessing pipeline for face recognition // Step 1: Convert YUV420 to RGB565 esp_imgfx_color_convert_process(cc_handle, \u0026amp;yuv420_image, \u0026amp;rgb565_image); // Step 2: Correct image orientation esp_imgfx_rotate_process(rotate_handle, \u0026amp;rgb565_image, \u0026amp;rgb565_rotated); // Step 3: Extract face region esp_imgfx_crop_set_cfg(crop_handle, \u0026amp;face_crop_cfg); esp_imgfx_crop_process(crop_handle, \u0026amp;rgb565_rotated, \u0026amp;face_roi); // Step 4: Ready for AI inference Medical Image Enhancement # Use Case: Endoscope image detail enhancement for diagnostic assistance\n// Enhance specific regions for medical diagnosis // Original: 640x480 → ROI: 200x200 → Enhanced: 800x800 // Step 1: Extract region of interest esp_imgfx_crop_cfg_t roi_cfg; esp_imgfx_crop_get_cfg(crop_handle, \u0026amp;roi_cfg); roi_cfg.cropped_res.width = 200; roi_cfg.cropped_res.height = 200; roi_cfg.x_pos = 220; roi_cfg.y_pos = 140; esp_imgfx_crop_set_cfg(crop_handle, \u0026amp;roi_cfg); esp_imgfx_crop_process(crop_handle, \u0026amp;endoscope_image, \u0026amp;roi_image); // Step 2: Enhance detail with 4x scaling esp_imgfx_scale_cfg_t scale_cfg; esp_imgfx_scale_get_cfg(scale_handle, \u0026amp;scale_cfg); scale_cfg.scale_res.width = 800; scale_cfg.scale_res.height = 800; esp_imgfx_scale_set_cfg(scale_handle, \u0026amp;scale_cfg); esp_imgfx_scale_process(scale_handle, \u0026amp;roi_image, \u0026amp;enhanced_image); Multi-Display Adaptation # Challenge: Support various embedded display sizes (0.96\u0026quot; OLED to 7\u0026quot; industrial screens)\n// Dynamic scaling for different display targets typedef struct { int width, height; const char* name; } display_config_t; display_config_t displays[] = { {128, 64, \u0026#34;0.96\\\u0026#34; OLED\u0026#34;}, {320, 240, \u0026#34;2.4\\\u0026#34; TFT\u0026#34;}, {800, 480, \u0026#34;7\\\u0026#34; Industrial\u0026#34;} }; // Adaptive scaling function void adapt_to_display(esp_imgfx_data_t* src, int display_index) { esp_imgfx_scale_cfg_t scale_cfg; esp_imgfx_scale_get_cfg(scale_handle, \u0026amp;scale_cfg); scale_cfg.scale_res.width = displays[display_index].width; scale_cfg.scale_res.height = displays[display_index].height; esp_imgfx_scale_set_cfg(scale_handle, \u0026amp;scale_cfg); esp_imgfx_scale_process(scale_handle, src, \u0026amp;display_buffer); } Performance Benchmarks # refer to the performance benchmarks for detailed results on processing times and resource usage.\nResources and Support # 📚 Development Resources # 📖 Documentation: Complete API Reference 💻 Sample Projects: In the ESP_IMAGE_EFFECTS Component repo, see the files esp_image_effects/test_apps/main/*.c 📦 Component Registry: ESP_IMAGE_EFFECTS Component 📋 Release Notes: Version History \u0026amp; Updates 🛠️ Technical Support # 💬 Community Forum: ESP32 Developer Community 🐛 Issue Tracker: GitHub Issues 🚀 Getting Started # Install Component: idf.py add-dependency \u0026quot;espressif/esp_image_effects\u0026quot; Run Examples: Check test_apps/ directory for working examples Join Community: Share your projects and get help from developers worldwide Conclusion # Designed for intelligent vision, making every frame efficient!\nESP_IMAGE_EFFECTS v1.0.0 represents a significant milestone in embedded image processing. By combining high performance with ease of use, we\u0026rsquo;re empowering developers to create sophisticated vision applications on resource-constrained devices.\nWhether you\u0026rsquo;re building smart security systems, medical devices, industrial automation, or consumer electronics, ESP_IMAGE_EFFECTS provides the tools you need to process images efficiently and effectively.\nReady to transform your vision applications?\nESP_IMAGE_EFFECTS looks forward to exploring the infinite possibilities of image processing with developers worldwide. Join us in shaping the future of embedded computer vision!\n","date":"29 August 2025","externalUrl":null,"permalink":"/blog/2025/08/announcing_esp_image_effects/","section":"Blog","summary":"Espressif\u0026rsquo;s ESP_IMAGE_EFFECTS component is a powerful image processing library that can do common image processing operations such as scaling, rotation, cropping, and color space conversion. This article introduces the library, shows how to use it in processing images, and provides usage examples.","title":"ESP-Image-Effects Release | Lightweight, Powerful, and Made for a Colorful World","type":"blog"},{"content":"","date":"29 August 2025","externalUrl":null,"permalink":"/authors/hou-haiyan/","section":"Developer Portal Authors","summary":"","title":"Hou Haiyan","type":"authors"},{"content":"","date":"29 August 2025","externalUrl":null,"permalink":"/tags/image-color-space/","section":"Tags","summary":"","title":"Image Color Space","type":"tags"},{"content":"","date":"29 August 2025","externalUrl":null,"permalink":"/tags/image-crop/","section":"Tags","summary":"","title":"Image Crop","type":"tags"},{"content":"","date":"29 August 2025","externalUrl":null,"permalink":"/tags/image-effects/","section":"Tags","summary":"","title":"Image Effects","type":"tags"},{"content":"","date":"29 August 2025","externalUrl":null,"permalink":"/tags/image-processing/","section":"Tags","summary":"","title":"Image Processing","type":"tags"},{"content":"","date":"29 August 2025","externalUrl":null,"permalink":"/tags/image-rotate/","section":"Tags","summary":"","title":"Image Rotate","type":"tags"},{"content":"","date":"29 August 2025","externalUrl":null,"permalink":"/tags/image-scale/","section":"Tags","summary":"","title":"Image Scale","type":"tags"},{"content":" New chip support status This page lists the hardware products currently being integrated into Espressif SDKs and frameworks. The respective product pages provide:\nSupport status of SDKs and frameworks Other important information For versions of hardware products already in mass production, see Espressif website.\n","date":"28 August 2025","externalUrl":null,"permalink":"/hardware/","section":"Hardware","summary":"","title":"Hardware","type":"hardware"},{"content":" Software development status This page lists the software products that are currently being developed or further improved. The respective product pages provide:\nSuppor status of Espressif hardware Support status of features Other important information ","date":"28 August 2025","externalUrl":null,"permalink":"/software/","section":"Software","summary":"","title":"Software","type":"software"},{"content":"","date":"27 August 2025","externalUrl":null,"permalink":"/tags/arduino-core/","section":"Tags","summary":"","title":"Arduino Core","type":"tags"},{"content":" Arduino Support Status # This page is a collection of useful links and Information.\nGeneral Information # Questions about the contents of this page should be directed to:\nEspressif Sales Contact Page Espressif Technical Inquiries Page Arduino for Espressif Discord Server GitHub Issues GitHub Discussions Additionally, be sure to check the Arduino for Espressif section on Espressif\u0026rsquo;s website for general information about Espressif implementation of Arduino APIs. You can also use the chatbot for assistance.\nArduino for Espressif Support Status # Device Support Information # The Arduino Core for ESP32 is an Espressif Initiative, that started in 2016, close to the release of ESP32.\nAll ESP32** chips will eventually be supported, although support levels may vary across devices.\nSupport Status Information # Device support Table Technical Documentation Releases and Plans # Release Plan (GH Wiki) Release Development Status Users should always use the latest release available. Disclaimers # Arduino is a trademark, and its use follow well defined policies. Espressif does not control any aspects of this trademark, and does not claim any ownership of it. Espressif is the developer of the Arduino Core for ESP32 and the Arduino Component for ESP-IDF. Both are implementations of Arduino APIs (or the Arduino Programming Language) compatible with Espressif chips. Arduino Core for ESP32 and Arduino Component for ESP-IDF are licensed under GPL, following the Arduino license. Products based on Arduino Core for ESP32 must comply with GPL. ","date":"27 August 2025","externalUrl":null,"permalink":"/software/arduino-support-status/","section":"Software","summary":"","title":"Arduino Support Status","type":"software"},{"content":"","date":"27 August 2025","externalUrl":null,"permalink":"/authors/ricardo-tafas/","section":"Developer Portal Authors","summary":"","title":"Ricardo Tafas","type":"authors"},{"content":"","date":"27 August 2025","externalUrl":null,"permalink":"/tags/support/","section":"Tags","summary":"","title":"Support","type":"tags"},{"content":" Zephyr Support Status # General Information # Questions about the contents of this page should be directed to:\nEspressif Sales Contact Page Espressif Technical Inquiries Page Zephyr Discord Server – Espressif Channel GitHub Issues GitHub Discussions Additionally, be sure to check the Zephyr section on Espressif\u0026rsquo;s website for general information about Espressif and Zephyr. You can also use the chatbot for assistance.\nFor historical context, users can refer to the ESP32 Support Status RFC.\nZephyr Support Status # Device Support Information # Espressif began contributing directly to the Zephyr project in May 2020. Initially aiming to support only the ESP32, the strategy was later expanded to include other devices in response to community requests.\nAll ESP32** chips will eventually be supported, although support levels may vary across devices.\nSince the release of version 4.0 for the ESP32-C3, the system has been considered stable for production. However, users are always advised to test the system with their specific application before making any major decisions.\nPeripheral Support Table # Loading... Legend:\n✅ : Supported ⏳ : Not yet Supported ❌ : Not available on this device Current chip versions are listed as supported in Zephyr. For the latest chip versions, please consult the Espressif website. Peripherals developed by the community are marked as supported if a test case is provided and has passed both internal manual and automated testing. The camera implementation on ESP32 and ESP32-S2 is based on ESP-IDF software. It will not be ported to Zephyr. ULP is not a full CPU and will not be supported in Zephyr for ESP32 and ESP32-S2. For ESP32 and ESP32-S2, DMA is implemented on a per-peripheral basis. With the exception of the ESP32 DAC, all peripheral DMA is supported. Flash encryption and secure boot are only available through Espressif\u0026rsquo;s port of MCUboot. MCUboot\u0026rsquo;s \u0026ldquo;soft features\u0026rdquo; may still be available in the Zephyr port of MCUboot. SMP (Symmetric MultiProcessing) is currently non-functional and has Bluetooth limitations. Check the thread about it. For ESP8684, please refer to ESP32-C2. For ESP8685, please refer to ESP32-C3. Zephyr Releases # Devices and Release Plan # Espressif fully adheres to the Zephyr schedule and plans its development around Zephyr\u0026rsquo;s public roadmap. The first ready-for-production release of Zephyr for Espressif products was version 4.0, targeting the ESP32-C3.\nLoading... Work on devices often begins before official releases, and devices may become available in the middle of a release cycle. Therefore, the table above reflects the first official release that supports the device. Dates are tentative and subject to change. The Zephyr Release Plan may be updated without notice. Best Release for Espressif Devices # Users should always use the latest hash or commit from the Zephyr repository during the development cycle, due to ongoing updates and bug fixes. During the development stage, users are expected to use the latest available software. In other words, they should work with the most recent commit hash from the Zephyr GitHub repository, even if it does not correspond to a numbered release. The version will typically resemble v4.0-hashnumber.\nEspressif strongly recommends adhering to the rolling release model for Zephyr-based software on its devices, staying aligned with upstream developments. Espressif considers Zephyr version numbers to be weak indicators of software status. Remaining between releases is not seen as problematic, given Git\u0026rsquo;s robust tracking capabilities. Furthermore, any backfixes that diverge from upstream will result in a fork, which, according to best practices, should be avoided.\nEspressif follows Zephyr\u0026rsquo;s LTS releases solely for operating system bug fixes.\nDisclaimers # Espressif does not control the Zephyr Project and does not claim any ownership of it. The Zephyr Project is managed by the Linux Foundation, and Espressif participates as a regular contributor.\nAccordingly, elements such as release dates, planning, issue classification, relevance levels, major technical decisions, and the activities of the Technical Steering Committee (TSC) and the broader community, as well as much of the information found on the Zephyr Project\u0026rsquo;s GitHub, are not under Espressif\u0026rsquo;s control or supervision.\nEspressif remains fully committed to adhering the Zephyr Project\u0026rsquo;s rules, regulations, and governance, just like any other regular contributor. For this reason, Zephyr RTOS is part of Espressif SDK offering, and it is a solution that can be used along with supported Espressif chips.\n","date":"27 August 2025","externalUrl":null,"permalink":"/software/zephyr-support-status/","section":"Software","summary":"","title":"Zephyr Support Status","type":"software"},{"content":"","date":"26 August 2025","externalUrl":null,"permalink":"/tags/adc/","section":"Tags","summary":"","title":"Adc","type":"tags"},{"content":" Introduction # An Analog-to-Digital Converter (ADC) is essential for bridging the gap between the physical analog world and digital systems. It is widely used to bring analog signals — for example, temperature, sound, and voltage — into the digital domain for further processing. The accuracy of an ADC depends on its specifications, including resolution, range, and sampling rate. Additionally, various factors can further affect accuracy, such as offset and gain errors, non-linearity (DNL and INL), and temperature drift.\nIn this article, we will dive into technical details, discuss the accuracy of different Espressif SoCs, and explore techniques to calibrate and improve their accuracy. The following Espressif SoCs will be covered:\nESP32 ESP32-S2 ESP32-S3 ESP32-C3 ESP32-C2 ESP32-C6 ESP32-H2 ESP32-P4 ESP32-C5 ADC Technical Specifications # Espressif SoCs integrate either one or two ADC peripherals capable of measuring analog signals on dedicated IO pins. The table below compares some of their specifications. The specifications can be found in respective datasheets.\nSAR ADC Resolution Channels Range\n(mV) DNL INL Sampling\nrate\n(Ksps) Variation\namong\nsamples ESP32 x2 12-bit 8+10 150 ~ 2450 ±7 ±12 RTC: 200\nDIG: 2000 ±6 % ESP32-S2 x2 13-bit 10+10 0 ~ 2500 ±7 ±12 - - ESP32-S3 x2 12-bit 10+10 0 ~ 2900 ±4 ±8 100 ±100 mV ESP32-C3 x2 12-bit 6 0 ~ 2500 ±7 ±12 100 - ESP32-C2 x1 12-bit 5 0 ~ 2800 +3, -1 +8, -4 100 - ESP32-C6 x1 12-bit 7 0 ~ 3300 +12, -8 ±10 100 - ESP32-H2 x1 12-bit 5 0 ~ 3300 +12, -8 ±10 100 - ESP32-P4 x2 12-bit 14 0 ~ 3300 +3, -1 +3, -5 100 - ESP32-C5 x1 12-bit 6 0 ~ 3300 ±5 ±5 2000 - Table 1. ADC Specifications Comparision\nADC Calibration # In ESP-IDF, an ADC calibration driver is provided to calibrate the raw ADC readings during conversion. The calibration driver helps improve the accuracy by reducing most of the errors.\nThe ADC calibration driver provides ADC calibration schemes. Espressif SoCs support either Line Fitting scheme or Curve Fitting scheme. Line Fitting scheme applies linear transformation in calibration, while Curve Fitting scheme applies non-linear transformation. Calibration schemes contain algorithms and built-in coefficients for converting input raw readings to final output voltage reading. These coefficients are carefully tuned in production line to work on all chips in mass production. The calibration driver also provides APIs to implement custom ADC calibration schemes. However, custom calibration schemes may not work well on all chips, and hence not recommended for mass production.\nThe list below shows the calibration schemes for each series of Espressif SoC.\nESP32: Line Fitting ESP32-S2: Line Fitting ESP32-S3: Curve Fitting ESP32-C3: Curve Fitting ESP32-C2: Line Fitting ESP32-C6: Curve Fitting ESP32-H2: Curve Fitting ESP32-P4: Curve Fitting ESP32-C5: Curve Fitting ADC Accuracy Performance # Here we measure and present a visual demonstration of the overall ADC accuracy performance of Espressif SoCs. In the measurement, we adjust the input voltage in a 10 mV step over time and take the raw value read from the ADC. We then calculate the calibrated voltage from the raw value readings. The measured ADC performance of each SoC is presented in two ways:\nTime Graph: This shows the Input/Output voltage reading over time. It allows us to verify whether the linearity of ADC is as expected. There are 3 lines in the graph: Raw value: Represent raw reading based on the bit width. With a 12-bit resolution, the range of the raw value is from 0 to 4095. Smooth value: Represent calibrated output voltage reading. Base line: Represent input voltage to ADC. Error Graph: This shows the error distribution over voltage. It allows us to view the error range across the supported voltage levels. Note that measurement result on individual chip may slightly differ from the overall SoC performance. For overall result specification, please follow the SoC datasheet.\nESP32 # This graph shows the input/output voltage reading over time for ESP32.\nFig 1. ESP32 Time Graph\nIn Fig 1., we see that the raw reading of ESP32 exhibits offset error. It also shows nonlinearity error at the higher voltage range. However, after calibration, both offset error and nonlinearity are greatly improved. The range is still limited at the start and end of the full-range, mostly due to the offset error.\nThe deviation after calibration cannot be clearly visualized in the voltage over time graph. This can be viewed from the error over voltage graph:\nFig 2. ESP32 Error Graph\nFrom the graph, we can see that, aside from the loss of readings at the beginning and end of the range, the calibrated error is generally less than 30 mV in this measurement. Interestingly, the calibration performs better in the range where the raw readings exhibit non-linearity issues; in this region, the error gradually reduces toward zero.\nESP32-S2 # The time graph shows that the ESP32-S2 suffers from gain error but has better linearity than the ESP32. Calibration can correct the gain error, however, the usable range at the end is lost due to this error.\nFig 3. ESP32-S2 Time Graph\nFrom the error graph the calibrated ESP32-S2 performs much better than the ESP32 in the lower range. However, the error starts to increase gradually when the input voltage exceeds 2200 mV.\nESP32-S2 is best for applications requiring high accuracy in low voltage range.\nFig 4. ESP32-S2 Error Graph\nESP32-S3 # From the time graph, the ESP32-S3 shows good linearity with minimal offset and gain errors in the low-voltage range. At around 2750 mV, it starts to exhibit non-linearity. The calibration corrects the curve but results in a loss of measurements at the higher voltage range.\nFig 5. ESP32-S3 Time Graph\nThe error flucturates between -30 to 0 mV until the output cuts off.\nFig 6. ESP32-S3 Error Graph\nESP32-C3 # The raw readings show that the ESP32-C3 exhibits gain error and slight non-linearity at higher voltage ranges. The calibration scheme corrects the gain error, but a relatively high error still persists at the upper voltage range. In this measurement, the voltage range reaches 2890 mV, and the error increases to about 50 mV at high voltages. Note that the voltage range in specification is up to 2500 mV.\nIt is suggested that designers avoid using the ADC on the ESP32-C3 at higher voltage ranges.\nFig 7. ESP32-C3 Time Graph\nFig 8. ESP32-C3 Error Graph\nESP32-C2 # From the graph, the ESP32-C2 raw readings show a negative gain error, which is corrected well after calibration. The error range after calibration is only about ±10 mV. The ESP32-C2 is recommended for applications that require high ADC accuracy. However, according to the specification, the voltage range is limited to 2800 mV. It is suggested to avoid operating at higher voltage ranges in mass production.\nFig 9. ESP32-C2 Time Graph\nFig 10. ESP32-C2 Error Graph\nESP32-C6 # The ESP32-C6 ADC is able to perform full-range conversion. The raw readings show a negative gain error, which is effectively corrected through calibration, limiting the error to around ±10 mV. As the voltage increases, the error range shifts slightly upward to approximately +20 to 0 mV. Overall, the error range is ±40 mV according to the specification. The ESP32-C6 ADC can be used for full-range applications that require average accuracy.\nFig 11. ESP32-C6 Time Graph\nFig 12. ESP32-C6 Error Graph\nESP32-H2 # Similar to the ESP32-C6, the ESP32-H2 ADC is able to perform full-range conversion, with raw readings showing a negative gain error. Calibration effectively limits the error in the range of ±23 mV, according to the specification. The ESP32-H2 ADC is suitable for full-range applications requiring higher accuracy than the ESP32-C6 can offer.\nFig 13. ESP32-H2 Time Graph\nFig 14. ESP32-H2 Error Graph\nESP32-P4 # The ESP32-P4 ADC is also able to perform full-range conversion, though it exhibits a negative gain error. After calibration, the error remains consistent, within ±15 mV, across the full range. Its accuracy is very close to that of the ESP32-C2, with the added advantage of full-range measurement capability. It is recommended for full-range, high-accuracy applications.\nFig 15. ESP32-P4 Time Graph\nFig 16. ESP32-P4 Error Graph\nESP32-C5 # The ESP32-C5 ADC has similar performance to the ESP32-P4, with slightly higher accuracy in the lower voltage range. It is also recommended for high-accuracy applications.\nFig 17. ESP32-C5 Time Graph\nFig 18. ESP32-C5 Error Graph\nADC Range Extension # As you can see from the graphs presented above, some SoCs do not support full-scale measurement (0–3300 mV). However, full-scale measurement may be required for certain applications. To address this, we provide an ADC range extension solution for the ESP32-S2 and ESP32-S3. The solution is available as a patch for ESP-IDF v4.x and v5.x, respectively.\nNoise Impact # Noise can affect ADC measurements, causing variations between readings of the same input voltage. The documentation recommends connecting a bypass capacitor (e.g., a 100 nF ceramic capacitor) to the ADC input pad to minimize noise. In addition, the technique of multisampling can further reduce the impact of noise.\nTemperature Drift # Temperature drift can affect ADC accuracy when the operating temperature deviates significantly from normal conditions. A temperature compensation algorithm is currently under development for Espressif SoCs that support a curve-fitting scheme. The impact of temperature drift is carefully studied for each SoC and expressed in formulas and coefficients. These formulas and coefficients are then applied during calibration calculations based on readings from the on-board temperature sensor. This feature is expected to be available in ESP-IDF later this year.\nADC Performance Comparison Among SoCs # The graph below provides an overview to help designers choose the right Espressif SoC for applications with different requirements. Note that the graph is based on worst-case figures from the specification. Using lower attenuation settings and applying optimization techniques, it is possible to achieve better performance.\nFig 17. ADC Selection Matrix\nThe ESP32-C2, ESP32-C5, ESP32-P4, ESP32-C6, and ESP32-H2 series can perform full-range measurement. Among them, the ESP32-H2, ESP32-P4, and ESP32-C5 have similar performance and work well in applications requiring high-accuracy ADC performance.\nOther SoCs have a shorter measurement range. However, there is a solution to extend the ADC range for the ESP32-S2 and ESP32-S3.\nThe ESP32 and ESP32-S3 exhibit relatively poorer error performance. Their error characteristics and voltage range should be carefully considered before using them in ADC applications.\nIn addition, sampling rate is also an important factor to consider. Both the ESP32 and ESP32-C5 can achieve higher sampling rates than the others, reaching up to 2000 ksps.\nConclusion # In this article, we explored the technical specifications of the ADCs in Espressif SoCs and discussed their accuracy after calibration. We also introduced ongoing efforts to improve range, noise, and temperature drift performance.\nWith this information, designers can make more informed decisions when selecting the appropriate SoC for their specific ADC application needs.\n","date":"26 August 2025","externalUrl":null,"permalink":"/blog/2025/08/adc-performance/","section":"Blog","summary":"This article compares the Analog-to-Digital Converter (ADC) performance of different Espressif SoCs and shows the techniques to improve the ADC accuracy using software calibration. The results should help developers choose the most suitable SoC and optimize it for their application\u0026rsquo;s accuracy and voltage range requirements.","title":"Comparing ADC Performance of Espressif SoCs","type":"blog"},{"content":"","date":"26 August 2025","externalUrl":null,"permalink":"/tags/peripheral/","section":"Tags","summary":"","title":"Peripheral","type":"tags"},{"content":"","date":"26 August 2025","externalUrl":null,"permalink":"/authors/zhang-wei/","section":"Developer Portal Authors","summary":"","title":"Zhang Wei","type":"authors"},{"content":" Introduction # In microcontroller-based systems running FreeRTOS, developers work within environments that are both constrained and capable. These platforms provide low-level hardware control alongside the benefits of a lightweight real-time operating system.\nC continues to be the primary language in this domain, valued for its efficiency, portability, and direct access to hardware. It enables precise control over performance and resource usage, which is an essential requirement for real-time applications.\nHowever, C also has notable shortcomings. It lacks built-in support for structured error handling and object-oriented programming (OOP), features that can help manage complexity and improve maintainability in large or safety-critical systems. As embedded software becomes more sophisticated, often involving numerous modules, tasks, and hardware interfaces, developers must adopt robust patterns to handle errors and organize code effectively. These needs are especially critical in FreeRTOS-based development, where tasks may fail independently and resources must be carefully managed.\nIn this article, we will examine how ESP-IDF handles error management within its codebase and how you can leverage these tools in your code.\nError handling in C # C provides no built-in exception handling, so error management is a manual, discipline-driven part of embedded development. In systems using FreeRTOS, where multiple tasks may run concurrently and shared resources must be protected, robust error handling becomes even more important to ensure system stability and predictable behavior.\nCommon Techniques # Over the years, two common techniques for managing errors have emerged to manage errors.\nReturn Codes\nThe most widespread method is returning status codes from functions to indicate success or failure. These codes are often:\nIntegers (0 for success, non-zero for errors or warnings) Enumerations representing different error types NULL pointers for memory allocation or resource acquisition failures Each calling function is responsible for checking the return value and taking appropriate action, such as retrying, logging, or aborting.\nGlobal errno Variable\nThe C standard library defines a global variable errno to indicate error conditions set by certain library or system calls (e.g., fopen, malloc). After a function call, a developer can check errno to understand what went wrong. It’s typically used like this:\nFILE *fp = fopen(\u0026#34;config.txt\u0026#34;, \u0026#34;r\u0026#34;); if (fp == NULL) { printf(\u0026#34;File open failed, errno = %d\\n\u0026#34;, errno); } However, in embedded systems FreeRTOS, errno comes with important caveats:\nIt is often shared globally, which makes it unsafe in multi-tasking environments. Some implementations (like newlib with thread-safety enabled) provide thread-local errno, but this increases memory usage. It is rarely used in embedded systems due to its \u0026ldquo;implicit\u0026rdquo; nature. In FreeRTOS-based applications, the use of return code is typically followed approach.\nIn embedded system design, development frameworks often also define:\nCustom error types\nMany embedded projects define their own error handling systems, which typically include a consistent error type definitions across modules (e.g., typedef int err_t;)\nMacros for error checking\nTo reduce repetitive boilerplate code, macros are often used to check errors and handle cleanup in a consistent way:\n#define CHECK(expr) do { if (!(expr)) return ERR_FAIL; } while (0) These can help standardize behavior across tasks and improve code readability.\nIn conclusion, in RTOS-based embedded systems where robustness and reliability are critical, manual error handling must be systematic and consistent. While errno exists and can be used cautiously, most embedded applications benefit more from explicit well-defined error enums and structured reporting mechanisms.\nESP-IDF approach # ESP-IDF defines its error codes as esp_err_t type and provides a couple of error checking macros.\nesp_err_t \u0026ndash; Structured error codes\nEspressif’s ESP-IDF framework introduces a standardized error handling approach through the use of the esp_err_t type. This is a 32-bit integer used to represent both generic and module-specific error codes. The framework defines a wide range of constants, such as:\n#define ESP_OK 0 // Success #define ESP_FAIL 0x101 // Generic failure #define ESP_ERR_NO_MEM 0x103 // Out of memory #define ESP_ERR_INVALID_ARG 0x102 // Invalid argument The full list is available on the error codes documentation page.\nDevelopers typically write functions that return esp_err_t, and use these codes to control program flow or report diagnostics. ESP_OK is zero and errors can be easily checked like this:\nesp_err_t ret = i2c_driver_install(...); if (ret != ESP_OK) { printf(\u0026#34;I2C driver install failed: %s\u0026#34;, esp_err_to_name(ret)); return ret; } ESP-IDF also provides utilities like esp_err_to_name() and esp_err_to_name_r() to convert error codes into readable strings for logging, which is particularly helpful for debugging.\nESP_ERROR_CHECK \u0026ndash; Error checking macro\nTo reduce repetitive error checking code in testing and examples, ESP-IDF includes macros like ESP_ERROR_CHECK(). This macro evaluates an expression (typically a function call returning esp_err_t), logs a detailed error message if the result is not ESP_OK, and aborts the program. You will find this macro repeatedly used in ESP-IDF examples:\nESP_ERROR_CHECK(i2c_driver_install(...)); There is also ESP_ERROR_CHECK_WITHOUT_ABORT version of this macro which doesn\u0026rsquo;t stop execution if an error is returned.\nOut of curiosity, let\u0026rsquo;s look at the macro definition\n#define ESP_ERROR_CHECK(x) do { \\ esp_err_t err_rc_ = (x); \\ if (unlikely(err_rc_ != ESP_OK)) { \\ abort(); \\ } \\ } while(0) At its core, this macro simply checks whether the given value equals ESP_OK and halts execution if it does not. However, there are two elements that might seem confusing if you\u0026rsquo;re not familiar with C macros:\nThe do { } while (0) wrapper\nThis is a common best practice when writing multi-line macros. It ensures the macro behaves like a single statement in all contexts, helping avoid unexpected behavior during compilation. If you\u0026rsquo;re curious about the reasoning behind this pattern, this article offers a good explanation.\nThe unlikely function\nThis is used as a compiler optimization hint. It tells the compiler that the condition err_rc_ != ESP_OK is expected to be false most of the time—i.e., errors are rare—so it can optimize for the more common case where ESP_OK is returned. While it doesn\u0026rsquo;t change the program\u0026rsquo;s behavior, it can improve performance by guiding branch prediction and code layout.\nExamples # In this section, we’ll start with a simple, self-contained example to demonstrate how error codes and macros work in practice. Then, we’ll examine how these concepts are applied in an actual ESP-IDF example by reviewing its source code.\nBasic Example: Division # To demonstrate the use of the error codes, we will implement a division function.\nUnlike other basic operations, division can result in an error if the second argument is zero, which is not allowed. To handle this case, we use an esp_err_t return type for error reporting.\nThe division function is implemented as follows:\nesp_err_t division(float * result, float a, float b){ if(b==0 || result == NULL){ return ESP_ERR_INVALID_ARG; } *result = a/b; return ESP_OK; } As you can see, since the function’s return type is esp_err_t, we need an alternative way to return the division result. The standard approach is to pass a pointer to a result variable as an argument. While this may seem cumbersome for a simple application, its advantages become increasingly clear when applying object-oriented programming (OOP) principles in C.\nIn the app_main function, we first check for errors before printing the result.\nvoid app_main(void) { printf(\u0026#34;\\n\\n*** Testing Errors ***!\\n\\n\u0026#34;); float division_result = 0; float a = 10.5; float b = 3.3; if(division(\u0026amp;division_result,a,b)==ESP_OK){ printf(\u0026#34;Working division: %f\\n\u0026#34;, division_result); }else{ printf(\u0026#34;Division Error!\\n\u0026#34;); } b = 0; if(division(\u0026amp;division_result,a,b)==ESP_OK){ printf(\u0026#34;Working division: %f\\n\u0026#34;, division_result); }else{ printf(\u0026#34;Division Error!\\n\u0026#34;); } } And the result is as expected\n*** Testing Errors ***! Working division: 3.181818 Division Error! We can also use ESP_ERROR_CHECK_WITHOUT_ABORT(division(\u0026amp;division_result,a,b)) instead of the if/else block. It results is a silent pass for the first function call and in the following message for the second.\nESP_ERROR_CHECK_WITHOUT_ABORT failed: esp_err_t 0x102 (ESP_ERR_INVALID_ARG) at 0x4200995a --- 0x4200995a: app_main at \u0026lt;folder_path\u0026gt;/error-example/main/main.c:37 file: \u0026#34;./main/main.c\u0026#34; line 37 func: app_main expression: division(\u0026amp;division_result, a, b) Using ESP_ERROR_CHECK makes the system reboot after the error is found.\nESP-IDF example # Let’s examine a more complete example taken directly from the ESP-IDF example folder. The following code is from the HTTPS request example.\nThe app_main function code is as follows\nvoid app_main(void) { ESP_ERROR_CHECK(nvs_flash_init()); ESP_ERROR_CHECK(esp_netif_init()); ESP_ERROR_CHECK(esp_event_loop_create_default()); //[...] ESP_ERROR_CHECK(example_connect()); if (esp_reset_reason() == ESP_RST_POWERON) { ESP_ERROR_CHECK(update_time_from_nvs()); } const esp_timer_create_args_t nvs_update_timer_args = { .callback = (void *)\u0026amp;fetch_and_store_time_in_nvs, }; esp_timer_handle_t nvs_update_timer; ESP_ERROR_CHECK(esp_timer_create(\u0026amp;nvs_update_timer_args, \u0026amp;nvs_update_timer)); ESP_ERROR_CHECK(esp_timer_start_periodic(nvs_update_timer, TIME_PERIOD)); xTaskCreate(\u0026amp;https_request_task, \u0026#34;https_get_task\u0026#34;, 8192, NULL, 5, NULL); } As you can see, almost all function calls are surrounded by the ESP_ERROR_CHECK macro.\nESP_ERROR_CHECK is used only in examples and prototypes because it aborts execution on error. It should not be used in production code, where a properly designed error-handling mechanism is preferred. Conclusion # In this article, we examined error handling in FreeRTOS-based embedded systems, focusing on the ESP-IDF framework. We covered common C techniques, the importance of systematic error management, and how ESP-IDF uses esp_err_t and macros to simplify error checking. Through both a simple example and a real-world ESP-IDF example, we saw practical applications of these concepts to improve code robustness and reliability.\n","date":"19 August 2025","externalUrl":null,"permalink":"/blog/2025/08/errors_and_logging/","section":"Blog","summary":"This article explains error handling in FreeRTOS-based embedded systems, highlighting common C practices and their limitations. It introduces ESP-IDF’s \u003ccode\u003eesp_err_t\u003c/code\u003e type and error-checking macros, demonstrating how they help manage errors systematically. It shows practical ways to implement error handling in embedded applications.","title":"ESP-IDF tutorial series: Errors","type":"blog"},{"content":" Assignment steps # You will:\nRun the example (to make sure that everything is working) Create an alarm component Add the component configuration Run the example # To test that everything it\u0026rsquo;s working, first you need to just run the example.\nClone the repo with the starting code\ngit clone https://github.com/FBEZ-docs-and-templates/devrel-advanced-workshop-code Open the folder assignment_1_1_base with VSCode\nNote: assigment_1_1_base and assignment_3_2_base are starting code. All other folders contain the solution for the assignments Set the target: \u0026gt; ESP-IDF: Set Espressif Device Target Select the port: \u0026gt; ESP-IDF: Select Port to Use (COM, tty, usbserial) Set the AP data:\nOpen menuconfig: \u0026gt; ESP-IDF: SDK Configuration Editor (menuconfig)\n→ WiFi SSID → Set your ssid\n→ WiFi Password → Set your password\nBuild, flash and monitor the device\n\u0026gt; ESP-IDF: Build, Flash, and Start a Monitor on Your Device\n(or hit the flame icon (🔥) located in the bottom bar) You should now see the example running and connecting to your WiFi network and to the mqtt://test.mosquitto.org server.\nShow terminal output I (30) boot: ESP-IDF v5.4.2-dirty 2nd stage bootloader I (30) boot: compile time Jul 22 2025 10:52:56 I (30) boot: chip revision: v0.1 I (31) boot: efuse block revision: v1.0 I (34) boot.esp32c3: SPI Speed : 80MHz I (38) boot.esp32c3: SPI Mode : DIO I (42) boot.esp32c3: SPI Flash Size : 2MB I (46) boot: Enabling RNG early entropy source... I (50) boot: Partition Table: I (53) boot: ## Label Usage Type ST Offset Length I (59) boot: 0 nvs WiFi data 01 02 00009000 00006000 I (66) boot: 1 phy_init RF data 01 01 0000f000 00001000 I (72) boot: 2 factory factory app 00 00 00010000 00100000 I (79) boot: End of partition table I (82) esp_image: segment 0: paddr=00010020 vaddr=3c0c0020 size=1e7ech (124908) map I (109) esp_image: segment 1: paddr=0002e814 vaddr=3fc93c00 size=01804h ( 6148) load I (111) esp_image: segment 2: paddr=00030020 vaddr=42000020 size=b1fd4h (729044) map I (229) esp_image: segment 3: paddr=000e1ffc vaddr=3fc95404 size=01620h ( 5664) load I (231) esp_image: segment 4: paddr=000e3624 vaddr=40380000 size=13b38h ( 80696) load I (248) esp_image: segment 5: paddr=000f7164 vaddr=50000000 size=0001ch ( 28) load I (254) boot: Loaded app from partition at offset 0x10000 I (254) boot: Disabling RNG early entropy source... I (265) cpu_start: Unicore app I (274) cpu_start: Pro cpu start user code I (274) cpu_start: cpu freq: 160000000 Hz I (274) app_init: Application information: I (274) app_init: Project name: mqtt_tcp I (278) app_init: App version: 1 I (281) app_init: Compile time: Jul 22 2025 10:53:00 I (286) app_init: ELF file SHA256: b10017352... I (291) app_init: ESP-IDF: v5.4.2-dirty I (295) efuse_init: Min chip rev: v0.1 I (299) efuse_init: Max chip rev: v1.99 I (303) efuse_init: Chip rev: v0.1 I (307) heap_init: Initializing. RAM available for dynamic allocation: I (313) heap_init: At 3FC9B2E0 len 00024D20 (147 KiB): RAM I (318) heap_init: At 3FCC0000 len 0001C710 (113 KiB): Retention RAM I (324) heap_init: At 3FCDC710 len 00002B50 (10 KiB): Retention RAM I (330) heap_init: At 5000001C len 00001FCC (7 KiB): RTCRAM I (336) spi_flash: detected chip: generic I (339) spi_flash: flash io: dio W (342) spi_flash: Detected size(4096k) larger than the size in the binary image header(2048k). Using the size in the binary image header. I (355) sleep_gpio: Configure to isolate all GPIO pins in sleep state I (361) sleep_gpio: Enable automatic switching of GPIO sleep configuration I (367) main_task: Started on CPU0 I (377) main_task: Calling app_main() I (377) mqtt_example: [APP] Startup.. I (377) mqtt_example: [APP] Free memory: 270780 bytes I (377) mqtt_example: [APP] IDF version: v5.4.2-dirty I (397) temperature_sensor: Range [-10°C ~ 80°C], error \u0026lt; 1°C I (397) example_connect: Start example_connect. I (397) pp: pp rom version: 8459080 I (397) net80211: net80211 rom version: 8459080 I (417) wifi:wifi driver task: 3fca3b0c, prio:23, stack:6656, core=0 I (417) wifi:wifi firmware version: bea31f3 I (417) wifi:wifi certification version: v7.0 I (417) wifi:config NVS flash: enabled I (417) wifi:config nano formatting: disabled I (427) wifi:Init data frame dynamic rx buffer num: 32 I (427) wifi:Init static rx mgmt buffer num: 5 I (437) wifi:Init management short buffer num: 32 I (437) wifi:Init dynamic tx buffer num: 32 I (447) wifi:Init static tx FG buffer num: 2 I (447) wifi:Init static rx buffer size: 1600 I (447) wifi:Init static rx buffer num: 10 I (457) wifi:Init dynamic rx buffer num: 32 I (457) wifi_init: rx ba win: 6 I (457) wifi_init: accept mbox: 6 I (467) wifi_init: tcpip mbox: 32 I (467) wifi_init: udp mbox: 6 I (467) wifi_init: tcp mbox: 6 I (477) wifi_init: tcp tx win: 5760 I (477) wifi_init: tcp rx win: 5760 I (477) wifi_init: tcp mss: 1440 I (487) wifi_init: WiFi IRAM OP enabled I (487) wifi_init: WiFi RX IRAM OP enabled I (487) phy_init: phy_version 1201,bae5dd99,Mar 3 2025,15:36:21 I (527) wifi:mode : sta (7c:df:a1:42:64:70) I (527) wifi:enable tsf I (527) example_connect: Connecting to SamsungFrancesco... W (527) wifi:Password length matches WPA2 standards, authmode threshold changes from OPEN to WPA2 I (537) example_connect: Waiting for IP(s) I (3057) wifi:new:\u0026lt;1,0\u0026gt;, old:\u0026lt;1,0\u0026gt;, ap:\u0026lt;255,255\u0026gt;, sta:\u0026lt;1,0\u0026gt;, prof:1, snd_ch_cfg:0x0 I (3057) wifi:state: init -\u0026gt; auth (0xb0) I (4057) wifi:state: auth -\u0026gt; init (0x200) I (4057) wifi:new:\u0026lt;1,0\u0026gt;, old:\u0026lt;1,0\u0026gt;, ap:\u0026lt;255,255\u0026gt;, sta:\u0026lt;1,0\u0026gt;, prof:1, snd_ch_cfg:0x0 I (4057) example_connect: Wi-Fi disconnected 2, trying to reconnect... I (6477) example_connect: Wi-Fi disconnected 205, trying to reconnect... I (8887) wifi:new:\u0026lt;1,0\u0026gt;, old:\u0026lt;1,0\u0026gt;, ap:\u0026lt;255,255\u0026gt;, sta:\u0026lt;1,0\u0026gt;, prof:1, snd_ch_cfg:0x0 I (8887) wifi:state: init -\u0026gt; auth (0xb0) I (8967) wifi:state: auth -\u0026gt; assoc (0x0) I (9017) wifi:state: assoc -\u0026gt; run (0x10) I (9087) wifi:connected with SamsungFrancesco, aid = 1, channel 1, BW20, bssid = ce:db:d8:a6:6b:2a I (9087) wifi:security: WPA2-PSK, phy: bgn, rssi: -50 I (9087) wifi:pm start, type: 1 I (9097) wifi:dp: 1, bi: 102400, li: 3, scale listen interval from 307200 us to 307200 us I (9107) wifi:set rx beacon pti, rx_bcn_pti: 0, bcn_timeout: 25000, mt_pti: 0, mt_time: 10000 I (9147) wifi:\u0026lt;ba-add\u0026gt;idx:0 (ifx:0, ce:db:d8:a6:6b:2a), tid:0, ssn:1, winSize:64 I (9177) wifi:dp: 2, bi: 102400, li: 4, scale listen interval from 307200 us to 409600 us I (9177) wifi:AP\u0026#39;s beacon interval = 102400 us, DTIM period = 2 I (10157) esp_netif_handlers: example_netif_sta ip: 10.75.149.18, mask: 255.255.255.0, gw: 10.75.149.225 I (10157) example_connect: Got IPv4 event: Interface \u0026#34;example_netif_sta\u0026#34; address: 10.75.149.18 I (10397) example_connect: Got IPv6 event: Interface \u0026#34;example_netif_sta\u0026#34; address: fe80:0000:0000:0000:7edf:a1ff:fe42:6470, type: ESP_IP6_ADDR_IS_LINK_LOCAL I (10397) example_common: Connected to example_netif_sta I (10397) example_common: - IPv4 address: 10.75.149.18, I (10407) example_common: - IPv6 address: fe80:0000:0000:0000:7edf:a1ff:fe42:6470, type: ESP_IP6_ADDR_IS_LINK_LOCAL I (10417) mqtt_example: Other event id:7 I (15517) mqtt_example: Temperature: 37.60 °C E (19627) transport_base: tcp_read error, errno=Connection reset by peer E (19627) mqtt_client: esp_mqtt_handle_transport_read_error: transport_read() error: errno=104 I (19637) mqtt_example: MQTT_EVENT_ERROR E (19637) mqtt_example: Last error captured as transport\u0026#39;s socket errno: 0x68 I (19647) mqtt_example: Last errno string (Connection reset by peer) E (19647) mqtt_client: esp_mqtt_connect: mqtt_message_receive() returned -2 E (19657) mqtt_client: MQTT connect failed I (19657) mqtt_example: MQTT_EVENT_DISCONNECTED I (20567) mqtt_example: Temperature: 36.60 °C I (25667) mqtt_example: Temperature: 36.60 °C I (29667) mqtt_example: Other event id:7 I (30667) mqtt_example: Temperature: 36.60 °C Create the alarm component # To create the alarm component, you need to\n\u0026gt; ESP-IDF: Create New ESP-IDF Component\n→ alarm\nA new components/alarm folder is crated.\nMove the files into the component folder\nalarm.c → components/alarm/alarm.c\nalarm.h → components/alarm/include/alarm.h\nAdd the esp_timer requirement to the component CMakeLists.txt\nidf_component_register(SRCS \u0026#34;alarm.c\u0026#34; REQUIRES esp_timer INCLUDE_DIRS \u0026#34;include\u0026#34;) You didn\u0026rsquo;t need to add REQUIRES esp_timer in the main component, because it inherited dependencies from the main application\u0026rsquo;s build configuration Add the component configuration # In alarm.c file, you can see two hardcoded values\n#define ALARM_THRESHOLD_PERCENT 2 // 2% chance #define ALARM_REFRESH_INTERVAL_MS 1000 // reevaluate every 1000 ms We will replace these values with component configurations.\nCreate a Kconfig file in the root directory of the alarm component Add the following to Kconfig\nmenu \u0026#34;Alarm Component Configuration\u0026#34; config ALARM_THRESHOLD_PERCENT int \u0026#34;Alarm threshold percent\u0026#34; default 2 range 0 100 help Set the threshold percent for the alarm (e.g., 2 for 2% chance). config ALARM_REFRESH_INTERVAL_MS int \u0026#34;Alarm refresh interval (ms)\u0026#34; default 1000 range 1 60000 help Set the interval in milliseconds to reevaluate the alarm. endmenu Comment out the defines\n//#define ALARM_THRESHOLD_PERCENT 2 // 2% chance //#define ALARM_REFRESH_INTERVAL_MS 1000 // reevaluate every 1000 ms Replace the macro name in the rest of the code\nALARM_THRESHOLD_PERCENT → CONFIG_ALARM_THRESHOLD_PERCENT ALARM_REFRESH_INTERVAL_MS → CONFIG_ALARM_REFRESH_INTERVAL_MS Clean the project: ESP-IDF: Full Clean Project Rebuild and flash: ESP-IDF: Build, Flash and Start Monitor on Your Device Assignment solution code # Show full assignment code alarm.c\n#include \u0026lt;stdlib.h\u0026gt; #include \u0026#34;alarm.h\u0026#34; #include \u0026#34;esp_random.h\u0026#34; #include \u0026#34;esp_timer.h\u0026#34; // for esp_timer_get_time() // Define internal behavior constants // #define ALARM_THRESHOLD_PERCENT 2 // 2% chance // #define ALARM_REFRESH_INTERVAL_MS 1000 // reevaluate every 1000 ms // Internal alarm structure (hidden from user) struct alarm_t { int64_t last_check_time_us; bool last_state; }; alarm_t* alarm_create(void) { alarm_t *alarm = malloc(sizeof(alarm_t)); if (!alarm) return NULL; alarm-\u0026gt;last_check_time_us = 0; alarm-\u0026gt;last_state = false; return alarm; } bool is_alarm_set(alarm_t *alarm) { if (!alarm) return false; int64_t now_us = esp_timer_get_time(); int64_t elapsed_us = now_us - alarm-\u0026gt;last_check_time_us; if (elapsed_us \u0026gt;= CONFIG_ALARM_REFRESH_INTERVAL_MS * 1000) { uint32_t rand_val = esp_random() % 100; alarm-\u0026gt;last_state = rand_val \u0026lt; CONFIG_ALARM_THRESHOLD_PERCENT; alarm-\u0026gt;last_check_time_us = now_us; } return alarm-\u0026gt;last_state; } void alarm_delete(alarm_t *alarm) { if (alarm) { free(alarm); } } Kconfig\nmenu \u0026#34;Alarm Component Configuration\u0026#34; config ALARM_THRESHOLD_PERCENT int \u0026#34;Alarm threshold percent\u0026#34; default 2 range 0 100 help Set the threshold percent for the alarm (e.g., 2 for 2% chance). config ALARM_REFRESH_INTERVAL_MS int \u0026#34;Alarm refresh interval (ms)\u0026#34; default 1000 range 1 60000 help Set the interval in milliseconds to reevaluate the alarm. You can find the whole solution project on the assignment_1_1 folder on the github repo.\nNext step: assignment_1_2\n","date":"5 August 2025","externalUrl":null,"permalink":"/workshops/esp-idf-advanced/assignment-1-1/","section":"Workshops","summary":"Create the \u003ccode\u003ealarm\u003c/code\u003e component and refactor the code to use it. (Guided)","title":"ESP-IDF Adv. - Assign.  1.1","type":"workshops"},{"content":"In this second part, we will separate the connection logic from the main function. The main advantage of this approach is that you could transparently change the connection type (e.g. to MQTTS or HTTP).\nIn this assignment, we will refactor the connection to Wi-Fi and MQTT code to fit into a new component.\nAssignment details # You should create a cloud_manager component with the following methods\ncloud_manager_t *cloud_manager_create(void); esp_err_t cloud_manager_connect(cloud_manager_t *manager); esp_err_t cloud_manager_disconnect(cloud_manager_t *manager); esp_err_t cloud_manager_send_temperature(cloud_manager_t *manager, float temp); esp_err_t cloud_manager_send_alarm(cloud_manager_t *manager); void cloud_manager_delete(cloud_manager_t *manager); The following parameters should be set through menuconfig:\nBroker URL (move it from the main to the cloud_manager component) The channel where the temperature is published (sensor/temperature by default) The channel where the alarm is published (sensor/alarm by default) Assignment steps outline # Create a new component and fill cloud_manager.h Add the suggested methods\nAdd an opaque declaration typedef struct cloud_manager_t cloud_manager_t;\nNote: In cloud_manager.h you need to import just esp_err.h Fill cloud_manager.c\nImplement cloud_manager_t as: struct cloud_manager_t { esp_mqtt_client_handle_t client; esp_mqtt_client_config_t mqtt_cfg; }; In cloud_manager_create just return the initialized object. In cloud_manager_connect initialize everything. You can use the function example_connect. Add the following to the cloud_manager component CMakeList.txt\nPRIV_REQUIRES mqtt nvs_flash esp_netif protocol_examples_common In app_main.c\nInitialize and connect to the cloud_manager cloud_manager_t *cloud = cloud_manager_create(); ESP_ERROR_CHECK(cloud_manager_connect(cloud)); Call the publishing functions in the appropriate position Assignment solution code # Show full assignment code cloud_manager.h # #pragma once #include \u0026#34;esp_err.h\u0026#34; typedef struct cloud_manager_t cloud_manager_t; /** * @brief Creates a new cloud manager instance */ cloud_manager_t *cloud_manager_create(void); /** * @brief Connects the cloud manager (starts MQTT) */ esp_err_t cloud_manager_connect(cloud_manager_t *manager); /** * @brief Disconnects the cloud manager */ esp_err_t cloud_manager_disconnect(cloud_manager_t *manager); /** * @brief Sends a temperature value to the cloud */ esp_err_t cloud_manager_send_temperature(cloud_manager_t *manager, float temp); /** * @brief Sends an alarm event to the cloud */ esp_err_t cloud_manager_send_alarm(cloud_manager_t *manager); /** * @brief Frees the memory */ void cloud_manager_delete(cloud_manager_t *manager); cloud_manager.c # #include \u0026lt;stdio.h\u0026gt; #include \u0026lt;string.h\u0026gt; #include \u0026#34;cloud_manager.h\u0026#34; #include \u0026#34;esp_log.h\u0026#34; #include \u0026#34;mqtt_client.h\u0026#34; #include \u0026#34;nvs_flash.h\u0026#34; #include \u0026#34;esp_event.h\u0026#34; #include \u0026#34;esp_netif.h\u0026#34; #include \u0026#34;protocol_examples_common.h\u0026#34; static const char *TAG = \u0026#34;cloud_manager\u0026#34;; struct cloud_manager_t { esp_mqtt_client_handle_t client; esp_mqtt_client_config_t mqtt_cfg; }; // Event handler for MQTT static void mqtt_event_handler(void *handler_args, esp_event_base_t base, int32_t event_id, void *event_data) { esp_mqtt_event_handle_t event = event_data; esp_mqtt_client_handle_t client = event-\u0026gt;client; switch ((esp_mqtt_event_id_t)event_id) { case MQTT_EVENT_CONNECTED: ESP_LOGI(TAG, \u0026#34;Connected to MQTT broker\u0026#34;); esp_mqtt_client_subscribe(client, CONFIG_TEMPERATURE_CHANNEL, 0); esp_mqtt_client_subscribe(client, CONFIG_ALARM_CHANNEL, 0); break; case MQTT_EVENT_DISCONNECTED: ESP_LOGI(TAG, \u0026#34;Disconnected from MQTT broker\u0026#34;); break; case MQTT_EVENT_PUBLISHED: ESP_LOGI(TAG, \u0026#34;Message published (msg_id=%d)\u0026#34;, event-\u0026gt;msg_id); break; case MQTT_EVENT_ERROR: ESP_LOGE(TAG, \u0026#34;MQTT_EVENT_ERROR\u0026#34;); break; default: break; } } cloud_manager_t *cloud_manager_create(void) { cloud_manager_t *manager = calloc(1, sizeof(cloud_manager_t)); if (!manager) return NULL; manager-\u0026gt;mqtt_cfg = (esp_mqtt_client_config_t){ .broker.address.uri = CONFIG_BROKER_URL, }; return manager; } esp_err_t cloud_manager_connect(cloud_manager_t *manager) { if(manager == NULL){return ESP_ERR_INVALID_ARG;} ESP_ERROR_CHECK(nvs_flash_init()); ESP_ERROR_CHECK(esp_netif_init()); manager-\u0026gt;client = esp_mqtt_client_init(\u0026amp;manager-\u0026gt;mqtt_cfg); esp_mqtt_client_register_event(manager-\u0026gt;client, ESP_EVENT_ANY_ID, mqtt_event_handler, manager); ESP_ERROR_CHECK(example_connect()); return esp_mqtt_client_start(manager-\u0026gt;client); } esp_err_t cloud_manager_disconnect(cloud_manager_t *manager) { if (!manager || !manager-\u0026gt;client) return ESP_ERR_INVALID_ARG; return esp_mqtt_client_stop(manager-\u0026gt;client); } esp_err_t cloud_manager_send_temperature(cloud_manager_t *manager, float temp) { if (!manager || !manager-\u0026gt;client) return ESP_ERR_INVALID_ARG; char payload[64]; snprintf(payload, sizeof(payload), \u0026#34;%.2f\u0026#34;, temp); ESP_LOGI(TAG, \u0026#34;Temperature: %.2f °C\u0026#34;, temp); int msg_id = esp_mqtt_client_publish(manager-\u0026gt;client, CONFIG_TEMPERATURE_CHANNEL, payload, 0, 1, 0); return msg_id \u0026gt;= 0 ? ESP_OK : ESP_FAIL; } esp_err_t cloud_manager_send_alarm(cloud_manager_t *manager) { if (!manager || !manager-\u0026gt;client) return ESP_ERR_INVALID_ARG; const char *alarm_payload = \u0026#34;ALARM ON!\u0026#34;; int msg_id = esp_mqtt_client_publish(manager-\u0026gt;client, CONFIG_ALARM_CHANNEL, alarm_payload, 0, 1, 0); return msg_id \u0026gt;= 0 ? ESP_OK : ESP_FAIL; } void cloud_manager_delete(cloud_manager_t *manager) { if (manager) { free(manager); } } Kconfig # menu \u0026#34;Cloud MQTT Configuration\u0026#34; config BROKER_URL string \u0026#34;Broker URL\u0026#34; default \u0026#34;mqtt://test.mosquitto.org/\u0026#34; help URL of the broker to connect to config TEMPERATURE_CHANNEL string \u0026#34;MQTT channel for publishing the temperature\u0026#34; default \u0026#34;/sensor/temperature\u0026#34; help The channel in the mqtt broker where the temperature is published config ALARM_CHANNEL string \u0026#34;MQTT channel for publishing the alarm\u0026#34; default \u0026#34;/sensor/alarm\u0026#34; help The channel in the mqtt broker where the alarm is published endmenu You can find the whole solution project on the assignment_1_2 folder on the github repo.\nNext step: assignment 1.3\n","date":"5 August 2025","externalUrl":null,"permalink":"/workshops/esp-idf-advanced/assignment-1-2/","section":"Workshops","summary":"Create a \u003ccode\u003ecloud_manager\u003c/code\u003e component and refactor the code to use it.","title":"ESP-IDF Adv. - Assign.  1.2","type":"workshops"},{"content":"In this assignment, you will create two versions of sdkconfig (production and debug). The only difference between the two is the logging: Debug will display all logs, while production has all the logs suppressed.\nAssignment Detail # You project must have the following configuration files:\nsdkconfig.defaults: containing the esp32-c3 target sdkconfig.prod: containing the logging suppression configuration (both app log and bootloader log) sdkconfig.debug: containing the logging enable configuration profile files to simplify the build command The final project folder tree is\n. |-- main | |-- CMakeLists.txt | |-- app_main.c | `-- idf_component.yml |-- profiles | |-- debug | `-- prod |-- sdkconfig |-- sdkconfig.debug |-- sdkconfig.defaults |-- sdkconfig.old `-- sdkconfig.prod Assignment steps # We will:\nCreate the production sdkconfig version (guided) Create a profile file (guided) Create the debug sdkconfig version Create production version (guided) # To create the debug configuration, we first need to find the log configuration.\nChanging the configuration in menuconfig # ESP-IDF: SDK Configuration Editor (menuconfig)\nSearch for log Uncheck the fields\nBootloader Config → Bootloader log verbosity Log → Log Lever → Default log verbosity Create sdkconfig.prod file # The easiest way to find the configuration names that we changed is to run the save-defconfig tool, which will generate a sdkconfig.defaults file with only the changed parameters.\nESP-IDF: Save Default Config File (save-defconfig) Looking at the new sdkconfig.defaults, we can see two new configurations:\nCONFIG_LOG_DEFAULT_LEVEL_NONE=y CONFIG_BOOTLOADER_LOG_LEVEL_NONE=y Cut these configs and paste them into a sdkconfig.prod file Build and flash # To build the project use\nidf.py -B build-production -DSDKCONFIG=build-production/sdkconfig -DSDKCONFIG_DEFAULTS=\u0026#34;sdkconfig.defaults;sdkconfig.prod\u0026#34; build It will create a build-production folder for this version.\nTo flash the project, you just need to specify the build folder, which already contains all the required information\nidf.py -B build-debug -p \u0026lt;YOUR_PORT\u0026gt; flash monitor Create Profile files # To simplify the process we will create a profile file.\nCreate a profile folder Create a prod file inside the folder Add the CLI parameters\n-B build-production -DSDKCONFIG=build-production/sdkconfig -DSDKCONFIG_DEFAULTS=\u0026#34;sdkconfig.defaults;sdkconfig.prod\u0026#34; We can now build the production version using\nidf.py @profiles/prod build Debug version # Now you can do the same for the debugging setup. For this assignment step, you need to create and fill:\nsdkconfig.debug profile/debug Assignment solution code # Show solution code skdconfig.defaults\n# This file was generated using idf.py save-defconfig. It can be edited manually. # Espressif IoT Development Framework (ESP-IDF) 5.4.2 Project Minimal Configuration # CONFIG_IDF_TARGET=\u0026#34;esp32c3\u0026#34; skdconfig.prod\nCONFIG_LOG_DEFAULT_LEVEL_NONE=y CONFIG_BOOTLOADER_LOG_LEVEL_NONE=y skdconfig.prod\nCONFIG_LOG_DEFAULT_LEVEL_INFO=y You can find the whole solution project in the assignment_1_3 folder in the GitHub repo.\nNext step: Lecture 2\n","date":"5 August 2025","externalUrl":null,"permalink":"/workshops/esp-idf-advanced/assignment-1-3/","section":"Workshops","summary":"Support multiple configurations via sdkconfigs","title":"ESP-IDF Adv. - Assign.  1.3","type":"workshops"},{"content":"In this assigment, we will decouple the alarm and temperature code by using the default event loop. In the previous code, we were already indirectly using this event loop for capturing MQTT and Wi-Fi events.\nAssignment steps # We will:\nCreate the events\nTEMP_EVENT_BASE with temp_event_id ALARM_EVENT_BASE with alarm_event_id_t Create the handler functions\nalarm_event_handler temp_event_handler Register the handler functions Create the two timers\nesp_timer_create esp_timer_start_periodic Create the timer callback functions to post the event every 5s and 200ms\ntemp_timer_callback alarm_timer_callback Create a infinite sleep loop in main Create the events # We start by defining the two event bases outisde any function (global)\nESP_EVENT_DEFINE_BASE(TEMP_EVENT_BASE); ESP_EVENT_DEFINE_BASE(ALARM_EVENT_BASE); We define their event_id as an enum. In this case, both comprise just a single value.\ntypedef enum { TEMP_EVENT_MEASURE, } temp_event_id_t; typedef enum { ALARM_EVENT_CHECK, } alarm_event_id_t; Create handler funcions # We create the two event handler functions which do the actual job of posting the data on the MQTT channel. The posting code is the same of the previous assignment.\nstatic void temp_event_handler(void* handler_arg, esp_event_base_t base, int32_t id, void* event_data) { float temp; if (temperature_sensor_read_celsius(sensor, \u0026amp;temp) == ESP_OK) { cloud_manager_send_temperature(cloud, temp); } else { ESP_LOGW(\u0026#34;APP\u0026#34;, \u0026#34;Failed to read temperature\u0026#34;); } } static void alarm_event_handler(void* handler_arg, esp_event_base_t base, int32_t id, void* event_data) { if (is_alarm_set(alarm)) { ESP_LOGI(\u0026#34;APP\u0026#34;, \u0026#34;ALARM ON!!\u0026#34;); cloud_manager_send_alarm(cloud); } } Register the handler functions # In the app_main we can now register the two handler function. We need to specify the event base and id they\u0026rsquo;re connected to:\nESP_ERROR_CHECK(esp_event_handler_register(TEMP_EVENT_BASE, TEMP_EVENT_MEASURE, temp_event_handler, NULL)); ESP_ERROR_CHECK(esp_event_handler_register(ALARM_EVENT_BASE, ALARM_EVENT_CHECK, alarm_event_handler, NULL)); Create the timers # The actual source of event in this assignment are timers, so we need to start two of them.\nTo create and start the temperature and alarm timers, you need to add to your app_main():\n// Create and start periodic timers // Temperature timer const esp_timer_create_args_t temp_timer_args = { .callback = \u0026amp;temp_timer_callback, .name = \u0026#34;temp_timer\u0026#34; }; esp_timer_handle_t temp_timer; ESP_ERROR_CHECK(esp_timer_create(\u0026amp;temp_timer_args, \u0026amp;temp_timer)); ESP_ERROR_CHECK(esp_timer_start_periodic(temp_timer, TEMPERATURE_MEAS_PERIOD_US)); // Alarm timer const esp_timer_create_args_t alarm_timer_args = { .callback = \u0026amp;alarm_timer_callback, .name = \u0026#34;alarm_timer\u0026#34; }; esp_timer_handle_t alarm_timer; ESP_ERROR_CHECK(esp_timer_create(\u0026amp;alarm_timer_args, \u0026amp;alarm_timer)); ESP_ERROR_CHECK(esp_timer_start_periodic(alarm_timer, ALARM_CHECK_PERIOD_US)); The two macros ALARM_CHECK_PERIOD_US and TEMPERATURE_MEAS_PERIOD_US could be added as defines at the beginning of the code or as a module\u0026rsquo;s parameter. For the sake of semplicity, we will define them at the beginning of app_main.c as\n#define TEMPERATURE_MEAS_PERIOD_US (5 * 1000000) #define ALARM_CHECK_PERIOD_US (200 * 1000) Create the timer callback functions # In the previous code, we gave as .callback the functions temp_timer_callback and a alarm_timer_callback. These functions are called when the timer expires.\nIn this assignment, these functions need to just post an event\nstatic void temp_timer_callback(void* arg) { esp_event_post(TEMP_EVENT_BASE, TEMP_EVENT_MEASURE, NULL, 0, 0); } static void alarm_timer_callback(void* arg) { esp_event_post(ALARM_EVENT_BASE, ALARM_EVENT_CHECK, NULL, 0, 0); } The event loop will take care of calling the right function when the event is triggered.\nMain sleep # The last thing to do, is to let the main continue to run while events are triggered. We can do this by adding an infinite loop\nwhile (1) { vTaskDelay(pdMS_TO_TICKS(1000)); } Assignment solution code # Show full assignment code #include \u0026#34;cloud_manager.h\u0026#34; #include \u0026#34;temperature_sensor.h\u0026#34; #include \u0026#34;alarm.h\u0026#34; #include \u0026#34;esp_log.h\u0026#34; #include \u0026#34;esp_event.h\u0026#34; #include \u0026#34;esp_timer.h\u0026#34; #define TEMPERATURE_MEAS_PERIOD_US (5 * 1000000) #define ALARM_CHECK_PERIOD_US (200 * 1000) ESP_EVENT_DEFINE_BASE(TEMP_EVENT_BASE); ESP_EVENT_DEFINE_BASE(ALARM_EVENT_BASE); static bool previous_alarm_set = false; typedef enum { TEMP_EVENT_MEASURE, } temp_event_id_t; typedef enum { ALARM_EVENT_CHECK, } alarm_event_id_t; static temperature_sensor_t *sensor = NULL; static alarm_t *alarm = NULL; static cloud_manager_t *cloud = NULL; static void temp_event_handler(void* handler_arg, esp_event_base_t base, int32_t id, void* event_data) { float temp; if (temperature_sensor_read_celsius(sensor, \u0026amp;temp) == ESP_OK) { cloud_manager_send_temperature(cloud, temp); } else { ESP_LOGW(\u0026#34;APP\u0026#34;, \u0026#34;Failed to read temperature\u0026#34;); } } static void alarm_event_handler(void* handler_arg, esp_event_base_t base, int32_t id, void* event_data) { bool alarm_state = is_alarm_set(alarm); if (alarm_state \u0026amp;\u0026amp; !previous_alarm_set) { printf(\u0026#34;ALARM ON!!\\n\u0026#34;); cloud_manager_send_alarm(cloud); } previous_alarm_set = alarm_state; } static void temp_timer_callback(void* arg) { esp_event_post(TEMP_EVENT_BASE, TEMP_EVENT_MEASURE, NULL, 0, 0); } static void alarm_timer_callback(void* arg) { esp_event_post(ALARM_EVENT_BASE, ALARM_EVENT_CHECK, NULL, 0, 0); } void app_main(void) { ESP_LOGI(\u0026#34;APP\u0026#34;, \u0026#34;Starting...\u0026#34;); ESP_ERROR_CHECK(esp_event_loop_create_default()); sensor = temperature_sensor_create(); alarm = alarm_create(); cloud = cloud_manager_create(); printf(\u0026#34;Connecting...\\n\u0026#34;); ESP_ERROR_CHECK(cloud_manager_connect(cloud)); printf(\u0026#34;Connected!\\n\u0026#34;); // Register event handlers ESP_ERROR_CHECK(esp_event_handler_register(TEMP_EVENT_BASE, TEMP_EVENT_MEASURE, temp_event_handler, NULL)); ESP_ERROR_CHECK(esp_event_handler_register(ALARM_EVENT_BASE, ALARM_EVENT_CHECK, alarm_event_handler, NULL)); // Create and start periodic timers const esp_timer_create_args_t temp_timer_args = { .callback = \u0026amp;temp_timer_callback, .name = \u0026#34;temp_timer\u0026#34; }; esp_timer_handle_t temp_timer; ESP_ERROR_CHECK(esp_timer_create(\u0026amp;temp_timer_args, \u0026amp;temp_timer)); ESP_ERROR_CHECK(esp_timer_start_periodic(temp_timer, TEMPERATURE_MEAS_PERIOD_US)); const esp_timer_create_args_t alarm_timer_args = { .callback = \u0026amp;alarm_timer_callback, .name = \u0026#34;alarm_timer\u0026#34; }; esp_timer_handle_t alarm_timer; ESP_ERROR_CHECK(esp_timer_create(\u0026amp;alarm_timer_args, \u0026amp;alarm_timer)); ESP_ERROR_CHECK(esp_timer_start_periodic(alarm_timer, ALARM_CHECK_PERIOD_US)); // The main task can now just sleep while (1) { vTaskDelay(pdMS_TO_TICKS(1000)); } // Cleanup (unreachable in this example) cloud_manager_disconnect(cloud); cloud_manager_delete(cloud); temperature_sensor_delete(sensor); alarm_delete(alarm); } You can find the whole solution project in the assignment_2_1 folder in the GitHub repo.\nConclusion # Using an event loop decouples the managent of the alarm and temperature sensor. In this specific assignment, we could have reached the same result by using the timers callback function to do the same and avoid all the event loop overhead. But in general, events can come from a variety of sources and event loop offer an unified approach to decouple the application logic.\nIf you still have time, you can check out assignment 2.2, which adds an additional source event triggered by a gpio.\nOtherwise:\nNext step: Lecture 3\n","date":"5 August 2025","externalUrl":null,"permalink":"/workshops/esp-idf-advanced/assignment-2-1/","section":"Workshops","summary":"Event loop: Manage temperature and alarm sensor via events","title":"ESP-IDF Adv. - Assign.  2.1","type":"workshops"},{"content":"In this assignment you\u0026rsquo;ll extend the functionality from Assignment 2.1 by introducing an additional event source: When GPIO9 is pressed, an alarm event is posted to the system.\nAssignment detail # The code for detecting a GPIO press is provided below. You need to integrate the logic into the existing event loop. Use the same ALARM_EVENT_BASE as the alarm trigger used before. Create a ALARM_EVENT_BUTTON to differenciate it from the ALARM_EVENT_CHECK. There is an alternative version for esp_event_post called esp_event_isr_post. Reading GPIO code # #include \u0026#34;driver/gpio.h\u0026#34; #include \u0026#34;esp_attr.h\u0026#34; #include \u0026#34;esp_log.h\u0026#34; #define GPIO_INPUT_IO_9 9 #define ESP_INTR_FLAG_DEFAULT 0 static const char *TAG = \u0026#34;example\u0026#34;; // ISR handler static void gpio_isr_handler(void* arg) { uint32_t gpio_num = (uint32_t) arg; ESP_EARLY_LOGI(TAG, \u0026#34;GPIO[%d] interrupt triggered\u0026#34;, gpio_num); } void app_main(void) { gpio_config_t io_conf = { .intr_type = GPIO_INTR_NEGEDGE, // Falling edge interrupt .mode = GPIO_MODE_INPUT, // Set as input mode .pin_bit_mask = (1ULL \u0026lt;\u0026lt; GPIO_INPUT_IO_9), .pull_up_en = GPIO_PULLUP_ENABLE, // Enable pull-up .pull_down_en = GPIO_PULLDOWN_DISABLE, }; gpio_config(\u0026amp;io_conf); // Install GPIO ISR service gpio_install_isr_service(ESP_INTR_FLAG_DEFAULT); // Hook ISR handler for specific GPIO pin gpio_isr_handler_add(GPIO_INPUT_IO_9, gpio_isr_handler, (void*) GPIO_INPUT_IO_9); ESP_LOGI(TAG, \u0026#34;GPIO 9 configured as input with falling edge interrupt\u0026#34;); } Assignment solution code # Show full assignment code #include \u0026#34;cloud_manager.h\u0026#34; #include \u0026#34;temperature_sensor.h\u0026#34; #include \u0026#34;alarm.h\u0026#34; #include \u0026#34;esp_log.h\u0026#34; #include \u0026#34;esp_event.h\u0026#34; #include \u0026#34;esp_timer.h\u0026#34; #include \u0026#34;driver/gpio.h\u0026#34; #include \u0026#34;esp_attr.h\u0026#34; #define TEMPERATURE_MEAS_PERIOD_US (5 * 1000000) #define ALARM_CHECK_PERIOD_US (200 * 1000) #define GPIO_INPUT_IO_9 9 #define ESP_INTR_FLAG_DEFAULT 0 static const char *TAG = \u0026#34;assignment2_2\u0026#34;; // EVENTS ESP_EVENT_DEFINE_BASE(TEMP_EVENT_BASE); ESP_EVENT_DEFINE_BASE(ALARM_EVENT_BASE); static bool previous_alarm_set = false; typedef enum { TEMP_EVENT_MEASURE, } temp_event_id_t; typedef enum { ALARM_EVENT_CHECK, ALARM_EVENT_BUTTON } alarm_event_id_t; // GPIO // ISR handler static void gpio_isr_handler(void* arg) { uint32_t gpio_num = (uint32_t) arg; // Now that we post the event, we remove the log: // It is not recommended to log or print inside an ISR // // ESP_EARLY_LOGI(TAG, \u0026#34;GPIO[%d] interrupt triggered\u0026#34;, gpio_num); esp_event_isr_post(ALARM_EVENT_BASE, ALARM_EVENT_BUTTON, NULL, 0, 0); } static temperature_sensor_t *sensor = NULL; static alarm_t *alarm = NULL; static cloud_manager_t *cloud = NULL; static void temp_event_handler(void* handler_arg, esp_event_base_t base, int32_t id, void* event_data) { float temp; if (temperature_sensor_read_celsius(sensor, \u0026amp;temp) == ESP_OK) { cloud_manager_send_temperature(cloud, temp); } else { ESP_LOGW(\u0026#34;APP\u0026#34;, \u0026#34;Failed to read temperature\u0026#34;); } } static void alarm_event_button_handler(void* handler_arg, esp_event_base_t base, int32_t id, void* event_data) { ESP_LOGI(\u0026#34;APP\u0026#34;, \u0026#34;ALARM ON!!\u0026#34;); cloud_manager_send_alarm(cloud); } static void alarm_event_handler(void* handler_arg, esp_event_base_t base, int32_t id, void* event_data) { bool alarm_state = is_alarm_set(alarm); if (alarm_state \u0026amp;\u0026amp; !previous_alarm_set) { ESP_LOGI(\u0026#34;APP\u0026#34;, \u0026#34;ALARM ON!!\u0026#34;); cloud_manager_send_alarm(cloud); } previous_alarm_set = alarm_state; } static void temp_timer_callback(void* arg) { esp_event_post(TEMP_EVENT_BASE, TEMP_EVENT_MEASURE, NULL, 0, 0); } static void alarm_timer_callback(void* arg) { esp_event_post(ALARM_EVENT_BASE, ALARM_EVENT_CHECK, NULL, 0, 0); } void app_main(void) { ESP_LOGI(\u0026#34;APP\u0026#34;, \u0026#34;Starting...\u0026#34;); ESP_ERROR_CHECK(esp_event_loop_create_default()); sensor = temperature_sensor_create(); alarm = alarm_create(); cloud = cloud_manager_create(); ESP_LOGI(\u0026#34;APP\u0026#34;, \u0026#34;Connecting...\u0026#34;); ESP_ERROR_CHECK(cloud_manager_connect(cloud)); ESP_LOGI(\u0026#34;APP\u0026#34;, \u0026#34;Connected!\u0026#34;); // Register event handlers ESP_ERROR_CHECK(esp_event_handler_register(TEMP_EVENT_BASE, TEMP_EVENT_MEASURE, temp_event_handler, NULL)); ESP_ERROR_CHECK(esp_event_handler_register(ALARM_EVENT_BASE, ALARM_EVENT_CHECK, alarm_event_handler, NULL)); ESP_ERROR_CHECK(esp_event_handler_register(ALARM_EVENT_BASE, ALARM_EVENT_BUTTON, alarm_event_button_handler, NULL)); // Create and start periodic timers const esp_timer_create_args_t temp_timer_args = { .callback = \u0026amp;temp_timer_callback, .name = \u0026#34;temp_timer\u0026#34; }; esp_timer_handle_t temp_timer; ESP_ERROR_CHECK(esp_timer_create(\u0026amp;temp_timer_args, \u0026amp;temp_timer)); ESP_ERROR_CHECK(esp_timer_start_periodic(temp_timer, TEMPERATURE_MEAS_PERIOD_US)); const esp_timer_create_args_t alarm_timer_args = { .callback = \u0026amp;alarm_timer_callback, .name = \u0026#34;alarm_timer\u0026#34; }; esp_timer_handle_t alarm_timer; ESP_ERROR_CHECK(esp_timer_create(\u0026amp;alarm_timer_args, \u0026amp;alarm_timer)); // GPIO gpio_config_t io_conf = { .intr_type = GPIO_INTR_NEGEDGE, // Falling edge interrupt .mode = GPIO_MODE_INPUT, // Set as input mode .pin_bit_mask = (1ULL \u0026lt;\u0026lt; GPIO_INPUT_IO_9), .pull_up_en = GPIO_PULLUP_ENABLE, // Enable pull-up .pull_down_en = GPIO_PULLDOWN_DISABLE, }; gpio_config(\u0026amp;io_conf); // Install GPIO ISR service gpio_install_isr_service(ESP_INTR_FLAG_DEFAULT); // Hook ISR handler for specific GPIO pin gpio_isr_handler_add(GPIO_INPUT_IO_9, gpio_isr_handler, (void*) GPIO_INPUT_IO_9); // The main task can now just sleep while (1) { vTaskDelay(pdMS_TO_TICKS(1000)); } // Cleanup (unreachable in this example) cloud_manager_disconnect(cloud); cloud_manager_delete(cloud); temperature_sensor_delete(sensor); alarm_delete(alarm); } You can find the whole solution project on the assignment_2_2 folder on the github repo.\nNext step: Lecture 3\n","date":"5 August 2025","externalUrl":null,"permalink":"/workshops/esp-idf-advanced/assignment-2-2/","section":"Workshops","summary":"Event loop: add an external GPIO event","title":"ESP-IDF Adv. - Assign.  2.2","type":"workshops"},{"content":"In this assignment, you will analyze the binary image size and optimize the memory footprint of your application.\nAssignment steps # We will:\nBuild the original project to spot any oversized or suspicious sections (e.g., .text, .data, .rodata) that may hide unoptimized code. Change configuration to reduce it. Rebuild the project to check the improvement. Build the original project # \u0026gt; ESP-IDF: Full Clean Project \u0026gt; ESP-IDF: Build Your Project You will get the summary table of Fig.1 for the binary image.\nFig.1 - Size calculation\nRemoving the logs # Remove the logging output in the menuconfig\nif you don\u0026rsquo;t remember how to do that, check assignment 1.3 \u0026gt; ESP-IDF: Build Your Project Fig.2 - Size calculation after removing logging\nThe binary size is 77kb less than before.\nCertificate Bundle # Open menuconfig: \u0026gt; ESP-IDF: SDK Configuration Editor (menuconfig) Uncheck Certificate Bundle → Enable trusted root certificate bundle \u0026gt; ESP-IDF: Build Your Project Fig.3 - Size calculation after removing certificate bundle\nMQTT unused options # Open menuconfig: \u0026gt; ESP-IDF: SDK Configuration Editor (menuconfig) Uncheck ESP-MQTT Configurations → Enable MQTT over SSL Uncheck ESP-MQTT Configurations → Enable MQTT over Websocket \u0026gt; ESP-IDF: Build Your Project Fig.4 - Size calculation after removing mqtt ssl and websocket support\nWe gained another 6.7kb.\nConclusion # In this assignment, we saw how to check the size of our binary and how to use the menuconfig to removed unused options to improve the memory footprint of our application.\nNext step: assignment 3.2\n","date":"5 August 2025","externalUrl":null,"permalink":"/workshops/esp-idf-advanced/assignment-3-1/","section":"Workshops","summary":"Reduce binary size by working on configuration.","title":"ESP-IDF Adv. - Assign.  3.1","type":"workshops"},{"content":" Core dump # For this assignment, you need to get the assignment_3_2_base project.\nAssignment steps # We will:\nEnable the core dump in the menuconfig Build and run the application Analyze the core dump Fix the bugs in the project Build and run the application again Enable the core dump # Enable the core dump\nOpen menuconfig: \u0026gt; ESP-IDF: SDK Configuration Editor (menuconfig) Set Core Dump → Data destination → Flash \u0026gt; ESP-IDF: Build, Flash and Start a Monitor on Your Device Build an run the application # Now wait the core fault to happen.\nWhen it happens, halt the execution (CTRL + ]) Create a new terminal \u0026gt; ESP-IDF: Open ESP-IDF Terminal run idf.py coredump-info \u0026gt; coredump.txt Open the file coredump.txt Analyze the core dump # Now look closely to the core dump file.\nClick here if you couldn't generate coredump.txt Executing action: coredump-info Serial port /dev/cu.usbmodem1131101 Connecting... Detecting chip type... ESP32-C3 =============================================================== ==================== ESP32 CORE DUMP START ==================== Crashed task handle: 0x3fc9ff18, name: \u0026#39;sys_evt\u0026#39;, GDB name: \u0026#39;process 1070202648\u0026#39; Crashed task is not in the interrupt context ================== CURRENT THREAD REGISTERS =================== ra 0x4200d822\t0x4200d822 \u0026lt;is_alarm_set+20\u0026gt; sp 0x3fc9fe50\t0x3fc9fe50 gp 0x3fc94600\t0x3fc94600 \u0026lt;country_info_24ghz+200\u0026gt; tp 0x3fc9ff10\t0x3fc9ff10 t0 0x4005890e\t1074104590 t1 0x90000000\t-1879048192 t2 0xffffffff\t-1 fp 0x0\t0x0 s1 0x8b7f7a\t9142138 a0 0x8b7f7a\t9142138 a1 0x0\t0 a2 0x8b7f7a0\t146274208 a3 0x0\t0 a4 0x4ddf\t19935 a5 0x4c4b3f\t4999999 a6 0x60023000\t1610756096 a7 0xa\t10 s2 0x0\t0 s3 0x0\t0 s4 0xffffffff\t-1 s5 0x0\t0 s6 0xffffffff\t-1 s7 0x0\t0 s8 0x0\t0 s9 0x0\t0 s10 0x0\t0 s11 0x0\t0 t3 0x0\t0 t4 0xfe42\t65090 t5 0x0\t0 t6 0x0\t0 pc 0x4200d840\t0x4200d840 \u0026lt;is_alarm_set+50\u0026gt; ==================== CURRENT THREAD STACK ===================== #0 is_alarm_set (alarm=0x0) at /Users/francesco/Documents/articles/devrel-advanced-workshop-code/assignment_3_2/components/alarm/alarm.c:40 #1 0x4200d48c in alarm_event_handler (handler_arg=\u0026lt;optimized out\u0026gt;, base=\u0026lt;optimized out\u0026gt;, id=\u0026lt;optimized out\u0026gt;, event_data=\u0026lt;optimized out\u0026gt;) at /Users/francesco/Documents/articles/devrel-advanced-workshop-code/assignment_3_2/main/app_main.c:66 #2 0x420b1944 in handler_execute (loop=loop@entry=0x3fc9f13c, handler=\u0026lt;optimized out\u0026gt;, post=\u0026lt;error reading variable: Cannot access memory at address 0x4c4b3f\u0026gt;) at /Users/francesco/esp/v5.4.2/esp-idf/components/esp_event/esp_event.c:136 #3 0x420b2290 in esp_event_loop_run (event_loop=event_loop@entry=0x3fc9f13c, ticks_to_run=ticks_to_run@entry=4294967295) at /Users/francesco/esp/v5.4.2/esp-idf/components/esp_event/esp_event.c:696 #4 0x420b2388 in esp_event_loop_run_task (args=0x3fc9f13c, args@entry=\u0026lt;error reading variable: value has been optimized out\u0026gt;) at /Users/francesco/esp/v5.4.2/esp-idf/components/esp_event/esp_event.c:106 #5 0x403877cc in vPortTaskWrapper (pxCode=\u0026lt;optimized out\u0026gt;, pvParameters=\u0026lt;optimized out\u0026gt;) at /Users/francesco/esp/v5.4.2/esp-idf/components/freertos/FreeRTOS-Kernel/portable/riscv/port.c:255 ======================== THREADS INFO ========================= Id Target Id Frame * 1 process 1070202648 is_alarm_set (alarm=0x0) at /Users/francesco/Documents/articles/devrel-advanced-workshop-code/assignment_3_2/components/alarm/alarm.c:40 2 process 1070198548 0x403851d4 in esp_cpu_wait_for_intr () at /Users/francesco/esp/v5.4.2/esp-idf/components/esp_hw_support/cpu.c:64 3 process 1070209148 0x4038345e in esp_crosscore_int_send_yield (core_id=core_id@entry=0) at /Users/francesco/esp/v5.4.2/esp-idf/components/esp_system/crosscore_int.c:121 4 process 1070196668 0x4038345e in esp_crosscore_int_send_yield (core_id=core_id@entry=0) at /Users/francesco/esp/v5.4.2/esp-idf/components/esp_system/crosscore_int.c:121 5 process 1070253776 0x4038345e in esp_crosscore_int_send_yield (core_id=core_id@entry=0) at /Users/francesco/esp/v5.4.2/esp-idf/components/esp_system/crosscore_int.c:121 6 process 1070222780 0x4038345e in esp_crosscore_int_send_yield (core_id=core_id@entry=0) at /Users/francesco/esp/v5.4.2/esp-idf/components/esp_system/crosscore_int.c:121 7 process 1070191796 0x40387998 in vPortClearInterruptMaskFromISR (prev_int_level=1) at /Users/francesco/esp/v5.4.2/esp-idf/components/freertos/FreeRTOS-Kernel/portable/riscv/port.c:515 TCB NAME PRIO C/B STACK USED/FREE ---------- ---------------- -------- ---------------- 0x3fc9ff18 sys_evt 20/20 352/2460 0x3fc9ef14 IDLE 0/0 208/1312 0x3fca187c tiT 18/18 336/3240 0x3fc9e7bc main 1/1 336/3752 0x3fcac6d0 mqtt_task 5/5 768/5372 0x3fca4dbc wifi 23/23 336/6312 0x3fc9d4b4 esp_timer 22/22 224/3856 ==================== THREAD 1 (TCB: 0x3fc9ff18, name: \u0026#39;sys_evt\u0026#39;) ===================== #0 is_alarm_set (alarm=0x0) at /Users/francesco/Documents/articles/devrel-advanced-workshop-code/assignment_3_2/components/alarm/alarm.c:40 #1 0x4200d48c in alarm_event_handler (handler_arg=\u0026lt;optimized out\u0026gt;, base=\u0026lt;optimized out\u0026gt;, id=\u0026lt;optimized out\u0026gt;, event_data=\u0026lt;optimized out\u0026gt;) at /Users/francesco/Documents/articles/devrel-advanced-workshop-code/assignment_3_2/main/app_main.c:66 #2 0x420b1944 in handler_execute (loop=loop@entry=0x3fc9f13c, handler=\u0026lt;optimized out\u0026gt;, post=\u0026lt;error reading variable: Cannot access memory at address 0x4c4b3f\u0026gt;) at /Users/francesco/esp/v5.4.2/esp-idf/components/esp_event/esp_event.c:136 #3 0x420b2290 in esp_event_loop_run (event_loop=event_loop@entry=0x3fc9f13c, ticks_to_run=ticks_to_run@entry=4294967295) at /Users/francesco/esp/v5.4.2/esp-idf/components/esp_event/esp_event.c:696 #4 0x420b2388 in esp_event_loop_run_task (args=0x3fc9f13c, args@entry=\u0026lt;error reading variable: value has been optimized out\u0026gt;) at /Users/francesco/esp/v5.4.2/esp-idf/components/esp_event/esp_event.c:106 #5 0x403877cc in vPortTaskWrapper (pxCode=\u0026lt;optimized out\u0026gt;, pvParameters=\u0026lt;optimized out\u0026gt;) at /Users/francesco/esp/v5.4.2/esp-idf/components/freertos/FreeRTOS-Kernel/portable/riscv/port.c:255 ==================== THREAD 2 (TCB: 0x3fc9ef14, name: \u0026#39;IDLE\u0026#39;) ===================== #0 0x403851d4 in esp_cpu_wait_for_intr () at /Users/francesco/esp/v5.4.2/esp-idf/components/esp_hw_support/cpu.c:64 #1 0x42015ce8 in esp_vApplicationIdleHook () at /Users/francesco/esp/v5.4.2/esp-idf/components/esp_system/freertos_hooks.c:58 #2 0x4038859c in prvIdleTask (pvParameters=\u0026lt;error reading variable: value has been optimized out\u0026gt;) at /Users/francesco/esp/v5.4.2/esp-idf/components/freertos/FreeRTOS-Kernel/tasks.c:4341 #3 0x403877cc in vPortTaskWrapper (pxCode=\u0026lt;optimized out\u0026gt;, pvParameters=\u0026lt;optimized out\u0026gt;) at /Users/francesco/esp/v5.4.2/esp-idf/components/freertos/FreeRTOS-Kernel/portable/riscv/port.c:255 ==================== THREAD 3 (TCB: 0x3fca187c, name: \u0026#39;tiT\u0026#39;) ===================== #0 0x4038345e in esp_crosscore_int_send_yield (core_id=core_id@entry=0) at /Users/francesco/esp/v5.4.2/esp-idf/components/esp_system/crosscore_int.c:121 #1 0x40387a5c in vPortYield () at /Users/francesco/esp/v5.4.2/esp-idf/components/freertos/FreeRTOS-Kernel/portable/riscv/port.c:638 #2 0x40387450 in xQueueReceive (xQueue=0x3fca099c, pvBuffer=pvBuffer@entry=0x3fca182c, xTicksToWait=\u0026lt;optimized out\u0026gt;, xTicksToWait@entry=6) at /Users/francesco/esp/v5.4.2/esp-idf/components/freertos/FreeRTOS-Kernel/queue.c:1659 #3 0x42086ae8 in sys_arch_mbox_fetch (mbox=mbox@entry=0x3fc9b7c0 \u0026lt;tcpip_mbox\u0026gt;, msg=msg@entry=0x3fca182c, timeout=60) at /Users/francesco/esp/v5.4.2/esp-idf/components/lwip/port/freertos/sys_arch.c:313 #4 0x420710ea in tcpip_timeouts_mbox_fetch (mbox=mbox@entry=0x3fc9b7c0 \u0026lt;tcpip_mbox\u0026gt;, msg=msg@entry=0x3fca182c) at /Users/francesco/esp/v5.4.2/esp-idf/components/lwip/lwip/src/api/tcpip.c:104 #5 0x420711dc in tcpip_thread (arg=\u0026lt;error reading variable: value has been optimized out\u0026gt;) at /Users/francesco/esp/v5.4.2/esp-idf/components/lwip/lwip/src/api/tcpip.c:142 #6 0x403877cc in vPortTaskWrapper (pxCode=\u0026lt;optimized out\u0026gt;, pvParameters=\u0026lt;optimized out\u0026gt;) at /Users/francesco/esp/v5.4.2/esp-idf/components/freertos/FreeRTOS-Kernel/portable/riscv/port.c:255 ==================== THREAD 4 (TCB: 0x3fc9e7bc, name: \u0026#39;main\u0026#39;) ===================== #0 0x4038345e in esp_crosscore_int_send_yield (core_id=core_id@entry=0) at /Users/francesco/esp/v5.4.2/esp-idf/components/esp_system/crosscore_int.c:121 #1 0x40387a5c in vPortYield () at /Users/francesco/esp/v5.4.2/esp-idf/components/freertos/FreeRTOS-Kernel/portable/riscv/port.c:638 #2 0x40388d04 in vTaskDelay (xTicksToDelay=xTicksToDelay@entry=100) at /Users/francesco/esp/v5.4.2/esp-idf/components/freertos/FreeRTOS-Kernel/tasks.c:1588 #3 0x4200d7e8 in app_main () at /Users/francesco/Documents/articles/devrel-advanced-workshop-code/assignment_3_2/main/app_main.c:136 #4 0x420b420e in main_task (args=\u0026lt;error reading variable: value has been optimized out\u0026gt;) at /Users/francesco/esp/v5.4.2/esp-idf/components/freertos/app_startup.c:208 #5 0x403877cc in vPortTaskWrapper (pxCode=\u0026lt;optimized out\u0026gt;, pvParameters=\u0026lt;optimized out\u0026gt;) at /Users/francesco/esp/v5.4.2/esp-idf/components/freertos/FreeRTOS-Kernel/portable/riscv/port.c:255 ==================== THREAD 5 (TCB: 0x3fcac6d0, name: \u0026#39;mqtt_task\u0026#39;) ===================== #0 0x4038345e in esp_crosscore_int_send_yield (core_id=core_id@entry=0) at /Users/francesco/esp/v5.4.2/esp-idf/components/esp_system/crosscore_int.c:121 #1 0x40387a5c in vPortYield () at /Users/francesco/esp/v5.4.2/esp-idf/components/freertos/FreeRTOS-Kernel/portable/riscv/port.c:638 #2 0x403875bc in xQueueSemaphoreTake (xQueue=0x3fcac8e0, xTicksToWait=\u0026lt;optimized out\u0026gt;, xTicksToWait@entry=4294967295) at /Users/francesco/esp/v5.4.2/esp-idf/components/freertos/FreeRTOS-Kernel/queue.c:1901 #3 0x42086910 in sys_arch_sem_wait (sem=sem@entry=0x3fcac8d0, timeout=timeout@entry=0) at /Users/francesco/esp/v5.4.2/esp-idf/components/lwip/port/freertos/sys_arch.c:165 #4 0x420713d4 in tcpip_send_msg_wait_sem (fn=\u0026lt;optimized out\u0026gt;, apimsg=apimsg@entry=0x3fcae33c, sem=0x3fcac8d0) at /Users/francesco/esp/v5.4.2/esp-idf/components/lwip/lwip/src/api/tcpip.c:461 #5 0x42088840 in netconn_gethostbyname_addrtype (name=name@entry=0x3fcac8b8 \u0026lt;error: Cannot access memory at address 0x3fcac8b8\u0026gt;, addr=addr@entry=0x3fcae3a8, dns_addrtype=\u0026lt;optimized out\u0026gt;) at /Users/francesco/esp/v5.4.2/esp-idf/components/lwip/lwip/src/api/api_lib.c:1333 #6 0x4206de2a in lwip_getaddrinfo (nodename=nodename@entry=0x3fcac8b8 \u0026lt;error: Cannot access memory at address 0x3fcac8b8\u0026gt;, servname=servname@entry=0x0, hints=hints@entry=0x3fcae3fc, res=res@entry=0x3fcae41c) at /Users/francesco/esp/v5.4.2/esp-idf/components/lwip/lwip/src/api/netdb.c:495 #7 0x42021468 in getaddrinfo (nodename=0x3fcac8b8 \u0026lt;error: Cannot access memory at address 0x3fcac8b8\u0026gt;, servname=0x0, hints=0x3fcae3fc, res=0x3fcae41c) at /Users/francesco/esp/v5.4.2/esp-idf/components/lwip/include/lwip/netdb.h:23 #8 esp_tls_hostname_to_fd (host=\u0026lt;optimized out\u0026gt;, hostlen=\u0026lt;optimized out\u0026gt;, port=1883, addr_family=\u0026lt;optimized out\u0026gt;, address=address@entry=0x3fcae464, fd=fd@entry=0x3fcae460) at /Users/francesco/esp/v5.4.2/esp-idf/components/esp-tls/esp_tls.c:210 #9 0x420218c4 in tcp_connect (host=host@entry=0x3fca24cc \u0026lt;error: Cannot access memory at address 0x3fca24cc\u0026gt;, hostlen=\u0026lt;optimized out\u0026gt;, port=port@entry=1883, cfg=cfg@entry=0x3fcac83c, error_handle=error_handle@entry=0x3fcac824, sockfd=sockfd@entry=0x3fcac8a0) at /Users/francesco/esp/v5.4.2/esp-idf/components/esp-tls/esp_tls.c:359 #10 0x42021ebc in esp_tls_plain_tcp_connect (host=host@entry=0x3fca24cc \u0026lt;error: Cannot access memory at address 0x3fca24cc\u0026gt;, hostlen=\u0026lt;optimized out\u0026gt;, port=port@entry=1883, cfg=cfg@entry=0x3fcac83c, error_handle=error_handle@entry=0x3fcac824, sockfd=sockfd@entry=0x3fcac8a0) at /Users/francesco/esp/v5.4.2/esp-idf/components/esp-tls/esp_tls.c:533 #11 0x42023e06 in tcp_connect (t=\u0026lt;optimized out\u0026gt;, host=0x3fca24cc \u0026lt;error: Cannot access memory at address 0x3fca24cc\u0026gt;, port=1883, timeout_ms=10000) at /Users/francesco/esp/v5.4.2/esp-idf/components/tcp_transport/transport_ssl.c:148 #12 0x42023210 in esp_transport_connect (t=\u0026lt;optimized out\u0026gt;, host=\u0026lt;optimized out\u0026gt;, port=\u0026lt;optimized out\u0026gt;, timeout_ms=\u0026lt;optimized out\u0026gt;) at /Users/francesco/esp/v5.4.2/esp-idf/components/tcp_transport/transport.c:123 #13 0x4200f628 in esp_mqtt_task (pv=0x3fca1a28, pv@entry=\u0026lt;error reading variable: value has been optimized out\u0026gt;) at /Users/francesco/esp/v5.4.2/esp-idf/components/mqtt/esp-mqtt/mqtt_client.c:1620 #14 0x403877cc in vPortTaskWrapper (pxCode=\u0026lt;optimized out\u0026gt;, pvParameters=\u0026lt;optimized out\u0026gt;) at /Users/francesco/esp/v5.4.2/esp-idf/components/freertos/FreeRTOS-Kernel/portable/riscv/port.c:255 ==================== THREAD 6 (TCB: 0x3fca4dbc, name: \u0026#39;wifi\u0026#39;) ===================== #0 0x4038345e in esp_crosscore_int_send_yield (core_id=core_id@entry=0) at /Users/francesco/esp/v5.4.2/esp-idf/components/esp_system/crosscore_int.c:121 #1 0x40387a5c in vPortYield () at /Users/francesco/esp/v5.4.2/esp-idf/components/freertos/FreeRTOS-Kernel/portable/riscv/port.c:638 #2 0x40387450 in xQueueReceive (xQueue=0x3fca2c9c, pvBuffer=0x3fca4d48, xTicksToWait=\u0026lt;optimized out\u0026gt;, xTicksToWait@entry=4294967295) at /Users/francesco/esp/v5.4.2/esp-idf/components/freertos/FreeRTOS-Kernel/queue.c:1659 #3 0x420b3d64 in queue_recv_wrapper (queue=\u0026lt;optimized out\u0026gt;, item=\u0026lt;optimized out\u0026gt;, block_time_tick=\u0026lt;optimized out\u0026gt;) at /Users/francesco/esp/v5.4.2/esp-idf/components/esp_wifi/esp32c3/esp_adapter.c:238 #4 0x400407be in ppTask () #5 0x403877cc in vPortTaskWrapper (pxCode=\u0026lt;optimized out\u0026gt;, pvParameters=\u0026lt;optimized out\u0026gt;) at /Users/francesco/esp/v5.4.2/esp-idf/components/freertos/FreeRTOS-Kernel/portable/riscv/port.c:255 ==================== THREAD 7 (TCB: 0x3fc9d4b4, name: \u0026#39;esp_timer\u0026#39;) ===================== #0 0x40387998 in vPortClearInterruptMaskFromISR (prev_int_level=1) at /Users/francesco/esp/v5.4.2/esp-idf/components/freertos/FreeRTOS-Kernel/portable/riscv/port.c:515 #1 0x40387a28 in vPortExitCritical () at /Users/francesco/esp/v5.4.2/esp-idf/components/freertos/FreeRTOS-Kernel/portable/riscv/port.c:624 #2 0x40389774 in ulTaskGenericNotifyTake (uxIndexToWait=uxIndexToWait@entry=0, xClearCountOnExit=xClearCountOnExit@entry=1, xTicksToWait=xTicksToWait@entry=4294967295) at /Users/francesco/esp/v5.4.2/esp-idf/components/freertos/FreeRTOS-Kernel/tasks.c:5759 #3 0x42017e9a in timer_task (arg=\u0026lt;error reading variable: value has been optimized out\u0026gt;) at /Users/francesco/esp/v5.4.2/esp-idf/components/esp_timer/src/esp_timer.c:459 #4 0x403877cc in vPortTaskWrapper (pxCode=\u0026lt;optimized out\u0026gt;, pvParameters=\u0026lt;optimized out\u0026gt;) at /Users/francesco/esp/v5.4.2/esp-idf/components/freertos/FreeRTOS-Kernel/portable/riscv/port.c:255 ======================= ALL MEMORY REGIONS ======================== Name Address Size Attrs .rtc.text 0x50000000 0x0 RW .rtc.force_fast 0x50000000 0x1c RW A .rtc_noinit 0x5000001c 0x0 RW .rtc.force_slow 0x5000001c 0x0 RW .iram0.text 0x40380000 0x13d0a R XA .dram0.data 0x3fc93e00 0x2ed8 RW A .flash.text 0x42000020 0xb4fd8 R XA .flash.appdesc 0x3c0c0020 0x100 R A .flash.rodata 0x3c0c0120 0x1ff3c RW A .eh_frame_hdr 0x3c0e005c 0x0 RW .eh_frame 0x3c0e005c 0x0 RW .flash.tdata 0x3c0e005c 0x0 RW .iram0.data 0x40393e00 0x0 RW .iram0.bss 0x40393e00 0x0 RW .dram0.heap_start 0x3fc9b8e0 0x0 RW .coredump.tasks.data 0x3fc9ff18 0x150 RW .coredump.tasks.data 0x3fc9fdb0 0x160 RW .coredump.tasks.data 0x3fc9ef14 0x150 RW .coredump.tasks.data 0x3fc9ee30 0xd0 RW .coredump.tasks.data 0x3fca187c 0x150 RW .coredump.tasks.data 0x3fca1720 0x150 RW .coredump.tasks.data 0x3fc9e7bc 0x150 RW .coredump.tasks.data 0x3fc9e660 0x150 RW .coredump.tasks.data 0x3fcac6d0 0x150 RW .coredump.tasks.data 0x3fcae240 0x300 RW .coredump.tasks.data 0x3fca4dbc 0x150 RW .coredump.tasks.data 0x3fca4c60 0x150 RW .coredump.tasks.data 0x3fc9d4b4 0x150 RW .coredump.tasks.data 0x3fc9d3c0 0xe0 RW ===================== ESP32 CORE DUMP END ===================== =============================================================== Done! Identify the crashed task and context # The core dump starts with:\nCrashed task handle: 0x3fc9ff18, name: \u0026#39;sys_evt\u0026#39; Crashed task is not in the interrupt context From which, we can conclude the following:\nThe crash happened in the FreeRTOS task called sys_evt. The crash did not happen during an interrupt, so it\u0026rsquo;s a normal task context crash. Look at the program counter (PC) and stack trace # The register dump shows:\npc 0x4200d840\t0x4200d840 \u0026lt;is_alarm_set+50\u0026gt; ra 0x4200d822\t0x4200d822 \u0026lt;is_alarm_set+20\u0026gt; sp 0x3fc9fe50 It means that:\nThe program counter (PC) is at address 0x4200d840, inside the function is_alarm_set, specifically at offset +50 bytes. The return address (ra) is also inside is_alarm_set, which means the crash happened inside that function. Examine the stack trace # Stack trace (reversed call order):\n#0 is_alarm_set (alarm=0x0) at alarm.c:40 #1 alarm_event_handler at app_main.c:66 #2 handler_execute (esp_event.c:136) #3 esp_event_loop_run (esp_event.c:696) #4 esp_event_loop_run_task (esp_event.c:106) #5 vPortTaskWrapper (port.c:255) The crash originated from is_alarm_set being called from alarm_event_handler. This handler is called by the ESP-IDF event loop (esp_event_loop_run). Focus on function arguments # Look at is_alarm_set arguments:\n#0 is_alarm_set (alarm=0x0) at alarm.c:40 The argument alarm is 0x0 (NULL pointer) (!) Diagnose the crash reason # The crash happened inside is_alarm_set with a NULL pointer argument. Usually, this means:\nis_alarm_set dereferenced alarm without checking if it was NULL. Since alarm is NULL, accessing its fields caused an invalid memory access, crashing the program. Check the source # The crash line is alarm.c:40. If you look at that line in your source:\nreturn alarm-\u0026gt;last_state; Dereferencing alarm without NULL check causes a fault if alarm == NULL. If we look a couple of lines above, we spot\nalarm = NULL; which is likely our bug.\nBuild and run the application again # Remove the line and the useless else block, to get the following is_alarm_set function.\nbool is_alarm_set(alarm_t *alarm) { int64_t now_us = esp_timer_get_time(); int64_t elapsed_us = now_us - alarm-\u0026gt;last_check_time_us; if (elapsed_us \u0026gt;= CONFIG_ALARM_REFRESH_INTERVAL_MS * 1000) { uint32_t rand_val = esp_random() % 100; alarm-\u0026gt;last_state = rand_val \u0026lt; CONFIG_ALARM_THRESHOLD_PERCENT; alarm-\u0026gt;last_check_time_us = now_us; } return alarm-\u0026gt;last_state; } Rebuild and run the application\n\u0026gt; ESP-IDF: Build, Flash and Start a Monitor Another crash!\nIf you still have time, try to solve it by moving to assignment 3.3.\nIf you don\u0026rsquo;t, don\u0026rsquo;t worry: all the following assignments will be based on the assignment 2.1 code.\nConclusion # In this assignment, we learnt how to create a core dump and how to analyze it to understand the reason of a core crash. Core dump analysis is a very strong tool to debug your application.\nIf you still have time, try assignment 3.3\nOtherwise\nNext step: Lecture 4\n","date":"5 August 2025","externalUrl":null,"permalink":"/workshops/esp-idf-advanced/assignment-3-2/","section":"Workshops","summary":"Explore core dump \u0026ndash; guided","title":"ESP-IDF Adv. - Assign.  3.2","type":"workshops"},{"content":"If you still have time, try to find the other bug in the code by using the info provided by the core dump again.\nSolution steps outline # Create the core dump file as you did in the previous assignment.\nWait for the crash to happen Stop monitor (CTRL + ]) Run idf.py coredump-info \u0026gt; coredump.txt Open the file coredump.txt Expand the second core dump Executing action: coredump-info Serial port /dev/cu.usbmodem1131101 Connecting... Detecting chip type... ESP32-C3 =============================================================== ==================== ESP32 CORE DUMP START ==================== Crashed task handle: 0x3fc9ff18, name: \u0026#39;sys_evt\u0026#39;, GDB name: \u0026#39;process 1070202648\u0026#39; Crashed task is not in the interrupt context ================== CURRENT THREAD REGISTERS =================== ra 0x4200dc68\t0x4200dc68 \u0026lt;temperature_sensor_read_celsius+10\u0026gt; sp 0x3fc9fe40\t0x3fc9fe40 gp 0x3fc94600\t0x3fc94600 \u0026lt;country_info_24ghz+200\u0026gt; tp 0x3fc9ff10\t0x3fc9ff10 t0 0x4005890e\t1074104590 t1 0x0\t0 t2 0xffffffff\t-1 fp 0x0\t0x0 s1 0x3fc9f13c\t1070199100 a0 0x3fcacc14\t1070255124 a1 0x3fc9fe5c\t1070202460 a2 0x0\t0 a3 0x0\t0 a4 0x3fcacb34\t1070254900 a5 0x0\t0 a6 0x4200d4c2\t1107350722 a7 0x9800000\t159383552 s2 0x0\t0 s3 0x0\t0 s4 0xffffffff\t-1 s5 0x0\t0 s6 0xffffffff\t-1 s7 0x3fcacb44\t1070254916 s8 0x0\t0 s9 0x0\t0 s10 0x0\t0 s11 0x0\t0 t3 0x0\t0 t4 0x604f\t24655 t5 0x0\t0 t6 0x0\t0 pc 0x0\t0x0 ==================== CURRENT THREAD STACK ===================== #0 0x00000000 in ?? () #1 0x4200dc68 in temperature_sensor_read_celsius (sensor=\u0026lt;optimized out\u0026gt;, temperature=temperature@entry=0x3fc9fe5c) at /Users/francesco/Documents/articles/devrel-advanced-workshop-code/assignment_3_2/components/temperature_sensor/temperature_sensor.c:150 #2 0x4200d4d4 in temp_event_handler (handler_arg=\u0026lt;optimized out\u0026gt;, base=\u0026lt;optimized out\u0026gt;, id=\u0026lt;optimized out\u0026gt;, event_data=\u0026lt;optimized out\u0026gt;) at /Users/francesco/Documents/articles/devrel-advanced-workshop-code/assignment_3_2/main/app_main.c:50 #3 0x420b1942 in handler_execute (loop=loop@entry=0x3fc9f13c, handler=\u0026lt;optimized out\u0026gt;, post=\u0026lt;error reading variable: Cannot access memory at address 0x0\u0026gt;) at /Users/francesco/esp/v5.4.2/esp-idf/components/esp_event/esp_event.c:136 #4 0x420b228e in esp_event_loop_run (event_loop=event_loop@entry=0x3fc9f13c, ticks_to_run=ticks_to_run@entry=4294967295) at /Users/francesco/esp/v5.4.2/esp-idf/components/esp_event/esp_event.c:696 #5 0x420b2386 in esp_event_loop_run_task (args=0x3fc9f13c, args@entry=\u0026lt;error reading variable: value has been optimized out\u0026gt;) at /Users/francesco/esp/v5.4.2/esp-idf/components/esp_event/esp_event.c:106 #6 0x403877cc in vPortTaskWrapper (pxCode=\u0026lt;optimized out\u0026gt;, pvParameters=\u0026lt;optimized out\u0026gt;) at /Users/francesco/esp/v5.4.2/esp-idf/components/freertos/FreeRTOS-Kernel/portable/riscv/port.c:255 ======================== THREADS INFO ========================= Id Target Id Frame * 1 process 1070202648 0x00000000 in ?? () 2 process 1070198548 0x403851d4 in esp_cpu_wait_for_intr () at /Users/francesco/esp/v5.4.2/esp-idf/components/esp_hw_support/cpu.c:64 3 process 1070254080 0x4038345e in esp_crosscore_int_send_yield (core_id=core_id@entry=0) at /Users/francesco/esp/v5.4.2/esp-idf/components/esp_system/crosscore_int.c:121 4 process 1070196668 0x4038345e in esp_crosscore_int_send_yield (core_id=core_id@entry=0) at /Users/francesco/esp/v5.4.2/esp-idf/components/esp_system/crosscore_int.c:121 5 process 1070209148 0x4038345e in esp_crosscore_int_send_yield (core_id=core_id@entry=0) at /Users/francesco/esp/v5.4.2/esp-idf/components/esp_system/crosscore_int.c:121 6 process 1070222780 0x4038345e in esp_crosscore_int_send_yield (core_id=core_id@entry=0) at /Users/francesco/esp/v5.4.2/esp-idf/components/esp_system/crosscore_int.c:121 7 process 1070191796 0x40387998 in vPortClearInterruptMaskFromISR (prev_int_level=1) at /Users/francesco/esp/v5.4.2/esp-idf/components/freertos/FreeRTOS-Kernel/portable/riscv/port.c:515 TCB NAME PRIO C/B STACK USED/FREE ---------- ---------------- -------- ---------------- 0x3fc9ff18 sys_evt 20/20 352/2460 0x3fc9ef14 IDLE 0/0 208/1312 0x3fcac800 mqtt_task 5/5 624/5516 0x3fc9e7bc main 1/1 336/3752 0x3fca187c tiT 18/18 336/3240 0x3fca4dbc wifi 23/23 336/6312 0x3fc9d4b4 esp_timer 22/22 224/3856 ==================== THREAD 1 (TCB: 0x3fc9ff18, name: \u0026#39;sys_evt\u0026#39;) ===================== #0 0x00000000 in ?? () #1 0x4200dc68 in temperature_sensor_read_celsius (sensor=\u0026lt;optimized out\u0026gt;, temperature=temperature@entry=0x3fc9fe5c) at /Users/francesco/Documents/articles/devrel-advanced-workshop-code/assignment_3_2/components/temperature_sensor/temperature_sensor.c:150 #2 0x4200d4d4 in temp_event_handler (handler_arg=\u0026lt;optimized out\u0026gt;, base=\u0026lt;optimized out\u0026gt;, id=\u0026lt;optimized out\u0026gt;, event_data=\u0026lt;optimized out\u0026gt;) at /Users/francesco/Documents/articles/devrel-advanced-workshop-code/assignment_3_2/main/app_main.c:50 #3 0x420b1942 in handler_execute (loop=loop@entry=0x3fc9f13c, handler=\u0026lt;optimized out\u0026gt;, post=\u0026lt;error reading variable: Cannot access memory at address 0x0\u0026gt;) at /Users/francesco/esp/v5.4.2/esp-idf/components/esp_event/esp_event.c:136 #4 0x420b228e in esp_event_loop_run (event_loop=event_loop@entry=0x3fc9f13c, ticks_to_run=ticks_to_run@entry=4294967295) at /Users/francesco/esp/v5.4.2/esp-idf/components/esp_event/esp_event.c:696 #5 0x420b2386 in esp_event_loop_run_task (args=0x3fc9f13c, args@entry=\u0026lt;error reading variable: value has been optimized out\u0026gt;) at /Users/francesco/esp/v5.4.2/esp-idf/components/esp_event/esp_event.c:106 #6 0x403877cc in vPortTaskWrapper (pxCode=\u0026lt;optimized out\u0026gt;, pvParameters=\u0026lt;optimized out\u0026gt;) at /Users/francesco/esp/v5.4.2/esp-idf/components/freertos/FreeRTOS-Kernel/portable/riscv/port.c:255 ==================== THREAD 2 (TCB: 0x3fc9ef14, name: \u0026#39;IDLE\u0026#39;) ===================== #0 0x403851d4 in esp_cpu_wait_for_intr () at /Users/francesco/esp/v5.4.2/esp-idf/components/esp_hw_support/cpu.c:64 #1 0x42015ce6 in esp_vApplicationIdleHook () at /Users/francesco/esp/v5.4.2/esp-idf/components/esp_system/freertos_hooks.c:58 #2 0x4038859c in prvIdleTask (pvParameters=\u0026lt;error reading variable: value has been optimized out\u0026gt;) at /Users/francesco/esp/v5.4.2/esp-idf/components/freertos/FreeRTOS-Kernel/tasks.c:4341 #3 0x403877cc in vPortTaskWrapper (pxCode=\u0026lt;optimized out\u0026gt;, pvParameters=\u0026lt;optimized out\u0026gt;) at /Users/francesco/esp/v5.4.2/esp-idf/components/freertos/FreeRTOS-Kernel/portable/riscv/port.c:255 ==================== THREAD 3 (TCB: 0x3fcac800, name: \u0026#39;mqtt_task\u0026#39;) ===================== #0 0x4038345e in esp_crosscore_int_send_yield (core_id=core_id@entry=0) at /Users/francesco/esp/v5.4.2/esp-idf/components/esp_system/crosscore_int.c:121 #1 0x40387a5c in vPortYield () at /Users/francesco/esp/v5.4.2/esp-idf/components/freertos/FreeRTOS-Kernel/portable/riscv/port.c:638 #2 0x403875bc in xQueueSemaphoreTake (xQueue=0x3fcaca20, xTicksToWait=\u0026lt;optimized out\u0026gt;, xTicksToWait@entry=101) at /Users/francesco/esp/v5.4.2/esp-idf/components/freertos/FreeRTOS-Kernel/queue.c:1901 #3 0x4208695e in sys_arch_sem_wait (sem=\u0026lt;optimized out\u0026gt;, timeout=1000) at /Users/francesco/esp/v5.4.2/esp-idf/components/lwip/port/freertos/sys_arch.c:175 #4 0x42070b2a in lwip_select (maxfdp1=55, readset=0x3fcae488, writeset=0x0, exceptset=0x3fcae480, timeout=0x3fcae490) at /Users/francesco/esp/v5.4.2/esp-idf/components/lwip/lwip/src/api/sockets.c:2142 #5 0x4200abe8 in esp_vfs_select (nfds=nfds@entry=55, readfds=readfds@entry=0x3fcae488, writefds=writefds@entry=0x0, errorfds=errorfds@entry=0x3fcae480, timeout=0x3fcae490) at /Users/francesco/esp/v5.4.2/esp-idf/components/vfs/vfs.c:1570 #6 0x42023706 in base_poll_read (t=0x3fcac734, timeout_ms=1000) at /Users/francesco/esp/v5.4.2/esp-idf/components/tcp_transport/transport_ssl.c:176 #7 0x4202325c in esp_transport_poll_read (t=\u0026lt;optimized out\u0026gt;, timeout_ms=timeout_ms@entry=1000) at /Users/francesco/esp/v5.4.2/esp-idf/components/tcp_transport/transport.c:156 #8 0x4200f9f8 in esp_mqtt_task (pv=0x3fca1a28, pv@entry=\u0026lt;error reading variable: value has been optimized out\u0026gt;) at /Users/francesco/esp/v5.4.2/esp-idf/components/mqtt/esp-mqtt/mqtt_client.c:1736 #9 0x403877cc in vPortTaskWrapper (pxCode=\u0026lt;optimized out\u0026gt;, pvParameters=\u0026lt;optimized out\u0026gt;) at /Users/francesco/esp/v5.4.2/esp-idf/components/freertos/FreeRTOS-Kernel/portable/riscv/port.c:255 ==================== THREAD 4 (TCB: 0x3fc9e7bc, name: \u0026#39;main\u0026#39;) ===================== #0 0x4038345e in esp_crosscore_int_send_yield (core_id=core_id@entry=0) at /Users/francesco/esp/v5.4.2/esp-idf/components/esp_system/crosscore_int.c:121 #1 0x40387a5c in vPortYield () at /Users/francesco/esp/v5.4.2/esp-idf/components/freertos/FreeRTOS-Kernel/portable/riscv/port.c:638 #2 0x40388d04 in vTaskDelay (xTicksToDelay=xTicksToDelay@entry=100) at /Users/francesco/esp/v5.4.2/esp-idf/components/freertos/FreeRTOS-Kernel/tasks.c:1588 #3 0x4200d7e8 in app_main () at /Users/francesco/Documents/articles/devrel-advanced-workshop-code/assignment_3_2/main/app_main.c:136 #4 0x420b420c in main_task (args=\u0026lt;error reading variable: value has been optimized out\u0026gt;) at /Users/francesco/esp/v5.4.2/esp-idf/components/freertos/app_startup.c:208 #5 0x403877cc in vPortTaskWrapper (pxCode=\u0026lt;optimized out\u0026gt;, pvParameters=\u0026lt;optimized out\u0026gt;) at /Users/francesco/esp/v5.4.2/esp-idf/components/freertos/FreeRTOS-Kernel/portable/riscv/port.c:255 ==================== THREAD 5 (TCB: 0x3fca187c, name: \u0026#39;tiT\u0026#39;) ===================== #0 0x4038345e in esp_crosscore_int_send_yield (core_id=core_id@entry=0) at /Users/francesco/esp/v5.4.2/esp-idf/components/esp_system/crosscore_int.c:121 #1 0x40387a5c in vPortYield () at /Users/francesco/esp/v5.4.2/esp-idf/components/freertos/FreeRTOS-Kernel/portable/riscv/port.c:638 #2 0x40387450 in xQueueReceive (xQueue=0x3fca099c, pvBuffer=pvBuffer@entry=0x3fca182c, xTicksToWait=\u0026lt;optimized out\u0026gt;, xTicksToWait@entry=1) at /Users/francesco/esp/v5.4.2/esp-idf/components/freertos/FreeRTOS-Kernel/queue.c:1659 #3 0x42086ae6 in sys_arch_mbox_fetch (mbox=mbox@entry=0x3fc9b7c0 \u0026lt;tcpip_mbox\u0026gt;, msg=msg@entry=0x3fca182c, timeout=10) at /Users/francesco/esp/v5.4.2/esp-idf/components/lwip/port/freertos/sys_arch.c:313 #4 0x420710e8 in tcpip_timeouts_mbox_fetch (mbox=mbox@entry=0x3fc9b7c0 \u0026lt;tcpip_mbox\u0026gt;, msg=msg@entry=0x3fca182c) at /Users/francesco/esp/v5.4.2/esp-idf/components/lwip/lwip/src/api/tcpip.c:104 #5 0x420711da in tcpip_thread (arg=\u0026lt;error reading variable: value has been optimized out\u0026gt;) at /Users/francesco/esp/v5.4.2/esp-idf/components/lwip/lwip/src/api/tcpip.c:142 #6 0x403877cc in vPortTaskWrapper (pxCode=\u0026lt;optimized out\u0026gt;, pvParameters=\u0026lt;optimized out\u0026gt;) at /Users/francesco/esp/v5.4.2/esp-idf/components/freertos/FreeRTOS-Kernel/portable/riscv/port.c:255 ==================== THREAD 6 (TCB: 0x3fca4dbc, name: \u0026#39;wifi\u0026#39;) ===================== #0 0x4038345e in esp_crosscore_int_send_yield (core_id=core_id@entry=0) at /Users/francesco/esp/v5.4.2/esp-idf/components/esp_system/crosscore_int.c:121 #1 0x40387a5c in vPortYield () at /Users/francesco/esp/v5.4.2/esp-idf/components/freertos/FreeRTOS-Kernel/portable/riscv/port.c:638 #2 0x40387450 in xQueueReceive (xQueue=0x3fca2c9c, pvBuffer=0x3fca4d48, xTicksToWait=\u0026lt;optimized out\u0026gt;, xTicksToWait@entry=4294967295) at /Users/francesco/esp/v5.4.2/esp-idf/components/freertos/FreeRTOS-Kernel/queue.c:1659 #3 0x420b3d62 in queue_recv_wrapper (queue=\u0026lt;optimized out\u0026gt;, item=\u0026lt;optimized out\u0026gt;, block_time_tick=\u0026lt;optimized out\u0026gt;) at /Users/francesco/esp/v5.4.2/esp-idf/components/esp_wifi/esp32c3/esp_adapter.c:238 #4 0x400407be in ppTask () #5 0x403877cc in vPortTaskWrapper (pxCode=\u0026lt;optimized out\u0026gt;, pvParameters=\u0026lt;optimized out\u0026gt;) at /Users/francesco/esp/v5.4.2/esp-idf/components/freertos/FreeRTOS-Kernel/portable/riscv/port.c:255 ==================== THREAD 7 (TCB: 0x3fc9d4b4, name: \u0026#39;esp_timer\u0026#39;) ===================== #0 0x40387998 in vPortClearInterruptMaskFromISR (prev_int_level=1) at /Users/francesco/esp/v5.4.2/esp-idf/components/freertos/FreeRTOS-Kernel/portable/riscv/port.c:515 #1 0x40387a28 in vPortExitCritical () at /Users/francesco/esp/v5.4.2/esp-idf/components/freertos/FreeRTOS-Kernel/portable/riscv/port.c:624 #2 0x40389774 in ulTaskGenericNotifyTake (uxIndexToWait=uxIndexToWait@entry=0, xClearCountOnExit=xClearCountOnExit@entry=1, xTicksToWait=xTicksToWait@entry=4294967295) at /Users/francesco/esp/v5.4.2/esp-idf/components/freertos/FreeRTOS-Kernel/tasks.c:5759 #3 0x42017e98 in timer_task (arg=\u0026lt;error reading variable: value has been optimized out\u0026gt;) at /Users/francesco/esp/v5.4.2/esp-idf/components/esp_timer/src/esp_timer.c:459 #4 0x403877cc in vPortTaskWrapper (pxCode=\u0026lt;optimized out\u0026gt;, pvParameters=\u0026lt;optimized out\u0026gt;) at /Users/francesco/esp/v5.4.2/esp-idf/components/freertos/FreeRTOS-Kernel/portable/riscv/port.c:255 ======================= ALL MEMORY REGIONS ======================== Name Address Size Attrs .rtc.text 0x50000000 0x0 RW .rtc.force_fast 0x50000000 0x1c RW A .rtc_noinit 0x5000001c 0x0 RW .rtc.force_slow 0x5000001c 0x0 RW .iram0.text 0x40380000 0x13d0a R XA .dram0.data 0x3fc93e00 0x2ed8 RW A .flash.text 0x42000020 0xb4fd6 R XA .flash.appdesc 0x3c0c0020 0x100 R A .flash.rodata 0x3c0c0120 0x1ff3c RW A .eh_frame_hdr 0x3c0e005c 0x0 RW .eh_frame 0x3c0e005c 0x0 RW .flash.tdata 0x3c0e005c 0x0 RW .iram0.data 0x40393e00 0x0 RW .iram0.bss 0x40393e00 0x0 RW .dram0.heap_start 0x3fc9b8e0 0x0 RW .coredump.tasks.data 0x3fc9ff18 0x150 RW .coredump.tasks.data 0x3fc9fda0 0x170 RW .coredump.tasks.data 0x3fc9ef14 0x150 RW .coredump.tasks.data 0x3fc9ee30 0xd0 RW .coredump.tasks.data 0x3fcac800 0x150 RW .coredump.tasks.data 0x3fcae2c0 0x270 RW .coredump.tasks.data 0x3fc9e7bc 0x150 RW .coredump.tasks.data 0x3fc9e660 0x150 RW .coredump.tasks.data 0x3fca187c 0x150 RW .coredump.tasks.data 0x3fca1720 0x150 RW .coredump.tasks.data 0x3fca4dbc 0x150 RW .coredump.tasks.data 0x3fca4c60 0x150 RW .coredump.tasks.data 0x3fc9d4b4 0x150 RW .coredump.tasks.data 0x3fc9d3c0 0xe0 RW ===================== ESP32 CORE DUMP END ===================== =============================================================== Done! Good bug hunting!\nShow solution The error is caused by line 128 in app_main.c\nfree(sensor); It deletes the sensor object and the temperature reading is using an invalid pointer.\nNext step: Lecture 4\n","date":"5 August 2025","externalUrl":null,"permalink":"/workshops/esp-idf-advanced/assignment-3-3/","section":"Workshops","summary":"Explore core dump - DIY","title":"ESP-IDF Adv. - Assign.  3.3","type":"workshops"},{"content":"To perform OTA, we need a partition table with at least two partitions.\nAssignment steps # In this first assignment, we will:\nCheck the current partition table loaded in your module Change it to a different default partition table Check the new partition table Check the current partiton table # To check the current partition table you need to\nRead the flash and dump the partition table in a .bin file Convert the .bin file to a readable format Read the flash # To read the flash we can use esptool.py:\nesptool.py -p \u0026lt;YOUR-PORT\u0026gt; read_flash 0x8000 0x1000 partition_table.bin where \u0026lt;YOUR-PORT\u0026gt; is the same port you use to flash the device (e.g. /dev/tty.usbmodem1131101 or COM25).\nThis creates a partition_table.bin file.\nConvert the partition table # To convert it to a readable format, we can use gen_esp32part.py.\npython $IDF_PATH/components/partition_table/gen_esp32part.py partition_table.bin You should get this output:\nParsing binary partition input... Verifying table... # ESP-IDF Partition Table # Name, Type, SubType, Offset, Size, Flags nvs,data,nvs,0x9000,24K, phy_init,data,phy,0xf000,4K, factory,app,factory,0x10000,1M, coredump,data,coredump,0x110000,64K, Change partition table # Now we change the partition table, using the most appropriate default option selectable via menuconfig.\nOpen menuconfig: \u0026gt; ESP-IDF: SDK Configuration Editor (menuconfig)\n→ Partition Table → Factory app, two OTA definitions Since we\u0026rsquo;re now using two OTAs, the default flash configuration of 2MB is not enough, so we need to change it too\nOpen menuconfig: \u0026gt; ESP-IDF: SDK Configuration Editor (menuconfig)\n→ Serial Flasher Config → Flash Size → 4MB Check the new partition table # Let\u0026rsquo;s do the same steps as before\nesptool.py -p \u0026lt;YOUR-PORT\u0026gt; read_flash 0x8000 0x1000 partition_table.bin python $IDF_PATH/components/partition_table/gen_esp32part.py partition_table.bin And you\u0026rsquo;ll get\nParsing binary partition input... Verifying table... # ESP-IDF Partition Table # Name, Type, SubType, Offset, Size, Flags nvs,data,nvs,0x9000,16K, otadata,data,ota,0xd000,8K, phy_init,data,phy,0xf000,4K, factory,app,factory,0x10000,1M, ota_0,app,ota_0,0x110000,1M, ota_1,app,ota_1,0x210000,1M, Conclusion # In this assignment you changed the partition table from Single factory app, no ota to the default Factory app, two ota definitions. Both of these partition table scheme are provided as default values from ESP-IDF. In the next assignment you will create a custom partition table.\nNext step: assignment 4.2\n","date":"5 August 2025","externalUrl":null,"permalink":"/workshops/esp-idf-advanced/assignment-4-1/","section":"Workshops","summary":"Change partition table to Factory app, two ota definitions","title":"ESP-IDF Adv. - Assign.  4.1","type":"workshops"},{"content":"In this assignment, you\u0026rsquo;ll set a custom partiton table using VSCode.\nAssignment steps # First, you need to enable the custom partition table in the menuconfig\nOpen menuconfig: \u0026gt; ESP-IDF: SDK Configuration Editor (menuconfig)\n→ Partition Table → Custom Partition Table CSV Open editor: \u0026gt; ESP-IDF: Open Partition Table Editor UI Copy the previous partition table Add a spiffs partition Custom partition table\nBuild the partition table: \u0026gt; ESP-IDF: Build Partition Table Flash the partition table: \u0026gt; ESP-IDF: Flash (UART) Your Project Parsing binary partition input... Verifying table... # ESP-IDF Partition Table # Name, Type, SubType, Offset, Size, Flags nsv,data,nvs,0x9000,16K, otadata,data,ota,0xd000,8K, phy_init,data,phy,0xf000,4K, factory_app,app,factory,0x10000,1M, ota_0,app,ota_0,0x110000,1M, ota_1,app,ota_1,0x210000,1M, fs,data,spiffs,0x310000,64K, Next step: assignment 4.3\n","date":"5 August 2025","externalUrl":null,"permalink":"/workshops/esp-idf-advanced/assignment-4-2/","section":"Workshops","summary":"Create a custom partition table","title":"ESP-IDF Adv. - Assign.  4.2","type":"workshops"},{"content":"In this assignment, we will enable flash encryption.\nEnabling flash encryption (and secure bootloader) is an irreversible operation. Double check before doing any step. Assignment steps # In this assignment, we will:\nCheck your device encryption status Enable flash encryption (development mode) Set partition table Check the encryption status again Check device encryption status # Open an ESP-IDF terminal : \u0026gt; ESP-IDF: Open ESP-IDF Terminal Inside the terminal, run idf.py efuse-summary Now check the relevant eFuses listed in the table below. They must all be at their default zero state.\neFuse Description BLOCK_KEYN AES key storage. N is between 0 and 5. KEY_PURPOSE_N Control the purpose of eFuse block BLOCK_KEYN, where N is between 0 and 5. For flash encryption, the only valid value is 4 for XTS_AES_128_KEY. DIS_DOWNLOAD_MANUAL_ENCRYPT If set, disables flash encryption when in download boot modes. SPI_BOOT_CRYPT_CNT Enables encryption and decryption when an SPI boot mode is set. Feature is enabled if 1 or 3 bits are set in the eFuse; disabled otherwise. Show the eFuse blocks EFUSE_NAME (Block) Description = [Meaningful Value] [Readable/Writeable] (Hex Value) ---------------------------------------------------------------------------------------- Calibration fuses: K_RTC_LDO (BLOCK1) BLOCK1 K_RTC_LDO = 96 R/W (0b0011000) K_DIG_LDO (BLOCK1) BLOCK1 K_DIG_LDO = 20 R/W (0b0000101) V_RTC_DBIAS20 (BLOCK1) BLOCK1 voltage of rtc dbias20 = 172 R/W (0x2b) V_DIG_DBIAS20 (BLOCK1) BLOCK1 voltage of digital dbias20 = 32 R/W (0x08) DIG_DBIAS_HVT (BLOCK1) BLOCK1 digital dbias when hvt = -12 R/W (0b10011) THRES_HVT (BLOCK1) BLOCK1 pvt threshold when hvt = 1600 R/W (0b0110010000) TEMP_CALIB (BLOCK2) Temperature calibration data = -9.0 R/W (0b101011010) OCODE (BLOCK2) ADC OCode = 96 R/W (0x60) ADC1_INIT_CODE_ATTEN0 (BLOCK2) ADC1 init code at atten0 = 1736 R/W (0b0110110010) ADC1_INIT_CODE_ATTEN1 (BLOCK2) ADC1 init code at atten1 = -272 R/W (0b1001000100) ADC1_INIT_CODE_ATTEN2 (BLOCK2) ADC1 init code at atten2 = -368 R/W (0b1001011100) ADC1_INIT_CODE_ATTEN3 (BLOCK2) ADC1 init code at atten3 = -824 R/W (0b1011001110) ADC1_CAL_VOL_ATTEN0 (BLOCK2) ADC1 calibration voltage at atten0 = -204 R/W (0b1000110011) ADC1_CAL_VOL_ATTEN1 (BLOCK2) ADC1 calibration voltage at atten1 = -4 R/W (0b1000000001) ADC1_CAL_VOL_ATTEN2 (BLOCK2) ADC1 calibration voltage at atten2 = -160 R/W (0b1000101000) ADC1_CAL_VOL_ATTEN3 (BLOCK2) ADC1 calibration voltage at atten3 = -332 R/W (0b1001010011) Config fuses: WR_DIS (BLOCK0) Disable programming of individual eFuses = 0 R/W (0x00000000) RD_DIS (BLOCK0) Disable reading from BlOCK4-10 = 0 R/W (0b0000000) DIS_ICACHE (BLOCK0) Set this bit to disable Icache = False R/W (0b0) DIS_TWAI (BLOCK0) Set this bit to disable CAN function = False R/W (0b0) DIS_DIRECT_BOOT (BLOCK0) Disable direct boot mode = False R/W (0b0) UART_PRINT_CONTROL (BLOCK0) Set the default UARTboot message output mode = Enable when GPIO8 is high at reset R/W (0b10) ERR_RST_ENABLE (BLOCK0) Use BLOCK0 to check error record registers = without check R/W (0b0) BLOCK_USR_DATA (BLOCK3) User data = 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 R/W BLOCK_SYS_DATA2 (BLOCK10) System data part 2 (reserved) = 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 R/W Flash fuses: FLASH_TPUW (BLOCK0) Configures flash waiting time after power-up; in u = 0 R/W (0x0) nit of ms. If the value is less than 15; the waiti ng time is the configurable value; Otherwise; the waiting time is twice the configurable value FORCE_SEND_RESUME (BLOCK0) Set this bit to force ROM code to send a resume co = False R/W (0b0) mmand during SPI boot FLASH_CAP (BLOCK1) Flash capacity = 4M R/W (0b001) FLASH_TEMP (BLOCK1) Flash temperature = 105C R/W (0b01) FLASH_VENDOR (BLOCK1) Flash vendor = XMC R/W (0b001) Identity fuses: DISABLE_WAFER_VERSION_MAJOR (BLOCK0) Disables check of wafer version major = False R/W (0b0) DISABLE_BLK_VERSION_MAJOR (BLOCK0) Disables check of blk version major = False R/W (0b0) WAFER_VERSION_MINOR_LO (BLOCK1) WAFER_VERSION_MINOR least significant bits = 3 R/W (0b011) PKG_VERSION (BLOCK1) Package version = 0 R/W (0b000) BLK_VERSION_MINOR (BLOCK1) BLK_VERSION_MINOR = 1 R/W (0b001) WAFER_VERSION_MINOR_HI (BLOCK1) WAFER_VERSION_MINOR most significant bit = False R/W (0b0) WAFER_VERSION_MAJOR (BLOCK1) WAFER_VERSION_MAJOR = 0 R/W (0b00) OPTIONAL_UNIQUE_ID (BLOCK2) Optional unique 128-bit ID = 7c c7 9b 3a 4c 1f e1 be 56 79 19 20 4f ff cd 0e R/W BLK_VERSION_MAJOR (BLOCK2) BLK_VERSION_MAJOR of BLOCK2 = With calibration R/W (0b01) WAFER_VERSION_MINOR (BLOCK0) calc WAFER VERSION MINOR = WAFER_VERSION_MINOR_HI = 3 R/W (0x3) \u0026lt;\u0026lt; 3 + WAFER_VERSION_MINOR_LO (read only) Jtag fuses: SOFT_DIS_JTAG (BLOCK0) Set these bits to disable JTAG in the soft way (od = 0 R/W (0b000) d number 1 means disable ). JTAG can be enabled in HMAC module DIS_PAD_JTAG (BLOCK0) Set this bit to disable JTAG in the hard way. JTAG = False R/W (0b0) is disabled permanently Mac fuses: MAC (BLOCK1) MAC address = 84:f7:03:42:8c:a8 (OK) R/W CUSTOM_MAC (BLOCK3) Custom MAC address = 00:00:00:00:00:00 (OK) R/W Security fuses: DIS_DOWNLOAD_ICACHE (BLOCK0) Set this bit to disable Icache in download mode (b = False R/W (0b0) oot_mode[3:0] is 0; 1; 2; 3; 6; 7) DIS_FORCE_DOWNLOAD (BLOCK0) Set this bit to disable the function that forces c = False R/W (0b0) hip into download mode DIS_DOWNLOAD_MANUAL_ENCRYPT (BLOCK0) Set this bit to disable flash encryption when in d = False R/W (0b0) ownload boot modes SPI_BOOT_CRYPT_CNT (BLOCK0) Enables flash encryption when 1 or 3 bits are set = Disable R/W (0b000) and disables otherwise SECURE_BOOT_KEY_REVOKE0 (BLOCK0) Revoke 1st secure boot key = False R/W (0b0) SECURE_BOOT_KEY_REVOKE1 (BLOCK0) Revoke 2nd secure boot key = False R/W (0b0) SECURE_BOOT_KEY_REVOKE2 (BLOCK0) Revoke 3rd secure boot key = False R/W (0b0) KEY_PURPOSE_0 (BLOCK0) Purpose of Key0 = USER R/W (0x0) KEY_PURPOSE_1 (BLOCK0) Purpose of Key1 = USER R/W (0x0) KEY_PURPOSE_2 (BLOCK0) Purpose of Key2 = USER R/W (0x0) KEY_PURPOSE_3 (BLOCK0) Purpose of Key3 = USER R/W (0x0) KEY_PURPOSE_4 (BLOCK0) Purpose of Key4 = USER R/W (0x0) KEY_PURPOSE_5 (BLOCK0) Purpose of Key5 = USER R/W (0x0) SECURE_BOOT_EN (BLOCK0) Set this bit to enable secure boot = False R/W (0b0) SECURE_BOOT_AGGRESSIVE_REVOKE (BLOCK0) Set this bit to enable revoking aggressive secure = False R/W (0b0) boot DIS_DOWNLOAD_MODE (BLOCK0) Set this bit to disable download mode (boot_mode[3 = False R/W (0b0) :0] = 0; 1; 2; 3; 6; 7) ENABLE_SECURITY_DOWNLOAD (BLOCK0) Set this bit to enable secure UART download mode = False R/W (0b0) SECURE_VERSION (BLOCK0) Secure version (used by ESP-IDF anti-rollback feat = 0 R/W (0x0000) ure) BLOCK_KEY0 (BLOCK4) Purpose: USER Key0 or user data = 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 R/W BLOCK_KEY1 (BLOCK5) Purpose: USER Key1 or user data = 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 R/W BLOCK_KEY2 (BLOCK6) Purpose: USER Key2 or user data = 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 R/W BLOCK_KEY3 (BLOCK7) Purpose: USER Key3 or user data = 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 R/W BLOCK_KEY4 (BLOCK8) Purpose: USER Key4 or user data = 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 R/W BLOCK_KEY5 (BLOCK9) Purpose: USER Key5 or user data = 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 R/W Spi Pad fuses: SPI_PAD_CONFIG_CLK (BLOCK1) SPI PAD CLK = 0 R/W (0b000000) SPI_PAD_CONFIG_Q (BLOCK1) SPI PAD Q(D1) = 0 R/W (0b000000) SPI_PAD_CONFIG_D (BLOCK1) SPI PAD D(D0) = 0 R/W (0b000000) SPI_PAD_CONFIG_CS (BLOCK1) SPI PAD CS = 0 R/W (0b000000) SPI_PAD_CONFIG_HD (BLOCK1) SPI PAD HD(D3) = 0 R/W (0b000000) SPI_PAD_CONFIG_WP (BLOCK1) SPI PAD WP(D2) = 0 R/W (0b000000) SPI_PAD_CONFIG_DQS (BLOCK1) SPI PAD DQS = 0 R/W (0b000000) SPI_PAD_CONFIG_D4 (BLOCK1) SPI PAD D4 = 0 R/W (0b000000) SPI_PAD_CONFIG_D5 (BLOCK1) SPI PAD D5 = 0 R/W (0b000000) SPI_PAD_CONFIG_D6 (BLOCK1) SPI PAD D6 = 0 R/W (0b000000) SPI_PAD_CONFIG_D7 (BLOCK1) SPI PAD D7 = 0 R/W (0b000000) Usb fuses: DIS_USB_JTAG (BLOCK0) Set this bit to disable function of usb switch to = False R/W (0b0) jtag in module of usb device DIS_USB_SERIAL_JTAG (BLOCK0) USB-Serial-JTAG = Enable R/W (0b0) USB_EXCHG_PINS (BLOCK0) Set this bit to exchange USB D+ and D- pins = False R/W (0b0) DIS_USB_SERIAL_JTAG_ROM_PRINT (BLOCK0) USB printing = Enable R/W (0b0) DIS_USB_SERIAL_JTAG_DOWNLOAD_MODE (BLOCK0) Disable UART download mode through USB-Serial-JTAG = False R/W (0b0) Vdd fuses: VDD_SPI_AS_GPIO (BLOCK0) Set this bit to vdd spi pin function as gpio = False R/W (0b0) Wdt fuses: WDT_DELAY_SEL (BLOCK0) RTC watchdog timeout threshold; in unit of slow cl = 40000 R/W (0b00) ock cycle Enable encryption # Open menuconfig: \u0026gt; ESP-IDF: SDK Configuration Editor (menuconfig)\n→ Security Features → Enable flash encryption on boot (READ DOCS FIRST)\nMake sure you have: Enable usage mode → Development (Not secure)\nYour configuration should ressemble this:\nFlash encryption options\nWe will also increase the bootloader verbosity to see what happens\nOpen menuconfig: \u0026gt; ESP-IDF: SDK Configuration Editor (menuconfig)\n→ Bootloader log verbosity → verbose Set partition table # If you\u0026rsquo;d try to flash the project, you will get an error.\nShow error Successfully created esp32c3 image. Generated \u0026lt;PROJECT_ROOT\u0026gt;/build/bootloader/bootloader.bin [103/103] cd \u0026lt;PROJECT_ROOT\u0026gt;/build/bootloader/esp-idf/esptool_py \u0026amp;\u0026amp; \u0026lt;PYTHON_ENV_PATH\u0026gt;/bin/python \u0026lt;ESP_IDF_PATH\u0026gt;/components/partition_table/check_sizes.py --offset 0x8000 bootloader 0x0 \u0026lt;PROJECT_ROOT\u0026gt;/build/bootloader/bootloader.bin FAILED: esp-idf/esptool_py/CMakeFiles/bootloader_check_size \u0026lt;PROJECT_ROOT\u0026gt;/build/bootloader/esp-idf/esptool_py/CMakeFiles/bootloader_check_size cd \u0026lt;PROJECT_ROOT\u0026gt;/build/bootloader/esp-idf/esptool_py \u0026amp;\u0026amp; \u0026lt;PYTHON_ENV_PATH\u0026gt;/bin/python \u0026lt;ESP_IDF_PATH\u0026gt;/components/partition_table/check_sizes.py --offset 0x8000 bootloader 0x0 \u0026lt;PROJECT_ROOT\u0026gt;/build/bootloader/bootloader.bin Error: Bootloader binary size 0x91f0 bytes is too large for partition table offset 0x8000. Bootloader binary can be maximum 0x8000 (32768) bytes unless the partition table offset is increased in the Partition Table section of the project configuration menu. ninja: build stopped: subcommand failed. [972/978] Generating ld/sections.ld ninja: build stopped: subcommand failed. The reason is that the bootloader now takes more space and does not fit in the space of the standard partition table offset (0x8000). We need to change it to 0xf000 before moving on.\nOpen menuconfig: \u0026gt; ESP-IDF: SDK Configuration Editor (menuconfig)\n→ Offset of partition table → 0xf000 Now you can build and flash again and you will get:\n[Flash Encryption] WARNING: Flash Encryption in Development Mode This will burn eFuses on your device which is an IRREVERSIBLE operation. In Development Mode: Development Mode: Allows re-flashing with plaintext data The flash encryption process requires two steps: 1. First, you need to confirm by typing \u0026#34;BURN DEV\u0026#34; in the input box at the top of the screen 2. After flashing completes, you MUST reset your device 3. Then flash again to enable encryption The flashing logs will be different than usual this time, informing us about the flashing encryption process.\nShow flashing logs D (122) boot: type=1 subtype=2 I (125) boot: 0 nvs WiFi data 01 02 00010000 00004000 D (132) boot: load partition table entry 0x3c00f020 D (136) boot: type=1 subtype=0 I (139) boot: 1 otadata OTA data 01 00 00014000 00002000 D (146) boot: load partition table entry 0x3c00f040 D (150) boot: type=1 subtype=1 I (153) boot: 2 phy_init RF data 01 01 00016000 00001000 D (160) boot: load partition table entry 0x3c00f060 D (164) boot: type=0 subtype=0 I (167) boot: 3 factory factory app 00 00 00020000 00100000 D (174) boot: load partition table entry 0x3c00f080 D (178) boot: type=0 subtype=10 I (181) boot: 4 ota_0 OTA app 00 10 00120000 00100000 D (188) boot: load partition table entry 0x3c00f0a0 D (192) boot: type=0 subtype=11 I (195) boot: 5 ota_1 OTA app 00 11 00220000 00100000 I (202) boot: End of partition table D (205) boot: OTA data offset 0x14000 D (208) bootloader_flash: rodata starts from paddr=0x00014000, size=0x2000, will be mapped to vaddr=0x3c000000 V (218) bootloader_flash: after mapping, starting from paddr=0x00010000 and vaddr=0x3c000000, 0x10000 bytes are mapped D (229) boot: otadata[0]: sequence values 0xffffffff D (233) boot: otadata[1]: sequence values 0xffffffff D (238) boot: OTA sequence numbers both empty (all-0xFF) or partition table does not have bootable ota_apps (app_count=2) I (249) boot: Defaulting to factory image D (252) boot: Trying partition index -1 offs 0x20000 size 0x100000 D (258) esp_image: reading image header @ 0x20000 D (263) bootloader_flash: mmu set block paddr=0x00020000 (was 0xffffffff) D (269) esp_image: image header: 0xe9 0x06 0x02 0x02 403802ea V (275) esp_image: loading segment header 0 at offset 0x20018 V (280) esp_image: segment data length 0x1fd24 data starts 0x20020 V (286) esp_image: MMU page size 0x10000 V (290) esp_image: segment 0 map_segment 1 segment_data_offs 0x20020 load_addr 0x3c0c0020 I (297) esp_image: segment 0: paddr=00020020 vaddr=3c0c0020 size=1fd24h (130340) map D (305) esp_image: free data page_count 0x00000080 D (309) bootloader_flash: rodata starts from paddr=0x00020020, size=0x1fd24, will be mapped to vaddr=0x3c000000 V (319) bootloader_flash: after mapping, starting from paddr=0x00020000 and vaddr=0x3c000000, 0x20000 bytes are mapped V (351) esp_image: loading segment header 1 at offset 0x3fd44 D (351) bootloader_flash: mmu set block paddr=0x00030000 (was 0xffffffff) V (351) esp_image: segment data length 0x2cc data starts 0x3fd4c V (357) esp_image: MMU page size 0x10000 V (361) esp_image: segment 1 map_segment 0 segment_data_offs 0x3fd4c load_addr 0x3fc93e00 I (369) esp_image: segment 1: paddr=0003fd4c vaddr=3fc93e00 size=002cch ( 716) load D (376) esp_image: free data page_count 0x00000080 D (381) bootloader_flash: rodata starts from paddr=0x0003fd4c, size=0x2cc, will be mapped to vaddr=0x3c000000 V (390) bootloader_flash: after mapping, starting from paddr=0x00030000 and vaddr=0x3c000000, 0x20000 bytes are mapped V (401) esp_image: loading segment header 2 at offset 0x40018 D (406) bootloader_flash: mmu set block paddr=0x00040000 (was 0xffffffff) V (413) esp_image: segment data length 0xb4b94 data starts 0x40020 V (419) esp_image: MMU page size 0x10000 V (422) esp_image: segment 2 map_segment 1 segment_data_offs 0x40020 load_addr 0x42000020 --- 0x42000020: esp_app_format_init_elf_sha256 at /Users/francesco/esp/v5.4.2/esp-idf/components/esp_app_format/esp_app_desc.c:88 I (430) esp_image: segment 2: paddr=00040020 vaddr=42000020 size=b4b94h (740244) map D (438) esp_image: free data page_count 0x00000080 D (442) bootloader_flash: rodata starts from paddr=0x00040020, size=0xb4b94, will be mapped to vaddr=0x3c000000 V (452) bootloader_flash: after mapping, starting from paddr=0x00040000 and vaddr=0x3c000000, 0xc0000 bytes are mapped V (580) esp_image: loading segment header 3 at offset 0xf4bb4 D (580) bootloader_flash: mmu set block paddr=0x000f0000 (was 0xffffffff) V (581) esp_image: segment data length 0x2c24 data starts 0xf4bbc V (587) esp_image: MMU page size 0x10000 V (591) esp_image: segment 3 map_segment 0 segment_data_offs 0xf4bbc load_addr 0x3fc940cc I (598) esp_image: segment 3: paddr=000f4bbc vaddr=3fc940cc size=02c24h ( 11300) load D (606) esp_image: free data page_count 0x00000080 D (610) bootloader_flash: rodata starts from paddr=0x000f4bbc, size=0x2c24, will be mapped to vaddr=0x3c000000 V (620) bootloader_flash: after mapping, starting from paddr=0x000f0000 and vaddr=0x3c000000, 0x10000 bytes are mapped V (633) esp_image: loading segment header 4 at offset 0xf77e0 D (636) bootloader_flash: mmu set block paddr=0x000f0000 (was 0xffffffff) V (643) esp_image: segment data length 0x13cc8 data starts 0xf77e8 V (649) esp_image: MMU page size 0x10000 V (652) esp_image: segment 4 map_segment 0 segment_data_offs 0xf77e8 load_addr 0x40380000 --- 0x40380000: _vector_table at /Users/francesco/esp/v5.4.2/esp-idf/components/riscv/vectors_intc.S:54 I (660) esp_image: segment 4: paddr=000f77e8 vaddr=40380000 size=13cc8h ( 81096) load D (668) esp_image: free data page_count 0x00000080 D (672) bootloader_flash: rodata starts from paddr=0x000f77e8, size=0x13cc8, will be mapped to vaddr=0x3c000000 V (682) bootloader_flash: after mapping, starting from paddr=0x000f0000 and vaddr=0x3c000000, 0x20000 bytes are mapped V (708) esp_image: loading segment header 5 at offset 0x10b4b0 D (708) bootloader_flash: mmu set block paddr=0x00100000 (was 0xffffffff) V (709) esp_image: segment data length 0x1c data starts 0x10b4b8 V (714) esp_image: MMU page size 0x10000 V (718) esp_image: segment 5 map_segment 0 segment_data_offs 0x10b4b8 load_addr 0x50000000 I (726) esp_image: segment 5: paddr=0010b4b8 vaddr=50000000 size=0001ch ( 28) load D (734) esp_image: free data page_count 0x00000080 D (738) bootloader_flash: rodata starts from paddr=0x0010b4b8, size=0x1c, will be mapped to vaddr=0x3c000000 V (748) bootloader_flash: after mapping, starting from paddr=0x00100000 and vaddr=0x3c000000, 0x10000 bytes are mapped V (758) esp_image: image start 0x00020000 end of last section 0x0010b4d4 D (764) bootloader_flash: mmu set block paddr=0x00100000 (was 0xffffffff) D (771) boot: Calculated hash: 95320d19f00e1b0ae9da94d51f205ea7a1731fc9a3252e2a61a665c109798d46 I (785) boot: Loaded app from partition at offset 0x20000 I (785) boot: Checking flash encryption... D (788) efuse: BLK0 REG2 [18-20], len=3 bits D (792) efuse: BLK0 REG0 [4-4], len=1 bits V (796) flash_encrypt: CRYPT_CNT 0, write protection 0 D (801) efuse: BLK0 REG0 [4-4], len=1 bits D (805) efuse: BLK0 REG2 [18-20], len=3 bits I (809) efuse: Batch mode of writing fields is enabled D (814) efuse: BLK0 REG2 [24-27], len=4 bits D (818) efuse: BLK0 REG2 [28-31], len=4 bits D (822) efuse: BLK0 REG3 [0-3], len=4 bits D (825) efuse: BLK0 REG3 [4-7], len=4 bits D (829) efuse: BLK0 REG3 [8-11], len=4 bits D (833) efuse: BLK0 REG3 [12-15], len=4 bits I (837) flash_encrypt: Generating new flash encryption key... D (843) flash_encrypt: Key generation complete D (847) efuse: BLK0 REG2 [24-27], len=4 bits D (851) efuse: BLK0 REG0 [8-8], len=1 bits D (855) efuse: BLK0 REG1 [0-0], len=1 bits D (858) efuse: BLK0 REG0 [23-23], len=1 bits D (862) efuse: BLK4 REG0 [0-31], len=32 bits D (866) efuse: BLK4 REG1 [0-31], len=32 bits D (870) efuse: BLK4 REG2 [0-31], len=32 bits D (874) efuse: BLK4 REG3 [0-31], len=32 bits D (878) efuse: BLK4 REG4 [0-31], len=32 bits D (882) efuse: BLK4 REG5 [0-31], len=32 bits D (886) efuse: BLK4 REG6 [0-31], len=32 bits D (890) efuse: BLK4 REG7 [0-31], len=32 bits D (894) efuse: BLK0 REG2 [28-31], len=4 bits D (898) efuse: BLK0 REG0 [9-9], len=1 bits D (902) efuse: BLK0 REG1 [1-1], len=1 bits D (906) efuse: BLK0 REG0 [24-24], len=1 bits D (910) efuse: BLK5 REG0 [0-31], len=32 bits D (914) efuse: BLK5 REG1 [0-31], len=32 bits D (918) efuse: BLK5 REG2 [0-31], len=32 bits D (922) efuse: BLK5 REG3 [0-31], len=32 bits D (926) efuse: BLK5 REG4 [0-31], len=32 bits D (930) efuse: BLK5 REG5 [0-31], len=32 bits D (934) efuse: BLK5 REG6 [0-31], len=32 bits D (938) efuse: BLK5 REG7 [0-31], len=32 bits D (942) efuse: BLK0 REG3 [0-3], len=4 bits D (946) efuse: BLK0 REG0 [10-10], len=1 bits D (950) efuse: BLK0 REG1 [2-2], len=1 bits D (954) efuse: BLK0 REG0 [25-25], len=1 bits D (958) efuse: BLK6 REG0 [0-31], len=32 bits D (962) efuse: BLK6 REG1 [0-31], len=32 bits D (966) efuse: BLK6 REG2 [0-31], len=32 bits D (970) efuse: BLK6 REG3 [0-31], len=32 bits D (974) efuse: BLK6 REG4 [0-31], len=32 bits D (978) efuse: BLK6 REG5 [0-31], len=32 bits D (982) efuse: BLK6 REG6 [0-31], len=32 bits D (986) efuse: BLK6 REG7 [0-31], len=32 bits D (990) efuse: BLK0 REG3 [4-7], len=4 bits D (993) efuse: BLK0 REG0 [11-11], len=1 bits D (997) efuse: BLK0 REG1 [3-3], len=1 bits D (1001) efuse: BLK0 REG0 [26-26], len=1 bits D (1005) efuse: BLK7 REG0 [0-31], len=32 bits D (1009) efuse: BLK7 REG1 [0-31], len=32 bits D (1013) efuse: BLK7 REG2 [0-31], len=32 bits D (1017) efuse: BLK7 REG3 [0-31], len=32 bits D (1022) efuse: BLK7 REG4 [0-31], len=32 bits D (1026) efuse: BLK7 REG5 [0-31], len=32 bits D (1030) efuse: BLK7 REG6 [0-31], len=32 bits D (1034) efuse: BLK7 REG7 [0-31], len=32 bits D (1038) efuse: BLK0 REG3 [8-11], len=4 bits D (1042) efuse: BLK0 REG0 [12-12], len=1 bits D (1046) efuse: BLK0 REG1 [4-4], len=1 bits D (1050) efuse: BLK0 REG0 [27-27], len=1 bits D (1054) efuse: BLK8 REG0 [0-31], len=32 bits D (1058) efuse: BLK8 REG1 [0-31], len=32 bits D (1062) efuse: BLK8 REG2 [0-31], len=32 bits D (1066) efuse: BLK8 REG3 [0-31], len=32 bits D (1070) efuse: BLK8 REG4 [0-31], len=32 bits D (1074) efuse: BLK8 REG5 [0-31], len=32 bits D (1078) efuse: BLK8 REG6 [0-31], len=32 bits D (1082) efuse: BLK8 REG7 [0-31], len=32 bits D (1087) efuse: BLK0 REG3 [12-15], len=4 bits D (1091) efuse: BLK0 REG0 [13-13], len=1 bits D (1095) efuse: BLK0 REG1 [5-5], len=1 bits D (1099) efuse: BLK0 REG0 [28-28], len=1 bits D (1103) efuse: BLK9 REG0 [0-31], len=32 bits D (1107) efuse: BLK9 REG1 [0-31], len=32 bits D (1111) efuse: BLK9 REG2 [0-31], len=32 bits D (1115) efuse: BLK9 REG3 [0-31], len=32 bits D (1119) efuse: BLK9 REG4 [0-31], len=32 bits D (1123) efuse: BLK9 REG5 [0-31], len=32 bits D (1127) efuse: BLK9 REG6 [0-31], len=32 bits D (1131) efuse: BLK9 REG7 [0-31], len=32 bits D (1135) efuse: BLK0 REG2 [24-27], len=4 bits D (1139) efuse: BLK0 REG0 [8-8], len=1 bits D (1143) efuse: BLK0 REG1 [0-0], len=1 bits D (1147) efuse: BLK0 REG0 [23-23], len=1 bits D (1151) efuse: BLK4 REG0 [0-31], len=32 bits D (1155) efuse: BLK4 REG1 [0-31], len=32 bits D (1159) efuse: BLK4 REG2 [0-31], len=32 bits D (1164) efuse: BLK4 REG3 [0-31], len=32 bits D (1168) efuse: BLK4 REG4 [0-31], len=32 bits D (1172) efuse: BLK4 REG5 [0-31], len=32 bits D (1176) efuse: BLK4 REG6 [0-31], len=32 bits D (1180) efuse: BLK4 REG7 [0-31], len=32 bits I (1184) efuse: Writing EFUSE_BLK_KEY0 with purpose 4 D (1189) efuse: BLK0 REG2 [24-27], len=4 bits D (1193) efuse: BLK0 REG0 [8-8], len=1 bits D (1197) efuse: BLK0 REG1 [0-0], len=1 bits D (1201) efuse: BLK0 REG0 [23-23], len=1 bits D (1205) efuse: BLK4 REG0 [0-31], len=32 bits D (1209) efuse: BLK4 REG1 [0-31], len=32 bits D (1213) efuse: BLK4 REG2 [0-31], len=32 bits D (1217) efuse: BLK4 REG3 [0-31], len=32 bits D (1221) efuse: BLK4 REG4 [0-31], len=32 bits D (1225) efuse: BLK4 REG5 [0-31], len=32 bits D (1229) efuse: BLK4 REG6 [0-31], len=32 bits D (1233) efuse: BLK4 REG7 [0-31], len=32 bits D (1237) efuse: BLK4 REG0 [0-31], len=32 bits D (1241) efuse: BLK4 REG1 [0-31], len=32 bits D (1245) efuse: BLK4 REG2 [0-31], len=32 bits D (1250) efuse: BLK4 REG3 [0-31], len=32 bits D (1254) efuse: BLK4 REG4 [0-31], len=32 bits D (1258) efuse: BLK4 REG5 [0-31], len=32 bits D (1262) efuse: BLK4 REG6 [0-31], len=32 bits D (1266) efuse: BLK4 REG7 [0-31], len=32 bits D (1270) efuse: BLK0 REG0 [23-23], len=1 bits D (1274) efuse: BLK0 REG0 [23-23], len=1 bits D (1278) efuse: BLK0 REG1 [0-0], len=1 bits D (1282) efuse: BLK0 REG1 [0-0], len=1 bits D (1286) efuse: BLK0 REG2 [24-27], len=4 bits D (1290) efuse: BLK0 REG0 [8-8], len=1 bits D (1294) efuse: BLK0 REG0 [8-8], len=1 bits W (1298) flash_encrypt: Not disabling UART bootloader encryption I (1304) flash_encrypt: Disable UART bootloader cache... D (1309) efuse: BLK0 REG1 [10-10], len=1 bits D (1313) efuse: BLK0 REG1 [10-10], len=1 bits I (1317) flash_encrypt: Disable JTAG... D (1320) efuse: BLK0 REG1 [19-19], len=1 bits D (1324) efuse: BLK0 REG1 [19-19], len=1 bits D (1328) efuse: BLK0 REG1 [9-9], len=1 bits D (1332) efuse: BLK0 REG1 [9-9], len=1 bits D (1336) efuse: BLK0 REG4 [1-1], len=1 bits D (1340) efuse: BLK0 REG4 [1-1], len=1 bits I (1345) efuse: BURN BLOCK4 I (1350) efuse: BURN BLOCK4 - OK (write block == read block) I (1352) efuse: BURN BLOCK0 I (1357) efuse: BURN BLOCK0 - OK (all write block bits are set) I (1360) efuse: Batch mode. Prepared fields are committed D (1365) esp_image: reading image header @ 0x0 D (1369) bootloader_flash: mmu set block paddr=0x00000000 (was 0x00100000) D (1376) esp_image: image header: 0xe9 0x03 0x02 0x02 403cc71a V (1382) esp_image: loading segment header 0 at offset 0x18 V (1387) esp_image: segment data length 0x32e8 data starts 0x20 V (1393) esp_image: MMU page size 0x10000 V (1396) esp_image: segment 0 map_segment 0 segment_data_offs 0x20 load_addr 0x3fcd5990 I (1404) esp_image: segment 0: paddr=00000020 vaddr=3fcd5990 size=032e8h ( 13032) D (1411) esp_image: free data page_count 0x00000080 D (1416) bootloader_flash: rodata starts from paddr=0x00000020, size=0x32e8, will be mapped to vaddr=0x3c000000 V (1426) bootloader_flash: after mapping, starting from paddr=0x00000000 and vaddr=0x3c000000, 0x10000 bytes are mapped V (1437) esp_image: loading segment header 1 at offset 0x3308 D (1442) bootloader_flash: mmu set block paddr=0x00000000 (was 0xffffffff) V (1448) esp_image: segment data length 0xcfc data starts 0x3310 V (1454) esp_image: MMU page size 0x10000 V (1458) esp_image: segment 1 map_segment 0 segment_data_offs 0x3310 load_addr 0x403cc710 I (1466) esp_image: segment 1: paddr=00003310 vaddr=403cc710 size=00cfch ( 3324) D (1473) esp_image: free data page_count 0x00000080 D (1477) bootloader_flash: rodata starts from paddr=0x00003310, size=0xcfc, will be mapped to vaddr=0x3c000000 V (1487) bootloader_flash: after mapping, starting from paddr=0x00000000 and vaddr=0x3c000000, 0x10000 bytes are mapped V (1498) esp_image: loading segment header 2 at offset 0x400c D (1503) bootloader_flash: mmu set block paddr=0x00000000 (was 0xffffffff) V (1510) esp_image: segment data length 0x51b8 data starts 0x4014 V (1516) esp_image: MMU page size 0x10000 V (1519) esp_image: segment 2 map_segment 0 segment_data_offs 0x4014 load_addr 0x403ce710 I (1527) esp_image: segment 2: paddr=00004014 vaddr=403ce710 size=051b8h ( 20920) D (1535) esp_image: free data page_count 0x00000080 D (1539) bootloader_flash: rodata starts from paddr=0x00004014, size=0x51b8, will be mapped to vaddr=0x3c000000 V (1549) bootloader_flash: after mapping, starting from paddr=0x00000000 and vaddr=0x3c000000, 0x10000 bytes are mapped V (1561) esp_image: image start 0x00000000 end of last section 0x000091cc D (1566) bootloader_flash: mmu set block paddr=0x00000000 (was 0xffffffff) D (1573) flash_encrypt: bootloader is plaintext. Encrypting... I (2151) flash_encrypt: bootloader encrypted successfully D (2151) flash_parts: partition table verified, 7 entries D (2151) flash_encrypt: partition table is plaintext. Encrypting... I (2205) flash_encrypt: partition table encrypted and loaded successfully I (2206) flash_encrypt: Encrypting partition 1 at offset 0x14000 (length 0x2000)... I (2331) flash_encrypt: Done encrypting D (2331) esp_image: reading image header @ 0x20000 D (2331) bootloader_flash: mmu set block paddr=0x00020000 (was 0x00000000) D (2334) esp_image: image header: 0xe9 0x06 0x02 0x02 403802ea V (2340) esp_image: loading segment header 0 at offset 0x20018 V (2345) esp_image: segment data length 0x1fd24 data starts 0x20020 V (2351) esp_image: MMU page size 0x10000 V (2355) esp_image: segment 0 map_segment 1 segment_data_offs 0x20020 load_addr 0x3c0c0020 I (2363) esp_image: segment 0: paddr=00020020 vaddr=3c0c0020 size=1fd24h (130340) map D (2370) esp_image: free data page_count 0x00000080 D (2375) bootloader_flash: rodata starts from paddr=0x00020020, size=0x1fd24, will be mapped to vaddr=0x3c000000 V (2385) bootloader_flash: after mapping, starting from paddr=0x00020000 and vaddr=0x3c000000, 0x20000 bytes are mapped V (2416) esp_image: loading segment header 1 at offset 0x3fd44 D (2416) bootloader_flash: mmu set block paddr=0x00030000 (was 0xffffffff) V (2417) esp_image: segment data length 0x2cc data starts 0x3fd4c V (2423) esp_image: MMU page size 0x10000 V (2427) esp_image: segment 1 map_segment 0 segment_data_offs 0x3fd4c load_addr 0x3fc93e00 I (2435) esp_image: segment 1: paddr=0003fd4c vaddr=3fc93e00 size=002cch ( 716) D (2442) esp_image: free data page_count 0x00000080 D (2447) bootloader_flash: rodata starts from paddr=0x0003fd4c, size=0x2cc, will be mapped to vaddr=0x3c000000 V (2456) bootloader_flash: after mapping, starting from paddr=0x00030000 and vaddr=0x3c000000, 0x20000 bytes are mapped V (2467) esp_image: loading segment header 2 at offset 0x40018 D (2472) bootloader_flash: mmu set block paddr=0x00040000 (was 0xffffffff) V (2479) esp_image: segment data length 0xb4b94 data starts 0x40020 V (2485) esp_image: MMU page size 0x10000 V (2489) esp_image: segment 2 map_segment 1 segment_data_offs 0x40020 load_addr 0x42000020 --- 0x42000020: esp_app_format_init_elf_sha256 at /Users/francesco/esp/v5.4.2/esp-idf/components/esp_app_format/esp_app_desc.c:88 I (2497) esp_image: segment 2: paddr=00040020 vaddr=42000020 size=b4b94h (740244) map D (2504) esp_image: free data page_count 0x00000080 D (2509) bootloader_flash: rodata starts from paddr=0x00040020, size=0xb4b94, will be mapped to vaddr=0x3c000000 V (2519) bootloader_flash: after mapping, starting from paddr=0x00040000 and vaddr=0x3c000000, 0xc0000 bytes are mapped V (2647) esp_image: loading segment header 3 at offset 0xf4bb4 D (2647) bootloader_flash: mmu set block paddr=0x000f0000 (was 0xffffffff) V (2648) esp_image: segment data length 0x2c24 data starts 0xf4bbc V (2654) esp_image: MMU page size 0x10000 V (2658) esp_image: segment 3 map_segment 0 segment_data_offs 0xf4bbc load_addr 0x3fc940cc I (2666) esp_image: segment 3: paddr=000f4bbc vaddr=3fc940cc size=02c24h ( 11300) D (2673) esp_image: free data page_count 0x00000080 D (2678) bootloader_flash: rodata starts from paddr=0x000f4bbc, size=0x2c24, will be mapped to vaddr=0x3c000000 V (2687) bootloader_flash: after mapping, starting from paddr=0x000f0000 and vaddr=0x3c000000, 0x10000 bytes are mapped V (2700) esp_image: loading segment header 4 at offset 0xf77e0 D (2703) bootloader_flash: mmu set block paddr=0x000f0000 (was 0xffffffff) V (2710) esp_image: segment data length 0x13cc8 data starts 0xf77e8 V (2716) esp_image: MMU page size 0x10000 V (2720) esp_image: segment 4 map_segment 0 segment_data_offs 0xf77e8 load_addr 0x40380000 --- 0x40380000: _vector_table at /Users/francesco/esp/v5.4.2/esp-idf/components/riscv/vectors_intc.S:54 I (2728) esp_image: segment 4: paddr=000f77e8 vaddr=40380000 size=13cc8h ( 81096) D (2735) esp_image: free data page_count 0x00000080 D (2740) bootloader_flash: rodata starts from paddr=0x000f77e8, size=0x13cc8, will be mapped to vaddr=0x3c000000 V (2750) bootloader_flash: after mapping, starting from paddr=0x000f0000 and vaddr=0x3c000000, 0x20000 bytes are mapped V (2773) esp_image: loading segment header 5 at offset 0x10b4b0 D (2773) bootloader_flash: mmu set block paddr=0x00100000 (was 0xffffffff) V (2774) esp_image: segment data length 0x1c data starts 0x10b4b8 V (2780) esp_image: MMU page size 0x10000 V (2784) esp_image: segment 5 map_segment 0 segment_data_offs 0x10b4b8 load_addr 0x50000000 I (2792) esp_image: segment 5: paddr=0010b4b8 vaddr=50000000 size=0001ch ( 28) D (2799) esp_image: free data page_count 0x00000080 D (2804) bootloader_flash: rodata starts from paddr=0x0010b4b8, size=0x1c, will be mapped to vaddr=0x3c000000 V (2813) bootloader_flash: after mapping, starting from paddr=0x00100000 and vaddr=0x3c000000, 0x10000 bytes are mapped V (2824) esp_image: image start 0x00020000 end of last section 0x0010b4d4 D (2830) bootloader_flash: mmu set block paddr=0x00100000 (was 0xffffffff) D (2837) boot: Calculated hash: 95320d19f00e1b0ae9da94d51f205ea7a1731fc9a3252e2a61a665c109798d46 I (2845) flash_encrypt: Encrypting partition 3 at offset 0x20000 (length 0xeb500)... I (16131) flash_encrypt: Done encrypting D (16131) esp_image: reading image header @ 0x120000 D (16131) bootloader_flash: mmu set block paddr=0x00120000 (was 0x00100000) D (16135) esp_image: image header: 0x09 0xe5 0x92 0x04 10ef8522 E (16140) esp_image: image at 0x120000 has invalid magic byte (nothing flashed here?) D (16148) esp_image: reading image header @ 0x220000 D (16153) bootloader_flash: mmu set block paddr=0x00220000 (was 0x00120000) D (16159) esp_image: image header: 0xff 0xff 0xff 0x0f ffffffff E (16165) esp_image: image at 0x220000 has invalid magic byte (nothing flashed here?) D (16172) flash_encrypt: All flash regions checked for encryption pass D (16179) efuse: BLK0 REG0 [4-4], len=1 bits D (16183) efuse: BLK0 REG2 [18-20], len=3 bits D (16187) flash_encrypt: CRYPT_CNT 0 -\u0026gt; 1 D (16191) efuse: BLK0 REG2 [18-20], len=3 bits I (16195) efuse: BURN BLOCK0 I (16200) efuse: BURN BLOCK0 - OK (all write block bits are set) I (16204) flash_encrypt: Flash encryption completed I (16208) boot: Resetting with flash encryption enabled... ESP-ROM:esp32c3-api1-20210207 Build:Feb 7 2021 rst:0x3 (RTC_SW_SYS_RST),boot:0xc (SPI_FAST_FLASH_BOOT) Saved PC:0x40048b82 --- 0x40048b82: ets_secure_boot_verify_bootloader_with_keys in ROM SPIWP:0xee mode:DIO, clock div:1 load:0x3fcd5990,len:0x32e8 load:0x403cc710,len:0xcfc load:0x403ce710,len:0x51b8 entry 0x403cc71a I (31) boot: ESP-IDF v5.4.2-dirty 2nd stage bootloader I (31) boot: compile time Jul 22 2025 09:21:12 D (31) bootloader_flash: XMC chip detected by RDID (00204016), skip. D (35) bootloader_flash: mmu set block paddr=0x00000000 (was 0xffffffff) I (41) boot: chip revision: v0.3 I (44) boot: efuse block revision: v1.1 D (48) boot.esp32c3: magic e9 D (51) boot.esp32c3: segments 03 D (53) boot.esp32c3: spi_mode 02 D (56) boot.esp32c3: spi_speed 0f D (59) boot.esp32c3: spi_size 02 I (62) boot.esp32c3: SPI Speed : 80MHz I (66) boot.esp32c3: SPI Mode : DIO I (70) boot.esp32c3: SPI Flash Size : 4MB D (74) boot: Enabling RTCWDT(9000 ms) I (77) boot: Enabling RNG early entropy source... D (82) bootloader_flash: rodata starts from paddr=0x0000f000, size=0xc00, will be mapped to vaddr=0x3c000000 V (91) bootloader_flash: after mapping, starting from paddr=0x00000000 and vaddr=0x3c000000, 0x10000 bytes are mapped D (101) boot: mapped partition table 0xf000 at 0x3c00f000 D (107) flash_parts: partition table verified, 7 entries I (112) boot: Partition Table: I (114) boot: ## Label Usage Type ST Offset Length D (121) boot: load partition table entry 0x3c00f000 D (125) boot: type=1 subtype=2 I (128) boot: 0 nvs WiFi data 01 02 00010000 00004000 D (135) boot: load partition table entry 0x3c00f020 D (139) boot: type=1 subtype=0 I (142) boot: 1 otadata OTA data 01 00 00014000 00002000 D (149) boot: load partition table entry 0x3c00f040 D (153) boot: type=1 subtype=1 I (156) boot: 2 phy_init RF data 01 01 00016000 00001000 D (163) boot: load partition table entry 0x3c00f060 D (167) boot: type=0 subtype=0 I (170) boot: 3 factory factory app 00 00 00020000 00100000 D (177) boot: load partition table entry 0x3c00f080 D (181) boot: type=0 subtype=10 I (184) boot: 4 ota_0 OTA app 00 10 00120000 00100000 D (191) boot: load partition table entry 0x3c00f0a0 D (195) boot: type=0 subtype=11 I (198) boot: 5 ota_1 OTA app 00 11 00220000 00100000 I (205) boot: End of partition table D (208) boot: OTA data offset 0x14000 D (212) bootloader_flash: rodata starts from paddr=0x00014000, size=0x2000, will be mapped to vaddr=0x3c000000 V (221) bootloader_flash: after mapping, starting from paddr=0x00010000 and vaddr=0x3c000000, 0x10000 bytes are mapped D (232) boot: otadata[0]: sequence values 0xffffffff D (236) boot: otadata[1]: sequence values 0xffffffff D (241) boot: OTA sequence numbers both empty (all-0xFF) or partition table does not have bootable ota_apps (app_count=2) I (252) boot: Defaulting to factory image D (255) boot: Trying partition index -1 offs 0x20000 size 0x100000 D (261) esp_image: reading image header @ 0x20000 D (266) bootloader_flash: mmu set block paddr=0x00020000 (was 0xffffffff) D (272) esp_image: image header: 0xe9 0x06 0x02 0x02 403802ea V (278) esp_image: loading segment header 0 at offset 0x20018 V (283) esp_image: segment data length 0x1fd24 data starts 0x20020 V (289) esp_image: MMU page size 0x10000 V (293) esp_image: segment 0 map_segment 1 segment_data_offs 0x20020 load_addr 0x3c0c0020 I (301) esp_image: segment 0: paddr=00020020 vaddr=3c0c0020 size=1fd24h (130340) map D (308) esp_image: free data page_count 0x00000080 D (313) bootloader_flash: rodata starts from paddr=0x00020020, size=0x1fd24, will be mapped to vaddr=0x3c000000 V (322) bootloader_flash: after mapping, starting from paddr=0x00020000 and vaddr=0x3c000000, 0x20000 bytes are mapped V (356) esp_image: loading segment header 1 at offset 0x3fd44 D (356) bootloader_flash: mmu set block paddr=0x00030000 (was 0xffffffff) V (357) esp_image: segment data length 0x2cc data starts 0x3fd4c V (362) esp_image: MMU page size 0x10000 V (366) esp_image: segment 1 map_segment 0 segment_data_offs 0x3fd4c load_addr 0x3fc93e00 I (374) esp_image: segment 1: paddr=0003fd4c vaddr=3fc93e00 size=002cch ( 716) load D (382) esp_image: free data page_count 0x00000080 D (386) bootloader_flash: rodata starts from paddr=0x0003fd4c, size=0x2cc, will be mapped to vaddr=0x3c000000 V (396) bootloader_flash: after mapping, starting from paddr=0x00030000 and vaddr=0x3c000000, 0x20000 bytes are mapped V (406) esp_image: loading segment header 2 at offset 0x40018 D (412) bootloader_flash: mmu set block paddr=0x00040000 (was 0xffffffff) V (418) esp_image: segment data length 0xb4b94 data starts 0x40020 V (424) esp_image: MMU page size 0x10000 V (428) esp_image: segment 2 map_segment 1 segment_data_offs 0x40020 load_addr 0x42000020 --- 0x42000020: esp_app_format_init_elf_sha256 at /Users/francesco/esp/v5.4.2/esp-idf/components/esp_app_format/esp_app_desc.c:88 I (436) esp_image: segment 2: paddr=00040020 vaddr=42000020 size=b4b94h (740244) map D (443) esp_image: free data page_count 0x00000080 D (447) bootloader_flash: rodata starts from paddr=0x00040020, size=0xb4b94, will be mapped to vaddr=0x3c000000 V (457) bootloader_flash: after mapping, starting from paddr=0x00040000 and vaddr=0x3c000000, 0xc0000 bytes are mapped V (598) esp_image: loading segment header 3 at offset 0xf4bb4 D (598) bootloader_flash: mmu set block paddr=0x000f0000 (was 0xffffffff) V (599) esp_image: segment data length 0x2c24 data starts 0xf4bbc V (604) esp_image: MMU page size 0x10000 V (608) esp_image: segment 3 map_segment 0 segment_data_offs 0xf4bbc load_addr 0x3fc940cc I (616) esp_image: segment 3: paddr=000f4bbc vaddr=3fc940cc size=02c24h ( 11300) load D (623) esp_image: free data page_count 0x00000080 D (628) bootloader_flash: rodata starts from paddr=0x000f4bbc, size=0x2c24, will be mapped to vaddr=0x3c000000 V (638) bootloader_flash: after mapping, starting from paddr=0x000f0000 and vaddr=0x3c000000, 0x10000 bytes are mapped V (650) esp_image: loading segment header 4 at offset 0xf77e0 D (654) bootloader_flash: mmu set block paddr=0x000f0000 (was 0xffffffff) V (660) esp_image: segment data length 0x13cc8 data starts 0xf77e8 V (666) esp_image: MMU page size 0x10000 V (670) esp_image: segment 4 map_segment 0 segment_data_offs 0xf77e8 load_addr 0x40380000 --- 0x40380000: _vector_table at /Users/francesco/esp/v5.4.2/esp-idf/components/riscv/vectors_intc.S:54 I (678) esp_image: segment 4: paddr=000f77e8 vaddr=40380000 size=13cc8h ( 81096) load D (685) esp_image: free data page_count 0x00000080 D (690) bootloader_flash: rodata starts from paddr=0x000f77e8, size=0x13cc8, will be mapped to vaddr=0x3c000000 V (699) bootloader_flash: after mapping, starting from paddr=0x000f0000 and vaddr=0x3c000000, 0x20000 bytes are mapped V (727) esp_image: loading segment header 5 at offset 0x10b4b0 D (727) bootloader_flash: mmu set block paddr=0x00100000 (was 0xffffffff) V (727) esp_image: segment data length 0x1c data starts 0x10b4b8 V (733) esp_image: MMU page size 0x10000 V (737) esp_image: segment 5 map_segment 0 segment_data_offs 0x10b4b8 load_addr 0x50000000 I (745) esp_image: segment 5: paddr=0010b4b8 vaddr=50000000 size=0001ch ( 28) load D (752) esp_image: free data page_count 0x00000080 D (757) bootloader_flash: rodata starts from paddr=0x0010b4b8, size=0x1c, will be mapped to vaddr=0x3c000000 V (766) bootloader_flash: after mapping, starting from paddr=0x00100000 and vaddr=0x3c000000, 0x10000 bytes are mapped V (777) esp_image: image start 0x00020000 end of last section 0x0010b4d4 D (783) bootloader_flash: mmu set block paddr=0x00100000 (was 0xffffffff) D (790) boot: Calculated hash: 95320d19f00e1b0ae9da94d51f205ea7a1731fc9a3252e2a61a665c109798d46 I (804) boot: Loaded app from partition at offset 0x20000 I (804) boot: Checking flash encryption... D (807) efuse: BLK0 REG2 [18-20], len=3 bits D (811) efuse: BLK0 REG0 [4-4], len=1 bits V (815) flash_encrypt: CRYPT_CNT 1, write protection 0 I (820) flash_encrypt: flash encryption is enabled (1 plaintext flashes left) I (827) boot: Disabling RNG early entropy source... D (831) boot: Mapping segment 0 as DROM D (835) boot: Mapping segment 2 as IROM D (838) boot: calling set_cache_and_start_app D (842) boot: configure drom and irom and start V (847) boot: rodata starts from paddr=0x00020020, vaddr=0x3c0c0020, size=0x1fd24 V (854) boot: after mapping rodata, starting from paddr=0x00020000 and vaddr=0x3c0c0000, 0x20000 bytes are mapped V (864) boot: mapped one page of the rodata, from paddr=0x00020000 and vaddr=0x3c7f0000, 0x10000 bytes are mapped V (874) boot: text starts from paddr=0x00040020, vaddr=0x42000020, size=0xb4b94 --- 0x42000020: esp_app_format_init_elf_sha256 at /Users/francesco/esp/v5.4.2/esp-idf/components/esp_app_format/esp_app_desc.c:88 V (881) boot: after mapping text, starting from paddr=0x00040000 and vaddr=0x42000000, 0xc0000 bytes are mapped D (891) boot: start: 0x403802ea --- 0x403802ea: call_start_cpu0 at /Users/francesco/esp/v5.4.2/esp-idf/components/esp_system/port/cpu_start.c:387 You need to do the last two steps.\nClick the reset button on your device Flash the project again: \u0026gt; ESP-IDF: Flash (UART) Your Project Check the device encryption status # Open an ESP-IDF terminal : \u0026gt; ESP-IDF: Open ESP-IDF Terminal Inside the terminal, run idf.py efuse-summary Show eFuses summary espefuse.py v4.9.0 Connecting... === Run \u0026#34;summary\u0026#34; command === EFUSE_NAME (Block) Description = [Meaningful Value] [Readable/Writeable] (Hex Value) ---------------------------------------------------------------------------------------- Calibration fuses: K_RTC_LDO (BLOCK1) BLOCK1 K_RTC_LDO = 96 R/W (0b0011000) K_DIG_LDO (BLOCK1) BLOCK1 K_DIG_LDO = 20 R/W (0b0000101) V_RTC_DBIAS20 (BLOCK1) BLOCK1 voltage of rtc dbias20 = 172 R/W (0x2b) V_DIG_DBIAS20 (BLOCK1) BLOCK1 voltage of digital dbias20 = 32 R/W (0x08) DIG_DBIAS_HVT (BLOCK1) BLOCK1 digital dbias when hvt = -12 R/W (0b10011) THRES_HVT (BLOCK1) BLOCK1 pvt threshold when hvt = 1600 R/W (0b0110010000) TEMP_CALIB (BLOCK2) Temperature calibration data = -9.0 R/W (0b101011010) OCODE (BLOCK2) ADC OCode = 96 R/W (0x60) ADC1_INIT_CODE_ATTEN0 (BLOCK2) ADC1 init code at atten0 = 1736 R/W (0b0110110010) ADC1_INIT_CODE_ATTEN1 (BLOCK2) ADC1 init code at atten1 = -272 R/W (0b1001000100) ADC1_INIT_CODE_ATTEN2 (BLOCK2) ADC1 init code at atten2 = -368 R/W (0b1001011100) ADC1_INIT_CODE_ATTEN3 (BLOCK2) ADC1 init code at atten3 = -824 R/W (0b1011001110) ADC1_CAL_VOL_ATTEN0 (BLOCK2) ADC1 calibration voltage at atten0 = -204 R/W (0b1000110011) ADC1_CAL_VOL_ATTEN1 (BLOCK2) ADC1 calibration voltage at atten1 = -4 R/W (0b1000000001) ADC1_CAL_VOL_ATTEN2 (BLOCK2) ADC1 calibration voltage at atten2 = -160 R/W (0b1000101000) ADC1_CAL_VOL_ATTEN3 (BLOCK2) ADC1 calibration voltage at atten3 = -332 R/W (0b1001010011) Config fuses: WR_DIS (BLOCK0) Disable programming of individual eFuses = 8388864 R/W (0x00800100) RD_DIS (BLOCK0) Disable reading from BlOCK4-10 = 1 R/W (0b0000001) DIS_ICACHE (BLOCK0) Set this bit to disable Icache = False R/W (0b0) DIS_TWAI (BLOCK0) Set this bit to disable CAN function = False R/W (0b0) DIS_DIRECT_BOOT (BLOCK0) Disable direct boot mode = True R/W (0b1) UART_PRINT_CONTROL (BLOCK0) Set the default UARTboot message output mode = Enable when GPIO8 is high at reset R/W (0b10) ERR_RST_ENABLE (BLOCK0) Use BLOCK0 to check error record registers = without check R/W (0b0) BLOCK_USR_DATA (BLOCK3) User data = 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 R/W BLOCK_SYS_DATA2 (BLOCK10) System data part 2 (reserved) = 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 R/W Flash fuses: FLASH_TPUW (BLOCK0) Configures flash waiting time after power-up; in u = 0 R/W (0x0) nit of ms. If the value is less than 15; the waiti ng time is the configurable value; Otherwise; the waiting time is twice the configurable value FORCE_SEND_RESUME (BLOCK0) Set this bit to force ROM code to send a resume co = False R/W (0b0) mmand during SPI boot FLASH_CAP (BLOCK1) Flash capacity = 4M R/W (0b001) FLASH_TEMP (BLOCK1) Flash temperature = 105C R/W (0b01) FLASH_VENDOR (BLOCK1) Flash vendor = XMC R/W (0b001) Identity fuses: DISABLE_WAFER_VERSION_MAJOR (BLOCK0) Disables check of wafer version major = False R/W (0b0) DISABLE_BLK_VERSION_MAJOR (BLOCK0) Disables check of blk version major = False R/W (0b0) WAFER_VERSION_MINOR_LO (BLOCK1) WAFER_VERSION_MINOR least significant bits = 3 R/W (0b011) PKG_VERSION (BLOCK1) Package version = 0 R/W (0b000) BLK_VERSION_MINOR (BLOCK1) BLK_VERSION_MINOR = 1 R/W (0b001) WAFER_VERSION_MINOR_HI (BLOCK1) WAFER_VERSION_MINOR most significant bit = False R/W (0b0) WAFER_VERSION_MAJOR (BLOCK1) WAFER_VERSION_MAJOR = 0 R/W (0b00) OPTIONAL_UNIQUE_ID (BLOCK2) Optional unique 128-bit ID = 7c c7 9b 3a 4c 1f e1 be 56 79 19 20 4f ff cd 0e R/W BLK_VERSION_MAJOR (BLOCK2) BLK_VERSION_MAJOR of BLOCK2 = With calibration R/W (0b01) WAFER_VERSION_MINOR (BLOCK0) calc WAFER VERSION MINOR = WAFER_VERSION_MINOR_HI = 3 R/W (0x3) \u0026lt;\u0026lt; 3 + WAFER_VERSION_MINOR_LO (read only) Jtag fuses: SOFT_DIS_JTAG (BLOCK0) Set these bits to disable JTAG in the soft way (od = 0 R/W (0b000) d number 1 means disable ). JTAG can be enabled in HMAC module DIS_PAD_JTAG (BLOCK0) Set this bit to disable JTAG in the hard way. JTAG = True R/W (0b1) is disabled permanently Mac fuses: MAC (BLOCK1) MAC address = 84:f7:03:42:8c:a8 (OK) R/W CUSTOM_MAC (BLOCK3) Custom MAC address = 00:00:00:00:00:00 (OK) R/W Security fuses: DIS_DOWNLOAD_ICACHE (BLOCK0) Set this bit to disable Icache in download mode (b = True R/W (0b1) oot_mode[3:0] is 0; 1; 2; 3; 6; 7) DIS_FORCE_DOWNLOAD (BLOCK0) Set this bit to disable the function that forces c = False R/W (0b0) hip into download mode DIS_DOWNLOAD_MANUAL_ENCRYPT (BLOCK0) Set this bit to disable flash encryption when in d = False R/W (0b0) ownload boot modes SPI_BOOT_CRYPT_CNT (BLOCK0) Enables flash encryption when 1 or 3 bits are set = Enable R/W (0b001) and disables otherwise SECURE_BOOT_KEY_REVOKE0 (BLOCK0) Revoke 1st secure boot key = False R/W (0b0) SECURE_BOOT_KEY_REVOKE1 (BLOCK0) Revoke 2nd secure boot key = False R/W (0b0) SECURE_BOOT_KEY_REVOKE2 (BLOCK0) Revoke 3rd secure boot key = False R/W (0b0) KEY_PURPOSE_0 (BLOCK0) Purpose of Key0 = XTS_AES_128_KEY R/- (0x4) KEY_PURPOSE_1 (BLOCK0) Purpose of Key1 = USER R/W (0x0) KEY_PURPOSE_2 (BLOCK0) Purpose of Key2 = USER R/W (0x0) KEY_PURPOSE_3 (BLOCK0) Purpose of Key3 = USER R/W (0x0) KEY_PURPOSE_4 (BLOCK0) Purpose of Key4 = USER R/W (0x0) KEY_PURPOSE_5 (BLOCK0) Purpose of Key5 = USER R/W (0x0) SECURE_BOOT_EN (BLOCK0) Set this bit to enable secure boot = False R/W (0b0) SECURE_BOOT_AGGRESSIVE_REVOKE (BLOCK0) Set this bit to enable revoking aggressive secure = False R/W (0b0) boot DIS_DOWNLOAD_MODE (BLOCK0) Set this bit to disable download mode (boot_mode[3 = False R/W (0b0) :0] = 0; 1; 2; 3; 6; 7) ENABLE_SECURITY_DOWNLOAD (BLOCK0) Set this bit to enable secure UART download mode = False R/W (0b0) SECURE_VERSION (BLOCK0) Secure version (used by ESP-IDF anti-rollback feat = 0 R/W (0x0000) ure) BLOCK_KEY0 (BLOCK4) Purpose: XTS_AES_128_KEY Key0 or user data = ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? -/- BLOCK_KEY1 (BLOCK5) Purpose: USER Key1 or user data = 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 R/W BLOCK_KEY2 (BLOCK6) Purpose: USER Key2 or user data = 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 R/W BLOCK_KEY3 (BLOCK7) Purpose: USER Key3 or user data = 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 R/W BLOCK_KEY4 (BLOCK8) Purpose: USER Key4 or user data = 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 R/W BLOCK_KEY5 (BLOCK9) Purpose: USER Key5 or user data = 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 R/W Spi Pad fuses: SPI_PAD_CONFIG_CLK (BLOCK1) SPI PAD CLK = 0 R/W (0b000000) SPI_PAD_CONFIG_Q (BLOCK1) SPI PAD Q(D1) = 0 R/W (0b000000) SPI_PAD_CONFIG_D (BLOCK1) SPI PAD D(D0) = 0 R/W (0b000000) SPI_PAD_CONFIG_CS (BLOCK1) SPI PAD CS = 0 R/W (0b000000) SPI_PAD_CONFIG_HD (BLOCK1) SPI PAD HD(D3) = 0 R/W (0b000000) SPI_PAD_CONFIG_WP (BLOCK1) SPI PAD WP(D2) = 0 R/W (0b000000) SPI_PAD_CONFIG_DQS (BLOCK1) SPI PAD DQS = 0 R/W (0b000000) SPI_PAD_CONFIG_D4 (BLOCK1) SPI PAD D4 = 0 R/W (0b000000) SPI_PAD_CONFIG_D5 (BLOCK1) SPI PAD D5 = 0 R/W (0b000000) SPI_PAD_CONFIG_D6 (BLOCK1) SPI PAD D6 = 0 R/W (0b000000) SPI_PAD_CONFIG_D7 (BLOCK1) SPI PAD D7 = 0 R/W (0b000000) Usb fuses: DIS_USB_JTAG (BLOCK0) Set this bit to disable function of usb switch to = True R/W (0b1) jtag in module of usb device DIS_USB_SERIAL_JTAG (BLOCK0) USB-Serial-JTAG = Enable R/W (0b0) USB_EXCHG_PINS (BLOCK0) Set this bit to exchange USB D+ and D- pins = False R/W (0b0) DIS_USB_SERIAL_JTAG_ROM_PRINT (BLOCK0) USB printing = Enable R/W (0b0) DIS_USB_SERIAL_JTAG_DOWNLOAD_MODE (BLOCK0) Disable UART download mode through USB-Serial-JTAG = False R/W (0b0) Vdd fuses: VDD_SPI_AS_GPIO (BLOCK0) Set this bit to vdd spi pin function as gpio = False R/W (0b0) Wdt fuses: WDT_DELAY_SEL (BLOCK0) RTC watchdog timeout threshold; in unit of slow cl = 40000 R/W (0b00) ock cycle You should spot the following differences:\n[...] WR_DIS (BLOCK0) Disable programming of individual eFuses = 8388864 R/W (0x00800100) RD_DIS (BLOCK0) Disable reading from BlOCK4-10 = 1 R/W (0b0000001) [...] DIS_DIRECT_BOOT (BLOCK0) Disable direct boot mode = True R/W (0b1) [...] DIS_PAD_JTAG (BLOCK0) Set this bit to disable JTAG in the hard way. JTAG = True R/W (0b1) [...] DIS_DOWNLOAD_ICACHE (BLOCK0) Set this bit to disable Icache in download mode (b = True R/W (0b1)) [...] SPI_BOOT_CRYPT_CNT (BLOCK0) Enables flash encryption when 1 or 3 bits are set = Enable R/W (0b001) [...] KEY_PURPOSE_0 (BLOCK0) Purpose of Key0 = XTS_AES_128_KEY R/- (0x4) [...] BLOCK_KEY0 (BLOCK4) Purpose: XTS_AES_128_KEY Key0 or user data = ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? -/- [...] DIS_USB_JTAG (BLOCK0) Set this bit to disable function of usb switch to = True R/W (0b1) We can see that:\nThe flash encryption is set (SPI_BOOT_CRYPT_CNT). One of the eFuse blocks has been reserved to store the encryption key. Now your device has flash encryption. Since we selected the development, you can still reflash it using the serial port.\nConclusion # In this assignment, we added flash encryption to the project by enabling the appropriate options in the menuconfig and by accommodating the partition table offset as required.\nNext step: Conclusion\n","date":"5 August 2025","externalUrl":null,"permalink":"/workshops/esp-idf-advanced/assignment-4-3/","section":"Workshops","summary":"","title":"ESP-IDF Adv. - Assign.  4.3","type":"workshops"},{"content":" Introduction # In this lecture, we will explore ESP-IDF build system.\nThe ESP-IDF build system is built on top of CMake and Ninja, two powerful tools that make project configuration and compilation fast and efficient. CMake is responsible for setting up your project and generating the necessary build files, while Ninja handles the actual building process with speed and minimal overhead.\nTo simplify development, ESP-IDF provides a command-line tool called idf.py. This tool acts as a front-end to CMake and Ninja, managing project setup, building, and flashing the firmware to your device using esptool.py. It also gives you access to a configuration menu where you can customize your project\u0026rsquo;s settings, which are saved in a single sdkconfig file. IDEs like VSCode and Espressif IDE (Eclipse) usually offer wrappers around the idf.py tool.\nIn this workshop we will use the VSCode plugin.\nModular development # To streamline the development of layered code, ESP-IDF offers a components system, paired with a powerful component manager.\nESP-IDF Components # In ESP-IDF, projects are organized into components \u0026mdash; self-contained, modular blocks of code that provide specific functionality such as drivers, libraries, protocols, utilities, or application logic. This structure simplifies code reuse, organization, and maintenance across complex applications.\nFor example, interfacing with a sensor can be handled by a dedicated component that encapsulates all communication and data processing logic, eliminating the need to rewrite code in every project.\nThe ESP-IDF framework itself is kept separate from your project and is referenced using the IDF_PATH environment variable. To build and flash your code, you’ll need the appropriate toolchain installed and accessible via your system’s PATH.\nA typical component includes:\nSource code Header files CMakeLists.txt file for build configuration idf_component.yml file that describes dependencies and version information This structure allows components to be easily integrated and managed within ESP-IDF projects, supporting modular development and code sharing Component Management and Usage.\nComponent manager # The IDF Component Manager is a tool designed to simplify the management of components in ESP-IDF projects. It allows developers to:\nAdd components as dependencies to projects. Automatically download and update components from the ESP Component Registry or from git repositories. Manage component versions and dependencies reliably. When you build your project, the Component Manager fetches all required components and places them in a managed_components folder, ensuring your project has everything it needs to compile and run. This streamlines the process of extending project functionality and encourages code reuse within the Espressif developer community.\nBoard Support Packages (BSP) in ESP-IDF # One kind of ESP-IDF component is the Board Support Package (BSP), a versioned component that encapsulates hardware initialization for a specific development board. BSPs provide pre-configured drivers and a consistent API for accessing onboard peripherals such as LEDs, buttons, displays, touch panels, audio codecs, and SD cards. Like any ESP-IDF component, a BSP can be integrated into a project via the component manager using idf_component.yml.\nOn a basic board like the ESP32-C6-DevKit, the BSP abstracts setup for components like the onboard button and addressable LED. On more complex platforms (e.g., ESP32-S3-BOX-3), it includes initialization for multiple peripherals such as displays and audio devices—packaged as a single, reusable component.\nThe main reasons for using a BSP are:\nPeripheral initialization: BSPs handle low-level setup (GPIOs, I2C, SPI, etc.) for supported hardware. Reusable abstraction: They expose a common API, enabling code reuse across different projects or board variants. Faster bring-up: With peripherals already configured, application logic can be developed and tested faster and more efficiently. Custom and Generic BSPs # For unsupported or custom boards, developers can use generic BSPs (e.g., esp_bsp_generic, esp_bsp_devkit) and adjust hardware mappings via menuconfig. This allows BSPs to act as a flexible hardware abstraction layer for both official and custom hardware designs.\nHow to create a component # Let\u0026rsquo;s see how to create a component led_toggle starting from the hello_world example.\nAfter you create a project from the example hello_world, your project folder will be as follows:\n. ├── CMakeLists.txt ├── main │ ├── CMakeLists.txt │ └── hello_world_main.c ├── pytest_hello_world.py ├── README.md ├── sdkconfig ├── sdkconfig.ci └── sdkconfig.old To create a component, press F1 to enter the Command palette and type:\n\u0026gt; ESP-IDF: Create a new ESP-IDF Component\n→ led_toggle Now the folder tree changed to\n. ├── CMakeLists.txt ├── components # \u0026lt;--- new folder │ └── led_toggle │ ├── CMakeLists.txt │ ├── include │ │ └── led_toggle.h │ └── led_toggle.c ├── main │ ├── CMakeLists.txt │ └── hello_world_main.c ├── pytest_hello_world.py ├── README.md ├── sdkconfig ├── sdkconfig.ci └── sdkconfig.old As you can see, a new components folder has been created and inside of it you can find the led_toggle component folder.\nA component folder contains:\nCMakeLists.txt: configuration used by the build system include folder: which contains the headers (automatically passed to the linker) .c file: the actual component code You need to perform a full clean to see newly added components. In VSCode, run:\n\u0026gt; ESP-IDF: Full Clean Project. Let\u0026rsquo;s assume you have the following component header file:\n// led_toggle.h #include \u0026#34;driver/gpio.h\u0026#34; typedef struct { int gpio_nr; bool status; }led_gpio_t; esp_err_t config_led(led_gpio_t * led_gpio); esp_err_t drive_led(led_gpio_t * led_gpio); esp_err_t toggle_led(led_gpio_t * led_gpio); After a full clean, you can simply include it in your main file and call its functions:\n#include \u0026#34;led_toggle.h\u0026#34; //[...] void app_main(void) { printf(\u0026#34;Hello world!\\n\u0026#34;); led_gpio_t led_board = { .gpio_nr = 5, .status = true }; config_led(led_board) drive_led(led_board) } Managing Configuration in ESP-IDF Projects # ESP-IDF projects handle configuration management primarily through two key files: sdkconfig and sdkconfig.defaults.\nsdkconfig contains the active configuration for your project. It is automatically generated and updated by configuration tools such as idf.py menuconfig, capturing all selected options. sdkconfig.defaults provides a set of default values for configuration options. It\u0026rsquo;s especially useful for setting up consistent initial configurations for new builds or different environments (e.g., development, testing, production). You can generate a sdkconfig.defaults file that reflects your current configuration using the following VSCode command (in the command palette):\n\u0026gt; ESP-IDF: Save Default SDKCONFIG File (save-defconfig) Which is a wrapper around:\nidf.py save-defconfig This command saves all configuration values that differ from the ESP-IDF defaults into sdkconfig.defaults.\nPerformance Optimization # Build configurations can also play a key role in optimizing system performance. The default settings in ESP-IDF represent a balanced compromise between performance, resource usage, and feature availability.\nFor production systems, designers often have specific optimization goals, e.g. reducing memory usage, increasing speed, or minimizing power consumption. These goals can be achieved by selecting and tuning the appropriate configuration options.\nTo assist with this, the official documentation provides a helpful Performance Optimization Guide, which outlines strategies and configuration tips to help you reach your performance targets effectively.\nUsing Multiple Default Files and Target-Specific Defaults # ESP-IDF supports multiple defaults files (skconfig.xxx), which can be specified via the SDKCONFIG_DEFAULTS environment variable or within your project\u0026rsquo;s CMakeLists.txt. These files are listed using semicolons as separators and are applied in order. If there are overlapping configuration keys, the values in earlier files are overridden by those in the following ones. This layered approach allows you to:\nMaintain shared settings in one file Override them with environment-specific or product-specific defaults in others You can also define target-specific defaults using files named sdkconfig.defaults.\u0026lt;chip\u0026gt;, such as sdkconfig.defaults.esp32s3. These are only considered if a generic sdkconfig.defaults file exists (even if it’s empty). This mechanism supports fine-grained control over configurations for different Espressif chip variants within the same project.\nManaging Build Scenarios with Profile Files # Profile files allow you to encapsulate build settings for specific scenarios (e.g., development, debugging, production) into reusable files. These profiles contain idf.py command-line arguments and can streamline the build process by eliminating repetitive flag specification.\nFor example:\nprofiles/prod – for production builds profiles/debug – for debugging builds To build using a profile:\nidf.py @profiles/prod build You can also combine profile files with additional command-line arguments for even more flexibility. This approach promotes consistency and simplifies switching between build environments. For more details, see the ESP-IDF multi-config example.\nThe VSCode ESP-IDF extension lets you define multiple configurations via JSON file. It\u0026rsquo;s planned to unify this approach with the CLI one in the near future. You can check the detail in the documentation. Practical Example: Isolating Development and Production Builds # To maintain separate configurations for development and production:\nCreate a sdkconfig.defaults file for development.\nCreate production-specific files, such as sdkconfig.prod_common and sdkconfig.prod1.\nBuild with the production configuration using:\nidf.py -B build_prod1 -D SDKCONFIG_DEFAULTS=\u0026#34;sdkconfig.prod_common;sdkconfig.prod1\u0026#34; build This creates an isolated build directory (build_prod1) and applies the specified default configuration layers. As a result, you can maintain reproducible and isolated builds across different environments.\nBy effectively leveraging sdkconfig.defaults, multiple defaults files, and profile-based builds, ESP-IDF projects can achieve greater configurability, repeatability, and clarity across various development scenarios.\nWe will explore this topic more in-depth in the assignment 1.3.\nConclusion # The ESP-IDF build system provides a powerful foundation for developing embedded applications. With modular components, managed dependencies, and support for reusable Board Support Packages (BSPs), developers can build scalable and maintainable projects. Tools like idf.py, the Component Manager, and profile-based build configurations streamline both development and deployment workflows. By mastering these tools and practices, you\u0026rsquo;ll be well-equipped to create robust firmware across a variety of hardware platforms and development scenarios.\nNext Step: assignment_1_1\nAdditional information # What is the ESP Component Registry? IDF Component Manager and ESP Component Registry Documentation ","date":"5 August 2025","externalUrl":null,"permalink":"/workshops/esp-idf-advanced/lecture-1/","section":"Workshops","summary":"In this lecture, we explore the ESP-IDF build system, built on CMake and Ninja. We focus on modular components, the Component Manager, and Board Support Packages (BSPs) for hardware abstraction. We also cover how to create custom components and manage configurations using sdkconfig files and build profiles, enabling flexible and reproducible builds.","title":"ESP-IDF Adv. - Lecture 1","type":"workshops"},{"content":" Introduction # Managing asynchronous events—such as Wi-Fi connectivity, timers, or custom application signals—can be challenging in embedded systems. Espressif\u0026rsquo;s ESP-IDF addresses this complexity through its event loop library, which allows components to define events and register handlers that respond when those events occur. This model encourages loose coupling between components and promotes a clean, event-driven programming style by deferring execution to a dedicated context rather than handling events directly in interrupt service routines or application threads.\nWhen are event loop useful # Event loops are essential when handling asynchronous events in a modular and structured manner. Consider a scenario where a Wi-Fi connection is established: different components—such as a logger, a UI module, and a network service—may each need to respond to this event. The event loop allows each component to independently register a handler, and ensures all handlers are executed in the order they were registered.\nThis approach reduces tight coupling and eliminates the need for complex interdependencies between components. As a result, applications become more modular, scalable, and easier to maintain.\nEvent loops are especially useful in situations where multiple components need to react to the same event independently—for example, networking, sensor data processing, or inter-task communication. This approach simplifies coordination and improves maintainability across the system.\nEvents and Callback Functions # The event loop revolves around two key concepts:\nEvents Callback functions In simple terms, when a registered event is triggered (or posted), the event loop invokes the corresponding callback function. To make this work, you must register both the event and its associated callback with the event loop.\nSimplified event loop block diagram\nSince many events can be logically grouped—for example, all events related to Wi-Fi or MQTT—they are categorized using two identifiers:\nAn event base, which defines the group. An event ID, which identifies the specific event within that group. For instance, Wi-Fi-related events fall under the event base WIFI_EVENT. Specific event IDs within this base include WIFI_EVENT_STA_START and WIFI_EVENT_STA_DISCONNECTED.\nDefault event loop # ESP-IDF automatically creates and manages a default event loop for core system events—such as Wi-Fi, IP configuration, and Bluetooth. This default loop is internal, and its handle is abstracted away from the user. System components post events to this loop, and application code can register handlers to process them.\nFor many use cases, the default event loop is sufficient and avoids the overhead of creating a custom loop. Developers can also post their own application events to the default event loop, making it an efficient option when memory usage is a concern. You can read more about the difference between default event loop and user event loop on the documentation.\nCode Snippets # Defining an event # The following code snippet demonstrates how to define an event base and event IDs using the ESP-IDF macros\n// In your header file (e.g., my_events.h) #include \u0026#34;esp_event.h\u0026#34; ESP_EVENT_DECLARE_BASE(MY_EVENT_BASE); typedef enum { MY_EVENT_ID_1, MY_EVENT_ID_2, MY_EVENT_ID_3, } my_event_id_t; // In your source file (e.g., my_events.c) #include \u0026#34;my_events.h\u0026#34; ESP_EVENT_DEFINE_BASE(MY_EVENT_BASE); This approach uses ESP_EVENT_DECLARE_BASE() to declare the event base in a header file and ESP_EVENT_DEFINE_BASE() to define it in a source file. Event IDs are typically declared as an enumeration for clarity and maintainability. This pattern is recommended across ESP-IDF for all supported chips.\nThese macros just create global variables. We can take a look to their code to understand what they do:\n// Defines for declaring and defining event base #define ESP_EVENT_DECLARE_BASE(id) extern esp_event_base_t const id #define ESP_EVENT_DEFINE_BASE(id) esp_event_base_t const id = #id Defining and Registering an Event Handler # The following example shows how to define a handler and register it to the default event loop for a specific event:\n// Define the event handler void run_on_event(void* handler_arg, esp_event_base_t base, int32_t id, void* event_data) { // Event handler logic } // Register the handler to the default event loop esp_event_handler_register(MY_EVENT_BASE, MY_EVENT_ID, \u0026amp;run_on_event, NULL); Posting an Event to the Default Event Loop # To trigger an event from within your application, you can post to the default event loop like this:\n// Post an event to the default event loop esp_event_post(MY_EVENT_BASE, MY_EVENT_ID, \u0026amp;event_data, sizeof(event_data), portMAX_DELAY); Creating and Using a User Event Loop # In more advanced scenarios, you might want to create a dedicated event loop. Here\u0026rsquo;s how:\nesp_event_loop_handle_t user_loop; esp_event_loop_args_t loop_args = { .queue_size = 5, .task_name = \u0026#34;user_event_task\u0026#34;, // Set to NULL to avoid creating a dedicated task .task_priority = uxTaskPriorityGet(NULL), .task_stack_size = 2048, .task_core_id = tskNO_AFFINITY }; // Create the user event loop esp_event_loop_create(\u0026amp;loop_args, \u0026amp;user_loop); // Register a handler with the custom event loop esp_event_handler_register_with(user_loop, MY_EVENT_BASE, MY_EVENT_ID, \u0026amp;run_on_event, NULL); // Post an event to the custom loop esp_event_post_to(user_loop, MY_EVENT_BASE, MY_EVENT_ID, \u0026amp;event_data, sizeof(event_data), portMAX_DELAY); Conclusion # The event loop mechanism in Espressif\u0026rsquo;s ESP-IDF framework offers a powerful way to handle asynchronous events cleanly and efficiently. Used by default for system-level notifications like Wi-Fi connectivity, the event loop can also be extended for custom application needs through user-defined loops. By facilitating decoupled, ordered, and modular event processing, this architecture helps developers build more maintainable and scalable embedded systems—especially in complex IoT applications.\nNext step: assignment 2.1\nFurther reading # Event Loop Library Overview esp_event APIs Default Event Loop Example User Event Loops Example ","date":"5 August 2025","externalUrl":null,"permalink":"/workshops/esp-idf-advanced/lecture-2/","section":"Workshops","summary":"In this article, we explore the event loop—a core component of Espressif\u0026rsquo;s ESP-IDF framework that facilitates efficient, decoupled, and asynchronous event handling in embedded applications. We examine its functionality, highlight its benefits, explain how it is used by default within ESP-IDF, and provide practical code examples to demonstrate common usage patterns.","title":"ESP-IDF Adv. - Lecture 2","type":"workshops"},{"content":" Introduction # We’ll focus on two useful tools:\nSize Analysis: Understand and manage your application’s memory footprint. Core Dump: Capture the system state after a crash for detailed post-mortem debugging. Let\u0026rsquo;s take a closer look at each.\nSize Analysis # What Is Size Analysis? # Size analysis is the process of examining how much flash and RAM your firmware consumes. This helps ensure the application fits within the target hardware and leaves enough memory available for runtime operations such as task scheduling, buffer management, and peripheral interaction.\nPerforming Size Analysis # When building a project with ESP-IDF, the build system automatically provides a memory usage summary. After running:\nESP-IDF: Build Your Project You’ll see output like this:\nTotal sizes: DRAM .data size: 1234 bytes DRAM .bss size: 5678 bytes IRAM size: 9101 bytes Flash code size: 11213 bytes Flash rodata size: 1415 bytes This breakdown gives insight into where your application is consuming resources. For deeper analysis, ESP-IDF offers additional commands:\nidf.py size: Provides a summary of statically-allocated memory usage. idf.py size-components: Shows per-component memory usage. idf.py size-files: Breaks down usage by source file. idf.py size-symbols: Lists symbol-level memory usage (useful for pinpointing heavy functions or variables). These tools help identify memory hotspots and guide you in optimizing your codebase.\nOnce you know the memory usage of your firmware, you can begin pruning both the configuration and code to reduce it. After making your changes, test the memory usage again to see how much impact they had.\nCore Dumps # What Is a Core Dump? # A core dump is a snapshot of the device’s memory and processor state at the time of a crash. It includes:\nCall stacks of all tasks CPU register contents Relevant memory regions This data allows developers to analyze what went wrong, even after the device resets, making core dumps an invaluable tool for diagnosing hard-to-reproduce bugs.\nEnabling and Using Core Dumps # To enable core dumps on an Espressif device using ESP-IDF, you need to\nEnable the core dump in the menuconfig\nTrigger and Analyze the Core Dump When a crash occurs, the Espressif chip saves the core dump to flash or shows it in UART. You can analyze it using:\nidf.py coredump-info These commands decode the core dump and present a readable backtrace, variable states, and register values. This makes it easier to identify the root cause of a failure.\nCore dumps are an invaluable tool to be used alongside debugging.\nConclusion # Mastering size analysis and core dumps is extremely useful for embedded developers. Size analysis helps ensure your application remains within resource limits and runs efficiently, while core dumps provide a powerful mechanism for post-crash diagnostics.\nBy integrating these tools into your development workflow, you\u0026rsquo;ll be better prepared to build robust, high-performance applications.\nNext step: assignment 3.1\nFurther Reading # ESP-IDF Core Dump Guide ","date":"5 August 2025","externalUrl":null,"permalink":"/workshops/esp-idf-advanced/lecture-3/","section":"Workshops","summary":"In this article, we cover two key tools for embedded development on Espressif platforms: size analysis and core dumps. You’ll learn what they do, why they matter, and how to use them to build more efficient and reliable applications.","title":"ESP-IDF Adv. - Lecture 3","type":"workshops"},{"content":" Introduction # As IoT devices become more widespread in homes, industries, and critical infrastructure, the need for robust security is growing rapidly. These connected systems often handle personal data, control physical processes, and operate in untrusted environments—making them attractive targets for attackers.\nIn response to these risks, new regulations like the EU’s Radio Equipment Directive Delegated Act (RED DA) are raising the bar for IoT security, requiring manufacturers to implement stronger protections by design.\nTo meet these evolving demands, three core technologies have become staples of modern IoT security: over-the-air (OTA) updates, flash encryption, and secure bootloaders.\nOTA Updates allow devices to receive firmware updates remotely, enabling timely security patches and feature enhancements without requiring physical access. This is crucial for maintaining device integrity over its lifecycle, especially once deployed in the field.\nFlash Encryption protects data stored in the device’s flash memory by encrypting it at the hardware level. This ensures that sensitive information (such as cryptographic keys or user data) remains inaccessible even if an attacker gains physical access to the device.\nSecure Bootloaders verify the integrity and authenticity of firmware before execution. By checking digital signatures during the boot process, they prevent unauthorized or malicious code from running on the device\nIn the following assignments, you will enable these features on the hardware. If you don\u0026rsquo;t feel comfortable, you can follow the developer portal article to emulate security features using QEMU. Together, these features form a foundational security layer, helping developers build devices that are compliant with new regulations and resilient against real-world threats.\nIn this article we\u0026rsquo;ll see what each of these features. To use the OTA we need to first change the partition table. For this reason, before we start, we need to spend a few words about partition tables.\nPartition Tables # The partition table defines how the flash memory is organized, specifying where applications, data, filesystems, and other resources are stored. This logical separation allows developers to manage firmware, persistent data, and update mechanisms efficiently.\nESP-IDF uses partition tables because they enable:\nSeparation of code and data: Application and persistent data are isolated, allowing firmware updates without erasing user data. OTA updates: Multiple app partitions and OTA data management for robust remote firmware upgrades. Flexible storage: Support for filesystems and custom data regions for certificates, logs, or configuration. Structure and Location # The partition table is typically flashed at offset 0x8000 in the device’s SPI flash. It occupies 0xC00 bytes, supporting up to 95 entries, and includes an MD5 checksum for integrity verification. The table itself takes up a full 4 KB flash sector, so any partition following it must start at least at offset 0x9000, depending on the table size and alignment requirements. Each entry in the table includes a name (label), type (such as app or data), subtype, offset, and size in flash memory.\nBuilt-in Partition Schemes # ESP-IDF provides several predefined partition tables for common use cases, selectable via menuconfig:\nSingle factory app, no OTA: Contains a single application partition and basic data partitions (NVS, PHY init). Factory app, two OTA definitions: Adds support for over-the-air (OTA) updates, with two OTA app partitions and an OTA data slot. We will use this predefined partition table in the assignment 4.1 For example, the \u0026ldquo;Factory app, two OTA definitions\u0026rdquo; scheme typically looks like this:\nName Type SubType Offset Size nvs data nvs 0x9000 0x4000 otadata data ota 0xd000 0x2000 phy_init data phy 0xf000 0x1000 factory app factory 0x10000 1M ota_0 app ota_0 0x110000 1M ota_1 app ota_1 0x210000 1M The bootloader uses the partition table to locate the application to boot and the data regions for NVS, PHY calibration, and OTA management.\nCustom Partition Tables # For advanced use cases, developers can define custom partition tables in CSV format. This allows for additional partitions, such as extra NVS storage, SPIFFS, or FAT filesystems, tailored to the application’s needs. The custom CSV is specified in the project configuration, and ESP-IDF tools will flash and use it accordingly.\nUse custom partition table to increase the size of OTA partitions to the maximum available space (after all other partition sizes are known): This way you have the most space available when doing OTA updates in the future! We will test this option in assignment 4.2.\nOver-the-Air (OTA) Updates on Espressif Devices # Over-the-Air (OTA) updates allow you to remotely upgrade the firmware of embedded devices without requiring physical access. This capability is especially important for IoT deployments, where devices are often distributed across wide or hard-to-reach areas. OTA ensures your devices stay up to date with the latest features, bug fixes, and security patches long after they\u0026rsquo;ve been deployed.\nIn the OTA process, the Espressif device downloads the firmware from a given location, as depicted in Fig.1.\nFig.1 \u0026ndash; OTA basic diagram\nKey benefits of OTA include:\nRemote maintenance: Update firmware without on-site visits. Improved security: Quickly patch known vulnerabilities. Feature updates: Seamlessly deliver new functionality to users. Lower maintenance costs: Avoid expensive manual recalls or servicing. Implementing OTA with ESP-IDF # ESP-IDF offers built-in support for OTA through two main methods:\nNative API: Using the app_update component for full control over the update process. Simplified API: Using the esp_https_ota component for a higher-level interface that handles HTTPS download and flashing automatically. In most cases, application needs to interact with public interface of esp_https_ota and app_update components only. In Fig.2 you can find a simplified diagram of the OTA key components.\nFig.2 \u0026ndash; OTA key components (simplified diagram)\nA typical OTA workflow includes:\nDownloading the new firmware image over Wi-Fi or Ethernet. Writing it to an unused OTA partition in flash. Updating the OTA data partition to mark the new firmware as the active version. Rebooting the device to apply the update. To use OTA, you must add an appropriate partition table. Example code snippet using esp_https_ota # Using esp_https_ota is straightforward and typically requires just a few lines of code.\n#include \u0026#34;esp_https_ota.h\u0026#34; esp_err_t do_firmware_upgrade() { esp_http_client_config_t config = { .url = \u0026#34;https://example.com/firmware.bin\u0026#34;, .cert_pem = (char *)server_cert_pem_start, }; esp_https_ota_config_t ota_config = { .http_config = \u0026amp;config, }; esp_err_t ret = esp_https_ota(\u0026amp;ota_config); if (ret == ESP_OK) { esp_restart(); } else { return ESP_FAIL; } return ESP_OK; } This code downloads a new firmware image and, if successful, restarts the device to boot into the new firmware. For more advanced usage, refer to the ESP-IDF OTA documentation.\nOTA partition table layout # OTA requires a specific partition table layout. At minimum, you need:\nNVS partition: For non-volatile storage. OTA Data partition: To track which firmware partition is active. Two OTA app partitions: For active/passive firmware images. An example of valid partition table is the following.\nName, Type, SubType, Offset, Size, Flags nvs, data, nvs, , 0x6000, otadata, data, ota, , 0x2000, phy_init, data, phy, , 0x1000, ota_0, app, ota_0, , 1M, ota_1, app, ota_1, , 1M, This layout ensures safe updates: the new firmware is written to the inactive partition, and only after verification is it marked as active for the next boot. The OTA data partition is two flash sectors (0x2000 bytes) to prevent corruption in case of power failure during updates.\nBesides the already mentioned (data,nvs), this partition table contains a (data,ota) field which plays an important role in OTA updates.\notadata partition # The otadata partition (also referred to as the OTA Data partition) is a special partition in the ESP-IDF partition table, required for projects that use Over-The-Air (OTA) firmware updates. Its main purpose is to store information about which OTA app slot (such as ota_0 or ota_1) should be booted by the device. It\u0026rsquo;s typical size is 0x2000 bytes (two flash sectors)\nThe otadata partition is used as follows:\nOn first boot (or after erasing), the otadata partition is empty (all bytes set to 0xFF). In this state, the bootloader will boot the factory app if present, or the first OTA slot if not. After a successful OTA update, the otadata partition is updated to indicate which OTA app slot should be booted next. The partition is designed to be robust against power failures: it uses two sectors, and a counter field to determine the most recent valid data if the sectors disagree. Flash encryption # Flash encryption is a critical security feature, designed to protect the contents of flash memory. When enabled, all data stored in flash is encrypted, making it extremely difficult for unauthorized parties to extract sensitive information, even if they have physical access to the device.\nHow Flash Encryption Works # On first boot, firmware is flashed as plaintext and then encrypted in place. The encryption process uses hardware-accelerated algorithms such as XTS-AES-128, XTS-AES-256, or AES-256, depending on the chip series. The encryption key is securely stored in eFuse blocks within the chip and is not accessible by software, ensuring robust key protection. For example, ESP32 uses AES-256, while ESP32-C3, ESP32-C6, and ESP32-H2 use XTS-AES-128 with a 256-bit key stored in eFuse blocks. Some newer chips, like ESP32-S3 and ESP32-P4, also support XTS-AES-256 with a 512-bit key option, using two eFuse blocks for key storage.\nFlash access is transparent: any memory-mapped region is automatically decrypted when read, and encrypted when written, without requiring changes to application code.\nBy default, critical partitions such as the bootloader, partition table, NVS key partition, otadata, and all application partitions are encrypted. Other partitions can be selectively encrypted by marking them with the encrypted flag in the partition table.\nModes and Security Considerations # Flash encryption can be enabled in \u0026ldquo;Development\u0026rdquo; or \u0026ldquo;Release\u0026rdquo; mode.\nIn development mode, it is possible to re-flash plaintext firmware for testing, but this is not secure for production. In release mode, re-flashing plaintext firmware is prevented, and the device is locked down for maximum security. It is strongly recommended to use release mode for production devices to prevent unauthorized firmware extraction or modification.\nImportant Usage Notes # Do not interrupt power during the initial encryption pass on first boot, as this can corrupt flash contents and require re-flashing. Enabling flash encryption increases the bootloader size, which may require updating the partition table offset. We\u0026rsquo;ll see it in detail in assignment 4.3 If secure boot is also enabled, re-flashing the bootloader requires a special \u0026ldquo;Re-flashable\u0026rdquo; secure boot digest. Secure Bootloader # Espressif devices offer a feature called Secure Boot, which is implemented via a secure bootloader. This mechanism forms the foundation of device security, protecting against unauthorized code execution and firmware tampering.\nA secure bootloader is a special program that verifies the authenticity and integrity of the firmware before allowing it to run on the device. It does this by checking cryptographic signatures appended to the bootloader and application images. If any part of the code has been altered or is not signed by a trusted key, the device will refuse to execute it.\nThis process establishes a chain of trust:\nThe hardware (ROM bootloader) verifies the software bootloader. The software bootloader then verifies the application firmware. This ensures that only code signed by the device manufacturer (or another trusted entity) can run, protecting against malware, unauthorized updates, and physical tampering with the device\u0026rsquo;s flash memory. The private signing key is kept secret, while the public key or its digest is stored securely in the device\u0026rsquo;s eFUSE memory, making it inaccessible to software and attackers.\nHow to Use Secure Bootloader # Enabling secure bootloader on Espressif devices involves the following steps\nEnable Secure Boot in Configuration:\nUse menuconfig to enable secure boot under \u0026ldquo;Security Features\u0026rdquo;. Generate or Specify a Signing Key:\nIf a signing key does not exist, generate one using the provided command (e.g., idf.py secure-generate-signing-key). For production, generate keys using a trusted tool like OpenSSL. Build and Flash the Bootloader:\nBuild the secure boot-enabled bootloader: idf.py bootloader Flash the bootloader manually using the command printed by the build process. Build and Flash the Application:\nBuild and flash the application and partition table: idf.py flash The application image will be signed automatically using the specified key. Verify Secure Boot Activation:\nOn first boot, the device will enable secure boot, burn the necessary eFUSEs, and verify the signatures. Monitor the serial output to confirm successful activation. Once secure boot is enabled, the bootloader cannot be reflashed (unless using a special \u0026ldquo;reflashable\u0026rdquo; mode, which is not recommended for production). Always keep your private signing key secure, as its compromise undermines the entire secure boot process Conclusion # In this article, we explored three foundational pillars of modern IoT security: OTA updates, flash encryption, and secure bootloaders. Together, these features ensure that devices can be updated securely, protect sensitive data at rest, and verify firmware integrity from the moment they power on. As IoT security requirements continue to evolve, mastering these tools is essential for building resilient and regulation-compliant embedded systems. In the next assignments, you will test these features first-hand.\nNext step: assignment 4.1\n","date":"5 August 2025","externalUrl":null,"permalink":"/workshops/esp-idf-advanced/lecture-4/","section":"Workshops","summary":"In this article, we explore the advanced features required for security: OTA update, flash encryption, and secure bootloader","title":"ESP-IDF Adv. - Lecture 4","type":"workshops"},{"content":"Welcome to Espressif\u0026rsquo;s Advanced ESP-IDF Workshop!\nIntroduction # In this hands-on workshop, you\u0026rsquo;ll develop a solid understanding of the ESP-IDF framework, included modular development via components, event loops, core dumps, and security features.\nEstimated time: 3 hours. Agenda # The workshop is divided into four parts. Here\u0026rsquo;s the outline:\nPart 1: Components\nLecture 1 \u0026ndash; What is a component, how to create it, and how to support multiple hardware versions via BSPs and multi-config Assignment 1.1 \u0026ndash; Refactor the code creating the alarm component Assignment 1.2 \u0026ndash; Refactor the code creating the cloud_manager component Assignment 1.3 \u0026ndash; Multiple configuration using sdkconfig Part 2: Event Loops\nLecture 2 \u0026ndash; Event loop basics in ESP-IDF, using timer events, and separation of concerns Assignment 2.1 \u0026ndash; Refactor the code to use the event loop mechanism Assignment 2.2 \u0026ndash; Add a gpio event to the event loop Break (15 minutes)\nPart 3: Performance and crash analysis\nLecture 3 \u0026ndash; Application size analysis and core dumps Assignment 3.1 \u0026ndash; Analyze application size and suggest optimizations Assignment 3.2 \u0026ndash; Analyze a crash using core dumps (guided) Assignment 3.3 \u0026ndash; Analyze a crash using core dumps (optional) Part 4: OTA and Security Features\nLecture 4 \u0026ndash; OTA fundamentals, partition table configuration, secure bootloader, flash encryption Assignment 4.1 \u0026ndash; Modify the partition table to support OTA Assignment 4.2 \u0026ndash; Use a custom partition table Assignment 4.3 \u0026ndash; Enable flash encryption Prerequisites # To follow this workshop, make sure you meet the prerequisites listed below.\nGood knowledge of:\nC programming and its linker Call back functions and function pointers MQTT protocol and usage Embedded programming\nFlashing / Programming, linking Familiarity with MCU peripherals such as GPIO and I2C Basic experience with ESP-IDF Tools installation (VSCode + ESP-IDF extension)\nWe strongly recommend installing VSCode and the ESP-IDF plugin before the workshop begins. If you run into any issues, there will be some time during the first assignment to complete the installation.\nReference Table # Prerequisite Description Reference MCU memory types Difference between Flash, RAM and EEPROM L. Harvie (Medium) PSRAM What is PSRAM M. Hawthorne (Technipages) MCU serial peripherals Difference between SPI, I2C, UART nextpcb.com ESP-IDF VSCode Plugin Espressif official VSCode Extension vscode-esp-idf-extension installation Partition table What is partition table and why it\u0026rsquo;s useful Wikipedia disk partitioning article Workshop # Without further delay, let’s get started! You’ll find links to each part of the workshop below.\nThe first lecture builds on the code in assignment_1_1_base.\nIf you’re unable to complete a particular assignment, please download its prerequisite as shown in the diagram below.\na a s s s s i i g g n n m m e e n n t t _ _ 1 3 _ _ 1 2 _ _ b b a a s s e e a s s i g n m e n t _ 1 _ 1 a s s i g n m e n t a a _ s s 1 s s _ i i 2 g g n n m m e e n n t t _ a 2 3 s _ _ s 1 2 i g n m e n t a a _ s s 1 s s _ i i 3 g g n n m m e e n n t t _ 2 4 _ _ 2 1 a a s s s s i i g g n n m m e e n n t t _ 3 4 _ _ 1 2 Even if you complete all assignments successfully, you’ll still need to download at least assignment_1_1_base and assignment_3_2_base. Your next step is Lecture 1.\nPart 1 Lecture 1 assignment 1.1 assignment 1.2 assignment 1.3 Part 2 Lecture 2 assignment 2.1 assignment 2.2 Part 3 Lecture 3 assignment 3.1 assignment 3.2 assignment 3.3 Part 4 Lecture 4 assignment 4.1 assignment 4.2 assignment 4.3 Conclusion # Congratulations! You just arrived at the end of this workshop. We hope it was a fruitful experience and the start of a longer journey. Thank you for following the advanced ESP-IDF workshop.\n","date":"5 August 2025","externalUrl":null,"permalink":"/workshops/esp-idf-advanced/","section":"Workshops","summary":"This workshop is about advanced features of ESP-IDF and focuses on modular development, event loops, core dumps, size analysis and flash encryption.","title":"ESP-IDF Advanced Workshop","type":"workshops"},{"content":" Create a new project starting from the hello world example and change the displayed string (Guided).\nAssignment steps # In this assignment you will:\nCreate a new project starting from the hello_world example Change the displayed string. In this workshop, we\u0026rsquo;ll be using ESP-IDF Extension for VS Code. If you didn\u0026rsquo;t install it yet, please follow these instructions. Step 1: Create a new project starting from the hello_world example # In this section, we will:\nCreate a new project from an example Build the project Flash and monitor Please note that most commands in VS Code are executed through the Command Palette, which you can open by pressing Ctrl+Shift+P (or Cmd+Shift+P)\nIn this guide, commands to enter in the Command Palette are marked with the symbol \u0026gt;. Usually it is sufficient to type a few character of the command, then a dropdown menu will help you find the right one. Create a new project from an example # Open VS Code \u0026gt; ESP-IDF: Show Example Project (If asked) Choose the ESP-IDF version Click on get_started → hello_world Click on the button Select Location for Creating hello_world Example in the new tab. Fig.1 - Create new project tab\nA new window will open with the following file structure:\nFig.2 - hello_world example files\nFor now, you can ignore the folders .vscode, .devcontainer, and build. You will work on the main/hello_world_main.c file.\nBuild the project # To compile (build) your project, you first need to tell the compiler which core (called target) you are using. You can do it through the IDE as follows:\n\u0026gt; ESP-IDF: Set Espressif Device Target In the dropdown menu, choose esp32c3 → ESP32-C3 chip (via builtin USB-JTAG) Now you\u0026rsquo;re ready to compile your project:\n\u0026gt; ESP-IDF: Build Your Project You can also click on the small 🔧 icon located in the bottom bar A terminal tab will open at the bottom of your IDE and show the successful compilation and size of the compiled binary.\nFig.3 - Compilation result\nIf you have problems that are hard to debug, it is useful to do a full clean of your project by using the command \u0026gt; ESP-IDF: Full clean project. Flash and monitor # To see the firmware running, you need to store it on the device (flash) and then you need to read the output it emits on the serial port (monitor).\nConnect the board to your workstation Check that the device is recognized\nIf you don\u0026rsquo;t know how, check this guide Note the name assigned to the Espressif device On Windows, it starts with COM On Linux/macOS, it starts with tty or ttyUSB Inform the IDE about the port the board is connected at\n\u0026gt; ESP-IDF: Select Port to Use (COM, tty, usbserial) If you\u0026rsquo;re having trouble, check the Establish Serial Connection with ESP32 Guide. Now you can flash and monitor your device.\n\u0026gt; ESP-IDF: Build, Flash and Start a Monitor on Your Device If a dropdown menu appears, choose UART In the terminal, you should now see the Hello World! string and the countdown before the reset.\nStep 2: Change the displayed string # Identify the output string and change it to Hello LED.\nConclusion # You can now create a new project and flash it on the board. In the next assignment, we\u0026rsquo;ll consolidate this process.\nNext step # Next assignment → Assignment 1.2\nOr go back to navigation menu\n","date":"5 August 2025","externalUrl":null,"permalink":"/workshops/esp-idf-basic/assignment-1-1/","section":"Workshops","summary":"","title":"ESP-IDF Basics - Assign. 1.1","type":"workshops"},{"content":" Assignment outcomes # A new project from the blink example is created. The output GPIO is changed according to the board schematic. The EVK LED is blinking. Assignment steps outline # For this assignment, you will create a new project from the other get_started example: blink. In the blink example, you need to specify the GPIO on which the LED is connected. The default value is GPIO8 but it\u0026rsquo;s different on your board. You will need to change the configuration value through menuconfig.\nCreate the project from example as done in the previous assignment. Change the example GPIO number in menuconfig: Find the GPIO on which the LED is connected on your board \u0026gt; ESP-IDF: SDK Configuration Editor (menuconfig) → Example Configuration → Blink GPIO number Build, flash, and monitor the example. Check that the LED is flashing. Is the output port correct? See the board schematic. Fig.1 - Board Top View\nBonus task # (Bonus) Change the main filename to hello_led_main.c and the project folder to hello_led. Did you encounter errors? Where is the problem? Solution The linker is not informed that it needs to compile the file hello_led_main.c as well. You need to modify the CMakeLists.txt file, which contains the list of source files to include.\nThe build system is a topic covered in the advanced workshop.\nidf_component_register(SRCS \u0026#34;hello_led_main.c\u0026#34; INCLUDE_DIRS \u0026#34;.\u0026#34;) Conclusion # You have now a solid understanding of the project creation, building, and flashing. In the next lesson, we will focus on what usually is the main topic for an Espressif application \u0026ndash; connectivity.\nNext step # Next lecture → Lecture 2\nOr go back to navigation menu\n","date":"5 August 2025","externalUrl":null,"permalink":"/workshops/esp-idf-basic/assignment-1-2/","section":"Workshops","summary":"Create a new project from the \u003ccode\u003eblink\u003c/code\u003e example and change the output GPIO pin via \u003ccode\u003emenuconfig\u003c/code\u003e","title":"ESP-IDF Basics - Assign. 1.2","type":"workshops"},{"content":" Assignment Steps # Create a new project from a template Start a soft-AP Start an HTTP server Create a new project from a template # In the previous exercises, we created a project based on an example. This time, we will create a project from an empty template instead.\nOpen VS Code Run \u0026gt; ESP-IDF: Create Project from Extension Template In the appeared dropdown menu, Choose a container directory Select the location where the project folder will be created In the appeared dropdown menu. choose template-app In the folder you selected, the following project files are now present:\n. ├── CMakeLists.txt ├── README.md └── main/ ├── CMakeLists.txt └── main.c As you can see, the structure is much simpler than in the blink or hello_world example.\nStart a soft-AP # To keep things as simple as possible, this tutorial will hard-code the access point (AP) credentials. As a result, we won\u0026rsquo;t use Non-Volatile Storage (NVS), which is typically used in Wi-Fi applications to store credentials and calibration data.\nNVS is enabled by default. To avoid warnings and errors, we have to disable it through menuconfig.\nDisable NVS # To disable NVS, open menuconfig and find for the NVS option:\n\u0026gt; ESP-IDF: SDK Configuration Editor (menuconfig) → NVS Deselect PHY and Wi-Fi, as shown in Fig.2 Fig. 2 - NVS options to disable\nClick Save Close the menuconfig tab Define soft-AP parameters # Now open the file main/main.c. We\u0026rsquo;ll use define to set the parameters required by the soft-AP:\n#define ESP_WIFI_SSID \u0026#34;\u0026lt;YOURNAME_esp_test\u0026gt;\u0026#34; #define ESP_WIFI_PASS \u0026#34;test_esp\u0026#34; #define ESP_WIFI_CHANNEL 1 #define MAX_STA_CONN 2 To avoid overlapping with the other participants, please choose a unique SSID name. This is not the recommended way to store credentials. Please store them securely in NVS or manage them through configuration settings using menuconfig. For this workshop, use a unique SSID value! Initialize IP stack and Event Loop # Espressif\u0026rsquo;s Wi-Fi component relies on an event loop to handle asynchronous events. To start the soft-AP, we need to:\nInclude esp_wifi.h, string.h, and esp_log.h Initialize the IP stack (via esp_netif_init and esp_netif_create_default_wifi_ap) Start the default event loop Create and register an event handler function to process Wi-Fi events To keep things clean, we\u0026rsquo;ll encapsulate this code in the function wifi_init_softap\n#include \u0026#34;esp_wifi.h\u0026#34; #include \u0026#34;string.h\u0026#34; #include \u0026#34;esp_log.h\u0026#34; static const char* TAG = \u0026#34;main\u0026#34;; // Used for logging // ... void wifi_init_softap() { esp_netif_init(); esp_event_loop_create_default(); esp_netif_create_default_wifi_ap(); wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT(); // always start with this esp_wifi_init(\u0026amp;cfg); esp_event_handler_instance_register(WIFI_EVENT, ESP_EVENT_ANY_ID, \u0026amp;wifi_event_handler, NULL, NULL); wifi_config_t wifi_config = { .ap = { .ssid = ESP_WIFI_SSID, .ssid_len = strlen(ESP_WIFI_SSID), .channel = ESP_WIFI_CHANNEL, .password = ESP_WIFI_PASS, .max_connection = MAX_STA_CONN, .authmode = WIFI_AUTH_WPA2_PSK, .pmf_cfg = { .required = true, }, }, }; esp_wifi_set_mode(WIFI_MODE_AP); esp_wifi_set_config(WIFI_IF_AP, \u0026amp;wifi_config); esp_wifi_start(); ESP_LOGI(TAG, \u0026#34;wifi_init_softap finished. SSID:%s password:%s channel:%d\u0026#34;, ESP_WIFI_SSID, ESP_WIFI_PASS, ESP_WIFI_CHANNEL); } Register handlers for soft-AP # Create a wifi_event_handler function to handle Wi-Fi events.\nBecause this function is invoked by wifi_init_softap(), it must be defined before that function. static void wifi_event_handler(void* arg, esp_event_base_t event_base, int32_t event_id, void* event_data){ printf(\u0026#34;Event nr: %ld!\\n\u0026#34;, event_id); } Call the function inside the app_main\nvoid app_main(void) { wifi_init_softap(); } Choose the target (esp32c3) and select port as done in the previous assignments. \u0026gt; ESP-IDF: Build, Flash and Start a Monitor on Your Device You should start seeing several event numbers appearing on the terminal.\n[...] I (576) wifi:Init max length of beacon: 752/752 Event n°: 43! I (576) esp_netif_lwip: DHCP server started on interface WIFI_AP_DEF with IP: 192.168.4.1 Event n°: 12! I (586) main: wifi_init_softap completata. SSID:TEST_WORKSHOP password:test_esp canale:1 I (596) main_task: Returned from app_main() Connect to the soft-AP with a Smartphone # Take your smartphone, open the Wi-Fi list, and select the SSID that you chose at the previous step (Fig.2)\nFig. 2 - List of APs\nIn the terminal, you should now see Event nr: 14! which corresponds to WIFI_EVENT_AP_STACONNECTED (you can check the enum value on GitHub - remember that enumeration of values start from 0!)\nThis indicates that a station (i.e. your smartphone) has connected to the soft-AP (i.e. the Espressif module).\nStart an HTTP server # The HTTP server library provided by ESP-IDF is called esp_http_server. To use it, you’ll need to include the library and configure and start the server.\nInclude the library # To use esp_http_server in your project, you’ll need to ensure that CMake recognizes it as a required component.\nInclude the HTTP server header:\n#include \u0026#34;esp_http_server.h\u0026#34; To use the logging library (ESP_LOGI), we define a string named TAG:\nstatic const char* TAG = \u0026#34;main\u0026#34;; Configure the HTTP Server # We encapsulate the server setup in a dedicated function:\nhttpd_handle_t start_webserver() { httpd_handle_t server = NULL; httpd_config_t config = HTTPD_DEFAULT_CONFIG(); if (httpd_start(\u0026amp;server, \u0026amp;config) == ESP_OK) { ESP_LOGI(TAG, \u0026#34;Server started successfully, registering URI handlers...\u0026#34;); return server; } ESP_LOGE(TAG, \u0026#34;Failed to start server\u0026#34;); return NULL; } After calling httpd_start(), the server handle is initialized and can be used to manage the HTTP server.\nIn your app_main function, start the server calling:\nhttpd_handle_t server = start_webserver(); HTTP URI management # We\u0026rsquo;ll return an HTML page when the user visits the / route. To register a route, we call the function httpd_register_uri_handler after the start_webserver in app_main.\nhttpd_register_uri_handler(server,\u0026amp;hello_world_uri); The httpd_uri_t structure defines the properties of the URI being registered.\nstatic const httpd_uri_t hello_world_uri= { .uri = \u0026#34;/\u0026#34;, // the address at which the resource can be found .method = HTTP_GET, // The HTTP method (HTTP_GET, HTTP_POST, ...) .handler = hello_get_handler, // The function which process the request .user_ctx = NULL // Additional user data for context }; The last piece we need is the request handler function\nstatic esp_err_t hello_get_handler(httpd_req_t *req) { const char* resp_str = \u0026#34;\u0026lt;h1\u0026gt;Hello World\u0026lt;/h1\u0026gt;\u0026#34;; httpd_resp_send(req, resp_str, HTTPD_RESP_USE_STRLEN); return ESP_OK; } Note the HTML embedded in the response string.\nConnect to the server # For Espressif devices, the default IP address of the Soft-AP is usually 192.168.4.1.\nYou can verify this in the terminal output. Look for a log line like this:\nI (766) esp_netif_lwip: DHCP server started on interface WIFI_AP_DEF with IP: 192.168.4.1 Open the web browser again on your connected device and enter the IP address in the address bar. As shown in Fig.3, you should now get the HTML page that we sent in the hello_get_handler function.\nFig. 3 – HTML page displayed\nAssignment Code # Show assignment code #include \u0026lt;stdio.h\u0026gt; #define ESP_WIFI_SSID \u0026#34;TEST_WORKSHOP\u0026#34; #define ESP_WIFI_PASS \u0026#34;test_esp\u0026#34; #define ESP_WIFI_CHANNEL 1 #define MAX_STA_CONN 2 #include \u0026#34;esp_wifi.h\u0026#34; #include \u0026#34;string.h\u0026#34; #include \u0026#34;esp_log.h\u0026#34; #include \u0026#34;esp_http_server.h\u0026#34; static const char* TAG = \u0026#34;main\u0026#34;; static esp_err_t hello_get_handler(httpd_req_t *req) { const char* resp_str = \u0026#34;\u0026lt;h1\u0026gt;Hello World\u0026lt;/h1\u0026gt;\u0026#34;; httpd_resp_send(req, resp_str, HTTPD_RESP_USE_STRLEN); return ESP_OK; } static const httpd_uri_t hello_world_uri= { .uri = \u0026#34;/\u0026#34;, .method = HTTP_GET, .handler = hello_get_handler, .user_ctx = NULL }; static void wifi_event_handler(void* arg, esp_event_base_t event_base, int32_t event_id, void* event_data){ printf(\u0026#34;Evento n°: %ld!\\n\u0026#34;, event_id); } void wifi_init_softap(){ esp_netif_init(); esp_event_loop_create_default(); esp_netif_create_default_wifi_ap(); wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT(); esp_wifi_init(\u0026amp;cfg); esp_event_handler_instance_register(WIFI_EVENT, ESP_EVENT_ANY_ID, \u0026amp;wifi_event_handler, NULL, NULL); wifi_config_t wifi_config = { .ap = { .ssid = ESP_WIFI_SSID, .ssid_len = strlen(ESP_WIFI_SSID), .channel = ESP_WIFI_CHANNEL, .password = ESP_WIFI_PASS, .max_connection = MAX_STA_CONN, .authmode = WIFI_AUTH_WPA2_PSK, .pmf_cfg = { .required = true, }, }, }; esp_wifi_set_mode(WIFI_MODE_AP); esp_wifi_set_config(WIFI_IF_AP, \u0026amp;wifi_config); esp_wifi_start(); ESP_LOGI(TAG, \u0026#34;wifi_init_softap finished. SSID:%s password:%s channel:%d\u0026#34;, ESP_WIFI_SSID, ESP_WIFI_PASS, ESP_WIFI_CHANNEL); } httpd_handle_t start_webserver() { httpd_handle_t server = NULL; httpd_config_t config = HTTPD_DEFAULT_CONFIG(); if (httpd_start(\u0026amp;server, \u0026amp;config) == ESP_OK) { ESP_LOGI(TAG, \u0026#34;Server successfully started, registering URI handlers...\u0026#34;); return server; } ESP_LOGE(TAG, \u0026#34;Server initialization failed\u0026#34;); return NULL; } void app_main(void) { wifi_init_softap(); httpd_handle_t server = start_webserver(); httpd_register_uri_handler(server,\u0026amp;hello_world_uri); } Conclusion # Now you can put the Espressif device into Soft-AP or STA mode and create an HTTP server which can return both HTML based content of a JSON based response for a REST API.\nNext step # Next assignment: Assignment 2.2\nOr go back to navigation menu\n","date":"5 August 2025","externalUrl":null,"permalink":"/workshops/esp-idf-basic/assignment-2-1/","section":"Workshops","summary":"Start a soft-AP and an HTTP server (guided)","title":"ESP-IDF Basics - Assign. 2.1","type":"workshops"},{"content":"The goal of the second assignment is to add the following routes to the HTTP server that we created in the previous assignment:\nGET /led/on → turns the LED on and returns JSON {\u0026ldquo;led\u0026rdquo;: \u0026ldquo;on\u0026rdquo;} GET /led/off→ turns the LED off and returns JSON {\u0026ldquo;led\u0026rdquo;: \u0026ldquo;off\u0026rdquo;} POST /led/blink → accepts JSON { \u0026quot;times\u0026quot;: int, \u0026quot;interval_ms\u0026quot;: int } to blink the LED the specified number of times at the given interval, and returns JSON {\u0026quot;blink\u0026quot;: \u0026quot;done\u0026quot;} Solution outline # To control the LED, you can use the code from the blink example. Here the relevant snippets are displayed just for your convenience.\nBoards with GPIO LED (.e.g RUST Board) # Include the GPIO header\n#include \u0026#34;driver/gpio.h\u0026#34; Specify the pin to use\n#define OUTPUT_LED GPIO_NUM_7 Create the LED configuration function (to be called from app_main)\nstatic void configure_led(void) { ESP_LOGI(TAG, \u0026#34;LED Configured!\\n\u0026#34;); gpio_reset_pin(OUTPUT_LED); /* Set the GPIO as push/pull output */ gpio_set_direction(OUTPUT_LED, GPIO_MODE_OUTPUT); } Boards with RGB LED (e.g. DevkitC board) # Add the led_strip component by creating the file idf_component.yml inside the main folder\ndependencies: espressif/led_strip: \u0026#34;^3.0.0\u0026#34; Include the library\n#include \u0026#34;led_strip.h\u0026#34; Specify the pin to use (check your board!)\n#define BLINK_GPIO 8 Create the LED configuration function (to be called from app_main)\nstatic void configure_led(void) { ESP_LOGI(TAG, \u0026#34;Example configured to blink addressable LED!\u0026#34;); /* LED strip initialization with the GPIO and pixels number*/ led_strip_config_t strip_config = { .strip_gpio_num = BLINK_GPIO, .max_leds = 1, // at least one LED on board }; led_strip_rmt_config_t rmt_config = { .resolution_hz = 10 * 1000 * 1000, // 10MHz .flags.with_dma = false, }; ESP_ERROR_CHECK(led_strip_new_rmt_device(\u0026amp;strip_config, \u0026amp;rmt_config, \u0026amp;led_strip)); led_strip_clear(led_strip); } Turn the led on and off with the following commands\n// LED ON led_strip_set_pixel(led_strip, 0, 16, 16, 16); led_strip_refresh(led_strip); // LED OFF led_strip_clear(led_strip); Run a full clean before building again\nESP-IDF: Full Clean Project Assignment Code # Show assignment code (GPIO LED) #include \u0026lt;stdio.h\u0026gt; #define ESP_WIFI_SSID \u0026#34;TEST_WORKSHOP\u0026#34; #define ESP_WIFI_PASS \u0026#34;test_esp\u0026#34; #define ESP_WIFI_CHANNEL 1 #define MAX_STA_CONN 2 #include \u0026#34;esp_wifi.h\u0026#34; #include \u0026#34;string.h\u0026#34; #include \u0026#34;esp_log.h\u0026#34; #include \u0026#34;esp_http_server.h\u0026#34; #include \u0026#34;driver/gpio.h\u0026#34; #define OUTPUT_LED GPIO_NUM_7 static const char* TAG = \u0026#34;main\u0026#34;; static void configure_led(void) { ESP_LOGI(TAG, \u0026#34;LED Configured!\\n\u0026#34;); gpio_reset_pin(OUTPUT_LED); /* Set the GPIO as push/pull output */ gpio_set_direction(OUTPUT_LED, GPIO_MODE_OUTPUT); } static esp_err_t hello_get_handler(httpd_req_t *req) { const char* resp_str = \u0026#34;\u0026lt;h1\u0026gt;Hello World\u0026lt;/h1\u0026gt;\u0026#34;; httpd_resp_send(req, resp_str, HTTPD_RESP_USE_STRLEN); return ESP_OK; } /* Handler definitions */ static void wifi_event_handler(void* arg, esp_event_base_t event_base, int32_t event_id, void* event_data){ printf(\u0026#34;Event number: %ld!\\n\u0026#34;, event_id); } static esp_err_t led_on_handler(httpd_req_t *req) { led_control(1); const char* resp_str = \u0026#34;{\\\u0026#34;led\\\u0026#34;: \\\u0026#34;on\\\u0026#34;}\u0026#34;; httpd_resp_set_type(req, \u0026#34;application/json\u0026#34;); httpd_resp_send(req, resp_str, HTTPD_RESP_USE_STRLEN); return ESP_OK; } static esp_err_t led_off_handler(httpd_req_t *req) { led_control(0); const char* resp_str = \u0026#34;{\\\u0026#34;led\\\u0026#34;: \\\u0026#34;off\\\u0026#34;}\u0026#34;; httpd_resp_set_type(req, \u0026#34;application/json\u0026#34;); httpd_resp_send(req, resp_str, HTTPD_RESP_USE_STRLEN); return ESP_OK; } /* URI definitions */ static const httpd_uri_t hello_world_uri= { .uri = \u0026#34;/\u0026#34;, .method = HTTP_GET, .handler = hello_get_handler, .user_ctx = NULL }; static const httpd_uri_t led_on_uri = { .uri = \u0026#34;/led/on\u0026#34;, .method = HTTP_GET, .handler = led_on_handler, .user_ctx = NULL }; static const httpd_uri_t led_off_uri = { .uri = \u0026#34;/led/off\u0026#34;, .method = HTTP_GET, .handler = led_off_handler, .user_ctx = NULL }; void wifi_init_softap(){ esp_netif_init(); esp_event_loop_create_default(); esp_netif_create_default_wifi_ap(); wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT(); // always start from here esp_wifi_init(\u0026amp;cfg); esp_event_handler_instance_register(WIFI_EVENT, ESP_EVENT_ANY_ID, \u0026amp;wifi_event_handler, NULL, NULL); wifi_config_t wifi_config = { .ap = { .ssid = ESP_WIFI_SSID, .ssid_len = strlen(ESP_WIFI_SSID), .channel = ESP_WIFI_CHANNEL, .password = ESP_WIFI_PASS, .max_connection = MAX_STA_CONN, .authmode = WIFI_AUTH_WPA2_PSK, .pmf_cfg = { .required = true, }, }, }; esp_wifi_set_mode(WIFI_MODE_AP); esp_wifi_set_config(WIFI_IF_AP, \u0026amp;wifi_config); esp_wifi_start(); ESP_LOGI(TAG, \u0026#34;wifi_init_softap completed. SSID:%s password:%s channel:%d\u0026#34;, ESP_WIFI_SSID, ESP_WIFI_PASS, ESP_WIFI_CHANNEL); } httpd_handle_t start_webserver() { httpd_handle_t server = NULL; httpd_config_t config = HTTPD_DEFAULT_CONFIG(); if (httpd_start(\u0026amp;server, \u0026amp;config) == ESP_OK) { ESP_LOGI(TAG, \u0026#34;Server started successfully, registering URI handlers...\u0026#34;); return server; } ESP_LOGE(TAG, \u0026#34;Unable to start the server\u0026#34;); return NULL; } void app_main(void) { wifi_init_softap(); configure_led(); httpd_handle_t server = start_webserver(); /* Register URI/Handler */ httpd_register_uri_handler(server,\u0026amp;hello_world_uri); httpd_register_uri_handler(server, \u0026amp;led_on_uri); httpd_register_uri_handler(server, \u0026amp;led_off_uri); } Show assignment code (RGB LED) #include \u0026lt;stdio.h\u0026gt; #define ESP_WIFI_SSID \u0026#34;TEST_WORKSHOP\u0026#34; #define ESP_WIFI_PASS \u0026#34;test_esp\u0026#34; #define ESP_WIFI_CHANNEL 1 #define MAX_STA_CONN 2 #include \u0026#34;esp_wifi.h\u0026#34; #include \u0026#34;string.h\u0026#34; #include \u0026#34;esp_log.h\u0026#34; #include \u0026#34;esp_http_server.h\u0026#34; #include \u0026#34;led_strip.h\u0026#34; #define BLINK_GPIO 8 static const char* TAG = \u0026#34;main\u0026#34;; static led_strip_handle_t led_strip; static void configure_led(void) { /* LED strip initialization with the GPIO and pixels number*/ led_strip_config_t strip_config = { .strip_gpio_num = BLINK_GPIO, .max_leds = 1, // at least one LED on board }; led_strip_rmt_config_t rmt_config = { .resolution_hz = 10 * 1000 * 1000, // 10MHz .flags.with_dma = false, }; ESP_ERROR_CHECK(led_strip_new_rmt_device(\u0026amp;strip_config, \u0026amp;rmt_config, \u0026amp;led_strip)); led_strip_clear(led_strip); } void drive_led(bool level){ if(level){ led_strip_set_pixel(led_strip, 0, 16, 16, 16); led_strip_refresh(led_strip); }else{ led_strip_clear(led_strip); } } static esp_err_t hello_get_handler(httpd_req_t *req) { const char* resp_str = \u0026#34;\u0026lt;h1\u0026gt;Hello World\u0026lt;/h1\u0026gt;\u0026#34;; httpd_resp_send(req, resp_str, HTTPD_RESP_USE_STRLEN); return ESP_OK; } static esp_err_t led_on_handler(httpd_req_t *req) { drive_led(1); const char* resp_str = \u0026#34;{\\\u0026#34;led\\\u0026#34;: \\\u0026#34;on\\\u0026#34;}\u0026#34;; httpd_resp_set_type(req, \u0026#34;application/json\u0026#34;); httpd_resp_send(req, resp_str, HTTPD_RESP_USE_STRLEN); return ESP_OK; } static esp_err_t led_off_handler(httpd_req_t *req) { drive_led(0); const char* resp_str = \u0026#34;{\\\u0026#34;led\\\u0026#34;: \\\u0026#34;off\\\u0026#34;}\u0026#34;; httpd_resp_set_type(req, \u0026#34;application/json\u0026#34;); httpd_resp_send(req, resp_str, HTTPD_RESP_USE_STRLEN); return ESP_OK; } static const httpd_uri_t hello_world_uri= { .uri = \u0026#34;/\u0026#34;, .method = HTTP_GET, .handler = hello_get_handler, .user_ctx = NULL }; static const httpd_uri_t led_on_uri = { .uri = \u0026#34;/led/on\u0026#34;, .method = HTTP_GET, .handler = led_on_handler, .user_ctx = NULL }; static const httpd_uri_t led_off_uri = { .uri = \u0026#34;/led/off\u0026#34;, .method = HTTP_GET, .handler = led_off_handler, .user_ctx = NULL }; static void wifi_event_handler(void* arg, esp_event_base_t event_base, int32_t event_id, void* event_data){ printf(\u0026#34;Event n°: %ld!\\n\u0026#34;, event_id); } void wifi_init_softap(){ esp_netif_init(); esp_event_loop_create_default(); esp_netif_create_default_wifi_ap(); wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT(); // sempre iniziare da qui esp_wifi_init(\u0026amp;cfg); esp_event_handler_instance_register(WIFI_EVENT, ESP_EVENT_ANY_ID, \u0026amp;wifi_event_handler, NULL, NULL); wifi_config_t wifi_config = { .ap = { .ssid = ESP_WIFI_SSID, .ssid_len = strlen(ESP_WIFI_SSID), .channel = ESP_WIFI_CHANNEL, .password = ESP_WIFI_PASS, .max_connection = MAX_STA_CONN, .authmode = WIFI_AUTH_WPA2_PSK, .pmf_cfg = { .required = true, }, }, }; esp_wifi_set_mode(WIFI_MODE_AP); esp_wifi_set_config(WIFI_IF_AP, \u0026amp;wifi_config); esp_wifi_start(); ESP_LOGI(TAG, \u0026#34;wifi_init_softap completed. SSID:%s password:%s channel:%d\u0026#34;, ESP_WIFI_SSID, ESP_WIFI_PASS, ESP_WIFI_CHANNEL); } httpd_handle_t start_webserver() { httpd_handle_t server = NULL; httpd_config_t config = HTTPD_DEFAULT_CONFIG(); if (httpd_start(\u0026amp;server, \u0026amp;config) == ESP_OK) { ESP_LOGI(TAG, \u0026#34;Server started successfully\u0026#34;); return server; } ESP_LOGE(TAG, \u0026#34;Impossible to start the server\u0026#34;); return NULL; } void app_main(void) { configure_led(); wifi_init_softap(); httpd_handle_t server = start_webserver(); httpd_register_uri_handler(server,\u0026amp;hello_world_uri); httpd_register_uri_handler(server,\u0026amp;hello_world_uri); httpd_register_uri_handler(server, \u0026amp;led_on_uri); httpd_register_uri_handler(server, \u0026amp;led_off_uri); } Conclusion # Now we have a clear picture of how to connect REST API requests to physical device control. You will work on a more complex application in the last assignment 3.3.\nNext step # If you still have time, you can try this optional assignment.\nNext (optional) assignment → Assignment 2.3\nOtherwise, you can move to the third lecture.\nNext lecture → Lecture 3\nOr go back to navigation menu\n","date":"5 August 2025","externalUrl":null,"permalink":"/workshops/esp-idf-basic/assignment-2-2/","section":"Workshops","summary":"Add more routes to the HTTP server to drive the LED remotely","title":"ESP-IDF Basics - Assign. 2.2","type":"workshops"},{"content":"This assignment is optional. You can do it if you still have time before the break.\nAdd another route to the HTTP server from the previous assignments:\nPOST /led/flash → accepts JSON {\u0026quot;periods\u0026quot;: [int], \u0026quot;duty_cycles\u0026quot;: [int]} and for each element, calculates the on-time and off-time and drives the LED accordingly. To test a POST request, you need an app that allows you to send structured HTTP requests. One example is Teste. If you connect your computer to the module’s access point, you can instead use the Python script below. Python script for POST request Create the following script post_test.py #!/usr/bin/env python3 \u0026#34;\u0026#34;\u0026#34; Send LED flashing parameters to an ESP device via HTTP POST. Endpoint: POST http://192.168.4.1/led/flash Body: {\u0026#34;periods\u0026#34;: [int, ...], \u0026#34;duty_cycles\u0026#34;: [int, ...]} Each pair (period, duty_cycle) defines one blink pattern. \u0026#34;\u0026#34;\u0026#34; import requests import json # --- Configuration --- ESP_IP = \u0026#34;192.168.4.1\u0026#34; # Replace with your module’s IP address ENDPOINT = f\u0026#34;http://{ESP_IP}/led/flash\u0026#34; # Example data: # periods in milliseconds, duty_cycles in percentage payload = { \u0026#34;periods\u0026#34;: [1000, 500, 2000], \u0026#34;duty_cycles\u0026#34;: [50, 75, 25] } def send_led_flash(payload): \u0026#34;\u0026#34;\u0026#34;Send POST request to the ESP endpoint with LED flash parameters.\u0026#34;\u0026#34;\u0026#34; try: print(f\u0026#34;Sending POST to {ENDPOINT} ...\u0026#34;) response = requests.post(ENDPOINT, json=payload, timeout=5) response.raise_for_status() print(\u0026#34;✅ Request successful!\u0026#34;) print(\u0026#34;Response:\u0026#34;, response.text) except requests.exceptions.RequestException as e: print(\u0026#34;❌ Error communicating with the ESP:\u0026#34;, e) if __name__ == \u0026#34;__main__\u0026#34;: print(\u0026#34;Payload:\u0026#34;, json.dumps(payload, indent=2)) send_led_flash(payload) Open an ESP-IDF Terminal ESP-IDF: Open ESP-IDF Terminal Run the script python post_test.py Solution outline # You need to check that both periods and duty_cycles have the same length and contain positive number only. duty_cycles should contain numbers between 0 and 100.\nYou can traverse the two arrays and calculate for each element at index i the LED on_time and off_time as follows:\non_time[i] = duty_cycle[i]/100 * periods[i] off_time[i] = periods[i]-on_time[i] You can drive the LED according to the sequence:\nON: on_time[1] OFF: off_time[1] ON: on_time[2] OFF: off_time[2] ... Conclusion # If you managed to reach this point, it means you have good understanding of a basic REST API implementation. You can now move to the third lecture, detailing the management of external libraries and the use of the components found on the component registry.\nNext step # Next lecture → Lecture 3\nOr go back to navigation menu\n","date":"5 August 2025","externalUrl":null,"permalink":"/workshops/esp-idf-basic/assignment-2-3/","section":"Workshops","summary":"Add a new route to the HTTP server for a programmable blink (Optional)","title":"ESP-IDF Basics - Assign. 2.3 (Optional)","type":"workshops"},{"content":"This assignment has two tasks:\nCreate a led-toggle component Refactor the hello_led example using the created component led-toggle component # The first task is to create a led-toggle component.\nCreate a new component # Open your project hello_led in VS Code Create a new component: \u0026gt; ESP-IDF: Create New ESP-IDF Component Type led_toggle in the text field appearing on top (see Fig.1) Fig.1 - Create new component\nThe project will now contain the folder components and all the required files:\n. └── hello_led/ ├── components/ │ └── led_toggle/ │ ├── include/ │ │ └── led_toggle.h │ ├── CMakeList.txt │ └── led_toggle.c ├── main └── build Create the toggle function # Add the following code to the component header and source files (depending on your evk) and implement the toggle function.\nesp_err is an enum (hence an int) used to return error codes. You can check its values in the documentation. This enum is used also with logging and macros like ESP_ERR_CHECK, which you will find almost all esp-idf examples. LED GPIO Version # led_toggle.h\n#include \u0026#34;driver/gpio.h\u0026#34; typedef struct { int gpio_nr; bool status; }led_gpio_t; esp_err_t led_config(led_gpio_t * led_gpio); esp_err_t led_drive(led_gpio_t * led_gpio); esp_err_t led_toggle(led_gpio_t * led_gpio); led_toggle.c\nesp_err_t led_config(led_gpio_t * led_gpio){ gpio_config_t io_conf = {}; io_conf.intr_type = GPIO_INTR_DISABLE; io_conf.mode = GPIO_MODE_OUTPUT; io_conf.pin_bit_mask = (1ULL\u0026lt;\u0026lt;led_gpio-\u0026gt;gpio_nr); io_conf.pull_down_en = 0; io_conf.pull_up_en = 0; return gpio_config(\u0026amp;io_conf); } esp_err_t led_drive(led_gpio_t * led_gpio){ return gpio_set_level(led_gpio-\u0026gt;gpio_nr, led_gpio-\u0026gt;status); // turns led on } esp_err_t led_toggle(led_gpio_t * led_gpio){ //TBD return 0; } LED RGB Version # led_toggle.h\n#include \u0026#34;led_strip.h\u0026#34; typedef struct { int gpio_nr; bool status; led_strip_handle_t led_strip; }led_handle_t; esp_err_t led_config(led_handle_t * leg_rgb); esp_err_t led_drive(led_handle_t * leg_rgb, bool level); esp_err_t led_toggle(led_handle_t * leg_rgb); led_toggle.c\n#include \u0026lt;stdio.h\u0026gt; #include \u0026#34;led_toggle.h\u0026#34; #include \u0026#34;esp_err.h\u0026#34; esp_err_t led_config(led_handle_t * led_handle) { led_strip_config_t strip_config = { .strip_gpio_num = led_handle-\u0026gt;gpio_nr, .max_leds = 1, // at least one LED on board }; led_strip_rmt_config_t rmt_config = { .resolution_hz = 10 * 1000 * 1000, // 10MHz .flags.with_dma = false, }; esp_err_t ret = led_strip_new_rmt_device(\u0026amp;strip_config, \u0026amp;rmt_config, \u0026amp;led_handle-\u0026gt;led_strip); led_strip_clear(led_handle-\u0026gt;led_strip); return ret; } esp_err_t led_drive(led_handle_t * led_handle, bool level){ if(level){ esp_err_t ret = led_strip_set_pixel(led_handle-\u0026gt;led_strip, 0, 16, 16, 16); led_strip_refresh(led_handle-\u0026gt;led_strip); led_handle-\u0026gt;status = true; return ret; }else{ led_handle-\u0026gt;status= false; return led_strip_clear(led_handle-\u0026gt;led_strip); } } esp_err_t led_toggle(led_handle_t * led_handle){ //TBD return 0; } Test the component # Now, in app_main, include the appropriate header Configure the peripheral (using the config_led function) Test that everything works correctly through the drive_led function Refactor the hello_led code # Now you are ready to:\nImplement the toggle_led function Refactor the hello_led code to use the newly created component. Assignment solution # Assignment code #include \u0026lt;stdio.h\u0026gt; #define ESP_WIFI_SSID \u0026#34;TEST_WORKSHOP\u0026#34; #define ESP_WIFI_PASS \u0026#34;test_esp\u0026#34; #define ESP_WIFI_CHANNEL 1 #define MAX_STA_CONN 2 #include \u0026#34;esp_wifi.h\u0026#34; #include \u0026#34;string.h\u0026#34; #include \u0026#34;esp_log.h\u0026#34; #include \u0026#34;esp_http_server.h\u0026#34; #include \u0026#34;led_toggle.h\u0026#34; #define OUTPUT_LED 8 static const char* TAG = \u0026#34;main\u0026#34;; led_handle_t my_led = { .gpio_nr = OUTPUT_LED, .status = false, .led_strip = false }; static esp_err_t hello_get_handler(httpd_req_t *req) { const char* resp_str = \u0026#34;\u0026lt;h1\u0026gt;Hello World\u0026lt;/h1\u0026gt;\u0026#34;; httpd_resp_send(req, resp_str, HTTPD_RESP_USE_STRLEN); return ESP_OK; } /* Handler definitions */ static void wifi_event_handler(void* arg, esp_event_base_t event_base, int32_t event_id, void* event_data){ printf(\u0026#34;Evento n°: %ld!\\n\u0026#34;, event_id); } static esp_err_t led_on_handler(httpd_req_t *req) { ESP_ERROR_CHECK(led_drive(\u0026amp;my_led,true)); const char* resp_str = \u0026#34;{\\\u0026#34;led\\\u0026#34;: \\\u0026#34;on\\\u0026#34;}\u0026#34;; httpd_resp_set_type(req, \u0026#34;application/json\u0026#34;); httpd_resp_send(req, resp_str, HTTPD_RESP_USE_STRLEN); return ESP_OK; } static esp_err_t led_off_handler(httpd_req_t *req) { led_drive(\u0026amp;my_led,false); const char* resp_str = \u0026#34;{\\\u0026#34;led\\\u0026#34;: \\\u0026#34;off\\\u0026#34;}\u0026#34;; httpd_resp_set_type(req, \u0026#34;application/json\u0026#34;); httpd_resp_send(req, resp_str, HTTPD_RESP_USE_STRLEN); return ESP_OK; } static esp_err_t led_toggle_handler(httpd_req_t *req) { led_toggle(\u0026amp;my_led); const char* resp_str = \u0026#34;{\\\u0026#34;led\\\u0026#34;: \\\u0026#34;toggled\\\u0026#34;}\u0026#34;; httpd_resp_set_type(req, \u0026#34;application/json\u0026#34;); httpd_resp_send(req, resp_str, HTTPD_RESP_USE_STRLEN); return ESP_OK; } /* URI definitions */ static const httpd_uri_t hello_world_uri= { .uri = \u0026#34;/\u0026#34;, .method = HTTP_GET, .handler = hello_get_handler, .user_ctx = NULL }; static const httpd_uri_t led_on_uri = { .uri = \u0026#34;/led/on\u0026#34;, .method = HTTP_GET, .handler = led_on_handler, .user_ctx = NULL }; static const httpd_uri_t led_off_uri = { .uri = \u0026#34;/led/off\u0026#34;, .method = HTTP_GET, .handler = led_off_handler, .user_ctx = NULL }; static const httpd_uri_t led_toggle_uri = { .uri = \u0026#34;/led/toggle\u0026#34;, .method = HTTP_GET, .handler = led_toggle_handler, .user_ctx = NULL }; void wifi_init_softap(){ esp_netif_init(); esp_event_loop_create_default(); esp_netif_create_default_wifi_ap(); wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT(); // sempre iniziare da qui esp_wifi_init(\u0026amp;cfg); esp_event_handler_instance_register(WIFI_EVENT, ESP_EVENT_ANY_ID, \u0026amp;wifi_event_handler, NULL, NULL); wifi_config_t wifi_config = { .ap = { .ssid = ESP_WIFI_SSID, .ssid_len = strlen(ESP_WIFI_SSID), .channel = ESP_WIFI_CHANNEL, .password = ESP_WIFI_PASS, .max_connection = MAX_STA_CONN, .authmode = WIFI_AUTH_WPA2_PSK, .pmf_cfg = { .required = true, }, }, }; esp_wifi_set_mode(WIFI_MODE_AP); esp_wifi_set_config(WIFI_IF_AP, \u0026amp;wifi_config); esp_wifi_start(); ESP_LOGI(TAG, \u0026#34;wifi_init_softap completata. SSID:%s password:%s canale:%d\u0026#34;, ESP_WIFI_SSID, ESP_WIFI_PASS, ESP_WIFI_CHANNEL); } httpd_handle_t start_webserver() { httpd_handle_t server = NULL; httpd_config_t config = HTTPD_DEFAULT_CONFIG(); if (httpd_start(\u0026amp;server, \u0026amp;config) == ESP_OK) { ESP_LOGI(TAG, \u0026#34;Server avviato con successo, registrazione degli handler URI...\u0026#34;); return server; } ESP_LOGE(TAG, \u0026#34;Impossibile avviare il server\u0026#34;); return NULL; } void app_main(void) { wifi_init_softap(); led_config(\u0026amp;my_led); httpd_handle_t server = start_webserver(); /* Registrazione URI/Handler */ httpd_register_uri_handler(server,\u0026amp;hello_world_uri); httpd_register_uri_handler(server, \u0026amp;led_on_uri); httpd_register_uri_handler(server, \u0026amp;led_off_uri); httpd_register_uri_handler(server, \u0026amp;led_toggle_uri); } Conclusion # You can now create your own components, which makes your code easier to maintain and to share. In the next assignment, you will face a typical development problem and use the skills you just learned.\nNext step # Next assignment → Assignment 3.2\nOr go back to navigation menu\n","date":"5 August 2025","externalUrl":null,"permalink":"/workshops/esp-idf-basic/assignment-3-1/","section":"Workshops","summary":"Create a led-toggle component and refactor the hello_led example using the component","title":"ESP-IDF Basics - Assign. 3.1","type":"workshops"},{"content":"In this assignment, you will read the temperature values from the on-board sensor OR the on-chip sensor depending on your board.\nOn board sensor e.g. Rust board\nFind the part number of the sensor on your board Find the code for driving the sensor Read temperature from the sensor and output it on the serial port with printf. It is not asked to develop the driver, focus on the fastest way to solve the problem and what the previous lecture was about. On chip sensor e.g. DevkitC\nFind the sensor api reference page Find how to include, initialize and configure the sensor Read temperature from the sensor and output it on the serial port with printf. Hint # Show hint on board sensor The sensor I2C address can be found on the EVK GitHub page.\nTo install a dependency, open an ESP-IDF terminal:\n\u0026gt; ESP-IDF: Open ESP-IDF Terminal Then use idf.py:\nidf.py add-dependency \u0026#34;repository_name_in_the_registry\u0026#34; Remember to adjust the settings in menuconfig.\nShow hint on chip sensor The information can be found in the ESP-IDF Programming guide.\nConfigure the sensor\ntemperature_sensor_config_t temp_sensor = { .range_min = -10, // Minimum measurable temperature .range_max = 80, // Maximum measurable temperature .clk_src = TEMPERATURE_SENSOR_CLK_SRC_DEFAULT }; Install and enable it\n// Install temperature sensor driver temperature_sensor_install(\u0026amp;temp_sensor, \u0026amp;temp_handle); temperature_sensor_enable(temp_handle); Read the temperature\ntemperature_sensor_get_celsius(temp_handle, \u0026amp;tsens_out) Conclusion # Now that you can read the on board sensor, you\u0026rsquo;re ready to move to the last assignment of the workshop to put everything together.\nNext step # Next assignment → Assignment 3.3\nOr go back to navigation menu\n","date":"5 August 2025","externalUrl":null,"permalink":"/workshops/esp-idf-basic/assignment-3-2/","section":"Workshops","summary":"","title":"ESP-IDF Basics - Assign. 3.2","type":"workshops"},{"content":"In this assignment, you will put all you have done together by adding the two routes below to your HTTP server.\nFor this assignment, you have to\nAdd the route GET /enviroment/ which returns the json object { \u0026#39;temperature\u0026#39;: float, } (Optional) add route POST /startblink/ which flashes the led according to the temperature reading Flashes the number of tens digit (e.g. 29 degrees → 2) with 400ms on and 200ms off Pauses 1 sec Flashes the number of units digit (e.g. 29 degrees → 2) with 400ms on and 200ms off Conclusion # You have create a basic IoT application, putting together sensor reading and HTTP connectivity, letting external services to interact with your application.\nNext step # Next step → Conclusion\nOr go back to navigation menu\n","date":"5 August 2025","externalUrl":null,"permalink":"/workshops/esp-idf-basic/assignment-3-3/","section":"Workshops","summary":"","title":"ESP-IDF Basics - Assign. 3.3","type":"workshops"},{"content":" ESP-IDF Introduction # The ESP-IDF (Espressif IoT Development Framework) is the official operating system and development framework for the Espressif Systems SoCs. It provides a comprehensive environment for building IoT applications with robust networking, security, and reliability features.\nThe ESP-IDF framework includes FreeRTOS, enabling developers to build real-time, multitasking applications. It provides a comprehensive set of libraries, tools, and documentation, serving as the foundation for development on Espressif devices.\nESP-IDF includes more than 400 examples, covering a wide range of use cases and helping developers quickly get started on their projects.\nArchitecture # The ESP-IDF platform architecture is mainly divided into 3 layers:\nESP-IDF platform Contains the core components required and the operating system. Includes the FreeRTOS, drivers, build system, protocols, etc. Middleware Adds new features to ESP-IDF, for example the audio framework and HMI. In this workshop, we won\u0026rsquo;t use them. AIoT Application Your application. Fig.1 - ESP-IDF High level Overview\nAll the necessary building blocks for your application will be included in the ESP-IDF platform. ESP-IDF is constantly developing, growing, and improving; acquiring new features and supporting more Espressif cores. Visit the ESP-IDF project on GitHub to get the updated list of supported versions and the maintenance period.\nespressif/esp-idf Espressif IoT Development Framework. Official development framework for Espressif SoCs. C 17733 8184 Main ESP-IDF blocks # As mentioned, ESP-IDF is built on FreeRTOS and contains several libraries. The main libraries you will include in your projects are:\nFreeRTOS (freertos): lightweight, real-time operating system kernel designed for embedded devices, providing multitasking capabilities through preemptive scheduling, task management, and inter-task communication. Drivers (esp_driver_xxx): libraries for driving peripherals. Protocols (esp_http, esp-tls etc.): libraries implementing protocols. During the assignments, you will learn how to include both internal libraries provided by ESP-IDF and external libraries. ESP-IDF also offers a convenient system for managing external dependencies, known as components.\nComponents # Components are packages that include libraries along with additional files for dependency management, metadata, and configuration.\nFig.2 - ESP-IDF Components\nThey are used to add new features such as sensor drivers, communication protocols, board support packages, and other functionalities not included in ESP-IDF by default. Some components are already integrated into example projects, and ESP-IDF itself adopts the external component model to promote modularity.\nUsing components enhances maintainability and accelerates development by enabling code reuse and sharing across multiple projects.\nIf you want to create and publish your own component, we recommend that you watch the talk DevCon23 - Developing, Publishing, and Maintaining Components for ESP-IDF or read the How to create an ESP-IDF component article.\nYou can also find components by browsing our ESP Registry platform.\nIn assignment 3.2, you will have a chance to create your own component and use it in your project.\nFrameworks # Also, ESP-IDF serves as the basis for several other frameworks, including:\nArduino for Espressif ESP-ADF (Audio Development Framework): Designed for audio applications. ESP-WHO (AI Development Framework): Focused on face detection and recognition. ESP-RainMaker: Simplifies building connected devices with cloud capabilities. ESP-Matter SDK: Espressif\u0026rsquo;s SDK for Matter is the official Matter development framework for ESP32 series SoCs. To see all the supported frameworks, please visit our GitHub organization page.\nESP-IDF Development # In addition to libraries, ESP-IDF includes the necessary tools to compile, flash, and monitor your device.\nYou can develop applications for Espressif devices using any plain text editor, such as Gedit or Notepad++, by following the manual installation guide provided in Espressif\u0026rsquo;s documentation.\nHowever, for this workshop, we will use an IDE (Integrated Development Environment) to streamline both development and setup. Espressif supports several IDEs, but we will focus on Visual Studio Code (VS Code). Espressif provides an official VS Code extension called ESP-IDF, which enables you to develop, compile, flash, and debug your projects directly within the editor.\nTo give you an idea, the ESP-IDF VS Code Extension manages the toolchain and gives you some useful commands which we will use later, such as:\n\u0026gt; ESP-IDF: Build Your Project \u0026gt; ESP-IDF: Set Espressif Device Target \u0026gt; ESP-IDF: Full clean project The character \u0026gt; indicates VS Code Command Palette, which can be opened by pressing F1 or Ctrl+Shift+P (or Cmd+Shift+P).\nAll these commands are wrappers around the main ESP-IDF front-end tool which is idf.py.\nHardware used in this workshop # In this workshop we will use an ESP32-C3 SoC based module, called ESP32-C3-Mini-1-N4. You can spot the ESP32-C3-Mini-1-N4 on your workshop board (see Fig. 3). The ESP32-C3 SoC is under the ESP32-C3-Mini-1-N4 shield.\nFig.3 - ESP32-C3 SoC, module, and workshop board\nESP32-C3 SoC # ESP32-C3 is a highly-integrated SoC equipped with a 32-bit RISC-V processor, supporting 2.4 GHz Wi-Fi and Bluetooth LE connectivity. The functional block diagram for ESP32-C3 is shown in Fig.4.\nFig.4 - ESP32-C3 Block Diagram\nESP32-C3 has the following features:\nA 32-bit RISC-V single-core processor @ 160 MHz.\nA Wi-Fi subsystem Supports Station mode, SoftAP mode, SoftAP + Station mode, and promiscuous mode.\nA Bluetooth LE subsystem\nSupports Bluetooth 5 and Bluetooth mesh.\nIntegrated memory\n400 KB SRAM and 384 KB ROM on the chip, external flash connection capability\nSecurity mechanisms\nCryptographic hardware accelerators, encrypted flash, secure bootloader\nA rich set of peripheral interfaces The 22 programmable GPIOs can be configured flexibly to support LED PWM, UART, I2C, SPI, I2S, ADC, TWAI, RMT, and USB Serial/JTAG applications.\nThe ESP32-C3 series of chips has several variants, including the version with in-package SPI flash. You can find them on the ESP32-C3 Series Comparison section of the datasheet. ESP8685 is a small package version of ESP32-C3.\nESP32-C3-Mini-1-N4 Module # In addition to SoCs, Espressif offers modules, which integrate an SoC, additional flash, (optionally) PSRAM memory, and a PCB antenna or an antenna connector. The main advantage of modules is not only their ease of use but also a simplified certification process.\nThe module we will use is the ESP32-C3-MINI-1-N4. As the name suggests, it includes 4MB of flash. If you\u0026rsquo;re curious about how to interpret the module part number, you can check the article Espressif part numbers explained: A complete guide - Modules on the Espressif Developer Portal .\nESP32-C3 Workshop board # Fig.5 - Workshop board\nBoard peripheral overview # You can find the schematic of the version 1 of the DevKit on the github page.\nI2C peripheral\nThis board includes the following peripherals over the I2C bus:\nPeripheral Part number Reference Crate Address IMU ICM-42670-P Datasheet Link 0x68 Temperature and Humidity SHTC3 Datasheet Link 0x70 I2C Bus Connection\nSignal GPIO SDA GPIO7 SCL GPIO8 GPIO\nThe following devices are connected through GPIO:\nI/O Devices GPIO WS2812 LED GPIO2 LED GPIO10 Button/Boot GPIO9 Power supply\nUSB type-C (no PD compatibility). Li-Ion battery charger - MCP73831T-2ACI/OT, it charges up to 4.2V. Recommendation: MCP73831T-2ACI/OT does not provide battery protection for over-current or over-discharge. For the battery (Li-Ion or Li-Po), it\u0026rsquo;s recommended to use the ones with embedded protection. Limitation: reading the battery voltage is not supported. Pin Layout\nLeft Side\nPin Number Description SoC 1 Reset EN/CHIP_PU 2 3V3 3 N/C 4 GND 5 IO0/ADC1-0 GPIO0 6 IO1/ADC1-1 GPIO1 7 IO2/ADC1-2 GPIO2 8 IO3/ADC1-3 GPIO3 9 IO4/ADC2-0 GPIO4 10 IO5/ADC2-1 GPIO5 11 IO6/MTCK GPIO6 12 IO7/MTDO/LED GPIO7 13 IO8/LOG GPIO8 14 IO21/U0RXD GPIO21 15 IO20/U0TXD GPIO20 16 IO9/BOOT GPIO9 Right Side\nPin Number Description SoC 1 VBAT 2 EN [1] 3 VBUS [2] 4 NC 5 NC 6 NC 7 NC 8 NC 9 IO18/USB_D- GPIO18 10 IO19/USB_D+ GPIO19 11 IO8/SCL GPIO8 12 IO10/SDA GPIO10 [1] Connected to LDO enable pin* [2] Connected to USB 5V* Schematics # You can find the board schematic on the KiCad Libraries GitHub Repository.\nConclusion # Now that we have a high-level overview of both hardware and firmware, we\u0026rsquo;re ready to start the first assignment.\nNext Step # Next Assignment → assignment 1.1\nOr go back to navigation menu\n","date":"5 August 2025","externalUrl":null,"permalink":"/workshops/esp-idf-basic/lecture-1/","section":"Workshops","summary":"In this lesson, we are preparing the ground for the first practical exercise. We introduce ESP-IDF, the official Espressif framework for IoT application development, then explore its architecture, main components, and development tools. We also examine the hardware used in the workshop, based on the ESP32-C3 SoC.","title":"ESP-IDF Basics - Lecture 1","type":"workshops"},{"content":" Internet connectivity # Applications communicate over the internet using different protocols, many of which are build on top of other protocols forming a layered structure.\nThe ISO/OSI model is a conceptual framework that breaks down how data (like messages, videos, or web pages) travels across networks — including Wi-Fi and Ethernet — into seven steps (layers). Each layer has its own job and uses specific protocols (rules or languages for communication).\nThe ISO/OSI model is typically visualized like on Fig.1.\nFig.1 - ISO OSI Stack\nStarting from the bottom, the layers are:\nPhysical - This is the actual hardware: radio signals, antennas, and frequencies.\nExample: Wi-Fi, Ethernet\nData Link - Controls the direct connection between devices (like your laptop and router) and handles things like access to the wireless channel.\nExample: MAC (Media Access Control)\nNetwork - Figures out how data gets from one network to another.\nExample: IP (Internet Protocol)\nTransport - Makes sure data is delivered correctly and in the right order.\nExamples: TCP (Transmission Control Protocol), UDP (User Datagram Protocol)\nSession - Manages and maintains connections between devices or applications.\nNo single protocol in Wi-Fi, but session handling happens in apps using things like NetBIOS, SMB, or TLS\nPresentation - Translates data so it\u0026rsquo;s readable on both ends (like turning an encrypted message back into text).\nExamples: SSL/TLS (used for encryption), JPEG, MP3, ASCII\nApplication - What the user sees: websites, video calls, email, etc.\nExamples: HTTP (web), HTTPS (secure web), SMTP (email), FTP (file transfer), DNS (domain names)\nSome of the layers of this conceptual framework can me managed by a single protocol. For instance the Ethernet protocol takes care of both the physical and the data link layers.\nHigher level protocols may use the same lower level stack. For instance the MQTT protocol sits at the same level as HTTP. Both of them make use of the TCP/IP stack.\nEncapsulation # The combination of the layers is done through encapsulation.\nEncapsulation is the process by which data is wrapped with protocol information at each layer of the network stack to facilitate proper transmission and delivery. In the context of a Wi-Fi network, application data is first encapsulated within a TCP segment, which provides reliable transport services. This TCP segment is then encapsulated within an IP packet, adding logical addressing and routing information necessary for delivery across networks. Finally, the IP packet is enclosed within a Wi-Fi (IEEE 802.11) frame or an Ethernet frame, which handles the physical and data link layer functions for wireless communication. Each layer adds its own header (and sometimes trailer) to the data unit, enabling modular and efficient network communication.\nA picture is worth more than a thousand words:\nFig.2 - Encapsulation\nSimply put, the whole content of the higher level is inside the payload or data field of the lower layer protocol.\nConnectivity in Espressif # Now that we have an understanding of the connectivity layers, let\u0026rsquo;s explore which ones are supported by Espressif.\nPhysical Layers # Espressif modules support three main physical layers, depending on the SoC:\nWi-Fi: Supported by all devices, it is used for connection to a router and then to the internet. It will be the focus of this workshop. BLE: In IoT, it is mainly used for direct communication with a smartphone and for provisioning (i.e. setting up credentials). Thread/Zigbee: IoT protocols that are used for local machine-to-machine (M2M) communication based on mesh topology (many to many connection). To connect to the internet, a Thread-to-Wi-Fi bridge is required. The Matter protocol utilizes all of these connectivity layers: BLE is used for provisioning, Thread enables low-power communication, and Wi-Fi is used for high-bandwidth data transfer. In this workshop, we will focus on Wi-Fi only. Let\u0026rsquo;s briefly review its topology.\nWi-Fi topology # In a Wi-Fi network, there are two main roles: Access Point (AP) (usually called softAP in Espressif) and Station (STA).\nThe Access Point (AP) is the central device (like a Wi-Fi router) that broadcasts the wireless network and connects stations to each other and to external networks like the internet. A Station (STA) is any device that connects to the AP. It can be a smartphone, laptop, or smart home device. The AP manages the wireless medium, while STAs communicate through the AP, not directly with each other (unless in ad hoc mode). This setup forms a basic infrastructure mode network, which is the most common type of Wi-Fi setup.\nFig.3 - STA vs AP\nEspressif\u0026rsquo;s modules can function in both modes. To connect to an AP, a station need the SSID (router network name) and the password.\nIn the first part of the assignment, we will put the Espressif device in AP mode and use our smartphone to connect to it.\nApplication layer protocols # In the Internet of Things (IoT), various communication protocols are used, with MQTT and HTTP being among the most common. MQTT is specifically designed for machine-to-machine (M2M) communication and is widely used to manage networks of sensors and actuators, particularly in home automation systems due to its lightweight and efficient messaging model.\nHTTP, on the other hand, is best known as the protocol behind the web, used to deliver HTML-based content. However, another major application of HTTP in IoT is for implementing REST APIs. These APIs are not intended for direct user interaction, but rather to be accessed by external applications or services.\nFor example, imagine a smart home web application that displays the status of various sensors in your house. Instead of connecting to each device individually, the application queries the REST API exposed by a sensor gateway, which acts as a bridge between the devices and the user interface.\nIn this webinar, we will use HTTP to serve a simple HTML page and implement a REST API, so let\u0026rsquo;s focus on these concepts.\nHTTP, HTML, and JSON: Serving Web Pages and Building REST APIs # HTTP can be used to serve HTML pages (like those viewed in web browsers) and structured data such as JSON, which is commonly used to implement REST APIs—mainly for communication between applications.\nHTTP Basics # HTTP (Hypertext Transfer Protocol) is the foundation of communication on the web, based on a simple client-server model. In this model, the client (such as a web browser or application) sends a request to a server, which processes it and returns a response.\nHTTP Requests # HTTP defines several request methods, each serving a specific purpose:\nGET - Retrieve data from the server POST - Send or create new data on the server PUT - Update existing data DELETE - Remove data HTTP Responses # After receiving a request, the server sends an HTTP response, which includes a status code to indicate the outcome. Common status codes include:\n200 OK - The request was successful 201 Created - A new resource was successfully created (usually after a POST) 400 Bad Request - The server couldn\u0026rsquo;t understand the request due to invalid syntax 401 Unauthorized - Authentication is required or has failed 404 Not Found - The requested resource does not exist 500 Internal Server Error - A general error occurred on the server Modern applications and IoT systems often use JSON (JavaScript Object Notation) to format and exchange data. This structured format is at the core of REST APIs, which allow clients to interact with server-side resources using standard HTTP methods.\nFig.4 - Client-server interaction\nHTML: Web Pages # HTML (HyperText Markup Language) is the standard language for creating web pages. With ESP-IDF, you can serve HTML pages directly from your embedded device using HTTP.\nThese HTML pages can be used to:\nDisplay real-time sensor readings Provide control interfaces (e.g., buttons or sliders to interact with GPIOs) Allow user configuration of network settings or parameters A simple HTML page served by an ESP device might look like this:\n\u0026lt;!DOCTYPE html\u0026gt; \u0026lt;html\u0026gt; \u0026lt;head\u0026gt; \u0026lt;title\u0026gt;ESP Sensor Dashboard\u0026lt;/title\u0026gt; \u0026lt;/head\u0026gt; \u0026lt;body\u0026gt; \u0026lt;h1\u0026gt;Living Room Sensor\u0026lt;/h1\u0026gt; \u0026lt;p\u0026gt;Temperature: 22.5°C\u0026lt;/p\u0026gt; \u0026lt;p\u0026gt;Humidity: 60%\u0026lt;/p\u0026gt; \u0026lt;/body\u0026gt; \u0026lt;/html\u0026gt; In Fig.5 you can see the HTML code rendering.\nFig.5 - HTML page rendering\nServing HTML content from your ESP device allows users to interact with it through any web browser, with no additional software required.\nJSON: REST API # JSON is a lightweight, human-readable format used to represent structured data. It\u0026rsquo;s ideal for web and IoT applications to exchange information between clients and servers.\nA JSON object is made up of key-value pairs. Here\u0026rsquo;s a simple example:\n{ \u0026#34;temperature\u0026#34;: 22.5, \u0026#34;humidity\u0026#34;: 60, \u0026#34;sensor\u0026#34;: \u0026#34;living_room\u0026#34; } In this case, the object represents a reading from a sensor in the living room.\nREST API # A REST API (Representational State Transfer Application Programming Interface) allows applications to interact with a server using standard HTTP methods. It follows the client-server model, with the server usually responding with JSON-formatted data and an appropriate HTTP status code.\nREST APIs organize access to resources through routes, or URL paths, which are typically human-readable and logically structured.\nExample REST API routes:\nGET /sensors - Retrieve a list of all sensors GET /sensors/42 - Retrieve data for sensor with ID 42 POST /sensors - Create a new sensor PUT /sensors/42 - Update sensor 42\u0026rsquo;s settings DELETE /sensors/42 - Delete sensor 42 This approach allows easy access and manipulation of data, making REST APIs ideal for modern web and IoT applications.\nIn the second part of this workshop, you will implement both a simple HTML page and a REST API using HTTP. These examples will help you understand how to serve web content and expose device data to external applications.\nConclusion # This article introduced the layered structure of internet communication, focusing on the ISO/OSI model and its practical use in Wi-Fi networks. We explored how protocols like HTTP and MQTT operate within this framework, how encapsulation allows data to flow through the layers, and how REST APIs enable structured, JSON-based communication between devices and applications. These concepts form the foundation for building modern, connected IoT systems.\nNow you have all the technical background to start the assignments.\nNext step # Next assignment → Assignment 2.1\nOr go back to navigation menu\n","date":"5 August 2025","externalUrl":null,"permalink":"/workshops/esp-idf-basic/lecture-2/","section":"Workshops","summary":"In this lesson, we introduce the layered structure of Internet communication, explaining the ISO/OSI model and the data encapsulation process. We also explore HTTP and MQTT protocols, showing how REST APIs and the JSON format enable communication between IoT devices and applications.","title":"ESP-IDF Basics - Lecture 2","type":"workshops"},{"content":" Introduction # As we saw earlier, ESP-IDF contains several libraries, from FreeRTOS \u0026mdash; the operating system which manages all tasks \u0026mdash; to the peripheral drivers and protocol libraries. Including the libraries for every possible protocol, algorithm, or driver inside ESP-IDF is not possible: It\u0026rsquo;s size would increase dramatically. If you need a specific protocol, you can probably find it\u0026rsquo;s C implementation somewhere on Github. In this case, the challenge will be to port it to ESP-IDF, taking care of finding all dependencies and informing the build system about which files should be compiled and linked.\nTo solve these problem, Espressif developed a component system similar to a package system in GNU/Linux distributions. The components take care of the dependencies and the build system and you can simply include the header file and you\u0026rsquo;re ready to go! Like in the case of Linux packages, there is also a component manager and a component registry, where you can find all the official packages by Espressif. Once, components are included, the idf.py tool will download the component and set the stage for its use.\nFor additional information, we recommend that you watch the talk DevCon23 - Developing, Publishing, and Maintaining Components for ESP-IDF.\nWe will explore the differences in the use of the integrated libraries and the ones provided by the component registry. We will also see how to create a component, in order to make reusable code.\nWe will explore how to:\nInclude and use the gpio and the i2c libraries (included) See how and use the button component (registry) Create a new component During the assignments, the goal will be to control the LED and the I2C sensor (SHTC3) on the board (see Fig. 1).\nFig.1 - GPIO connected to the LED\nIncluded Libraries # Let’s take a look at how to use the included libraries. This usually involves three main steps:\nLet the build system know about the library (include the header file and update CMakeLists.txt) Configure the library settings Use the library by calling its functions GPIO # A GPIO (General-Purpose Input/Output) peripheral is a digital interface on a microcontroller or processor that allows it to read input signals (like button presses) or control output devices (like LEDs) through programmable pins. These pins can be configured individually as either input or output and are commonly used for basic device interfacing and control.\nOn our board, we have an LED connected to the GPIO10 (see Fig. 1) and we will use this pin for the example.\nIncluding the library # To include the gpio library, we first need to include the header file and tell the build system where to find it.\nWe need first to include\n#include \u0026#34;driver/gpio.h\u0026#34; and then add to CMakeList.txt\nREQUIRES esp_driver_gpio Note that the header file and the required path are different: When including a library, make sure you check the programming guide first.\nTo find the string for the REQUIRES path, do the following:\nOpen the ESP-IDF Programming Guide In the upper left corner, choose the SoC (in our case, ESP32-C3) Find the relevant peripheral API reference (in our case, GPIO) In the peripheral API reference, find the Header File section for the required header (in our case, normal GPIO) Configuration # Peripherals have many settings (input/output, frequency, etc). You need to confiure them before using the peripherals.\nIn case of GPIO, a basic configuration is\n//zero-initialize the config structure. gpio_config_t io_conf = {}; //disable interrupt io_conf.intr_type = GPIO_INTR_DISABLE; //set as output mode io_conf.mode = GPIO_MODE_OUTPUT; //bit mask of the pins that you want to set,e.g.GPIO18/19 io_conf.pin_bit_mask = GPIO_OUTPUT_PIN_SEL; //disable pull-down mode io_conf.pull_down_en = 0; //disable pull-up mode io_conf.pull_up_en = 0; //configure GPIO with the given settings gpio_config(\u0026amp;io_conf); In this workshop, we will use GPIO for output. Due to this, we won\u0026rsquo;t talk about:\nInterrupts (trigger a function when the input changes) Pull-up and pull-down (set a default input value) The only field that needs some explanation is the pin_bit_mask. The configuration refers to the whole GPIO peripheral. In order to apply the configuration only to certain pins (via gpio_config), we need to specify the pins via a bit mask. The pin_bit_mask is set equal to GPIO_OUTPUT_PIN_SEL which is\n#define GPIO_OUTPUT_LED 10 #define GPIO_OUTPUT_PIN_SEL (1ULL\u0026lt;\u0026lt;GPIO_OUTPUT_LED) // i.e. 0000000000000000000000000000010000000000 If you want to apply the configuration to more than one GPIO, you need to OR them. For example:\n#define GPIO_OUTPUT_LED 10 #define GPIO_OUTPUT_EXAMPLE 12 #define GPIO_OUTPUT_PIN_SEL ((1ULL\u0026lt;\u0026lt;GPIO_OUTPUT_LED) | (GPIO_OUTPUT_EXAMPLE))// i.e. 0000000000000000000000000001010000000000 Usage # Once the peripheral is configured, we can use the function gpio_set_level to set the GPIO output to either 0 or 1. The header file:\ngpio_set_level(GPIO_OUTPUT_LED, 1); // turns led on gpio_set_level(GPIO_OUTPUT_LED, 0); // turns led off I2C # I2C (Inter-Integrated Circuit) is a communication protocol that uses only two wires—SDA (data line) and SCL (clock line)—to transmit data between devices. Usually, it is used to connect a microcontroller to an external sensor or actuator. It allows multiple peripherals to communicate with a microcontroller using unique addresses, enabling efficient and scalable device interconnection.\nIncluding the library # Consulting the corresponding programming guide section we get the header file\n#include \u0026#34;driver/i2c_master.h\u0026#34; and value for the CMakeList.txt\nREQUIRES esp_driver_i2c Configuration # A configuration has the following form:\ni2c_master_bus_config_t bus_config = { .i2c_port = I2C_NUM_0, .sda_io_num = I2C_MASTER_SDA_IO, .scl_io_num = I2C_MASTER_SCL_IO, .clk_source = I2C_CLK_SRC_DEFAULT, .glitch_ignore_cnt = 7, .flags.enable_internal_pullup = true, }; i2c_new_master_bus(\u0026amp;bus_config, bus_handle); i2c_device_config_t dev_config = { .dev_addr_length = I2C_ADDR_BIT_LEN_7, .device_address = SHTC3_SENSOR_ADDR, .scl_speed_hz = 400000, }; i2c_master_bus_add_device(*bus_handle, \u0026amp;dev_config, dev_handle); The values for our board are (see Fig. 1)\n#define I2C_MASTER_SDA_IO 7 #define I2C_MASTER_SCL_IO 8 #define SHTC3_SENSOR_ADDR 0x70 The other macros are defined internally.\nComponent registry # Use a component from the registry - button # For our last external library (button), we will use the component manager and registry.\nGo to the component registry Search for the button component (espressif/button) Copy the instruction on the left (see Fig.2) - idf.py add-dependency \u0026quot;espressif/button^4.1.3\u0026quot; In VSCode: \u0026gt; ESP-IDF: Open ESP-IDF Terminal and paste the instruction Fig.2 - espressif/button component\nYou should get a message\nExecuting action: add-dependency NOTICE: Successfully added dependency \u0026#34;espressif/button\u0026#34;: \u0026#34;^4.1.3\u0026#34; to component \u0026#34;main\u0026#34; NOTICE: If you want to make additional changes to the manifest file at path \u0026lt;user_path\u0026gt;/blink/main/idf_component.yml manually, please refer to the documentation: https://docs.espressif.com/projects/idf-component-manager/en/latest/reference/manifest_file.html A new file idf_component.yml has been created in your project with the following content:\ndependencies: espressif/led_strip: ^2.4.1 espressif/button: ^4.1.3 You can add dependencies directly in this file, but it\u0026rsquo;s recommended to use idf.py add-dependency utility.\nTo use the component, you have to include the appropriate header file and call the functions given in the component documentation and folder.\nCreate a component # For detailed instructions on how to create a component using the CLI, you can refer to the article How to create an ESP-IDF component on the Espressif Developer Portal.\nIn VSCode, you can follow a similar flow:\nCreate a new project Create a new component by calling \u0026gt; ESP-IDF: Create New ESP-IDF Component Give the component a name (e.g. led_toggle) The project will now contain a components folder and all the required files\n. └── project_folder/ ├── components/ │ └── led_toggle/ │ ├── include/ │ │ └── led_toggle.h │ ├── CMakeList.txt │ └── led_toggle.c ├── main └── build Each time you create or download a component, you need to perform a project full cleal by calling:\n\u0026gt; ESP-IDF: Full Clean Project\nYou can then include your component in the main file as led_toggle.h.\nConclusion # In this short lecture, we explored two main ways to include external libraries: directly through the CMakeLists.txt file and via the component registry. We covered how to include and use libraries with both methods and explained how to create a custom component from scratch using VSCode. Now it\u0026rsquo;s time to put these concepts into practice in the upcoming assignments.\nNext step # Next assignment → Assignment 3.1\nOr go back to navigation menu\n","date":"5 August 2025","externalUrl":null,"permalink":"/workshops/esp-idf-basic/lecture-3/","section":"Workshops","summary":"In this lecture we\u0026rsquo;ll explore how to include libraries inside ESP-IDF, external libraries, and components from the ESP Component Registry","title":"ESP-IDF Basics - Lecture 3","type":"workshops"},{"content":"","date":"5 August 2025","externalUrl":null,"permalink":"/series/ws00a/","section":"Series","summary":"","title":"WS00A","type":"series"},{"content":"","date":"5 August 2025","externalUrl":null,"permalink":"/series/ws00b/","section":"Series","summary":"","title":"WS00B","type":"series"},{"content":"When developing IoT products, one of the key challenges is ensuring fast and reliable device restoration after reboots or power cycles. This is especially important in applications like lighting control, where devices are expected to resume operation immediately.\nIn this post, we examine the ESP-IDF boot-up flow and highlight strategies to accelerate restoration by restoring device state during the bootloader stage — before the application is even loaded.\nESP-IDF Boot Flow: Overview # The ESP-IDF boot process consists of multiple stages that ensure secure and reliable startup:\nFirst-Stage Bootloader (ROM Bootloader):\nInitializes basic components and loads the second-stage bootloader from flash (basic read mode). Performs SHA-256 hash validation of the bootloader image. If Secure Boot is enabled, digital signature verification (e.g., RSA or ECDSA) is also done. Second-Stage Bootloader:\nStored in flash and performs more advanced tasks like clock and peripheral initialization (e.g., flash quad mode). Verifies the application image’s integrity using a SHA-256 hash and, if Secure Boot is enabled, cryptographic signature checks. Application Execution:\nOnce verified, control is passed to the application image. This flow ensures system integrity and protection, but adds latency — particularly as the size of the application image increases.\nImpact of Integrity Checks on Boot Time # Both the second-stage bootloader and the application image go through integrity validation. When Secure Boot is enabled, this includes digital signature verification using asymmetric cryptography.\nESP32-C3: Boot Time to Application The most time-consuming factor during boot is reading and verifying artifacts from external SPI flash. Since the bootloader is relatively small, its verification completes quickly. However, verifying the application image can take a significant amount of time and scales with its size. While security features like Secure Boot and Flash Encryption add some overhead, the application image size has the greatest impact on the overall boot time.\nLet\u0026rsquo;s see how the default device restoration time looks like with 2MB application image size:\nDefault Restoration Time ESP-IDF also provides configuration options to skip application image integrity checks - only for Secure Boot disabled cases. These options include:\nCONFIG_BOOTLOADER_SKIP_VALIDATE_ALWAYS CONFIG_BOOTLOADER_SKIP_VALIDATE_ON_POWER_ON These options can reduce boot time by avoiding application integrity step. However, this approach is not recommended in most production use-cases, as it could mask potential flash corruption and lead to the execution of tampered or damaged firmware. For safety and reliability, it is advisable to keep all integrity checks enabled.\nAnother way to accelerate device restoration is by using the bootloader.\nFaster Restoration Using Bootloader # When it comes to IoT, speed isn’t just about performance — it\u0026rsquo;s about perception. Imagine walking into a room, flipping a switch, and your smart lighting takes half a second too long to react. That lag, however minor, breaks the illusion of instant control.\nTo address this, the device restoration can be moved in the bootloader, rather than waiting for the application image to come up. This allows the device to respond immediately, without compromising security or reliability.\nBootloader restoration involves:\nDevice driver code to interact with peripherals Reading device state from (encrypted) flash storage Device Drivers in Bootloader # ESP-IDF\u0026rsquo;s HAL APIs (Non-OS based) allow interacting with peripherals like I2C, SPI, or RMT during the bootloader phase — for example, to restore LED brightness levels or update display state. Please note that HAL APIs are not intended to be stable across different ESP-IDF versions but provide a good initial reference.\nHowever, since bootloader code is non-upgradeable, any driver code must be minimal, reliable, and well-tested.\nNote: Recent targets like ESP32-C5 support safe bootloader updates, allowing you to modify the bootloader code for bug fixes or enhancements. However, this is not available on all ESP32 variants.\nGetting Device State from NVS # NVS (Non-Volatile Storage) is a logging based file-system component (in ESP-IDF) with consideration for flash wear levelling in its design and hence an ideal choice to store frequently changing device state data on the flash. ESP-IDF now supports a lightweight, read-only NVS (Non-Volatile Storage) implementation in the second-stage bootloader. This allows device state (such as configuration or previous runtime values) to be easily accessible during the bootloader stage.\nBootloader: Lightweight Read-Only NVS This capability is made available via bootloader_hooks. ESP-IDF supports bootloader customization, as specified in the Custom Bootloader guide. The NVS bootloader example provides a complete reference implementation.\nSupport for Encrypted NVS # The bootloader can now read from encrypted NVS partitions. Targets with AES hardware acceleration use it to perform XTS-AES decryption. On devices without such hardware (e.g., ESP32-C2), decryption is handled via the mbedTLS implementation in ROM.\nBootloader Size Considerations # When Secure Boot v2 is enabled, the total bootloader size limits for each target can be found in the Bootloader Size guide. The additional space used by the NVS read-only implementation (including decryption support) is optimized to stay under 5 KB.\nHowever, if you include additional device driver code, ensure the total size fits within the maximum bootloader size limit.\nPractical Example and Benchmark # We created a demo application to test and validate the bootloader NVS restoration method. You can find the source code here:\n👉 Example: Faster Device State Restoration\nThe project simulates a lighting product where the last known state is restored during the bootloader stage.\nFeature Baseline Approach Bootloader Optimization Restoration Time 405 ms \u0026lt; 90 ms Application Image Size 1.25 MB 1.25 MB Secure Boot Enabled Enabled Flash/NVS Encryption Enabled Enabled Let\u0026rsquo;s see how the optimized device restoration time looks like per above application size:\nOptimized Restoration Time By restoring the device state before the application image is even verified, we reduce startup latency significantly. As application images grow larger, this optimization offers even more noticeable gains.\nSummary # To reduce device boot time:\nSome may consider reducing the image size or skipping certain checks, but this can compromise security or reliability. A more robust approach is to move device state restoration to the bootloader, enabling faster responsiveness while retaining all integrity and security checks. This method provides the best of both worlds — faster restoration without sacrificing security or reliability.\n","date":"18 July 2025","externalUrl":null,"permalink":"/blog/2025/07/faster-device-restoration/","section":"Blog","summary":"Fast and secure device restoration during boot-up is critical for real-time IoT applications like smart lighting. In this article, we explore how to reduce boot-up delays by restoring device state early, directly from the ESP-IDF bootloader.","title":"Boot Secure, Restore Smart: Accelerating Device Startup on ESP32","type":"blog"},{"content":" Overview # What is ESP H.264? # Espressif has recently launched the esp_h264 component for ESP32 series microcontrollers, which through hardware acceleration, dynamic scheduling and lightweight algorithms, is able to balance the computing power and power consumption of video codec.\nKey Features # Hardware Acceleration: Leverages ESP32-P4 for hardware encoding and high-speed decoding, with single-instruction, multiple-data (SIMD) acceleration on ESP32-S3 for enhanced efficiency Memory Optimization: Implements advanced algorithms to minimize memory usage, ensuring stable operation on resource-constrained devices Dynamic Configuration: Flexible parameter adjustment for real-time optimization of performance, resource allocation, and video quality Advanced Encoding: Supports Baseline profile, high-quality I/P frame generation, ROI encoding, and bitrate control Efficient Decoding: Software-based parsing of standard H.264 streams for smooth video playback Target Applications # esp_h264 main applications are:\nVideo surveillance systems Remote meetings and communication Mobile streaming applications IoT video processing CODEC specifications # Encoding # Platform Type Max Resolution Max Performance Advanced Features ESP32-S3 Software Any 320×240@11fps Basic encoding ESP32-P4 Hardware ≤1080P 1920×1080@30fps Dual encoding, ROI optimization, Motion vector output Decoding # Platform Type Max Resolution Max Performance ESP32-S3 Software Any 320×240@19fps ESP32-P4 Software Any 1280×720@10fps Getting Started # Basic Workflow # The hardware encoding standardization process can be summarized into four core operations:\nInitialize: Create encoder with configuration parameters Start: Open the encoder for processing Process: Execute frame-by-frame encoding in a loop Cleanup: Release resources and destroy encoder object Quick Start Example # // Hardware single-stream encoding configuration example esp_h264_enc_cfg_hw_t cfg = {0}; cfg.gop = 30; cfg.fps = 30; cfg.res = {.width = 640, .height = 480}; cfg.rc = { .bitrate = (640 * 480 * 30) / 100, .qp_min = 26, .qp_max = 30 }; cfg.pic_type = ESP_H264_RAW_FMT_O_UYY_E_VYY; // Initialize encoder esp_h264_enc_t *enc = NULL; esp_h264_enc_hw_new(\u0026amp;cfg, \u0026amp;enc); // Allocate input/output buffers esp_h264_enc_in_frame_t in_frame = {.raw_data.len = 640 * 480 * 1.5}; in_frame.raw_data.buffer = esp_h264_aligned_calloc(128, 1, in_frame.raw_data.len, \u0026amp;in_frame.raw_data.len, ESP_H264_MEM_INTERNAL); // Start encoding esp_h264_enc_open(enc); // Encoding loop while (capture_frame(in_frame.raw_data.buffer)) { esp_h264_enc_process(enc, \u0026amp;in_frame, \u0026amp;out_frame); send_packet(out_frame.raw_data.buffer); } // Resource release esp_h264_enc_close(enc); esp_h264_enc_del(enc); esp_h264_free(in_frame.raw_data.buffer); API Reference # The following section provides a brief overview of the available functions. These functions are thread-safe and can be called at any time during the encoder lifecycle. Encoding functions # Function Description Platform Support esp_h264_enc_sw_new Create single-stream software encoder ESP32-S3, ESP32-P4 esp_h264_enc_hw_new Create single-stream hardware encoder ESP32-P4 only esp_h264_enc_dual_hw_new Create dual-stream hardware encoder ESP32-P4 only esp_h264_enc_open Start encoder All platforms esp_h264_enc_process Execute encoding for a single frame and output compressed data All platforms esp_h264_enc_close Stop encoder All platforms esp_h264_enc_del Release encoder resources All platforms Decoding functions # Function Description Platform Support esp_h264_dec_sw_new Create software decoder ESP32-S3, ESP32-P4 esp_h264_dec_open Start decoder All platforms esp_h264_dec_process Execute decoding for a single frame and output raw data All platforms esp_h264_dec_close Stop decoder All platforms esp_h264_dec_del Release decoder resources All platforms Dynamic Parameter Control # Function Description Typical Use Cases esp_h264_enc_get_resolution Get resolution information Display configuration esp_h264_enc_get/set_fps Dynamically adjust frame rate Network bandwidth adaptation esp_h264_enc_get/set_gop Dynamically adjust GOP size Quality vs. bandwidth balance esp_h264_enc_get/set_bitrate Dynamically adjust bitrate Network bandwidth adaptation Advanced Features # This section highlights advanced capabilities of the H.264 encoder that offer greater control and flexibility for specialized use cases. These features include region-based quality adjustments, motion vector extraction for video analysis, and dual-stream encoding support on the ESP32-P4.\nRegion of Interest (ROI) Encoding # ROI encoding allows you to allocate more bits to important areas of the frame while reducing quality in less critical regions.\nROI Configuration\n// Set the center area for high-priority encoding esp_h264_enc_roi_cfg_t roi_cfg = { .roi_mode = ESP_H264_ROI_MODE_DELTA_QP, .none_roi_delta_qp = 10 // Increase QP by 10 for non-ROI region }; ESP_H264_CHECK(esp_h264_enc_hw_cfg_roi(param_hd, roi_cfg)); // Define the center 1/4 area as ROI esp_h264_enc_roi_reg_t roi_reg = { .x = width / 4, .y = height / 4, .len_x = width / 2, .len_y = height / 2 }; ESP_H264_CHECK(esp_h264_enc_hw_set_roi_region(param_hd, roi_reg)); ROI API Functions\nFunction Description Use Cases esp_h264_enc_cfg_roi Configure ROI parameters Key encoding for faces, license plates esp_h264_enc_get_roi_cfg_info Get current ROI configuration Status monitoring esp_h264_enc_set_roi_region Define ROI regions Specific area enhancement esp_h264_enc_get_roi_region Get ROI region information Configuration verification Motion Vector Extraction # Extract motion vector data for video analysis and post-processing applications.\nMotion Vector API Functions\nFunction Description Use Cases esp_h264_enc_cfg_mv Configure motion vector output Video analysis setup esp_h264_enc_get_mv_cfg_info Get motion vector configuration Configuration verification esp_h264_enc_set_mv_pkt Set motion vector packet buffer Data collection esp_h264_enc_get_mv_data_len Get motion vector data length Buffer management Dual-Stream Encoding (ESP32-P4 Only) # ESP32-P4 supports simultaneous encoding of two independent video streams with different parameters.\n// Main stream 1080P storage, sub-stream 480P transmission esp_h264_enc_cfg_dual_hw_t dual_cfg = {0}; dual_cfg.cfg0 = {.res = {1920, 1080}, .bitrate = 4000000}; // Main stream dual_cfg.cfg1 = {.res = {640, 480}, .bitrate = 1000000}; // Sub-stream ESP_H264_CHECK(esp_h264_enc_dual_hw_new(\u0026amp;dual_cfg, \u0026amp;enc)); Application Scenarios \u0026amp; Best Practices # The following examples demonstrate how to apply advanced encoding features to meet specific use-case requirements. Each scenario outlines an optimal configuration strategy, showcasing how ROI, bitrate control, and motion vectors can be tailored for performance, privacy, or adaptability.\n1. Video Surveillance # In video surveillance applications, it\u0026rsquo;s critical to maintain high visual fidelity in regions that contain important details—such as faces, license plates, or motion-detected areas—while conserving bandwidth and storage elsewhere. ROI (Region of Interest) encoding allows the encoder to prioritize such regions by allocating more bits, thereby enhancing clarity where it matters most.\nOptimal Configuration:\nEnable ROI encoding to enhance key visual areas. GOP = 30 ensures a keyframe every second at 30 fps, balancing video seekability and compression. QP range: [20–35] provides a controlled balance between compression efficiency and perceptual quality, especially in bandwidth-constrained environments. // Surveillance optimized configuration esp_h264_enc_cfg_hw_t surveillance_cfg = { .gop = 30, .fps = 25, .res = {1280, 720}, .rc = { .bitrate = 2000000, .qp_min = 20, .qp_max = 35 } }; ROI Setup for Key Areas: To further refine quality, specific regions—such as the center of the frame or areas flagged by motion detection—can be configured for lower quantization parameters (QPs), resulting in better detail preservation.\nReduce QP in key regions by up to 25%, improving clarity for facial recognition or license plate reading. Leverage motion vector data to dynamically track and adapt ROI regions for intelligent, resource-efficient surveillance. 2. Privacy Protection # In scenarios where privacy is a concern—such as public-facing cameras or indoor monitoring—specific regions of the video may need to be intentionally blurred. This can be achieved by strategically increasing the quantization parameter (QP) in those regions, reducing detail without additional processing overhead.\nImplementation Strategy:\nIncrease QP by 25% in ROI areas to achieve blur effect Use fixed GOP to prevent mosaic area diffusion // Privacy protection ROI configuration esp_h264_enc_roi_cfg_t privacy_cfg = { .roi_mode = ESP_H264_ROI_MODE_DELTA_QP, .none_roi_delta_qp = -5 // Better quality for non-sensitive areas }; // Blur sensitive area esp_h264_enc_roi_reg_t blur_region = { .x = sensitive_x, .y = sensitive_y, .len_x = sensitive_width, .len_y = sensitive_height, .qp = 15 // High QP for blur effect }; 3. Network Adaptive Streaming # For real-time video applications operating over variable or constrained networks, maintaining a stable and responsive stream is essential. By dynamically adjusting encoding parameters such as bitrate and frame rate based on current bandwidth conditions, the encoder can optimize video quality while minimizing buffering and transmission failures.\nStrategy:\nEnable dynamic bitrate control (CBR/VBR) Adjust parameters based on network conditions // Network adaptation function void adapt_to_network_conditions(esp_h264_enc_handle_t enc, uint32_t available_bandwidth) { esp_h264_enc_param_hw_handle_t param_hd; esp_h264_enc_hw_get_param_hd(enc, \u0026amp;param_hd); if (available_bandwidth \u0026lt; 1000000) { // \u0026lt; 1 Mbps esp_h264_enc_set_bitrate(\u0026amp;param_hd-\u0026gt;base, 800000); esp_h264_enc_set_fps(\u0026amp;param_hd-\u0026gt;base, 15); } else if (available_bandwidth \u0026lt; 3000000) { // \u0026lt; 3 Mbps esp_h264_enc_set_bitrate(\u0026amp;param_hd-\u0026gt;base, 2000000); esp_h264_enc_set_fps(\u0026amp;param_hd-\u0026gt;base, 25); } else { // \u0026gt;= 3 Mbps esp_h264_enc_set_bitrate(\u0026amp;param_hd-\u0026gt;base, 4000000); esp_h264_enc_set_fps(\u0026amp;param_hd-\u0026gt;base, 30); } } Resources and Support # Development Resources # Sample Projects: ESP H.264 Sample Projects Component Registry: ESP H.264 Component Release Notes: Latest updates and compatibility information Technical Support # Official Forum: Espressif Technical Support GitHub Issue Tracker: ESP-ADF Issues Conclusion # Espressif\u0026rsquo;s lightweight H.264 codec component esp_h264 is designed for efficient video processing on resource-constrained devices. This comprehensive guide analyzes its core advantages from four dimensions: technical features, API interfaces, application scenarios, and troubleshooting, thereby helping developers unlock the potential of embedded video codec.\nWhether you\u0026rsquo;re building a surveillance system, implementing video streaming, or developing innovative multimedia applications, ESP H.264 offers the tools and performance needed to succeed in resource-constrained environments.\n","date":"18 July 2025","externalUrl":null,"permalink":"/blog/2025/07/esp-h264-use-tips/","section":"Blog","summary":"This article introduces Espressif\u0026rsquo;s esp_h264 component, a lightweight H.264 codec optimized for embedded devices. It shows how to leverage hardware acceleration, implement efficient video processing, and optimize performance for various applications.","title":"ESP H.264 Practical Usage Guide","type":"blog"},{"content":"","date":"18 July 2025","externalUrl":null,"permalink":"/tags/h.264/","section":"Tags","summary":"","title":"H.264","type":"tags"},{"content":"","date":"18 July 2025","externalUrl":null,"permalink":"/authors/harshal-patil/","section":"Developer Portal Authors","summary":"","title":"Harshal Patil","type":"authors"},{"content":" Introduction # As AI agents and language models become increasingly capable, the next frontier lies in enabling them to interact with the real world. For users of ESP RainMaker, this means letting AI tools query and control IoT devices using natural language prompts and seamlessly integrate with their existing workflows.\nTo support this shift, ESP RainMaker now has a local Model Context Protocol (MCP) server implementation. This integration allows tools like Claude Desktop, Cursor, Gemini CLI, Windsurf, etc., to interact with your RainMaker devices using natural language prompts, securely and locally.\nThis post introduces the MCP standard, explains how it connects AI to tools, and explores how the ESP RainMaker MCP server fits into this ecosystem.\nWhat is the Model Context Protocol (MCP)? # The Model Context Protocol (MCP) is a major development in AI infrastructure. Introduced by Anthropic in late 2024 and since adopted by OpenAI, Google DeepMind, and others, it defines a unified way for AI systems to access tools, data sources, and services—regardless of vendor or use case.\nMCP is often compared to USB-C for AI. Just as USB-C provides a universal interface to connect monitors, storage, and peripherals, MCP standardizes how AI models invoke external tools.\nBefore MCP, most integrations were bespoke and fragile—one-off bridges between models and services. MCP simplifies this through a consistent transport protocol and tool interface.\nKey Functions of MCP # Accessing Up-to-Date Information: Enables AI models to access real-time information (e.g., weather, news, sensor data). Interacting with Specialized Tools: Allows models to invoke domain-specific services like a calendar, a document viewer, or a CLI tool. Executing Actions: Empowers AI systems to go beyond passive querying and perform actions—such as sending emails, starting jobs, or (in our case) controlling IoT devices like lights, thermostats, and schedules. ESP RainMaker MCP Server # The ESP RainMaker MCP Server bridges MCP clients with the esp-rainmaker-cli, which in turn communicates with the ESP RainMaker backend.\nThis makes it possible for tools like Claude, Cursor, Gemini CLI, Windsurf, etc., to control your IoT devices, read their parameters, or modify schedules—through simple prompts.\nKey Capabilities # Device Management: List nodes, check statuses, and read parameter values. Control Commands: Change device states like power, brightness, temperature. Schedule Handling: Add, edit, or remove schedules across devices or rooms. Group Management: Create homes/rooms and bulk-assign devices logically. Authentication Integration: Leverages the secure login flow of esp-rainmaker-cli. Example Workflows # Once set up, users can invoke tools using natural prompts such as:\n\u0026ldquo;Show me my home structure and devices in it\u0026rdquo; “List all my RainMaker devices” “Turn off the living room lights” “Schedule the heater to turn on at 6 AM on weekdays” “Group all outdoor lights into a new room called ‘Garden’” \u0026ldquo;I just left from home. Can you check if I locked properly and turned off everything?\u0026rdquo; \u0026ldquo;Can you check the air quality and turn on my purifier if required\u0026rdquo; (may need other MCP server to fetch air quality data) \u0026ldquo;Turn on my lights an hour before sunset\u0026rdquo; (may need other MCP server to fetch sunset time) \u0026ldquo;Do you think I will need to use the AC in next few days?\u0026rdquo; (may need other MCP server to fetch weather data) These requests are automatically interpreted by the LLM, mapped to the correct tool calls, and executed via the local MCP server—without needing to write custom code or scripts.\nSamples with Claude Desktop # MCP Server Architecture # MCP is based on a client-server model:\nMCP Client: Typically integrated into an AI interface (e.g., Claude, Cursor, Gemini CLI, Windsurf, etc.). It handles the interaction with users and passes tool invocation requests to the server. MCP Server: Implements a set of tools and wraps external services. It exposes a standard interface for tool discovery, execution, and result formatting. What Happens During a Call? # The client discovers local MCP servers and their available tools. The LLM is made aware of the tools via context sharing. The LLM response includes structured tool call(s) it wants the client to execute. The client invokes the appropriate MCP tool locally. The MCP server translates that into a backend call, CLI command, or other operation. The result is passed back to the LLM as context for follow-up reasoning or response generation. This approach provides a secure, local-first mechanism for models to interact with software and hardware systems.\nTransport Modes # MCP currently supports two transport types:\nStdio-based: The current ESP RainMaker MCP server operates via standard input/output, suitable for local integration with clients like Claude Desktop, Cursor, Gemini CLI, Windsurf, etc. HTTP-based: Future variant may support HTTP-based transport, allowing deployment in cloud or containerized environments without requiring explicit setup on the user\u0026rsquo;s machine. This flexibility opens the door to broader adoption, including integration into backend agents or voice assistants.\nRepository and Setup # The project is available at:\nhttps://github.com/espressif/esp-rainmaker-mcp\nThe repository includes:\nFull usage instructions Supported tools and parameters Configuration steps for Claude Desktop, Cursor, Gemini CLI, and Windsurf We invite developers, partners, and AI tool builders to try out the server, provide feedback, and build on top of this foundation.\n","date":"18 July 2025","externalUrl":null,"permalink":"/blog/2025/07/esp-rainmaker-mcp-server/","section":"Blog","summary":"ESP RainMaker now supports the Model Context Protocol (MCP), enabling natural language interactions with your IoT devices via tools like Claude, Cursor, Gemini CLI, Windsurf, etc. This blog introduces the new stdio-based MCP server, outlines use cases, and hints at what’s next.","title":"Introducing ESP RainMaker MCP Server","type":"blog"},{"content":"","date":"18 July 2025","externalUrl":null,"permalink":"/tags/mcp/","section":"Tags","summary":"","title":"MCP","type":"tags"},{"content":"","date":"18 July 2025","externalUrl":null,"permalink":"/tags/performance-tuning/","section":"Tags","summary":"","title":"Performance Tuning","type":"tags"},{"content":"","date":"18 July 2025","externalUrl":null,"permalink":"/authors/piyush-shah/","section":"Developer Portal Authors","summary":"","title":"Piyush Shah","type":"authors"},{"content":" Introduction # In Part 1 of this series, we introduced the upcoming requirements of the RED Delegated Act (DA) and the associated harmonized standard EN 18031, which comes into effect in August 2025. These new obligations place a strong emphasis on cybersecurity, privacy, and protection against network abuse for all radio-connected products entering the European market.\nWith the compliance deadline drawing closer, Espressif is taking proactive steps to simplify and accelerate the path to RED DA compliance for developers building with our chipsets and modules.\nDocumentation Templates – Foundation for Compliance # To further assist customers, we have prepared technical document templates for the ESP32 series of SoCs. These templates are intended to assist manufacturers in preparing RED-DA self-assessment compliance documentation for products based on the ESP32 series of SoCs.\nThese templates are being developed in close collaboration with Brightsight to ensure they meet the expectations of Notified Bodies, Market Surveillance Authorities, and Approved Testing Labs (ATLs).\nWhat’s Included in the Templates? # Base conformance documentation templates include:\nProduct Risk Assessment : This document outlines the identified security risks related to Article 3.3(d) of the RED Delegated Act, specifically concerning network harm. Applicable EN 18031 Standards : This document details how the product meets the security requirements defined in the harmonized standard EN 18031-1. Declaration of Conformity : This is a template that manufacturers can use to declare their product compliance with the RED Delegated Act through the self-assessment route. Technical Specifications : Details about the product design and features. This is a product-specific document. These templates are intended to be used as a starting point, allowing product makers to significantly reduce time and effort in preparing RED DA compliance documentation.\nCompliance Pathways: Choose the Approach That Fits Your Product # With Espressif’s platform support and draft templates, you now have three practical paths to achieve RED DA compliance, depending on your product complexity, internal expertise, and certification strategy.\n1. Self-Declaration Using Espressif Templates # For customers using Espressif firmware stacks with minimal customization:\nYou can adapt the provided documentation templates for your specific product. Complete a self-assessment and issue a Declaration of Conformity (DoC). Suitable for devices not under the restricted list and companies confident in handling regulatory documentation. 2. Consultancy-Assisted Self-Declaration # If additional guidance is needed:\nWork with a security consultancy to update the templates, fill any gaps, and validate your conformity documentation. You remain responsible for issuing the final DoC, but with confidence that expert support has verified your assumptions. 3. Full Conformity Assessment via ATL or Notified Body # For products with:\nProducts which will fall under the restricted list as defined in the standard Custom security models Mandatory for a certain device types Demanding Market segments Engaging an Approved Testing Laboratory (ATL) or Notified Body allows a formal third-party evaluation to issue an attestation of conformity, which can carry more weight during audits or market checks.\nRecommended Partners for Compliance # While Espressif will try to facilitate maximum support for our customers to achieve the RED DA conformance, we understand that some customers may need further professional assistance. In order to facilitate this, Espressif will continue to work with other companies to provide a streamlined solution. At present, Espressif has established following partnerships that customers can take advantage of.\n🔸 Brightsight # Services: End-to-end RED DA conformity assessment (ATL), documentation advisory, vulnerability analysis Role: Espressif’s direct partner for preparing reference documentation and platform-level conformance 🔸 CyberWhiz # Services: RED DA consultancy and documentation preparation Role: Independent consultancy specialized in embedded systems and EU compliance If you need introductions or referrals to either of these partners, contact us via sales@espressif.com.\nEspressif\u0026rsquo;s Compliance Coverage: What We Will Support # Espressif will complete the full RED DA conformance and provide the related reports and documentation for firmware platforms where Espressif is the primary maintainer and software publisher. These include:\n✅ ESP-AT # Our AT command firmware for Wi-Fi and Bluetooth connectivity modules, widely used in embedded products along with a Host MCU.\n✅ ESP-ZeroCode # An out-of-the-box complete solution with predefined features for fast time-to-market, currently supporting varied Matter devices applications.\n✅ Espressif\u0026rsquo;s AWS IoT ExpressLink # The pre-provisioned, pre-programmed connectivity modules with AWS qualified firmware for AWS IoT core integration, for secure and reliable device onboarding.\nFor these platforms, Espressif is undergoing formal conformance activities based on the EN 18031 template supplied by Brightsight, a globally recognized security laboratory and Notified Body via SGS Fimko. This conformance is focused on ensuring compliance with the EN 18031 standard.\nKey Benefit: When you build your product on top of these firmware platforms which does not include changes to the network stack, you inherit a significant portion of Espressif’s RED DA conformance. The final product compliance is still dependent on the complete application.\nWhat to Expect Next # Espressif is currently finalizing draft templates and internal reviews for each supported firmware platform as listed above and ESP32 series SoCs. Over the coming weeks:\nWe will provide documentation packages for each firmware platform and ESP32 series SoCs via sales@espressif.com. We are also evaluating other channels for publication. Platform-specific guiding document will accompany the templates to assist in completion. We will host a webinar with Brightsight to walk through the documentation and answer developer questions. We encourage all customers targeting the EU market to start evaluating their RED DA readiness now, especially if product releases are planned for late 2025 or beyond.\nStay Informed # Espressif remains committed to providing transparent, practical, and secure solutions to meet evolving regulatory and market needs. If you have questions about RED DA, documentation needs, or how to engage with our compliance partners, please reach out to us.\n🌐 Espressif Developer Portal 📚 RED DA Part 1 Blog Updates # August 2025: Preparing for RED DA (EN 18031) Compliance - Watch our recorded webinar with Brightsight covering RED DA compliance requirements and implementation guidance. September 2025: Practical RED DA Compliance – Tools \u0026amp; Real-World Insights - Watch our recorded webinar with CyberWhiz covering practical RED DA compliance tools and real-world insights. ","date":"9 July 2025","externalUrl":null,"permalink":"/blog/2025/07/esp32-red-da-en18031-compliance-guide-part2/","section":"Blog","summary":"Espressif is streamlining RED Delegated Act (RED-DA) compliance by providing pre-certified firmware platforms, documentation templates, and partner support to help developers meet the upcoming EN 18031 standard. With flexible pathways including self-declaration and third-party assessments, developers can accelerate EU market readiness for Aug 2025 and beyond.","title":"RED DA Compliance (Part 2): Espressif’s Platform Support, Templates, and Pathways for Conformity","type":"blog"},{"content":"We’re excited to announce that our brand-new documentation website, the Centralized Documentation Platform (CDP), is now available to customers!\nCDP has been built with users in mind. It aims to bring together everything you need to find, read, and interact with Espressif’s technical documentation — in one centralized, easy-to-use place.\n📚 What is CDP? # CDP stands for Espressif Centralized Documentation Platform, and it’s your new one-stop hub for exploring all of Espressif’s technical documents.\nWith CDP, you can:\n🔍 Search through a unified library of Espressif documents 📑 Browse documents by a hardware or software product or a document type 💬 Chat with documents using our AI-powered chatbot CDP focuses on documentation. It does not replace the product pages on www.espressif.com. 🤔 Why CDP? # You might be wondering — why a whole new site?\nCurrently, Espressif documents are scattered across multiple platforms, including:\nwww.espressif.com – hosting Technical Documents, PCNs, Advisories, and Certificates docs.espressif.com – hosting primarily software documents Various GitHub repositories CDP aims to solve the problem of fragmented information. By consolidating existing resources into a single, unified platform, CDP provides users with a more efficient one-stop documentation experience.\n✨ Key Features of CDP # Here’s what you can experience on CDP.\nEspressif’s Technical Documentation in One Place # CDP aims to bring all Espressif’s technical documentation into one centralized place and has made a significant step towards that goal.\nCompared with the old technical document webpage on www.espressif.com, CDP offers many more documents (including English and Chinese versions):\n~ 800 certificates ~ 100 PCNs ~ 100 advisories ~ 200 software documents Most of the above-mentioned documents are available in HTML format, including those only available in PDF format traditionally:\nDatasheets Technical reference manuals (TRMs) PCNs and advisories ESP32-C6 Datasheet in HTML\nChatBot # Need quick answers? Our AI-powered chatbot is here to help!\nYou can ask questions in any language The bot responds based on Espressif documentation only If the requested information is not available in the documentation, the chatbot will respectfully indicate this to avoid providing inaccurate or speculative responses (hallucinations) Each answer includes references to the source documents, so you can verify the information Chatbot on CDP\nEnhanced Search # The new search function is designed to help you quickly locate exactly what you need.\nSearch across all documents or limit the search to the currently opened document Use fuzzy search by default for more flexible matching Support exact match searches when you check the “Exact Match” option Combine search with filters for greater precision Automatically correct typos in your keywords to save time on small mistakes Exact Search in Document Center\nComprehensive Filters # Quickly locate the information you need using a powerful and flexible filtering system.\nFilter by PRODUCT SERIES to find documents for a particular chip series Use CATEGORIES to narrow down to specific software or hardware groups Toggle Show EOL Products to view documents for end-of-life products Select by DOCUMENT TYPE (e.g., datasheet, manual, certificate, PCN, etc.) to find exactly what you need Collection of User Feedback # Your input matters! CDP includes a built-in feedback mechanism to:\nLet you report errors, make suggestions, or leave comments Help the Espressif Technical Documentation Team understand what’s working — and where we can do better Shape the future of CDP through continuous, community-driven improvements Feedback Submission\n🔮 What’s Next? # We have some more features coming! Here’s what’s coming next:\nSubscription to documents\nA more polished experience of homepage, filters, etc.\nContinued improvements based on your feedback\nRedirecting and retiring older pages:\nPages for Technical Documents, PCNs, Advisories, and Certificates on www.espressif.com will be closed by the end of 2025, assuming no major issues are found. After that point, traffic to those pages will be automatically redirected to CDP. For now, content on platforms like docs.espressif.com and GitHub will continue to be updated in parallel with CDP. No shutdown date is currently set for those platforms. 💬 We Need Your Feedback! # CDP is now open for user access, and its features will continue to be improved. We’d love your help to make CDP better. Whether you find a bug, have a suggestion, or just want to tell us what you think — we’re all ears.\nJust click the Feedback button on the right of each page on CDP!\nThanks for being part of the Espressif community. We’re excited to bring you a better documentation experience and can’t wait to hear what you think of CDP!\nConclusion # The Centralized Documentation Platform (CDP) marks a significant step toward a better, more streamlined way to access Espressif’s technical resources. With smarter search, AI-powered assistance, and an intuitive interface, CDP is designed to make your documentation experience faster, easier, and more productive.\nWe invite you to explore the platform, try out the new features, and let us know how it works for you. Your feedback is crucial in helping us refine and grow CDP into the best possible tool for the Espressif developer community.\nHappy exploring!\n","date":"8 July 2025","externalUrl":null,"permalink":"/blog/2025/07/introducing-cdp/","section":"Blog","summary":"This article introduces Espressif’s new Centralized Documentation Platform (CDP) — a unified site for all technical documentation, featuring enhanced search, integrated chatbot support, and improved feedback tools.","title":"Introducing CDP: The New Espressif Documentation Website – Now Available to Customers!","type":"blog"},{"content":"","date":"4 July 2025","externalUrl":null,"permalink":"/tags/imu/","section":"Tags","summary":"","title":"IMU","type":"tags"},{"content":"","date":"4 July 2025","externalUrl":null,"permalink":"/tags/motor/","section":"Tags","summary":"","title":"Motor","type":"tags"},{"content":" Introduction # In the first part of this series, we built a real-time motor control and sensing system using NuttX RTOS on the ESP32-C6. We covered DC motor control using the MCPWM Peripheral, potentiometer-based speed adjustment via ADC, and speed measurement using a quadrature encoder. This setup provided a foundation for embedded motor control. Now, we start working on sensor integration.\nIn this second and final part, we extend the system with two major features:\nIntegration of the MPU6050 IMU sensor to measure vibrations Wireless data streaming using the ESP32-C6 Wi-Fi capabilities, enabling real-time sensor data transfer to a host computer for visualization and analysis By the end of this article, you will have a complete, connected motor control and sensing platform. The ESP32-C6 will not only control and monitor the motor, but also capture vibration data and stream it wirelessly for live plotting and further analysis on the receiver side. This demonstrates the power of NuttX and Espressif devices for building advanced, networked embedded applications on modern microcontrollers.\nHardware Requirements # This second part introduces two new elements to enhance the system:\nWi-Fi connectivity: The ESP32-C6 onboard Wi-Fi module enables wireless data streaming. A host computer with network connectivity is required to receive and visualize the sensor data in real time.\nGY521 IMU module (MPU6050): Provides 3-axis accelerometer and gyroscope data for vibration measurement. Connects to the ESP32-C6 via I2C.\nSet Up the Build Environment # Building wireless capabilities requires that we clear our environment, since some new files will have to be added to our build system. The following snippet shows how to clear the current NuttX build and merge the motor_sensing defconfig, allowing us to continue building from the first article scenario.\nmake distclean ./tools/configure.sh esp32c6-devkitc:nsh kconfig-merge -m .config ../apps/external/motor_sensing/config/defconfig make olddefconfig Make sure you have the nuttx-esp-motor-sensing repository linked to nuttx-apps.\nWi-Fi Setup # To enable wireless data streaming, we need to configure the ESP32-C6 Wi-Fi settings. NuttX provides a ready-to-use Wi-Fi configuration that we can merge with our existing setup. We are going to use that instead of manually selecting all Wi-Fi-related options through menuconfig.\nUse the following command to merge the Wi-Fi configuration with the current setup:\nkconfig-merge -m .config boards/risc-v/esp32c6/esp32c6-devkitc/configs/wifi/defconfig make olddefconfig This command merges the Wi-Fi-specific configuration options into your current .config file, enabling networking support, Wi-Fi drivers, and socket APIs needed for wireless communication.\nNow run make to build the firmware.\nWi-Fi Network Configuration # With Wi-Fi support enabled, you\u0026rsquo;ll need to configure the network connection. In the NuttX shell, use the wapi command to connect to your Wi-Fi network:\nnsh\u0026gt; wapi psk wlan0 \u0026lt;mynetwork\u0026gt; \u0026lt;mypassword\u0026gt; nsh\u0026gt; wapi essid wlan0 \u0026lt;mynetwork\u0026gt; nsh\u0026gt; renew wlan0 Replace mynetwork and mypassword with your actual Wi-Fi network credentials. The renew command requests an IP address from your router using DHCP.\nOnce connected, verify your network configuration using ifconfig:\nnsh\u0026gt; ifconfig wlan0\tLink encap:Ethernet HWaddr 60:ff:ff:ff:ff:ff at RUNNING mtu 576 inet addr:10.42.0.199 DRaddr:10.42.0.1 Mask:255.255.255.0 A successful connection will show an assigned IP address. You can now ping a website to test the connection.\nIMU (MPU6050) Setup # Measuring vibrations requires that we integrate the MPU6050 IMU with the ESP32-C6 using the I2C interface.\nEnable I2C and MPU6050 Driver in NuttX # To enable the MPU6050 IMU, start by running make menuconfig in the NuttX project directory. Navigate to System Type → Peripheral Support and enable I2C0. On ESP32-C6 this should set GPIOs 6 and 5 as SCL and SDA pins, respectively. To verify, enter System Type → I2C Configuration to see the designated GPIOs.\nThen, go to Device Drivers → Sensor Device Support and enable the Invensense MPU60x0 Sensor support driver. Make sure to also select the MPU60x0 I2C Interface option, instead of SPI. Once these options are set, save your configuration and proceed to build the firmware.\nVerify Device Registration # To verify the IMU properly registered in the system, connect the IMU to the board and then build and flash the board:\nmake make flash ESPTOOL_BINDIR=./ ESPTOOL_PORT=/dev/ttyUSB0 Open a serial terminal and check the available devices. You should now see /dev/imu0 among the other character drivers.\nnsh\u0026gt; ls /dev /dev: adc0 console imu0 motor0 null pcnt0 qe0 random ttyS0 zero IMU Application # Now that we have our devices configured, we need an application that is able to read the accelerometer data and send it to our computer, wirelessly.\nTo accomplish this, we\u0026rsquo;ll need to create another program similar to motor_sensing of the first article. This program will read accelerometer data and open a socket that will be used to send the data.\nThe data transmitting part of this software will use a simple client/server socket, which is a widely available example for socket communication.\nFirst, we need some definitions for the MPU6050 and for the socket:\n#define REG_LOW_MASK 0xFF00 #define REG_HIGH_MASK 0x00FF #define MPU6050_AFS_SEL 4096.0f /* Accel scale factor */ #define SAMPLE_RATE_MS 20 /* 50 Hz sample rate */ #define TCP_PORT 5000 /* TCP port to send data */ #define MAX_MSG_SIZE 64 /* Maximum message size */ #define MAX_CLIENTS 1 /* Maximum number of clients */ Next, we need a data structure to hold the MPU6050 data. It must match the structure provided in the MPU6050 driver, which includes accelerometer, gyroscope, and temperature data.\nstruct mpu6050_imu_msg { int16_t acc_x; int16_t acc_y; int16_t acc_z; int16_t temp; int16_t gyro_x; int16_t gyro_y; int16_t gyro_z; }; This structure allows us to read the IMU through its file descriptor, which should be opened in the main function. On success, the raw IMU data must be converted to a usable value in units of g, which is achieved by concatenating the MSB and LSB registers to obtain a 16-bit integer and dividing the value by the AFS_SEL value, which is a scaling factor determined by the precision setting. More details about this can be found in the MPU6050 datasheet.\nFor the conversion function, we also need a simple structure to hold the processed accelerometer data:\nstruct sensor_accel { float x; float y; float z; }; The IMU reading function converts the raw sensor data to acceleration values in g-force units:\nstatic void read_mpu6050(int fd, struct sensor_accel *acc_data) { struct mpu6050_imu_msg raw_imu; int16_t raw_data[7]; memset(\u0026amp;raw_imu, 0, sizeof(raw_imu)); int ret = read(fd, \u0026amp;raw_data, sizeof(raw_data)); if (ret != sizeof(raw_data)) { printf(\u0026#34;Failed to read IMU data\\n\u0026#34;); acc_data-\u0026gt;x = 0; acc_data-\u0026gt;y = 0; acc_data-\u0026gt;z = 0; return; } /* Convert raw data */ raw_imu.acc_x = ((raw_data[0] \u0026amp; REG_HIGH_MASK) \u0026lt;\u0026lt; 8) + ((raw_data[0] \u0026amp; REG_LOW_MASK) \u0026gt;\u0026gt; 8); raw_imu.acc_y = ((raw_data[1] \u0026amp; REG_HIGH_MASK) \u0026lt;\u0026lt; 8) + ((raw_data[1] \u0026amp; REG_LOW_MASK) \u0026gt;\u0026gt; 8); raw_imu.acc_z = ((raw_data[2] \u0026amp; REG_HIGH_MASK) \u0026lt;\u0026lt; 8) + ((raw_data[2] \u0026amp; REG_LOW_MASK) \u0026gt;\u0026gt; 8); /* Convert to g force */ acc_data-\u0026gt;x = raw_imu.acc_x / MPU6050_AFS_SEL; acc_data-\u0026gt;y = raw_imu.acc_y / MPU6050_AFS_SEL; acc_data-\u0026gt;z = raw_imu.acc_z / MPU6050_AFS_SEL; } Now, we create our main function which opens the IMU file descriptor, reads it and also establishes network communication.\nThe main function performs the following steps:\nOpens and checks if the IMU device is available Creates a TCP socket and waits for a connection from client Once a connection is established, accepts the client and starts reading IMU data Sends the data over the network connection Monitors for client disconnections and waits for reconnection when needed This process repeats every 20 ms, as defined by the SAMPLE_RATE_MS value.\nThe following code is also available in the example repository.\nint main(int argc, FAR char *argv[]) { int fd; struct sensor_accel acc_data; char msg_buffer[MAX_MSG_SIZE]; /* Socket variables */ int server_fd, client_fd; struct sockaddr_in server_addr, client_addr; socklen_t client_len = sizeof(client_addr); int opt = 1; printf(\u0026#34;MPU60x0 Accelerometer Test\\n\u0026#34;); printf(\u0026#34;Sample Rate: %d ms (%d Hz)\\n\u0026#34;, SAMPLE_RATE_MS, 1000/SAMPLE_RATE_MS); printf(\u0026#34;TCP server starting on port %d\\n\u0026#34;, TCP_PORT); /* Open IMU device */ fd = open(\u0026#34;/dev/imu0\u0026#34;, O_RDONLY); if (fd \u0026lt; 0) { printf(\u0026#34;Failed to open imu0\\n\u0026#34;); return EXIT_FAILURE; } /* Create TCP socket */ server_fd = socket(AF_INET, SOCK_STREAM, 0); if (server_fd \u0026lt; 0) { printf(\u0026#34;Failed to create socket\\n\u0026#34;); close(fd); return EXIT_FAILURE; } /* Set socket options */ if (setsockopt(server_fd, SOL_SOCKET, SO_REUSEADDR, \u0026amp;opt, sizeof(opt)) \u0026lt; 0) { printf(\u0026#34;Failed to set socket options\\n\u0026#34;); close(fd); close(server_fd); return EXIT_FAILURE; } /* Configure server address */ memset(\u0026amp;server_addr, 0, sizeof(server_addr)); server_addr.sin_family = AF_INET; server_addr.sin_addr.s_addr = INADDR_ANY; server_addr.sin_port = htons(TCP_PORT); /* Bind socket */ if (bind(server_fd, (struct sockaddr *)\u0026amp;server_addr, sizeof(server_addr)) \u0026lt; 0) { printf(\u0026#34;Failed to bind socket\\n\u0026#34;); close(fd); close(server_fd); return EXIT_FAILURE; } /* Listen for connections */ if (listen(server_fd, MAX_CLIENTS) \u0026lt; 0) { printf(\u0026#34;Failed to listen\\n\u0026#34;); close(fd); close(server_fd); return EXIT_FAILURE; } printf(\u0026#34;Waiting for client connection...\\n\u0026#34;); /* Accept client connection */ client_fd = accept(server_fd, (struct sockaddr *)\u0026amp;client_addr, \u0026amp;client_len); if (client_fd \u0026lt; 0) { printf(\u0026#34;Failed to accept client\\n\u0026#34;); close(fd); close(server_fd); return EXIT_FAILURE; } printf(\u0026#34;Client connected\\n\u0026#34;); while (1) { read_mpu6050(fd, \u0026amp;acc_data); /* Format data as string with newline */ snprintf(msg_buffer, MAX_MSG_SIZE, \u0026#34;%.3f,%.3f,%.3f\\n\u0026#34;, acc_data.x, acc_data.y, acc_data.z); /* Send data over TCP */ ssize_t bytes_sent = send(client_fd, msg_buffer, strlen(msg_buffer), 0); /* Check if client disconnected */ if (bytes_sent \u0026lt;= 0) { printf(\u0026#34;Client disconnected, waiting for new connection...\\n\u0026#34;); close(client_fd); /* Wait for new client */ client_fd = accept(server_fd, (struct sockaddr *)\u0026amp;client_addr, \u0026amp;client_len); if (client_fd \u0026lt; 0) { printf(\u0026#34;Failed to accept new client\\n\u0026#34;); break; } printf(\u0026#34;New client connected\\n\u0026#34;); continue; } printf(\u0026#34;Accel (g): X=%.3f Y=%.3f Z=%.3f\\n\u0026#34;, acc_data.x, acc_data.y, acc_data.z); usleep(SAMPLE_RATE_MS * 1000); } /* Cleanup */ close(fd); close(client_fd); close(server_fd); return EXIT_SUCCESS; } Client-Side Data Acquisition # Now that we have everything set up on our ESP32-C6, we just need a simple program to wirelessly connect to our board and obtain this data.\nThis client program can be built in many ways using Python\u0026rsquo;s sockets module, C sockets or even a bash script. For the sake of simplicity, we\u0026rsquo;ll use a bash script. The following snippet connects to our server using netcat and prints the received data.\n#!/bin/bash # Default connection parameters HOST=\u0026#34;10.42.0.199\u0026#34; PORT=5000 # Check if custom host/port provided if [ $# -eq 2 ]; then HOST=$1 PORT=$2 fi echo \u0026#34;Connecting to IMU server at $HOST:$PORT...\u0026#34; # Connect to server and process data nc $HOST $PORT | while IFS=\u0026#34;,\u0026#34; read -r x y z; do printf \u0026#34;X: %6s Y: %6s Z: %6s\\r\u0026#34; \u0026#34;$x\u0026#34; \u0026#34;$y\u0026#34; \u0026#34;$z\u0026#34; done echo -e \u0026#34;\\nConnection closed.\u0026#34; Testing Application # With the IMU and socket program ready, we enable it through menuconfig on Application Configuration → Motor Sensing Apps → Motor IMU Data Example, build and flash the board.\nThe imu program should now be available on the NuttShell. Make sure you are connected to a Wi-Fi network.\nExecute the IMU program on NuttX:\nnsh\u0026gt; imu MPU60x0 Accelerometer Test Sample Rate: 20 ms (50 Hz) TCP server starting on port 5000 Waiting for client connection... Now run the client-side bash script. You should see data being received:\n$ ./imu_client.sh Connecting to IMU server at 10.42.0.199:5000... X: 1.168 Y: -0.077 Z: 0.145 Exiting the bash script and restarting should keep the data flowing with no issues.\nPractical Use # To fulfill the initial proposal of measuring motor vibrations, we can now change the motor speed by moving the potentiometer and log this data for analysis.\nThe following figure shows the results of a simple test where the motor was stopped, then speed gradually increased and decreased until a full stop.\nThe data and script used to generate the plots are available on the example repository.\nConclusion # In this second part of the NuttX motor control series, we successfully transformed a basic motor control system into a complete networked sensing platform. Building on the foundation established in the first article, we\u0026rsquo;ve now added sensing and connectivity capabilities.\nIn summary, the achievements in this article include:\nWi-Fi connectivity integration: Configured and connected the ESP32-C6 to wireless networks using NuttX\u0026rsquo;s networking stack IMU sensor integration: Implemented MPU6050 accelerometer support via I2C for vibration measurement Wireless data streaming: Created a TCP socket-based system for streaming sensor data from the embedded device to a host computer Cross-platform communication: Developed both embedded firmware and host-side client scripts for data exchange The combination of both articles demonstrates how NuttX can be used to build advanced embedded systems that bridge the gap between traditional motor control and modern IoT applications. We started with basic motor control using familiar peripherals and evolved into a comprehensive system capable of wireless sensor data streaming, creating a complete embedded IoT platform.\nRelated Resources # NuttX ESP32 Documentation MPU6050 Datasheet. ESP32-C6 Technical Reference Manual Example Repository Getting Started with NuttX and ESP32 ","date":"4 July 2025","externalUrl":null,"permalink":"/blog/2025/07/nuttx-motor-control-and-sensing-data-trans/","section":"Blog","summary":"This article extends the NuttX motor control system with inertial measurement unit (IMU) sensor integration for vibration measurement and wireless data streaming capabilities using the ESP32-C6 Wi-Fi connectivity.","title":"NuttX for Motor Control and Sensing: IMU Integration and Wireless Data Streaming","type":"blog"},{"content":"We are excited to announce the official release of ESP-Audio-Effects v1.0.0! This is a powerful and flexible audio processing library designed to provide developers with efficient audio effects processing capabilities. You can now visit the ESP-Audio-Effects release page for more details. ESP-Audio-Effects is widely used in various smart audio devices, including smart speakers, headphones, audio playback devices, and voice interaction systems. Let\u0026rsquo;s dive into ESP-Audio-Effects now and enhance your audio processing capabilities!\nIntroduction to ESP-Audio-Effects Component # ALC(Automatic Level Control): By adjusting the audio gain, the input audio volume is automatically regulated. When the gain is set to a positive value, the audio volume increases; when set to a negative value, the volume decreases. A gradual adjustment approach is used to prevent sudden volume changes, ensuring a smoother and more natural audio transition. If the gain is set too high, it will dynamically adjust the gain in real-time to keep the audio signal within a reasonable range, preventing distortion caused by clipping.\nEQUALIZER: By precisely controlling the filter type, gain, frequency, and Q factor of each frequency band, precise audio tuning and optimization can be achieved. This approach offers greater flexibility than a graphic equalizer, making it suitable for professional audio engineering. It can effectively address specific frequency issues and enhance overall audio quality.\nFADE: By setting the fade-in and fade-out times, smooth transitions between audio can be achieved. When playing new audio, the FADER automatically fades out the old audio while gradually fading in the new audio, preventing abrupt audio changes and enhancing the user experience.\nSONIC: By adjusting the speed and pitch, SONIC enables audio speed and pitch manipulation. It processes the audio in real-time, allowing it to be played at different speeds and pitches, providing users with a richer and more diverse audio experience.\nMIXER: By combining multiple input audio signals into a single output signal, the process adjusts the starting weight, target weight, and transition time for each audio signal. This ensures a harmonious and balanced audio output, where the final result blends the different signals seamlessly.\nDATA WEAVER: It is primarily used for data interleaving and de-interleaving functions. (cfr. Data Layaout)\nRATE CONVERSION: It is used for audio sample rate conversion, supporting conversions between various sample rates that are integer multiples of 4000 and 11025.\nCHANNEL CONVERSION By setting a weight array, the audio signal can be converted from one channel layout to another.\nBIT CONVERSION It is used for audio signal bit depth conversion, supporting mutual conversion between U8, S16, S24, and S32 bit depths.\nData Layout # The component supports both interleaved and deinterleaved formats for input data.\nInterleaved format: You can call the esp_ae_xxx_process() interface. In multi-channel audio, such as stereo, the interleaved format arranges the samples sequentially, for example:\nL0 R0 L1 R1 L2 R2 ... Among them, L and R represent the data of the left and right channels, respectively.\nDeinterleaved format: You can call the esp_ae_xxx_deintlv_process() interface. In deinterleaved format, the data for each channel is stored separately, for example:\nL1, L2, L3, ... (Left Channel) R1, R2, R3, ... (Right Channel) The data of each channel is stored in various independent buffers.\nAPI Style # The component adopts a unified and simple API design, with a clear and intuitive interface style. Developers can easily perform audio processing through the following functions:\nCategory Function Description Initialization esp_ae_xxx_open( ) Create the audio effects handle for using. Audio Process with interleave esp_ae_xxx_process( ) Processes audio data in the interleaved format. Audio Process with deinterleave esp_ae_xxx_deintlv_process( ) Processes audio data in the deinterleaved format. Set Parameter esp_ae_xxx_set_xxx( ) Sets specific parameters for the audio effect component. Get Parameter esp_ae_xxx_get_xxx( ) Retrieves the current parameters of the audio effect component. Release esp_ae_xxx_close( ) Closes the audio effect component and releases resources. Example of Using Audio Effects in GMF # Each function of esp-audio-effects has been added to the esp-gmf (General Multimedia Framework) framework as a gmf-audio element. By integrating these audio effect elements through a pipeline, flexible combinations of audio processing can be achieved. You can see an example of pipeline in the picture below.\nGMF Pipeline Sketch Map\nHere is a simple example of how to use esp-audio-effects in GMF.\nConclusion # ESP-Audio-Effects v1.0.0 is a versatile audio processing library. With features like Automatic Level Control, Equalizers, Dynamic Range Control, and more, it offers developers more control over audio effects. Through seamless integration with esp-gmf, developers can create easily create audio pipelines tailored to their application.\nIf you want to learn more about esp-audio-effects, check out our Github repository. Feel free to contact us and let\u0026rsquo;s explore more possibilities in audio processing together!\n","date":"2 July 2025","externalUrl":null,"permalink":"/blog/2025/07/overview-of-esp-audio-effects/","section":"Blog","summary":"This article explores the features and capabilities of ESP-Audio-Effects, a powerful audio processing library from Espressif. It introduces core function such as ALC, Equalizer, Mixer, Sonic, DRC, and more, and demonstrates how they integrate into the GMF (General Multimedia Framework) pipeline. With support for flexible configuration, interleaved and deinterleaved formats, and a unified API style, this library empowers developers to build robust and customizable audio processing applications.","title":"A Comprehensive Overview of Espressif's Audio Effects library","type":"blog"},{"content":"","date":"2 July 2025","externalUrl":null,"permalink":"/tags/esp-audio-effects/","section":"Tags","summary":"","title":"Esp-Audio-Effects","type":"tags"},{"content":"","date":"2 July 2025","externalUrl":null,"permalink":"/tags/esp-gmf/","section":"Tags","summary":"","title":"ESP-GMF","type":"tags"},{"content":"","date":"30 June 2025","externalUrl":null,"permalink":"/authors/marek-matej/","section":"Developer Portal Authors","summary":"","title":"Marek Matej","type":"authors"},{"content":" Motivation # Building executables for embedded systems is often a time-consuming process. As the number of builds increases, the cumulative wait time can become significant. This applies not only to local desktop builds but also to CI environments, where high resource utilization may lead to increased costs.\nThe ESP32 series of microcontrollers traditionally relies on a 2nd stage bootloader. Due to the design of the ROM loader, using this bootloader is typically the only viable method to boot the SoC.\nThe ROM loader imposes the following requirements:\nOnly ESP image format is supported SRAM only target addresses Limited size of the image To satisfy these constraints, the 2nd stage bootloader is essential. Among other functions, it serves as a bridge to overcome the limitations imposed by the ROM loader.\nHowever, the bootloader image often needs to be rebuilt and re-flashed, further increasing the overall build time.\nTo mitigate this and reduce the time required for both building and flashing, we can integrate essential features of the ESP32 bootloader directly into the application image. This integration must be carried out with careful consideration of the ROM loader’s requirements and limitations.\nTechnical background # In our journey, the main obstacle we need to overcome is the ROM loader’s limitation to accept only RAM-loadable images.\nSince the ESP image format consists of a list of memory segments interpreted by the ROM loader, we can construct a binary image that includes only the segments the ROM loader is capable of processing.\nBy adhering to these constraints, we can craft a simplified bootable image that embeds the minimal required bootloader functionality directly into the application itself, eliminating the need to recompile and reflash a separate bootloader component.\nIn the next section, we’ll walk through how to prepare such an image and modify the application accordingly.\nNow its a good time to read the ROM-loader chapter at related article.\nImage build # The image loadable by the ROM code is generated using the esptool elf2image command. To hide the non-RAM segments from the ROM loader view, we use the --ram-only-header argument.\nflowchart LR A --\u003e|linker| B B --\u003e|post build| C C --\u003e|post process| D A@{ shape: rounded, label: \"**Build***(west build)*\" } B@{ shape: rounded, label: \"**.elf***(objcpy .bin discarded)*\" } C@{ shape: rounded, label: \"**esptool.py***elf2image**--ram-only-header*\" } D@{ shape: rounded, label: \"**.bin***(ESP image format)*\" } To produce a compliant binary image named zephyr.bin from the input ELF file zephyr.elf, the following command can be used:\nesptool.py elf2image --ram-only-header -o zephyr.bin zephyr.elf This command creates an image where the exposed initial segments are SRAM-loadable and thus acceptable to the ROM loader. These are followed by additional segments intended for cache mapping, which cannot be processed during the initial boot phase.\nImportantly, the image header only declares the number of RAM-loadable segments. As a result, the flash segments are effectively hidden from the ROM loader and must be handled later during runtime.\nThis means that a minimal bootstrap routine must be executed as part of the loaded application. Its responsibility is to remap or reinitialize the remaining segments—typically code or data located in flash—so that the system can transition from minimal execution to full application runtime.\nAs a rule of thumb, the image header will account for all SRAM segments. Any segments that cannot be loaded by the ROM loader will be placed after the declared number of segments, making them invisible to the ROM loader.\nThe 1-byte checksum is placed after the last SRAM loadable segment, following by the rest of the segments. SHA256 digest is not implemented and it is disabled in the image header. In the next section, we’ll explore how to implement this runtime remapping and integrate it into the startup sequence.\nImage runtime # First, the ROM loader identifies the image header and calculates a 1-byte checksum over the number of segments specified in the header. If the checksum matches, the ROM loader transfers control to the entry point address.\nOnce the clock and flash subsystems are initialized, it is time to handle the memory-mapped segments that were hidden from the ROM loader. This is done by parsing the image\u0026rsquo;s segment headers and identifying their target virtual memory addresses (VMAs). As a result, the real number of image segments is calculated.\nAfter collecting all the \u0026ldquo;invisible\u0026rdquo; segments, their load memory addresses (LMAs) must be corrected, as the elf2image tool may have reordered the segments in the binary. At this point, these segments are mapped into their correct memory locations, and the system can proceed with the standard initialization process.\nImage parsing identifies segments whose VMAs fall within the cache\u0026rsquo;s address range The end of the segment is indicated by the load_addr field in the header having the value 0xFFFFFFFF Typically, there are exactly two such mapped segments: one in the IROM (instruction ROM) region and one in the DROM (data ROM) region, which are located in the CACHE address space.\nflowchart LR ROM ==\u003e SRAM FLASH .-\u003e|1.Load| ROM SRAM .-\u003e|2.Scan| FLASH SRAM .-\u003e|3.Map| B FLASH .-\u003e|3.a| CACHE SRAM ==\u003e|Platform init| CACHE PSRAM .-\u003e|3.b| CACHE CACHE ==\u003e|System init| INIT subgraph A [\"1st stage\"]; ROM; SRAM; end; subgraph C [\"Application start\"]; INIT; end; subgraph B [\"2nd stage\"]; CACHE; FLASH; PSRAM; end; ROM@{ shape: rounded, label: \"**ROM loader**(ROM code)\" }; SRAM@{ shape: rounded, label: \"**Simpleboot**(RAM code)\" }; CACHE@{ shape: rounded, label: \"**CACHE**(.code)(.rodata)\" }; FLASH@{ shape: rounded, label: \"**FLASH**(0x0)(0x1000)\" }; PSRAM@{ shape: rounded, label: \"**PSRAM**\" }; INIT@{ shape: rounded, label: \"**INIT**(z_prep_c)(z_cstart))\" }; Using the Simple Boot in Zephyr # To create single image ESP32 builds in Zephyr, we simply build the code for the target board. The configuration option CONFIG_ESP_SIMPLE_BOOT is enabled by default.\nwest build -b \u0026lt;full/board/qualifier\u0026gt; \u0026lt;sample/code/path\u0026gt; The configuration option that separates the single image (or simple boot image) from the bootloader supported image is selecting the bootloader. Adding the CONFIG_BOOTLOADER_MCUBOOT=y tells the build system to create the image that should be loaded by the MCUboot, to disable CONFIG_ESP_SIMPLE_BOOT.\nConclusion # Single-image binaries reduce build and flash times, making them well-suited for testing and lightweight development workflows. However, this simplicity comes with certain limitations:\nFixed boot address Supported for only one image format No support for OTA updates No flash encryption now (can be implemented in the future) While this simplified boot approach is not suitable for all applications, it can effectively serve specific use cases—particularly during development, prototyping, or continuous integration scenarios where speed and simplicity are prioritized over advanced features.\nAdditional readings # ESP32 bootstrapping article. ","date":"30 June 2025","externalUrl":null,"permalink":"/blog/2025/06/simple-boot-explained/","section":"Blog","summary":"In this article, we explore a simplified ESP32 boot process using single-image binaries to speed up build and flash times — ideal for development workflows. This approach sacrifices features like OTA updates but enables faster iteration.","title":"Simple Boot explained","type":"blog"},{"content":"","date":"30 June 2025","externalUrl":null,"permalink":"/tags/simpleboot/","section":"Tags","summary":"","title":"Simpleboot","type":"tags"},{"content":"","date":"27 June 2025","externalUrl":null,"permalink":"/tags/education/","section":"Tags","summary":"","title":"Education","type":"tags"},{"content":"","date":"27 June 2025","externalUrl":null,"permalink":"/tags/genesis/","section":"Tags","summary":"","title":"Genesis","type":"tags"},{"content":" Meet Genesis # Genesis IoT Discovery Lab is a hands-on modular kit powered by the ESP32-S3-WROOM-1-N8R2, designed for quick prototyping, real-world learning, and portable experimentation.\nAt its core: a sleek board with eight universal AX22 ports. Around it: a growing family of 50+ plug-and-play modules—from sensors and displays to relays, motors, and NeoPixels. Just snap in a module and start coding. No jumper wires. No guesswork. No digging for pinouts.\nIt is all open hardware. All reusable. And it just works.\nYou can join the waiting list on the Crowd Supply page.\nAX22 Spread Quick rundown # You can join the waiting list on the Crowd Supply page.\nOne Port. Endless Possibilities. # Every AX22 port has a standard 10-pin layout with everything you need—I²C, SPI, UART, ADC, 3× GPIOs, power, and ground. That means any module can go into any port, no rewiring or reconfiguring required.\nAX22 Port Pinout Pin Signal Function 1 GND Ground 2 3.3V Power 3 IO1 GPIO / ADC 4 IO2 / UART TX GPIO / Chip Select / Serial TX 5 IO3 / UART RX GPIO / Serial RX 6 MOSI SPI 7 MISO SPI 8 SCK SPI Clock 9 SDA I²C Data 10 SCL I²C Clock Modules snap in with the correct alignment every time. Whether you\u0026rsquo;re writing Arduino sketches, building MicroPython projects, or working with ESP-IDF, AX22 ports remove the wiring hassle and let you focus on building fast.\nYou can join the waiting list on the Crowd Supply page.\nJust Plug It In # Want to monitor temperature and humidity? Drop in a DHT11 or BME280 module. Need motion sensing? Snap in a VL53L0CX. Ready to light things up? Add a NeoPixel matrix or relay driver.\nAll modules speak a common language: plug into any port, call the matching helper (genesis.dht11(), genesis.bme280(), genesis.relay(), etc.), and start prototyping.\nNo breadboards. No errors. Just working hardware.\nYou can join the waiting list on the Crowd Supply page.\nSome examples # Case study # There are hundreds of projects and development cases you could go through but, for the sake of simplicity, lets take a simple example. A light that flashes/tracks the sounds of music.\nFor this we would need an LED and a Microphone.\nIt can be plugged into the matrix like this:\n#include \u0026lt;AX22-0009-MIC.h\u0026gt; #include \u0026lt;AX22-0028-LED.h\u0026gt; // The mic is on port 6, LED on port 8 MatrixMic mic(6); MatrixLED led(8); void setup() { mic.begin(); led.begin(); } void loop() { int volume = mic.getVolume(); // e.g., returns 0–1023 int brightness = map(volume, 0, 1023, 0, 255); led.setBrightness(brightness); // Brightness reacts to sound delay(20); // Smooth reaction } And that\u0026rsquo;s it, that\u0026rsquo;s a working project.\nMore examples can be viewed here.\nWhy Genesis Feels Effortless # ✅ Standard ports — no wiring confusion or pin mismatches. 🔄 Hot-swappable — swap modules live during lessons or demos. 🧠 Cross-platform — works with Arduino, ESP-IDF, MicroPython, CircuitPython, MicroBlocks. 🎒 Classroom-friendly — reliable, fast setup for repeatable labs. 🔋 Portable — run on USB or battery with built-in Li-Po charger and power switch. AX22 Integration # AX22 Ports are designed to be fully transferable—so you can integrate them into your own custom PCBs and still benefit from the shared ecosystem of modules. This gives you the freedom to build your own hardware while maintaining compatibility with a growing library of plug-and-play components.\nGENESIS isnt a system its a board that carries 8x AX22 Ports. Which means you could have other boards, with different MCUs and different port count (See disclaimer). In this first pilot run, GENESIS runs on a custom ESP32-S3 board, as its perfect for testing IoT, BT and a myriad of peripherals.\nUnder the Hood # Below are the specs of the first pilot GENESIS\nFeature Description Microcontroller ESP32-S3-WROOM-1-N8R2 (240 MHz dual-core LX7, 8MB Flash, 2MB PSRAM) Connectivity Wi-Fi 802.11 b/g/n + Bluetooth 5 (LE + Mesh) Ports 8 × AX22, STEMMA QT / Qwiic compatible Power Options USB-C, Li-Ion/Li-Po battery support, on-board switch \u0026amp; protection Included Modules D-Pad, rotary encoder, MEMS mic, motor driver, 8×8 NeoPixel, OLED, VL53L0CX, relays, switches, potentiometer, and more License CERN-OHL-S v2.0 — all schematics, layouts, and 3D models open-source What You Get # ✅ Genesis mainboard (ESP32-S3, USB-C, LiPo-ready) ✅ 8 × AX22 ports — each with full protocol support ✅ Snap-in modules — sensors, switches, LEDs, displays, etc (Right now almost at 50). ✅ Adapters — STEMMA QT, breadboard breakout, 90° port adapter ✅ Source files \u0026amp; code — See below. Open the box, plug in a module, and start building. It takes less than a minute to get your first project running.\nDocumentation # The entire project is built around openness and accessibility, which means we are taking the time to do it right. Every single module will have its own dedicated landing page like this one with KiCad project files, schematics, 3D models, and a clear usage guide.\nWe are still finalizing the full library, but everything will be fully documented and ready by launch.\nWho Is Genesis For? # User What Genesis Solves Students \u0026amp; Educators Instant setup, clean repeatable labs, no wiring mistakes Makers \u0026amp; Hackers Prototype faster and swap parts without rewiring Hardware Teams Validate hardware flows before custom PCBs Creative Coders Drive lights, sounds, motors without clutter Sim Enthusiasts Build USB keypads, gauges, or lighting modules — fast Engineer Build Custom AX22 Boards that snap into genesis for a quick IC test Built for Community # Genesis is fully open source. No vendor lock-in. No license traps. Build your own AX22 modules, remix the hardware, or fork the code.\nWant to collaborate or give feedback? Join the Discord, star the repo on GitHub, or follow us on Crowd Supply for campaign news, early access, and beta invitations.\nComing Soon on Crowd Supply # The launch is around the corner. Sign up to get:\n🐣 Early-bird pricing 🎁 Giveaway updates 🧪 Beta tester slots 📦 Shipping notifications → Follow Genesis on Crowd Supply\nDisclaimer # Yes, at first glance this might look like “yet another hardware standard.” That was never the goal.\nI was building my own microcontrollers and just needed a few peripherals. At some point, I realized it would be helpful if at least the ground pin was always in the same place—sounds obvious, but it was not during months of sleep deprivation.\nSo I started placing other pins consistently too. Three GPIOs were easy. Fitting UART, I2C, SPI, analog, and digital into 10 pins… took some trial and error.\nAfter a few modules, I thought: might as well make a matching port to plug them straight into the MCU. Then I made an ESP32-S3 board with 8 of these ports. It worked.\nI kept going—more modules, more sensors—and eventually, it became a whole ecosystem.\nNot planned. Just happened organically.\n","date":"27 June 2025","externalUrl":null,"permalink":"/blog/2025/06/modular-esp32s3-prototyping-platform-genesis/","section":"Blog","summary":"Genesis turns the ESP32-S3 into a modular playground with snap-in AX22 modules for prototyping, teaching, and creative hardware experimentation.","title":"Genesis IoT Discovery Lab – A Plug-and-Play Classroom Built on ESP32-S3","type":"blog"},{"content":"","date":"27 June 2025","externalUrl":null,"permalink":"/tags/modular-hardware/","section":"Tags","summary":"","title":"Modular-Hardware","type":"tags"},{"content":"","date":"27 June 2025","externalUrl":null,"permalink":"/authors/povilas-dumcius/","section":"Developer Portal Authors","summary":"","title":"Povilas Dumcius","type":"authors"},{"content":" Introduction # This article is Part 2 of our soft-AP tutorial. If you\u0026rsquo;re unfamiliar with what a soft-AP is or how to set one up, we recommend starting with the Part 1.\nIn this part, the main source file will be called basic_http_server.c. If you\u0026rsquo;re starting here, you can use the same main filename, while if you\u0026rsquo;re coming from Part 1, there is no need to change it. Just keep in mind that when you read basic_http_server.c we\u0026rsquo;re talking about your basic_soft_ap.c.\nYou can find the complete code in the tutorial-http-server folder in this GitHub repository.\nIn this tutorial, we\u0026rsquo;ll walk through the following steps:\nSet up a basic HTTP server Create a URI route that serves an HTML page View the HTML page in a web browser Quick Start (If You Missed Part 1) # If you\u0026rsquo;re in a hurry, you can do the following steps before starting:\nCreate a new basic project (e.g., hello_world or blink). Replace the main file with the version provided in this GitHub repo. Disable NVS, as explained in this section of the previous article. Alternatively, you can simply clone the repository and navigate to the tutorial_soft_ap folder.\nHTTP server setup # The HTTP server library provided by ESP-IDF is called esp_http_server. To use it, you’ll need to:\nInclude the library - Make sure it\u0026rsquo;s added in both your CMakeLists.txt file and in your basic_http_server.c source file. Configure and start the server - Initialize the server with default settings and start it so it can handle incoming HTTP requests. Let\u0026rsquo;s go through these steps in detail.\nInclude the library # The HTTP server functionality in ESP-IDF is provided by the esp_http_server library. To use it in your project, you’ll need to ensure that CMake recognizes it as a required component. For more information, check out the official API reference.\nInclude the HTTP server header in your basic_http_server.c file:\n#include \u0026#34;esp_http_server.h\u0026#34; Add esp_http_server to your CMakeLists.txt under the PRIV_REQUIRES list. This tells the build system to include the necessary components.\nYour CMakeLists.txt should look like this:\nidf_component_register(SRCS \u0026#34;basic_http_server.c\u0026#34; PRIV_REQUIRES esp_wifi esp_http_server INCLUDE_DIRS \u0026#34;.\u0026#34;) With this setup, your project is ready to use the HTTP server API.\nConfigure the HTTP Server # To set up and manage the HTTP server in ESP-IDF, you\u0026rsquo;ll need two key components:\nhttpd_handle_t: A handle that represents the server instance httpd_config_t: A configuration structure that defines how the server behaves To keep things organized, we’ll encapsulate the server setup in a dedicated function:\nhttpd_handle_t start_webserver() This function initializes and starts the server, then returns the server handle. You’ll call it from main() to keep your code modular and easy to maintain.\nMinimal Implementation # Here\u0026rsquo;s a basic version of the start_webserver() function:\nhttpd_handle_t start_webserver() { httpd_config_t config = HTTPD_DEFAULT_CONFIG(); httpd_handle_t server = NULL; httpd_start(\u0026amp;server, \u0026amp;config); return server; } After calling httpd_start(), the server handle is initialized and can be used to manage the server, e.g. registering URI handlers or shutting it down.\nThe httpd_config_t structure holds various server parameters. To simplify configuration, ESP-IDF provides the HTTPD_DEFAULT_CONFIG() macro, which populates the structure with default values. If you\u0026rsquo;re curious about the specific defaults, you can take a look at the macro definition on GitHub.\nIn your main() function, you can start the server like this:\nhttpd_handle_t server = start_webserver(); Returning the server handle allows you to perform additional operations, like stopping the server or adding URI routes, as we\u0026rsquo;ll explore in the next sections.\nError Handling # The httpd_start() function returns an esp_err_t result, which you can use to check if the server started successfully. If it fails, you can log the error or take appropriate action (like halting the app).\nHere’s the updated version of start_webserver() with basic error handling:\nhttpd_handle_t start_webserver() { httpd_handle_t server = NULL; httpd_config_t config = HTTPD_DEFAULT_CONFIG(); if (httpd_start(\u0026amp;server, \u0026amp;config) == ESP_OK) { ESP_LOGI(TAG, \u0026#34;Server started successfully, registering URI handlers...\u0026#34;); return server; } ESP_LOGE(TAG, \u0026#34;Failed to start server\u0026#34;); return NULL; } This makes your server setup more robust and easier to debug. If you\u0026rsquo;re unsure about ESP_LOGI and ESP_LOGE macros, you can check Espressif\u0026rsquo;s loggin library documentation.\nHTTP URI Management # We\u0026rsquo;ve started the HTTP server, but we haven\u0026rsquo;t defined any URI routes yet. In this section, we\u0026rsquo;ll walk through how to handle requests by setting up a basic route.\nWe will take the following steps:\nConnect to the server and observe the default response Implement and register a URI handler Check the result in a browser Connect to the Server # Before we can serve any content, let\u0026rsquo;s connect to the soft-AP and try accessing the HTTP server from a browser.\nConnect to the Soft-AP # This step is covered in detail in the previous article, where you\u0026rsquo;ll find instructions on how to connect your smartphone or laptop to the Soft-AP network created by your Espressif device.\nFind the IP Address of the Soft-AP # Every device connected to the Soft-AP receives an IP address, including the access point itself. In a typical setup, this IP behaves like the “router” address.\nFor Espressif devices, the default IP address of the Soft-AP is usually 192.168.4.1.\nYou can verify this in the terminal output. Look for a log line like this:\nI (766) esp_netif_lwip: DHCP server started on interface WIFI_AP_DEF with IP: 192.168.4.1 This confirms that the DHCP server is running and the Soft-AP is accessible at 192.168.4.1.\nVisit the Address in a Browser # Now, open a web browser on your connected device and enter the IP address (e.g., http://192.168.4.1) in the address bar, as shown in Fig.1:\nFig. 1 – Entering the IP address in the browser\nWhen no specific route is entered and you just typed the IP address, you\u0026rsquo;re implicitly requesting the / route.\nAt this stage, since no URI handlers have been registered, you\u0026rsquo;ll see an error message in your browser like:\nNothing matches the given URI And in the terminal, the following warning will appear:\nW (20566) httpd_uri: httpd_uri: URI \u0026#39;/\u0026#39; not found W (20566) httpd_txrx: httpd_resp_send_err: 404 Not Found - Nothing matches the given URI This means the server is running, but it doesn\u0026rsquo;t yet know how to respond to requests for / or any other route.\nIn the next step, we’ll fix that by registering a URI handler for /, so we can serve actual content.\nImplement and register the URI handler # To demonstrate how to implement a URI handler, we\u0026rsquo;ll return an HTML page when the user visits the / route. An overview of the required components is shown in Fig. 2.\nFig.2 - URI registration and management overview\nTo register a route, we use the function:\nesp_err_t httpd_register_uri_handler(httpd_handle_t server, const httpd_uri_t *hello_world_uri); This function requires the server handle (in our case the variable server) and a pointer to an httpd_uri_t structure.\nThe httpd_uri_t structure defines the properties of the URI being registered.\nFor our example, the structure is defined as follows:\nstatic const httpd_uri_t hello_world_uri= { .uri = \u0026#34;/\u0026#34;, // the address at which the resource can be found .method = HTTP_GET, // The HTTP method (HTTP_GET, HTTP_POST, ...) .handler = hello_get_handler, // The function which process the request .user_ctx = NULL // Additional user data for context }; The last piece we need is the request handler function, which must follow this signature:\nstatic esp_err_t processing_function (httpd_req_t) In our simple example, the function looks like this.\nstatic esp_err_t hello_get_handler(httpd_req_t *req) { const char* resp_str = \u0026#34;\u0026lt;h1\u0026gt;Hello World\u0026lt;/h1\u0026gt;\u0026#34;; httpd_resp_send(req, resp_str, HTTPD_RESP_USE_STRLEN); return ESP_OK; } Note the embedded HTML in the response string. We use httpd_resp_send to send the response. This function takes the request object and the response string.\nYour code should now resemble this one.\nView the web page in the browser # Open the web browser again on your connected device and enter the IP address in the address bar. As shown in Fig.3, you should now get the HTML page that we sent in the hello_get_handler function.\nFig. 3 – HTML page displayed\nYou can now change the HTML and add additional routes.\nConclusion # You\u0026rsquo;ve now set up a basic HTTP server on your Espressif device in soft-AP mode. We covered how to include the esp_http_server library, start the server, connect to it, and register a simple URI handler to return an HTML response.\nThis forms a solid foundation for building more interactive web-based interfaces on your device. You can now easily expand by adding more routes, returning different data formats, or handling user input.\nCheck out the full example on GitHub, and keep experimenting!\n","date":"26 June 2025","externalUrl":null,"permalink":"/blog/2025/06/basic_http_server/","section":"Blog","summary":"This article shows how to create a simple HTTP server. It explains the functions you need and the setup required. After reading this, you should be able to create your own HTTP server on Espressif devices.","title":"ESP-IDF Tutorials: Basic HTTP server","type":"blog"},{"content":"","date":"26 June 2025","externalUrl":null,"permalink":"/tags/http-server/","section":"Tags","summary":"","title":"HTTP Server","type":"tags"},{"content":"","date":"18 June 2025","externalUrl":null,"permalink":"/tags/edge-computing/","section":"Tags","summary":"","title":"Edge Computing","type":"tags"},{"content":"","date":"18 June 2025","externalUrl":null,"permalink":"/tags/neural-networks/","section":"Tags","summary":"","title":"Neural Networks","type":"tags"},{"content":"","date":"18 June 2025","externalUrl":null,"permalink":"/tags/recognition/","section":"Tags","summary":"","title":"Recognition","type":"tags"},{"content":"ESP-DL is a small and fast neural network inference framework designed for Espressif SoCs, such as the ESP32-S3/P4. It provides efficient model deployment solutions and helps developers quickly implement edge AI applications. Specifically, ESP-DL has the following advantages:\nEfficient Operator Implementation: ESP-DL efficiently implements common AI operators such as Conv, Gemm, Add, and Mul. The list of supported operators. Static Memory Planner: The memory planner automatically allocates different layers to the optimal memory location based on the user-specified internal RAM size, ensuring efficient overall running speed while minimizing memory usage. Dual Core Scheduling: Automatic dual-core scheduling allows computationally intensive operators to fully utilize the dual-core computing power. Currently, Conv2D and DepthwiseConv2D support dual-core scheduling. 8bit LUT Activation: All activation functions except for ReLU and PReLU are implemented using an 8-bit LUT (Look Up Table) method in ESP-DL to accelerate inference. You can use any activation function, and their computational complexity remains the same. With the ESP-DL framework, you can quickly deploy deep learning models to ESP32 series chips, empowering end devices with intelligent perception and decision-making capabilities, enabling edge AI applications.\nThis article demonstrates how the advanced features of ESP-DL enable powerful edge AI applications despite the constraints of embedded systems. You will learn the complete workflow for implementing touchpad-based digit recognition on the ESP32-S3 and the ESP32-P4 using ESP-DL \u0026ndash; collecting and preprocessing touch data, designing a lightweight CNN model, training and evaluating the model in PyTorch, quantizing it for optimized edge deployment, and, eventually, implementing efficient C++ code for model loading, data preprocessing, and inference.\nTouch Data Collection and Preprocessing # Touch Data Collection # To collect the data, the ESP_Touch_Kit_Touchpad is used, featuring a 6×7 array of touch channels. When a finger touches the pad, it changes the capacitance value of the corresponding touch channel. By detecting the changes in capacitance values, the finger position is determined. If you wish to replicate this project, you can refer to the design requirements at the link above and create your own touchpad.\nESP Touch Kit Touchpad Due to the limited resolution of the original 6x7 touchpad, anything drawn on it ends up looking the same. Therefore, a software interpolation algorithm was applied to interpolate the original 6x7 data to 30x25 in order to obtain more image details. Through the software interpolation algorithm, we collected a series of different digits as training inputs for the model.\nInterpolated Touch Dataset Based on Touchpad Drawing The publicly available MNIST dataset was not used because its binarized images preserve fine, continuous stroke details. In contrast, the interpolated data collected from the touchpad has simpler strokes, and sometimes non-continuous strokes. As a result, using MNIST for training and deployment would lead to poor recognition performance.\nInterpolated Touch Data vs. MNIST Data The Interpolated touch dataset contains ten categories from digit 0 to 9, with a total of 2,081 samples. Although this dataset is smaller than MNIST, it is sufficiently representative for the current digit recognition task. You can also expand the dataset size according to your actual needs to further improve the model\u0026rsquo;s generalization capability. The sample distribution across different categories is as follows:\nCategory Distribution in the interpolated touch dataset Dataset Preparation # Before model training, the interpolated touch data is preprocessed using the torchvision.transforms module from PyTorch. First, the images are converted to single-channel grayscale images, and random affine transformations (rotation of ±10 degrees, translation of ±10%) are applied to enhance data diversity. Subsequently, the images are converted to tensor format and normalized with a mean of 0.5 and standard deviation of 0.5.\nAfter data processing, the dataset is loaded using ImageFolder, a PyTorch utility that organizes images into labeled datasets based on folder names. It is then randomly split into training and test sets with an 8:2 ratio.\nimport torch import torch.nn as nn import torch.optim as optim from torch.utils.data import DataLoader, random_split from torchvision import datasets, transforms transform = transforms.Compose([ transforms.Grayscale(num_output_channels=1), transforms.RandomAffine(degrees=10, translate=(0.1, 0.1)), transforms.ToTensor(), transforms.Normalize((0.5,), (0.5,)), ]) dataset = datasets.ImageFolder(root=\u0026#39;./dataset\u0026#39;, transform=transform) train_size = int(0.8 * len(dataset)) test_size = len(dataset) - train_size train_dataset, test_dataset = random_split(dataset, [train_size, test_size]) train_loader = DataLoader(dataset=train_dataset, batch_size=32, shuffle=True) test_loader = DataLoader(dataset=test_dataset, batch_size=32, shuffle=False) Lightweight CNN Model Design # This solution uses a lightweight convolutional neural network model designed for this purpose. The model employs three convolutional layers for feature extraction, each followed by a ReLU activation function, and uses max pooling layers after the first two convolutional layers to reduce feature map dimensions. Finally, a fully connected layer maps the features to 10 digit categories. The specific structure is as follows:\nclass Net(torch.nn.Module): def __init__(self): super(Net, self).__init__() self.model = torch.nn.Sequential( torch.nn.Conv2d(in_channels=1, out_channels=16, kernel_size=3, stride=1, padding=1), torch.nn.ReLU(), torch.nn.MaxPool2d(kernel_size=2, stride=2), torch.nn.Conv2d(in_channels=16, out_channels=32, kernel_size=3, stride=1, padding=1), torch.nn.ReLU(), torch.nn.MaxPool2d(kernel_size=2, stride=2), torch.nn.Conv2d(in_channels=32, out_channels=64, kernel_size=3, stride=1, padding=1), torch.nn.ReLU(), torch.nn.Flatten(), torch.nn.Linear(in_features=7 * 6 * 64, out_features=256), torch.nn.ReLU(), torch.nn.Dropout(p=0.5), torch.nn.Linear(in_features=256, out_features=10), torch.nn.Softmax(dim=1) ) def forward(self, x): output = self.model(x) return output It should be noted that the model structure provided here serves only as a reference example. In practical applications, you can design different network architectures according to specific requirements, such as:\nAdjusting the number of convolutional layers and channels Trying different activation functions (such as LeakyReLU, ELU, etc.) Using other types of pooling layers (such as average pooling) Adding batch normalization layers Adopting modern network structures like residual connections Model Training and Evaluation in PyTorch # Training Parameter Configuration # During the model training process, the following parameter configuration is employed:\nLoss Function: CrossEntropyLoss, suitable for multi-classification tasks Optimizer: Adam optimizer with a learning rate of 0.001 device = \u0026#34;cuda:0\u0026#34; if torch.cuda.is_available() else \u0026#34;cpu\u0026#34; model = Net().to(device) criterion = nn.CrossEntropyLoss() optimizer = optim.Adam(model.parameters(), lr=0.001) The above parameter configuration is not the only option. In practical applications, you should flexibly adjust hyperparameters such as loss function, optimizer, and learning rate according to specific task requirements to find the most suitable configuration for the current scenario, thereby achieving better model performance.\nTraining Process # A phased training strategy is employed, dividing the training process into training and testing phases. During the training phase, the model calculates predictions through forward propagation, computes loss using the cross-entropy loss function, and updates model parameters through backpropagation. During the testing phase, the model evaluates performance on the test set and calculates accuracy. The training process continues for 100 epochs, with training and test set accuracies saved after each epoch for subsequent analysis. The specific implementation is as follows:\ndef train_epoch(model, train_loader, criterion, optimizer, device): model.train() running_loss = 0.0 correct = 0 total = 0 for inputs, labels in train_loader: inputs, labels = inputs.to(device), labels.to(device) optimizer.zero_grad() outputs = model(inputs) loss = criterion(outputs, labels) loss.backward() optimizer.step() running_loss += loss.item() _, predicted = torch.max(outputs.data, 1) total += labels.size(0) correct += (predicted == labels).sum().item() epoch_loss = running_loss / len(train_loader) epoch_acc = 100 * correct / total return epoch_loss, epoch_acc def test_epoch(model, test_loader, criterion, device): model.eval() running_loss = 0.0 correct = 0 total = 0 with torch.no_grad(): for inputs, labels in test_loader: inputs, labels = inputs.to(device), labels.to(device) outputs = model(inputs) loss = criterion(outputs, labels) running_loss += loss.item() _, predicted = torch.max(outputs.data, 1) total += labels.size(0) correct += (predicted == labels).sum().item() epoch_loss = running_loss / len(test_loader) epoch_acc = 100 * correct / total return epoch_loss, epoch_acc num_epochs = 100 train_acc_array = [] test_acc_array = [] for epoch in range(num_epochs): train_loss, train_acc = train_epoch(model, train_loader, criterion, optimizer, device) test_loss, test_acc = test_epoch(model, test_loader, criterion, device) print(f\u0026#39;Epoch [{epoch + 1}/{num_epochs}], \u0026#39; f\u0026#39;Train Loss: {train_loss:.4f}, Train Acc: {train_acc:.2f}%, \u0026#39; f\u0026#39;Test Loss: {test_loss:.4f}, Test Acc: {test_acc:.2f}%\u0026#39;) train_acc_array.append(train_acc) test_acc_array.append(test_acc) torch.save(model.state_dict(), \u0026#39;./models/final_model.pth\u0026#39;) Accuracy Curves During Training After training, the model is saved as final_model.pth for subsequent model deployment.\nModel Quantization and Conversion for Deployment # Model quantization is an important optimization technique for deploying deep learning models on edge devices, offering the following key advantages:\nReduced Model Size: By converting floating-point parameters to fixed-point parameters, it significantly reduces the model\u0026rsquo;s storage space requirements. Improved Inference Speed: Fixed-point operations are more efficient than floating-point operations, helping to accelerate model inference. ESP-DL uses a proprietary .espdl format for model deployment, supporting both 8-bit and 16-bit quantization precision. The model quantization process requires the ESP-PPQ tool, which can be installed as follows:\npip uninstall ppq pip install git+https://github.com/espressif/esp-ppq.git ESP-PPQ provides two quantization interfaces: espdl_quantize_onnx and espdl_quantize_torch, supporting ONNX models and PyTorch models respectively. For other deep learning frameworks (such as TensorFlow, PaddlePaddle, etc.), models need to be converted to ONNX format before quantization.\nBased on the quantization reference script provided by ESP-DL, a suitable quantization script can be built for the implementation:\nimport torch from PIL import Image from ppq.api import espdl_quantize_torch from torch.utils.data import Dataset from torch.utils.data import random_split from torchvision import transforms, datasets DEVICE = \u0026#34;cpu\u0026#34; class FeatureOnlyDataset(Dataset): def __init__(self, original_dataset): self.features = [] for item in original_dataset: self.features.append(item[0]) def __len__(self): return len(self.features) def __getitem__(self, idx): return self.features[idx] def collate_fn2(batch): features = torch.stack(batch) return features.to(DEVICE) if __name__ == \u0026#39;__main__\u0026#39;: BATCH_SIZE = 32 INPUT_SHAPE = [1, 25, 30] TARGET = \u0026#34;esp32s3\u0026#34; NUM_OF_BITS = 8 ESPDL_MODEL_PATH = \u0026#34;./s3/touch_recognition.espdl\u0026#34; transform = transforms.Compose([ transforms.Grayscale(num_output_channels=1), transforms.ToTensor(), transforms.Normalize((0.5,), (0.5,)), ]) dataset = datasets.ImageFolder(root=\u0026#34;../dataset/extra\u0026#34;, transform=transform) train_size = int(0.8 * len(dataset)) test_size = len(dataset) - train_size train_dataset, test_dataset = random_split(dataset, [train_size, test_size]) image = Image.open(\u0026#34;../dataset/extra/9/20250225_140331.png\u0026#34;).convert(\u0026#39;L\u0026#39;) input_tensor = transform(image).unsqueeze(0) feature_only_test_data = FeatureOnlyDataset(test_dataset) testDataLoader = torch.utils.data.DataLoader(dataset=feature_only_test_data, batch_size=BATCH_SIZE, shuffle=False, collate_fn=collate_fn2) model = Net().to(DEVICE) model.load_state_dict(torch.load(\u0026#34;./final_model.pth\u0026#34;, map_location=DEVICE)) model.eval() quant_ppq_graph = espdl_quantize_torch( model=model, espdl_export_file=ESPDL_MODEL_PATH, calib_dataloader=testDataLoader, calib_steps=8, input_shape=[1] + INPUT_SHAPE, inputs=[input_tensor], target=TARGET, num_of_bits=NUM_OF_BITS, device=DEVICE, error_report=True, skip_export=False, export_test_values=True, verbose=1, dispatching_override=None ) After executing the above script, three files will be exported:\n*.espdl \u0026ndash; model binary file *.info \u0026ndash; model text file *.json \u0026ndash; quantization information file To avoid inconsistencies between the actual inference results and PC inference results, input_tensor is included for testing during the quantization process. After quantization, the test results can be checked in the *.info file to verify consistency with PC inference results.\ntest outputs value: %23, shape: [1, 10], exponents: [0], value: array([4.78089300e-25, 1.05306175e-20, 3.62514101e-34, 9.60267995e-24, 9.60267995e-24, 6.47023468e-26, 3.97544995e-31, 1.15482239e-17, 3.87399781e-21, 1.00000000e+00, 0.00000000e+00, 0.00000000e+00], dtype=float32) Additionally, if 8-bit quantization does not achieve satisfactory results for your model, ESP-DL provides various quantization schemes. You can refer to the documentation How to quantize model to further reduce model performance loss.\nEdge Deployment and Inference on ESP32-S3/P4 # You can load the model from rodata, partition, or SD card. For more details, please refer to How to load \u0026amp; test \u0026amp; profile model.\nTouchDigitRecognition::TouchDigitRecognition(const char* model_name, size_t feature_size) { m_model = new dl::Model(model_name, fbs::MODEL_LOCATION_IN_FLASH_PARTITION); m_model-\u0026gt;minimize(); m_preprocessor = new DataPreprocessor(m_model, feature_size); m_postprocessor = new DataPostprocessor(m_model); m_feature_size = feature_size; m_quant_buffer = (int8_t*)heap_caps_calloc(feature_size * sizeof(int8_t), 1, MALLOC_CAP_SPIRAM); } After loading the model, the interpolated touch data needs to be preprocessed to ensure the validity of the model input data. Preprocessing mainly includes data format conversion and quantization implemented as follows:\nDataPreprocessor::DataPreprocessor(dl::Model* model, size_t feature_size) : m_model(model), m_feature_size(feature_size) { auto inputs = m_model-\u0026gt;get_inputs(); if (!inputs.empty()) { dl::TensorBase* input_tensor = inputs.begin()-\u0026gt;second; m_input_scale = 1.0f / DL_SCALE(input_tensor-\u0026gt;exponent); } } void DataPreprocessor::process(const uint8_t* input_data, int8_t* quant_buffer) { for (size_t i = 0; i \u0026lt; m_feature_size; i++) { int8_t value = (input_data[i] == 0 ? -1 : 1); quant_buffer[i] = dl::quantize\u0026lt;int8_t\u0026gt;((float)value, m_input_scale); } } After data preprocessing, the processed data needs to be fed into the model for inference. The entire inference process consists of three steps:\nData Encapsulation. Model Execution. Result Parsing. Here is the complete inference implementation:\nint TouchDigitRecognition::predict(const uint8_t* input_data) { m_preprocessor-\u0026gt;process(input_data, m_quant_buffer); std::map\u0026lt;std::string, dl::TensorBase*\u0026gt; inputs; auto model_inputs = m_model-\u0026gt;get_inputs(); for (auto \u0026amp;input_pair : model_inputs) { dl::TensorBase* tensor = new dl::TensorBase( {1, static_cast\u0026lt;int\u0026gt;(m_feature_size)}, m_quant_buffer, input_pair.second-\u0026gt;exponent, input_pair.second-\u0026gt;dtype, false, MALLOC_CAP_SPIRAM ); inputs.emplace(input_pair.first, tensor); } m_model-\u0026gt;run(inputs); for (auto \u0026amp;input : inputs) { delete input.second; } return m_postprocessor-\u0026gt;process(); } Finally, the model output needs to be processed. Since the model output is processed through the Softmax layer, obtaining the probability distribution for each category, the final recognition result can be obtained by finding the index corresponding to the maximum probability value:\nint DataPostprocessor::process() { auto outputs = m_model-\u0026gt;get_outputs(); if (outputs.empty()) { return -1; } m_model_output = outputs.begin()-\u0026gt;second; float *output_ptr = (float *)m_model_output-\u0026gt;data; int size = m_model_output-\u0026gt;get_size(); auto max_iter = std::max_element(output_ptr, output_ptr + size); int max_index = std::distance(output_ptr, max_iter); ESP_LOGI(TAG, \u0026#34;Predict result: %d\u0026#34;, max_index); return max_index; } Summary # This article introduces a handwritten digit recognition application implemented using the ESP-DL framework, demonstrating how to deploy deep learning models on ESP32 series chips.\nAll the Python scripts for data processing, model training, quantization, as well as the C++ code for model inference and the pre-trained models mentioned in this article, are available in the esp-iot-solution GitHub repository: touchpad_digit_recognition\nFeel free to try these examples, implement your own applications, and share your experience!\n","date":"18 June 2025","externalUrl":null,"permalink":"/blog/2025/06/touchpad-digit-recognition/","section":"Blog","summary":"This article demonstrates how to implement a touchpad-based digit recognition system using ESP-DL on ESP32 series chips. It covers the complete workflow from data collection and preprocessing to model training, quantization, and deployment, showcasing ESP-DL\u0026rsquo;s capabilities in edge AI applications.","title":"Touchpad Digit Recognition Based on ESP-DL","type":"blog"},{"content":"Nos dias 5 e 6 de agosto, Campinas (SP) receberá a segunda edição do Espressif Summit Brazil, que ocorrerá no moderno Hotel Vitória Concept. O evento tem início às 9h00, com um welcome coffee, seguido do keynote pontualmente às 9h30.\nApós o sucesso da edição inaugural, o Summit retorna trazendo uma programação ampliada, com conteúdos exclusivos focados na comunidade técnica. O primeiro dia será marcado por uma série de palestras ministradas por renomados especialistas da Espressif, incluindo convidados internacionais, abordando os mais recentes avanços em IoT, segurança digital, hardware, software, firmware e conectividade wireless. Os temas das palestras incluem Arduino, ESP-IDF, NuttX, Zephyr, segurança, redes, protocolos, RainMaker, Matter e muito mais.\nNo segundo dia, o público terá acesso a uma agenda diversificada com palestras adicionais, workshops práticos (vagas limitadas), sessões interativas de hardware hacking, além de painéis de discussão e muitas oportunidades para ampliar conexões profissionais, trocar experiências e realizar networking com especialistas da indústria.\nDurante todo o evento, haverá também uma área de exposições com a participação de empresas parceiras e distribuidores, apresentando produtos inovadores, protótipos avançados e soluções comerciais desenvolvidas com tecnologias Espressif. Os visitantes poderão ainda conferir ferramentas e recursos técnicos essenciais para acelerar o desenvolvimento de dispositivos conectados.\nSe você é desenvolvedor, arquiteto de sistemas, especialista em segurança, engenheiro de hardware, ou simplesmente apaixonado por inovação tecnológica, o Espressif Summit Brazil 2025 é imperdível.\nVenha participar deste grande encontro de tecnologia, inovação e colaboração com a Espressif e sua comunidade de parceiros!\nComo participar # As inscrições para as palestras dos dois dias serão gratuitas. Os workshops terão um custo adicional. As inscrições serão realizadas pelo Portal Embarcados e as vagas são limitadas. Garanta já a sua aqui!\nAgenda # Dia 5 de Agosto # 09h00: Welcome Coffee 09h30: Boas vindas e Keynote 10h30 às 12h00: Palestras Técnicas 12h00 às 13h00: Intervalo para Almoço e Networking 13h00 às 17h30: Palestras Técnicas 17h30 às 18h00: Encerramento do Dia Dia 6 de Agosto # 08h30: Welcome Coffee 09h00 às 12h00: Workshops Práticos (salas workshop 1 e 2) 09h00 às 12h00: Palestras (sala talks \u0026amp; hackespace) 12h00 às 13h00: Intervalo para Almoço e Networking 13h00 às 17h00: Workshops Práticos (salas workshop 1 e 2) 13h00 às 17h00: Palestras, Painéis e Sessões de Hardware Hacking (sala talks \u0026amp; hackespace) 17h00 às 17h30: Encerramento Oficial e Agradecimentos (sala talks \u0026amp; hackespace) Palestras # Horário Tópico Palestrante(s) Slides 09:30 Boas vindas e Keynote Ivan Grokhotkov 10:00 Apresentação Corporativa: M5Stack and Embarcados Allen Chao, Thiago Lima 📥 📥 10:30 Uma atualização sobre as soluções da Espressif: De A(rduino) a Z(ephyr) Pedro Minatel, Ivan Grokhotkov, Ricardo Tafas 📥 📥 11:30 Interoperabilidade e inovação para casas inteligentes: RainMaker e Matter Pedro Minatel 📥 13:00 Segurança em dispositivos ESP32 – Um panorama de como proteger seu projeto Amey Inamdar 📥 14:00 Colocando o S no IoT: Conectividade segura com o ESP-IDF Euripedes Rocha 📥 15:00 ESP-BIST: Simplificando o desenvolvimento de aplicações seguras Lucas Tamborrino 📥 16:00 Python em NuttX: novas possibilidades para sistemas embarcados Tiago Medicci 📥 16:30 Zigbee com Arduino: conectando seus dispositivos ao Home Assistant Lucas Vaz 📥 17:00 Projetos ESP-IDF de alto desempenho: como usar CI/CD para ganhar agilidade e confiança Pedro Minatel 📥 Workshops # Horário Workshop Instrutor(es) Slides 09:00 ESP-IDF básico: do zero ao seu primeiro projeto com ESP32 e componentes Pedro, Fabio 📥 09:00 ESP-IDF avançado: técnicas e ferramentas avançadas para dominar o desenvolvimento com ESP32 Ivan, Euripedes 📥 13:00 Arduino no ESP-IDF: simplificando o desenvolvimento com flexibilidade Rodrigo Garcia, Lucas V. 📥 13:00 Apresentando o ESP32-P4 para soluções de conectividade Euripedes, Guilherme 📥 Sobre a Espressif # A Espressif Systems (SSE: 688018.SH) é uma empresa pública, multinacional e fabless de semicondutores, que desenvolve chips de comunicação sem fio de última geração e baixo consumo de energia. Nossas soluções de AIoT são sustentáveis, versáteis e acessíveis, atendendo a uma ampla variedade de aplicações inteligentes em diversos setores. Com um ciclo de desenvolvimento completo, inovamos em todas as camadas da tecnologia — desde os protocolos Wi-Fi, Bluetooth LE e IEEE 802.15.4, até RF, MCUs RISC-V, algoritmos de IA, sistemas operacionais, toolchains, frameworks de AIoT e serviços em nuvem.\nNossa Missão e Visão # Na Espressif, temos o compromisso de oferecer soluções de AIoT open-source que capacitam tanto empresas quanto desenvolvedores. Ao disponibilizar ferramentas acessíveis e recursos abrangentes, fortalecemos uma comunidade global de inovadores que buscam gerar impacto positivo no mundo real. Nossa visão é promover a colaboração, inspirar a criatividade e impulsionar o avanço tecnológico rumo a um futuro mais conectado, eficiente e sustentável.\n","date":"17 June 2025","externalUrl":null,"permalink":"/events/summit-brazil-25/","section":"Events","summary":"On August 5th and 6th 2025, Campinas (Brazil) will host the second edition of the Espressif Summit Brazil, featuring talks, workshops, and exhibitions focused on IoT, digital security, hardware, software, and connectivity.","title":"Espressif Summit Brazil 2025","type":"events"},{"content":"","date":"17 June 2025","externalUrl":null,"permalink":"/tags/save-the-date/","section":"Tags","summary":"","title":"Save-the-Date","type":"tags"},{"content":" Introduction # In the first part, we introduced the essential tools for firmware debugging and explained how to establish an openOCD connection with the Espressif device.\nIn this second part, we\u0026rsquo;ll launch a debugging session, step through the code using navigation commands, and inspect variables in real time. By the end of this tutorial, you\u0026rsquo;ll have a solid understanding of what a debugger can do and why it\u0026rsquo;s often the most effective tool for diagnosing and fixing malfunctioning firmware.\nIn this article, we will:\nGet an overview of the debug window and available commands. Learn the differences between key debugging navigation commands. Explore the tools available for inspecting variables. Prerequisites\nThis article is the second part of a series. For the setup, please refer to the first part.\nDebug window overview # A debugger gives you control over how a program runs, letting you pause execution, inspect variables, and step through code one instruction at a time. This level of control is what sets debugging apart from simply running the program normally.\nBreakpoint # One way to use this control is by stepping line by line through the code, watching how variables change and how the program flows. While this can be helpful, it quickly becomes impractical in larger programs. Instead, it\u0026rsquo;s often more effective to let the program run freely until it reaches a specific point of interest. That’s where breakpoints come in. A breakpoint pauses execution at a defined line, giving you the opportunity to examine the program\u0026rsquo;s state and decide what to do next.\nStarting a debugging section # In this first debugging session, we\u0026rsquo;ll set a breakpoint and reach it using the first navigation command: Continue.\nOpen hello_world_main.c from the hello_world example project.\nIf the project isn\u0026rsquo;t open yet, refer to the first part of this article. Click on line 24 to set a breakpoint. A red dot will appear next to the line number (see Fig. 1). Press F5 (or go to Run → Start Debugging). This starts the debugging session.\nIf a dropdown menu appears instead, check that a launch.json file exists in the .vscode folder. You can find a basic launch.json here. Hit F5 again (Continue) to reach the breakpoint (see Fig.2). Fig.1 - Breakpoint set\nFig.2 - Debugging session started\nNavigation commands explanation # In the debugging interface, the available commands are located in the top-right corner. They are:\nHere\u0026rsquo;s the polished version of your list:\nContinue: Runs the code until the next breakpoint is reached. Step Over: Executes the current instruction or the entire function, then moves to the next instruction at the same level. Step Into: Executes the current instruction (like Step Over), but if it\u0026rsquo;s a function call, it enters the function and allows you to debug it line by line. Step Out: Executes the remaining code in the current function and exits to the calling function. Restart: Restarts the debugging session from the beginning. Disconnect: Disconnects from openOCD, effectively stopping the debugging session. All the commands are self-explanatory, except for the subtle yet important difference between Step Over and Step Into.\nIn other words, Step Into allows you to enter a function call and debug it line by line, while Step Over executes the entire function without stepping into it, moving directly to the next line in the current function.\nNavigation commands # Now, let\u0026rsquo;s put the navigation commands into action to see how they work in practice.\nIn the remainder of this section, we will:\nModify the hello_world_main.c example. Start a new debugging session. Explore the difference between Continue and Step Over. Examine the difference between Step Over and Step Into. Modifying hello_world_main.c # Let\u0026rsquo;s add a simple summation function before the main function void app_main(void):\n// Function to calculate the summation of all integers from 1 to \u0026#39;number\u0026#39; int summation(int number){ int sum = 0; for(int i=1;i\u0026lt;=number;i++){ sum += i; } return sum; } And change the void app_main(void) content to\nvoid app_main(void) { printf(\u0026#34;Hello world!\\n\u0026#34;); int final_number = 6; int sum = summation(final_number); printf(\u0026#34;The summation up to %d is %d\\n\u0026#34;,final_number,sum); } Your hello_world_main.c should now look like this gist.\nStart a new debugging session # Now, let\u0026rsquo;s start a new debugging session:\nSave the updated hello_world_main.c file. Set a breakpoint at the line int final_number=6. Press F5 to begin the debugging session. Your screen should now resemble Scr.A, as shown in Fig.1. The debugger stops execution at the beginning of the app_main function and waits for commands.\nContinue vs Step Over # Let\u0026rsquo;s look at the difference between Continue and Step Over with the help of Fig. 3.\nFig.3 - Continue vs Step-over\nContinue (F5) \u0026ndash; Scr A → Scr B\nExecution proceeds normally until it reaches the breakpoint we previously set. Step-Over (F10) \u0026ndash; Scr A → Scr C\nThe debugger executes the current line and then moves to the next line in the same function. Before moving on, let\u0026rsquo;s restart the debugging session.\nRestarting the debugging session\nPress ⇧+F5 to exit the debugging session. Press F5 to enter a new debugging session\nWe are in Scr A (Fig. 3) again Press F5 again to reach the breakpoint\nWe\u0026rsquo;re now in Scr. B (Fig. 1) which is the same as Scr. α (Fig.4) Step Over vs Step Into # Let\u0026rsquo;s now look at the difference between Step Over and Step Into with the help of Fig. 4.\nFig. 4 - Step-over vs step-into\nSince the current line in Scr. α involves a function call, it\u0026rsquo;s the perfect case to highlight the difference between Step Over and Step Into.\nStep-over (F10) \u0026ndash; Scr. α → Scr. β\nThe function is executed, and the debugger moves to the next line in the current function. Step-into (F11) \u0026ndash; Scr. α → Scr. γ The debugger steps into the function, allowing you to inspect it line by line. To continue inspecting the function, you can keep using the Step Over command. When you\u0026rsquo;re ready to exit the function call, you have two options:\nStep Out (⇧+F11) — Scr. β\nExecutes the remaining lines of the function and resumes at the line following the function call.\nContinue (F5) — Scr. α\nResumes execution until the next breakpoint is hit.\nThese navigation commands help you move through your code with precision. Next, let’s look at how to inspect variables during debugging.\nInspecting variables # So far, we\u0026rsquo;ve navigated the code flow, but without inspecting variables, it\u0026rsquo;s hard to grasp what\u0026rsquo;s really happening.\nIn this section, we\u0026rsquo;ll look into the inspecting variables tools with the help of Fig.5.\nFig.5 - Variable inspection\nLet\u0026rsquo;s start a new debugging session and reach the line sum += i.\nRestarting the debugging session\nPress ⇧+F5 to exit the debugging session. Set a breakpoint at line sum += i Press F5 to enter a new debugging session Press F5 again to reach the breakpoint As you know by now, we have a few options to get to the sum +=1 line. The easiest one (followed above) is to set a breakpoint on the line and use Continue. Available inspection tools # At this point of the code, three variables are defined : number, i and sum. The next step is to read their value.\nYou can inspect the variable in three places:\nIn the VARIABLES pane under Local on the left (see Fig 5) In the DEBUG CONSOLE, by typing the variable name and hitting Enter ⏎ By adding them to the WATCH pane VARIABLES displays all variables currently defined in the function scope, including local variables, global variables, and register values.\nDEBUG CONSOLE is the most convenient tool for quick inspections. Use it to evaluate expressions and examine memory.\nWATCH is useful for monitoring variables and expressions you want to track. Just click the + icon on the right side of the pane (see Fig. 5).\nVARIABLES pane # When the breakpoint is first reached, VARIABLES → Local displays:\nsum = 0 i = 1 Remember, the core hasn\u0026rsquo;t executed the highlighted line yet—that\u0026rsquo;s why sum is still 0.\nPressing Continue (F5) again results in what we expect to see:\nsum=1 i=2 DEBUG console # Among the available methods to view variable values during execution, the DEBUG CONSOLE \u0026mdash; highlighted at the bottom of Fig.5 - is the most flexible.\nAt any moment during the debugging session, you can write an expression in the DEBUG CONSOLE which is evaluated when hitting Enter ⏎.\nType (sum+1)*2 on the DEBUG CONSOLE (next to the \u0026gt; sign, as shown in Fig. 5). As expected, you will get 4.\nWATCH pane # As a final step, let\u0026rsquo;s explore the WATCH tool. It allows you to enter full expressions, just like in the DEBUG CONSOLE. These expressions are saved and automatically evaluated in every debugging session, with their current values shown.\nTo see the WATCH pane in action:\nClick + on the right side of WATCH pane. A text input \u0026ldquo;Expression to watch\u0026rdquo; appears. Type sum*sum inside of the text input Start a new session (⇧+F5 followed by F5) Hit F5 again to reach the breakpoint In the WATCH pane a sum*sum= 0 appeared.\nThis field is updated according to the expression value. Press F5 repeatedly to generate the sequence 0, 1, 9, 36, ... which corresponds to the square of the sum.\nThe calculation is performed in the IDE, not on the core. Conclusion # In this second part, we explored the various functions of the debugger. We first examined different ways to navigate through the code and highlighted the differences between Continue, Step-into, and Step-over. Then, we focused on tools for inspecting variables, including the DEBUG CONSOLE, the VARIABLES pane, and the WATCH tool. With these tools at your disposal, you\u0026rsquo;re now equipped to enhance your coding efficiency, identify issues more easily, and improve the overall quality of your code.\n","date":"12 June 2025","externalUrl":null,"permalink":"/blog/2025/06/debugging-with-vscode-part-2/","section":"Blog","summary":"This two-part guide shows how to set up VS Code with the ESP-IDF extension to debug Espressif boards using JTAG. In this second part, we will debug a simple project using gdb through Espressif\u0026rsquo;s VSCode extension. We will explore the debugging options for navigating the code and inspecting the variables.","title":"Debugging with ESP-IDF VS Code extension: Part 2","type":"blog"},{"content":"","date":"12 June 2025","externalUrl":null,"permalink":"/tags/vscode/","section":"Tags","summary":"","title":"Vscode","type":"tags"},{"content":"","date":"28 May 2025","externalUrl":null,"permalink":"/tags/broker/","section":"Tags","summary":"","title":"Broker","type":"tags"},{"content":" Introduction # Traditionally, MQTT brokers run in the cloud or on powerful servers. But what if we could run them directly on IoT devices?\nThe lightweight implementation of the popular Eclipse Mosquitto™ broker makes this possible. Ported to ESP-IDF, this version brings MQTT broker functionality to edge devices and reduces the need for always-on external infrastructure.\nOptimized for the limited resources of the ESP32, this port maintains the core features of Eclipse Mosquitto and benefits from its feature completeness, configurability, extensibility, and portability. Running this MQTT broker directly on the device reduces latency, enhances privacy by keeping data local, and allows for fully autonomous IoT networks \u0026ndash; even in the absence of internet connectivity.\nKey features # Supports TLS transport (based on ESP-TLS) Supports plain TCP transport Single listener configuration (only one transport at a time) Use cases of running an MQTT broker on IoT devices # While it is possible to run an MQTT broker on IoT devices, what are the use cases and considerations? Let\u0026rsquo;s explore three interesting scenarios where running the broker on an IoT device is particularly beneficial.\nLocal broker for private IoT networks # One powerful use case is running a local Mosquitto broker on the ESP32 to serve local IoT devices within a private network segment:\nCreate an independent home automation hub that works even when internet connectivity fails Integrate with platforms like ESP-Home, Home Assistant, or custom IoT devices Enhance privacy by keeping all data within the local network Testing on target # Another use-case is testing MQTT applications directly on the ESP32. By running both the client and broker on the same chip, developers can:\nDevelop and test MQTT-based applications without external dependencies Simulate complex MQTT interactions in a controlled environment Debug communication issues in isolation before deploying to a production environment Create self-contained test fixtures for IoT product validation Bridged brokers over P2P networks # The serverless MQTT example demonstrates how two ESP32 devices running Mosquitto can create a synchronized broker system over peer-to-peer connections:\nConnect IoT devices across separate private networks without requiring cloud infrastructure Synchronize two local MQTT networks across the internet using secure peer-to-peer connections Create resilient IoT networks that can operate across geographical locations Enable MQTT communication between networks separated by NATs or firewalls Technical specifications # Memory Footprint: Program memory: ~60 kB Stack size: Minimum 5 kB (recommended) Heap usage: ~2 kB on startup, ~4 kB per connected client Connectivity: TCP or TLS transport API: Simple C API with broker configuration structure Dependencies: ESP-IDF components: newlib, esp_timer, esp_tls (for secure TLS connections) Managed components: sock_utils (for porting) Implementation details # The MQTT broker is implemented as a port of the original Mosquitto codebase. It follows a single-threaded, event-driven architecture that efficiently handles multiple connections through socket multiplexing. The core of this implementation consists of a number of key components covered below.\nSocket multiplexing # The broker uses an abstracted multiplexing layer that utilizes polling implementations with:\nMux Layer: An abstraction layer (mux.c) that provides common interface functions for socket multiplexing Poll Implementation: Uses standard poll() mechanisms for handling multiple file descriptors Event loop # The main broker loop (loop.c) performs the following operations:\nProcesses incoming client connections Handles socket read/write events Manages client keepalive tracking Processes message queues and subscriptions Handles disconnections and cleanup ESP-IDF integration # The port includes a custom implementation (net__esp_tls.c) that integrates ESP-TLS for secure connections, which handles TLS context initialization and manages secure socket connections. ESP-TLS is an internal component of ESP-IDF providing simplified and abstracted access to security related APIs, you can read more about it in the official ESP-IDF documentation.\nSimplified message handling # graph TD A[Client Connection Request] --\u003e B[Socket Accept] B --\u003e C{TLS Enabled?} C --\u003e|Yes| D[ESP-TLS Context Creation] C --\u003e|No| E[Plain TCP Connection] D --\u003e F[TLS Handshake] F --\u003e G[Connection Ready] E --\u003e G G --\u003e H[Socket Multiplexing] subgraph \"Event Loop\" H --\u003e I[Poll for Events] I --\u003e J[Process Socket Events] J --\u003e K[Handle Client Messages] K --\u003e L[Route Messages to Subscribers] L --\u003e I end M[Client Disconnect] --\u003e N[Socket Cleanup] N --\u003e O[Release Resources] How to use the MQTT broker in your project # To use the ESP32 Mosquitto Port in your projects, you\u0026rsquo;ll need to download the mosquitto component and initialize the broker with appropriate configuration settings. It is important to provide sufficient stack space for the running task.\nStart from an existing example # Use the below command to create a new project from the simple broker example\n$ idf.py create-project-from-example \u0026#34;espressif/mosquitto:broker\u0026#34; Configure the project with:\n$ idf.py menuconfig In the appeared configuration menu:\nGo to Connection and choose the preferred connection Go to Example and choose the example transport (TLS or plain TCP) Then build and flash normally with: $ idf.py build flash monitor Use the broker in your project # Add mosquitto component to your project dependency with:\n$ idf.py add-dependency \u0026#34;espressif/mosquitto\u0026#34; Configure the broker and start it in your application:\nstruct mosq_broker_config config = { .host = \u0026#34;0.0.0.0\u0026#34;, // Listen on all interfaces .port = 1883, // Standard MQTT port .tls_cfg = NULL // No TLS in this example }; // Start the broker (runs in the current task) mosq_broker_run(\u0026amp;config); Future development # The ESP32 Mosquitto Port is designed to be expanded with additional features in future releases, supporting:\nPlugins and configuration files to extend broker functionality WebSocket and Websocket Secure transports License information # The ESP32 Mosquitto Port is licensed under the dual Eclipse Distribution License (EDL) and Eclipse Public License (EPL). These licenses ensure that the software remains free and open-source while providing clear terms for usage, modification, and distribution.\nEclipse Distribution License (EDL): A BSD-style license that allows for commercial use, modification, distribution, and private use with minimal restrictions. Eclipse Public License (EPL): A copyleft license that requires any distributed modifications to also be licensed under the EPL. For full license details, please refer to the LICENSE files included in the source code repository:\nedl-v10 - Eclipse Distribution License version 1.0 epl-v20 - Eclipse Public License version 2.0 Resources # Official Mosquitto documentation ESP32 Mosquitto component ESP32 Mosquitto port development repository Brokerless MQTT example Eclipse, Eclipse Mosquitto, and the Eclipse Foundation logos are trademarks of Eclipse Foundation, Inc. ","date":"28 May 2025","externalUrl":null,"permalink":"/blog/2025/05/esp-idf-mosquitto-port/","section":"Blog","summary":"Mosquitto \u0026ndash; the industry-standard MQTT broker \u0026ndash; has been ported to ESP-IDF. Its lightweight version retains Mosquitto\u0026rsquo;s core functionality and security features to run on resource-constrained IoT devices. This MQTT broker is ideal for edge computing, testing, and standalone IoT deployments. In this article, we will do an overview and show you how to get started.","title":"Lightweight MQTT Broker for ESP32: Mosquitto ported to ESP-IDF","type":"blog"},{"content":"","date":"28 May 2025","externalUrl":null,"permalink":"/tags/mqtt/","section":"Tags","summary":"","title":"MQTT","type":"tags"},{"content":"Espressif Systems (SSE: 688018.SH) announced ESP32-C5, the industry’s first RISC-V SoC that supports 2.4 GHz and 5 GHz dual-band Wi-Fi 6, along with Bluetooth 5 (LE) and IEEE 802.15.4 (Zigbee, Thread) connectivity. Today, we are glad to announce that ESP32-C5 is now in mass production.\nESP32-C5 is designed for applications that require high-efficiency, low-latency wireless transmission. ESP32-C5 has a 32-bit single-core processor which can clock up to 240 MHz in speed. It has a 384 KB on-chip SRAM along with external PSRAM support, 320 KB of ROM. It has up to 29 programmable GPIOs, supporting all the commonly used peripherals, high speed interfaces like SDIO, QSPI, and the best-in-class security features. The ESP32-C5 also includes an LP-CPU running upto 40MHz which can act as the main processor for power sensitive applications. To learn more about the various capabilities and features of this MCU, please visit our website.\nThe ESP32-C5 benefits from software support provided by Espressif\u0026rsquo;s well-established IoT development framework, ESP-IDF. The upcoming ESP-IDF v5.5, will include initial support for the ESP32-C5. For a detailed list of ESP-IDF features supported for the ESP32-C5, click here. The ESP32-C5 can also act as the connectivity coprocessor for external hosts using the ESP-AT or ESP-Hosted solutions.\nESP32-C5 development boards are now available for purchase at Espressif\u0026rsquo;s official stores If you are interested in the ESP32-C5 series products, please contact our customer support team.\nWhere to buy # Taobao (China) AliExpress (outside of China) Amazon (US) Robu (India) Digikey Mouser Akizuki References # Press Release ","date":"23 May 2025","externalUrl":null,"permalink":"/blog/2025/05/news-esp32c5-mp/","section":"Blog","summary":"Espressif has launched the ESP32-C5, the first RISC-V SoC with dual-band Wi-Fi 6, Bluetooth 5 (LE), and IEEE 802.15.4 support. Designed for low-latency wireless applications, it features a 240 MHz CPU, LP-CPU, and rich peripheral options. Backed by ESP-IDF, the ESP32-C5 is now in mass production and ready for developers.","title":"Espressif's ESP32-C5 is Now in Mass Production","type":"blog"},{"content":" Introduction # Debugging is a critical part of the development process, especially when working with embedded systems. It allows developers to identify and fix errors, ensuring that the firmware interacts correctly with the peripherals and the external hardware. While there are several ways to debug code, the most powerful method is to use a debugger, which provides real-time insights into how the code runs on the hardware.\nMany developers start with basic debugging, often using printf statements to track program flow and check variable values. While helpful, this method has major limits. Printf-based debugging forces you to change the code and recompile it each time you test something new. In contrast, debuggers let you step through code, inspect memory, and set breakpoints without touching the source.\nIn this guide, we\u0026rsquo;ll walk through the steps necessary to set up debugging for Espressif devices using Visual Studio Code (VS Code) and the ESP-IDF Extension. The ESP-IDF Extension manages the whole toolchain, but knowing the tools it uses, like openOCD and gdb, gives you more control and helps you fix problems that may arise along the way.\nThis guide will show you the two available hardware paths to debug Espressif devices (JTAG pins and USB pins) and the interacting tools which make debugging possible.\nThis article has two parts. In this first part, we will explain the debugging process, describe the tools, set up the hardware, and start the openOCD server. In the second part, we will run gdb and explore its options for debugging the code.\nIn the rest of the article, we’ll use “Espressif device\u0026quot; to refer to both the modules and SoCs, since the steps below apply to both.\nPrerequisites\nBefore you begin, make sure you have the following:\nAn Espressif development board based on one of the following series: ESP32-C3, ESP32-C6, or ESP32-S3\nEither an expendable USB cable (that supports data transfer) or the ESP-PROG debug probe\nVisual Studio Code (VS Code)\nIf not installed, follow the installation instructions\nESP-IDF Extension for VS Code\nIf not installed, follow the setup instructions\nAbility to use ESP-IDF extension for VS Code to build, flash, and monitor a simple example project, such as blink or hello_world\nIf you\u0026rsquo;re unsure, check Create an ESP-IDF Project\nDebugging process # The debugging process requires several tools working together. You interact with the IDE, which manages the compiler, the debugger and the flasher (software) tool. The flasher tool communicates to a (hardware) programmer which can upload the firmware to the flash memory of the microcontroller and manage JTAG interactions.\nWith USB enabled devices, the programmer/debugger is built into the SoC (but remains external to the workstation). You can find an overview of the debugging process in Fig. 1.\nFig.1 - Debugging Workflow\nWe will use VSCode IDE with ESP-IDF Extension, which manages the following tools for both flashing and debugging:\nCompiling and flashing: The extension uses idf.py, which is a CLI front-end tool which takes care of the compilation (CMake/ninja) and the flashing (esptool.py) processes. Debugging: The extension connects seamlessly with esp-gdb which derives from the venerable GNU Debugger (gdb). The esp-gdb interfaces with a forked version of openOCD called openocd-esp32 which supports newly released SoC series sooner than the original openOCD. We will use the terms openocd-esp32 and openOCD interchangeably. The same goes for esp-gdb and gdb. With older ESP-IDF plugin versions, you needed to install openOCD separately. Now it comes directly with ESP-IDF plugin. Testing openOCD availability\nLet\u0026rsquo;s check if your version of VS Code extension comes with openOCD installed.\nMost commands in VSCode are executed through the Command Palette, which you can open by pressing CTRL+SHIFT+P (or CMD+SHIFT+P if you\u0026rsquo;re on mac-os). In this guide, commands to enter in the Command Palette are marked with the symbol \u0026gt; . Lauch VS Code. Open a new Terminal. \u0026gt; ESP-IDF: Open ESP-IDF-Terminal In the terminal type openocd --version You should read something like\nOpen On-Chip Debugger v0.12.0-esp32-20241016 (2024-10-16-14:27) Now that we ensured we\u0026rsquo;re using an updated IDE, let\u0026rsquo;s set up the hardware.\nHardware for debugging # Espressif devices usually require separate hardware for flashing and debugging via JTAG. By default, you flash Espressif devices using the serial port (UART0) which does not support JTAG. Note that most of Espressif development boards do not include a JTAG probe. A notable exception is the ESP32-WROVER-KIT. They only offer a USB-to-UART connection for flashing and monitoring.\nTo debug an development board—or any Espressif-based board—you have two options:\nJTAG over JTAG pins (with a JTAG probe) \u0026ndash; briefly described below for completeness JTAG over USB pins \u0026ndash; used in the rest of the article All Espressif devices support the first option. The second option works only with USB-equipped devices, such as the ESP32-S3 or ESP32-C3. Although both options are shown, in the rest of the article, we will use the JTAG over USB pins option.\nJTAG over JTAG pins # To debug using the JTAG pins, you first need a JTAG probe. Espressif offers a probe called ESP-PROG, whose JTAG connector is shown in Fig.2.\nFig.2 - ESP-PROG JTAG connector\nTo enable JTAG programming, connect the four pins TMS, TCK, TDO, TDI of the JTAG probe to the corresponding Espressif module pins.\nIn the table below, you can find the pins for three common modules.\nJTAG ESP-PROG ESP32-C3-MINI-1 ESP32-S3-WROOM-1 ESP32-C6-WROOM-1 TMS ESP_TMS GPIO 4 GPIO 42 GPIO 4 TCK ESP_TCK GPIO 6 GPIO 39 GPIO 6 TDO ESP_TDO GPIO 7 GPIO 40 GPIO 7 TDI ESP_TDI GPIO 5 GPIO 41 GPIO 5 For other modules, consult the Pin Description section of the datasheet and look for MTMS, MTCK, MTDO, MTDI pins.\nThe JTAG peripheral is generally enabled by default and can be disabled in production and for security reasons using the appropriate eFuses (EFUSE_DISABLE_JTAG or EFUSE_HARD_DIS_JTAG depending on the SoC series).\nWhile the ESP-PROG works with most Espressif devices, it requires additional hardware and uses up to four pins. In newer cores, you have a second option via USB, as shown Debugging workflow illustration in Fig.1.\nJTAG over USB # Most newer Espressif SoC series integrate the USB peripheral and it can be used for JTAG debugging. Take a thick usb cable (designed for both charging and data transmission) and strip it using a wire stripper or a pair of scissors. You should see the four wires inside, as shown in Fig.3.\nFig.3 - USB cable pins\nNow connect GND , D+ and D- to the corresponding Espressif module pins. If you\u0026rsquo;re using an development board you can connect VCC to the +5V of the pin (not the 3v3 pin!).\nUSB supply pin is about 5V. To power your board with it, connect VCC to the input of an LDO regulator that outputs 3.3V for the Espressif module. In the table below, you can find the pins for three common modules.\nESP32-C3-MINI-1 ESP32-S3-WROOM-1 ESP32-C6-WROOM-1 D+ GPIO 19 GPIO 19 GPIO 13 D- GPIO 18 GPIO 20 GPIO 12 For other modules, consult the Pin Description section of the datasheet and look for USB_D+ and USB_D-.\nNow that the hardware is ready, we can move back to the IDE. We will use the JTAG over USB pin option.\nOpenOCD connection # OpenOCD uses a server-client model to debug embedded systems. The OpenOCD server connects to the target hardware through a debug adapter (usually via JTAG). It exposes a network interface that clients, such as gdb or telnet, can use to send commands or load code.\nNext, we\u0026rsquo;ll start the openOCD server and test the connection with the hardware. The steps below are for an ESP32-C3 board, but you can easily adjust them for your module. We will use the JTAG over USB pins option. If you\u0026rsquo;re using the ESP-PROG, modify steps 2 and 3 accordingly.\nCreate a project from the hello_world example.\nIf you\u0026rsquo;re unsure, please check the documentation \u0026gt; ESP-IDF: Select Port to Use (COM, tty, usbserial) - Choose the port you\u0026rsquo;re connected to. You may find the SoC name and package next to the correct option (e.g. ESP32-C3 (QFN32) (revision v0.3)) \u0026gt;ESP-IDF: Set Espressif Device target → esp32c3 →ESP32-C3 chip (via Built-in USB-JTAG)\n(\u0026quot;esp32c3\u0026quot; should now appear at the bottom left corner) \u0026gt;ESP-IDF: Select OpenOCD Board Configuration→ESP32-C3 chip (via Built-in USB-JTAG) \u0026gt;ESP-IDF: OpenOCD Manager → Start OpenOCD The Scan for kits notification may appear. You can allow it to automatically set up the port and board, but be sure to check the result! After completing the steps, you should see:\nOpen On-Chip Debugger v0.12.0-esp32-20241016 (2024-10-16-14:27) Licensed under GNU GPL v2 For bug reports, read http://openocd.org/doc/doxygen/bugs.html debug_level: 2 Info : only one transport option; autoselecting \u0026#39;jtag\u0026#39; Info : esp_usb_jtag: VID set to 0x303a and PID to 0x1001 Info : esp_usb_jtag: capabilities descriptor set to 0x2000 Info : Listening on port 6666 for tcl connections Info : Listening on port 4444 for telnet connections Info : esp_usb_jtag: serial (84:F7:03:42:8C:A8) Info : esp_usb_jtag: Device found. Base speed 40000KHz, div range 1 to 255 [...] Info : [esp32c3] Examination succeed Info : [esp32c3] starting gdb server on 3333 Info : Listening on port 3333 for gdb connections Congratulations, openOCD server is now waiting for a connection. In the second part, we\u0026rsquo;ll start gdb and connect to it.\nTroubleshooting # Some issues may have logs that are hard for beginners to understand. Below are two common problems and how to fix them.\nAddress already in use # You could gets\n❌ Error: couldn\u0026#39;t bind tcl to socket on port 6666: Address already in use it means that openOCD is already running. To close it, you have to:\nOpen an ESP-IDF terminal: ≫ESP-IDF: Open ESP-IDF Terminal Find the process number: ps aux | grep openocd (e.g. 13819) Kill the process: kill \u0026lt;process-nr\u0026gt; (e.g. kill 13819) Could not find or open device # You could get Error: esp_usb_jtag: could not find or open device (ESP32-S3-DevKitC-1) (OCD-631) #219\nit may mean that the firmware inside the board does not expect the connection.\nYou may need to\nBuild the project\n\u0026gt; ESP-IDF: Build your project. Flash the firmware\n\u0026gt; ESP-IDF: Flash (UART) your project. If you followed the steps above, the flashing is performed via the JTAG peripheral through the USB pins.\nIf it\u0026rsquo;s still not working, connect your board via UART0 pins (which in an development board can be accessed using the development board USB port)\nChoose the right port\n≫ ESP-IDF: Select Port to Use (COM, tty, usbserial) Flash it again\n\u0026gt; ESP-IDF: Flash (UART) your project. Conclusion # In this tutorial, you learned how to connect your Espressif module via JTAG and start the openOCD server. In part two, we\u0026rsquo;ll launch gdb and explore the code using various commands.\nGo to Part 2\n","date":"20 May 2025","externalUrl":null,"permalink":"/blog/2025/05/debugging-with-vscode/","section":"Blog","summary":"This two-part guide shows how to set up VS Code with the ESP-IDF extension to debug Espressif boards using JTAG. This first part covers the debugging process, hardware setup and connections, and starting the openOCD server.","title":"Debugging with ESP-IDF VS Code extension: Part 1","type":"blog"},{"content":" Introduction # This series of articles demonstrates how to use multiple ESP32-C6 peripherals to build a complete motor control and sensing system. We\u0026rsquo;ll explore:\nMotor Control PWM (MCPWM) for DC motor speed control Quadrature encoder (pulse counter) for motor speed measurement ADC for real-time potentiometer position reading Inertial Measurement Unit (IMU) via I2C for vibration analysis Wireless connectivity for data acquisition and processing The goal is to build a comprehensive motor control and sensing system using the NuttX RTOS. We\u0026rsquo;ll implement open-loop speed control while measuring mechanical vibrations through an IMU. The system will stream sensor data wirelessly to a computer for logging and analysis, showcasing NuttX\u0026rsquo;s real-time capabilities, multi-threading support and the ESP32-C6 wireless connectivity features.\nIn this first article, we\u0026rsquo;ll focus on implementing basic motor control. You\u0026rsquo;ll learn how to use the ESP32-C6 MCPWM peripheral to drive a DC motor through an H-bridge, with speed control provided by a potentiometer input and reading the quadrature encoder. This will give us the basic functionalities before we can get to data offloading and analysis in the next article.\nGetting Started # If you are not familiar with NuttX, please refer to the NuttX official documentation and Getting Started with NuttX and ESP32 article. This article assumes basic familiarity with the NuttX environment and jumps straight into the application development.\nAs the starting point for our project, we create an empty repository that will be used as an extension of nuttx-apps. This approach allows simple integration with the NuttX build system, just like a standard application.\nHardware Requirements # The following components are used in this project:\nCHR-GM25-370 6V DC Motor with integrated gearbox and quadrature encoder L298N H-Bridge motor driver module 10kΩ linear potentiometer GY521 IMU module (MPU6050) ESP32-C6-DevkitC development board All components have been mounted on a test bench as shown below:\nMotor Setup # For motor control using the H-Bridge, we can use either one or two pins for PWM signals. Using one pin works but the motor will only spin in one direction, while two pins allows us to control both direction (forward and reverse) and speed.\nWhile NuttX and the Espressif MCPWM driver support both modes, this application focuses on unidirectional control using a single GPIO. We\u0026rsquo;ll use PWM_A on GPIO 20 of the ESP32-C6 to control motor speed.\nOur setup uses an L298N H-Bridge module driving a 6V DC motor. The motor includes a gearbox that reduces the output speed to 210 RPM. A quadrature encoder attached to the gearbox shaft will be used for speed measurement. The encoder is powered with 3.3 V and channels 1 and 2 of the encoder are connected to GPIO pins 10 and 11.\nPotentiometer Setup # Motor speed control is implemented using a normalized range from 0.0 to 1.0. A potentiometer provides manual control over this range, allowing intuitive speed adjustment.\nThe ADC support in ESP32 and NuttX makes this implementation straightforward. We\u0026rsquo;ll connect the potentiometer\u0026rsquo;s wiper to GPIO 3 (ADC1 Channel 3) and power it with the board\u0026rsquo;s 3.3V supply.\nSchematic # The schematic for this setup is available in the figure below.\nApplication Setup # Before diving into the code, we need to configure the required drivers for motor control and ADC functionality.\nWe\u0026rsquo;ll start with the motor defconfig for the ESP32-C6, which provides the baseline configuration for motor control features.\nSet up Motor Driver # In the nuttx directory, configure the board using:\n./tools/configure.sh esp32c6-devkitc:motor Next, enter the menuconfig interface with make menuconfig and navigate to System Type → MCPWM Configuration → MCPWM Motor Configuration. Here you can verify that GPIO 20 is correctly assigned to PWM_A output. This menu also allows customization of the PWM frequency and configuration of a fault GPIO pin, which can be used as a hardware safety cutoff.\nSet up Quadrature Encoder # The pulse counter (PCNT) peripheral of the ESP32-C6 can be configured as a quadrature encoder interface. While we could use the existing qencoder defconfig, we\u0026rsquo;ll configure it manually to understand the available options and their impact on encoder operation.\nIn menuconfig, navigate to System Type → Peripheral Support and enable Pulse Counter (PCNT / QE) Module. This will open a configuration menu where we need to set:\nEnable PCNT Unit 0 Use this PCNT Unit as Quadrature Encoder Enable Glitch Filter for this PCNT Unit The quadrature encoder driver operates in X4 mode by default, providing maximum resolution for position and speed measurement. Configure the GPIO pins as follows:\nPCNT Unit 0 Configuration: - CH0 Edge/Pulse Pin: GPIO 10 - CH0 Level/Control: GPIO 11 - CH1 Edge/Pulse Pin: GPIO 10 - CH1 Level/Control: GPIO 11 Finally, enable the generic quadrature encoder driver support:\nNavigate to Device Drivers Enable Sensor Device Support Enter the Sensor menu and enable Qencoder Once configured, the quadrature encoder will be available as a character device at /dev/qe0.\nSet up ADC # With its 12-bit SAR ADC, the ESP32-C6 can directly read the potentiometer position. Although NuttX provides a ready-to-use adc defconfig, following the manual configuration steps helps understand how the ADC peripheral is set up for our specific application.\nIn menuconfig, navigate to System Type → Peripheral Support and enable the ADC driver. The ESP32-C6 provides one ADC unit, while some other ESP32 variants offer two units.\nUnder System Type → ADC Configuration, you can configure the ADC\u0026rsquo;s input attenuation, operation mode, and channel selection. Navigate to ADC1 Channel Selection and enable ADC Channel 3 (GPIO 3).\nEach ADC channel maps to a specific GPIO pin. You can find these mappings in the ESP32-C6 datasheet or the NuttX documentation for ADC.\nFor debugging purposes, it\u0026rsquo;s recommended to enable the ADC example application. Navigate to Application Configuration → Examples and enable ADC Example along with Use software trigger.\nVerify Driver Registration # After configuring the device drivers on menuconfig, let\u0026rsquo;s verify they\u0026rsquo;re properly registered in the system. Build and flash the firmware:\nmake make flash ESPTOOL_BINDIR=./ ESPTOOL_PORT=/dev/ttyUSB0 Open a serial terminal and check the available devices:\nnsh\u0026gt; ls /dev /dev: adc0 console motor0 null pcnt0 qe0 random ttyS0 zero Success! We can see /dev/adc0, /dev/motor0 and /dev/qe0 are now available, confirming successful driver initialization.\nSave Configuration # It\u0026rsquo;s a good practice to save working configurations for future use. This eliminates the need to manually reconfigure menuconfig options each time you rebuild.\nSave your current configuration:\nmake savedefconfig Make sure to copy the generated defconfig file outside the nuttx tree to prevent it from being deleted during make distclean operations.\nWriting Application Code # Our motor control application implements the following functionality:\nOpening character driver for motor and ADC Motor speed control using a normalized range (0.0 to 1.0) Emergency motor stop capability ADC sampling from the potentiometer Real-time conversion of ADC readings to motor speed values Continuous speed updates based on potentiometer position Shows speed measurement in RPM from the encoder data Code Structure # The application follows this directory structure:\n. ├── apps │ ├── Make.defs │ ├── Makefile │ ├── motor_sensing │ │ ├── config │ │ │ └── defconfig │ │ ├── Kconfig │ │ ├── Make.defs │ │ ├── Makefile │ │ └── motor_sensing_main.c ├── LICENSE └── README.md The main implementation resides in motor_sensing_main.c, while our saved configuration is stored in apps/motor_sensing/config/defconfig.\nFor details on external application integration with NuttX, refer to the official documentation.\nThis entire application is available on a GitHub repository.\nImplementation Details # First, we define the constants needed for our application. These include device paths, ADC thresholds, and encoder parameters:\n#define MOTOR_DEVPATH \u0026#34;/dev/motor0\u0026#34; #define ADC_DEVPATH \u0026#34;/dev/adc0\u0026#34; #define QE_DEVPATH \u0026#34;/dev/qe0\u0026#34; #define ADC_MIN_THRESHOLD 100 #define ADC_MAX_THRESHOLD 2500 #define TASK_DELAY_MS 100 #define BASE_PPR 11 /* Base encoder PPR */ #define GEAR_RATIO 34 /* Gear reduction ratio */ #define PULSES_PER_REV (BASE_PPR * GEAR_RATIO) The constants are organized as follows:\nDevice paths for accessing our character drivers ADC thresholds create dead zones at the extremes of potentiometer travel Encoder parameters account for both the base encoder resolution and the gearbox ratio The control loop period defines how often we update motor speed and read sensors Next, we implement the motor control function. By consulting include/nuttx/motor/motor.h, we can access the motor control API.\nWe create a motor_set_speed function that first checks which state the motor is in, so we can then set the operation mode, target speed and start it. This function takes two arguments: the file descriptor of the motor driver and a floating point value for speed, with a range of 0.0 to 1.0.\nstatic int motor_set_speed(int fd, float speed) { int ret; struct motor_state_s state; if (speed \u0026lt; 0.0 || speed \u0026gt; 1.0) { printf(\u0026#34;Error: Speed must be between 0.0 and 1.0\\n\u0026#34;); return ERROR; } printf(\u0026#34;Setting motor speed to: %f\\n\u0026#34;, speed); /* Get current motor state */ ret = ioctl(fd, MTRIOC_GET_STATE, (unsigned long)\u0026amp;state); if (ret \u0026lt; 0) { printf(\u0026#34;Failed to get motor state: %d\\n\u0026#34;, ret); return ret; } ret = ioctl(fd, MTRIOC_SET_MODE, MOTOR_OPMODE_SPEED); if (ret \u0026lt; 0) { printf(\u0026#34;Failed to set speed mode: %d\\n\u0026#34;, ret); return ret; } params.speed = speed; ret = ioctl(fd, MTRIOC_SET_PARAMS, \u0026amp;params); if (ret \u0026lt; 0) { printf(\u0026#34;Failed to set parameters: %d\\n\u0026#34;, ret); return ret; } /* Only start if not already running */ if (state.state != MOTOR_STATE_RUN) { ret = ioctl(fd, MTRIOC_START, 0); if (ret \u0026lt; 0) { printf(\u0026#34;Failed to start motor: %d\\n\u0026#34;, ret); return ret; } } return OK; } For ADC handling, by consulting include/nuttx/analog/adc.h, we can access the ADC driver API. We implement a function that reads the potentiometer voltage and maps it to our motor speed range. The function applies threshold values to create dead zones at the extremes of the potentiometer\u0026rsquo;s travel:\nstatic int check_speed_update(int adc_fd, float *speed) { int ret; struct adc_msg_s sample; size_t readsize; ssize_t nbytes; if (speed == NULL) { return ERROR; } /* Trigger ADC conversion */ ret = ioctl(adc_fd, ANIOC_TRIGGER, 0); if (ret \u0026lt; 0) { printf(\u0026#34;ANIOC_TRIGGER ioctl failed: %d\\n\u0026#34;, errno); return ERROR; } /* Read ADC value */ readsize = sizeof(struct adc_msg_s); nbytes = read(adc_fd, \u0026amp;sample, readsize); if (nbytes \u0026lt;= 0) { printf(\u0026#34;ADC read failed: %d\\n\u0026#34;, errno); return ERROR; } /* Apply thresholds and map ADC value to speed */ if (sample.am_data \u0026lt; ADC_MIN_THRESHOLD) { *speed = 0.0; } else if (sample.am_data \u0026gt; ADC_MAX_THRESHOLD) { *speed = 1.0; } else { /* Linear mapping from ADC range to speed range */ *speed = (float)(sample.am_data - ADC_MIN_THRESHOLD) / (float)(ADC_MAX_THRESHOLD - ADC_MIN_THRESHOLD); } printf(\u0026#34;ADC Value: %\u0026#34; PRId32 \u0026#34; | Motor Speed: %.2f\\n\u0026#34;, sample.am_data, *speed); return OK; } Regarding quadrature encoder, by consulting include/nuttx/sensors/qencoder.h, we can access the quadrature encoder API. Our control loop should read the quadrature encoder position each iteration, reset it and calculate the motor speed in RPM. The speed calculation takes into account:\nThe X4 encoding mode, which generates 4 counts per encoder pulse The gearbox reduction ratio The base encoder resolution (pulses per revolution) The time elapsed between measurements static float calculate_rpm(int32_t pulses, uint32_t time_ms) { /* Convert encoder pulses to RPM: * RPM = (pulses/4 / PULSES_PER_REV) * (60000 / time_ms) * Note: divide by 4 because driver uses X4 encoding by default */ return ((float)(pulses / 4.0f) * 60000.0f) / ((float)PULSES_PER_REV * (float)time_ms); } Our main control loop now handles both speed control and measurement:\nReads the commanded speed from the potentiometer via ADC Updates the motor speed Reads and resets the encoder position Calculates and displays the actual motor speed in RPM while (!g_should_exit) { /* Get commanded speed from ADC */ ret = check_speed_update(adc_fd, \u0026amp;speed); if (ret == OK) { ret = motor_set_speed(motor_fd, speed); if (ret != OK) { printf(\u0026#34;Failed to set motor speed\\n\u0026#34;); break; } } else { printf(\u0026#34;Failed to update speed from ADC\\n\u0026#34;); break; } /* Read encoder position */ ret = ioctl(qe_fd, QEIOC_POSITION, (unsigned long)((uintptr_t)\u0026amp;position)); if (ret \u0026lt; 0) { printf(\u0026#34;Failed to read position: %d\\n\u0026#34;, ret); break; } /* Reset counter to avoid overflow */ ret = ioctl(qe_fd, QEIOC_RESET, 0); if (ret \u0026lt; 0) { printf(\u0026#34;Failed to reset encoder: %d\\n\u0026#34;, ret); break; } /* Calculate and display speeds */ rpm = calculate_rpm(position, TASK_DELAY_MS); printf(\u0026#34;Command: %.2f%%, Speed: %.2f RPM\\n\u0026#34;, speed * 100.0f, rpm); usleep(TASK_DELAY_MS * 1000); } Testing Application # To test our implementation, we\u0026rsquo;ll first load our saved configuration and rebuild the environment with our custom application enabled.\nEnvironment Setup # First, clean the current environment and link our external repository. If this is your first time adding an external directory:\n# In the nuttx directory make distclean cd .. ln -s \u0026lt;absolute path to external repo\u0026gt;/nuttx-esp-motor-sensing/apps/ $PWD/apps/external This makes our application available in the Application Configuration menu alongside standard applications.\nThere are two approaches to configure NuttX with our custom settings:\nCopy the saved defconfig to NuttX\u0026rsquo;s board directory Load the base configuration and merge with our custom defconfig We\u0026rsquo;ll use the second approach to avoid modifying the source tree:\n# Load base configuration ./tools/configure.sh esp32c6-devkitc:nsh # Merge with our custom defconfig kconfig-merge -m .config ../apps/external/motor_sensing/config/defconfig \u0026amp;\u0026amp; make olddefconfig Now enable our application through menuconfig. Navigate to Application Configuration → Motor Sensing Apps and enable the Motor Sensing Example.\nBuild and flash the firmware to your board:\nmake make flash ESPTOOL_BINDIR=./ ESPTOOL_PORT=/dev/ttyUSB0 Running the Application # With the board flashed and the H-Bridge powered up, review the connections:\nGPIO 20 to the H-Bridge input signal GPIO 3 to the potentiometer wiper GPIO 10 and 11 to encoder Power the potentiometer and encoder with 3.3V Power the H-Bridge externally Launch the application from the NSH console:\nnsh\u0026gt; msense Reading ADC and controlling motor... Sample time: 100 ms ADC range: 100 to 2500 Encoder PPR: 374 Command: 0.00%, Speed: 0.00 RPM As you rotate the potentiometer, you\u0026rsquo;ll see the ADC values and corresponding motor speeds update in real-time. The motor\u0026rsquo;s speed will smoothly follow the potentiometer position:\nCommand: 51.67%, Speed: 36.90 RPM Command: 55.25%, Speed: 78.61 RPM Command: 58.13%, Speed: 94.65 RPM Command: 62.42%, Speed: 102.67 RPM Command: 67.46%, Speed: 110.70 RPM Command: 72.50%, Speed: 117.11 RPM Command: 77.46%, Speed: 125.13 RPM Command: 82.50%, Speed: 133.16 RPM (also available on BiliBili) Conclusion # In this first article, we\u0026rsquo;ve successfully implemented basic motor control using NuttX on an ESP32-C6. We\u0026rsquo;ve covered several key aspects:\nSetting up NuttX\u0026rsquo;s MCPWM driver for motor control Configuring ADC for analog input reading Setting up quadrature encoder for speed measurement Implementing real-time speed control using a potentiometer Reading actual motor speed through encoder feedback The implementation demonstrates NuttX\u0026rsquo;s capability to handle real-time control tasks while maintaining a clean and organized codebase. By using the character driver interface, we\u0026rsquo;ve created a portable application that could be adapted to other boards with minimal changes.\nWhile this implementation uses open-loop control, it provides speed measurement through the quadrature encoder. The motor responds well to potentiometer input, and the ADC sampling provides stable readings for speed control.\nWhat\u0026rsquo;s Next # In the second part of this series, we expand this foundation to create a complete motor control and analysis system. The following items are added:\nMPU6050 IMU configuration for vibration analysis Wi-Fi connectivity for real-time data streaming Data visualization and analysis on a host computer You can access the second article here.\nRelated Resources # NuttX ESP32 Documentation ESP32-C6 Technical Reference Manual Example Repository Getting Started with NuttX and ESP32 Part 2: NuttX for Motor Control and Sensing: IMU Integration and Wireless Data Streaming ","date":"16 May 2025","externalUrl":null,"permalink":"/blog/2025/05/nuttx-motor-control-and-sensing/","section":"Blog","summary":"This article demonstrates how to implement motor control and speed sensing on an ESP32-C6 using NuttX RTOS. It covers setting up MCPWM for motor control, ADC for potentiometer reading, and quadrature encoder for speed measurement. The implementation showcases NuttX\u0026rsquo;s real-time capabilities through a practical example using common peripherals and sensors.","title":"NuttX for Motor Control and Sensing: MCPWM and DC Motor Control","type":"blog"},{"content":"","date":"1 May 2025","externalUrl":null,"permalink":"/tags/hmi/","section":"Tags","summary":"","title":"HMI","type":"tags"},{"content":"The ESP32-P4 is tailored for high-performance embedded applications, with strong support for rich Human-Machine Interfaces, efficient edge computing, and increased IO-connectivity demands.\nTo experience its rich capabilities, Espressif has launched ESP32-P4 EYE Devkit, a devkit with a mini digital camera form factor.\nESP32-P4-EYE is a vision development board based on the ESP32-P4 SoC, mainly targeting camera applications. ESP32-P4 features a dual-core 400 MHz RISC-V processor and supports up to 32 MB of PSRAM. In addition, ESP32-P4 supports USB 2.0 standard, MIPI-CSI/DSI, H264 Encoder, and various other peripherals. With all of its outstanding features, the board is an ideal choice for developing low-cost, high-performance, low-power network-connected audio and video products.\nThe board integrates the ESP32-C6-MINI-1U module for Wi-Fi, Bluetooth, Thread and Zigbee. It supports MIPI-CSI camera interface and USB 2.0 High-Speed device mode. Rich onboard features include a camera, display, microphone, and MicroSD card, enabling real-time monitoring of the environment and collection of image and audio data. It is suitable for applications such as smart surveillance cameras, vision model detection, and edge computing in IoT that require real-time image processing and wireless communication.\nThe pilot batch will come in a 3D printed enclosure. Grab them while stocks last!\nESP32-P4 EYE DevKit is now available on the Official AliExpress Store.\nResources:\nESP32-P4 EYE User Guide ESP32-P4 Overview ","date":"1 May 2025","externalUrl":null,"permalink":"/blog/2025/05/introducing-p4-eye/","section":"Blog","summary":"Discover the ESP32-P4 EYE DevKit — a compact, camera-focused development board designed for real-time image processing and edge computing. Learn how this powerful, low-cost solution can accelerate your next smart camera or IoT project.","title":"Introducing ESP32-P4-EYE: A Powerful Vision Development Board for Edge AI","type":"blog"},{"content":"","date":"1 May 2025","externalUrl":null,"permalink":"/tags/mipi-csi/","section":"Tags","summary":"","title":"MIPI-CSI","type":"tags"},{"content":"","date":"1 May 2025","externalUrl":null,"permalink":"/tags/p4/","section":"Tags","summary":"","title":"P4","type":"tags"},{"content":"","date":"1 May 2025","externalUrl":null,"permalink":"/authors/tan-kai-jie-kyler/","section":"Developer Portal Authors","summary":"","title":"Tan Kai Jie (Kyler)","type":"authors"},{"content":"","date":"1 May 2025","externalUrl":null,"permalink":"/tags/technology/","section":"Tags","summary":"","title":"Technology","type":"tags"},{"content":"Last updated: Loading... The ESP32-C5-DevKitC-1-N8R4 development board is now available for purchase.\nThis page lists the projects in which the ESP32-C5 v1.0 is supported.\nTo show the status of features, the following icons are used:\n:white_check_mark: Supported feature :hourglass_flowing_sand: Unsupported feature (IDF-1234) \u0026quot;IDF-1234\u0026quot; indicates an internal issue reference to help us keep this list up to date :question: Support status unknown Such status issues will be checked and fixed shortly This page will be periodically updated to reflect the current support status for the ESP32-C5 v1.0.\nSome links provided below might appear invalid due to being generated as placeholders for documents to be added later. ESP-IDF # Now the master branch contains the latest preview support for ESP32-C5 v1.0. Until a full support version is released, please update to the HEAD of master branch to develop with v1.0 chips.\nIf you would like to try features with the early samples of the ESP32-C5 v0.1, please refer to the ESP32-C5 v0.1 support status page.\nIf you have an issue to report about any of the ESP32-C5 features, please create an issue in the ESP-IDF GitHub issue tracker.\nLoading... Other Projects # If you have an issue to report about any of the ESP32-C5 features, please create an issue in the issue tracker of a respective project.\nLoading... ","date":"24 April 2025","externalUrl":null,"permalink":"/hardware/esp32c5/","section":"Hardware","summary":"","title":"ESP32-C5 v1.0 status","type":"hardware"},{"content":"FOURCC (Four Character Code) is a widely used identifier in the multimedia domain, typically employed for the rapid identification of audio and video codecs, container formats, pixel formats, and more. Espressif Systems defines a comprehensive FOURCC encoding standard, called ESP FOURCC, which is specified in the open-source project ESP-GMF, specifically in the esp_fourcc.h header file. This standard covers audio, video, image, container formats, and various pixel formats. This article provides an in-depth overview of the background, significance, definition principles, implementation methods, and advantages of ESP FOURCC.\nespressif/esp-gmf Espressif General Multimedia Framework (ESP-GMF) C 91 23 Background and Significance of FOURCC # The history of FOURCC can be traced back to the 1980s with the OSType mechanism in the Macintosh system, where four-character identifiers were used to represent file types. In the 1990s, QuickTime adopted this approach in the audio-video domain, which later became a core identification method in MP4 containers, FFmpeg, and other mainstream frameworks.\nIn embedded systems, where resources are constrained and memory and computational efficiency are crucial, using compact identifiers is essential. Defining unique enumeration values or constants for each module to represent data formats often leads to the following issues:\nLack of standardization: If different modules define their own format identifiers independently, the same data format may have different enumeration values across different modules, increasing interface adaptation complexity. High conversion overhead: When transferring data between modules, inconsistencies in format identifiers require additional conversion operations, leading to unnecessary runtime overhead. Difficult debugging: When different modules use different identification methods, it becomes challenging to intuitively confirm the actual data format during debugging, increasing the complexity of issue resolution. In contrast, the FOURCC mechanism resolves these issues by using a unified 32-bit identifier. This not only ensures consistency in data formats across modules but also allows for compile-time constant generation, facilitating quick comparisons and lookups, thereby significantly enhancing overall system performance and maintainability.\nFundamental Principles and Implementation of FOURCC # Core Mechanism of FOURCC # FOURCC is a compact encoding scheme based on ASCII characters. The core principle is to generate a 32-bit unsigned integer (uint32_t) from four consecutive characters. For example, the string \u0026quot;H264\u0026quot; corresponds to the hexadecimal value 0x48323634, where each character’s ASCII code is combined in sequence:\n'H' → 0x48 '2' → 0x32 '6' → 0x36 '4' → 0x34 Implementation of ESP FOURCC # In ESP-GMF, FOURCC definitions are primarily found in the esp_fourcc.h header file, which includes the following components:\nMacro Definition\nESP-GMF defines the macro ESP_FOURCC_TO_INT(a, b, c, d), allowing developers to generate FOURCC values at compile time. This macro converts four input characters into a 32-bit integer. For example:\n#define ESP_FOURCC_H264 ESP_FOURCC_TO_INT(\u0026#39;H\u0026#39;,\u0026#39;2\u0026#39;,\u0026#39;6\u0026#39;,\u0026#39;4\u0026#39;) // 0x48323634 Helper Functions\nThe esp_fourcc.h header provides a macro ESP_FOURCC_TO_STR(fourcc), which calls gmf_fourcc_to_str. This function converts a uint32_t FOURCC value into a string representation. For example:\nprintf(\u0026#34;Format: %s\\n\u0026#34;, ESP_FOURCC_TO_STR(0x48323634)); // \u0026#34;H264\u0026#34; FOURCC Definitions\nESP FOURCC v1.0.0 defines commonly used types in multimedia applications for embedded devices, including audio and video codecs, container formats, and pixel formats. For specific details, refer to esp_fourcc.h .\nMultimedia FOURCC Formats # The esp_fourcc.h file defines multimedia formats covering video and audio codecs, containers, and image codecs. Below is a list of commonly used formats:\nESP FOURCC Classification and Character Representation Table\nCategory ESP FOURCC Example Character Representation Encoding Standard/Technical Features Video Codecs ESP_FOURCC_H264 'H264' H.264/AVC (with start codes) ESP_FOURCC_AVC1 'AVC1' H.264 (without start codes, MP4 compatible) ESP_FOURCC_H265 'H265' HEVC/H.265 (high compression efficiency) Container Formats ESP_FOURCC_MP4 'MP4 ' MPEG-4 Part 14 (multi-track support) ESP_FOURCC_OGG 'OGG ' Ogg Container ESP_FOURCC_FLV 'FLV ' Flash Video (optimized for streaming) Image Codecs ESP_FOURCC_PNG 'PNG ' Lossless compression (supports transparency) ESP_FOURCC_JPEG 'JPEG' Lossy compression (high compression ratio) ESP_FOURCC_WEBP 'WEBP' Hybrid lossy/lossless compression (size optimized) Audio Codecs ESP_FOURCC_MP3 'MP3 ' MPEG Layer III (widely compatible) ESP_FOURCC_AAC 'AAC ' Advanced Audio Coding (efficient compression) ESP_FOURCC_OPUS 'OPUS' Low-latency dynamic bitrate (optimized for real-time communication) Pixel FOURCC Formats # esp_fourcc.h defines various FOURCC pixel formats, including RGB, YUV, grayscale, and special formats. Each format’s data storage method is also specified. The following table lists some commonly used formats:\nESP FOURCC Pixel Format Classification Table\nCategory ESP FOURCC Example Character Representation Technical Features RGB Formats ESP_FOURCC_RGB16 'RGB6' RGB-5-6-5 little-endian, 16-bit compression (low bandwidth) ESP_FOURCC_RGB24 'RGB3' RGB-8-8-8 packed, 24-bit true color YUV Formats ESP_FOURCC_NV12 'NV12' YUV 4:2:0 semi-planar (Y plane + interleaved UV) ESP_FOURCC_YUYV 'YUYV' YUV 4:2:2 packed (Y-U-Y-V interleaved) ESP_FOURCC_YUV420P 'I420' YUV 4:2:0 planar format (Y + U + V planes) Grayscale ESP_FOURCC_GREY 'GREY' 8-bit single-channel grayscale Special Formats ESP_FOURCC_RAW16 'RAW6' 16-bit raw data (little-endian storage) Practical Application Cases # In the ESP-GMF framework, various modules (such as video decoders, audio processors, and image filters) utilize FOURCC codes for capability declaration and interface matching. For example, a video decoder may declare its supported FOURCC formats for input and output. The upper-layer scheduler uses FOURCC codes to ensure correct data flow between modules. This mechanism enhances system robustness and facilitates the expansion of new functionalities.\nConclusion # ESP FOURCC provides a unified and efficient way to identify multimedia data formats across embedded systems, addressing common challenges such as inconsistent identifiers, high conversion overhead, and debugging complexity. By leveraging the compact and expressive FOURCC encoding method, the ESP-GMF framework ensures standardized communication between modules while optimizing for performance and maintainability.\nThrough clear macro definitions, helper utilities, and an extensible set of format codes, ESP FOURCC enables developers to build scalable and interoperable multimedia applications with ease. Whether working with audio, video, images, or pixel data, ESP FOURCC lays a solid foundation for future-proof, modular embedded multimedia development.\n","date":"24 April 2025","externalUrl":null,"permalink":"/blog/2025/04/esp-fourcc-introduction/","section":"Blog","summary":"This article explores ESP FOURCC standard based on FOURCC (Four Character Code), a standardized 32-bit identifier used in multimedia for format consistency, reducing conversion overhead and debugging complexity. It highlights Espressif implementation in ESP-GMF, where \u003ccode\u003eesp_fourcc.h\u003c/code\u003e defines FOURCC values for video, audio, container, image, and pixel formats, optimizing efficiency in embedded systems.","title":"Introduction to ESP FOURCC","type":"blog"},{"content":"","date":"24 April 2025","externalUrl":null,"permalink":"/authors/jason-mao/","section":"Developer Portal Authors","summary":"","title":"Jason Mao","type":"authors"},{"content":"","date":"23 April 2025","externalUrl":null,"permalink":"/authors/cai-guanhong/","section":"Developer Portal Authors","summary":"","title":"Cai Guanhong","type":"authors"},{"content":"","date":"23 April 2025","externalUrl":null,"permalink":"/tags/esp-now/","section":"Tags","summary":"","title":"ESP-NOW","type":"tags"},{"content":" This article provides an overview of the ESP-SparkBot, its features, and functionality.It also details the hardware design and outlines the software framework that supports its operation.\nIntroduction # With the booming development of generative artificial intelligence, large language models (LLMs) are becoming a core technology in the AI field. They are not only driving the realization of application scenarios such as AI programming, intelligent customer service, and smart office, but also enriching interactive experiences and service quality in areas such as smart homes, remote healthcare, online education, and personalized entertainment. However, these technologies typically rely on powerful cloud computing resources, and extending them to edge devices requires overcoming numerous challenges such as computing power, latency, and power consumption. Espressif Systems with its leading wireless SoC technology, provides a solution to this challenge and is committed to bringing the powerful capabilities of AI to a wider range of edge devices, making AI technology more accessible and serving people’s daily lives.\nIn this article, we introduce the ESP-Sparkbot AI Robot—a versatile solution designed to meet a range of needs. Whether you\u0026rsquo;re looking to create a smart home system, enhance your experience with a reliable voice assistant, or find an engaging AI toy for your children, the ESP-Sparkbot has you covered.\nOverview of ESP-SparkBot # ESP-SparkBot is a low-cost, multi-functional, AI large language model robot with ESP32-S3. It is an intelligent device integrating voice interaction, facial recognition, remote control, motion detection, and multimedia functions.\nIn home automation, ESP-SparkBot can be your personal assistant. In smart office scenarios, ESP-SparkBot act as your computer\u0026rsquo;s secondary screen. In outdoor entertainment settings, the ESP-SparkBot can seamlessly transform into a compact speaker and portable camera. In this video you can see the functions and application scenario of ESP-SparkBot.\nThe ESP-ESP-SparkBot can be powered in two ways:\nButton Battery (Default Power Supply): The ESP-SparkBot is equipped with a 2000mA lithium battery, supporting power supply via the lithium battery and charging of the lithium battery via its base.\nUSB Power Supply (via ESP32-S3 USB Interface): The ESP-SparkBot also features a USB Type-C port, enabling continuous power supply via USB, which simplifies program downloading and debugging. This added functionality expands usage scenarios and enhances overall convenience for users.\nKey Features and Capabilities # This section highlights the ESP-SparkBot\u0026rsquo;s key functionalities and the innovative features that make it a versatile AI Conversation Robot for smart device control and integration.\nSmart Voice Weather Assistant \u0026amp; Time Manager # The ESP-SparkBot serves as a smart voice assistant, offering real-time access to local data such as the current date, time, weather conditions, temperature fluctuations, and air quality via IP address. This makes the ESP-SparkBot not only your personal assistant but also an essential smart companion, delivering timely and valuable weather and time information whenever you need it.\nLarge Language model AI Chat Assistant Robot # The ESP-SparkBot utilizes the OpenAI platform and integrates the advanced ChatGPT model to support seamless online voice interaction. This transforms the ESP-SparkBot into not just a smart home assistant, but also an intelligent conversational partner, enabling users to engage in natural language communication and effortlessly retrieve information, thus enhancing both interactivity and convenience in the smart home experience.\nRelaxation Game # ESP-SparkBot is equipped with a touch button on top, allowing users tap a virtual zen drum and accumulate merit. With the ESP-NOW broadcast function, multiple ESP-SparkBots can be controlled simultaneously to tap the virtual zen drums, exponentially increasing the accumulated merit.\nVirtual 3D Die # The ESP-SparkBot also features a built-in accelerometer, enabling it to function as a virtual die. By randomly rotating or shaking ESP-SparkBot, the 3D die displayed on the screen will rotate according to the accelerometer data. Once the movement stops, the on-screen die will gradually come to a halt and display the final result.\n2048 Game # ESP-SparkBot comes integrated with the 2048 game. After entering the 2048 game interface, users can interact with the game through gesture recognition enabled by the built-in accelerometer. Tapping the touch button on top will reset the game.\nOffline speech recognition, face recognition and motion detection # In addition to online interactions with cloud-based large models, ESP-SparkBot also supports running various offline AI models locally, such as offline speech recognition, face recognition, and motion detection.\nSpeech Recognition By leveraging the ESP-SR library, ESP-SparkBot can perform local speech recognition with ease.\nFace recognition and motion detection The ESP-SparkBot features a foldable camera on top, enabling real-time facial detection and recognition. Users can easily add or remove faces through voice commands. With the ESP-WHO library, integrating additional vision AI models is simple, including capabilities such as cat face recognition, human face recognition, motion detection, and pedestrian detection.\nRemote Controlled Reconnaissance Robot # The ESP-SparkBot can function as a wireless, remote-controlled reconnaissance robot, responding to voice commands to control its movement direction and light displays. Additionally, users can issue voice commands to capture photos while the robot is in motion.\nBy connecting to the robot\u0026rsquo;s WebSocket server, users can achieve two-way interaction with mobile remote control and real-time video streaming. No dedicated app installation is required—users can simply access the remote control interface via a web browser, featuring a simulated joystick design for smooth and intuitive operation.\nUSB Screen Mirror # With just a single USB cable, the ESP-SparkBot transforms into a plug-and-play USB secondary display. It supports bi-directional audio transmission and touch control, enabling it to function as both a speaker and a microphone. In addition to providing smooth video streaming for TV shows, it offers an immersive experience for gaming, including esports and AAA titles.\nHardware Design # The hardware system of the ESP-SparkBot is composed as follows:\nESP-SparkBot Hardware Design\nDescription of Different Circuit Blocks # Main MCU: ESP32-S3-WROOM-1-N16R8 module，responsible for controlling the entire system. In includes both connectivity (Wi-Fi and Bluetooth) and peripherals (LCD, camera and audio).\nCamera: Uses a DVP interface camera, whose model is OV2640. It is used for capture images and transmit video streams.\nAudio: An audio module is used for both microphone input and speaker output. It transmits digital audio data via the I2S interface and drives the speaker to play audio signals through an audio amplifier circuit.\nLCD (Display): 1.54-inch with 240x240 pixel resolution. This LCD is equipped with the ST7789 controller.\nUSB Type-C (USB-C Interface): Supports USB Type-C connection for device power supply and data transmission. Support USB serial communication for debugging and flashing firmware.\nDC-DC Converter : Responsible for converting the input voltage to the stable voltage required by the ESP32-S3 and other modules.\nConnector Pins (External Connectors): Connection interfaces for external devices, facilitating interconnection with other modules or development boards. Can be used for expanding functionality and debugging.\nTouch (Touch Circuit): Touch sensing circuit for detecting user touch operations.\nMicrophone Module: Microphone signal biasing network.\nPower Switching Circuit: Responsible for switching between different power inputs (such as battery and USB). Ensures stable operation of the device under multiple power supply methods.\nLithium Battery Charging Circuit: Manages the charging process of the lithium battery, supporting battery overcharge protection and constant current/constant voltage charging. Provides a portable power solution for the device.\nIMU (BMI270) (Inertial Measurement Unit): Used for detect the acceleration and angular velocity. It realizes motion detection, attitude detection and gesture recognition functions.\nButton: Detects button input for user interaction, enabling function switching or mode selection.\nComplete open-source hardware resources are available at ESP-SparkBot. For more ESP hardware design instructions, please refer to the ESP Hardware Design Guidelines\nSoftware Design # The software code for the ESP-SparkBot AI robot is fully open-source and available at esp-friends/esp_sparkbot. This repository includes a series of sample projects designed to showcase the full capabilities of the ESP-SparkBot. For more details, see: ESP-SparkBot examples.\nConclusion # The ESP-SparkBot is a versatile AI-powered robot offering voice interaction, facial recognition, motion detection, and multimedia features for smart home, office, and entertainment use. With both its hardware and software being open-source, and welcoming contributions from the community, it makes advanced AI accessible and practical for everyday applications, enhancing both personal and professional experiences.\n","date":"23 April 2025","externalUrl":null,"permalink":"/blog/2025/04/esp32-s3-sparkbot/","section":"Blog","summary":"","title":"ESP-SparkBot：Large Language Model Robot with ESP32-S3","type":"blog"},{"content":"","date":"23 April 2025","externalUrl":null,"permalink":"/tags/face-recognition/","section":"Tags","summary":"","title":"Face Recognition","type":"tags"},{"content":"","date":"23 April 2025","externalUrl":null,"permalink":"/tags/motion-detection/","section":"Tags","summary":"","title":"Motion Detection","type":"tags"},{"content":"","date":"23 April 2025","externalUrl":null,"permalink":"/tags/offline-speech-recognition/","section":"Tags","summary":"","title":"Offline Speech Recognition","type":"tags"},{"content":"","date":"23 April 2025","externalUrl":null,"permalink":"/tags/usb-screen-mirror/","section":"Tags","summary":"","title":"USB Screen Mirror","type":"tags"},{"content":" Introduction # In any Wi-Fi-enabled application, the first step is always to establish a connection between the device and the router. In Wi-Fi terminology, the device is referred to as a Station (STA), while the router functions as an Access Point (AP). In most applications, the Espressif module operates as a station, connecting to an existing router. However, before it can do so, the end user must perform provisioning—providing the module with the router\u0026rsquo;s SSID and password.\nThere are multiple ways to handle provisioning, but the two most common methods are via Bluetooth and via Wi-Fi. When using Wi-Fi for provisioning, the process typically follows these steps:\nThe Espressif module starts a soft-AP (temporary access point). The user connects to this soft-AP. The module serves an HTTP page that prompts the user to enter the SSID and password. The user provides the necessary credentials. The module shuts down the soft-AP and switches to station mode, connecting to the router. Even if your application primarily runs the Espressif module in station mode, you\u0026rsquo;ll still might need to set up a soft-AP for provisioning.\nBecause provisioning is such a common requirement, this tutorial will be followed by another tutorial that explains how to set up an HTTP server to collect the SSID and password from the user.\nThis and the following tutorials use a simple provisioning technique, which is inherently less secure.\nFor real-world applications, it is better to use a robust provisioning solution, such as the Unified Provisioning framework. It allows configuring ESP devices with Wi-Fi credentials and custom settings using various transport methods (Wi-Fi SoftAP or Bluetooth LE) and security schemes.\nThis tutorial lays the groundwork for building more advanced Wi-Fi connectivity applications by ensuring a smooth and reliable connection setup.\nIn the steps that follow, we will:\nCreate a new project based on the hello_world example. Rename the project and remove any unnecessary libraries and configurations. Start the Soft-AP and set up handlers to manage Wi-Fi events. Verify the connection using your smartphone In this tutorial, we will also encounter\nmenuconfig - The tool which handles the configuration in ESP-IDF projects Event loops – A design pattern used throughout the Espressif ESP-IDF framework to simplify the management of complex applications. esp-netif – Espressif\u0026rsquo;s abstraction layer for TCP/IP networking. Non-volatile storage (NVS) – For saving credentials Prerequisites # Before starting this tutorial, ensure that you\nCan compile and flash the hello_world example. Two main methods followed below are using idf.py directly (CLI approach) or using the VS Code ESP-IDF Extension. If required, you can follow the instructions in the ESP-IDF Getting Started guide. Have an Espressif evaluation board or another compatible board for flashing the code. In this tutorial we will use the ESP32-C3-DevkitM-1 but any Espressif evaluation board will work just as well. If you built your own board, you might need an ESP-PROG programmer. Understand the difference between a Wi-Fi access point and a Wi-Fi station. (Optional) Have a basic knowledge of the logging system in Espressif. If you\u0026rsquo;re not quite comfortable with any of the above steps yet, consider checking out the ESP-IDF with ESP32-C6 Workshop. These resources can help you get hands-on experience with setup, flashing, and basic debugging before diving into this tutorial.\nStarting a new project from hello_world # To start a new project and prepare for the following steps, we will perform these actions:\nCreate a new project using the hello_world example as a starting point. Set the target core (in our case, ESP32-C3) Select right port (here /dev/tty.usbserial-11320) Build, flash, and start a monitor with hello_world. To start, create a new project from hello_world. Below you can find a refresher for VS Code and using the CLI.\nVS Code extension CLI Most commands in VSCode are executed through the Command Palette, which you can open by pressing CTRL+SHIFT+P (or CMD+SHIFT+P if you’re on mac-os). In the following, commands to enter in the Command Palette are marked with the symbol \u0026gt;.\n\u0026gt; ESP-IDF: New Project\nFollow the instructions to create a new project using the hello_world as a template \u0026gt; ESP-IDF: Set Espressif Device Target Choose your SoC. In this tutorial we use esp32c3 If you are using an evaluation board or a USB-UART bridge, select The ESP32-C3 Chip via builtin USB-JTAG If you\u0026rsquo;re using one of the ESP-PROG programmers, choose the most appropriate option. \u0026gt; ESP-IDF: Select Port to Use (COM, tty, usbserial) Choose the port assigned to the board. Check with your os device manager if unsure \u0026gt; ESP-IDF: Build, Flash and start a Monitor on your device If you\u0026rsquo;re using a simple text editor and the CLI commands, you can follow the instruction on the get-started guide (linux/mac-os | windows ).\nIf everything runs smoothly, we should see the compilation finish successfully, followed by the firmware flashing and the hello_world example running, displaying Hello world! and restarting after 10 seconds.\nWe have just compiled the code and flashed it onto the internal flash memory of the Espressif module. On boot, the module now runs the hello_world example, sending a \u0026lsquo;Hello, World\u0026rsquo; message to the serial port (connected to the programmer), along with a countdown until the module restarts. This step ensures that the entire process is working correctly. Now, we can begin modifying the code to implement the soft-AP.\nRenaming the Project and Cleaning Up # Now, we will rename the project and remove all the necessary commands and library. Update the content of hello_world_main.c to the following code:\n#include \u0026lt;stdio.h\u0026gt; #include \u0026#34;sdkconfig.h\u0026#34; void app_main(void) { printf(\u0026#34;Hello tutorial!\\n\u0026#34;); } Then build, flash, and monitor again to confirm that everything is working correctly. Before moving on, rename the file hello_world_main.c → basic_soft_ap.c for clarity. Update CMake to ensure it compiles the new file instead of the old one. Open main/CMakeLists.txt and change the content to\nidf_component_register(SRCS \u0026#34;basic_http_server.c\u0026#34; PRIV_REQUIRES INCLUDE_DIRS \u0026#34;\u0026#34;) After making these changes:\nPerform a full clean: Run in the command palette ESP-IDF: Full Clean Project Build, flash and open a monitor again. Every time you change the CMakeLists.txt, you need to perform a full clean to see the changes take effect. To learn more about the build system, consult the document Build System. Disable NVS # To keep things as simple as possible, in this tutorial we will not use Non-Volatile Storage (NVS), which is commonly used with Wi-Fi to store credentials and access calibration data under the hood.\nBy default, some configuration variables have NVS enabled, which may cause warnings or errors. To avoid this, we need to disable them in menuconfig.\nVS Code extension CLI To access menuconfig, type ESP-IDF: SDK Configuration Editor in the command palette and hit Enter.\nIn the menuconfig search bar type NVS then uncheck the following options\nNVS options to be disabled\nTo access menuconfig, call idf.py menuconfig\nNow your project should resemble the bare-minimum example in the repository below.\nFBEZ-docs-and-templates/devrel-tutorials-code This repo contains the full code for the developer portal tutorials C 0 1 Starting the soft-AP # To set up a soft-AP, we will need to:\nDefine soft-AP parameters:\nTo keep things easy, we will use some #defines for SSID, password and the other soft-AP parameters. Initialize the IP Stack:\nWe\u0026rsquo;ll call esp_netif_init() to initialize the network interface. Initialize the event loop:\nWe\u0026rsquo;ll call esp_event_loop_create_default() to initialize the standard event loop. Register handlers for soft-AP:\nWe\u0026rsquo;ll register the event handlers needed for a soft-AP application. Espressif IP stack is managed through the unified interface called esp_netif. This interface was designed to provide an agnostic abstraction for different IP stacks. Currently, the only TCP/IP stack available through this interface is lwIP.\nFor most applications, creating a default network with the default event loop is sufficient \u0026ndash; this is the approach used in this tutorial.\nFor a complete implementation with error handling you can refer here. Define soft-AP parameters # Best practices dictate that we should avoid hard-coding credentials directly in our code. Instead, credentials should be stored in the Non-Volatile Storage (NVS) partition. This approach is commonly used in the ESP-IDF examples and is the recommended way to manage credentials.\nFor the sake of simplicity in this tutorial, however, we will define the AP credentials directly in the code as simple defines.\nFirst, you need to define all the necessary values for initialization, including:\nSSID (Wi-Fi network name) Password Wi-Fi Channel Maximum number of connections This is done using the #define statements:\n#define ESP_WIFI_SSID \u0026#34;esp_tutorial\u0026#34; #define ESP_WIFI_PASS \u0026#34;test_esp\u0026#34; #define ESP_WIFI_CHANNEL 1 #define MAX_STA_CONN 2 This is not the recommended way to store credentials. Please store them securely in NVS or manage them through configuration settings using menuconfig. Initialize the IP stack # To initialize the IP stack, we just need to call the two functions\nesp_netif_init(); esp_netif_create_default_wifi_ap(); Initialize the event loop # Espressif\u0026rsquo;s Wi-Fi component relies on an event loop to handle asynchronous events. Therefore, we need to:\nStart the default event loop. Create and register an event handler function to process Wi-Fi events. For now, this function will simply print the event_id.\nTo keep things clean, we will create a function called wifi_init_softap where we will encapsulate all the steps listed above required to start the soft-AP.\nvoid wifi_init_softap() { esp_netif_init(); esp_event_loop_create_default(); esp_netif_create_default_wifi_ap(); wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT(); // always start with this esp_wifi_init(\u0026amp;cfg); esp_event_handler_instance_register(WIFI_EVENT, ESP_EVENT_ANY_ID, \u0026amp;wifi_event_handler, NULL, NULL); wifi_config_t wifi_config = { .ap = { .ssid = ESP_WIFI_SSID, .ssid_len = strlen(ESP_WIFI_SSID), .channel = ESP_WIFI_CHANNEL, .password = ESP_WIFI_PASS, .max_connection = MAX_STA_CONN, .authmode = WIFI_AUTH_WPA2_PSK, .pmf_cfg = { .required = true, }, }, }; esp_wifi_set_mode(WIFI_MODE_AP); esp_wifi_set_config(WIFI_IF_AP, \u0026amp;wifi_config); esp_wifi_start(); ESP_LOGI(TAG, \u0026#34;wifi_init_softap finished. SSID:%s password:%s channel:%d\u0026#34;, ESP_WIFI_SSID, ESP_WIFI_PASS, ESP_WIFI_CHANNEL); } ESP_LOGI is a logging command which prints an information message on the terminal. If you\u0026rsquo;re unsure about it, check the logging library documentation.\nHandle Wi-Fi Events # At this point, the function handling Wi-Fi events is as follows:\nstatic void wifi_event_handler(void* arg, esp_event_base_t event_base, int32_t event_id, void* event_data){ printf(\u0026#34;Event nr: %ld!\\n\u0026#34;, event_id); } Now compile, flash, start a monitor and run the project. We should start seeing several event numbers appearing on the terminal.\nTesting the Connection with a Smartphone # At this point, take your smartphone, open the Wi-Fi list, and select the SSID esp_tutorial. When we do so, we should see on the terminal Event nr: 14!.\nListing of APs\nIf we check on the esp-idf source code related to the event codes (here), we will find that 14 corresponds to WIFI_EVENT_AP_STACONNECTED.\nThis indicates that a station (STA) has connected to the soft-AP.\nWe can use the event_id to distinguish between different events and then process the additional data you available in event_data.\nThis allows us to handle specific Wi-Fi events appropriately, such as when a station connects or disconnects from the soft-AP.\nevent_data is a void pointer, you need to cast it to the proper structure if you want to extract data. Here you can find two examples. You can find the complete code at the link soft-ap tutorial code.\nConclusion # In this tutorial, you learned how to:\nCreate a new project based on the hello_world example. Initialize the esp_netif library. Start the standard event loop to handle Wi-Fi events. Configure and launch a soft-AP, allowing devices to connect via Wi-Fi. Verify event handling by monitoring the terminal for connection events. This serves as a foundation for building more advanced Wi-Fi applications, such as MQTT clients, HTTP servers, or other networked solutions.\nNext step # Next Step: Check the basic http tutorial\n","date":"18 April 2025","externalUrl":null,"permalink":"/blog/2025/04/soft-ap-tutorial/","section":"Blog","summary":"This tutorial guides you through setting up a soft-AP using an Espressif module and ESP-IDF. It covers the process of creating a project, configuring Wi-Fi, and handling connection events through event loops. Upon completion, you’ll be able to establish a soft-AP and manage Wi-Fi connections. It is the first step to building more advanced networking applications.","title":"ESP-IDF Tutorials: Soft-AP","type":"blog"},{"content":"","date":"18 April 2025","externalUrl":null,"permalink":"/tags/soft-ap/","section":"Tags","summary":"","title":"Soft-AP","type":"tags"},{"content":"","date":"14 April 2025","externalUrl":null,"permalink":"/tags/embedded-wizard/","section":"Tags","summary":"","title":"Embedded Wizard","type":"tags"},{"content":"","date":"14 April 2025","externalUrl":null,"permalink":"/authors/embedded-wizard-team/","section":"Developer Portal Authors","summary":"","title":"Embedded Wizard Team","type":"authors"},{"content":"","date":"14 April 2025","externalUrl":null,"permalink":"/tags/esp-idf/","section":"Tags","summary":"","title":"ESP-IDF\"","type":"tags"},{"content":"","date":"14 April 2025","externalUrl":null,"permalink":"/tags/gui/","section":"Tags","summary":"","title":"GUI","type":"tags"},{"content":"The following article explains all necessary steps to create an Embedded Wizard UI application suitable for the ESP32-P4-Function-EV-Board from Espressif.\nPlease follow these instructions carefully and step by step in order to ensure that you will get everything up and running on your target. In case you are not familiar with Embedded Wizard, please first read the chapter basic concepts and the Quick Tour tutorial to understand the principles of Embedded Wizard and the GUI development workflow.\nPrerequisites # Although you can combine the ESP32-P4-Function-EV-Board with some other display panels, we highly recommend to start first with the following hardware components in order to ensure that you get the entire software up and running. As soon as you have your first UI application working on the recommended environment, you can start porting to your desired display.\nFirst, make sure you have all of the following items:\nHardware components # ESP32-P4-Function-EV-Board from Espressif USB cable to connect the board with your PC Software components # Embedded Wizard Studio Free or Embedded Wizard Studio Pro If you want to use the Free edition of Embedded Wizard Studio please register on our website and download the software.\nAs a customer, please visit the Embedded Wizard Download Center (login/password required) and download Embedded Wizard Studio Pro.\nEmbedded Wizard Build Environment for ESP32-P4-Function-EV-Board To evaluate Embedded Wizard on the mentioned target, you can find and download the suitable Build Environment for Embedded Wizard’s latest version under the category “software components” from the following link: https://doc.embedded-wizard.de/getting-started-esp32-p4-function-ev-board\nAs a customer, please visit the Embedded Wizard Download Center (login/password required) and download the latest version of the Build Environment and your licensed Platform Package libraries or source codes.\nESP-IDF V5.3.1 (stable) for ESP32-P4 from Espressif Installing Tools and Software # The following description assumes that you are familiar with ESP32-P4 software development and that you have installed the ESP32 toolchain for Windows.\n** IMPORTANT! **\nBefore starting the GUI development with Embedded Wizard, please make sure to have the ESP32 software development environment (ESP-IDF) installed and first applications running on your ESP32-S3-BOX. Please follow the ESP32-P4 Get Started documentation from Espressif. Please also make sure that the ESP-IDF installation path (IDF_PATH) does not contain any space characters - otherwise building examples will fail.\nStep 1: Install the latest version of Embedded Wizard Studio. Step 2: Unpack the provided Embedded Wizard Build Environment for ESP32-P4-Function-EV-Board to your \\esp development directory (e.g. C:\\ESP32\\esp\\ESP32-P4-Function-EV-Board). Embedded Wizard GUI Demos # If you just want to run our GUI demos on your ESP32-P4-Function-EV-Board without building the different examples, you can simply flash the binary file of the Embedded Wizard Master Demo.\nThe Embedded Wizard Master Demo combines a variety of examples within one huge demo application. It can be used for presentations and showcases. Each demo application can be activated from a common main menu. To return back from a demo application to the main menu, a small home button appears on top of every demo. Additionally, the Master Demo contains an auto-demo mode that presents one demo application after the other. The auto-demo starts automatically and stops as soon as the user touches the screen.\nIn order to flash the binary file to your target, please follow these steps:\nConnect your development board with your PC via USB (make sure to use the USB-UART connector). Open a ESP-IDF PowerShell console (with all necessary settings for building an ESP-IDF project) and navigate to the directory of the Master Demo within the Build Environment \\esp\\ESP32-P4-Function-EV-Board\\main\\MasterDemo. Flash the MasterDemo by starting the following script: python FlashMasterDemo.py Master Demo running on ESP32-P4-Function-EV-Board.\nExploring the Build Environment # The provided Embedded Wizard Build Environment for ESP32-P4-Function-EV-Board contains everything you need to create an Embedded Wizard UI application for the ESP32-P4-Function-EV-Board. After unpacking, you will find the following subdirectories and files within \\esp\\ESP32-P4-Function-EV-Board\\main:\nApplication\\GeneratedCode - This folder is used to receive the generated code from an Embedded Wizard UI project. The template project is building the UI application out of this folder. You can create your own UI project and generate the code into the subdirectory GeneratedCode without the need to adapt the project.\nApplication\\\\Source - This folder contains the files main.c and ewmain.c. There you will find the initialization of the system and the main loop to drive an Embedded Wizard GUI application. The file ewconfig.h contains general configuration settings for the target system, like memory ranges and display parameter and configuration settings for the Embedded Wizard Graphics Engine and Runtime Environment. Additionally, this folder contains the device driver C/H files used for the DeviceIntegration example.\nExamples\\ScreenSize - This folder contains a set of demo applications prepared for a dedicated screen size (1024x600 pixel). Each example is stored in a separate folder containing the entire Embedded Wizard UI project. Every project contains the necessary profile settings for the ESP32 target. The following samples are provided:\nHelloWorld - A very simple project that is useful as starting point and to verify that the entire toolchain, your installation and your board is properly working. ColorFormats - This project demonstrates that every UI application can be generated for different color formats: RGB565, Index8 and LumA44. ScreenOrientation - - This demo shows, that the orientation of the UI application is independent of the physical orientation of the display. DeviceIntegration - This example shows the integration of devices into a UI application and addresses typical questions: How to start a certain action on the target? How to get data from a device? GraphicsAccelerator - This application demonstrates the graphics performance of the PPA hardware graphics accelerator. Sets of basic drawing operations are executed permanently and continuously. BezierClock - The sample application BezierClock implements a fancy digital clock and timer application with animated digits. The application uses vector graphics to render dynamically the different digits for clock and timer. The change from one digit to another is handled by moving the vector points to get a smooth transition animation. BrickGame - The sample application BrickGame implements a classic \u0026ldquo;paddle and ball\u0026rdquo; game. In the game, a couple of brick rows are arranged in the upper part of the screen. A ball travels across the screen, bouncing off the top and side walls of the screen. When a brick is hit, the ball bounces away and the brick is destroyed. The player has a movable paddle to bounce the ball upward, keeping it in play. PatientMonitor - This application displays continuously measured data in an overwriting data recorder (such as an oscilloscope). The data graphs of the (simulated) measured values and the dialogs for user settings are presented in a modern, clean medical style. Dialogs are using blur filters to show the content behind them with a glass effect. PulseOximeter - The sample application PulseOximeter shows the implementation of a medical device for monitoring a person\u0026rsquo;s pulse frequency and peripheral oxygen saturation. The application demonstrates the usage of vector graphics within graphs and circular gauges. SmartThermostat - The SmartThermostat demo application shows the implementation of a fancy, rotatable temperature controller to adjust and display the nominal and actual temperature. WashingMachine - This demo shows the implementation of a washing machine with a couple of fancy scrollable list widgets to choose the washing program and parameters. The speciality of this sample application is the magnification effect of the centered list items and the soft fade-in/fade-out effects. WaveformGenerator - This WaveformGenerator demo application combines waveforms with different amplitudes and frequencies. The implementation shows the usage of vector graphics to draw a curve based on a list of coordinates. MasterDemo - This folder contains the binary file of the Embedded Wizard Master Demo application and a script file to flash the demo on your target. The Master Demo combines a variety of examples within one huge demo application. It can be used for presentations and showcases. PlatformPackage - This folder contains the necessary source codes and/or libraries of the ESP32 Platform Package: Several Graphics Engines for the supported color format RGB565 and the Runtime Environment (in the subdirectory \\RTE).\nTargetSpecific - This folder contains all configuration files and platform specific source codes. The different ew_bsp_xxx files implement the bridge between the Embedded Wizard UI application and the underlying board support package (ESP hardware drivers) in order to access the display.\nCreating the UI Examples # For the first bring up of your system, we recommend to use the example HelloWorld:\nPicture: Example \u0026lsquo;HelloWorld\u0026rsquo; within Embedded Wizard Studio.\nThe following steps are necessary to generate the source code of this sample application:\nNavigate to the directory \\main\\Examples\\\u0026lt;ScreenSize\u0026gt;\\HelloWorld.\nOpen the project file HelloWorld.ewp with your previously installed Embedded Wizard Studio. The entire project is well documented inline. You can run the UI application within the Prototyper by pressing Ctrl+F5.\nTo start the code generator, select the menu items Build➤Build this profile - or simply press F8. Embedded Wizard Studio generates now the sources files of the example project into the directory \\main\\Application\\GeneratedCode.\nCompiling, Linking and Flashing # The following steps are necessary to build and flash the Embedded Wizard UI sample application using the ESP-IDF toolchain:\nOpen a console (with all necessary settings for building an ESP-IDF project) and navigate to the top level of the Build Environment \\esp\\ESP32-P4-Function-EV-Board.\nIf you want to change or inspect the current settings, please insert:\nidf.py menuconfig Start compiling and linking: idf.py build Now you can flash the application: idf.py flash In order to get outputs from the application and to provide key inputs, start the monitor: idf.py monitor If everything works as expected, the application should be built and flashed to the ESP32-P4-Function-EV-Board.\nPicture: Example \u0026lsquo;HelloWorld\u0026rsquo; running on ESP32-P4.\nAll other examples can be created in the same way: Just open the desired example with Embedded Wizard Studio, generate code and rebuild the whole application using simply:\nidf.py build idf.py flash idf.py monitor Alternatively you can abbreviate it as one command:\nidf.py build flash monitor If you update just application code, you can speed up the flashing part by flashing only the application binary:\nidf.py app-flash monitor Creating your own UI Applications # In order to create your own UI project suitable for the ESP32-P4-Function-EV-Board, you can create a new project and select the ESP32-P4-Function-EV-Board project template:\nPicture: Create new Embedded Wizard Project.\nAs a result you get a new Embedded Wizard project, that contains the necessary Profile attributes suitable for the ESP32-P4-Function-EV-Board:\nPicture: Embedded Wizard Configuration.\nThe following profile settings are important for your target: ★The attribute PlatformPackage should refer to the ESP32 Platform Package. The supported color formats are RGB565, Index8 and LumA44.\nThe attribute PlatformPackage should refer to the ESP32 Platform Package. The supported color format is RGB565.\nThe attribute ScreenSize should correspond to the display size of the ESP32-P4-Function-EV-Board.\nThe attributes ModeOfBitmapResources and ModeOfStringConstants should be set to DirectAccess. This ensures that resources are taken directly from flash memory.\nThe attribute OutputDirectory should refer to the \\main\\Application\\GeneratedCode directory within your Build Environment. By using this template, it will be very easy to build the UI project for your target.\nThe attribute CleanOutputDirectories should be set to true to ensure that unused source code within the output directory \\main\\Application\\GeneratedCode will be deleted.\nNow you can use the template project in the same manner as it was used for the provided examples to compile, link and flash the binary.\nAfter generating code, please follow these steps, in order to build your own UI application:\nStart compiling, linking and flashing: idf.py build idf.py flash idf.py monitor Most of the project settings are taken directly out of the generated code, like the color format or the screen orientation. All other settings can be made directly within the file ewconfig.h, which contains general configuration settings for the target system.\nConsole output # In order to receive error messages or to display simple debug or trace messages from your Embedded Wizard UI application, a serial terminal like \u0026lsquo;Putty\u0026rsquo; or \u0026lsquo;TeraTerm\u0026rsquo; should be used or the monitor that is started together with idf.py monitor\nPicture: Console output.\nThis terminal connection can be used for all trace statements from your Embedded Wizard UI applications or for all debug messages from your C code.\nYou can find all release notes and the version history of the Build Environment (including Graphics Engine and Runtime Environment) for the ESP32-S3-BOX at the bottom of this page. These release notes describe only the platform specific aspects - for all general improvements and enhancements please see the Embedded Wizard release notes.\n","date":"14 April 2025","externalUrl":null,"permalink":"/blog/2025/04/how-to-easily-develop-ui-applications-for-the-esp32-p4/","section":"Blog","summary":"","title":"How to Create an UI Application for the ESP32-P4","type":"blog"},{"content":"","date":"9 April 2025","externalUrl":null,"permalink":"/tags/bevy/","section":"Tags","summary":"","title":"Bevy","type":"tags"},{"content":" Introduction # Embedded development in Rust is rapidly evolving, and one of exciting new developments is the introduction of no_std support into the Bevy Entity Component System (ECS). This improvement allows developers to leverage the powerful and modular design of Bevy ECS on resource‑constrained devices like the ESP32.\nIn this article, we demonstrate how to build an embedded application using Rust no_std and Bevy ECS on an ESP32 device, using a simulation of Conway’s Game of Life and ESP32 Spooky Maze Game as our examples.\nAlthough Conway’s Game of Life is a classic cellular automaton, our primary focus is on structuring embedded applications using Bevy ECS principles.\nThis approach helps organize code into clean, modular systems, ideal for interactive and data-intensive applications.\nThe second example, the Spooky Maze Game, is more complex, demonstrating an event-based approach to integrate peripherals like accelerometers with application logic.\nWhat is Bevy ECS? # Bevy ECS is the core data‑oriented architecture of the Bevy game engine. It provides a way to structure programs by breaking them into:\nEntities which represent objects Components which hold data Systems which operate on entities with specific components With the introduction of no_std support, Bevy ECS can now be used in bare‑metal environments where the standard library is not available—making it a compelling choice for embedded Rust development for ESP32.\nAdvantages for Embedded Rust Developers # Many advantages of Rust for embedded development were described in the article Rust + Embedded: A Development Power Duo.\nHere are some specific advantages of using ECS in Rust applications:\nModularity and Maintainability: ECS encourages the separation of data and behavior into independent systems, which leads to clearer, easier-to-maintain code. Efficient Resource Management: The data‑oriented design can lead to better cache utilization and efficient processing, critical for devices with limited memory and processing power. Scalability: Even on microcontrollers, ECS allows you to extend your application with additional features or behaviors without significant restructuring. Familiarity: Developers experienced with ECS on desktop or game development can leverage similar patterns on embedded platforms. Hardware and Software Setup # Hardware Requirements # ESP32 Development Board: ESP32-S3, ESP32-C3, or similar variants. Display Module: For example, an ILI9486-based display connected via SPI. If you\u0026rsquo;re uncertain which hardware to choose, we recommend the ESP32-S3-BOX-3 featuring ESP32-S3 with PSRAM and a display with touch control.\nSoftware Requirements # Rust Toolchain Use upstream Rust toolchain (version 1.85.0.0 or later) for RISC-V targets (ESP32-C, ESP32-P, ESP32-H) or installation via espup for Xtensa targets (ESP32, ESP32-S). cargo install espup espup install # For ESP32, ESP32-S espflash: Rust implementation of flashing tool for ESP32. cargo install espflash Note: The Rust tooling could be also installed by cargo binstall.\nCrates Used in the Project # ESP‑HAL and mipidsi: These crates provide the hardware abstraction and display support for ESP32 devices. Bevy ECS (no_std) The latest no_std support in Bevy ECS lets you use its powerful ECS model on bare‑metal targets. Building the Application # The Conway’s Game of Life example manages a simulation grid as an ECS resource. Systems update the game state and render to an off-screen framebuffer, which is then output to a physical display. A WASM version also simulates the display using an HTML canvas in a web browser.\nFlashing the binary onto your hardware is done using espflash or probe-rs configured in .config/cargo.toml.\nRunning Applications - Conway\u0026rsquo;s Game of Life # Source code ESP32-S3-BOX-3 - Conway # cd esp32-s3-box-3 cargo run --release ESP32-C3 - Conway # Use the upstream Rust toolchain with the RISC‑V target:\ncd esp32-c3-lcdkit cargo run --release ESP32 Spooky Maze Game # In this small application, a player navigates a maze collecting coins while using special power‑ups to overcome obstacles. When collisions occur (with coins, NPCs, etc.), events are dispatched so that game logic remains decoupled from hardware‑specific input.\nSource code ESP32-S3-BOX-3 - Spooky # cd spooky-maze-esp32-s3-box-3 cargo run --release Desktop - Spooky # cd spooky-maze-desktop cargo run Structure of main.rs # Bevy has support for Builder pattern which greatly simplifies the way how the application needs to be structured and allows easy connection between different systems.\nHere\u0026rsquo;s sample code:\nlet mut app = App::new(); app.add_plugins((DefaultPlugins,)) .insert_non_send_resource(DisplayResource { display }) .insert_non_send_resource(AccelerometerResource { sensor: icm_sensor }) .insert_resource(FrameBufferResource::new()) .add_systems(Startup, systems::setup::setup) .add_event::\u0026lt;PlayerInputEvent\u0026gt;() .add_event::\u0026lt;CoinCollisionEvent\u0026gt;() .add_event::\u0026lt;NpcCollisionEvent\u0026gt;() .add_systems( Update, ( player_input::dispatch_accelerometer_input::\u0026lt;MyI2c, MyI2cError\u0026gt;, systems::process_player_input::process_player_input, collisions::npc::detect_npc_collision, collisions::npc::handle_npc_collision, systems::npc_logic::update_npc_movement, systems::game_logic::update_game, embedded_systems::render::render_system, ), ) .run(); Architecture of the Application # Shared ECS Core # The app’s core is implemented in the spooky-core crate using Bevy ECS. This core contains all app logic (maze generation, collision detection, event handling, etc.) and is compiled with no_std for embedded targets and with std for desktop.\nBecause Bevy’s built‑in rendering and UI systems aren’t available in no_std mode, we implemented a custom renderer using the Embedded Graphics crate. This renderer draws the maze, sprites, and HUD elements to an off‑screen framebuffer, then flushes the output to the physical display. In addition, a sprite filtering layer (implemented via a custom SpriteBuf wrapper) discards “magic pink” pixels that denote transparency in our sprite assets.\nCustom Renderer for Embedded # On embedded devices, the demo uses a custom renderer that:\nDraws the maze background and sprites to an off‑screen framebuffer.\nApplies a filtering layer to skip “magic pink” pixels (which represent transparency). This technique is known from DOS games.\nFlushes the framebuffer to the physical display via SPI using the mipidsi crate.\nEvent‑Based Collision and Input # All input (keyboard or accelerometer) is dispatched as events into the ECS. Separate systems process these events to update game state (for example, moving the player or handling collisions with coins, NPCs, etc.). This design makes it easier to add new types of interactions without tightly coupling the game logic with the underlying hardware.\nResource Injection # Resources such as the maze, player position, HUD state and hardware peripherals like the ICM42670 accelerometer are injected as Bevy resources (using NonSend for non‑Sync hardware drivers). This allows our ECS systems to access sensor data seamlessly without directly coupling to hardware APIs.\nConclusion # The integration of no_std support into Bevy ECS opens up exciting new possibilities for embedded development in Rust. By leveraging modern ECS design patterns on devices like the ESP32, developers can create modular, efficient, and scalable applications—even in resource‑constrained environments. Whether you’re a seasoned embedded developer or a game developer exploring new hardware, this approach demonstrates that you can build powerful applications with Rust and Bevy ECS on ESP32 devices.\nRecommended IDE for Development # Rust Rover or CLion with Rust Rover plugin are great tools for Rust Embedded Development.\nAnother great option is VS Code with Rust plugins.\nAll IDEs mentioned above support simulation of ESP32 using Wokwi simulator.\nContributing # Contributions are welcome! If you’d like to help improve the demo, add new features, or extend hardware support, please submit a pull request. We especially encourage contributions that further refine the embedded no_std integration or improve the custom rendering pipeline.\n","date":"9 April 2025","externalUrl":null,"permalink":"/blog/2025/04/bevy-ecs-on-esp32-with-rust-no-std/","section":"Blog","summary":"","title":"Bevy Entity Component System on ESP32 with Rust no_std","type":"blog"},{"content":"","date":"9 April 2025","externalUrl":null,"permalink":"/tags/ecs/","section":"Tags","summary":"","title":"ECS","type":"tags"},{"content":"","date":"9 April 2025","externalUrl":null,"permalink":"/tags/embedded-systems/","section":"Tags","summary":"","title":"Embedded Systems","type":"tags"},{"content":"","date":"9 April 2025","externalUrl":null,"permalink":"/tags/no_std/","section":"Tags","summary":"","title":"No_std","type":"tags"},{"content":"","date":"9 April 2025","externalUrl":null,"permalink":"/tags/wasm/","section":"Tags","summary":"","title":"WASM","type":"tags"},{"content":" Introduction # The European Union’s Radio Equipment Directive (RED) 2014/53/EU ensures that all radio equipment placed on the EU market meets essential requirements for safety, health, electromagnetic compatibility, and efficient spectrum use. As part of its ongoing evolution, the directive now includes the Delegated Act (DA) on Cybersecurity (EN 18031), which introduces new cybersecurity requirements for radio equipment.\nFor manufacturers, system integrators, and developers — whether they have an extensive security background or not — understanding and implementing these requirements is crucial to ensuring continued market access. This article provides a structured approach to help companies assess their compliance position and identify the necessary steps for certification.\nWhat is RED DA? # The RED Delegated Act (DA) on Cybersecurity (EN 18031) is an extension of the EU’s Radio Equipment Directive (RED) 2014/53/EU. It introduces mandatory cybersecurity requirements for wirelessly connected products sold in the EU market. Product manufacturers who were previously RED-compliant must now reassess their products to meet RED DA requirements by August 1, 2025.\nRED DA Cybersecurity Requirements # Three main cybersecurity requirements were added as part of the RED DA under Article 3(3):\nArticle 3(3)(d): Protection of network connections. This entails implementing secure network connections, robust authentication mechanisms, and protection against unauthorized access. Article 3(3)(e): Protection of personal data and user privacy. This entails proper data encryption, secure data storage, and user consent mechanisms to safeguard personal data and privacy. Article 3(3)(f): Protection against financial fraud. This involves preventing fraud via secure payment interfaces and transaction verification mechanisms. EN 18031 as Harmonised Standards # To assist end-product manufacturers in meeting regulatory expectations, harmonized standards have been developed to translate legal requirements into actionable technical guidance. These standards provide technical details and solutions to meet the regulations. When manufacturers comply with these standards, they benefit from a \u0026ldquo;presumption of conformity,\u0026rdquo; meaning authorities automatically recognize compliance.\nOn January 28, 2025, the European Commission published references to the three harmonized EN 18031 standards, with restrictions, in the Official Journal of the European Union (OJEU).\nEach EN 18031 standard directly corresponds to its matching RED DA Article:\nEN 18031-1:2024: Covers security requirements for internet-connected radio equipment. EN 18031-2:2024: Covers requirements for equipment that processes personal data. EN 18031-3:2024: Covers requirements for equipment that enables financial transactions. What Does This Mean for Product Manufacturers? # If you are a manufacturer selling wireless-enabled products in the EU, you must ensure RED DA compliance. This applies to:\nNew product launches after August 1, 2025. Existing products that undergo significant updates affecting security. End-product manufacturers using pre-certified wireless modules still need to ensure full system compliance. RED DA obligations depend on a product\u0026rsquo;s status at the time the rules take effect:\nAny product not placed on the EU market by August 1, 2025, must comply with the RED DA. Products already shipped to distributors or available for purchase before August 1, 2025 are considered placed on the market and are not subject to RED DA retroactively. However, if a product receives security-relevant updates after August 1, 2025, it may be considered a new product and require reassessment under RED DA. Does EN 18031 Certification Apply to Modules or End Products? # EN 18031 certification applies to complete internet-connected radio equipment, not individual modules. While modules like those from Espressif serve as essential building blocks of end products, they can be independently certified, but such certification alone is not sufficient to demonstrate RED DA compliance for the final product.\nThe responsibility for RED DA compliance lies with the manufacturer of the final product. Even when a secure, pre-certified module is used, the overall end product must be evaluated as a whole to verify it meets the EN 18031 requirements.\nIn short, using a secure module supports compliance but does not replace the need for end-product certification.\nRED DA Compliance Process # Manufacturers have two paths to comply with RED DA cybersecurity requirements:\nSelf-Assessment Process # Self-assessment allows manufacturers to evaluate compliance by themselves. This approach has several benefits:\nIt is cost-effective, with no third-party fees. It saves time by avoiding external review processes. It gives manufacturers more control over the compliance process. To use self-assessment, manufacturers must:\nEnsure their products fully meet all applicable EN 18031 requirements. Create thorough technical documentation that demonstrates how each EN 18031 requirement is met. Generate a self-signed Declaration of Conformity. No further action is required, and documentation must be kept ready for inspection by market surveillance authorities if requested. Notified Body Assessment Process # The other option is to work with Notified Bodies to assess your compliance. Notified Bodies are independent organizations authorized by EU member states to evaluate whether products meet the requirements. This option becomes mandatory if a product follows the EN 18031 standards but makes exceptions for certain requirements. Scenarios that require Notified Body involvement include:\nIf a product requires a password for access, sections 6.2.5.1 and 6.2.5.2 of EN 18031-1/2/3 specify how passwords should be managed. However, if users can choose not to set a password, the product does not comply with RED DA, even if it follows the harmonized standard.\nStandard EN 18031-2 (sections 6.1.3 to 6.1.6) outlines four access control mechanisms for toys and childcare products. Some of these methods may not be compatible with parental or guardian controls. In such cases, adherence to the EN 18031 harmonized standard alone does not ensure compliance with RED DA.\nStandard EN 18031-3 (section 6.3.2.4) describes secure update mechanisms. It defines four implementation categories: digital signatures, secure communication, access control, and others. None of these methods alone is sufficient for handling financial assets. The criteria do not fully address authentication risks and therefore cannot ensure compliance with RED DA.\nThe Notified Body will:\nReview technical documentation. Evaluate the product against RED DA requirements. Conduct additional tests, if needed, to verify compliance. Issue a formal compliance certificate if all requirements are met. Documentation Requirements # To comply with RED DA regulations, manufacturers must prepare and maintain the following documents:\nTechnical Specifications: Details about the product design and features. Product Risk Assessment: List of identified risks and mitigation plans. Applicable EN 18031 Standards: List of standards applied to the product. Declaration of Conformity: Official statement of compliance. For self-assessment:\nThe end-product manufacturer self-signs Declaration of Conformity. For Notified Body assessment:\nThe end-product manufacturer prepares technical documentation. The Notified Body issues a Declaration of Conformity. End-product Manufacturer Responsibilities # End-product manufacturers are expected to follow these key requirements:\nPrepare all compliance documentation before placing products on the market. Keep documentation available for 10 years after the product is introduced to the market. Ensure the manufacturing process continues to maintain compliance. Affix the CE marking to compliant products. Market surveillance authorities may request compliance documentation at any time, even after a product is on the market. Manufacturers must provide these documents promptly upon request. Failure to comply with RED DA requirements can result in re-certification through a Notified Body, penalties, or even product recalls in certain cases.\nEspressif Module Compliance # Espressif’s SoCs have all the necessary hardware security capabilities to support compliance with RED DA requirements.\nWe provide a detailed Security Guide to help manufacturers implement security features in their products. The official firmware, with all recommended platform security features enabled, meets the cybersecurity requirements of RED DA. However, some requirements depend on the design of the final product built on Espressif SoCs.\nThe table below outlines the EN 18031 cybersecurity requirement categories and how they are addressed by the EN 18031 standards and Espressif’s platform:\nRED DA Compliance Mapping Table # ID¹ Requirement EN 18031-1 EN 18031-2 EN 18031-3 ESP Support² ACM Access Control – Ensures that security assets are accessible only to authorized users. Y Y Y :white_check_mark: AUM Authentication – Device shall authenticate users or external entities before granting access to security assets. Y Y Y :white_check_mark: SUM Secure Update – Device shall perform secure and verified update of firmware and software. Y Y Y :white_check_mark: SSM Secure Storage – Device shall securely store security assets and protect them from unauthorized access. Y Y Y :white_check_mark: SCM Secure Communication – Device shall use secure communication for communicating security and network assets with other entities via network interfaces. Y Y Y :white_check_mark: CCK Confidential Cryptographic – Device shall protect confidentiality of cryptographic material and operations. Y Y Y :white_check_mark: GEC General Equipment Capabilities – Device shall support hardware or software capabilities for security requirements. Y Y Y :white_check_mark: CRY Cryptography – Device shall implement best practice cryptographic algorithms to protect security assets and communication. Y Y Y :white_check_mark: DLM Deletion – Device shall provide the option to delete security assets and user personal data in a secure and irreversible manner. - Y - :white_check_mark: LGM Logging – Device shall record logs of security events for monitoring and audit purposes. - Y Y P RLM Resilience – Device shall maintain secure behavior during faults, attacks, or disruptions. Y - - P NMM Network Monitoring – Device shall monitor network interfaces to detect and respond to security events. Y - - P TCM Traffic Control – Device shall control and filter network traffic to protect security assets. Y - - P UNM User Notification – Device shall notify users about security events or changes in security posture. - Y - P ¹ ID denotes the cybersecurity requirement categories as defined in the EN 18031 standard.\n² \u0026lsquo;P\u0026rsquo; in this column indicates that the applicability of the requirement depends on the final end product design.\nFrequently Asked Questions (FAQs) # Q1: Does EN 18031 apply to Espressif connectivity modules or end products?\nA: Although Espressif connectivity modules are themselves components, the end-product manufacturer holds the final responsibility for compliance. If an Espressif module is used in a product with its default firmware and security settings, the final product may still require separate certification to confirm compliance.\nQ2: What if the product developer has no security background?\nA: Developers with no cybersecurity background should consider working with external security consultants or labs and leveraging Espressif’s guidance to meet the requirements.\nQ3: Does RED DA compliance require third-party certification?\nA: Not necessarily. In many cases, self-assessment is sufficient, but certain exceptions do require certification by a Notified Body, which means involving third-party labs.\nQ4: What happens if self-assessment documents are inadequate?\nA: If self-assessment documentation is found to be inadequate, regulatory authorities may request additional proof or corrections. This situation could result in penalties in cases of non-conformance\nQ5: Who can request compliance documentation?\nA: Market surveillance authorities, regulatory bodies, or even distributors may request to review these documents.\nQ6: In a two-chip architecture (host MCU + separate Wi-Fi/Bluetooth module), who is responsible for RED DA compliance?\nA: In a two-chip design, the end-product manufacturer is ultimately responsible for ensuring the entire system complies with RED DA. Even if the wireless connectivity module (e.g., an ESP32-based module) has its own security features or certifications, the final combined device (host MCU + module) must, as a whole, meet EN 18031 requirements. If the host MCU manages security credentials and controls the wireless connectivity module, its role must be evaluated as part of the overall RED DA compliance of the end product to ensure the entire system meets security requirements.\nQ7: What if Espressif manages the entire firmware and security configuration (e.g., ESP-Zerocode)?\nA: In such cases, where Espressif provides the complete firmware and security configuration, Espressif assumes the responsibility for RED DA compliance of the module. The end-product manufacturer must still ensure that no changes compromise the end product certified configuration.\nSummary # RED DA (EN 18031) compliance presents both challenges and opportunities for IoT manufacturers. By leveraging Espressif\u0026rsquo;s secure Wi-Fi modules and expertise, product developers can achieve compliance faster and more cost-effectively. Espressif is fully committed to supporting manufacturers in achieving RED DA compliance. We can help with:\nTechnical guidance on security implementation Pre-filled compliance documentation templates from the platform perspective For assistance, please reach out to us at sales@espressif.com.\nStay informed and ensure your devices meet the latest regulatory standards to avoid market disruptions. Plan ahead for RED DA compliance!\n","date":"8 April 2025","externalUrl":null,"permalink":"/blog/2025/04/esp32-red-da-en18031-compliance-guide/","section":"Blog","summary":"This guide helps manufacturers of wireless-enabled products based on Espressif modules understand the RED DA (EN 18031) cybersecurity requirements, identify their product’s category, and determine the right path to certification before launching in the EU market.","title":"RED DA (EN 18031) Certification Compliance: What You Need to Know","type":"blog"},{"content":"Imagine this scenario: you have finished programming your application, designed your PCB with a battery circuit, and you are finally ready to set it free by disconnecting the umbilical cord \u0026mdash; the USB cable. But to your great disappointment, you find too soon that your small LiPo battery drains in a matter of hours.\nIf you plan to run your application on a battery, it is of utmost importance to know how to design your hardware and software so that the application does not gobble up the power like a vacuum cleaner. Even something as simple as polling a GPIO can have a drastic impact on power consumption. Doing it the easiest way vs. using the chip\u0026rsquo;s low-power features can result in an average difference of 22 mA vs. 22 µA. In other words, with your 350 mAh LiPo battery, it is the difference between it lasting 16 hours vs. 2 years.\nIn this article, we\u0026rsquo;ll introduce one of the features that Espressif chips provide to achieve low-power consumption: the Ultra-Low-Power coprocessor (ULP), a processor separate from the main CPU. In a nutshell, if we run parts of our application on the ULP while the rest of the system sleeps, we can achieve much lower power consumption.\nThis article will focus on the latest iteration of the ULP \u0026mdash; the LP-Core \u0026mdash; available on the ESP32-C6 and a range of other new chips. For building the application, we will use ESP-IDF v5.4.\nLow-power on Espressif chips # Reducing power consumption of an application running on a microcontroller is mainly achieved through two general methods:\nClock gating and/or power gating parts of the chip, effectively turning off parts of the chip that you don\u0026rsquo;t need. Frequency scaling, reducing the clock frequency of the chip to lower power consumption. All Espressif chips support both methods but with varying degrees of flexibility. Newer chips, such as the ESP32-C6, have an even more powerful Power Management Unit (PMU), allowing for much finer control over which parts of the chip can be clock-gated or powered down.\nIn ESP-IDF, these two power-saving methods are exposed to users through sleep modes and power management:\nSleep modes: Allows for powering down parts of the chip, mainly through two different modes: Deep Sleep: Everything except a few low-power peripherals (e.g., the LP timer responsible for waking up the chip) is powered down and the state is lost. After waking up, the chip will boot up and configure the system again, similar to a power-on reset. Light Sleep: Most peripherals are powered down, but memory remains powered on, allowing the system to keep its state and continue executing from where it left off. Power Management: A high-level power management interface for the main high-performance CPU that can handle both automatic frequency scaling and entering light sleep when the chip is idle. What the ULP brings to the table in a low-power context is the ability to run even while the system is in deep sleep. This allows us to execute code and perform simple operations while keeping most of the system powered down.\nULP # The ULP is a coprocessor that operates independently from the main CPU. Its main advantage is that it is powered and clocked by a power domain controlled seperately from the rest of the system. This allows it to continue operating even while the rest of the system is in deep sleep. For more information about power domains on the ESP32-C6, see the ESP32-C6 TRM → Low-Power Management.\nThis enables us to offload certain tasks to the ULP, such as sensor readings, while waking up the main CPU only when it is necessary for some more complex task.\nImagine this scenario: you\u0026rsquo;re designing a smart plant-watering IoT device that measures soil humidity and waters the plant when needed. For a simple task like this, you could use the ULP to further reduce power consumption. While the rest of the system is powered down and sleeping, the ULP can periodically wake up, take measurements, as well as trigger watering action if necessary. Only when it is strictly necessary will the ULP wake up the main CPU and the rest of the system to perform actions that it cannot do \u0026mdash; for example, to update the cloud with the latest device status over Wi-Fi.\nTo summarize what the ULP is suitable for:\n:white_check_mark: Save power by performing simple tasks while the rest of the system sleeps :x: Help you achieve lower power-consumption during Wi-Fi or Bluetooth connections :white_check_mark: Assist main CPU by offloading simpler tasks Three generations of ULP coprocessor # As Espressif chips have evolved, so has the ULP. This article mainly focuses on the latest iteration of the ULP at the time of writing \u0026mdash; the ESP32-C6\u0026rsquo;s LP-Core. Some of the older chips had previous iterations. All in all, the ULP iterations are as follows:\nULP-FSM (ESP32, ESP32-S2, ESP32-S3) \u0026ndash; a simple state machine Programmed using an assembly-like language Able to perform simple tasks Can access a limited part of the chip\u0026rsquo;s memory, the low power memory. ULP-RISC-V (ESP32-S2, ESP32-S3) \u0026ndash; a RISC-V based CPU Programmed using standard C More powerful and much more approachable than the ULP-FSM LP-Core (ESP32-C6, ESP32-C5, ESP32-P4): \u0026ndash; even more powerful RISC-V based CPU Programmed using standard C Has an interrupt controller that conforms to the RISC-V standard Now able to access all of the chip\u0026rsquo;s memory and peripherals when the whole system is powered on; Has additional low-power peripherals, including UART, SPI and JTAG debugging As we focus on the ESP32-C6\u0026rsquo;s ULP LP-Core in this article, let\u0026rsquo;s review its specifications:\n32-bit RISC-V IMAC (Integer, Multiplication, Atomic, Compressed Instructions) CPU 20 MHz clock frequency Access to 16 KB of low-power memory (LP-RAM), memory which can stay powered on during sleep Access to low-power peripherals: LP IO, LP-I2C, LP-UART, and LP timer while the system is in deep sleep Access to all of the chip\u0026rsquo;s memory and peripherals when the whole system is in active mode. Enabling using the LP-Core as a generic co-processor instead of only as a low-power feature. JTAG debugging interface How to use the LP-Core # Now we know what the LP-Core is, its features, and what it can and cannot do. But how do we go about using it? How do we compile and load an application for it?\nThe standard way of using the LP-Core is to compile a separate application for it. This means that writing code for the LP-Core follows a slightly different workflow compared to your regular IDF apps. Luckily, ESP-IDF already integrates building LP-Core apps into its build system and provides APIs to load, run, and interact with the LP-Core to simplify this process for you!\nIn the following section, we will try this workflow and create your first ULP app. To understand how to structure and build a ULP app, we will:\nCreate an empty app that does nothing and build it. Learn how to use the APIs provided by ESP-IDF to load and run the ULP app. See how our main CPU application can interact with the ULP application and exchange information. Put the main system into deep sleep and show how the ULP can wake up the main CPU. Building your LP-Core app # All the following code and API are based on ESP-IDF v5.4. The files and code required for this step should look like this.\nOur main/ directory contains a folder for our LP-Core app. It is called ulp_app/ in this case.\nTo be able to build an LP-Core app, we also need some scaffolding files:\nEvery C application needs an entry point: the empty main() function in ulp_app/ulp_main.c is the entry point for our LP-Core app.\nIn the project\u0026rsquo;s main CMakeLists.txt, we\u0026rsquo;ve added the CMake functions needed to build the LP-Core app:\nidf_component_register(SRCS \u0026#34;my_ulp_app.c\u0026#34; INCLUDE_DIRS \u0026#34;.\u0026#34; PRIV_REQUIRES ulp) # LP-Core support additions to component CMakeLists.txt. set(ulp_app_name \u0026#34;ulp_hello_world\u0026#34;) # Specify all C and Assembly source files. set(ulp_sources \u0026#34;ulp_app/ulp_main.c\u0026#34;) # List all the component source files which include automatically generated LP-Core export file, ${ulp_app_name}.h: set(ulp_exp_dep_srcs \u0026#34;my_ulp_app.c\u0026#34;) # Call function to build LP-Core binary and embed in project using the argument provided above ulp_embed_binary(${ulp_app_name} \u0026#34;${ulp_sources}\u0026#34; \u0026#34;${ulp_exp_dep_srcs}\u0026#34;) With these scaffolding in place, we can set up the target with idf.py set-target esp32c6 and configure the necessary LP-Core related configs in menuconfig:\nTo enable building and using the LP-Core, CONFIG_ULP_COPROC_ENABLED To configure the amount of LP memory to reserve for the LP-Core app, set CONFIG_ULP_COPROC_RESERVE_MEM. For our small application in this article the default value is sufficient, but when creating more complex apps this value might have to be increased. Now you should have everything necessary to build our LP-Core app. Building it can be done the same way you normally build your IDF projects, e.g., with:\nidf.py build If the build was successful, you should now have an LP-Core app built as a separate binary in:\nbuild/esp-idf/main/ulp_hello_world It is already possible to flash the application now, but the LP-Core would not run our main function as we still need to initialize and run the LP-Core.\nRunning your LP-Core app # Now that we have built the LP-Core binary, let\u0026rsquo;s take a look at how to run it. The state of the project for this step will look like this.\nIn my_ulp_app.c\u0026rsquo;s main function we have added the following changes:\n#include \u0026#34;ulp_lp_core.h\u0026#34; extern const uint8_t ulp_hello_world_bin_start[] asm(\u0026#34;_binary_ulp_hello_world_bin_start\u0026#34;); extern const uint8_t ulp_hello_world_bin_end[] asm(\u0026#34;_binary_ulp_hello_world_bin_end\u0026#34;); void app_main(void) { ulp_lp_core_cfg_t cfg = { .wakeup_source = ULP_LP_CORE_WAKEUP_SOURCE_LP_TIMER, .lp_timer_sleep_duration_us = 1000000, }; ESP_ERROR_CHECK(ulp_lp_core_load_binary(ulp_hello_world_bin_start, (ulp_hello_world_bin_end - ulp_hello_world_bin_start))); ESP_ERROR_CHECK(ulp_lp_core_run(\u0026amp;cfg)); printf(\u0026#34;LP core loaded with firmware and running successfully\\n\u0026#34;); } To explain a bit more what is happening:\nextern const uint8_t ulp_hello_world_bin_start[] and .._end[] import the addresses to where the LP-Core binary is placed in flash. The LP-Core binary was automatically included into the app binary when we built our app.\nulp_lp_core_load_binary() copies the LP-Core binary from flash into LP-RAM, which is the memory area we have reserved for the LP-Core.\nulp_lp_core_run() then finally configures the LP-Core according to our config parameters. The wakeup_source is what will trigger the LP-Core to start running, in this case we choose the LP timer, which will make the LP-Core app be re-ran periodically. This is a common use-case when we want to monitor something with the LP-Core, but we don\u0026rsquo;t want it to be active all the time in order to further reduce power consumption. For more information about other wake-up sources, see ulp-lp-core-program-flow.\nThe LP-Core now has everything it needs to run, if you selected a wake-up source which has an immediate effect (e.g. ULP_LP_CORE_WAKEUP_SOURCE_HP_CPU) then the LP-Core will already be running. In our example we choose the LP_Timer with a sleep duration of 1 second, so the first run of the LP-Core app will occur one second after calling ulp_lp_core_run().\nInteracting with the LP-Core # We now have an app running on the LP-Core, but since the app is just an empty main(), it doesn\u0026rsquo;t do anything and we haven\u0026rsquo;t seen any proof that it is actually running.\nIf you want to see how the code look like at this stage you can find it here. Let\u0026rsquo;s expand our LP-Core app to increment a variable every time it runs.\nIn ulp_app/ulp_main.c, we have updated with a counter variable that will be incremented for every run:\nint my_counter = 0; int main (void) { my_counter++; } Note that an LP-Core app\u0026rsquo;s data and bss sections, i.e. global and static variables, are only initialized when you do ulp_lp_core_load_binary(), so here my_counter will keep its value between every call to main(). The life-cycle of an LP-Core app is a bit different from your regular apps. A typical LP-Core app will boot up, perform some measurements or actions, before returning from main() and shutting down, waiting for the next wake-up to restart it.\nEven though letting the LP-Core shut itself down is optimal from a power consumption point of view, it is of course also possible for users to never return from main(), keeping the LP-Core running indefinitely.\nObserving the result # Now we will keep incrementing my_counter once every 1 second (the wake-up interval we configured), but how do we monitor the results? The HP CPU is also able to access the LP memory the LP-Core runs from, so it is just a matter of getting the address of the variable. To simplify this ESP-IDF will automatically generate a header file, ulp_app_name.h which exports all of the global symbols in the LP-Core app.\nIn my_ulp_app.c, we\u0026rsquo;ve added some code to continuously print the value of the counter to the console.\nwhile(1) { printf(\u0026#34;ulp counter: %lu\\n\u0026#34;, ulp_my_counter); vTaskDelay(300 / portTICK_PERIOD_MS); } We have also included the autogenerated ulp_hello_world.h to gain access to the exported variable from the LP-Core app.\n#include \u0026#34;ulp_hello_world.h\u0026#34; Rebuild and flash your software and voila:\nWe finally have the proof that the LP-Core is running independently and doing what we expect it to do!\nPutting the system to sleep # We\u0026rsquo;ve been talking about how to reduce power consumption, but until now all we have done is just add one more module, the LP-Core, which runs in parallel with everything else on the chip, consuming even more power!\nThe last missing part of the puzzle is putting the rest of the system to sleep while the LP-Core works. Most applications will eventually want to wake up the main processor to perform tasks which the LP-Core isn\u0026rsquo;t suited for, so we\u0026rsquo;ll also add the LP-Core as a wake-up source for the HP-CPU.\nThe final version of our application will now be this.\nIn my_ulp_app.c, we have replaced the printing of the counter variable with code to put the system into deep sleep:\n/* Enable the LP-Core to wakeup the rest of the system */ ESP_ERROR_CHECK(esp_sleep_enable_ulp_wakeup()); // Go into to deep sleep esp_deep_sleep_start() We have also added a check and a print for the case when the wake-up is caused by the LP-Core as the first action after entering main():\nif (esp_sleep_get_wakeup_cause() == ESP_SLEEP_WAKEUP_ULP) { printf(\u0026#34;Wake-up cause was: ESP_SLEEP_WAKEUP_ULP\\n\u0026#34;); } And as a final step, we\u0026rsquo;ve modified our LP-Core code in ulp_app/ulp_main.c to include waking up the HP-CPU:\nif (my_counter \u0026gt;= 5) { ulp_lp_core_wakeup_main_processor(); } Since we configured the LP timer to wake up the LP-Core with a period of 1 sec, then this condition means that we will wake up the main processor on the 5th iteration, i.e., after 5 seconds.\nIf you now rebuild and re-flash your project, you\u0026rsquo;ll see that the HP-CPU resets once every 5 second with the reset reason rst:0x5 (SLEEP_WAKEUP).\nMeasuring power consumption # By connecting any device that can measure power consumption, we can get a better idea of what is happening when our code is running.\nPower consumption overview\nWe can see two spikes in the measured power consumption, separated by approximately 5 seconds of low power consumption. These two spikes are when the HP-CPU is active, as expected our LP-Core application wakes it up every 5 seconds.\nStart-up process\nZooming in on one of the high-activity sections, we can see the power consumption for the ESP32-C6 when booting up, running the ROM bootloader, followed by the secondary bootloader before finally booting our application and going into deep sleep. Without any optimization for start-up time, the whole process takes about 200 ms. Optimizing for start-up time is often important in low-power applications as any time spent booting is time not spent sleeping. For more information on how to do this, see:\nESP-IDF start-up time example ESP-Techpedia: Startup Time Optimization If we look at the period of low power consumption when the HP-CPU is sleeping we see the following: LP-Core power consumption\nThere are spikes of activity every one second, which is the wake-up interval for our LP-Core. During these short wake-ups the whole system is consuming approximately 20 µA. Between the wake-ups, both the LP-Core itself, HP-CPU, and almost all of the system is powered down, and we achieve the lowest possible power consumption: 10 µA.\nWrapping up # Now you should know the basics of what the LP-Core can do as well as how to get started programming it.\nStay tuned at the developer portal for more ULP related content!\nAdditional resources # ESP-IDF LP-Core Documentation LP-Core examples How to measure power consumption for Espressif modules ","date":"2 April 2025","externalUrl":null,"permalink":"/blog/2025/04/ulp-lp-core-get-started/","section":"Blog","summary":"In this article, we’ll start with a quick overview of Ultra Low Power coprocessors (ULPs) in Espressif chips and how they can significantly reduce power consumption in your applications. Then, we’ll walk through a tutorial on how to use ULPs in practice!","title":"Building low power applications on Espressif chips: Ultra-Low-Power (ULP) coprocessor","type":"blog"},{"content":"","date":"2 April 2025","externalUrl":null,"permalink":"/tags/lp-core/","section":"Tags","summary":"","title":"LP-Core","type":"tags"},{"content":"","date":"2 April 2025","externalUrl":null,"permalink":"/tags/ulp/","section":"Tags","summary":"","title":"ULP","type":"tags"},{"content":"","date":"1 April 2025","externalUrl":null,"permalink":"/tags/esptool/","section":"Tags","summary":"","title":"Esptool","type":"tags"},{"content":" Introduction # esptool is Espressif\u0026rsquo;s versatile command-line utility and Python library that serves as a Swiss Army knife for ESP chips. If you\u0026rsquo;re flashing any of the ESP8266 or ESP32-series SoCs, you\u0026rsquo;re likely already using esptool under the hood of a framework or IDE, even without realizing it.\nThis tool provides developers with everything needed to:\nRead, write, erase, and verify binary firmware data. Manipulate ROM memory and registers. Fetch chip information (MAC, flash chip info, security info, eFuses). Convert, analyze, assemble, and merge binary executable images. Perform chip diagnostics and provisioning (including secure boot and flash encryption). You can learn more about esptool and how to use it in its documentation.\nesptool\u0026rsquo;s next evolutionary step is the upcoming v5 major release, which is currently being developed in the repository master branch. It will bring significant improvements for both developers and users.\nesptool v5 is still under active development, with a planned release in May 2025. When released, it will first be available in the ESP-IDF v6 major release, with adoption by Arduino and other frameworks to follow.\nA migration guide is provided to help users transition from v4 when the stable release arrives. In the meantime, adventurous users can try a preview by installing the development version:\npip install esptool~=5.0.dev0 Updates for developers # Until now, esptool was primarily a command-line tool with limited Python integration. While powerful when used manually, its convoluted structure made embedding esptool into scripts or applications cumbersome. Developers often resorted to subprocess calls or workarounds, sacrificing reliability and flexibility.\nWith v5, this changes. The new public API transforms esptool into a true library, enabling:\nDirect programmatic control – No more CLI wrapping or output parsing. Structured workflows – Chain operations like backup flash -\u0026gt; erase flash -\u0026gt; write flash -\u0026gt; verify flash in one session. Type-safe API – Auto-completion and error checking in IDEs. Customizable logging – Integrate output with GUIs or logging systems. esptool v5 introduces enhancements for developers who need to integrate ESP chip programming into their Python applications. The new public API provides both high-level convenience functions and low-level control, while the customizable logging enables integration with GUIs and automated systems. Let\u0026rsquo;s have a look at the new features!\nPublic API # A set of high-level functions that encapsulate common operations and simplify the interaction with the ESP chip is now introduced as a public API. These functions are designed to be user-friendly and provide an intuitive way to work with the chip. The public API is the recommended way to interact with the chip programmatically.\nFor most use cases, the esptool.cmds module offers simplified access to common operations. The following example demonstrates a chained workflow that would otherwise require 5 individual runs of esptool on the command line:\nfrom esptool.cmds import ( attach_flash, detect_chip, erase_flash, flash_id, read_flash, reset_chip, run_stub, verify_flash, write_flash ) PORT = \u0026#34;/dev/ttyUSB0\u0026#34; BOOTLOADER = \u0026#34;bootloader.bin\u0026#34; FIRMWARE = \u0026#34;firmware.bin\u0026#34; with detect_chip(PORT) as esp: esp = run_stub(esp) # Upload and run the stub flasher (optional) attach_flash(esp) # Attach the flash memory chip, required for flash operations flash_id(esp) # Print information about the flash chip read_flash(esp, 0x0, 0x8000, \u0026#34;bl_backup.bin\u0026#34;) # Backup the loaded bootloader erase_flash(esp) # Erase the flash memory write_flash(esp, [(0, BOOTLOADER), (0x10000, FIRMWARE)]) # Write binary data verify_flash(esp, [(0, BOOTLOADER), (0x10000, FIRMWARE)]) # Verify written data reset_chip(esp, \u0026#34;hard_reset\u0026#34;) # Reset the chip and execute the loaded app Key features of the Public API:\nContext manager support for automatic resource cleanup. Flexible input types (file paths, bytes, or file-like objects). Multiple operations can be chained together as long as an esp object exists. For full instructions and detailed API reference, please see the related documentation.\nCustom logger integration # esptool v5 introduces a flexible logging system that replaces the previous hardcoded console output. It allows redirecting output by implementing a custom logger class. This can be useful when integrating esptool with graphical user interfaces or other systems where the default console output is not appropriate.\nBy extending or re-implementing the esptool logger you can achieve:\nOutput redirection to any system (GUI, web, log files). Progress reporting hooks for visual feedback (e.g., GUI progress bars filling up during long operations). For an example of a custom logger class and its specifics, please see the related documentation.\nUpdates for users # While the developer-focused improvements in esptool v5 are substantial, users relying on the command-line interface will also benefit from a more polished and user-friendly experience. Here’s what’s in store:\nColored and re-imagined output - The command-line interface now features colored output with indentation to make it easier to use the tool and distinguish between informational messages, warnings, and errors at a glance. Collapsing output stages - Long operations like flashing or verifying large binaries used to flood the terminal with repetitive status updates. With collapsing output stages, logs are condensed into concise, single-line summaries that update in place when a given operation successfully finishes. More Error Messages and Bug Fixes - More edge cases are now covered with meaningful notes, warnings, or error messages. Progress Bars - To provide better visual feedback, ASCII progress bars are introduced for time-consuming tasks like reading or writing flash memory. espefuse and espsecure improvements - All of the listed improvements are also happening in the bundled tools for eFuse manipulation (espefuse) and flash encryption / secure boot management (espsecure).\nThe team at Espressif is working hard to polish the mentioned features and to add new ones. Some of the new planned updates include a clean rewrite of the flasher stub and fast-reflashing capabilities (uploading only the changed parts of firmware, instead of the whole binary), among other enhancements.\nCall for contributions # We’re actively seeking contributors to help shape esptool v5. Whether you’re a developer interested in IDE integrations, a CI/CD expert who can test automation workflows, or a maintainer for less-common platforms, your skills are welcome! To get involved, check out the esptool GitHub repository, and feel free to report issues, suggest features, or submit pull requests.\n","date":"1 April 2025","externalUrl":null,"permalink":"/blog/2025/04/esptool-v5/","section":"Blog","summary":"esptool v5, currently under development by Espressif, boosts its new public API and customizable logging capabilities for developers. The new version brings enhancements for users as well. Contributions are welcome, preview out now.","title":"esptool: Updates about the upcoming v5 major release","type":"blog"},{"content":"","date":"1 April 2025","externalUrl":null,"permalink":"/authors/radim-karnis/","section":"Developer Portal Authors","summary":"","title":"Radim Karniš","type":"authors"},{"content":"","date":"1 April 2025","externalUrl":null,"permalink":"/tags/tools/","section":"Tags","summary":"","title":"Tools","type":"tags"},{"content":"","date":"27 March 2025","externalUrl":null,"permalink":"/tags/ble-adv/","section":"Tags","summary":"","title":"BLE ADV","type":"tags"},{"content":"","date":"27 March 2025","externalUrl":null,"permalink":"/tags/ble-hid/","section":"Tags","summary":"","title":"BLE-HID","type":"tags"},{"content":"","date":"27 March 2025","externalUrl":null,"permalink":"/tags/ble-mesh/","section":"Tags","summary":"","title":"BLE-Mesh","type":"tags"},{"content":" Introduction # In today’s fast-paced tech world, users are moving beyond simply wanting a variety of new smart platforms. Instead, they’re looking for an intelligent ecosystem where devices work together seamlessly, supported by tools that make managing them easier. This requires not only interoperability between devices but also the ability for them to understand and respond to users’ diverse needs, offering more personalized and intelligent services. As a result, ensuring communication across different brands and platforms has become an increasingly important challenge in the smart technology space.\nTo address this challenge, the ESP32-H2_Knob comes into play. Designed to connect seamlessly with a wide range of devices from different brands, it supports multiple communication protocols, enabling interoperability across various platforms. With the ESP32-H2_Knob, users can enjoy a truly connected ecosystem where different smart devices work together effortlessly. Using only one ESP-Knob, you can instantly switch between devices and adjust their settings.\nOverview of ESP-Knob # The ESP-Knob is a multifunctional smart knob controller developed by Espressif Application team and powered by the ESP32-H2 chip. It not only integrates with Home Assistant but also widely supports wireless communication protocols such as BLE-HID, Thread, Matter, ESP-BLE-MESH, and Zigbee. By establishing connections with mainstream smart devices like Apple HomePod and Amazon Echo, the ESP32-H2_Knob helps bridge cross-platform gaps, enabling simpler collaboration between devices from different ecosystems\nThe front of the ESP-Knob features a push-rotary knob housed in a durable aluminum alloy casing, capable of detecting both pressing and rotating actions. The back is equipped with a strong magnetic base that securely attaches to metal surfaces, offering flexible and convenient control placement.\nESP-Knobs\nIn this video you can see the ESP-Knob in action\nPower Supply Modes # To ensure flexibility and reliability, there are two ways to supply power to ESP-Knob:\nButton Battery (Default Power Supply): The ESP-Knob operates efficiently and stably with a single button battery, supporting low power management to extend battery life. ESP-Knob exploded view with batteries\nUSB Power Supply (via ESP32-H2 USB Interface): In terms of hardware design, the ESP-Knob also includes a USB-C port, allowing for continuous power supply via USB, which facilitates program downloading and debugging. Key Features and Capabilities # This section highlights the ESP-Knob\u0026rsquo;s key functionalities and the innovative features that make it a versatile tool for smart device control and integration.\nBLE ADV Broadcast Function # The ESP-Knob connects to the Home Assistant smart home system via the BTHome protocol, sending broadcast packets in the BTHome format to control the third-party smart devices easily, such as adjusting the brightness and color of the Xiaomi bedside lamp, as well as turning it on or off.\nMatter Control Function # The ESP-Knob is also compatible with the Matter-Over-Thread protocol, allowing for easily connect with smart devices such as Apple HomePod and Amazon Echo simultaneously. This enables users to seamlessly manage and control various smart home devices in their homes through the Matter protocol, facilitating a cross-platform smart home control system that enhances the coherence and convenience of the user experience.\nBLE-HID Device Control Function # The ESP-Knob also supports the BLE-HID protocol, allowing it as a Volume Control Device and a Wireless Slide Presenter when connected via Bluetooth.\nThe ESP-Knob can easily pair with smartphones or other Bluetooth devices, serving as an intuitive volume controller. Users can effortlessly adjust the volume using the knob, providing convenient volume control whether enjoying music at home or participating in video conferences at the office. In presentation or speech settings, the ESP-Knob can transform into a convenient Wireless Slide Presenter, enabling remote slide advancement thanks to its support for the BLE-HID protocol. BLE-Mesh \u0026amp; Zigbee Networking Control Functions # For multi-device Mesh scenarios, ESP-Knob supports both ESP-BLE-MESH and Zigbee protocols, and it can efficiently and reliably control multiple devices.\nMulti-device lighting control demonstration Long-distance \u0026amp; Through-wall control function # With the ESP32-H2\u0026rsquo;s transmission power of up to 20 dBm and the maximum reception sensitivity of -106.5 dBm, the ESP-Knob can easily achieve wall penetration communication while maintaining a stable connection over long distances. This means that even in complex environments with numerous obstacles and potential signal interference, the ESP-Knob can still provide reliable and continuous wireless connectivity, ensuring the stability and responsiveness of remote control and data transmission for smart home devices.\nWall Penetration and Long-Distance Control Demonstration Hardware Design # The hardware design of the ESP-Knob is relatively simple. Apart from the basic battery power supply circuit, rotary knob circuit, and download/debugging circuit, it only includes a simple LED indicator circuit. The hardware system of the ESP-Knob is composed as follows:\nESP-Knob Hardware Design\nThe circuit blocks annotated in the drawing are as follows:\nMain MCU: ESP32-H2-MINI-1-H2 module\nEC11 (Rotary Encoder): Used for user input, capable of detecting both rotation and press operations. The press signal from the EC11 controls VCC_EN, which is used for power switching or mode switching.\n5V → 3.3V (Power Module): Uses the XC6206P332MR-G low-dropout linear regulator to step down the USB power supply (5V) to the 3.3V required by the ESP32-H2.\nVBAT → 3.3V (Power Module): Utilizes the TPS61291 boost converter to accommodate a wide input voltage range, supplying 3.3V to the ESP32-H2 during operation. When the ESP32-H2 is in sleep mode, it is directly powered by the battery, and supporting low-power on sleep mode for wake-up functionality.\nUSB-C Interface: Use a USB-C port connect to the ESP32-H2 and used for data transmission and power supply.\nLED (LED Module): Uses GPIO2 and GPIO3 of the ESP32-H2 to control a dual-color LED for lighting and off, and used indicating different operating states of the ESP-Knob.\nBATTERY (Battery Management Module): Connects an external lithium battery (VBAT) through BT1 and monitors the battery voltage. The voltage is divided to BAT_ADC, allowing the ESP32-H2 to monitor the battery level.\nDEBUG (Download \u0026amp; Debug Interface): A reserved test point for the download interface and hardware reset interface of the ESP-Knob device. By connecting to the ESP32-H2’s UART0 interface (TXD0 and RXD0), it supports firmware flashing and debugging. Pulling the ESP_EN pin low allows for a hardware reset of the ESP-Knob.\nThe complete open-source hardware documentation for ESP-Knob can be found at ESP32-H2-Knob. For more details on ESP hardware design, please refer to the ESP Hardware Design Guidelines.\nAvailable firmware and examples # The example projects for the ESP-Knob available at the time of writing are detailed below. Once you flash the corresponding firmware, the ESP-Knob can be connected to different smart home systems. You can also directly download the three kinds of ESP-Knob firmware from the ESP-LAUNCHPAD. The examples are\nBLE-HID: A BLE-HID implementation based on the ble_hid_device_demo. You can adjust the volume by turning the knob and change the bonded device through a long press. BTHome firmware: It integrates Buttonand Dimmercomponents, broadcasting the data in BTHome protocol. It supports Home Assistant and automatic deep sleep. Matter universal switch: It implements a simple matter switch, which can be provisioned using the network qr-code. Conclusion # Leveraging the power of the ESP32-H2 chip, the independently developed smart ESP-Knob offers users a seamless smart home control experience. With its exceptional compatibility and flexibility, it allows developer to easily manage all smart devices in the home with a simple device. We encourage contributions from DIY developers to help expand and enhance the capabilities of the ESP-Knob, and we look forward to seeing fresh ideas and innovations from the community.\nApple and HomePod are trademarks of Apple Inc., registered in the U.S. and other countries and regions. ","date":"27 March 2025","externalUrl":null,"permalink":"/blog/2025/03/esp32h2-knob/","section":"Blog","summary":"This article provides an overview of the ESP-Knob, its features, and functionality. It also details the hardware design and outlines the firmware framework that supports its operation.","title":"ESP-Knob: A multifunctional smart controller with the ESP32-H2","type":"blog"},{"content":"","date":"27 March 2025","externalUrl":null,"permalink":"/tags/esp32-h2/","section":"Tags","summary":"","title":"ESP32-H2","type":"tags"},{"content":"","date":"27 March 2025","externalUrl":null,"permalink":"/tags/zigbee/","section":"Tags","summary":"","title":"Zigbee","type":"tags"},{"content":"While choosing an IoT platform, users are always concerned about its security. Security in IoT encompasses several aspects since multiple entities are involved. In this blogpost, we will go over all the relevant aspects of ESP RainMaker starting from the device hardware and network security, to client network security, authentication and access control, cloud data storage security, and finally, some relevant certifications.\nDevice Hardware Security # Secure Boot # The Secure Boot (or trusted boot) feature ensures that only authenticated software can execute on the device. The Secure Boot process forms a chain of trust by verifying all mutable software entities involved in the Application Startup Flow. Signature verification happens during both boot-up as well as in OTA updates.\nPlease refer to Secure Boot V2 for detailed documentation about this feature.\nSecure Signing # Enabling secure boot and pushing signed OTA upgrades has been made much simpler using the Secure signing feature in ESP RainMaker. For managing the signing keys, ESP RainMaker uses a FIPS-compliant cloud HSM for added security.\nFlash Encryption # The Flash Encryption feature helps to encrypt the contents on the off-chip flash memory and thus provides the confidentiality aspect to the software or data stored in the flash memory.\nPlease refer to Flash Encryption for detailed information about this feature.\nSecure Storage # Secure storage refers to the application-specific data that can be stored in a secure manner on the device, i.e., off-chip flash memory. This is typically a read-write flash partition and holds device-specific user configuration data. The ESP RainMaker agent uses this secure storage to store the Wi-Fi credentials of the user\u0026rsquo;s home and other such sensitive configuration data.\nESP-IDF provides the NVS (Non-Volatile Storage) management component which allows encrypted data partitions. This feature is tied with the platform Flash Encryption feature described earlier.\nPlease refer to NVS Encryption for detailed documentation on the working and instructions to enable this feature.\nIn the ESP RainMaker context, each device has a unique key-certificate pair that helps the device identify itself to the ESP RainMaker cloud. We utilize the encrypted storage to store this information, to protect it from getting cloned across devices.\nDevice Network Security # Network Provisioning # Secure Provisioning refers to a process of secure on-boarding of the RainMaker device onto the user\u0026rsquo;s Wi-Fi/Thread network.\nESP RainMaker uses ESP-IDF\u0026rsquo;s Wi-Fi Provisioning which ensures that the credentials are sent over an authenticated and encrypted channel, either using security 1 or security 2 as the security scheme.\nThe provisioning mechanism uses a Proof of Possession (PoP) pin, a unique secret per device, which is typically pasted on the device in plaintext as well via a QR code. A provisioning client, typically a phone app, will scan this QR code to begin secure communication with the device. This ensures that only a user who is physically in possession of the device can successfully onboard a device.\nESP RainMaker supports an augmented password-authenticated key exchange (PAKE) protocol (SRP6a) to securely authenticate a phone app with the device. All session communication between the phone app and the device is over an encrypted channel.\nCloud Communication (MQTT) # The device-to-cloud communication for ESP RainMaker uses a TLS1.2 encrypted channel with mutual authentication using X.509 certificates.\nEach device has a unique private key and certificate. These are flashed onto the device at the time of manufacturing. The ESP RainMaker cloud backend authenticates and only allows communication with devices that are registered with the cloud, and that can be identified using these certificates. This allows the cloud to authenticate the device.\nAdditionally, the device should also authenticate the cloud (or any other remote service that it accesses). A certificate bundle (a list of most common trusted root CAs) is maintained on the device. This list is used for server authentication to ensure that the device connects to a genuine server and does not get affected even if the server certificate changes. This is the same mechanism that browsers use to authenticate websites that you access through them.\n(Over-The-Air) Updates # The ESP RainMaker also manages and delivers OTA upgrades to connected devices.\nThe OTA update image URL is provided to ESP RainMaker devices over an encrypted MQTT channel. The devices then fetch the image over a secure HTTP (HTTPS) channel, ensuring that the update happens securely.\nBefore finalizing the images on the device, the devices perform a signature verification (refer to the Secure Boot section above) to ensure that the images are truly released by an entity that they trust. The private keys that are used to sign these devices are maintained in ESP RainMaker in a FIPS-compliant cloud HSM.\nSecure Signing # As mentioned earlier in the section for Secure Boot, ESP RainMaker makes it easier to manage OTA for devices with secure boot enabled. You can select appropriate signing key while creating an OTA Job. With the \u0026ldquo;Auto select key\u0026rdquo; option as mentioned here, even selecting the key is not required as the cloud backend can automatically choose the correct key as per the information reported in the node config and send a signed image during OTA.\nApplication Rollback # The OTA application rollback feature that is enabled by default ensures that the device can roll back to the older working firmware in case the newer one has issues causing it to either crash or not be able to connect to the server. Check here for more details.\nAnti-Rollback Protection # The anti-rollback protection feature ensures that the device only executes the application that meets the security version criteria as stored in its eFuse. Even though the application is trusted and signed by a legitimate key, it may contain some revoked security feature or credential. Hence, the device must reject any such application.\nESP-IDF allows this feature for the application only, and it is managed through the 2nd stage bootloader. The security version is stored in the device eFuse and it is compared against the application image header during both bootup and over-the-air updates. Check here for more details.\nLocal Control # Local Control in ESP RainMaker is built on top of ESP IDF\u0026rsquo;s local control feature, which ensures security similar to the one mentioned for Network provisioning above, using security 1 or 2 as the security scheme. The Proof of Possession (PoP) pin is randomly generated on the device and communicated to authorized end users via the cloud using RainMaker parameters. The pin changes if the device is reset to factory defaults.\nClient (User) Network Security # Clients in this context mean phone apps and dashboards that are accessed by admin or end users to talk to the ESP RainMaker backend server. All such communication uses HTTPS, ensuring that the data is encrypted.\nAuthentication and Access Control # Device # As mentioned earlier, each ESP RainMaker device has a unique private key and public certificate. The public certificate is registered with the cloud backend. This ensures that devices only with valid private key and certificate can connect to the cloud. The node ID (used as MQTT client ID) is also embedded into the certificate and validated during connection.\nThe cloud security policy ensures that a node can only publish and subscribe to its own topics, which are under node/\u0026lt;node_id\u0026gt;/*, or, if AWS basic ingest is enabled, under $aws/rules/*/node/\u0026lt;node_id\u0026gt;/*. This prevents nodes from accessing or modifying data from other nodes.\nClient (User) # Users can access ESP RainMaker APIs only when they have logged in and have received valid access and refresh tokens. The access token is to be passed under the \u0026ldquo;Authorization\u0026rdquo; header in all subsequent API calls. This token expires after one hour, but a new one can be fetched using the refresh token. For every user-authenticated call, the cloud backend extracts the user ID from the token to validate against application layer rules.\nUser-Device Mapping # ESP RainMaker has an elaborate method of user-device mapping which requires the user as well as the device to send the same information (exchanged between them on the local network during provisioning) to the cloud, within a window of 1 minute. This ensures that only the authorized user can access the node. More information can be found in the RainMaker Specifications.\nThis user can subsequently share the node with other users by sending them requests which the secondary users can accept or decline. This mechanism ensures that random spam devices do not get added to the account just because some malicious user shared them with the user.\nCloud Data Security # ESP RainMaker is built on AWS serverless architecture, and the data is stored in DynamoDB, S3, and Timestream. All these are encrypted by default. You can read more about this here:\nDynamoDB: Encryption at rest S3: Protecting data with encryption Timestream: Encryption at rest Certifications # ESP RainMaker is currently undergoing ETSI EN 303 645 (Cybersecurity Standard for Consumer IoT Devices) and ongoing 3rd-party penetration testing (for Cloud backend APIs).\nThe security measures taken for all components of ESP RainMaker ensure that the overall solution is highly secure and robust. With the added privacy measures of GDPR compliance, it makes for a perfect platform for your IoT devices. If you are interested in commercial deployments of ESP RainMaker, please reach out to sales@espressif.com or esp-rainmaker-admin@espressif.com.\n","date":"20 March 2025","externalUrl":null,"permalink":"/blog/2025/03/security-in-esp-rainmaker/","section":"Blog","summary":"This article provides a high level overview of the security architecture of the ESP RainMaker IoT platform, covering all aspects like device hardware and network security, client network security, authentication and access control, user-device mapping, cloud data security and certifications.","title":"Security in ESP RainMaker","type":"blog"},{"content":"","date":"19 March 2025","externalUrl":null,"permalink":"/tags/esp32-s2/","section":"Tags","summary":"","title":"ESP32-S2","type":"tags"},{"content":" This article clarifies Espressif\u0026rsquo;s SoC series, module types, memory options, antenna versions, and versioning.. It also explains why modules like WROOM and MINI are among Espressif\u0026rsquo;s most popular products. After reading the article, developers should be able to confidently select the right hardware for their projects.\nEspressif offers a wide range of Systems-on-Chip (SoCs) and modules, continually expanding its product lineup with new offerings while refining existing ones with each revision. However, keeping up with these changes and understanding the naming conventions can be challenging, particularly for newcomers to Espressif\u0026rsquo;s ecosystem.\nThis guide aims to simplify the process by breaking down the part numbers of Espressif modules into their key components and explaining how they correspond to module specifications. We will briefly cover the SoC series, module types, memory options, and versioning, to help you make informed decisions when selecting the right hardware for your project.\nLet\u0026rsquo;s start by briefly going through what the terms SoC and module mean:\nSoC is a chip containing integrated circuits, usually in a small package (QFN). Module is a solution integrated in a single package that includes an SoC along with passive components typically required by the SoC, such as a crystal oscillator for timekeeping, antenna impedance matching network, antenna, etc. Such components cannot be included in an SoC due to extremely limited space. This guide focuses on the Espressif\u0026rsquo;s module conventions and SoC naming conventions are explained to the extent needed to clarify the parts relevant to module naming conventions.\nThe next article will dive into SoC naming conventions.\nSoC series # Espressif SoCs are divided into different SoC series. At the time of writing this article, the most common SoC series are:\nESP32 ESP32-C2 / ESP32-C3 / ESP32-C5 / ESP32-C6 / ESP32-C61 ESP32-H2 / ESP32-H4 ESP32-P4 ESP32-S2 / ESP32-S3 You can also come across the names ESP8684 and ESP8685. These are members of the ESP32-C2 and ESP32-C3 series respectively. The ESP32 was the first Wi-Fi/BLE combo module developed by Espressif, which remains one of the most widely used SoCs. While it is still a viable option, this SoC is slowly but sure approaching its longevity commitment deadline. Released almost a decade ago, it may not be the best choice for new projects unless you have specific requirements, such as needing both Ethernet and Wi-Fi in a single package or requiring classic Bluetooth.\nNewer SoCs can be categorized into four main series based on the letter following the first dash:\n\u0026ldquo;C\u0026rdquo; \u0026ndash; Cost-optimized RISC-V cores with extensive connectivity options. \u0026ldquo;S\u0026rdquo; \u0026ndash; High-performance feature-rich SoCs. \u0026ldquo;H\u0026rdquo; \u0026ndash; BLE and 802.15.4 connectivity SoCs without Wi-Fi radio. \u0026ldquo;P\u0026rdquo; \u0026ndash; High-performance Microcontrollers without wireless connectivity typically used for HMI (such as display, camera) and edge processing applications. You can find the specific part number designations for the SoCs and the SoC with integrated memory in their respective datasheets, e.g. ESP32-S3. Modules # Although SoCs can be integrated directly into custom PCBs, modules could be a choice due to some technical points, including:\nThey include all the required components around the SoC (including antenna filter, clock crystal, etc.). They provide optimized RF design for the PCB antenna. They can incorporate extra memory chips (both flash and PSRAM). Above all: Modules are certified. Check the certificates at https://www.espressif.com/en/support/documents/certificates The last point is the most relevant, since it greatly reduces the end product\u0026rsquo;s certification cost.\nNow, we\u0026rsquo;ll cover module nomenclature.\nOriginally, Espressif offered two module types: WROOM and WROVER, with a smaller MINI variant introduced later. Today, the two main module form factors are WROOM and MINI:\nMINI: A compact form factor, MINI modules are available only with smaller flash memory sizes (4MB or 8MB, depending on the SoC series). WROOM: A larger module that can include additional memory. Available in different configurations with varying amounts of flash and PSRAM. For ESP32 series, the complete module name is WROOM-32. For newer series it\u0026rsquo;s called WROOM. WROVER: A legacy module used exclusively with ESP32 and ESP32-S2 SoCs. During the ESP32 era, WROOM modules only included extra flash memory, whereas WROVER modules integrated 8MB of PSRAM. This form factor is not used for newer SoCs as modern WROOM modules now support both flash and PSRAM expansion. Module form factors.\nMemory options # The available memory varies depending on the SoC itself and any additional memory chips included in the module. Therefore, to fully specify an Espressif component, you must also define its memory size.\nWhen talking about Espressif products, you can encounter four types or memory:\nROM: Internal memory, non-volatile and read-only. It stores the first-stage bootloader. RAM: Internal random-access memory, volatile. It\u0026rsquo;s the primary memory of the chip Flash: Internal or external memory, non-volatile. It\u0026rsquo;s the memory where the second stage bootloader, the code, and the data is stored. PSRAM: Internal or external memory, volatile. PSRAM stands for pseudo-static RAM. The PSRAM is an auxiliary memory to the internal RAM memory of the SoCs. Additional PSRAM can be useful for applications that require graphics or handling resource-intensive tasks. In part numbers, you can find the following letters denoting the memory size for Flash and PSRAM:\nN : flash memory with standard temperature range (-40/+85 ºC) H : flash memory with high temperature range (-40/+105 ºC) R : PSRAM These conventions are applicable to both SoCs (e.g. ESP32FN8, ESP32R2) and modules (e.g. ESP32-S3-WROOM-1-N16R8).\nROM and internal RAM are not present in the part number since their size is fixed for the whole series. However, you can always find it in a chip datasheet, for example see ESP32-S3 Chip Datasheet \u0026gt; Features \u0026gt; CPU and Memory.\nAntenna options # Espressif modules are available with either an integrated PCB antenna or an external antenna connector. The external antenna option is particularly useful when the module is enclosed in a metal case, as the antenna must be positioned outside in such case for optimal signal reception.\nModules with an external antenna connector include a \u0026ldquo;-U\u0026rdquo; suffix in their part number. For example, the ESP32-C3-MINI-1U-N4 features an external antenna connector, while the ESP32-C3-MINI-1-N4 comes with an integrated PCB antenna.\nSilicon versions # Over the years, several new silicon revisions have been developed, typically offering improved performance or addressing security vulnerabilities. The version can be specified by a letter (like the D and E in ESP32-WROOM-32D and ESP32-WROOM-32E) or a number. The versioning doesn\u0026rsquo;t follow a specific rule. A couple of examples, from the oldest to the newest version:\nESP32-WROOM-32-N4 -\u0026gt; ESP32-WROOM-32D-N4 -\u0026gt; ESP32-WROOM-32E-N4 ESP32-WROVER-N8R8 -\u0026gt; ESP32-WROVER-B-N8R8 -\u0026gt; ESP32-WROVER-E-N8R8 ESP32-C3-MINI-1-H4 -\u0026gt; ESP32-C3-MINI-1-H4X Part number # To summarize, specifying an Espressif component requires defining the SoC, the module package size, and the memory configuration (flash and PSRAM), as showed in the picture below. To check which versions are available for a specific module or SoC, you can consult the Series Comparison section of a respective module datasheet.\nExamples # ESP32-WROOM-32D-N8: SoC: ESP32 Module Format: WROOM-32 Version: D Memory: 8MB flash with normal temperature range ESP32-C3-MINI-1-N4 SoC: ESP32-C3 Module Format: MINI-1 Version: N/S - First release Memory: 4MB (i.e. integrated memory in SoC) ESP32-S3-WROOM-1-N16R8 SoC: ESP32-S3 Module: WROOM-1 Version: N/S - First release Memory: 16MB flash with normal temperature range / 8MB PSRAM Conclusion # Espressif\u0026rsquo;s lineup of SoCs and modules continues to evolve, offering a wide range of options tailored to different applications. Understanding the naming conventions and key specifications—such as SoC type, module form factor, and memory configuration—ensures you can select the best module for your project.\nBy using integrated modules, you can simplify development, reduce certification costs, and take advantage of pre-validated designs. Whether you need a compact, low-power solution or a high-performance module with extensive connectivity, Espressif provides an extensive nomenclature to suit your requirements.\nWith this knowledge, you should be better equipped now to navigate Espressif\u0026rsquo;s offerings and make informed decisions when selecting hardware for your next project.\n","date":"19 March 2025","externalUrl":null,"permalink":"/blog/2025/03/espressif-part-numbers-explained/","section":"Blog","summary":"","title":"Espressif part numbers explained: A complete guide - Modules","type":"blog"},{"content":"","date":"13 March 2025","externalUrl":null,"permalink":"/tags/clion/","section":"Tags","summary":"","title":"CLion","type":"tags"},{"content":"","date":"13 March 2025","externalUrl":null,"permalink":"/tags/ide/","section":"Tags","summary":"","title":"IDE","type":"tags"},{"content":"","date":"13 March 2025","externalUrl":null,"permalink":"/authors/oleg-zinovyev/","section":"Developer Portal Authors","summary":"","title":"Oleg Zinovyev","type":"authors"},{"content":"This tutorial shows how to work with an ESP-IDF project in CLion, a cross-platform C and C++ IDE. We’ll build an application, flash it to an ESP32-S3 board, and debug it. We’ll also run the serial monitor and examine the configuration menu that allows you to customize your ESP-IDF project. All of this will be done within the IDE, without having to switch to a system terminal or any other tool.\nThe tutorial is beginner-friendly, so it’s okay if you’ve never worked with ESP-IDF and CLion.\nPrerequisites # We’ll use the following hardware:\nESP32-S3-DevKitC-1 v1.1. MacBook Pro M2 Max. USB-C to micro USB data cable. To get started:\nInstall the ESP-IDF toolchain. Install CLion. You can use the free 30-day trial version. Be sure to check whether there are any discounted or free options available. Although we’ll be running CLion on macOS, the workflow and settings are generally similar to those for Windows and Linux, except in cases mentioned in this article. If you want to learn more about the configuration options available in CLion beyond those demonstrated in this tutorial, refer to the CLion documentation.\nConfiguring an ESP-IDF project # Run CLion. Select Open from the welcome screen. Navigate to the default ESP-IDF directory on your computer. For the purposes of this tutorial, this is /Users/username/esp/esp-idf. Then, go to the examples subdirectory and select a project to build. In this tutorial, we’ll be using led_strip_simple_encoder. It’s located in examples/peripherals/rmt. This application generates an LED rainbow chase on the board. Although it’s intended to be used with an LED strip, it also works with a single LED board like the one used here. The LED will simply flash different colors in a predetermined sequence.\nClick Trust Project. The Open Project Wizard will then open. Click Manage toolchains.... Click +, and select System (for Windows, select MinGW instead) to create a new toolchain. You can name it anything you like.\nSelect Add environment \u0026gt; From file in the new toolchain template. Click Browse.... Select the environment file on your computer. For macOS, you need the file called export.sh (on Windows, it’s export.bat), which is located in the default ESP-IDF directory. Click Apply Go to Settings \u0026gt; Build, Execution, Deployment \u0026gt; CMake.\nIn the default Debug profile settings, select the recently created toolchain, which in our case is ESP-IDF. In the CMake options field, enter -DIDF_TARGET=esp32s3 (because an ESP32-S3-based board is used). In the Build directory field, enter build. Click OK. Your project will then start to load. If the process fails, click Reset Cache and Reload Project in the CMake tool window settings.\nIf the project is loaded successfully, you’ll see [Finished] at the end of the CMake log. Your application is ready to be built and flashed to the board.\nBuilding the application and flashing the board # Make sure your board is connected to your computer via the UART port.\nIf you’re using the same application example, make sure that the GPIO LED number is correctly specified in the source code:\nIn CLion’s Project tool window, locate the main directory in your project directory and open the led_strip_example_main.c file. In the #define RMT_LED_STRIP_GPIO_NUM line, change the default value to 38 or 48, depending on your board hardware revision. Click the Run / Debug Configurations drop-down list on the main toolbar and select the flash configuration. This configuration allows you to build the project and then flash the board automatically.\nClick the green Build icon on the main IDE toolbar. In the Messages tool window, you can see data on the building and flashing processes.\nAfter the build, the board will blink according to the configured rainbow-chase pattern.\nTo change the chasing speed, update the EXAMPLE_ANGLE_INC_FRAME value in led_strip_example_main.c. To change the density of colors, update EXAMPLE_ANGLE_INC_LED in the same file.\nRunning the IDF monitor # Copy the path to your environment file from the toolchain settings. For this tutorial, it’s /Users/Oleg.Zinovyev/esp/esp-idf/export.sh. Go to Run | Edit Configurations and click Add New Configuration. Select the Shell Script template. In this new configuration dialog:\nEnter a name of your choice. Select Script text next to Execute. Enter the following text, including the path of the environment file you’ve just copied: . /Users/Oleg.Zinovyev/esp/esp-idf/export.sh ; idf.py flash monitor. Leave the rest of the options as they are and click OK. Click the green Run icon on the main toolbar.\nYou’ll then see the diagnostic data from the monitor displayed in the IDE’s terminal.\nWorking with the project configuration menu # The project configuration menu is a GUI tool running in the terminal that allows you to configure your ESP-IDF project. It’s based on Kconfig and offers various low-level configuration options, including access to bootloader, serial flash, and security features.\nThe project configuration menu runs through the idf.py menuconfig command, so you need to configure a run configuration accordingly.\nOpen the configuration you’ve created to run the serial monitor. Click Copy Configuration. Rename the copied configuration to reflect the new functionality, for example, ESP-menu-config. In the script text, replace flash monitor with menuconfig. Click OK. Make sure the IDE’s new terminal is disabled (unchecked), as the project configuration menu may not work properly with it. Click the green Run icon on the main toolbar. The project configuration menu will open in the IDE’s terminal.\nYou can use the keyboard to navigate the menu and change the default parameters of your project, for example, the flash size.\nUsing the idf.py command in the terminal # You can also use the idf.py command with various options in the terminal to manage your project and examine its configuration. For example, here is the output of the idf.py. size command showing the firmware size:\nYou can configure commands you often use as shell scripts and run them as separate configurations, as you did earlier when accessing the serial monitor port and project configuration menu.\nTo learn more about the idf.py options, read the official documentation.\nDebugging a project # We’ll use the Debug Servers configuration option to debug the project. This CLion feature provides a convenient way to configure and use a debug server with different build targets.\nUnplug the USB cable from the board’s UART connector and plug it into the USB connector. Make sure Debug Servers are enabled in Settings \u0026gt; Advanced Settings \u0026gt; Debugger. Select the led_strip_simple_encoder.elf configuration from the main toolbar switcher. After that, the Debug Servers switcher appears in the main toolbar.\nSelect Edit Debug Servers. Click + to add a new debug server. Select the Generic template. Here, you need to specify several parameters, some of which depend on your board. For this tutorial, we’ll use the following:\nGDB Server \u0026gt; Executable: /Users/Oleg.Zinovyev/.espressif/tools/openocd-esp32/v0.12.0-esp32-20241016/openocd-esp32/bin/openocd GDB Server \u0026gt; Arguments: -f board/esp32s3-builtin.cfg The Device Settings are as follows: Debugger \u0026gt; Custom GDB Executable: /Users/Oleg.Zinovyev/.espressif/tools/xtensa-esp-elf-gdb/14.2_20240403/xtensa-esp-elf-gdb/bin/xtensa-esp32s3-elf-gdb Debugger \u0026gt; Connection \u0026gt; Arguments: tcp::3333 Also, it’s best to disable the Persistent session option on the Debugger tab, as it can be unstable.\nLeave the rest of the default settings as they are and click Apply. You can also run the GDB server in test mode to verify that the settings are correct. Here is what the Test Run... output looks like when the test is successful:\nSave your changes and close the Debug Servers configuration dialog. Set a breakpoint in your source code file. Click the green Debug icon on the main toolbar. The debug session will start. You can then perform the necessary debugging actions and examine the application data.\nTo learn more about CLion’s debugger features, read the IDE’s documentation.\nFor further guidance about debugging your specific ESP32 chip, refer to the manufacturer’s documentation. There may be some peculiarities related to JTAG settings that you need to be aware of when configuring a debug server for a specific chip.\nConclusion # At CLion, we strive to make the IDE a universal and convenient tool for developing any embedded system, whether hardware, framework, or toolchain. The same is true for ESP-IDF: We plan to simplify the workflow for these projects and are actively working on it.\nWe’d appreciate it if you use this tutorial for your ESP-IDF project and give us your feedback. If you have anything to share or if you encounter any problems, please let us know through our issue tracker.\n","date":"13 March 2025","externalUrl":null,"permalink":"/blog/clion/","section":"Blog","summary":"","title":"Working with ESP-IDF in CLion","type":"blog"},{"content":"Espressif has released ESP32-H2 v1.2, bringing significant cryptographic and hardware security improvements. These features enhance protection, including from power and time analysis attacks, ensuring better reliability and security for IoT applications.\nWhy Upgrade? # The ESP32-H2 v1.2 introduces key enhancements focused on improving resistance to attacks like Differential Power Analysis (DPA) and Correlation Power Analysis (CPA). These upgrades are designed to help developers ensure robust security for applications that require high levels of data protection.\nTo utilize the new features of ESP32-H2 v1.2, ensure you\u0026rsquo;re using the compatible ESP-IDF version. If you\u0026rsquo;re on a pre-v1.2 chip, upgrading ESP-IDF is required for compatibility. This will ensure your binary supports both v1.2 and earlier chip versions.\nKey Benefits # Power Glitch Detector \u0026ndash; The addition of a Power Glitch Detector helps safeguard against power-related attacks that could manipulate device behaviour. Anti-Attack Pseudo-Round for AES/XTS-AES \u0026ndash; This function enhances the security of cryptographic operations, making the device more resistant to power analysis attacks like DPA and CPA. Constant-Time/Power Mode for ECC/ECDSA \u0026ndash; This mode ensures constant timing and power consumption during cryptographic operations, providing stronger defence against power-based analysis attacks. Product Upgrade Comparison # Category After Upgrade Before Upgrade Product Name No change: e.g., ESP32-H2, ESP32-H2-MINI-1 Product Variants the product ordering code is based on the pre-upgrade code with an \u0026ldquo;S\u0026rdquo; added at the end, indicating Security. e.g., ESP32-H2FH2S, ESP32-H2-MINI-1-H2S e.g., ESP32-H2FH2, ESP32-H2-MINI-1-H2 Chip Hardware Version Chip Revision v1.2 Chip Revision v0.1 ESP-IDF Version v5.1.6 and v5.2.5 , v5.3.3 (expected on 3/27), v5.4.1 (expected on 4/4), and above v5.1 and above Optimization enhanced security \u0026ndash; Getting Support and More Information # Upgrade now to benefit from these critical security improvements. For detailed technical information, guidelines, and the latest software versions, visit Espressif’s official website and our forum.\nFor more details, please refer to PCN20250104: Upgrade of ESP32-H2 Series Products. If you have any questions about this upgrade or need any assistance during the upgrade process, please feel free to contact your Espressif account manager or reach out to us through our official website. Let’s move forward to an even better development experience!\nReferences # Press Release ","date":"12 March 2025","externalUrl":null,"permalink":"/blog/2025/03/news-esp32h2-upgrade/","section":"Blog","summary":"Espressif has released ESP32-H2 v1.2, bringing significant cryptographic and hardware security improvements.","title":"ESP32-H2 Upgrade: Enhanced Security and Protection","type":"blog"},{"content":"","date":"10 March 2025","externalUrl":null,"permalink":"/tags/bluetooth/","section":"Tags","summary":"","title":"Bluetooth","type":"tags"},{"content":" Overview # Espressif has already provided a formal response to the recently published claims about ESP32 Bluetooth controller serving as a potential \u0026ldquo;backdoor\u0026rdquo; or having \u0026ldquo;undocumented features\u0026rdquo; that can cause security concerns.\nThis post highlights the technical details about the relevant commands (HCI Commands) that were undocumented and establishes that the mentioned undocumented HCI commands do not pose a security threat and are certainly not a \u0026ldquo;backdoor\u0026rdquo;.\nWhat are HCI Commands? # The Bluetooth protocol stack consists of two primary layers:\nBluetooth Controller (Lower Layer) – Handles radio operations, link management, and low-level Bluetooth communication. Each ESP32 series chip implements a controller through a combination of hardware and software. Bluetooth Host Stack (Upper Layer) – Manages higher-level Bluetooth functionality, such as pairing, encryption, and application-layer interactions. This is fully implemented in software. The ESP32 series of chips support open-source NimBLE and Bluedroid as Bluetooth host stacks. Zoom Image\nThese layers communicate via a standard interface call the Host Controller Interface (HCI). HCI defines a set of standard commands for the Bluetooth Host stack to use. The Bluetooth controller implements standard HCI commands along with a set of Vendor-specific HCI commands that are primarily used for custom hardware initialization on control as well as for debugging purposes.\nWhat is the Reported Security Issue? # The reported security issue highlights that the ESP32 contains a set of undocumented HCI commands. The issue claims that these could be used to gain malicious access to devices running Bluetooth on the ESP32.\nWhat are these Undocumented Commands? # The \u0026ldquo;undocumented\u0026rdquo; HCI commands mentioned in the report are debug commands present in the Bluetooth controller IP in the ESP32. These commands are mostly for assisting the debug (e.g., read/write RAM, memory mapped flash read, send/receive packets, etc.) and do not play any active role in the HCI communication from a standard Bluetooth host stack such as NimBLE or Bluedroid used on the ESP32.\nSuch debugging commands, a common paradigm for Bluetooth Controller implementations, assist developers to debug Controller behavior. This is particularly helpful in dual-chip solutions.\nESP32 Bluetooth Architecture # In ESP32, the Controller and the Host both run on the same MCU. The Host continues to communicate with the Controller over HCI. But since both are running on the same MCU, the HCI can be treated as a virtual HCI layer, an internal layer of communication.\nAny code accessing this virtual HCI layer should itself be first executing on the ESP32, with full execution privileges.\nZoom Image\nImpact # For the majority of the ESP32 applications, the Bluetooth Host and Controller are part of the same application binary running on ESP32. There is no security risk because the application already has full privileged access to the memory and registers as well as ability to send/receive Bluetooth packets irrespective of the availability of these HCI commands. These undocumented HCI commands cannot be triggered by Bluetooth, radio signals, or over the Internet, unless there is a vulnerability in the application itself or the radio protocols. Presence of such vulnerabilities will be a bigger problem and the presence of these undocumented commands does not offer additional attack surface. Only the original ESP32 chip has these commands. ESP32-C, ESP32-S and ESP32-H series chips are unaffected as they don\u0026rsquo;t have these commands supported in their Bluetooth controller. ESP32 Hosted Mode Operation (Less Commonly Used) # In a not-so-commonly-used alternate configuration, ESP32 can tunnel HCI commands over a serial (e.g., UART HCI) interface to an external host system. This is typically used in scenarios where ESP32 acts just as a communication coprocessor. This type of use of ESP32 is not as common as the standalone mode of operation.\nZoom Image\nIn such a system, the ESP32 fully trusts the host. If an attacker maliciously gains control over the host system, they could potentially issue these debug commands to influence ESP32\u0026rsquo;s behavior. However, an attacker must first compromise the host device, making this a second-stage attack vector rather than a standalone vulnerability. Or, gain a physical access to the device to send the HCI commands over serial interface.\nFor these UART-HCI-based implementations, the attack is not self-exploitable. Still, a software fix can disable debug commands via an OTA update for added security. We will have more updates in our software stack regarding this soon.\nMitigation # As summarized above, there is no real, known security threat that these undocumented commands pose. Regardless, Espressif has decided to take the following measures:\nEspressif will provide a fix that removes access to these HCI debug commands through a software patch for currently supported ESP-IDF versions Espressif will document all Vendor-specific HCI commands to ensure transparancy of what functionality is available at the HCI layer Summary # To summarize, for most ESP32 applications, we do not foresee any impact from the reported issue provided the product has the recommended platform security features enabled. For a small number of Bluetooth HCI serial use-cases, we can mitigate the issue by disabling debug commands and we will provide an update on that front soon.\nWe follow a standardized Product Security Incident Response process and we believe in responsible disclosure.\nWe believe that the security of devices based on Espressif chips is of paramount importance and are committed to transparency and best security practices. We will continue to work with the community to ensure that our devices are secure and that all security-related information is responsibly disclosed.\nUpdate # March 20, 2025: This issue has been assigned the identifier CVE-2025-27840 May 26, 2025: Precautionary measures promised above are part of software stack now, please see the advisory for more details AR2025-004 ","date":"10 March 2025","externalUrl":null,"permalink":"/blog/2025/03/esp32-bluetooth-clearing-the-air/","section":"Blog","summary":"","title":"ESP32 Undocumented Bluetooth Commands: Clearing the Air","type":"blog"},{"content":"","date":"7 March 2025","externalUrl":null,"permalink":"/series/nuttx-apps/","section":"Series","summary":"","title":"Nuttx-Apps","type":"series"},{"content":"","date":"7 March 2025","externalUrl":null,"permalink":"/tags/python/","section":"Tags","summary":"","title":"Python","type":"tags"},{"content":" Running Python on ESP32-S3 with NuttX # Yes, you heard it right: Apache NuttX now supports the Python interpreter on ESP32-S3!\nNuttX is a platform that can run applications built with programming languages other than traditional C. C++, Zig, Rust, Lua, BASIC, MicroPython, and, now, Python.\nWhy? # According to the IEEE Spectrum’s 11th annual rankings, Python leads as the most utilized programming language among IEEE members, with adoption rates over twice as high as the second-ranked language. The 2024 Stack Overflow Developer Survey reinforces this trend, reporting that Python was employed by over 51% of developers in the past year, cementing its position as the top-ranked language outside web-specific domains.\nBy integrating Python with NuttX, developers\u0026ndash;including makers and those outside traditional embedded programming\u0026ndash;gain access to a familiar ecosystem for building embedded applications, supported by Python’s vast library ecosystem and open-source tools. NuttX further complements this by offering a POSIX-compliant interface, enabling seamless porting of Python projects (which rely on POSIX APIs) and allowing Python applications to interact with hardware through socket interfaces and character drivers.\nIn essence, Python on NuttX creates a unified framework for hardware interaction. Developers can leverage Python scripts to directly access buses, peripherals, and other NuttX-supported hardware components.\nCritics may argue that Python was never intended for resource-constrained devices (typical in NuttX RTOS environments) and, instead, advocate for alternative embedded tools. However, recent advancements\u0026ndash;particularly Python’s optimizations for WebAssembly\u0026ndash;have significantly reduced its memory footprint and system demands. These improvements make Python increasingly viable even for low-resource environments.\nYou can find more information on how (and why!) Python was ported to NuttX in this article: Apache NuttX: Porting Python to NuttX. Now, let\u0026rsquo;s try Python on ESP32-S3!\nBuilding Python for ESP32-S3 on NuttX # Hardware Requirements # A ESP32-S3 board with at least 16MiB of flash and an external PSRAM of 8MiB or more is required to run Python.\nCheck the ESP Product Selector to find suitable modules providing the required flash size and memory. The example below uses the ESP32-S3-DevKitC-1 v1.1 board that integrates the ESP32-S3-WROOM-2-N32R8V module:\nSoftware Requirements # For those new to NuttX, we recommend reviewing the guide Getting Started with NuttX and ESP32 to configure your development environment for building NuttX applications.\nCompiling and Flashing # Clean any previous configuration and set the defconfig to enable the configurations required for building Python on ESP32-S3:\nmake -j distclean \u0026amp;\u0026amp; ./tools/configure.sh esp32s3-devkit:python To build and flash NuttX, run:\nmake flash ESPTOOL_BINDIR=./ ESPTOOL_PORT=/dev/ttyUSB0 -s -j$(nproc) Now you can grab a coffee :coffee: (Yes, we are building Python libraries and modules. It will take a while to build and flash).\nAfter compilation and flashing finish, open the serial terminal instance to interface with NuttX\u0026rsquo;s NuttShell (NSH).\nRunning Python on ESP32-S3 # After successful building and flashing, run the following command to open the NuttShell:\nminicom -D /dev/ttyUSB0 Type help to check the available applications on NuttX:\nnsh\u0026gt; help help usage: help [-v] [\u0026lt;cmd\u0026gt;] . cmp fdinfo ls pwd truncate [ dirname free lsmod readlink uname ? dd help mkdir rm umount alias df hexdump mkfifo rmdir unset unalias dmesg ifconfig mkrd rmmod uptime arp echo ifdown mount set usleep basename env ifup mv sleep watch break exec insmod nslookup source wget cat exit kill pidof test xd cd expr pkill printf time wait cp false ln ps true Builtin Apps: nsh ping renew wapi ws2812 ostest python sh wget As you can see, python is one of the built-in applications that can run on NuttShell:\nnsh\u0026gt; python Python 3.13.0 (main, Feb 17 2025, 16:20:05) [GCC 12.2.0] on nuttx Type \u0026#34;help\u0026#34;, \u0026#34;copyright\u0026#34;, \u0026#34;credits\u0026#34; or \u0026#34;license\u0026#34; for more information. \u0026gt;\u0026gt;\u0026gt; Here we are! ESP32-S3 is running the Python interpreter as an application on NuttX :rocket:\nWell, let\u0026rsquo;s quit Python interpreter and experiment with Python on NuttX!\n\u0026gt;\u0026gt;\u0026gt; quit() Creating a Python Script # NuttX provides a POSIX-compatible interface that can be used by Python scripts directly. Python\u0026rsquo;s built-in functions like open and write can be used to open and write to a character driver directly. Also, information about the active tasks and other system information are available through the PROCFS filesystem mounted at /proc/, which can be read directly with Python\u0026rsquo;s read function, for instance.\nConsidering that the ESP32-S3-DevKitC-1 board features a WS2812 LED (addressable RGB LED), a simple Python script could be used to monitor the CPU usage and provide an indication of the CPU load in a scale that goes from green to red when CPU usage varies from 0% to 100%.\nAfter some prompts on DeepSeek (or ChatGPT, grab your favorite LLM!), the following script was generated:\nimport sys import struct import select def get_cpu_load(): try: with open(\u0026#39;/proc/cpuload\u0026#39;, \u0026#39;r\u0026#39;) as f: content = f.read().strip() # Extract numeric value and remove percentage sign percent_str = content.replace(\u0026#39;%\u0026#39;, \u0026#39;\u0026#39;).strip() load_percent = float(percent_str) normalized_load = load_percent / 100.0 return max(0.0, min(normalized_load, 1.0)) except IOError as e: print(f\u0026#34;Error reading /proc/cpuload: {e}\u0026#34;) sys.exit(1) except ValueError: print(f\u0026#34;Invalid data in /proc/cpuload: \u0026#39;{content}\u0026#39;\u0026#34;) sys.exit(1) def main(): try: while True: load = get_cpu_load() # Calculate RGB values with proper rounding r = int(load * 255 + 0.5) g = int((1 - load) * 255 + 0.5) b = 0 # Pack as BGR0 (4 bytes) for the LED data = struct.pack(\u0026#39;4B\u0026#39;, b, g, r, 0) # Write to device try: with open(\u0026#39;/dev/leds0\u0026#39;, \u0026#39;wb\u0026#39;) as f: f.write(data) except IOError as e: print(f\u0026#34;Error writing to device: {e}\u0026#34;) sys.exit(1) # Wait 100ms using select (instead of time.sleep) select.select([], [], [], 0.1) except KeyboardInterrupt: print(\u0026#34;\\nExiting...\u0026#34;) sys.exit(0) if __name__ == \u0026#39;__main__\u0026#39;: main() It reads CPU usage from /proc/cpuload, transforms it to a scale that goes from green to red, and, then, sends it to the registered character driver of the RGB LED.\nSave this file on your host computer with the name cpumon.py, for instance.\nHow should we run this script on the board?\nTransfering the Python Script # We could create a ROMFS partition containing this script and then run it on NuttX. However, the embedded application concept is somehow related to the ability to run it without needing to reflash a device. So, can we send it through the Wi-Fi network to the board?\nYes, we can!\nConnect the board to your Wi-Fi network:\nnsh\u0026gt; wapi psk wlan0 \u0026lt;password\u0026gt; 3 nsh\u0026gt; wapi essid wlan0 \u0026lt;ssid\u0026gt; 1 nsh\u0026gt; renew wlan0 On the host computer, create a simple HTTP server with Python in the folder that contains the Python script to be sent:\npython -m http.server 8080 Now, check if the script is available through the network by accessing the host computer\u0026rsquo;s IP address (if possible, test it on a different machine). For instance, try to open in the web browser with http://\u0026lt;host_computer_ip\u0026gt;:8080/cpumon.py.\nOnce everything is set on the host side, download the Python script to the board:\nnsh\u0026gt; wget /tmp/cpumon.py http://\u0026lt;host_computer_ip\u0026gt;:8080/cpumon.py And, then, check if it was successfully downloaded:\nnsh\u0026gt; cat /tmp/cpumon.py import sys import struct import select def get_cpu_load(): . . . Running the Python Script # Finally, run the Python script in the background:\nnsh\u0026gt; python /tmp/cpumon.py \u0026amp; python [12:100] In a few seconds, the LED will show the CPU load average while the Python script is running in the background. To test it properly, create one or more instances of the cpuload app that increases CPU usage:\nnsh\u0026gt; cpuload \u0026amp; cpuload [13:253] nsh\u0026gt; cpuload \u0026amp; With 3 (three) instances of cpuload, the LED should be reddish as CPU load usage reaches nearly 90%:\nnsh\u0026gt; python /tmp/cpumon.py \u0026amp; python [12:100] nsh\u0026gt; cpuload \u0026amp; cpuload [13:253] nsh\u0026gt; cpuload \u0026amp; cpuload [14:253] nsh\u0026gt; cpuload \u0026amp; cpuload [15:253] nsh\u0026gt; ps PID GROUP CPU PRI POLICY TYPE NPX STATE EVENT SIGMASK STACK CPU COMMAND 0 0 0 0 FIFO Kthread - Assigned 0000000000000000 0003008 6.4% CPU0 IDLE 1 0 1 0 FIFO Kthread - Assigned 0000000000000000 0003008 8.5% CPU1 IDLE 2 0 --- 100 RR Kthread - Waiting Semaphore 0000000000000000 0001928 0.0% lpwork 0x3fcaa2c4 0x3fcaa24 3 3 1 100 RR Task - Running 0000000000000000 0002976 0.0% nsh_main 4 0 --- 255 RR Kthread - Waiting Semaphore 0000000000000000 0000656 0.0% spiflash_op 0x3fcd0d4c 5 0 --- 255 RR Kthread - Waiting Semaphore 0000000000000000 0000656 0.0% spiflash_op 0x3fcd0d4c 6 0 --- 223 RR Kthread - Waiting Semaphore 0000000000000000 0001944 0.0% rt_timer 7 0 --- 253 RR Kthread - Waiting MQ empty 0000000000000000 0006576 0.0% wifi 12 12 0 100 RR Task - Assigned 0000000000000000 0307088 12.0% python /tmp/cpumon.py 13 13 1 253 RR Task - Running 0000000000000000 0001968 26.9% cpuload 14 14 --- 253 RR Task - Waiting Signal 0000000000000000 0001960 25.1% cpuload 15 15 --- 253 RR Task - Waiting Signal 0000000000000000 0001960 22.3% cpuload nsh\u0026gt; cat /proc/cpuload 89.3% The following video shows this demo: the RGB LED goes from green to red when the CPU load average goes from 0% to 100%.\n(also available on BiliBili) Conclusion # Running the Python interpreter on NuttX is possible mainly due to its POSIX-compatible interface. In addition to that, NuttX exposes the drivers for each board\u0026rsquo;s peripherals as block or character drivers. Then, accessing the drivers is as easy as reading and writing to a file (and using the ioctl interface), just like any other Unix-based system.\nWith that in mind, building applications on Python that access boards\u0026rsquo; peripherals is just straightforward: relatively complex applications can be built in Python in minutes and, then, run on NuttX without the need of reflashing the device or compiling anything externally. That\u0026rsquo;s why we call them embedded applications: those applications are developed and tested externally\u0026ndash;on a host PC, for instance\u0026ndash;and, once validated, they can be transferred and run on NuttX without the need of knowing the inner details of the NuttX RTOS because it offers a well-known interface and well-known programming language.\nStay tuned for more updates about Python on NuttX!\nUseful Links # NuttX Documentation: Python Apache NuttX: Porting Python to NuttX NuttX GitHub NuttX channel on Youtube Developer Mailing List ","date":"7 March 2025","externalUrl":null,"permalink":"/blog/2025/03/nuttx-python-esp32s3/","section":"Blog","summary":"","title":"Running Python on ESP32-S3 with NuttX","type":"blog"},{"content":"","date":"7 March 2025","externalUrl":null,"permalink":"/authors/tiago-medicci/","section":"Developer Portal Authors","summary":"","title":"Tiago Medicci","type":"authors"},{"content":" To fully leverage the improved capabilities of the ESP32-C2, we recommend that all developers and manufacturers update to use the latest ESP-IDF minor version as soon as possible.\nEspressif has upgraded the ESP32-C2 (ESP8684) to enhance its performance and efficiency. This update provides additional memory and Flash storage, enabling developers to build more complex applications while ensuring long-term stability and support.\nWhy Upgrade? # To fully leverage the improved capabilities of the ESP32-C2, we recommend that all developers and manufacturers update to use the latest ESP-IDF minor version as soon as possible. Upgrading ensures compatibility with the latest hardware versions and prevents potential performance or stability issues\nDelaying the upgrade may result in compatibility issues, affecting performance and development efficiency. Espressif provides comprehensive technical documentation and resources to support a smooth migration.\nKey Benefits # Improved Memory for Real-Time Processing – Gain up to 20 KB of additional SRAM, enhancing real-time data processing and multi-tasking capabilities. This is particularly valuable for IoT devices, reducing the risk of memory overflow and improving program stability. Developers can now store more runtime data, optimize algorithms, and expand functionalities without worrying about memory constraints.\nExpanded Flash Storage for Greater Flexibility – With approximately 100 KB of extra Flash memory, developers can integrate larger OTA update packages, store more preloaded data, and extend device functionality over time. This additional space also allows for better logging and debugging, making performance optimization easier in real-world applications.\nEnhanced Performance and Stability – The combination of the ESP32-C2 v2.0 chip and the upgraded ESP-IDF framework optimizes hardware resource utilization, providing a smoother, more efficient development experience.\nUpgrading now ensures optimal performance and future-proof reliability for your projects. For detailed guidance, refer to Espressif’s technical resources.\nProduct Upgrade Comparison: Before and After # Category After Upgrade Before Upgrade Product Name No change: e.g., ESP8684, ESP8684-MINI-1. Product Variants The product ordering code is based on the pre-upgrade code with an \u0026ldquo;X\u0026rdquo; added at the end, indicating Extended. e.g., ESP8684H2X, ESP8684-MINI-1-H2X. e.g., ESP8684H2, ESP8684-MINI-1. Chip Hardware Version Chip Revision v2.0. Chip Revision v1.2. ESP-IDF Version IDF v5.4, IDF v5.3.2, v5.2.4, v5.1.5, IDF v5.0.8 and above. v5.0 and above. Optimization Increased user-available space, with approximately 20 KB of additional SRAM and about 100 KB of Flash space (depending on the actual application). Getting Support and More Information # This upgrade enhances performance and reliability, providing stronger support for your projects. For technical details, upgrade guidelines, and the latest software versions, visit Espressif’s official website and join the discussion on our forum.\nFor more details, please refer to PCN20250101: Upgrade ESP32-C2 (ESP8684) Series Products, Compatibility Announcement for ESP32-C2 Series v2.0 Chip.\nIf you have any questions about this upgrade or need any assistance during the upgrade process, please feel free to contact your Espressif account manager or reach out to us through our official website. Let’s move forward to an even better development experience!\nReferences # Press Release ","date":"7 March 2025","externalUrl":null,"permalink":"/blog/2025/03/esp32c2_news/","section":"Blog","summary":"","title":"ESP32-C2 (ESP8684) Upgrade: More Memory, Storage, and Performance","type":"blog"},{"content":"We\u0026rsquo;re thrilled to announce that Espressif will once again be attending Embedded World 2025 in Nuremberg!\n:calendar: Dates: March 11th (Tuesday) - March 13th (Thursday)\n:round_pushpin: Location: Nürnberg Messe, Hall 4A, Booth 131\nCome visit us and dive into the latest innovations and breakthroughs from Espressif!\nThis is your chance to meet and interact with our developers, explore live demos, and discuss the most recent advancements in ESP-IDF and all our frameworks. We\u0026rsquo;ll be showcasing our newest technologies and sharing insights on how they can be leveraged to build smarter, more efficient solutions.\nTogether with us, you will also find M5Stack and their incredible modular systems.\n:tada: What\u0026rsquo;s waiting for you at our booth?\n:rocket: New SoCs: Get the latest updates, including the powerful ESP32-C5 and the efficient ESP32-H4. :robot: AI \u0026amp; HMI Solutions: Explore how ESP32-P4 and ESP32-S3 are revolutionizing the fields of embedded Artificial Intelligence and Human-Machine Interfaces, enabling innovative and cost-sensitive solutions. :cloud: Rainmaker \u0026amp; Matter: Learn more about our cutting-edge IoT solutions and how they enable seamless smart home and cloud integrations, ensuring compatibility and ease of deployment. :video_game: Gaming Classics, Reimagined: Witness classic video games brought back to life on Espressif\u0026rsquo;s platforms. Whether you\u0026rsquo;re a developer, engineer, or enthusiast, there will be something for everyone. We\u0026rsquo;ll also have technical experts available for in-depth discussions and to answer your questions directly.\nSee you in Nuremberg!\nDownload Material # Update product catalog ESP-IDF news flyer ESP-Rust news flyer Arduino news flyer Zephyr news flyer ","date":"4 March 2025","externalUrl":null,"permalink":"/events/embedded_world_2025/","section":"Events","summary":"","title":"Embedded world 2025","type":"events"},{"content":"At Espressif Systems, we are continuously striving to make device development easier for device makers. For Matter devices, we launched the ESP ZeroCode solution, simplifying the device development by removing the software development efforts. Allowing product customizations to a limited extent, ESP ZeroCode is well-suited for those who want to launch connected products without having to build them from scratch using the ESP Matter or the Connectedhomeip (CHIP) SDK.\nToday, we announce our ESP LowCode Matter solution that achieves the best of both worlds by continuing to retain simplicity of ESP ZeroCode and providing the ability to customize, with ease, the typical parts of an application.\nWhat is ESP LowCode Matter? # ESP LowCode Matter is a solution that splits firmware into two parts for a single chip:\nSystem Firmware: Developed and maintained by Espressif, it wraps the complexity of the Matter protocol, OTA upgrades, and security management. Application Firmware: Developed by a device maker, it implements hardware interfacing, hardware communication protocols and other business and device logic. Zoom Image\nESP LowCode Matter is a culmination of learnings and efforts along multiple dimensions to ensure that the development experience is truly great. Let\u0026rsquo;s look at some of the key advantages of this solution.\nSimplified Development # ESP LowCode Matter makes the application code development intuitive, easy to understand and customize. It provides the simplicity and the flexibility to create any device with all the features of Matter (even custom ones), while isolating all the system level complexities from the application developer.\nThe generated application firmware is quite small, making the build-flash-debug cycle extremely fast Development is exposed through a simplified setup-loop style of programming One of the goals is to incorporate the production scenarios in the development workflow itself, with the following Matter specific features:\nUnique QR code generation and flashing Unique DAC certificate generation and flashing For development, the devices get a test DAC certificate. But for production, with Espressif\u0026rsquo;s Matter manufacturing service, the modules will be pre-programmed with the production certificates.\nSimplified Maintenance # Espressif maintains the System Firmware. The complexities of the Matter protocol, OTA upgrades, and security management are all happening internally. This isolates device makers from individually incorporating security fixes and other bug fixes that are provided in other base SDKs, such as ESP-IDF, ESP Matter, CHIP. This in turn helps to maintain the best security for in-field devices.\nIt leaves the application developer to focus on:\nDriver interfacing Event and state indication User interaction This is something that the device makers always wanted: the ability to write, create, and modify just the part that affects them and the end user, without having to deal with the complexities of what is happening internally. With that out of the way, the device makers can focus on the above three areas, in which they already have vast experience.\nDevice makers can modify the data model as per their device and application requirements. This Matter data model is interpreted by the system firmware but it is still outside the system firmware like a pluggable component.\nSimplified Certification # The ESP LowCode Matter system firmware undergoes regular and rigorous testing to meet the high quality bar that we have set for ourselves. This ensures that the various certifications and the tests required by them are done efficiently and smoothly.\nMatter Certification\nESP LowCode Matter products need to undergo full certification and testing. But, the Matter functionality is largely handled by Espressif in the system firmware itself, which ensures Matter compatibility. Additionally, Espressif will assist manufacturers in certifying their products and keeping the certification up to date in the most efficient manner. You can use this badge on your product packaging and marketing materials once the product is certified. Product Security Certification\nThe Product Security Certification from CSA (Connectivity Standards Alliance) is recommended for all devices. All the security measures are already in place and taken care of in ESP LowCode Matter. You can use this badge on your product packaging and marketing materials once the product is certified. \u0026ldquo;Works with\u0026rdquo; Badges and programs by various other Ecosystems\nSimilar to ESP ZeroCode, with ESP LowCode Matter, you can easily get certified for various other ecosystems, and get the \u0026ldquo;Works with\u0026rdquo; badges. Espressif is closely working with the Ecosystem providers to get the best experience for the device makers and the end users. Everything in the browser # We have built VS Code IDE plugins for ESP LowCode Matter, and integrated those with GitHub Codespaces. This provides a first-class development experience from the browser itself. It integrates the entire development workflow within the VS Code IDE loaded in your browser. No need to install any additional software on the development host. All development operations, edit, build, flash, and monitoring the console are available through the browser, in the familiar VS Code interface.\nYou can simply connect the device to your own laptop and access it through the browser.\nZoom Image\nInstead of using the browser-based IDE, you can also use your local VS Code IDE or your preferred editors. These workflows are also fully supported.\nFirst SoC: ESP32-C6 # The ESP32-C6 is the first SoC that is supported by ESP LowCode Matter. It is a 32-bit dual-core SoC with a High-Performance Core and a Low-Power Core. It is a great fit for the Matter protocol and the ESP LowCode Matter solution.\nFor ESP32-C6, ESP LowCode Matter completely partitions CPU and memory across system and application firmware. The High-Performance Core (and its associated memory) is dedicated to the system firmware while the Low-Power Core (and its associated memory) is dedicated to the application firmware. This split ensures that the application firmware is compartmentalized, and a developer doesn\u0026rsquo;t have to deal with the complexities of the system firmware.\nThe application firmware is a single-threaded application that runs on the Low Power Core without an OS.\nThis provides multiple benefits:\nDevelopment and debugging are contained, hence much simpler, as opposed to a fully multi-threaded FreeRTOS/IDF application. The partitioned memory ensures that the application firmware is stable and doesn\u0026rsquo;t affect the system firmware. The firmware is ~20KB for a typical application, making this a very small footprint. Simplified HAL drivers (RTOS independent low-level peripheral drivers) help to directly interface with the hardware peripherals. The ESP LowCode Matter platform uses the ESP-AMP project for facilitating this partitioning. You may read more about ESP-AMP here.\nTry # Try ESP LowCode Matter today by following the README.\nESP LowCode Matter represents a significant step forward in making Matter device development more accessible. Whether you\u0026rsquo;re building smart plugs, lights, appliances or custom Matter devices, ESP LowCode Matter provides the tools and simplicity you need to bring your ideas to life and launch products faster.\nLet us know what you think by joining the discussions and becoming a part of the growing ESP LowCode Matter community.\nDisclaimer: All trademarks and copyrights are property of their respective owners.\n","date":"27 February 2025","externalUrl":null,"permalink":"/blog/2025/02/introducing-esp-lowcode-matter/","section":"Blog","summary":"","title":"Introducing ESP LowCode Matter: Simplified Device Development","type":"blog"},{"content":"","date":"27 February 2025","externalUrl":null,"permalink":"/authors/kedar-sovani/","section":"Developer Portal Authors","summary":"","title":"Kedar Sovani","type":"authors"},{"content":"","date":"27 February 2025","externalUrl":null,"permalink":"/tags/low-code/","section":"Tags","summary":"","title":"Low Code","type":"tags"},{"content":"We\u0026rsquo;re excited to announce the 1.0.0-beta.0 release for esp-hal, the first vendor-backed Rust SDK! This has been a nearly 6 year long process to get to this point, and we now feel we have a solid 1.0 strategy.\nLet us take you on the journey of how we got here. If you\u0026rsquo;re just interested in what we\u0026rsquo;re stabilizing today, click here to jump to it.\nWhere It All Started # In 2019, I created the esp-rs organization, which laid dormant for some time. At the time, Espressif was exclusively using the Xtensa architecture for their chips which, whilst powerful, had one big caveat for Rust support: there was no LLVM backend for Xtensa. I tried to use mrustc to cross-compile Rust to C, and then use the GCC Xtensa toolchain but whilst I had some minor success the workflow was far too cumbersome.\nFast-forward a few months and Espressif announced the first iteration of their Xtensa enabled LLVM fork with the intention of getting it upstreamed. I was excited about this, and I got to work integrating this Xtensa enabled LLVM into the Rust compiler. I succeeded, with a lot of help from members of the Rust community and a reference set of PRs for RISC-V which had been merged just a bit earlier in the year. This project was set aside for a while, but I got back to it and managed to write the world\u0026rsquo;s first Rust blinky on an ESP32! I documented my early findings in a series of posts on my personal website. I read these posts again (mostly to remind myself what on earth I was doing 5 years ago), and one quote from my first post stood out to me.\nNow I know what most of you are thinking at this point, it\u0026rsquo;s not very Rusty; it contains bundles of unsafe code and there are no real abstractions here, and you are right; but it\u0026rsquo;s something to get the ball rolling.\nIt\u0026rsquo;s safe to say the ball definitely rolled.\nEspressif’s Official Support for Rust # Not long after that initial blog post, Espressif started sponsoring my work and allowed me to continue working on it in my spare time. At the same time, the community around esp-rs was starting to grow, and I really can\u0026rsquo;t thank these early contributors enough. Myself and a few early contributors, namely @jessebraham, and @arjanmels mostly focussed on the no_std side of things. Initially @reitermarkus and eventually @ivmarkov ported the Rust standard library which built on ESP-IDF. This was a great addition as it gave us a big head start because we could use the stable and tested code from ESP-IDF without having to write all the drivers from scratch for no_std immediately.\nEspressif had been observing our work (and may I add, were extremely helpful in answering any questions we had) and by 2021, they were keen to adopt it officially. They reached out to me and some other community contributors about a position in a newly forming Rust team, and I, along with @jessebraham gladly accepted.\nBringing Up the Ecosystem # It has been possible to write embedded Rust applications on stable since 2018. Most of the ecosystem, however, revolved around chips using the ARM architecture, which posed a bit of an uphill battle for us. Espressif had just released its last Xtensa chip (the ESP32-S3) and was now bringing out RISC-V based chips.\nWhilst most crates in the embedded Rust ecosystem are architecture independent, the tooling is a different story. Over the years we\u0026rsquo;ve spent a lot of time contributing to various open source projects, like probe-rs to either improve, or in the case of Xtensa, add support. This work is still on going, but we\u0026rsquo;re quite happy with the usability of the tooling on our chips now.\nXtensa based chips posed many challenges for us. We ended up writing xtensa-lx and xtensa-lx-rt using the proprietary (at the time, Cadence, the owners of the Xtensa IP have since released an open version) Xtensa instruction set manual. There was at least some runtime/startup support for RISC-V, but absolutely nothing for Xtensa in the Rust ecosystem.\nAnother challenge we faced is that we were the primary users of the LLVM Xtensa fork. This meant when there was a bug in code-generation we were the unfortunate souls to run into it. This ate copious amounts of developer time, but in the end it was worth it, as the backend is in good shape now. There is also a huge amount of progress to report on the upstreaming front for LLVM (which was stalled for a long, long time). Most of the base ISA is now in LLVM proper, and the remaining patches can be submitted in parallel, see the tracking issue for more details.\nFocusing on no_std Crates # In late 2021, @jessebraham started esp-hal with the aims of replacing the chip specific esp32-hal which was currently being worked on. It worked out amazingly well, and we had a setup where we could share driver code across multiple chips! It wasn\u0026rsquo;t long before most of Espressif\u0026rsquo;s Rust team started to contributing to it whilst also maintaining the standard library port (more on that later).\nNot long after, @BjoernQ joined the team and set out to add support for arguably the most important peripheral in an ESP32, the radio. He achieved success, and we\u0026rsquo;ve had no_std Wi-Fi, BLE and ESP-NOW support ever since! I cannot state how important these steps were, as it gave us confidence that we could build a fully functioning SDK supporting a whole lineup of chips, in pure Rust1!\nWe spent the entirety of 2022 and most of 2023 working exclusively on chip support; making sure new chips were supported, and trying to support as many peripherals as possible. During this time, we also experimented with adding async versions of some drivers, as the embassy project began to flourish.\nThis seemed like a good idea at the time but by the end of 2023 we realized that trying to support everything that the chips can do (there is a lot, try looking at a reference manual if you\u0026rsquo;re curious) whilst an admirable goal is likely unachievable in a reasonable time with the size of our team. We soon realized that API stability is far more important than having everything supported.\nTargeting Stability # The first step to stability, and something that had been on our backlog for a while was getting hardware in loop testing (HIL) working. This would be crucial to ensure that we ship reliable, bug-free software. HIL testing works by running tests on the device itself, through a debugger interface to talk to the host machine.\nWe initially planned on using defmt-test to run tests on our devices, but sadly it only supports ARM. Fortunately around this time, @t-moe created embedded-test which works in a similar way to defmt-test but has a couple of advantages:\nIt supports ARM, RISC-V and Xtensa (thanks to some great work by @bugadani to add Xtensa support to probe-rs) It supported async tests Its been working extremely well for us, and we\u0026rsquo;ve been amassing an ever growing list of test cases in the hil-test crate.\nThe next step, was figuring out what our APIs should look like. After all we can\u0026rsquo;t stabilize something unless we\u0026rsquo;re sure we\u0026rsquo;re going in the right direction. We spent some time reviewing the ecosystem and our own issue tracker for usability issues and found that many of the usability difficulties come from too many generic parameters on drivers.\nThis was not the only thing we found of course, but it was the biggest shift in our visible API. This was mostly inspired by the embassy project\u0026rsquo;s in-tree HALs. The official Rust embedded book actually promotes the use of typestating etc, which is why many HALs, including esp-hal ended up in this situation, but in our opinion the less generics the better, for reasons beyond just usability; there are also some nice code size improvements which are really important for small constrained resources devices.\nHere is a diff of type information of our old pin types, versus the new ones. Everything is now hidden within the type itself, seven generic paramters to zero. This makes storing a array of pins trivial, as they are all the same type!\n- GpioPin\u0026lt;Output\u0026lt;OpenDrain\u0026gt;, RA, IRA, PINTYPE, SIG, GPIONUM\u0026gt; + Output The remainder of our findings we placed in a living document, DEVELOPER-GUIDELINES which we used, and will continue to use to stabilize parts of the HAL.\nThe final step, was figuring out how we were going to document this. Supporting multiple chips from one crate poses an interesting challenge. We can no longer use docs.rs for our documentation (we can, and do, but only for one chip) so we\u0026rsquo;ve instead started self-hosting our docs, with a chip and version selector to combat this. You can view the docs on the official docs.espressif.com/projects/rust site. Once again, this was heavily inspired by embassy\u0026rsquo;s prior work in this area.\nOur Stabilization Strategy # Our stabilization strategy is quite simple, we\u0026rsquo;ve limited the scope of 1.0 stabilization to:\nInitializing the hal, esp_hal::init and the relevant configuration associated with that. Four \u0026ldquo;core\u0026rdquo; drivers to start: GPIO UART SPI I2C The time module, which provides Instant, Duration, and Rate. A couple of miscellaneous system APIs (SoC reset, etc.). #[main] macro. How esp-hal and friends are configured via esp-config. With the exception of the list above, everything else in esp-hal is now feature gated behind the unstable feature. With the scope limited, post 1.0 we can incrementally stabilize drivers, much like the Rust project itself does. This is quite a small amount to stabilize initially, however we feel it\u0026rsquo;s enough to build a foundation on. It\u0026rsquo;s expected that for most complex projects users will opt-in to the unstable feature. Over time, as we stabilize more drivers, and eventually more crates, users will be able to remove the unstable feature from their Cargo.toml files.\nWhat About the Other no_std esp-* Crates? # esp-hal is the foundation of many of the esp-rs ecosystem crates, esp-wifi is our next stabilization target, and builds directly on top of esp-hal. The end goal is of course to have every esp-* crate with a 1.0+ release.\nCall for Testing # As this is a beta release, we\u0026rsquo;d absolutely love to hear your feedback on esp-hal as it currently stands! Whether you\u0026rsquo;ve used it before, or you\u0026rsquo;re about to try it out for the first time, any feedback is most welcome!\nPlease open issues for anything that should be working that isn\u0026rsquo;t Please open discussions to discuss API decisions that perhaps aren\u0026rsquo;t quite as ergonomic or thought through as we intended We\u0026rsquo;ve created our own project generation tool, esp-generate to bootstrap starting a project, which is often a bit of a tricky thing to set up in embedded. Please do give it a try by first installing the tool with\ncargo install esp-generate then, to generate a project for the ESP32-C6, run\nesp-generate --chip esp32c6 NAME_OF_PROJECT We\u0026rsquo;re currently rewriting the book, but in the meantime it can still be helpful to read it to get an overview of the ecosystem.\nWhere Does This Leave the Standard Library Port? # At this time we\u0026rsquo;re officially marking the std crates as community supported, which we\u0026rsquo;ve reflected on the organization landing page. We will still maintain the upstream compiler targets, and ensure that those targets continue to function, but esp-idf-sys, esp-idf-hal and esp-idf-svc are now community projects. It\u0026rsquo;s been moving this way for a while, but we\u0026rsquo;d like to officially announce it here. Users wanting a more stable (and official) development environment should transition to esp-hal and the other no_std crates.\nWhat’s Next? # Our focus now is to keep pushing until esp-hal 1.0. We\u0026rsquo;ll then split our efforts and try to stabilize more things in esp-hal whilst also pushing for a stable Wi-Fi/BLE story. Preparing for the full esp-hal 1.0 release requires an overhaul of the book, along with a bunch of documentation and polish all round. Finally, we need to ensure our tooling is in a good place, so we plan to make a new espflash release to accomplish that.\nThis release would not have been possible without the help from the embedded Rust community, the embedded working group, and of course the esp-rs community and contributors which have heavily impacted how we\u0026rsquo;ve developed our Rust offering. I also can\u0026rsquo;t thank the Rust team at Espressif enough, they\u0026rsquo;re awesome to work with and oh so very talented! If you\u0026rsquo;re attending RustNL this year (2025) come say hi! We\u0026rsquo;ll have an Espressif booth setup, and you can catch us walking around the event too!\nIf you\u0026rsquo;re a company using (or considering) Rust on our chips, please do contact rust.support@espressif.com, we\u0026rsquo;d love to hear from you!\nThere are some binary blobs to run the Wi-Fi driver which we link to.\u0026#160;\u0026#x21a9;\u0026#xfe0e;\n","date":"24 February 2025","externalUrl":null,"permalink":"/blog/2025/02/rust-esp-hal-beta/","section":"Blog","summary":"","title":"esp-hal 1.0.0 beta announcement","type":"blog"},{"content":"ESP RainMaker is complete-yet-customizable IoT cloud platform software based on AWS Serverless architecture that simplifies the development of connected devices by providing device control and device management features. ESP RainMaker can be deployed in customers\u0026rsquo; own AWS accounts to achieve full autonomy and control for rapid development.\nThread, based on 802.15.4, is a low-power, secure, IP-based mesh networking protocol for IoT devices. It offers a secure, reliable, and scalable solution for connecting devices, enabling direct communication with each other and the Internet.\nIntroduction # Traditionally, Wi-Fi and Cellular IoT devices have relied on direct cloud connectivity to achieve autonomy in operation. With the IP capabilities of Thread networks and the evolution of Thread Border Routers enabling Internet connectivity, Thread-based devices can now achieve the same level of seamless, direct cloud communication.\nBeing in the best position to offer such a comprehensive solution, we at Espressif are excited to announce the ESP RainMaker over Thread solution. Integrating ESP RainMaker with Thread, the solution includes a device-agent SDK for both RainMaker over Thread devices and the Thread Border Router, a transparent cloud application, and iOS/Android phone apps.\nThe typical ESP RainMaker topology is shown below:\nWhy ESP RainMaker over Thread # With the ESP RainMaker over Thread solution, customers can deploy various AIoT applications, such as:\nLarge-scale networking: Supports up to 300 devices in a single network, with the ability to accommodate multiple networks within a deployment. Wide-range deployment: Multi-hop mesh networks can cover areas spanning several kilometers. Ultra-low power device: Battery-powered sensors can operate for several years. Additional benefits of using ESP RainMaker over Thread devices are:\nDirect point-to-point communication with the cloud, enabling direct remote control and device management such as cloud-based fleet management and OTA. Easy and secure network configuration with local and remote device control using phone apps. Compatibility with any Thread Border Routers that support NAT64, such as Apple HomePod and Espressif\u0026rsquo;s Thread Border Router solution. Supports a wide range of smart home device types, enabling rapid productization of Thread-based products. Thread device provisioning and control in the ESP RainMaker app:\nFeature Details # In addition to the existing ESP RainMaker over Wi-Fi solution, ESP RainMaker over Thread facilitated the introduction of several new features covered in the sections below.\nNetwork Provisioning # The new Network Provisioning component is an enhanced version of Wi-Fi Provisioning and now supports both Wi-Fi and Thread network provisioning:\nProvision Wi-Fi credentials via SoftAP or Bluetooth LE Provision Thread credentials via Bluetooth LE Thread Border Router Management # A new device type in the ESP RainMaker ecosystem is based on the ESP Thread Border Router, which supports the latest Thread 1.4 version:\nBi-directional IPv6 connectivity Service Discovery Multicast Forwarding NAT64 Credential Sharing TREL (Thread Radio Encapsulation Link) ESP RainMaker over Thread devices can communicate with other devices on the local network and the cloud through the Thread Border Router.\nLarge Scale Deployment # Thread, based on 802.15.4 as the underlying PHY and MAC layer, has bandwidth limitations that can pose challenges in large-scale deployments. For example, if too many devices within the same network attempt to generate heavy traffic—such as establishing TLS sessions with the cloud or performing OTA updates simultaneously—it can impact network connectivity and stability.\nTo ensure uninterrupted Thread communication for telemetry reporting and device control, we have implemented several solutions:\nTraffic Control\nA central device (typically the Thread BR) regulates the maximum number of devices allowed to establish TLS sessions with the cloud simultaneously.\nOTA Optimization\nThe number of simultaneous OTA sessions in a given environment needs to be limited. ESP RainMaker implements the logic to ensure managed OTA delivery to Thread devices in the environment even when devices span multiple Thread networks. When a new firmware version is available in the cloud, instead of pushing OTA notifications to all devices simultaneously, we introduced a query mechanism. This allows the cloud service to control the maximum number of parallel OTA sessions within a single network, ensuring a smoother update process.\nGroup Control # Multicast-based group control is supported for Thread devices, making it highly effective for managing large groups. For example, in a use case with 50 devices in a group, multicast control significantly reduces latency by eliminating the need to send 50 individual unicast messages.\nESP RainMaker Apps # Both the Android and iOS ESP RainMaker apps have been updated to support the new Network Provisioning feature and the Thread Border Router device type. They can be used to set up and manage ESP RainMaker Thread Border Routers and ESP RainMaker over Thread devices.\nOther Useful Links # Espressif RainMaker Espressif Thread Border Router Espressif 300x Thread Nodes Demo If you are interested in our ESP RainMaker over Thread solution, please contact our customer support team.\nApple and HomePod are trademarks of Apple Inc., registered in the U.S. and other countries and regions. ","date":"19 February 2025","externalUrl":null,"permalink":"/blog/2025/02/rainmaker-over-thread/","section":"Blog","summary":"","title":"Espressif RainMaker over Thread Solution","type":"blog"},{"content":"We are thrilled to announce the availability of the ESP-TEE (Trusted Execution Environment) framework for the ESP32-C6! Designed to enhance security on Espressif\u0026rsquo;s SoCs, ESP-TEE enables a protected execution environment to safeguard sensitive information and operations.\nThe ESP-TEE (Espressif Trusted Execution Environment) Framework The Importance of the ESP-TEE # Security is paramount in the IoT landscape, where billions of devices exchange sensitive information daily. The ESP-TEE framework empowers developers by offering:\nHardware-Enforced Isolation: The TEE ensures a secure environment where sensitive computations and data remain protected from the rest of the system (REE). Feature-Rich Security: ESP-TEE provides a comprehensive set of security features, including secure storage, secure OTA updates and attestation. Compliance with Security Certifications: The framework helps products meet the latest IoT security standards, fostering trust and reliability. Added Flexibility: Developers can separate trusted and untrusted components, improving maintainability and scalability of their solutions. Architecture # The system resources are divided into two domains:\nThe Trusted Execution Environment (TEE) - forms the secure sub-system and runs in Machine mode The Rich Execution Environment (REE) - contains the user application on top of ESP-IDF (including FreeRTOS) and runs in User mode Volume 2 of the RISC-V ISA specification, or “The Privileged Spec”, defines offered privilege levels. ESP32-C6 SoC supports 2 privilege levels: Machine (M) and User (U). Machine (M) mode being the most privileged and User (U) mode being the least.\nMachine Mode hosting TEE firmware provides secure execution environment for sensitive operations. REE application runs in the untrusted domain and interacts with the TEE firmware through the Secure Communication Interface. Hardware enforced isolation is achieved using the RISC-V architecture primitives and the security peripherals in ESP32-C6.\nWhy isolation matters # Isolation is a cornerstone of modern IoT security. By isolating sensitive operations and data in a trusted execution environment, ESP-TEE ensures that even if the main application is compromised, critical assets remain protected. This approach aligns with the latest IoT security certifications and compliance standards, making ESP-TEE an ideal choice for developing robust and secure IoT applications.\nESP-TEE in action # Imagine a smart home controller managing a variety of devices—from lighting to security cameras. The controller uses cryptographic keys to authenticate devices and encrypt communications, ensuring that only authorized components participate in the ecosystem.\nWith ESP-TEE on ESP32-C6:\nThe secure storage in TEE protects cryptographic operations and sensitive keys from unauthorized access. Computations involving sensitive keys are performed in TEE and the services are exposed to the REE through secure interface. Hardware isolation ensures that even if an untrusted component is compromised, critical data (e.g., cryptographic keys) remains safe. Compliance with IoT security standards strengthens user confidence in the system\u0026rsquo;s reliability. The result? A smart home controller that complies with stringent security certifications required in IoT, building trust with end users.\nGet Started Today # Learn More: Visit the ESP-TEE Documentation to explore the framework\u0026rsquo;s features and implementation details. Explore Examples: Find practical use cases and sample projects in the ESP-TEE Examples. Roadmap # The framework would officially be part of ESP-IDF v5.5 release for ESP32-C6 target. We plan to enable more RISC-V based Espressif SoCs with the ESP-TEE framework in the future. Secure your IoT applications today with ESP-TEE framework and build solutions that stand out in security, compliance, and user trust!\n","date":"18 February 2025","externalUrl":null,"permalink":"/blog/2025/02/announcing-esp-tee/","section":"Blog","summary":"","title":"Announcing ESP-TEE Framework for ESP32-C6","type":"blog"},{"content":"","date":"13 February 2025","externalUrl":null,"permalink":"/tags/espressif-ide/","section":"Tags","summary":"","title":"Espressif IDE","type":"tags"},{"content":"","date":"13 February 2025","externalUrl":null,"permalink":"/tags/github-copilot/","section":"Tags","summary":"","title":"GitHub Copilot","type":"tags"},{"content":"We all love GitHub Copilot as a powerful AI-powered coding assistant that enhances productivity. However, until now, it has been officially available only for VS Code and a few other editors. But here’s some good news for Eclipse users! We have tried the Copilot4Eclipse plugin with the Espressif-IDE LSP C/C++ Editor, and it works amazingly well, helping to write code faster and fix bugs.\nIntroducing Copilot4Eclipse # If you\u0026rsquo;ve been waiting for GitHub Copilot support in Eclipse, look no further than Copilot4Eclipse — a fantastic plugin that brings Copilot\u0026rsquo;s AI-assisted code generation to the Eclipse IDE. While the experience may not be identical to VS Code, Copilot4Eclipse offers similar features, making AI-assisted development possible within Eclipse.\nHow Copilot4Eclipse Enhances Development # AI-Powered Code Suggestions # Copilot4Eclipse streamlines development and boosts efficiency by generating entire functions, suggesting code completions, and refactoring snippets. It assists with boilerplate code, ESP32 API calls, and even offers intelligent improvements to your implementation—helping you write better code, faster.\nSeamless Integration with Espressif-IDE # Once you install Copilot4Eclipse in Espressif-IDE, you’ll see the Copilot menu, where you can enable GitHub Copilot suggestions. We tested Copilot4Eclipse with Espressif-IDE on ESP-IDF projects, and it worked flawlessly!\nGitHub Copilot Chat # GitHub Copilot Chat is an AI-powered coding assistant that provides real-time guidance directly within your IDE. It allows developers to choose a file, ask questions, get code explanations, debug errors, and generate code snippets—all through an interactive chat interface.\nSupport for Various Languages # Whether you\u0026rsquo;re coding in C or C++, GitHub Copilot’s AI-driven suggestions can help you write better code, faster.\nHow to Start Using Copilot4Eclipse # To get started with Copilot4Eclipse, you will need to:\nInstall the Copilot4Eclipse Plugin - Download and install the Copilot4Eclipse extension from the Eclipse Marketplace. Authenticate with GitHub - Sign in with your GitHub Copilot subscription to activate AI-powered assistance. Start Coding with AI Support - As you write code, Copilot4Eclipse provides intelligent suggestions, making coding easier and more productive. Conclusion # If you are working with Espressif-IDE or considering it for your development environment, the Copilot4Eclipse plugin can significantly enhance your productivity, help you write better code, generate boilerplate code for ESP-IDF, and assist in fixing bugs.\nGive it a try and let us know how it goes!\n","date":"13 February 2025","externalUrl":null,"permalink":"/blog/2025/02/github-copilot-in-espressif-ide/","section":"Blog","summary":"","title":"GitHub Copilot Now in Espressif-IDE with Copilot4Eclipse","type":"blog"},{"content":"","date":"13 February 2025","externalUrl":null,"permalink":"/authors/kondal-kolipaka/","section":"Developer Portal Authors","summary":"","title":"Kondal Kolipaka","type":"authors"},{"content":"","date":"17 January 2025","externalUrl":null,"permalink":"/tags/esp-idf-extension/","section":"Tags","summary":"","title":"ESP-IDF Extension","type":"tags"},{"content":"We’re excited to announce the release of the ESP-IDF VS Code Extension v1.9.0! This update brings powerful new features, performance enhancements, and numerous improvements to streamline your development experience. New Features and Improvements # Enhanced User Experience\nAdded two new interactive walkthroughs: \u0026ldquo;Basic Usage Guide\u0026rdquo; and \u0026ldquo;Advanced Features\u0026rdquo; for better user onboarding. Improved project creation from examples with enhanced UI/UX. Enhanced framework selection in examples and new projects. Optimized UX/UI for creating projects from examples. Serial Device Management\nIntroduced new configuration options for serial port filtering with idf.useSerialPortVendorProductFilter and idf.enableSerialPortChipIdRequest. Added customizable USB PID/VID filters through idf.usbSerialPortFilters. Default filtering now shows only known USB serial ports based on product and vendor IDs. Added option to disable chip ID display in serial port list. Project Configuration\nEnhanced support for multiple sdkconfig files in Project Configuration Editor with multiple profiles. Automated environment setup by computing ESP-IDF tools from IDF_PATH and IDF_TOOLS_PATH. Removed redundant configuration options in favor of automated path computation. Added notification for missing compile_commands.json file with generation option for better IntelliSense support. Improved ESP-IDF variables handling using idf_tools.py export --format key-value. Development Features\nAdded linker (ld) error display in VS Code \u0026lsquo;Problems\u0026rsquo; window (Thanks to contributor @GillesZunino). Implemented support for new ESP-IDF Size JSON format in binary analysis (ESP-IDF v5.3+). Added validation to prevent device reset during active debug sessions. Updated QEMU implementation with support for both ESP32 and ESP32-C3 targets. Enhanced telemetry reporting Bug Fixes # Fixed monitor terminal reset issues when using separate window layouts. Fixed unit tests not refreshing when using the Refresh tests button. Fixed ESP-IDF constraint file version parsing to match ESP-IDF\u0026rsquo;s naming convention (major.minor only). Fixed monitoring message display during flash failures. Fixed monitor device reset behavior during debug sessions. Fixed Docker configuration by using ESP-IDF tools version of QEMU. Check the full release notes for more detailed information.\nWe value your feedback! If you encounter any issues or have suggestions for further improvements, don’t hesitate to let us know by creating a GitHub issue.\nThank you for being part of the Espressif developer community—happy coding!\n","date":"17 January 2025","externalUrl":null,"permalink":"/blog/2025/01/release-v1-9-0/","section":"Blog","summary":"","title":"ESP-IDF VS Code Extension v1.9.0 release","type":"blog"},{"content":"","date":"17 January 2025","externalUrl":null,"permalink":"/tags/news/","section":"Tags","summary":"","title":"News","type":"tags"},{"content":"","date":"17 January 2025","externalUrl":null,"permalink":"/authors/radu-rentea/","section":"Developer Portal Authors","summary":"","title":"Radu Rentea","type":"authors"},{"content":"","date":"17 January 2025","externalUrl":null,"permalink":"/tags/visual-studio-code/","section":"Tags","summary":"","title":"Visual Studio Code","type":"tags"},{"content":"","date":"16 January 2025","externalUrl":null,"permalink":"/tags/esp-self-reflasher/","section":"Tags","summary":"","title":"ESP Self Reflasher","type":"tags"},{"content":"Migration is a word that carries a weighty importance in many contexts. It means relocation, resettling or, in case of the tech area, it could mean upgrade or replacement.\nA variety of reasons may motivate the big decision of migrating an entire piece of hardware or software from a production running system. They may range from technical to strategic purposes, frequently:\nUpdate deprecated part of the system; Better performance; Scalability; Specific desirable features; Licensing restrictions; Cost reductions; Industry standards compliance; Better support from vendor or community; Security; Also it is not uncommon to migrate to another platform out of necessity driven by constraints or issues that appear after implementation, thus choosing a flexible platform is often a good consideration when designing a solution.\nIn Embedded Systems, migration is quite an important subject that may emerge as a result of an ongoing production decision, or serve as a factor contributing to design choices at the project stage. Hardware-wise or firmware-wise, any change of that kind is risky, so it requires good planning, controlled testing, and careful execution.\nOn the firmware area, the same reasons motivate choosing a flexible platform for a project or actually migrating from a production running RTOS (Real Time Operating System) to another one.\nRelatively, changing an RTOS may not be as straight forward as a firmware update. One of the concerns that needs to be addressed beforehand is the bootloader compatibility.\nBesides initializing the system, the bootloader may be responsible for handling safe and secure firmware updates. However, it typically cannot update itself, either by design (usually due to security and safety reasons) or due to device restrictions, such as flash bootloader region protection. Also in most of the scenarios, the device is not physically accessible, thus a direct serial flashing is not practical.\nSupport for Espressif chips on platforms other than ESP-IDF, like NuttX RTOS and Zephyr RTOS keeps improving. It brings more interesting options to the table, such as offering a more flexible platform that provides more design choices or offering more flexibility in firmware migration.\nHowever there is no standard support for ESP-IDF bootloader on the mentioned RTOS, so in the case of an eventual migration from ESP-IDF to one of them, the bootloader would need to be replaced with MCUboot bootloader, for example, that is one of the options available for booting either NuttX RTOS or Zephyr RTOS on Espressif chips.\nMCUboot bootloader is an open source secure bootloader that handles fault-tolerant updates and image verification for authenticity and integrity. MCUboot was designed to provide good coverage of bootloader capabilities so it could be attractive to be ported to and used with more platforms.\nHowever, as said before, migration is driven by variable reasons according to each project, thus it is not the goal of this article to discuss or compare each platform.\nThis tutorial aims to demonstrate how ESP Self-Reflasher component can be used to migrate an ESP-IDF-bootloader-based application (OTA capable) to an MCUboot-based-bootloader application in case of an eventual need. The ESP Self-Reflasher component is used as a middle step application for enabling the device to \u0026ldquo;reflash\u0026rdquo; its own firmware.\nThe MCUboot-compatible application in this guide is a NuttX RTOS application but could also be a Zephyr RTOS application. The overall process described in this guide can be illustrated as:\nflowchart LR A[ESP-IDF bootloader + ESP-IDF application with OTA capabilities] --\u003e|OTA\nprocess| B[Reflashing application with ESP Self-Reflasher component] B --\u003e|Reflashing\nprocess| C(MCUboot bootloader + NuttX application) ESP Self-Reflasher component # The ESP Self-Reflasher is an ESP-IDF component that allows the device to be \u0026ldquo;reflashed\u0026rdquo; with new firmware. This is achieved through one of the following ways of operation:\nDownloading the reflashing image Embedding the reflashing image The component has examples for each way of operation. Both will be used in this guide.\nEnvironment prerequisites # Besides ESP-IDF (see ESP-IDF Getting Started), the following is required:\nESP Self-Reflasher examples: as shown in this guide, it is possible to create local copies of the ESP Self-Reflasher examples:\nidf.py create-project-from-example \u0026#39;espressif/esp-self-reflasher:boot_swap_download_example\u0026#39; idf.py create-project-from-example \u0026#39;espressif/esp-self-reflasher:boot_swap_embedded_example\u0026#39; ESP Self-Reflasher component can also be installed into a project via the ESP-IDF Component Manager:\nidf.py add-dependency \u0026#34;espressif/esp-self-reflasher\u0026#34; idf.py reconfigure NuttX: in order to build the application that will be migrated to, set the NuttX workspace. See NuttX Getting Started.\nMCUboot: in the case of building the bootloader standalone, follow the instructions here.\nStep-by-step guide # Build the reflashing images (MCUboot and NuttX application) # With the NuttX workspace ready, prepare the NSH (NuttShell) configuration with MCUboot compatibility, which is available under the mcuboot_nsh defconfig (premade application configuration for a board, more information here). This is the build that will be used as the final target of the reflashing process.\ncd \u0026lt;NUTTX_DIR\u0026gt; ./tools/configure.sh esp32-devkitc:mcuboot_nsh You can also manually configure other NuttX applications to be built with MCUboot compatibility:\nIn your NuttX workspace, enter the menuconfig: make menuconfig In the menu System Type -\u0026gt; Bootloader and Image Configuration, enable the option Enable MCUboot-bootable format Ensure that the flash image map (organization of image slots in flash) is properly configured in menuconfig -\u0026gt; System Type -\u0026gt; SPI Flash Configuration from menuconfig. For this example using the ESP32, the following flash image map is considered (note that the Bootloader offset may differ among other Espressif chip families):\nREGION OFFSET SIZE Bootloader 0x001000 0x00F000 Application primary slot 0x010000 0x100000 Application secondary slot 0x110000 0x100000 Scratch 0x210000 0x040000 If MCUboot is built separately from the NuttX build, make sure that both have a matching flash image map. Navigate to the menuconfig Exit and, when prompted, save the current settings.\nBuild the MCUboot bootloader:\nmake -j bootloader Now build the NuttX application:\nmake ESPTOOL_BINDIR=./ -s -j Build the reflashing application # Example 1: Download the target reflashing image # The ESP Self-Reflasher component provides the example boot_swap_download_example. This can be used as a starting point for the reflashing application.\nNavigate to a directory of your choice and create a local copy from the boot_swap_download_example.\nidf.py create-project-from-example \u0026#39;espressif/esp-self-reflasher:boot_swap_download_example\u0026#39; cd \u0026lt;SAMPLE_DIR\u0026gt;/boot_swap_download_example/ First, copy the final target images (NuttX and MCUboot binaries) to the directory that will be served for HTTP download.\ncp \u0026lt;NUTTX_DIR\u0026gt;/nuttx.bin \u0026lt;SAMPLE_DIR\u0026gt;/boot_swap_download_example/example_bin_dir/app_upd.bin cp \u0026lt;NUTTX_DIR\u0026gt;/mcuboot-esp32.bin \u0026lt;SAMPLE_DIR\u0026gt;/boot_swap_download_example/example_bin_dir/mcuboot-esp32.bin Configure the example:\nidf.py menuconfig Enter menu Example Configuration -\u0026gt; Bootloader reflash configuration and set the Bootloader bin url endpoint with the host IP, port and the bootloader binary name (e.g. http://192.168.0.100:8070/mcuboot-esp32.bin):\nhttp://\u0026lt;HOST_IP\u0026gt;:\u0026lt;HOST_PORT\u0026gt;/mcuboot-esp32.bin Then configure the similar parameters on the Example Configuration -\u0026gt; Application reflash configuration menu, set the Application upgrade url endpoint (e.g. http://192.168.0.100:8070/app_upd.bin):\nhttp://\u0026lt;HOST_IP\u0026gt;:\u0026lt;HOST_PORT\u0026gt;/app_upd.bin Also configure the Bootloader region address (the Bootloader offset mentioned above) and the Bootloader region size.\nSet the Application region address and Application region size. Note that if the boot_swap_download_example is flashed standalone directly as is, these must match the image Secondary Slot from the target MCUboot image organization as the example expects MCUboot to do the swapping to the Primary Slot later, otherwise, if the example is OTA upgraded which this tutorial walk through, these configs must match Primary Slot. It will depend on where the reflashing application is running from (Factory partition or OTA partition), as it should not overwrite itself on the process.\nConfigure the preferred network connection settings on the menu Example Connection Configuration, such as Wi-Fi SSID and Password.\nNavigate to the menuconfig Exit and, when prompted, save the current settings.\nBuild the example:\nidf.py build Example 2: Embed the target reflashing image # Alternatively, ESP Self-Reflasher component can be used without network connection and download step, however as using this way the \u0026ldquo;bootloader + target reflashing image\u0026rdquo; will be embedded on the reflashing application, it must not exceed the total size that the first OTA supports.\nIf the constraint is not a problem, boot_swap_embedded_example can be used as start point for the reflashing application. Note that for this guide, the size of the OTA partitions on the partition table may be changed (see next section).\nNavigate to a directory of your choice and create a local copy from the boot_swap_embedded_example.\nidf.py create-project-from-example \u0026#39;espressif/esp-self-reflasher:boot_swap_embedded_example\u0026#39; cd \u0026lt;SAMPLE_DIR\u0026gt;/boot_swap_embedded_example/ In this example, the MCUboot bootloader and target reflashing image needs to be merged in one binary as it goes embedded to the application.\nesptool.py -c esp32 merge_bin --output \u0026lt;SAMPLE_DIR\u0026gt;/boot_swap_embedded_example/example_bin_dir/app_upd.merged.bin 0x0000 \u0026lt;NUTTX_DIR\u0026gt;/mcuboot-esp32.bin 0xF000 \u0026lt;NUTTX_DIR\u0026gt;/nuttx.bin Note: In ESP32 case, the offsets on the merge step are shifted minus 0x1000 because of its bootloader offset 0x1000.\nConfigure the example:\nidf.py menuconfig Enter menu Example Configuration and set the directory where the merged binary is placed and its name. Set the Destination address, that for this example will be the Bootloader offset, and the Destination region size, that must be the image slot size from the target flash organization plus the bootloader region size.\nNavigate to the menuconfig Exit and, when prompted, save the current settings.\nBuild the example:\nidf.py build Build and flash the ESP-IDF application # The ESP-IDF\u0026rsquo;s simple_ota_example will be used as the hypothetical ESP-IDF application that will OTA to the reflashing application. The steps are basically the same as described on its documentation, with few changes.\nNavigate to the example directory.\ncd \u0026lt;IDF_DIR\u0026gt;/examples/system/ota/simple_ota_example/ Set the target chip:\nidf.py set-target esp32 Set the configurations for the example:\nidf.py menuconfig In the Example Configuration menu, set the firmware upgrade url endpoint with the host IP, port and the Reflasher application binary name (e.g. http://192.168.0.100:8070/boot_swap_download.bin):\nhttp://\u0026lt;HOST_IP\u0026gt;:\u0026lt;HOST_PORT\u0026gt;/\u0026lt;reflashing_application_name\u0026gt;.bin In the Example Connection Configuration menu, again set the preferred network connection settings, such as Wi-Fi SSID and Password.\nOnly for illustration purposes, this guide is using simple HTTP requests, so enable the Allow HTTP for OTA option in the Component config -\u0026gt; ESP HTTPS OTA.\nNote: If the boot_swap_embedded_example was used, define a custom partition table in Partition table menu. Create the partitions.csv file with the following content:\n# Name, Type, SubType, Offset, Size, Flags nvs, data, nvs, , 0x4000, otadata, data, ota, , 0x2000, phy_init, data, phy, , 0x1000, factory, app, factory, 0x10000, 0x180000, ota_0, app, ota_0, , 0x180000, Navigate to the menuconfig Exit and, when prompted, save the current settings.\nCopy the reflashing application binary that was build in the previous section to the directory where the HTTP server will run:\ncp \u0026lt;SAMPLE_DIR\u0026gt;/boot_swap_\u0026lt;MODE\u0026gt;_example/build/boot_swap_\u0026lt;MODE\u0026gt;_example.bin \u0026lt;HTTP_SERVER_DIR\u0026gt; Open a new bash and start the HTTP server for the OTA application. Here is a suggestion for creating the HTTP server using Python:\ncd \u0026lt;HTTP_SERVER_DIR\u0026gt; sudo python -m http.server -b \u0026lt;HOST_IP\u0026gt; \u0026lt;HOST_PORT\u0026gt; # e.g. sudo python -m http.server -b 192.168.0.100 8070 Note: If the boot_swap_download_example was used, copy the target reflashing images to the \u0026lt;HTTP_SERVER_DIR\u0026gt; or open another bash and start the HTTP server from where the reflashing images will be downloaded (watch for the that cannot be the same):\ncd \u0026lt;SAMPLE_DIR\u0026gt;/boot_swap_download_example/example_bin_dir/ sudo python -m http.server -b \u0026lt;HOST_IP\u0026gt; \u0026lt;HOST_PORT\u0026gt; # e.g. sudo python -m http.server -b 192.168.0.100 8071 Finally build and flash the OTA application:\nidf.py -p \u0026lt;SERIAL_PORT\u0026gt; flash monitor # e.g. idf.py -p /dev/ttyUSB0 flash monitor Execution output # Now that everything is properly build and set, after flashing the OTA application the console output will be similar as the following (check the section related to the example you chose to build):\nboot_swap_download_example # Note: Some Wifi and other common console log outputs are ommited.\nClick here to view I (29) boot: ESP-IDF v5.1.4 2nd stage bootloader I (29) boot: compile time Jan 14 2025 01:06:52 I (29) boot: Multicore bootloader I (34) boot: chip revision: v3.0 I (37) boot.esp32: SPI Speed : 40MHz I (42) boot.esp32: SPI Mode : DIO I (47) boot.esp32: SPI Flash Size : 4MB I (51) boot: Enabling RNG early entropy source... I (57) boot: Partition Table: I (60) boot: ## Label Usage Type ST Offset Length I (67) boot: 0 nvs WiFi data 01 02 00009000 00004000 I (75) boot: 1 otadata OTA data 01 00 0000d000 00002000 I (82) boot: 2 phy_init RF data 01 01 0000f000 00001000 I (90) boot: 3 factory factory app 00 00 00010000 00100000 I (97) boot: 4 ota_0 OTA app 00 10 00110000 00100000 I (105) boot: 5 ota_1 OTA app 00 11 00210000 00100000 I (112) boot: End of partition table ... I (505) cpu_start: Application information: I (510) cpu_start: Project name: simple_ota ... I (613) main_task: Calling app_main() I (613) simple_ota_example: OTA example app_main start ... I (863) example_connect: Start example_connect. ... I (1053) example_connect: Connecting to Home... I (1063) example_connect: Waiting for IP(s) ... I (4863) example_connect: Got IPv6 event: Interface \u0026#34;example_netif_sta\u0026#34; address: fe80:0000:0000:0000:c6dd:57ff:fe5f:2b04, type: ESP_IP6_ADDR_IS_LINK_LOCAL I (6763) esp_netif_handlers: example_netif_sta ip: 192.168.100.100, mask: 255.255.255.0, gw: 192.168.100.1 I (6763) example_connect: Got IPv4 event: Interface \u0026#34;example_netif_sta\u0026#34; address: 192.168.100.100 I (6773) example_common: Connected to example_netif_sta I (6773) example_common: - IPv4 address: 192.168.100.100, I (6783) example_common: - IPv6 address: fe80:0000:0000:0000:c6dd:57ff:fe5f:2b04, type: ESP_IP6_ADDR_IS_LINK_LOCAL ... I (6793) simple_ota_example: Starting OTA example task I (6803) simple_ota_example: Attempting to download update from http://192.168.100.101:8070/boot_swap_download.bin I (6823) main_task: Returned from app_main() I (6943) esp_https_ota: Starting OTA... I (6943) esp_https_ota: Writing to partition subtype 16 at offset 0x110000 ... I (22823) simple_ota_example: OTA Succeed, Rebooting... ... ets Jul 29 2019 12:21:46 rst:0xc (SW_CPU_RESET),boot:0x12 (SPI_FAST_FLASH_BOOT) configsip: 0, SPIWP:0xee clk_drv:0x00,q_drv:0x00,d_drv:0x00,cs0_drv:0x00,hd_drv:0x00,wp_drv:0x00 mode:DIO, clock div:2 load:0x3fff0030,len:7112 load:0x40078000,len:15624 load:0x40080400,len:4 load:0x40080404,len:3876 entry 0x4008064c I (29) boot: ESP-IDF v5.1.4 2nd stage bootloader I (29) boot: compile time Jan 14 2025 01:06:52 I (29) boot: Multicore bootloader I (33) boot: chip revision: v3.0 I (37) boot.esp32: SPI Speed : 40MHz I (42) boot.esp32: SPI Mode : DIO I (46) boot.esp32: SPI Flash Size : 4MB I (51) boot: Enabling RNG early entropy source... I (56) boot: Partition Table: I (60) boot: ## Label Usage Type ST Offset Length I (67) boot: 0 nvs WiFi data 01 02 00009000 00004000 I (75) boot: 1 otadata OTA data 01 00 0000d000 00002000 I (82) boot: 2 phy_init RF data 01 01 0000f000 00001000 I (90) boot: 3 factory factory app 00 00 00010000 00100000 I (97) boot: 4 ota_0 OTA app 00 10 00110000 00100000 I (105) boot: 5 ota_1 OTA app 00 11 00210000 00100000 I (112) boot: End of partition table ... I (498) cpu_start: Application information: I (502) cpu_start: Project name: boot_swap_download ... I (607) main_task: Calling app_main() I (607) boot_swap_download_example: Self Reflasher example app_main start I (627) example_connect: Start example_connect. ... I (797) example_connect: Connecting to Home... I (807) example_connect: Waiting for IP(s) ... I (4627) example_connect: Got IPv6 event: Interface \u0026#34;example_netif_sta\u0026#34; address: fe80:0000:0000:0000:c6dd:57ff:fe5f:2b04, type: ESP_IP6_ADDR_IS_LINK_LOCAL I (6497) esp_netif_handlers: example_netif_sta ip: 192.168.100.100, mask: 255.255.255.0, gw: 192.168.100.1 I (6497) example_connect: Got IPv4 event: Interface \u0026#34;example_netif_sta\u0026#34; address: 192.168.100.100 I (6507) example_common: Connected to example_netif_sta I (6507) example_common: - IPv4 address: 192.168.100.100, I (6517) example_common: - IPv6 address: fe80:0000:0000:0000:c6dd:57ff:fe5f:2b04, type: ESP_IP6_ADDR_IS_LINK_LOCAL ... I (6527) boot_swap_download_example: Starting Self Reflasher example task I (6537) self_reflasher: src_start 0x00210000 src_end 0x00310000 dest_start 0x00010000 dest_end 0x00110000 I (6787) main_task: Returned from app_main() I (10497) self_reflasher: Partition erased successfully I (15327) self_reflasher: Connection closed I (15327) self_reflasher: Total downloaded binary length: 1048576 (0x100000) I (15327) self_reflasher: File downloaded successfully I (15337) self_reflasher: Starting copy 0x00100000 bytes from address 0x00210000 to address 0x00010000 I (19137) self_reflasher: Flash destination region erased successfully I (21677) self_reflasher: Data copied from partition address 0x00210000 offset 0x00000000 to region: 0x00010000 I (21677) self_reflasher: Updating configuration for next download I (21687) self_reflasher: Current selected partition for download placement will be erased I (25617) self_reflasher: Partition erased successfully I (25807) self_reflasher: Connection closed I (25807) self_reflasher: Total downloaded binary length: 27376 (0x6af0) I (25807) self_reflasher: File downloaded successfully I (25817) self_reflasher: Starting copy 0x00006af0 bytes from address 0x00210000 to address 0x00001000 I (26417) self_reflasher: Flash destination region erased successfully I (26527) self_reflasher: Data copied from partition address 0x00210000 offset 0x00000000 to region: 0x00001000 I (26527) boot_swap_download_example: MCUboot+Image overwritting succeed, Rebooting... ... ets Jul 29 2019 12:21:46 rst:0xc (SW_CPU_RESET),boot:0x12 (SPI_FAST_FLASH_BOOT) configsip: 0, SPIWP:0xee clk_drv:0x00,q_drv:0x00,d_drv:0x00,cs0_drv:0x00,hd_drv:0x00,wp_drv:0x00 mode:DIO, clock div:2 load:0x3fff7c98,len:6176 load:0x40078000,len:13312 load:0x40090000,len:7804 entry 0x4007b3b0 [esp32] [INF] *** Booting MCUboot build v1.10.0-131-gb206b99b *** [esp32] [INF] [boot] chip revision: v3.0 [esp32] [INF] [boot.esp32] SPI Speed : 40MHz [esp32] [INF] [boot.esp32] SPI Mode : DIO [esp32] [INF] [boot.esp32] SPI Flash Size : 4MB [esp32] [INF] [boot] Enabling RNG early entropy source... [esp32] [INF] Primary image: magic=good, swap_type=0x1, copy_done=0x3, image_ok=0x1 [esp32] [INF] Scratch: magic=unset, swap_type=0x1, copy_done=0x3, image_ok=0x3 [esp32] [INF] Boot source: primary slot [esp32] [INF] Image index: 0, Swap type: none [esp32] [INF] Disabling RNG early entropy source... [esp32] [INF] br_image_off = 0x10000 [esp32] [INF] ih_hdr_size = 0x20 [esp32] [INF] Loading image 0 - slot 0 from flash, area id: 1 [esp32] [INF] DRAM segment: start=0x146dc, size=0x2e4, vaddr=0x3ffb1ee0 [esp32] [INF] IRAM segment: start=0x129f8, size=0x1ce4, vaddr=0x40080000 [esp32] [INF] start=0x400818ec IROM segment aligned lma 0x00020000 vma 0x400d0000 len 0x011b18 (72472) DROM segment aligned lma 0x00010000 vma 0x3f400000 len 0x0029b8 (10680) NuttShell (NSH) NuttX-10.4.0 nsh\u0026gt; boot_swap_embedded_example # Note: Some Wifi and other common console log outputs are ommited.\nClick here to view I (29) boot: ESP-IDF v5.1.4 2nd stage bootloader I (29) boot: compile time Jan 14 2025 00:49:05 I (29) boot: Multicore bootloader I (34) boot: chip revision: v3.0 I (37) boot.esp32: SPI Speed : 40MHz I (42) boot.esp32: SPI Mode : DIO I (47) boot.esp32: SPI Flash Size : 4MB I (51) boot: Enabling RNG early entropy source... I (57) boot: Partition Table: I (60) boot: ## Label Usage Type ST Offset Length I (67) boot: 0 nvs WiFi data 01 02 00009000 00004000 I (75) boot: 1 otadata OTA data 01 00 0000d000 00002000 I (82) boot: 2 phy_init RF data 01 01 0000f000 00001000 I (90) boot: 3 factory factory app 00 00 00010000 00180000 I (97) boot: 4 ota_0 OTA app 00 10 00190000 00180000 I (105) boot: End of partition table ... I (606) simple_ota_example: OTA example app_main start ... I (866) example_connect: Start example_connect. ... I (1046) example_connect: Connecting to Home... I (1046) example_connect: Waiting for IP(s) ... I (4866) example_connect: Got IPv6 event: Interface \u0026#34;example_netif_sta\u0026#34; address: fe80:0000:0000:0000:c6dd:57ff:fe5f:2b04, type: ESP_IP6_ADDR_IS_LINK_LOCAL I (6736) esp_netif_handlers: example_netif_sta ip: 192.168.100.100, mask: 255.255.255.0, gw: 192.168.100.1 I (6736) example_connect: Got IPv4 event: Interface \u0026#34;example_netif_sta\u0026#34; address: 192.168.100.100 I (6746) example_common: Connected to example_netif_sta I (6746) example_common: - IPv4 address: 192.168.100.100, I (6756) example_common: - IPv6 address: fe80:0000:0000:0000:c6dd:57ff:fe5f:2b04, type: ESP_IP6_ADDR_IS_LINK_LOCAL ... I (6766) simple_ota_example: Starting OTA example task I (6776) simple_ota_example: Attempting to download update from http://192.168.100.101:8070/boot_swap_embedded.bin I (6796) main_task: Returned from app_main() I (6886) esp_https_ota: Starting OTA... I (6896) esp_https_ota: Writing to partition subtype 16 at offset 0x190000 I (26356) esp_image: segment 0: paddr=00190020 vaddr=3f400020 size=1174b8h (1143992) map I (26696) esp_image: segment 1: paddr=002a74e0 vaddr=3ffb0000 size=036e8h ( 14056) I (26706) esp_image: segment 2: paddr=002aabd0 vaddr=40080000 size=05448h ( 21576) I (26706) esp_image: segment 3: paddr=002b0020 vaddr=400d0020 size=12ab0h ( 76464) map I (26736) esp_image: segment 4: paddr=002c2ad8 vaddr=40085448 size=0805ch ( 32860) I (26756) esp_image: segment 0: paddr=00190020 vaddr=3f400020 size=1174b8h (1143992) map I (27096) esp_image: segment 1: paddr=002a74e0 vaddr=3ffb0000 size=036e8h ( 14056) I (27106) esp_image: segment 2: paddr=002aabd0 vaddr=40080000 size=05448h ( 21576) I (27116) esp_image: segment 3: paddr=002b0020 vaddr=400d0020 size=12ab0h ( 76464) map I (27136) esp_image: segment 4: paddr=002c2ad8 vaddr=40085448 size=0805ch ( 32860) I (27196) simple_ota_example: OTA Succeed, Rebooting... ... ets Jul 29 2019 12:21:46 rst:0xc (SW_CPU_RESET),boot:0x12 (SPI_FAST_FLASH_BOOT) configsip: 0, SPIWP:0xee clk_drv:0x00,q_drv:0x00,d_drv:0x00,cs0_drv:0x00,hd_drv:0x00,wp_drv:0x00 mode:DIO, clock div:2 load:0x3fff0030,len:7112 load:0x40078000,len:15624 load:0x40080400,len:4 load:0x40080404,len:3876 entry 0x4008064c I (29) boot: ESP-IDF v5.1.4 2nd stage bootloader I (29) boot: compile time Jan 14 2025 00:49:05 I (29) boot: Multicore bootloader I (33) boot: chip revision: v3.0 I (37) boot.esp32: SPI Speed : 40MHz I (42) boot.esp32: SPI Mode : DIO I (46) boot.esp32: SPI Flash Size : 4MB I (51) boot: Enabling RNG early entropy source... I (56) boot: Partition Table: I (60) boot: ## Label Usage Type ST Offset Length I (67) boot: 0 nvs WiFi data 01 02 00009000 00004000 I (75) boot: 1 otadata OTA data 01 00 0000d000 00002000 I (82) boot: 2 phy_init RF data 01 01 0000f000 00001000 I (90) boot: 3 factory factory app 00 00 00010000 00180000 I (97) boot: 4 ota_0 OTA app 00 10 00190000 00180000 I (105) boot: End of partition table ... I (625) cpu_start: Application information: I (629) cpu_start: Project name: boot_swap_embedded ... I (734) boot_swap_embedded_example: Boot swap embedded bin example start I (744) self_reflasher: Starting copy 0x0010f000 bytes from address 0x001941bc to address 0x00001000 I (12934) self_reflasher: Data copied from address 0x001941bc to region: 0x00001000 I (12934) boot_swap_embedded_example: Overwritting succeed, Rebooting... ets Jul 29 2019 12:21:46 rst:0xc (SW_CPU_RESET),boot:0x12 (SPI_FAST_FLASH_BOOT) configsip: 0, SPIWP:0xee clk_drv:0x00,q_drv:0x00,d_drv:0x00,cs0_drv:0x00,hd_drv:0x00,wp_drv:0x00 mode:DIO, clock div:2 load:0x3fff7c98,len:6176 load:0x40078000,len:13312 load:0x40090000,len:7804 entry 0x4007b3b0 [esp32] [INF] *** Booting MCUboot build v1.10.0-131-gb206b99b *** [esp32] [INF] [boot] chip revision: v3.0 [esp32] [INF] [boot.esp32] SPI Speed : 40MHz [esp32] [INF] [boot.esp32] SPI Mode : DIO [esp32] [INF] [boot.esp32] SPI Flash Size : 4MB [esp32] [INF] [boot] Enabling RNG early entropy source... [esp32] [INF] Primary image: magic=good, swap_type=0x1, copy_done=0x3, image_ok=0x1 [esp32] [INF] Scratch: magic=unset, swap_type=0x1, copy_done=0x3, image_ok=0x3 [esp32] [INF] Boot source: primary slot [esp32] [INF] Image index: 0, Swap type: none [esp32] [INF] Disabling RNG early entropy source... [esp32] [INF] br_image_off = 0x10000 [esp32] [INF] ih_hdr_size = 0x20 [esp32] [INF] Loading image 0 - slot 0 from flash, area id: 1 [esp32] [INF] DRAM segment: start=0x146dc, size=0x2e4, vaddr=0x3ffb1ee0 [esp32] [INF] IRAM segment: start=0x129f8, size=0x1ce4, vaddr=0x40080000 [esp32] [INF] start=0x400818ec IROM segment aligned lma 0x00020000 vma 0x400d0000 len 0x011b18 (72472) DROM segment aligned lma 0x00010000 vma 0x3f400000 len 0x0029b8 (10680) NuttShell (NSH) NuttX-10.4.0 nsh\u0026gt; Conclusion # This article demonstrated how to configure and build the ESP Self-Reflasher examples and walked through their use, starting from an ESP-IDF OTA application, updating to one of the examples, replacing ESP-IDF\u0026rsquo;s bootloader and application with MCUboot bootloader and NuttX application respectively and finally reaching the NuttX application execution.\nThe ESP Self-Reflasher component may help on the process of migrating an ESP32-xx device from an ESP-IDF application to other MCUboot compatible platform, however it is strongly recommended to observe the already enabled constraints of a device beforehand and also to plan carefully as it uses risky flash operations.\n","date":"16 January 2025","externalUrl":null,"permalink":"/blog/2025/01/how-to-migrate-from-idf-bootloader-to-mcuboot-using-esp-self-reflasher/","section":"Blog","summary":"","title":"How to migrate from IDF Bootloader to MCUboot using ESP Self-Reflasher","type":"blog"},{"content":"","date":"6 January 2025","externalUrl":null,"permalink":"/tags/wled/","section":"Tags","summary":"","title":"WLED","type":"tags"},{"content":"Making amazing lighting installations might seem very complex, requiring a lot of expensive hardware and software. However, it can\u0026rsquo;t be further from the truth. With an ESP32 or ESP8266 at hand and with the help of some software from our wonderful community, this is not that complex. Try it yourself, and you will be pleasantly surprised.\nToday we will talk about a community project, created by Christian Schwinne a.k.a Aircoookie, called WLED.\nWLED # WLED is an open-source solution to control addressable LEDs based on the Arduino core for the ESP32 and ESP8266. It implements a web server to control the LED segments, creating a unique experience. WLED supports many outstanding features that allow you to create different lighting effects and advanced configurations, including various control interfaces, firmware upgrades OTA, scheduling, and much more. WLED is only compatible with addressable LEDs, including addressable RGBW. Please note that non-addressable RGB LEDs are not supported. For the full list of features, please visit the WLED documentation page.\nHow to use # WLED can be used in many different ways, from lighting up a single LED strip (1D) to driving a whole LED matrix (2D). This allows you to create visual scenes in both 1D or 2D, using custom color palettes, special visual effects (currently 117 different ones), multiple segments, and macros.\nTo get started with WLED you will need one of the supported ESP32s, a power supply, and at least one addressable LED strip.\nCurrently, WLED supports the following Espressif SoCs:\nESP8266 ESP32 ESP32-S2 (experimental) ESP32-S3 (experimental) ESP32-C3 (experimental) The easiest way to get started is by flashing the WLED firmware using the online flashing tool, called the WLED web installer. This tool is only compatible with Chrome and Edge (desktop versions), and the only thing you will need is a USB cable connected to your ESP board.\nFlashing the firmware will only take a few minutes. No previous installation is required. After flashing, you can connect to the WLED device via Wi-Fi AP SSID called WLED-AP with the password wled1234, and then you will be able to open the web interface at the IP address 4.3.2.1 or wled.me.\nOnce you have access to the WLED web interface, you will need to configure your Wi-Fi (if you want to control it via your local network), the LED strip settings, and then create effects presets and a playlist.\nThe web interface # The web interface is very intuitive and easy to use. You can use it to do almost all the configuration required to get the WLED working with your LED strip.\nWLED web interface - Welcome WLED web interface - Control WLED web interface - Configuration Mobile application # To get easy access to all WLED instances in your local network, you can use the mobile application:\nAndroid iOS Next steps # The WLED website provides an outstanding getting started guide that will show you everything you need to know about the project and how to start your own WLED application. You can also find an extensive list of tutorials from the very active community.\nTo explore more options, interfaces, integration, and more, do take a deeper look into the WLED site!\nHardware # To test the WLED project, we chose the ESP32-C3-Lyra V2.0 due to a number of features that simplify integration with LED strips.\nFirst and foremost, as you can see in the overview of components below, this board integrates two interfaces for LED strips:\nAddressable LED strip port (supported by WLED and used during testing) RGB LED strip port (not supported by WLED) A 12V DC power port connector allows for direct use of 12V LED strips. It means that only one power supply is needed to power both the ESP32-C3 and the LEDs.\nIn addition, this board integrates a microphone for sound reactivity and an IR receiver for remote control; however, we didn\u0026rsquo;t try these features during our tests.\nESP32-C3-Lyra V2.0 ESP32-C3-Lyra overview of components # ESP32-C3-Lyra overview of components ESP32-C3-Lyra is an ESP32-C3-based audio development board produced by Espressif for controlling light with audio. The board has control over the microphone, speaker, and LED strip, perfectly matching customers’ product development needs for ultra-low-cost and high-performance audio broadcasters and rhythm light strips.\nAs mentioned before, the support for the ESP32-C3 is still experimental, but you can use it for testing purposes.\nConclusion # WLED is one of the most popular community projects based on the Arduino core that uses the ESP32 and the ESP8266 and it\u0026rsquo;s actively maintained by the community. The project offers very intuitive documentation, making it easy for everyone to use the project without the need of creating the build environment or dealing with complex setup.\nThanks to all the project contributors for giving such an amazing solution for controlling LEDs.\nReferences # WLED official site\nWLED GitHub repo\nTop 5 Mistakes with WLED\n","date":"6 January 2025","externalUrl":null,"permalink":"/blog/2025/01/wled-powered-by-the-community/","section":"Blog","summary":"","title":"WLED - Powered by the Community","type":"blog"},{"content":"Although ESP32 SoCs typically feature a few hundred kilobytes of internal SRAM, some embedded IoT applications—such as those featuring sophisticated graphical user interfaces, handling large data volumes, or performing complex data processing—may require much more RAM. To meet these demands, Espressif provides modules that feature external PSRAM.\nIn this article, you will learn how to configure Zephyr to enable your application to take full advantage of the PSRAM available on ESP32 modules. We will explore three different strategies for utilizing this PSRAM: using it for dynamic memory allocation, adding it to your ESP32 memory map, and running code from PSRAM instead of Flash.\nGetting Started # Before we start, let’s first understand exactly what PSRAM stands for and what it really is. The acronym PSRAM stands for pseudo-static random-access memory. It is a type of dynamic random-access memory (DRAM) that includes additional circuitry to handle memory cell refresh automatically, while DRAM requires an external memory controller to refresh the cell memory charge. This additional circuitry allows PSRAM to keep the cost close to DRAM but provides ease of use and high speed similar to static random-access memory (SRAM).\nPSRAM is typically accessible via high-speed serial buses, and some ESP32 series SoCs can communicate with PSRAM and map its contents into the CPU\u0026rsquo;s virtual memory space through a memory management unit (MMU).\nIn a simplified way, we can describe the relationship among PSRAM, the MMU, and the CPU as follows:\nData is automatically copied from PSRAM to the data cache when the CPU attempts to access a memory position not currently in the cache.\nConversely, when CPU modifies data in the cache, the updated contents are copied back to PSRAM.\nAt the time of writing, while many ESP32 SoCs support external PSRAM, not all of them are supported on Zephyr yet.\nSoC series PSRAM capable Currently supported on Zephyr ESP32 yes yes ESP32-S2 yes yes ESP32-S3 yes yes ESP32-C5 yes no ESP32-C61 yes no ESP32-P4 yes no What Are ESP32 Modules and PSRAM? # To know which ESP32 modules contain PSRAM, we have to understand the module naming nomenclature. As an example, let’s look at the module whose name is ESP32-S3-WROOM-1-N8R8\nField Contents Meaning SoC series ESP32-S3 ESP32-S3 SoC series flash size N8 8 MB PSRAM size R8 8 MB If a module does not contain PSRAM, the R field is absent.\nAdditional resources for deciphering product nomenclatures can be found in a chip datasheet and module datasheet of a respective series. For example, see the ESP32-S3 series chip datasheet and module datasheet.\nUsing PSRAM with Custom ESP32 Hardware # Although Espressif offers modules featuring PSRAM across various ESP32 SoC series, there may be cases where custom hardware must be developed to meet specific requirements, such as PSRAM capacity or the SPI interface bus width, which impacts the time for each memory operation and overall data access speed. Additionally, there may be other reasons unrelated to PSRAM that necessitate custom hardware.\nIn this case, PSRAM will share data I/O and clock lines with external flash memory, but not chip-select line. PSRAM and flash have separate chip select lines (for example, see the ESP32-S3 Chip Datasheet). For information on how to connect off-package PSRAM lines, the respective SoC datasheet must be consulted.\nThe following SPI modes are supported to access external PSRAM memories:\nSingle SPI Dual SPI Quad SPI QPI Octo SPI OPI There are limits regarding the maximum PSRAM capacity that each ESP32 SoC series can manage. As an example, ESP32-S3 can manage PSRAMs up to 32 MB.\nEspressif currently offers some PSRAM models:\nPart number Memory Capacity Operating Voltage ESP-PSRAM32 4 MB 1.8V ESP-PSRAM32H 4 MB 3.3V ESP-PSRAM64 8 MB 1.8V ESP-PSRAM64H 8 MB 3.3V How to Set Up PSRAM in Zephyr # The Kconfig parameters related to PSRAM usage in Zephyr can be found in zephyr/soc/espressif/commom/Kconfig.spiram\nBelow are the main parameters related to PSRAM, along with a brief description of each:\nESP_SPIRAM: This configuration parameter enables support for an external SPI RAM chip, connected in parallel with the main SPI flash chip. If enabled, it automatically enables SHARED_MULTI_HEAP.\nESP_SPIRAM_HEAP_SIZE: This configuration parameter specifies SPIRAM heap size.\nESP_SPIRAM_MEMTEST: This configuration parameter controls SPIRAM memory test during initialization. It is enabled by default and can be disabled for faster startup.\nSPIRAM_MODE: This configuration parameter selects the mode of SPI RAM chip in use. The permitted values are SPIRAM_MODE_QUAD and SPIRAM_MODE_OCT. Please note that SPIRAM_MODE_OCT is only available in ESP32-S3.\nSPIRAM_TYPE: This configuration parameter defines the type of SPIRAM chip in use:\nSPIRAM_SPEED: This configuration parameter sets the SPIRAM clock speed in MHz:\nValue Clock speed SPIRAM_SPEED_20M 20 MHz SPIRAM_SPEED_26M 26 MHz SPIRAM_SPEED_40M 40 MHz SPIRAM_SPEED_80M 80 MHz SPIRAM_SPEED_120M 120 MHz SPIRAM_FETCH_INSTRUCTIONS: This configuration parameter allows moving instructions from flash to PSRAM. If enabled, instructions in flash will be moved into PSRAM on startup. If SPIRAM_RODATA parameter is also enabled, the code that normally requires execution during the SPI1 flash operation does not need to be placed in IRAM, thus optimizing RAM usage. By default, this parameter is disabled.\nSPIRAM_RODATA: This configuration parameter allows moving read-only data from flash to PSRAM. If SPIRAM_FETCH_INSTRUCTIONS parameter is also enabled, the code that normally requires execution during the SPI1 flash operation does not need to be placed in IRAM, thus optimizing RAM usage.\nInstalling Zephyr: A Step-by-Step Guide # To install Zephyr RTOS and the necessary tools, follow the instructions in the Getting Started Guide. By the end of the process, you will have a command-line Zephyr development environment set up and ready to build your application.\nMake sure to follow all the steps with a successful result for each one of them.\nUsing PSRAM for Dynamic Memory Allocation # PSRAM memory blocks can be made available to applications through Zephyr\u0026rsquo;s shared multi-heap library. The shared multi-heap memory pool manager uses the multi-heap allocator to manage a set of reserved memory regions with varying capabilities and attributes. For PSRAM, enabling the ESP_SPIRAM and SHARED_MULTI_HEAP parameters causes the external PSRAM to be mapped into the data virtual memory space during Zephyr\u0026rsquo;s early initialization stage. The shared multi-heap framework is initialized, and the PSRAM memory region is added to the pool.\nIf an application needs a memory block allocated from PSRAM, it must call shared_multi_heap_alloc() whith SMH_REG_ATTR_EXTERNAL as a parameter. This function will return an address pointing to a memory block inside PSRAM. If an aligned memory block is required, shared_multi_heap_aligned_alloc() should be called instead.\nWith the ownership of this memory block, the application is granted permission to read from and write to its addresses. Once the memory block is no longer needed, it can be returned to the pool from which it was allocated by calling shared_multi_heap_free() and passing the pointer to the block as a parameter.\nThe following sample code shows how to use Zephyr\u0026rsquo;s shared multi-heap API to allocate, use, and free memory from PSRAM:\nboards/esp32s3_devkitc_procpu.overlay:\n\u0026amp;psram0 { size = \u0026lt;DT_SIZE_M(8)\u0026gt;; }; prj.conf:\nCONFIG_LOG=y CONFIG_ESP_SPIRAM=y CONFIG_SHARED_MULTI_HEAP=y CONFIG_SPIRAM_MODE_OCT=y CONFIG_SPIRAM_SPEED_80M=y CONFIG_ESP32S3_DATA_CACHE_64KB=y CONFIG_ESP_SPIRAM_MEMTEST=y src/main.c:\n#include \u0026lt;zephyr/kernel.h\u0026gt; #include \u0026lt;soc/soc_memory_layout.h\u0026gt; #include \u0026lt;zephyr/multi_heap/shared_multi_heap.h\u0026gt; #include \u0026lt;zephyr/logging/log.h\u0026gt; LOG_MODULE_REGISTER(PSRAM_SAMPLE, LOG_LEVEL_INF); int main(void) { uint32_t *p_mem, k; LOG_INF(\u0026#34;Sample started\u0026#34;); p_mem = shared_multi_heap_aligned_alloc(SMH_REG_ATTR_EXTERNAL, 32, 1024*sizeof(uint32_t)); if (p_mem == NULL) { LOG_ERR(\u0026#34;PSRAM memory allocation failed!\u0026#34;); return -ENOMEM; } for (k = 0; k \u0026lt; 1024; k++) { p_mem[k] = k; } for (k = 0; k \u0026lt; 1024; k++) { if (p_mem[k] != k) { LOG_ERR(\u0026#34;p_mem[%\u0026#34;PRIu32\u0026#34;]: %\u0026#34;PRIu32\u0026#34; (expected value %\u0026#34;PRIu32\u0026#34;)\u0026#34;, k, p_mem[k], k); break; } } shared_multi_heap_free(p_mem); if (k \u0026lt; 1024) { LOG_ERR(\u0026#34;Failed checking memory contents.\u0026#34;); return -1; } LOG_INF(\u0026#34;Sample finished successfully!\u0026#34;); return 0; } To build a project containing these two files targeting a ESP32-S3-DevKitC-1 board:\nwest build -b esp32s3_devkitc/esp32s3/procpu \u0026lt;project folder path\u0026gt; --pristine This command will create a directory called build, which will contain the binary file of our sample along with other intermediate files produced during the building process.\nTo flash the generated binary into the ESP32-S3-DevKitC-1 board, run:\nwest flash To open a console and see the log messages produced during the sample execution, run:\nwest espressif monitor Here are the sample messages:\nESP-ROM:esp32s3-20210327 Build:Mar 27 2021 rst:0x1 (POWERON),boot:0x8 (SPI_FAST_FLASH_BOOT) SPIWP:0xee mode:DIO, clock div:1 load:0x3fc8fa20,len:0x2178 load:0x40374000,len:0xba10 entry 0x403795b0 I (62) soc_init: ESP Simple boot I (62) soc_init: compile time Mar 10 2025 18:43:57 W (62) soc_init: Unicore bootloader I (62) soc_init: chip revision: v0.2 I (65) flash_init: Boot SPI Speed : 80MHz I (68) flash_init: SPI Mode : DIO I (72) flash_init: SPI Flash Size : 8MB I (75) boot: DRAM: lma 0x00000020 vma 0x3fc8fa20 len 0x2178 (8568) I (81) boot: IRAM: lma 0x000021a0 vma 0x40374000 len 0xba10 (47632) I (88) boot: IRAM: lma 0x0000dbc8 vma 0x00000000 len 0x2430 (9264) I (94) boot: IMAP: lma 0x00010000 vma 0x42000000 len 0x4524 (17700) I (100) boot: IRAM: lma 0x0001452c vma 0x00000000 len 0xbacc (47820) I (106) boot: DMAP: lma 0x00020000 vma 0x3c010000 len 0x1674 (5748) I (112) boot: Image with 6 segments I (116) boot: IROM segment: paddr=00010000h, vaddr=42000000h, size=04522h ( 17698) map I (123) boot: DROM segment: paddr=00020000h, vaddr=3c010000h, size=01680h ( 5760) map I (142) boot: libc heap size 336 kB. I (142) spi_flash: detected chip: gd I (142) spi_flash: flash io: dio I (143) octal_psram: vendor id : 0x0d (AP) I (144) octal_psram: dev id : 0x02 (generation 3) I (149) octal_psram: density : 0x03 (64 Mbit) I (155) octal_psram: good-die : 0x01 (Pass) I (158) octal_psram: Latency : 0x01 (Fixed) I (163) octal_psram: VCC : 0x01 (3V) I (167) octal_psram: SRF : 0x01 (Fast Refresh) I (172) octal_psram: BurstType : 0x01 (Hybrid Wrap) I (176) octal_psram: BurstLen : 0x01 (32 Byte) I (181) octal_psram: Readlatency : 0x02 (10 cycles@Fixed) I (186) octal_psram: DriveStrength: 0x00 (1/1) I (191) MSPI Timing: PSRAM timing tuning index: 6 I (195) esp_psram: Found 8MB PSRAM device I (198) esp_psram: Speed: 80MHz I (608) esp_psram: SPI SRAM memory test OK *** Booting Zephyr OS build v4.0.0-6082-g6402eb6e9788 *** [00:00:00.636,000] \u0026lt;inf\u0026gt; PSRAM_SAMPLE: Sample started [00:00:00.636,000] \u0026lt;inf\u0026gt; PSRAM_SAMPLE: Sample finished successfully! Once the sample finishes executing successfully, we can conclude that the memory allocated from PSRAM was read and written to without any issues.\nAdding PSRAM to Your ESP32 Memory Map # Once ESP_SPIRAM is enabled, a section called .ext_ram.bss will be created. This section will hold non-initialized global variables that will later be placed in PSRAM. These global variables must be declared with __attribute__ ((section (\u0026quot;.ext_ram.bss\u0026quot;)).\nboards/esp32s3_devkitc_procpu.overlay:\n\u0026amp;psram0 { size = \u0026lt;DT_SIZE_M(8)\u0026gt;; }; prj.conf:\nCONFIG_LOG=y CONFIG_ESP_SPIRAM=y CONFIG_SPIRAM_MODE_OCT=y CONFIG_SPIRAM_SPEED_80M=y CONFIG_ESP32S3_DATA_CACHE_64KB=y CONFIG_ESP_SPIRAM_MEMTEST=n main.c:\n#include \u0026lt;zephyr/kernel.h\u0026gt; #include \u0026lt;zephyr/logging/log.h\u0026gt; LOG_MODULE_REGISTER(PSRAM_SAMPLE, LOG_LEVEL_INF); #define PSRAM_TEST_VECTOR_LEN (512*1024) __attribute__ ((section (\u0026#34;.ext_ram.bss\u0026#34;))) uint8_t psram_vector[PSRAM_TEST_VECTOR_LEN]; int main(void) { uint32_t k; LOG_INF(\u0026#34;Sample started\u0026#34;); LOG_DBG(\u0026#34;Writing...\u0026#34;); for (k = 0; k \u0026lt; PSRAM_TEST_VECTOR_LEN; k++) { psram_vector[k] = (uint8_t)k; LOG_DBG(\u0026#34;psram_vector[%\u0026#34;PRIu32\u0026#34;]: %\u0026#34;PRIu8, k, psram_vector[k]); } LOG_DBG(\u0026#34;Reading...\u0026#34;); for (k = 0; k \u0026lt; PSRAM_TEST_VECTOR_LEN; k++) { if (psram_vector[k] != (uint8_t)k) { LOG_ERR(\u0026#34;psram_vector[%\u0026#34;PRIu32\u0026#34;]: %\u0026#34;PRIu8\u0026#34; (expected value %\u0026#34;PRIu8\u0026#34;)\u0026#34;, k, psram_vector[k], (uint8_t)k); LOG_ERR(\u0026#34;Verification failed!\u0026#34;); return -1; } } LOG_INF(\u0026#34;Sample finished successfully!\u0026#34;); return 0; } To build a project containing these two files targeting a ESP32-S3-DevKitC-1 board, run:\n$ west build -b esp32s3_devkitc/esp32s3/procpu \u0026lt;project folder path\u0026gt; --pristine This command will create a directory called build, which will contain the binary file of our sample along with other intermediate files produced during the building process.\nBefore we move on, let\u0026rsquo;s take a look inside the build/zephyr/zephyr.map file:\n... 11290 *(SORT_BY_ALIGNMENT(.ext_ram.bss*)) 11291 .ext_ram.bss 0x000000003c020000 0x80000 app/libapp.a(main.c.obj) 11292 0x000000003c020000 psram_vector 11293 0x000000003c0a0000 . = ALIGN (0x10) 11294 0x000000003c0a0000 _ext_ram_bss_end = ABSOLUTE (.) 11295 0x000000003c0a0000 _ext_ram_heap_start = ABSOLUTE (.) 11296 0x000000003c2a0000 . = (. + 0x200000) 11297 *fill* 0x000000003c0a0000 0x200000 11298 0x000000003c2a0000 . = ALIGN (0x10) 11299 0x000000003c2a0000 _ext_ram_heap_end = ABSOLUTE (.) 11300 0x000000003c2a0000 _ext_ram_end = ABSOLUTE (.) ... Here we can see that the first position of psram_vector is at the address 0x3c020000 which is inside the region mapping for the external PSRAM on ESP32-S3. We can also see that although SHARED_MULTI_HEAP parameter was not explicitly enabled, it has some area reserved for spiram_head. It happens because SHARED_MULTI_HEAP parameter is enabled by default once ESP_SPIRAM is enabled.\nNow let\u0026rsquo;s flash the binary onto the ESP32-S3-DevKitC-1 board and observe the messages from the sample:\n$ west flash $ west espressif monitor ESP-ROM:esp32s3-20210327 Build:Mar 27 2021 rst:0x1 (POWERON),boot:0x8 (SPI_FAST_FLASH_BOOT) SPIWP:0xee mode:DIO, clock div:1 load:0x3fc8fa20,len:0x2178 load:0x40374000,len:0xba10 entry 0x403795b0 I (62) soc_init: ESP Simple boot I (62) soc_init: compile time Mar 10 2025 18:40:57 W (62) soc_init: Unicore bootloader I (62) soc_init: chip revision: v0.2 I (65) flash_init: Boot SPI Speed : 80MHz I (68) flash_init: SPI Mode : DIO I (72) flash_init: SPI Flash Size : 8MB I (75) boot: DRAM: lma 0x00000020 vma 0x3fc8fa20 len 0x2178 (8568) I (81) boot: IRAM: lma 0x000021a0 vma 0x40374000 len 0xba10 (47632) I (88) boot: IRAM: lma 0x0000dbc8 vma 0x00000000 len 0x2430 (9264) I (94) boot: IMAP: lma 0x00010000 vma 0x42000000 len 0x4484 (17540) I (100) boot: IRAM: lma 0x0001448c vma 0x00000000 len 0xbb6c (47980) I (106) boot: DMAP: lma 0x00020000 vma 0x3c010000 len 0x1654 (5716) I (112) boot: Image with 6 segments I (116) boot: IROM segment: paddr=00010000h, vaddr=42000000h, size=04482h ( 17538) map I (123) boot: DROM segment: paddr=00020000h, vaddr=3c010000h, size=01660h ( 5728) map I (142) boot: libc heap size 336 kB. I (142) spi_flash: detected chip: gd I (142) spi_flash: flash io: dio I (143) octal_psram: vendor id : 0x0d (AP) I (144) octal_psram: dev id : 0x02 (generation 3) I (150) octal_psram: density : 0x03 (64 Mbit) I (154) octal_psram: good-die : 0x01 (Pass) I (158) octal_psram: Latency : 0x01 (Fixed) I (163) octal_psram: VCC : 0x01 (3V) I (167) octal_psram: SRF : 0x01 (Fast Refresh) I (172) octal_psram: BurstType : 0x01 (Hybrid Wrap) I (176) octal_psram: BurstLen : 0x01 (32 Byte) I (181) octal_psram: Readlatency : 0x02 (10 cycles@Fixed) I (186) octal_psram: DriveStrength: 0x00 (1/1) I (191) MSPI Timing: PSRAM timing tuning index: 6 I (195) esp_psram: Found 8MB PSRAM device I (198) esp_psram: Speed: 80MHz I (608) esp_psram: SPI SRAM memory test OK *** Booting Zephyr OS build v4.0.0-6082-g6402eb6e9788 *** [00:00:00.648,000] \u0026lt;inf\u0026gt; PSRAM_SAMPLE: Sample started [00:00:00.683,000] \u0026lt;inf\u0026gt; PSRAM_SAMPLE: Sample finished successfully! Here, we can observe that the application now starts earlier compared to the previous sample. This improvement results from disabling the ESP_SPIRAM_MEMTEST parameter, which bypasses the PSRAM memory test that previously took a few hundred milliseconds. in\nPlacing Task Stack in PSRAM # Another way to to take advantage of PSRAM is by placing Zephyr\u0026rsquo;s task stacks in the .ext_ram.bss section via Z_KERNEL_STACK_DEFINE_IN() with its third parameter lsect being __attribute__((section(\u0026quot;.ext_ram.bss\u0026quot;))).\nNote: Be careful before deciding to put your task stacks in PSRAM: When flash cache is disabled (for example, if the flash is being written to), the external RAM also becomes inaccessible. Any read operations from or write operations to it will lead to an illegal cache access exception. You can find more restrictions regarding the use of external RAM here\nFollowing you will find a sample showing how to place a Zephyr\u0026rsquo;s task stack in PSRAM:\nboards/esp32s3_devkitc_procpu.overlay:\n\u0026amp;psram0 { size = \u0026lt;DT_SIZE_M(8)\u0026gt;; }; prj.conf:\nCONFIG_ESP_SPIRAM=y CONFIG_SPIRAM_MODE_OCT=y CONFIG_SPIRAM_SPEED_80M=y CONFIG_ESP32S3_DATA_CACHE_64KB=y src/main.c:\n#include \u0026lt;stdio.h\u0026gt; #include \u0026lt;inttypes.h\u0026gt; #include \u0026lt;zephyr/kernel.h\u0026gt; #define MY_TSTACK_SIZE 1024 static Z_KERNEL_STACK_DEFINE_IN(my_tstack, MY_TSTACK_SIZE, __attribute__((section(\u0026#34;.ext_ram.bss\u0026#34;)))); static struct k_thread my_tdata; void my_tfunc(void *arg1, void *arg2, void *arg3) { uint32_t my_tcounter = 0; printf(\u0026#34;my_tstack: 0x%\u0026#34;PRIX32\u0026#34;\\n\u0026#34;, (uint32_t)my_tstack); while(1) { printf(\u0026#34;%\u0026#34;PRIu32\u0026#34; - Hello World! - %s\\n\u0026#34;, ++my_tcounter, CONFIG_BOARD_TARGET); k_sleep(K_MSEC(250)); } } int main(void) { k_tid_t tid = k_thread_create(\u0026amp;my_tdata, my_tstack, MY_TSTACK_SIZE, my_tfunc, NULL, NULL, NULL, K_PRIO_PREEMPT(0), K_INHERIT_PERMS, K_NO_WAIT); return 0; } To build, flash and see the sample log, type:\n$ west build -b esp32s3_devkitc/esp32s3/procpu \u0026lt;application\u0026gt; --pristine $ west flash $ west espressif monitor Here is the log emitted by your board:\nESP-ROM:esp32s3-20210327 Build:Mar 27 2021 rst:0x1 (POWERON),boot:0x2b (SPI_FAST_FLASH_BOOT) SPIWP:0xee mode:DIO, clock div:1 load:0x3fc8dc80,len:0x19f0 load:0x40374000,len:0x9c64 entry 0x40377804 I (56) soc_init: ESP Simple boot I (57) soc_init: compile time Mar 10 2025 19:20:47 W (57) soc_init: Unicore bootloader I (57) soc_init: chip revision: v0.2 I (59) flash_init: Boot SPI Speed : 80MHz I (63) flash_init: SPI Mode : DIO I (66) flash_init: SPI Flash Size : 8MB I (70) boot: DRAM: lma 0x00000020 vma 0x3fc8dc80 len 0x19f0 (6640) I (76) boot: IRAM: lma 0x00001a18 vma 0x40374000 len 0x9c64 (40036) I (82) boot: IRAM: lma 0x0000b688 vma 0x00000000 len 0x4970 (18800) I (88) boot: IMAP: lma 0x00010000 vma 0x42000000 len 0x3de8 (15848) I (95) boot: IRAM: lma 0x00013df0 vma 0x00000000 len 0xc208 (49672) I (101) boot: DMAP: lma 0x00020000 vma 0x3c010000 len 0x1244 (4676) I (107) boot: Image with 6 segments I (110) boot: IROM segment: paddr=00010000h, vaddr=42000000h, size=03DE6h ( 15846) map I (118) boot: DROM segment: paddr=00020000h, vaddr=3c010000h, size=01250h ( 4688) map I (137) boot: libc heap size 347 kB. I (137) spi_flash: detected chip: gd I (137) spi_flash: flash io: dio I (137) octal_psram: vendor id : 0x0d (AP) I (139) octal_psram: dev id : 0x02 (generation 3) I (144) octal_psram: density : 0x03 (64 Mbit) I (149) octal_psram: good-die : 0x01 (Pass) I (153) octal_psram: Latency : 0x01 (Fixed) I (157) octal_psram: VCC : 0x01 (3V) I (161) octal_psram: SRF : 0x01 (Fast Refresh) I (166) octal_psram: BurstType : 0x01 (Hybrid Wrap) I (171) octal_psram: BurstLen : 0x01 (32 Byte) I (176) octal_psram: Readlatency : 0x02 (10 cycles@Fixed) I (181) octal_psram: DriveStrength: 0x00 (1/1) I (187) MSPI Timing: PSRAM timing tuning index: 6 I (189) esp_psram: Found 8MB PSRAM device I (193) esp_psram: Speed: 80MHz I (602) esp_psram: SPI SRAM memory test OK/ *** Booting Zephyr OS build v4.0.0-6083-g3a8e95b7f490 *** my_tstack: 0x3C020000 1 - Hello World! - esp32s3_devkitc/esp32s3/procpu 2 - Hello World! - esp32s3_devkitc/esp32s3/procpu 3 - Hello World! - esp32s3_devkitc/esp32s3/procpu 4 - Hello World! - esp32s3_devkitc/esp32s3/procpu 5 - Hello World! - esp32s3_devkitc/esp32s3/procpu 6 - Hello World! - esp32s3_devkitc/esp32s3/procpu 7 - Hello World! - esp32s3_devkitc/esp32s3/procpu 8 - Hello World! - esp32s3_devkitc/esp32s3/procpu 9 - Hello World! - esp32s3_devkitc/esp32s3/procpu ... You can confirm that the task stack my_tstack was allocated in PSRAM because the address 0x3C020000 is a virtual address mapping an external RAM position.\nRunning Code from PSRAM Instead of Flash # Enabling the SPIRAM_FETCH_INSTRUCTIONS parameter will move instructions from flash to PSRAM during startup, and if the ESP_SPIRAM_MEMTEST parameter is also enabled, the code that normally requires execution during the SPI1 flash operation does not need to be placed in IRAM, thus optimizing RAM usage.\nTo check the effects of SPIRAM_FETCH_INSTRUCTIONS and SPIRAM_RODATA parameters, let\u0026rsquo;s build hello_world first without enabling them and then enable them.\nBuilding hello_world with SPIRAM_FETCH_INSTRUCTIONS and SPIRAM_RODATA disabled\nwest build -b esp32s3_devkitc/esp32s3/procpu zephyr/samples/hello_world/ --pristine Memory region Used Size Region Size %age Used FLASH: 135376 B 8388352 B 1.61% iram0_0_seg: 39056 B 343552 B 11.37% dram0_0_seg: 39072 B 327168 B 11.94% irom0_0_seg: 14642 B 8 MB 0.17% drom0_0_seg: 69840 B 8 MB 0.83% rtc_iram_seg: 0 GB 8 KB 0.00% rtc_data_seg: 0 GB 8 KB 0.00% rtc_slow_seg: 0 GB 8 KB 0.00% IDT_LIST: 0 GB 8 KB 0.00% ESP-ROM:esp32s3-20210327 Build:Mar 27 2021 rst:0x1 (POWERON),boot:0xa (SPI_FAST_FLASH_BOOT) SPIWP:0xee mode:DIO, clock div:2 load:0x3fc8d8a0,len:0x176c load:0x40374000,len:0x9880 entry 0x40377bd0 I (67) soc_init: ESP Simple boot I (68) soc_init: compile time Dec 4 2024 19:25:19 W (68) soc_init: Unicore bootloader I (68) spi_flash: detected chip: gd I (70) spi_flash: flash io: dio W (73) spi_flash: Detected size(8192k) larger than the size in the binary image header(2048k). Using the size in the binary image header. I (85) soc_init: chip revision: v0.2 I (88) flash_init: Boot SPI Speed : 40MHz I (92) flash_init: SPI Mode : DIO I (96) flash_init: SPI Flash Size : 8MB I (99) soc_random: Enabling RNG early entropy source I (104) boot: DRAM: lma 0x00000020 vma 0x3fc8d8a0 len 0x176c (5996) I (110) boot: IRAM: lma 0x00001794 vma 0x40374000 len 0x9880 (39040) I (116) boot: padd: lma 0x0000b028 vma 0x00000000 len 0x4fd0 (20432) I (123) boot: IMAP: lma 0x00010000 vma 0x42000000 len 0x3934 (14644) I (129) boot: padd: lma 0x0001393c vma 0x00000000 len 0xc6bc (50876) I (135) boot: DMAP: lma 0x00020000 vma 0x3c010000 len 0x10d0 (4304) I (141) boot: Image with 6 segments I (144) boot: DROM segment: paddr=00020000h, vaddr=3c010000h, size=010D0h ( 4304) map I (152) boot: IROM segment: paddr=00010000h, vaddr=42000000h, size=03932h ( 14642) map I (171) soc_random: Disabling RNG early entropy source I (171) boot: Disabling glitch detection I (171) boot: Jumping to the main image... I (208) heap_runtime: ESP heap runtime init at 0x3fc918a0 size 351 kB. *** Booting Zephyr OS build v4.0.0-1471-ge60f04096cd8 *** Hello World! esp32s3_devkitc/esp32s3/procpu Building hello_world with SPIRAM_FETCH_INSTRUCTIONS and SPIRAM_RODATA enabled\nboards/esp32s3_devkitc_procpu.overlay:\n\u0026amp;psram0 { size = \u0026lt;DT_SIZE_M(8)\u0026gt;; }; west build -b esp32s3_devkitc/esp32s3/procpu zephyr/samples/hello_world/ --pristine -- -DCONFIG_ESP_SPIRAM=y -DCONFIG_SPIRAM_MODE_OCT=y -DCONFIG_SPIRAM_SPEED_80M=y -DCONFIG_ESP32S3_DATA_CACHE_64KB=y -DCONFIG_ESP_SPIRAM_MEMTEST=y -DCONFIG_SPIRAM_FETCH_INSTRUCTIONS=y -DCONFIG_SPIRAM_RODATA=y Memory region Used Size Region Size %age Used FLASH: 135916 B 8388352 B 1.62% iram0_0_seg: 43384 B 343552 B 12.63% dram0_0_seg: 45104 B 327168 B 13.79% irom0_0_seg: 15942 B 8 MB 0.19% drom0_0_seg: 70380 B 8 MB 0.84% ext_ram_seg: 1152 KB 8388544 B 14.06% rtc_iram_seg: 0 GB 8 KB 0.00% rtc_data_seg: 0 GB 8 KB 0.00% rtc_slow_seg: 0 GB 8 KB 0.00% IDT_LIST: 0 GB 8 KB 0.00% ESP-ROM:esp32s3-20210327 Build:Mar 27 2021 rst:0x1 (POWERON),boot:0x8 (SPI_FAST_FLASH_BOOT) SPIWP:0xee mode:DIO, clock div:2 load:0x3fc8e988,len:0x1c2c load:0x40374000,len:0xa968 entry 0x40377dcc I (72) soc_init: ESP Simple boot I (72) soc_init: compile time Dec 4 2024 19:32:57 W (72) soc_init: Unicore bootloader I (72) spi_flash: detected chip: gd I (75) spi_flash: flash io: dio W (78) spi_flash: Detected size(8192k) larger than the size in the binary image header(2048k). Using the size in the binary image header. I (90) soc_init: chip revision: v0.2 I (93) flash_init: Boot SPI Speed : 40MHz I (97) flash_init: SPI Mode : DIO I (100) flash_init: SPI Flash Size : 8MB I (104) soc_random: Enabling RNG early entropy source I (109) boot: DRAM: lma 0x00000020 vma 0x3fc8e988 len 0x1c2c (7212) I (115) boot: IRAM: lma 0x00001c54 vma 0x40374000 len 0xa968 (43368) I (121) boot: padd: lma 0x0000c5c8 vma 0x00000000 len 0x3a30 (14896) I (127) boot: IMAP: lma 0x00010000 vma 0x42000000 len 0x3e48 (15944) I (134) boot: padd: lma 0x00013e50 vma 0x00000000 len 0xc1a8 (49576) I (140) boot: DMAP: lma 0x00020000 vma 0x3c010000 len 0x12ec (4844) I (146) boot: Image with 6 segments I (149) boot: DROM segment: paddr=00020000h, vaddr=3c010000h, size=012F0h ( 4848) map I (157) boot: IROM segment: paddr=00010000h, vaddr=42000000h, size=03E46h ( 15942) map I (176) soc_random: Disabling RNG early entropy source I (176) boot: Disabling glitch detection I (176) boot: Jumping to the main image... I (177) octal_psram: vendor id : 0x0d (AP) I (181) octal_psram: dev id : 0x02 (generation 3) I (186) octal_psram: density : 0x03 (64 Mbit) I (190) octal_psram: good-die : 0x01 (Pass) I (195) octal_psram: Latency : 0x01 (Fixed) I (199) octal_psram: VCC : 0x01 (3V) I (203) octal_psram: SRF : 0x01 (Fast Refresh) I (208) octal_psram: BurstType : 0x01 (Hybrid Wrap) I (213) octal_psram: BurstLen : 0x01 (32 Byte) I (217) octal_psram: Readlatency : 0x02 (10 cycles@Fixed) I (223) octal_psram: DriveStrength: 0x00 (1/1) I (227) MSPI Timing: PSRAM timing tuning index: 6 I (231) esp_psram: Found 8MB PSRAM device I (235) esp_psram: Speed: 80MHz I (245) mmu_psram: Instructions copied and mapped to SPIRAM I (252) mmu_psram: Read only data copied and mapped to SPIRAM I (652) esp_psram: SPI SRAM memory test OK I (708) heap_runtime: ESP heap runtime init at 0x3fc93030 size 345 kB. *** Booting Zephyr OS build v4.0.0-1471-ge60f04096cd8 *** Hello World! esp32s3_devkitc/esp32s3/procpu Here, we can confirm that instructions and read-only data were copied and mapped to PSRAM, which can optimize RAM usage when there is code that needs to execute during an SPI1 flash operation.\nLetting ESP32 Wi-Fi Use PSRAM # Another potential use of PSRAM to reduce SRAM usage is by enabling ESP32_WIFI_NET_ALLOC_SPIRAM parameter, allowing the ESP32 Wi-Fi stack to dynamically allocate memory from PSRAM.\nTo check the results, let\u0026rsquo;s build the zephyr/samples/net/wifi/shell, first with ESP32_WIFI_NET_ALLOC_SPIRAM disabled and then with this parameter enabled. In both cases let\u0026rsquo;s flash the binary into the board and launch a console to interact with the shell. After connect to an access point we will execute net allocs to get information from where memory is being allocated in both cases.\nBuilding zephyr/samples/net/wifi/shell with ESP32_WIFI_NET_ALLOC_SPIRAM disabled\nBuilding, flashing, and monitoring:\n$ west build -b esp32s3_devkitc/esp32s3/procpu zephyr/samples/net/wifi/shell --pristine -DCONFIG_NET_DEBUG_NET_PKT_ALLOC=y $ west flash $ west espressif monitor Booting and interacting with the wifi shell to obtain information about the origing of the memory allocated by the wifi stack:\nESP-ROM:esp32s3-20210327 Build:Mar 27 2021 rst:0x1 (POWERON),boot:0x8 (SPI_FAST_FLASH_BOOT) SPIWP:0xee mode:DIO, clock div:1 load:0x3fc922b0,len:0x3648 load:0x40374000,len:0xe294 entry 0x4037c6e4 I (71) soc_init: ESP Simple boot I (71) soc_init: compile time Mar 10 2025 18:22:27 W (71) soc_init: Unicore bootloader I (71) soc_init: chip revision: v0.2 I (73) flash_init: Boot SPI Speed : 80MHz I (77) flash_init: SPI Mode : DIO I (81) flash_init: SPI Flash Size : 8MB I (84) boot: DRAM: lma 0x00000020 vma 0x3fc922b0 len 0x3648 (13896) I (90) boot: IRAM: lma 0x00003670 vma 0x40374000 len 0xe294 (58004) I (97) boot: IRAM: lma 0x00011918 vma 0x00000000 len 0xe6e0 (59104) I (103) boot: IMAP: lma 0x00020000 vma 0x42000000 len 0x5a478 (369784) I (109) boot: IRAM: lma 0x0007a480 vma 0x00000000 len 0x5b78 (23416) I (115) boot: DMAP: lma 0x00080000 vma 0x3c060000 len 0x16f94 (94100) I (122) boot: Image with 6 segments I (125) boot: IROM segment: paddr=00020000h, vaddr=42000000h, size=5A476h (369782) map I (132) boot: DROM segment: paddr=00080000h, vaddr=3c060000h, size=16FA0h ( 94112) map I (151) boot: libc heap size 166 kB. I (152) spi_flash: detected chip: gd I (152) spi_flash: flash io: dio *** Booting Zephyr OS build v4.0.0-6082-g6402eb6e9788 ***uart:~$ wifi scan Scan requested Num | SSID (len) | Chan (Band) | RSSI | Security | BSSID | MFP 1 | Soares 6 | 11 (2.4GHz) | -49 | WPA2-PSK | 90:0A:62:42:A5:BF | Disable ... uart:~$ wifi connect --key-mgmt 1 --ssid \u0026lt;SSID\u0026gt; --passphrase \u0026lt;PASSPHRASE\u0026gt; Connection requested Connected [00:04:27.263,000] \u0026lt;inf\u0026gt; net_dhcpv4: Received: 192.168.15.2 uart:~$ net ping 192.168.15.17 PING 192.168.15.17 28 bytes from 192.168.15.17 to 192.168.15.2: icmp_seq=1 ttl=64 time=8 ms 28 bytes from 192.168.15.17 to 192.168.15.2: icmp_seq=2 ttl=64 time=224 ms 28 bytes from 192.168.15.17 to 192.168.15.2: icmp_seq=3 ttl=64 time=455 ms uart:~$ net allocs Network memory allocations memory\tStatus\tPool\tFunction alloc -\u0026gt; freed 0x3fcb8140\tfree\tRX\teth_esp32_rx():139 -\u0026gt; net_icmpv4_input():648 0x3fcb7ec0\tfree\tTX\ticmpv4_handle_echo_request():446 -\u0026gt; ethernet_send():804 0x3fcb707c\tfree\tTDATA\tethernet_fill_header():608 -\u0026gt; ethernet_send():804 0x3fcb7098\tfree\tTDATA\tethernet_fill_header():608 -\u0026gt; ethernet_send():804 Building zephyr/samples/net/wifi/shell with ESP32_WIFI_NET_ALLOC_SPIRAM enabled\nBuilding, flashing and monitoring:\nsocs/esp32s3_procpu.overlay:\n... \u0026amp;psram0 { size = \u0026lt;DT_SIZE_M(8)\u0026gt;; }; $ west build -b esp32s3_devkitc/esp32s3/procpu zephyr/samples/net/wifi/shell --pristine -- -DCONFIG_ESP_SPIRAM=y -DCONFIG_SPIRAM_MODE_OCT=y -DCONFIG_SPIRAM_SPEED_80M=y -DCONFIG_ESP32S3_DATA_CACHE_64KB=y -DCONFIG_ESP32_WIFI_NET_ALLOC_SPIRAM=y -DCONFIG_NET_DEBUG_NET_PKT_ALLOC=y $ west flash $ west espressif monitor Booting and interacting with the wifi shell to obtain information about the origing of the memory allocated by the wifi stack:\nESP-ROM:esp32s3-20210327 Build:Mar 27 2021 rst:0x1 (POWERON),boot:0x8 (SPI_FAST_FLASH_BOOT) SPIWP:0xee mode:DIO, clock div:1 load:0x3fc93140,len:0x3a38 load:0x40374000,len:0xf130 entry 0x4037c85c I (73) soc_init: ESP Simple boot I (73) soc_init: compile time Mar 10 2025 18:05:09 W (74) soc_init: Unicore bootloader I (74) soc_init: chip revision: v0.2 I (76) flash_init: Boot SPI Speed : 80MHz I (80) flash_init: SPI Mode : DIO I (83) flash_init: SPI Flash Size : 8MB I (87) boot: DRAM: lma 0x00000020 vma 0x3fc93140 len 0x3a38 (14904) I (93) boot: IRAM: lma 0x00003a60 vma 0x40374000 len 0xf130 (61744) I (99) boot: IRAM: lma 0x00012ba8 vma 0x00000000 len 0xd450 (54352) I (105) boot: IMAP: lma 0x00020000 vma 0x42000000 len 0x5a924 (370980) I (112) boot: IRAM: lma 0x0007a92c vma 0x00000000 len 0x56cc (22220) I (118) boot: DMAP: lma 0x00080000 vma 0x3c060000 len 0x1714c (94540) I (124) boot: Image with 6 segments I (127) boot: IROM segment: paddr=00020000h, vaddr=42000000h, size=5A922h (370978) map I (135) boot: DROM segment: paddr=00080000h, vaddr=3c060000h, size=17150h ( 94544) map I (154) boot: libc heap size 182 kB. I (154) spi_flash: detected chip: gd I (154) spi_flash: flash io: dio I (155) octal_psram: vendor id : 0x0d (AP) I (156) octal_psram: dev id : 0x02 (generation 3) I (161) octal_psram: density : 0x03 (64 Mbit) I (166) octal_psram: good-die : 0x01 (Pass) I (170) octal_psram: Latency : 0x01 (Fixed) I (174) octal_psram: VCC : 0x01 (3V) I (179) octal_psram: SRF : 0x01 (Fast Refresh) I (183) octal_psram: BurstType : 0x01 (Hybrid Wrap) I (189) octal_psram: BurstLen : 0x01 (32 Byte) I (193) octal_psram: Readlatency : 0x02 (10 cycles@Fixed) I (198) octal_psram: DriveStrength: 0x00 (1/1) I (203) MSPI Timing: PSRAM timing tuning index: 6 I (207) esp_psram: Found 8MB PSRAM device I (210) esp_psram: Speed: 80MHz I (619) esp_psram: SPI SRAM memory test OK *** Booting Zephyr OS build v4.0.0-6082-g6402eb6e9788 *** uart:~$ wifi scan Scan requested Num | SSID (len) | Chan (Band) | RSSI | Security | BSSID | MFP 1 | Soares 6 | 11 (2.4GHz) | -63 | WPA2-PSK | 90:0A:62:42:A5:BF | Disable ... uart:~$ wifi connect --key-mgmt 1 --ssid \u0026lt;SSID\u0026gt; --passphrase \u0026lt;PASSPHRASE\u0026gt; Connection requested Connected [00:01:31.902,000] \u0026lt;inf\u0026gt; net_dhcpv4: Received: 192.168.15.2 uart:~$ net ping 192.168.15.17 PING 192.168.15.17 28 bytes from 192.168.15.17 to 192.168.15.2: icmp_seq=1 ttl=64 time=231 ms 28 bytes from 192.168.15.17 to 192.168.15.2: icmp_seq=2 ttl=64 time=6 ms 28 bytes from 192.168.15.17 to 192.168.15.2: icmp_seq=3 ttl=64 time=338 ms uart:~$ net allocs Network memory allocations memory\tStatus\tPool\tFunction alloc -\u0026gt; freed 0x3c0839a0\tfree\tRX\teth_esp32_rx():139 -\u0026gt; processing_data():178 0x3c083720\tfree\tTX\ticmpv4_handle_echo_request():446 -\u0026gt; ethernet_send():804 0x3c0828dc\tfree\tTDATA\tethernet_fill_header():608 -\u0026gt; ethernet_send():804 Examining the output from both sessions, we can confirm that in the first case, network stack allocations were made using memory from internal RAM \u0026ndash; addresses 0x3fcb8140, 0x3fcb7ec0, 0x3fcb707 and 0x3fcb7098. We can also confirm that in the second case, network stack allocations were taking memory from PSRAM \u0026ndash; addresses 0x3c0839a0, 0x3c083720, and 0x3c0828dc \u0026ndash; thus proving that enabling ESP32_WIFI_NET_ALLOC_SPIRAM avoids allocating memory from the precious internal SRAM and takes advantage of PSRAM.\nFinal Thoughts # Throughout this article, we explored three different strategies for utilizing PSRAM: using it for dynamic memory allocation, adding it to your ESP32 memory map, and running code from PSRAM instead of Flash.\nIn addition to these three strategies, it is also possible to leverage PSRAM to execute external code compiled as Position Independent Code (PIC), which can be placed in PSRAM by a loader for execution. You can find more information about this way of using PSRAM by consulting Zephyr\u0026rsquo;s document LLEXT \u0026ndash; Linkable Loadable Extensions.\nReferences # Zephyr on ESP Devices SPI Flash and External SPI RAM Configuration Support for External RAM ESP32 ESP32-S2 ESP32-S3 ESP32-P4 Zephyr Project Official Site Zephyr Project Documentation Site Getting Started Guide Supported Boards and Shields Espressif ESP32-DevKitC-WROVER ESP32-S2-DevKitC ESP32-S3-DevKitC-1 Shared Multi Heap Code And Data Relocation Linkable Loadable Extensions ","date":"30 December 2024","externalUrl":null,"permalink":"/blog/2024/12/zephyr-how-to-use-psram/","section":"Blog","summary":"This article presents ideas and suggestions on different scenarios to use the PSRAM available in some Espressif devices.","title":"Enabling External PSRAM for Zephyr Applications on ESP32 SoCs","type":"blog"},{"content":"","date":"30 December 2024","externalUrl":null,"permalink":"/authors/marcio-ribeiro/","section":"Developer Portal Authors","summary":"","title":"Marcio Ribeiro","type":"authors"},{"content":"","date":"30 December 2024","externalUrl":null,"permalink":"/tags/psram/","section":"Tags","summary":"","title":"PSRAM","type":"tags"},{"content":"","date":"30 December 2024","externalUrl":null,"permalink":"/tags/spiram/","section":"Tags","summary":"","title":"SPIRAM","type":"tags"},{"content":" Introduction # The ESP32-C6-DevKitM-1 was chosen for testing Wi-Fi, ESP-NOW, and ESP-NOW-LR due to its cutting-edge features and suitability for real-world evaluations. While its compact design and integrated capabilities make it an excellent choice, it should be noted that the board does not natively support external antennas. Instead, it features a high-quality PCB antenna optimized for typical IoT applications. Here are the key highlights:\nSupport for Wi-Fi 6 (802.11ax) - Provides enhanced speed, improved efficiency in congested environments, and reduced latency, making it a future-ready option for testing modern Wi-Fi capabilities. 2.4GHz Capability - Essential for evaluating long-range communication performance with ESP-NOW-LR, especially in challenging environments like forests or rugged terrains. Integrated PCB Antenna - While limited to an on-board antenna, the design ensures a compact and reliable setup for short- to medium-range testing. The board does not include a U.FL connector or external antenna support, which may limit range in certain scenarios. Power Efficiency - Designed for low-power operation, enabling prolonged testing in remote areas without frequent recharging, simulating real-world IoT deployment scenarios. Development Ecosystem - Fully compatible with Espressif’s ESP-IDF framework and third-party tools, making configuration, programming, and analysis straightforward and efficient. By combining these features, the ESP32-C6-DevKitM-1 offers a reliable platform for benchmarking wireless communication protocols in various conditions, from open fields to dense forests. While its lack of external antenna support is a limitation, the integrated PCB antenna performs well under typical testing ranges, making it a strong choice for general-purpose evaluations.\nConcept of data transmission and evaluation # To ensure accurate and consistent testing results, a carefully designed setup was implemented using the ESP32-C6-DevKitM-1 development boards. Two devices were employed, with one configured as the transmitter to send data packets and the other as the receiver to record performance metrics. This configuration allowed us to simulate real-world communication scenarios while isolating the behavior of each wireless protocol under test.\nThe experiments were carried out in two distinct environments to capture performance variations: open fields, which provided minimal interference and clear line-of-sight for communication, and forested areas, which introduced dense obstructions such as trees and foliage to mimic challenging conditions. These environments ensured that the protocols could be evaluated for both optimal and adverse conditions.\nThree key performance metrics were collected during testing:\nLatency - This was measured as the time taken for a message to travel from the transmitter to the receiver. By evaluating latency across various distances, we could assess the responsiveness of each protocol under different environmental and range conditions. Speed - The maximum throughput, or data transfer rate, was determined to understand how well each protocol supported high-speed communication. This was measured in both environments to identify the impact of interference and signal attenuation. Packet Success Rate - The reliability of each protocol was monitored by tracking the percentage of data packets successfully transmitted and received over increasing distances. This metric was critical for understanding the stability and robustness of each protocol in real-world use cases. Results # Wi-Fi # Wi-Fi exhibited a steady degradation in performance as distance increased. In open fields, latency started at around 20 ms at 30 meters and rose to approximately 35 ms at 150 meters, while in forested areas, latency climbed more steeply, starting at 25 ms at 20 meters and reaching nearly 40 ms at 100 meters. Speed in open fields was strong at shorter distances, peaking at 12 Mbps at 30 meters, but declined sharply to below 6 Mbps by 150 meters. In dense forests, speeds were lower, starting at 8 Mbps at 20 meters and dropping to under 4 Mbps at 100 meters due to interference. Success rates in open fields remained high at close ranges but fell to around 60% by 150 meters. In forested conditions, Wi-Fi success rates declined more quickly, dropping below 50% at 80 meters, highlighting its vulnerability to obstructions. ESP-NOW # ESP-NOW demonstrated excellent performance for mid-range communication. Latency in open fields remained consistently low, averaging under 20 ms even at distances up to 300 meters, and stayed manageable at about 30 ms in forests at 150 meters. Speed in open fields reached a maximum of 400 kbps at close ranges, gradually dropping to 50 kbps at 300 meters. In dense forests, speeds started at around 350 kbps at 25 meters but declined more quickly, reaching just 50 kbps by 150 meters. Success rates in open fields were near 100% up to 150 meters, gradually dropping to 60% by 300 meters. In forested conditions, success rates declined more sharply, falling below 50% at 125 meters. Overall, ESP-NOW performed well for moderate distances and offered reasonable resilience to environmental challenges. ESP-NOW-LR # ESP-NOW-LR excelled in long-range and challenging environments, showing remarkable stability over extended distances. In open fields, latency remained under 25 ms even at 900 meters, while in forests, it stayed consistent at around 30 ms up to 600 meters, despite environmental obstacles. Speed in open fields started at 100 kbps at 150 meters and declined steadily to about 10 kbps at 900 meters. In dense forests, the speed remained at 80 kbps up to 200 meters but saw a sharp decline beyond 400 meters. Success rates in open fields were near 100% up to 450 meters and dropped to 40% by 900 meters, while in forests, success rates followed a similar trend, starting near 100% but falling below 50% at 400 meters. These results highlight ESP-NOW-LR’s outstanding long-range performance and its ability to maintain connectivity in obstructed terrains. Conclusion # The ESP32 platform offers powerful and flexible communication protocols that cater to a wide range of applications. Wi-Fi provides high-throughput and internet connectivity for bandwidth-heavy applications. ESP-NOW excels in low-power, connectionless communication for peer-to-peer networks, ideal for local applications without requiring infrastructure. ESP-NOW-LR, powered by Espressif technology, extends the range of ESP-NOW to up to a kilometer, making it the perfect choice for long-range, low-power IoT applications in remote or challenging environments.\nThe ESP32-C6-DevKitM-1 provides a robust and versatile platform for evaluating Wi-Fi, ESP-NOW, and ESP-NOW-LR in diverse environments. Our tests reveal that:\nWi-Fi is ideal for high-speed communication in controlled environments. ESP-NOW balances power efficiency and responsiveness for local IoT networks. ESP-NOW-LR excels in long-range, low-power communication, especially in dense forests. ","date":"20 December 2024","externalUrl":null,"permalink":"/blog/esp-now-for-outdoor-applications/","section":"Blog","summary":"","title":"Exploring wireless communication protocols on ESP32 platform for outdoor applications","type":"blog"},{"content":"","date":"20 December 2024","externalUrl":null,"permalink":"/authors/sumsky-jan/","section":"Developer Portal Authors","summary":"","title":"Ján Šumský","type":"authors"},{"content":"","date":"20 December 2024","externalUrl":null,"permalink":"/authors/kubascik-michal/","section":"Developer Portal Authors","summary":"","title":"Michal Kubaščík","type":"authors"},{"content":"","date":"20 December 2024","externalUrl":null,"permalink":"/authors/gancarcik-samuel/","section":"Developer Portal Authors","summary":"","title":"Samuel Gancarčík","type":"authors"},{"content":"","date":"20 December 2024","externalUrl":null,"permalink":"/tags/wireless/","section":"Tags","summary":"","title":"Wireless","type":"tags"},{"content":" Introduction # Department of Technical Cybernetics at the Faculty of Management Science and Informatics mainly focuses embedded systems and IoT networks, implementing innovative approaches in such systems. Most applications are powered by batteries, and require low power consumption and reliable data transmission. Therefore, the new wireless protocol ESP-NOW has become interesting for implementation in IoT systems. Our testing mainly focuses on reliability of data transmission in indoor smart applications.\nSmart applications # Generally, smart application involves the interconnection of multiple sensors via wired or wireless connection. In basic concept, system consist of:\nmeasurement unit - microcontroler, microprocessor with sensors, etc., processing unit - high performance microcontroler, single-board computer, cloud system, etc., actuator unit - for example heating, cooling, watering, etc. By the most common smart appliances include smart lightning, smart plugs, siol moisture monitoring, machine status monitoring or search and rescue systems.\nCommunication protocols # Communication protocols could be divided to two classes:\nWired Protocols: Mostly used between microcontrolers, microprocessors and sensors. Most common are UART, IIC, SPI, and in industrial appliances CAN. Wireless Protocols: Commonly used between sensor nodes, or nodes and processing unit, cloud. Mostly used are Wi-Fi, Zigbee, Bluetooth or Bluetooth Low Energy, Matter, Thread or ESP-NOW. For data transmission over longer distances are implemented LoRa or GSM technologies. ESP-NOW vs. Wi-Fi # Both ESP-NOW and Wi-Fi are radio-frequency communication protocols. There are several points to mention, in case of wireless protocol chose.\nWith Wi-Fi connection, ESP32-based device is able to communicate with various types of devices and systems in network. In case of speed, Wi-Fi can work up to 70Mbps, and Wi-Fi range is up to 30 meters. On the other hand, power consumption of Wi-Fi based device is relatively high.\nUsing ESP-NOW, we can achieve much lower power consumption (aprox. 100mA while device is transmiting). ESP-NOW range is much higher - up to 200 meters with low packet loss. Data transmit speed is lower - up to 250kbps. Also, by implementing ESP-NOW, communication is limited to modules by Espressif Systems.\nESP-NOW is therefore designed mainly for low power devices, IoT, and not for huge data transfer.\nConcept of data transmission and evaluation # By the motivation of research has been evaluation of range and packet loss of data transmission over time and according to placement and environment.\nOur network concept consist of 8 sensor nodes based on ESP32 simulating sensor data, and central node - based on ESP32-S3 and ESP32-C6 combination. Block scheme is on following figure. Architecture of network is shown on following figure. Sensor nodes 1-8 are sending packets to central node over ESP-NOW. This device is recieving packets, and through UART sending to transmitter, connected to network over Wi-Fi. Data are consequently sent to Thingspeak.\nMethods # Evaluation of packets received for period of time, with stable frequency of sending. Relative reliability is calculated as ratio of received packets to expected number packets. Relative packet loss is calculated as ratio of non-received packets to expected number packets.\nData were sent to CU with period 250ms = 4 packets per second. Number of received packets is calculated for 30 seconds = 120 packets are expected with 0% packet loss.\nPlacement # 8 sensor nodes has been developed and placed over department. Each node has been sending packets to central unit. Description of placement is described on following picture. Results # As an result, we can see following comparison of multiple nodes. On following picture is success rate shown of nodes 1-4 and 5-8.\nBest success rate is defined as the lowest packet loss. It has been achieved between central unit and nodes 1,2,4,6.\nConclusion and recommendations # By our measurements we assume that 50% of nodes are reliable, and packet loss highly depends on structure of the building – number and structure of the walls between devices, percentage of open space. Future research will include analysis of signal over multiple floors. Furthermore, we need find place with lowest packet loss and changing power of signal on nodes to reduce power consumption of nodes.\nAs a recommendation for new large smart indoor application based on ESP-NOW protocol, we suggest to divide building to segments with highest percentage of open space, and usage of multiple central units. Also, developers should implement sophisticated software control of packet delivery and solve the issue of non-delivery status.\nMore informations # Article has been released on DevCon 2024 - see more.\n","date":"19 December 2024","externalUrl":null,"permalink":"/blog/reliability-esp-now/","section":"Blog","summary":"","title":"Data transmission reliability over ESP-NOW protocol in indoor environment","type":"blog"},{"content":"","date":"9 December 2024","externalUrl":null,"permalink":"/tags/esp32-s6/","section":"Tags","summary":"","title":"ESP32-S6","type":"tags"},{"content":"","date":"9 December 2024","externalUrl":null,"permalink":"/series/fl001/","section":"Series","summary":"","title":"FL001","type":"series"},{"content":"","date":"9 December 2024","externalUrl":null,"permalink":"/tags/flowcode/","section":"Tags","summary":"","title":"Flowcode","type":"tags"},{"content":" Effort # This set of workshops will take around 20 hours to complete. Requirements # You will need:\nM5Stack Dial with power lead Relay board - can be 12 or 24V Grove style 4 pin push leads Solenoid If you are implementing the door lock for real you will also need:\nMaglock 12 or 24V power supply 5V regulator board (for powering the M5Stack Dial) You will also need a copy of Flowcode with the ESP32 chip pack. Flowcode is free of charge for makers, professionals will need to buy a Pro license.\nThe ESP chip pack costs £60 or around $80 and is available from the Flowcode web site: www.flowcode.co.uk.\nLearning outcomes # This workshop is designed for engineers who have some experience of programming embedded systems and want to learn more about graphical display based systems and web based control and data gathering systems. For Matrix customers it assumes that you have completed the Introduction to Microcontrollers course. If you complete the exercises in this workbook then it will take you around 20 hours. This is designed for self study.\nIf you complete this workshop then will learn:\nESP32 programming Simple Input / Output pin control How encoders work How I2C sensors work SHT32 temperature humidity sensor operation How solenoid/maglocks work Graphical display programming Menu system design for graphical displays Embedded web based communication techniques Mobile phone app development Mobile phone / Embedded system design Whilst this project uses the M5Stack Dial the silks learned will be useful for any graphical display based project.\nVideo # Agenda # Assignment 1: Planning Assignment 2: Using the Display Assignment 3: Switch and I/O Pins Assignment 4: The Bezel Encoder Assignment 5: I2C Expansion Assignment 6: Menu System Assignment 7: Connecting to the web Assignment 8: Full Project Next step # Assignment 1: Planning\n","date":"9 December 2024","externalUrl":null,"permalink":"/workshops/flowcode/","section":"Workshops","summary":"","title":"Flowcode - M5 Stack Dial Workshop","type":"workshops"},{"content":"Ok - let’s be honest. Planning is a bit of a pain. Its boring. Its not the fun part of the job. At the start of a project we are itching to get on with the coding, the graphics and get something working.\nBut if you don’t plan then there can be all sorts of pain later: you end up redoing work, falling out with colleagues and customers, and it’s a lot less fun later on in the project.\nIn part 1 we show you how we plan the project.\nSpecification # We are going to show you how to make an electronic door lock based on the M5stack dial with the following features:\nBased on M5 stack dial Code entry access using bezel and switch Maglock door opener – 24VDC @10A Graphical display Remote unlock with mobile phone Weather information on mobile phone and locally Actually what we really want to do is teach you how to create a project based on the M5 stack dial. We have come up with the specification above so that we can teach you about the following:\nAssignment 1: Planning Assignment 2: Using the Display Assignment 3: Switch and I/O Pins Assignment 4: The Bezel Encoder Assignment 5: I2C Expansion Assignment 6: Menu System Assignment 7: Connecting to the web Assignment 8: Full Project Graphic designer’s brief # Usually we need a graphic designer in a project like this. They just have a knack of making stuff look right. In this case we gave the designer a brief of creating an image that allowed us to teach how to display text, vector graphics, and bitmap graphics in an Electronic safe/door lockproject. This is what he came up with: Fantastic.\nFrom this we get a create colour scheme and a theme for our project. What we need to do next is analyse this and turn it into information that we can use. The easiest way to do that is to redraw it. We are going to have to do that anyway to plan our menus.\nAfter doing that we get this:\nAs you can see we have taken the opportunity to draw a pixel grid on the diagram and we now understand the colours text sizes and position of all the graphical and text elements.\nWe also need to plan our menu and functionality. Once we have the main screen done this easily falls out of the design and we get the following screens:\nWhen the user presses the bezel from the home screen they can enter a combination. This graphic defines the elements on that screen.\nIf the code is incorrect then this screen tells them they have the wrong combination. They can ring a mobile number and the door can be unlocked by someone with the mobile phone app.\nIf they are successful then this screen is displayed. The door unlocks and they get a summary of the weather!\nSo that has defined our functionality. We can then show this to colleagues and customers and be really clear about what we are doing before we start. A real time saver!\nNow that we know what we are doing some other elements of the design easily come from this:\nColours # We need to know the colours of all the items on the display. We will declare some constants in the program to save us time as well. So we have a list:\nName R G B Constants Purple 64 33 87 PURPLER, PURPLEG, PURPLEB Light purple 85 47 108 LIGHTPURPLER, LIGHTPURPLEG, LIGHTPURPLEB Orange 255 102 0 ORANGER, ORANGEG, ORANGEB White 255 255 255 WHITER, WHITEG, WHITEB Red 255 0 0 Yellow 255 255 0 Green 0 255 255 Graphics # We also have a rough plan for the home screen graphics: Purple circle background\nGrid at 20 Pixel intervals Text Heading and subheading Red circles 30, 120 210, 120 22 diameter Orange circles 40, 170 200, 170 18 diameter Yellow circles 75,205 165, 205 15 diameter Green triangle 120, 225 – can’t do triangles so we can use some diminishing rectangles Bitmap is 80 x 80 pixels. Top left is 80, 80. Fonts # Type Size Font face Colour Font Index Const Heading 15 pixels high Arial bold Orange Font 0 HEADINGF Subheading 24 pixels high Arial bold Orange Font 1 SUBHEADINGF Instructions 10 pixels high Arial White Font 2 INSTRUCTIONSF Combo 60 pixels high Arial bold Orange Font 3 COMBOF Digit 35 pixels high Arial bold Orange Font 4 We now know roughly what fonts we are gong to use. In Flowcode every font is assigned a number so again we declare constants for the fonts as you can see in the table. That saves us from having to remember what font is what.\nBitmaps # There is only one bitmap. Like fonts in Flowcode bitmaps are represented by numbers, but as there is only 1 - bitmap 0 - its easy enough to remember.\nScreens # Screen number Constants Home screen 0 HOMES Code entry screen 1 CODES Enter screen 2 ENTERS Denial Screen 3 DENIALS Each screen is represented by a number in the Flowcode program. We set up Global constants for these numbers so that we don’t have to remember what the numbers are.\nConnections # We can also define the connections both inside the M5 stack dial and outside. Flowcode needs the actual processor connections in order to drive the various chips and I/O inside the Dial. This is what we get when we dig into it: Display is GC9A01A round, 240 x 240 pixel\nSPI bus with the following connections:\nMOSI A5 (GPIO5) MISO A1 (GPIO1) CLK A6 (GPIO6) CS A7 (GPIO7) DC RS A4 (GPIO4) Reset A8 (GPIO8) Backlight A9 (GPIO9) Bezel switch B10 (GPIO5) Buzzer A3 (GPIO3) Bezel encoder A B9 (GPIO41) B B8 (GPIO40) I2C SCL A15 (GPIO15) SDA A13 (GPIO13) Relay on I/O pin A1 (GPIO1), A2 (GPIO2) Video # Over to you # Now we need to set up the hardware for the project. You can see this on the photograph. We have an M5stack Dial connected to the PC via USB.\nThere is a board with two relays on that are connected to the general purpose IO pins G10 and G2. That allows us to switch 24A AT 28V - should be enough for a Maglock. For prototyping purposes I have put a small solenoid on the board to simulate the Maglock function. This is powered by a 24V plug top power supply.\nThere is a Grove board with a SHT21 temperature and humidity sensor. This is connected to the Dial I2C pins GPIO13 and GPIO15.\nGet your M5stack Dial, relay board and SHT31 board and a suitable power supply and set up your project.\nYou can see ours here:\nNext step # Assignment 2: Using the Display\n","date":"9 December 2024","externalUrl":null,"permalink":"/workshops/flowcode/01-planning/","section":"Workshops","summary":"","title":"Flowcode - M5 Stack Dial Workshop - 1. Planning","type":"workshops"},{"content":"In this section we show you how to use the Display component in Flowcode. Once you know the colours, fonts and other parameters of your design, display graphics are just a series of commands to draw the lines, graphics and text in the right places.\nOne of the great features of Flowcode is that you can simulate the graphical display on screen - this saves hours of coding time.\nFirst set up the panel in Flowcode as above: PWM channel connected to PortA.9 (GPIO9) This allows us to control the brightness of the display.\nThen add the GC9A01A_SPI display. Use the images here to get the correct settings.\nIf you need more information then you can left click on the display and click on HELP to get more information from the Flowcode Wiki.\nNotice that we have not got the exact fonts that we wanted - Flowcode does not include all fonts - although more can be made - but the fonts that we have should be fine.\nYou can also set up the Bitmap drawer. This will need the central graphic copying to the same directory as the Flowcode file so that it simulates properly.\nThe flowchart you can see above will produce the screen you can see below.\nOver to you # Now that you understand the basics of how to control the graphics and text you can complete the design of the first screen using the specification:\nDownload the program to the M5 stack dial and check is all works ok! Note that if you want to you can also create your program in C code or in Pseudocode:\nOpen the program ‘Using the display.fcfx’ and download it to your M5 stack Dial.\nUse Flowcode to create the Home screen you can see here.\nMake sure you include the light purple cross hatch - you may want to make a separate macro to print those.\nYou will need to have the bitmap ‘M5Stack Lock Test Purple.bmp’ in the same directory as the Flowcode program. Video and example file # A Flowcode example file accompanies this tutorial:\n2 - Using the display.fcfx Further reading: Flowcode Wiki.\nNext step # Assignment 3: Switch and I/O Pins\n","date":"9 December 2024","externalUrl":null,"permalink":"/workshops/flowcode/02-using-the-display/","section":"Workshops","summary":"","title":"Flowcode - M5 Stack Dial Workshop - 2. Using the Display","type":"workshops"},{"content":"There were quite a few new concepts in the previous section. This section is relatively easy: we are going to look at how you can use the Bezel switch and the general purpose I/O.\nThe Bezel switch is connected to B10 (GPIO42) and the I/O is connected to A1, A2 (GPIO1, GPIO2).\nStart a new M5stack Dial program in Flowcode. Add a switch and a LED to the 2D panel and create the program you can see here.\nThis is a simple program that reads the value of the switch on the bezel (B10 or GPIO42) and sends it to the pins on A1 and A4 (GPIO10 and GPIO2). You can simulate this and you can check it works by sending it to your hardware.\nSo what?\nYou will notice that the switch logic is reversed: when the bezel is pressed the input at Port B10 (GPIO42) goes low.\nOver to you # Modify the program so that the output stays on for 5 seconds when the bezel is pressed. Try the same program but use GPIO pins 13 and 15 rather than 10 and 42. Does the program work?\nVideo and example file # A Flowcode example file accompanies this tutorial:\n3 - Using the IO.fcfx Further reading: Flowcode Wiki.\nNext step # Assignment 4: The Bezel Encoder\n","date":"9 December 2024","externalUrl":null,"permalink":"/workshops/flowcode/03-switch-io-pins/","section":"Workshops","summary":"","title":"Flowcode - M5 Stack Dial Workshop - 3. Switch and I/O Pins","type":"workshops"},{"content":"The bezel encoder feeds into two inputs - GPIO 40 and 41. When you rotate the bezel the inputs go high - first one then the other. The direction of rotation dictates which of the two inputs goes high first. The Quadrature encoder component in Flowcode takes care of the details for you and increments or decrements a counter in the component itself. You need to detect when a change has been made using an interrupt and then read the counter value.\nStart with the previous program where you learned how to use the bezel switch and the Input Output pins. Add an Encoder and connect it to B.9 (GPIO41) and B.8 (GPIO40). Alter the properties as you can see in the image here.\nYour panel should look like this:\nThis program sets up interrupts for the GPIO pins 40 and 41 - the internal Bezel connections. The interrupts call the Encoderint macro which just checks for changes on the Encoder.\nAlter your program so that it looks like the flow chart here.\nNote that you will need to set up an Interrupt Macro with just one command in it.\nOver to you # Combine the functionality of the Bezel encoder, the switch and the display by altering the encoder counter to reset when the Bezel switch is pressed. You can use the Encoder hardware macro ‘Resetcounter’ for this.\nVideo and example file # A Flowcode example file accompanies this tutorial:\n4 - Using the encoder.fcfx Further reading: Flowcode Wiki.\nNext step # Assignment 5: I2C Expansion\n","date":"9 December 2024","externalUrl":null,"permalink":"/workshops/flowcode/04-the-bezel-encoder/","section":"Workshops","summary":"","title":"Flowcode - M5 Stack Dial Workshop - 4. The bezel encoder","type":"workshops"},{"content":"In this section we are going to read a sensor value using the I2C connection on the M5 Stack Dial.\nIn this case we will use a small Grove sensor that contains a SH31 temperature and humidity chip.\nOf course it’s a bit odd having a temperature and humidity sensor on a door lock! But it allows us to teach you how you can take advantage of the huge range of I2C sensors and expansion devices to extend the functionality of your M5stack Dial.\nStart with the program you made in the previous section.\nAdd a SHT31 Temp / Humidity sensor from the Sensors component section.\nAdjust its properties as you can see here:\nYou should have a panel that looks like this:\nAdd two variables of type INT: Temperature and Humidity.\nThen develop the program you can see below.\nThe program is easy to read but there are a few things of note:\nThe program initialises the display and the SHT31 sensor. Initialisation is used on many components to set up registers inside the microcontroller.\nWhen reading and display a value like this one issue you have is that you are writing new numbers on top of old ones. When the number changes the display becomes hard to read. So we need to clear the area of the screen before we rewrite the number. Clearing the screen takes time - its quicker to draw a rectangle of the background colour (black here).\nOver to you # In practice the temperature and humidity are quantities that change very slowly. So there is no need to constantly rewrite the values on the screen. Develop a program that only redraws the values when they change.\nVideo and example file # A Flowcode example file accompanies this tutorial:\n5 - Expanding with I2C.fcfx Further reading: Flowcode Wiki.\nNext step # Assignment 6: Menu System\n","date":"9 December 2024","externalUrl":null,"permalink":"/workshops/flowcode/05-i2c-expansion/","section":"Workshops","summary":"","title":"Flowcode - M5 Stack Dial Workshop - 5. I2C Expansion","type":"workshops"},{"content":" In this section we look at how you can create a menu system using Flowcode. To make coding easier we have a separate macro subroutine for each menu. One key issue here is that you need to make sure that you close each subroutine when navigating between screens. using a variable flag to control navigation. It’s a slightly odd structure but easy enough to create.\nIn Flowcode each screen is a separate mini subroutine program or ‘macro’ with an endless While loop. The navigation is controlled by two variables OldScreen and NewScreen. A screen navigation change is carried out by altering the NewScreen variable which is examined in the While loop every cycle. This structure might be a little unfamiliar to some engineers, but it is actually really flexible and it allows us to prevent while loops from not being closed - and hence the microcontroller subroutine stack clean - good coding practice.\nAt the core of this is a Switch or Case statement in the Main macro. This is driven by numbers so we declare some global constants representing the screens as follows:\nScreen number Constants Home screen 0 HOMESCREEN Code entry screen 1 CODESCREEN Enter screen 2 ENTERSCREEN Denial Screen 3 DENIALSCREEN Let’s see how this works: The code in the main screen is shown here.\nWe initialise the screen and set the brightness then jump straight into the main look with the Switch statement which controls navigation between screens.\nIn the Homescreen macro we print a message on the screen and then wait for the Bezel stiwch to be pressed. Remember that the swith is active low - it gives logic 0 when pressed so the test in the If statement is ‘Bezelswitch=0’.The Newscreen variable is altered to be the CODESCREEN.\nYou can see the other three macros for the other menus here. The code is similar to the Home screen.\nSo this program just cycles between the screens on the press of the Bezel switch.\nOver to You # We will not ask you to construct this program from scratch as there are now quite a few elements to it. Instead open the “6 - driving a menu.fcfx” Flowcode file and download it to your M5 stack Dial. Make sure that you can get it working and that you understand the program.\nIn this example we simply navigated between the screens, one after the other, using the bezel switch. In practice you might want a slightly different menu system driven from the front panel using the bezel encoder to select the screen that will be navigated to and the Bezel switch to make the selection. To implement this:\nAlter the Home screen so that it prints ENTER, CODE, DENIAL above each other on the M5 Stack Dial.\nPrint these in white text to start with. Modify the program to select the value of a new variable, Nextcreen, between 1 and 3 Overprint the ENTER, CODE, DENIAL text with red text as the encoder cycles the value of Nextscreen. Overprint in white the screen text as it is deselected. When the bezel switch is pressed change the program so that it navigates to the selected screen. Now you understand how to do menu selection with the bezel encoder and switch. You can use this simple technique to implement your own menu selection system.\nVideo and example file # A Flowcode example file accompanies this tutorial:\n6 - Driving a menu.fcfx Further reading: Flowcode Wiki.\nNext step # Assignment 7: Connecting to the web\n","date":"9 December 2024","externalUrl":null,"permalink":"/workshops/flowcode/06-menu-system/","section":"Workshops","summary":"","title":"Flowcode - M5 Stack Dial Workshop - 6. Menu System","type":"workshops"},{"content":"In this section we look at how you can create a mobile phone app to control the M5stack Dial. This works on Wifi and on the local router. Controlling the Dial from outside the range of the local router involves the use of a web Broker which we will not look at here.\nThe mobile phone app will allow you to control the Dial from anywhere in the range of the router.\nFlowcode Web Developer allows you to create Apps that work in a browser. It does this using the same PC interface as Flowcode Embedded - but it creates Javascript programs. If you have not used Javascript before there are three fundamental changes that you will need to get to grips with:\nFirstly Javascript is not like other programming languages - it is an object orientated programming language where one event or object calls another. Secondly Browsers can not be ‘talked to’ cold. Pages and their content can only be fetched by browsers from the server. That means that to send commands to an embedded system it needs to detect which pages have been accessed. So detecting a fetch of page “on.htm” might turn a light on and detecting a fetch of page “off.htm” might turn a light off. Correspondingly if we detect a page access of “getinfo.htm” then the returning HTML content can be the temperature value - or status of a switch etc. That allows us to have two way communication - but only instigated by the Javascript program in the browser on - in this case - the mobile phone. You will need to develop 2 programs: a Flowcode Embedded program that goes into the M5Stack Dial and a Flowcode Web Developer program that runs on your mobile phone. The Flowcode Embedded and Flowcode Web Developer programs are quite unfamiliar so its best to download the examples and work through them rather than create them from scratch.\nFirstly lets look at the Flowcode Embedded program “7 - Connecting to web FE.fcfx”. Here is the panel:\nThis builds on the panels in the previous programs. To the panel we have added a Web server, a Network comms layer component and a Wireless LAN component for the ESP32 chip. They all link together.\nWe need to pass information to and from the M5stack Dial Embedded system and the mobile phone. So how do we do this? Here is the strategy:\nEmbedded system initialisation # Connect to the wifi. Router assigns an IP address – in this case automatically assigned to 192.168.1.141 (you will have a slightly different number). Create a socket for communications to take place Controlling the state of an output on an embedded system # Mobile phone browser requests page “192.168.1.141/Enter.html”. Embedded system detects “192.168.1.141/Enter.html” request. Embedded system navigates to the Enter screen macro and the door is opened for 4 seconds Embedded system responds with “Door opened” Getting a temperature variable from the embedded system # Client browser requests page “192.168.1.141/gettemp.html”. Embedded system detects “192.168.1.141/gettemp.html” request in the HTML Callback macro Embedded system takes temperature sample from SHT31 sensor. Embedded system responds with the relevant data served HTML Client browser picks up the HTML data and displays it on the mobile phone We initialise the Wifi component and connect to the Router. This is a standard domestic Router and you will need to enter your Wifi network and password details.\nIf the connection is unsuccessful then we print an error on the Dial screen.\nIf the connection is successful we print the IP address and open a socket. Then we include the menu system from the previous program.\nThe next thing we need to do is periodically check the Web connection to see if a page has been requested. We do this by putting a CheckSocketActivity() command in the loop on each screen macro as you can see here:\nWhen there is activity then the HTMLcallback macro is automatically triggered:\nThe IP address is generated automatically by the server: in this case “192.168.1.141”.\nTo open the door lock remotely the phone/browser accesses the web page: “192.168.1. 141/Enter.html”. The HTML callback macro is automatically activated. If “enter.html“ is fetched then the Newscreen variable is changed to Enterscreen and the program continues from there at the end of the HTMLcallback macro. The message “unlocked” is returned as the fetched HTML.\nIf “gettemp.htm” is fetched then the temperature sensors is read, converted to a string and this string is served up as the fetched HTML.\nLets now look at the Web Developer program that creates the Javascript file:\nThe Web Developer program panel looks like this:\nIt contains an Enter button, A text field, A HTTP Fetch command component - FetchForEnter - a read Temp button, a\nDial indicator and a second HTTP Fetch component FetchForReadTemp.\nThe Enter button calls the Macro Enter:\nThe Enter macro calls the HTTP Fetch component FetchForEnter. This sends a page request to the server for page “192.168.1.141/enter.htm” which is set as a property of the FetchForEnter component.\nFetchForEnter component.has as a property the EnterConfirmation macro which is called after the Fetch is executed. Any returning HTML - in this case the confirmation text - is passed to the EnterConfirmation macro as a parameter.\nThe EnterConfirmation macro sets the text field to the HTML returned by the FetchForEnter call, then it waits 4seconds and sets the text field to “Locked”.\nSimilarly the ReadTemp macro calls the macro GetTemp. This simply calls the HTTP Fetch component FetchForReadTemp which accesses the page “192.168.1.141/gettemp.htm” which is set as a property of the FetchForReadTemp component. The FetchForReadTemp component.has as a property the SetGaugeValue macro which is called after the Fetch is executed. Any returning HTML - in this case the temperature value - is passed to the SetGaugeValue macro as a parameter.\nThe SetGauge macro sets the value of the Gauge to the temperature.\nOver to you # The web program and the embedded program only examined the Temperature.\nExpand both programs so that the Humidity is also read from the SHT31 and displayed on the mobile phone on a separate dial.\nAlter the text in the message box on the mobile phone so that it displays a different message\nVideo and example files # Mobile Phone App # A Flowcode example file accompanies this tutorial:\n7 - Connecting to web - Embedded.fcfx 7 - Connecting to web - Web Developer.fcfx Further reading: Flowcode Wiki.\nNext step # Assignment 8: Full Project\n","date":"9 December 2024","externalUrl":null,"permalink":"/workshops/flowcode/07-connecting-to-the-web/","section":"Workshops","summary":"","title":"Flowcode - M5 Stack Dial Workshop - 7. Connecting to the web","type":"workshops"},{"content":"If you have got this far then well done. You will have learned a lot about embedded programming, about developing apps for mobile devices and about electronics in general. You have learned the basics of how to construct all the individual elements of the system. Its up to you now to complete it.\nWhat we have done is completed the project for you so that you can refer to it when you get stuck. There are two final files: “7 - Connecting to web FE.fcfx” and “7 - Connecting to web FWD.fcfx”.\nOver to you # You have all the bones of the system in place. To get to the final design you need to do the following:\nDesign all the individual screen graphics. Refer to the Planning section for details of the graphics, colours, fonts etc. We suggest that you embed the graphic of the menus needed onto your Embedded program panel so it looks like this: Get the navigation between screens working properly. Get the logic for a successful combination to be entered properly in place. Get the communication between the Mobile phone and the M5Stack Dial working properly. This is a great creative challenge.\nGood luck and have fun!\nVideo and example files # A Flowcode example file accompanies this tutorial:\nFull project - Embedded.fcfx Full Project - Web Developer.fcfx Further reading: Flowcode Wiki.\nFurther reading # We hope that you have enjoyed this course.\nAdditional free courses that are available from the Flowcode team are:\nCAN bus communications Embedded internet communications Bluetooth communications GSM communications For further information on Flowcode see:\nwww.flowcode.co.uk\nFor further information on Educational hardware products from the Matrix team see:\nhttps://www.matrixtsl.com/eblocks/\n","date":"9 December 2024","externalUrl":null,"permalink":"/workshops/flowcode/08-full-project/","section":"Workshops","summary":"","title":"Flowcode - M5 Stack Dial Workshop - 8. Full Project","type":"workshops"},{"content":"John is an engineer with 40 years of experience in the development and manufacture of electronic products including televisions, satellite receivers, microcontroller development tools and a huge range of educational products.\nJohn is the founder of Matrix TSL – the UK’s leading engineering education equipment manufacturer. John is also the Project Manager for the Flowcode software development team.\n","date":"9 December 2024","externalUrl":null,"permalink":"/authors/john-dobson/","section":"Developer Portal Authors","summary":"","title":"John Dobson","type":"authors"},{"content":"","date":"9 December 2024","externalUrl":null,"permalink":"/tags/process/","section":"Tags","summary":"","title":"Process","type":"tags"},{"content":"","date":"5 December 2024","externalUrl":null,"permalink":"/tags/assembly/","section":"Tags","summary":"","title":"Assembly","type":"tags"},{"content":"","date":"5 December 2024","externalUrl":null,"permalink":"/tags/dsp/","section":"Tags","summary":"","title":"DSP","type":"tags"},{"content":"The recent breakthroughs in artificial intelligence technology in such fields as image recognition, speech recognition, and natural language processing have opened up more possibilities for embedded system applications. When attempting to deploy AI model inference on embedded devices such as the ESP32-P4, we always strive to minimize inference time as much as possible to meet real-time requirements.\nPIE (Processor Instruction Extensions), as a set of new extended instructions introduced in ESP32-S3/ESP32-P4, is designed to enhance the efficiency of specific AI and DSP (Digital Signal Processing) algorithms. Based on the SIMD (Single Instruction Multiple Data) concept, it supports vector operations in 8-bit, 16-bit, and 32-bit formats, significantly enhancing computational efficiency. Furthermore, for such operations as multiplication, shifting, and accumulation, PIE enables simultaneous data movement during computation, which further boosts the execution efficiency of individual instructions.\nTo understand the PIE, this article will analyze and test it from the perspectives of the instruction architecture, basic instruction format, and its applications.\nPIE Differences: ESP32-S3 vs. ESP32-P4 # You can use PIE on both the ESP32-S3 and ESP32-P4. Although the differences in applying the PIE on these two chips are minimal, you still need to pay attention to the distinctions between them:\nInstruction Architecture Differences: The PIE of the ESP32-S3 are designed based on the TIE (Tensilica Instruction Extension), while the ESP32-P4 supports the standard RV32IMAFCZc extension and includes a custom Xhwlp (hardware loop) extension to improve the efficiency of executing for-loops in hardware. Internal Structure Differences: Taking multiplication-accumulation (MAC) as an example, the ESP32-S3 has two 160-bit accumulators, while the ESP32-P4 has two 256-bit accumulators. Instruction Format Differences: The PIE of ESP32-S3 and ESP32-P4 are largely similar. However, it is important to note that ESP32-S3 instructions start with ee, while ESP32-P4 instructions start with esp. Additionally, some instructions may differ in functionality or usage; for detailed information, please refer to the respective technical reference manual. Multiplication-accumulation (MAC) instructions The diagram above shows the data path of the multiplier-accumulator within the PIE, with differences between ESP32-S3 and ESP32-P4 highlighted using the dashed boxes. Blue represents ESP32-S3, and green represents ESP32-P4. A more detailed explanation for the blocks in the diagram from left to right:\nMemory: It is used to store and quickly access data. Address Unit: Most of the instructions in PIE allow loading or storing data from/to 128-bit Q registers in parallel in one cycle. Additionally, The Address unit provides functionality to manipulate address registers in parallel, which saves the time to update address registers. Vector Registers: It contains eight 128-bit wide vector registers (QR). Each register can be represented as an array of 16 8-bit data elements, an array of 8 16-bit data elements, or an array of 4 32-bit data elements. ALU: It performs arithmetic operations such as addition, subtraction, and bitwise operations like AND, OR, shift, etc. The input for ALU operations comes from QR registers. QACC Accumulator Register: It is used for saving 16 8-bit MAC results or 8 16-bit MAC results. For the ESP32-S3, QACC consists of two parts: a 160-bit QACC_H and a 160-bit QACC_L. Meanwhile, for the ESP32-P4, the sizes of QACC_H and QACC_L are 256-bit each. It is possible to load data from memory to QACC or reset the initial value to 0. ACCX Accumulator Register: Some operations require accumulating the result of all multipliers to one value. In this case, the ACCX accumulator should be used. ACCX is a 40-bit accumulator register. The result of the accumulators could be shifted and stored in the memory as an 8-bit or 16-bit value. If you\u0026rsquo;re unfamiliar with the PIE architecture mentioned above, don\u0026rsquo;t worry. This article will demonstrate the application and performance acceleration of PIE from a practical perspective in an intuitive manner.\nBasic Instruction Formats and Applications # If your work often involves AI model inference or signal processing, you are likely to frequently encounter operations such as memory copying and vector computations. Take memory copy and vector addition as examples, you can utilize the PIE instruction through inline assembly or .s files. It is important to note that most instructions in PIE can load or store data from the 128-bit Q register within a single cycle; therefore, data should be 128-bit aligned.\nMemory Copy Acceleration # In memory copy scenarios, the eight 128-bit Q registers in PIE can be used to read and store data, achieving memory copy acceleration. The PIE format of the ESP32-P4 is as follows:\nesp.vld.128.ip qu,rs1,imm # Load 128-bit data from memory ; This instruction loads 128-bit data from memory to the register qu, ; with the pointer incremented by an immediate. ; imm starts at -2048, ends at 2032, and steps by 16. esp.vst.128.ip qu,rs1,imm # Store 128-bit data to memory ; This instruction stores the 128 bits in the register qu to memory, ; with the pointer incremented by an immediate. ; imm starts at -2048, ends at 2032, and steps in increments of 16 Next, based on the above instructions, write the code for memory copying in the form of a .s file.\n.data .align 16 .text .align 4 .global memcpy_pie .type memcpy_pie, @function memcpy_pie: # a0: store_ptr # a1: load_ptr # a2: length(bytes) li x28,0 Loop: esp.vld.128.ip q0, a1, 16 esp.vld.128.ip q1, a1, 16 esp.vld.128.ip q2, a1, 16 esp.vld.128.ip q3, a1, 16 esp.vld.128.ip q4, a1, 16 esp.vld.128.ip q5, a1, 16 esp.vld.128.ip q6, a1, 16 esp.vld.128.ip q7, a1, 16 esp.vst.128.ip q0, a0, 16 esp.vst.128.ip q1, a0, 16 esp.vst.128.ip q2, a0, 16 esp.vst.128.ip q3, a0, 16 esp.vst.128.ip q4, a0, 16 esp.vst.128.ip q5, a0, 16 esp.vst.128.ip q6, a0, 16 esp.vst.128.ip q7, a0, 16 addi x28, x28, 128 bge x28, a2, exit j Loop exit: ret In the above assembly file, the original data is stored in registers q0 to q7, respectively, and written back to the designated memory block.\nComparison of Memory Copy Efficiency A comparison experiment of memcpy is conducted on the ESP32-P4 in this article. The ESP32-P4 is configured to run at 360 MHz, with a 128 KB L2 cache size and 64 Bytes L2 cache line size. The test results show that, over 100 repeated rounds of copying 2040 bytes, the PIE version is 74.3% faster than the standard library and 97.2% faster than the ANSI C version with single-byte copying.\nFurther insights might be gained from exploring the reasons why the standard memcpy is more efficient than single-byte copying based on ANSI C, and why the PIE version of memory copying is the fastest.\nNewlib-esp32 includes the implementation of memcpy for various platforms. Taking the RISC-V-based ESP32-P4 as an example, compared to single-byte copying, the optimized memcpy improves data copying efficiency by using memory alignment and large block transfers. At the same time, the PIE further accelerates the memory copying speed by using eight 128-bit registers to load and store data.\nvoid * __inhibit_loop_to_libcall memcpy(void *__restrict aa, const void *__restrict bb, size_t n) { #define BODY(a, b, t) { \\ t tt = *b; \\ a++, b++; \\ *(a - 1) = tt; \\ } char *a = (char *)aa; const char *b = (const char *)bb; char *end = a + n; uintptr_t msk = sizeof (long) - 1; if (unlikely ((((uintptr_t)a \u0026amp; msk) != ((uintptr_t)b \u0026amp; msk)) || n \u0026lt; sizeof (long))) { small: if (__builtin_expect (a \u0026lt; end, 1)) while (a \u0026lt; end) BODY (a, b, char); return aa; } if (unlikely (((uintptr_t)a \u0026amp; msk) != 0)) while ((uintptr_t)a \u0026amp; msk) BODY (a, b, char); long *la = (long *)a; const long *lb = (const long *)b; long *lend = (long *)((uintptr_t)end \u0026amp; ~msk); if (unlikely (lend - la \u0026gt; 8)) { while (lend - la \u0026gt; 8) { long b0 = *lb++; long b1 = *lb++; long b2 = *lb++; long b3 = *lb++; long b4 = *lb++; long b5 = *lb++; long b6 = *lb++; long b7 = *lb++; long b8 = *lb++; *la++ = b0; *la++ = b1; *la++ = b2; *la++ = b3; *la++ = b4; *la++ = b5; *la++ = b6; *la++ = b7; *la++ = b8; } } while (la \u0026lt; lend) BODY (la, lb, long); a = (char *)la; b = (const char *)lb; if (unlikely (a \u0026lt; end)) goto small; return aa; } Mathematical Operations Acceleration # Taking vector addition of type int16_t as an example, compared to memory copy, it adds an additional addition instruction. The instruction format on the ESP32-P4 is as follows:\nesp.vadd.s16 qv, qx, qy ; This instruction performs a vector signed addition ; on 16-bit data in the two registers qx and qy. ; Then, the 8 results obtained from the calculation are saturated, ; and the saturated results are written to the register qv. Next, PIE will be written using inline assembly.\nvoid add_ansic(int16_t *x, int16_t *y, int16_t *z, int n) { for (int i = 0; i \u0026lt; n; i++) { z[i] = x[i] + y[i]; } } void add_pie(int16_t *x, int16_t *y, int16_t *z, int n) { asm volatile( \u0026#34; addi sp, sp, -32 \\n\u0026#34; \u0026#34; sw x31, 28(sp) \\n\u0026#34; \u0026#34; sw x30, 24(sp) \\n\u0026#34; \u0026#34; sw x29, 20(sp) \\n\u0026#34; \u0026#34; sw x28, 16(sp) \\n\u0026#34; \u0026#34; sw x27, 12(sp) \\n\u0026#34; \u0026#34; mv x31, %0 \\n\u0026#34; \u0026#34; mv x30, %1 \\n\u0026#34; \u0026#34; mv x29, %2 \\n\u0026#34; \u0026#34; mv x28, %3 \\n\u0026#34; \u0026#34;li x27, 0 \\n\u0026#34; \u0026#34;loop:\\n\u0026#34; \u0026#34; beq x27, x28, exit \\n\u0026#34; \u0026#34; esp.vld.128.ip q0, x31, 16 \\n\u0026#34; \u0026#34; esp.vld.128.ip q1, x31, 16 \\n\u0026#34; \u0026#34; esp.vld.128.ip q2, x31, 16 \\n\u0026#34; \u0026#34; esp.vld.128.ip q3, x31, 16 \\n\u0026#34; \u0026#34; esp.vld.128.ip q4, x30, 16 \\n\u0026#34; \u0026#34; esp.vld.128.ip q5, x30, 16 \\n\u0026#34; \u0026#34; esp.vld.128.ip q6, x30, 16 \\n\u0026#34; \u0026#34; esp.vld.128.ip q7, x30, 16 \\n\u0026#34; \u0026#34; esp.vadd.s16 q0, q0, q4 \\n\u0026#34; \u0026#34; esp.vadd.s16 q1, q1, q5 \\n\u0026#34; \u0026#34; esp.vadd.s16 q2, q2, q6 \\n\u0026#34; \u0026#34; esp.vadd.s16 q3, q3, q7 \\n\u0026#34; \u0026#34; esp.vst.128.ip q0, x29, 16 \\n\u0026#34; \u0026#34; esp.vst.128.ip q1, x29, 16 \\n\u0026#34; \u0026#34; esp.vst.128.ip q2, x29, 16 \\n\u0026#34; \u0026#34; esp.vst.128.ip q3, x29, 16 \\n\u0026#34; \u0026#34; addi x27, x27, 32 \\n\u0026#34; \u0026#34; j loop \\n\u0026#34; \u0026#34;exit:\\n\u0026#34; \u0026#34; lw x31, 28(sp) \\n\u0026#34; \u0026#34; lw x30, 24(sp) \\n\u0026#34; \u0026#34; lw x29, 20(sp) \\n\u0026#34; \u0026#34; lw x28, 16(sp) \\n\u0026#34; \u0026#34; lw x27, 12(sp) \\n\u0026#34; \u0026#34; addi sp, sp, 32 \\n\u0026#34; :: \u0026#34;r\u0026#34; (x), \u0026#34;r\u0026#34; (y) , \u0026#34;r\u0026#34; (z), \u0026#34;r\u0026#34; (n) ); } Comparison of Mathematical Operation Efficiency Subsequently, under the same conditions as the memory copy experiment, 100 rounds of int16_t vector addition have been conducted, with each vector having a length of 2048. The test results show that the PIE version was 93.8% faster compared to the ANSI C version.\nOverall, this article introduces two application scenarios of PIE and two implementation methods. PIE also includes other commands, which you can test by referring to the process described above.\nAdd PIE-based components to the project # If you prefer not to write PIE instructions but still want to accelerate AI inference or signal processing, you can try using components with integrated PIE instructions to simplify the development process. As of now, the following Espressif\u0026rsquo;s official components can be easily integrated into your existing projects to accelerate AI and DSP performance:\nesp-tflite-micro: the esp-nn component within esp-tflite-micro uses PIE to optimize certain basic AI operators, which can further accelerate model inference time. esp-dl: esp-dl provides a lightweight and efficient neural network inference framework specifically designed for ESP series chips, efficiently implementing common AI operators such as Conv2D, Pool2D, Gemm, Add, and Mul. esp-dsp: esp-dsp uses assembly optimization for mathematical operations such as matrix multiplication, dot product, and FFT, and also provides an ANSI-C implementation. AI and DSP Components Containing PIE Summary # To summarize, some key advantages of PIE are:\n128-bit vector operations, e.g., multiplication, addition, subtraction, accumulation, shifting, and comparison. Integration of data transfer into arithmetic instructions. Support for non-aligned 128-bit vector data. Configurable rounding and saturation modes. With the help of PIE instructions or related components, you can attempt to accelerate the computation process in your existing projects.\nPlease do try and share your experiences!\n","date":"5 December 2024","externalUrl":null,"permalink":"/blog/2024/12/pie-introduction/","section":"Blog","summary":"","title":"Explore the PIE capabilities on the ESP32-P4","type":"blog"},{"content":"","date":"5 December 2024","externalUrl":null,"permalink":"/tags/pie/","section":"Tags","summary":"","title":"PIE","type":"tags"},{"content":"","date":"2 December 2024","externalUrl":null,"permalink":"/tags/driver/","section":"Tags","summary":"","title":"Driver","type":"tags"},{"content":"Using a monolithic architecture to develop complex applications tightly integrated with all the business logic, peripheral drivers, protocols, cloud connectivity, and so on, might sound like a nightmare. Yet, this is common in embedded systems, because it helps keep the resource overhead to the minimum. Inevitably, such approach makes collaborative development, maintenance, and reuse of code challenging to say the least.\nThese days the resources in embedded systems are not as limited as before, which makes the use of modular architecture more reasonable. This is exactly what ESP-IDF offers. The self-contained modules that implement most of the system functions are called ESP-IDF components.\nThere are two types of ESP-IDF components: built-in components and project components. Built-in components are part of the system whose APIs can be called directly from your application. Project components can be added to your project according to your needs in order to extend the ESP-IDF functionality.\nYou can add the project components from the ESP component registry, from third-party sources, or you can choose to create your own components. This article covers the project components you can create yourself and add to your project.\nConceiving the component # Frequently, placing self-contained parts of code in a separate component not only helps to keep the application code cleaner, but also simplifies development and maintenance. To get started with the component development process, we need to understand the basic structure and how the component will interact with the application.\nAs covered in the article What is the ESP Component Registry, a component can be either created directly in the application or in a separated project and then added to the application.\nWhat is the ESP Component Registry? 8 November 2024\u0026middot;6 mins Registry Component ESP-IDF When choosing whether to create a component in a separate project, consider if you plan to share the component with other applications. If yes, the best approach is to create the component in a new project that will contain just the component and examples if needed.\nThis article will not cover how to publish the component in the ESP Component Registry. It will be covered in the next article of this series. For this tutorial, we will create an example component that simplifies communication with an I2C device. This component will be a driver for a sensor and can be used as a starting point for any other component.\nTo simplify hardware setup, we chose the existing ESP32-C3-DevKit-RUST-1 development board that integrates the SHTC3 I2C sensor. This sensor is an I2C temperature and humidity sensor with a typical accuracy of ±2 %RH and ±0.2 °C. You can find its specification on the official product page.\nTo be precise, the ESP32-C3-DevKit-RUST-1 development board integrates two sensors connected to the I2C peripheral on the following GPIOs:\nSignal GPIO SDA GPIO10 SCL GPIO8 All the project files for this board are available on GitHub.\nesp-rs/esp-rust-board Open Hardware with ESP32-C3 compatible with Feather specification designed in KiCad null 632 45 If you don\u0026rsquo;t have the proposed hardware, you can choose any other I2C device. All the information you might need should be provided by the manufacturer, including the device address, registers, etc. Creating the component # To create the component, we will go through some steps:\nCreate a new project (skip this step if you already have one). Add a new component inside the project. Write the component code. Test the component We assume that you already have the ESP-IDF version 5.2 or higher installed on your system. Create a new project # To create a new component, we will use a project as the starting point. This project will be used to develop and test the component. However, you can also create the component as a stand-alone without using a project.\nOn the CLI, create a new project named my_project_with_components using the command:\nidf.py create-project my_project_with_components Now inside the my_project_with_components folder, let\u0026rsquo;s test the build for the ESP32-C3 (this is the SoC we are using in the example below). However, you can use any other SoC.\ncd my_project_with_components idf.py set-target esp32c3 idf.py build If the build finished successfully, now it\u0026rsquo;s time to create the component.\nAdd a new component # The component can be created manually, however, the recommended way is to use the ESP-IDF idf.py tool with the create-component command to create all the basic component skeleton.\nIt is recommended that the components be stored in the folder components in the root of the project. To create such folder and the basic component skeleton for our shtc3 component project, we will use the following convenience command (notice the use of -C components to create the folder):\nidf.py create-component -C components shtc3 As a result, the new folder should contain the following structure:\n. └── components └── shtc3 ├── CMakeLists.txt ├── include │ └── shtc3.h └── shtc3.c Now we have created the component structure, including all the required files, you can populate the component with your own code. To illustrate this process, we will walk through the process for creating the I2C sensor SHTC3.\nWrite the component code # We will now create the required code for the component to get the values from the sensor using I2C peripheral. The focus for the code explanation will be more on the new I2C driver driver/i2c_master.h.\nTo avoid a very long code description, please see the full code on the SHTC3 component repository on GitHub.\npedrominatel/esp-components ESP Component Registry repository for my components. C 6 5 The basic flow for the component side will be:\nCreate the I2C device that will be attached read from the I2C bus. The I2C bus will be handled by the component example or the project that will use the component. Read the sensor registers Temperature Humidity ID/serial Set the sensor registers Wake Sleep Detach the sensor from the bus On the include/shtc3.h:\n#include \u0026#34;driver/i2c_master.h\u0026#34; #define SHTC3_I2C_ADDR ((uint8_t)0x70) // I2C address of SHTC3 sensor The SHTC3 sensor address is 0x70 and there is no address selection, so we can use always the same address.\nCreate the enumeration to hold the registers that can be read or written to the sensor.\n// SHTC3 register addresses write only typedef enum { SHTC3_REG_READ_ID = 0xEFC8, // Read ID register SHTC3_REG_WAKE = 0x3517, // Wake up sensor SHTC3_REG_SLEEP = 0xB098, // Put sensor to sleep SHTC3_REG_SOFT_RESET = 0x805D // Soft reset } shtc3_register_w_t; // SHTC3 register addresses read-write typedef enum { // Temperature first with clock stretching enabled in normal mode SHTC3_REG_T_CSE_NM = 0x7CA2, // Humidity first with clock stretching enabled in normal mode SHTC3_REG_RH_CSE_NM = 0x5C24, // Temperature first with clock stretching enabled in low power mode SHTC3_REG_T_CSE_LM = 0x6458, // Humidity first with clock stretching enabled in low power mode SHTC3_REG_RH_CSE_LM = 0x44DE, // Temperature first with clock stretching disabled in normal mode SHTC3_REG_T_CSD_NM = 0x7866, // Humidity first with clock stretching disabled in normal mode SHTC3_REG_RH_CSD_NM = 0x58E0, // Temperature first with clock stretching disabled in low power mode SHTC3_REG_T_CSD_LM = 0x609C, // Humidity first with clock stretching disabled in low power mode SHTC3_REG_RH_CSD_LM = 0x401A } shtc3_register_rw_t; As mentioned before, this project will be based on the new I2C API from ESP-IDF.\nAdd the REQUIRES \u0026quot;driver\u0026quot; to the component CMakeLists.txt located inside the component folder shtc3.\nidf_component_register( SRCS \u0026#34;shtc3.c\u0026#34; INCLUDE_DIRS \u0026#34;include\u0026#34; REQUIRES \u0026#34;driver\u0026#34; ) On the shtc3.c file:\nWe can start by creating the function to handle the I2C device creation, that will be attached to the bus.\ni2c_master_dev_handle_t shtc3_device_create(i2c_master_bus_handle_t bus_handle, const uint16_t dev_addr, const uint32_t dev_speed) { i2c_device_config_t dev_cfg = { .dev_addr_length = I2C_ADDR_BIT_LEN_7, .device_address = dev_addr, .scl_speed_hz = dev_speed, }; i2c_master_dev_handle_t dev_handle; // Add device to the I2C bus ESP_ERROR_CHECK(i2c_master_bus_add_device(bus_handle, \u0026amp;dev_cfg, \u0026amp;dev_handle)); return dev_handle; } In this function, the i2c_master_bus_handle_t will be provided and then the device will be created and attached to the bus by calling i2c_master_bus_add_device.\nTo create the device, the following settings are required:\ndev_addr_length: Device address length, that could it be 7 or 8 bits. Please see this information in the datasheet. device_address: Device address. scl_speed_hz: Bus clock speed. For normal mode up to 100kHz and fast mode up to 400kHz. Once the device is attached to the bus, the i2c_master_dev_handle_t will be returned to be used on any read or write operation with this sensor.\nTo remove the device from the bus you can use the function i2c_master_bus_rm_device. Let\u0026rsquo;s add to our component.\nesp_err_t shtc3_device_delete(i2c_master_dev_handle_t dev_handle) { return i2c_master_bus_rm_device(dev_handle); } To read and write operations, we will use 2 functions:\ni2c_master_transmit: Perform a write transaction on the I2C bus. i2c_master_transmit_receive: Perform a write-read transaction on the I2C bus. The function i2c_master_receive will be not used on this component. The complete list of functions can be found on the documentation.\nOn this sensor, the recommended (see datasheet) flow is:\nWakeup command Measurement command Read out command Sleep command Now let\u0026rsquo;s add the register write function to wakeup and sleep:\nstatic esp_err_t shtc3_wake(i2c_master_dev_handle_t dev_handle) { esp_err_t ret; shtc3_register_w_t reg_addr = SHTC3_REG_WAKE; uint8_t read_reg[2] = { reg_addr \u0026gt;\u0026gt; 8, reg_addr \u0026amp; 0xff }; ret = i2c_master_transmit(dev_handle, read_reg, 2, -1); ESP_RETURN_ON_ERROR(ret, TAG, \u0026#34;Failed to wake up SHTC3 sensor\u0026#34;); return ret; } Sleep:\nstatic esp_err_t shtc3_sleep(i2c_master_dev_handle_t dev_handle) { esp_err_t ret; shtc3_register_w_t reg_addr = SHTC3_REG_SLEEP; uint8_t read_reg[2] = { reg_addr \u0026gt;\u0026gt; 8, reg_addr \u0026amp; 0xff }; ret = i2c_master_transmit(dev_handle, read_reg, 2, -1); ESP_RETURN_ON_ERROR(ret, TAG, \u0026#34;Failed to put SHTC3 sensor to sleep\u0026#34;); return ret; } To read the temperature and humidity from the sensor, now we will use the i2c_master_transmit_receive function.\nesp_err_t shtc3_get_th(i2c_master_dev_handle_t dev_handle, shtc3_register_rw_t reg, float *data1, float *data2) { esp_err_t ret; uint8_t b_read[6] = {0}; uint8_t read_reg[2] = { reg \u0026gt;\u0026gt; 8, reg \u0026amp; 0xff }; shtc3_wake(dev_handle); // Read 4 bytes of data from the sensor ret = i2c_master_transmit_receive(dev_handle, read_reg, 2, b_read, 6, 200); ESP_RETURN_ON_ERROR(ret, TAG, \u0026#34;Failed to read data from SHTC3 sensor\u0026#34;); shtc3_sleep(dev_handle); // Convert the data *data1 = ((((b_read[0] * 256.0) + b_read[1]) * 175) / 65535.0) - 45; *data2 = ((((b_read[3] * 256.0) + b_read[4]) * 100) / 65535.0); return ret; } On this function, we will wakeup the sensor, write and read the data (temperature and humidity) and set the sensor to sleep. The conversion from the raw values to the temperature in Celsius and humidity in %RH is also described in the sensor datasheet.\nThe CRC for the temperature and humidity will be not considered for this example. If you need to implement the CRC, please see the information provided by the manufacturer.\nThis is a very basic sensor, with no configuration or calibration registers.\nTest the component # To test the component, let\u0026rsquo;s go back to the project we have created before or the project you are using for creating this component.\nFor testing, the application will do:\nInitialize the I2C bus. Create the sensor I2C device. Probe the I2C bus and check the sensor presence. Get the sensor ID. Start a new task to read the sensor every 1000 ms (1 sec). On the app_main function in the example-shtc3.c file, add the bus initialization and the device creation functions.\ni2c_master_bus_handle_t i2c_bus_init(uint8_t sda_io, uint8_t scl_io) { i2c_master_bus_config_t i2c_bus_config = { .i2c_port = CONFIG_SHTC3_I2C_NUM, .sda_io_num = sda_io, .scl_io_num = scl_io, .clk_source = I2C_CLK_SRC_DEFAULT, .glitch_ignore_cnt = 7, .flags.enable_internal_pullup = true, }; i2c_master_bus_handle_t bus_handle; ESP_ERROR_CHECK(i2c_new_master_bus(\u0026amp;i2c_bus_config, \u0026amp;bus_handle)); ESP_LOGI(TAG, \u0026#34;I2C master bus created\u0026#34;); return bus_handle; } The bus initialization is done by the function i2c_new_master_bus and the bus_handle will be used to create the device on this bus. If you have more devices, you can add to the same bus, but this will be not covered on this article.\ni2c_master_bus_handle_t bus_handle = i2c_bus_init(SHTC3_SDA_GPIO, SHTC3_SCL_GPIO); shtc3_handle = shtc3_device_create(bus_handle, SHTC3_I2C_ADDR, CONFIG_SHTC3_I2C_CLK_SPEED_HZ); Make sure to import the component header file.\n#include \u0026#34;shtc3.h\u0026#34; Now to proof that the sensor is present in the I2C bus, we can probe and check it before the read and write operations. This probe has the timeout set to 200 ms.\nesp_err_t err = i2c_master_probe(bus_handle, SHTC3_I2C_ADDR, 200); With the probe result, we can decide if the read task will be created or not.\nif(err == ESP_OK) { ESP_LOGI(TAG, \u0026#34;SHTC3 sensor found\u0026#34;); uint8_t sensor_id[2]; err = shtc3_get_id(shtc3_handle, sensor_id); ESP_LOGI(TAG, \u0026#34;Sensor ID: 0x%02x%02x\u0026#34;, sensor_id[0], sensor_id[1]); if(err == ESP_OK) { ESP_LOGI(TAG, \u0026#34;SHTC3 ID read successfully\u0026#34;); xTaskCreate(shtc3_read_task, \u0026#34;shtc3_read_task\u0026#34;, 4096, NULL, 5, NULL); } else { ESP_LOGE(TAG, \u0026#34;Failed to read SHTC3 ID\u0026#34;); } } else { ESP_LOGE(TAG, \u0026#34;SHTC3 sensor not found\u0026#34;); shtc3_device_delete(shtc3_handle); } Task to read the sensor.\nvoid shtc3_read_task(void *pvParameters) { float temperature, humidity; esp_err_t err = ESP_OK; shtc3_register_rw_t reg = SHTC3_REG_T_CSE_NM; while (1) { err = shtc3_get_th(shtc3_handle, reg, \u0026amp;temperature, \u0026amp;humidity); if(err != ESP_OK) { ESP_LOGE(TAG, \u0026#34;Failed to read data from SHTC3 sensor\u0026#34;); } else { ESP_LOGI(TAG, \u0026#34;Temperature: %.2f C, Humidity: %.2f %%\u0026#34;, temperature, humidity); } vTaskDelay(1000 / portTICK_PERIOD_MS); } } On this task, the sensor will be woken up, the readout will be read and processed, and then the sensor will return to sleep mode.\nCreating Kconfig (optional) # As a bonus, this component has a dedicated configuration menu using a Kconfig file.\nKconfig is a configuration system used in software projects to define and manage configuration options in a structured and hierarchical way. It\u0026rsquo;s widely used in projects like the Linux kernel, Zephyr, and ESP-IDF (Espressif IoT Development Framework).\nOn this configuration menu, you will be able to set the I2C GPIOs (SDA and SCL), the I2C port number, and the bus frequency. This removes any hardcoded configuration from the source code.\nmenu \u0026#34;Driver SHTC3 Sensor\u0026#34; menu \u0026#34;I2C\u0026#34; config SHTC3_I2C_NUM int \u0026#34;I2C peripheral index\u0026#34; default -1 range -1 3 help For auto select I2C peripheral, set to -1. config SHTC3_I2C_SDA int \u0026#34;I2C SDA pin\u0026#34; default 17 range 0 55 help Set the I2C SDA pin for the data signal. config SHTC3_I2C_SCL int \u0026#34;I2C SCL pin\u0026#34; default 18 range 0 55 help Set the I2C SCL pin for the clock signal. config SHTC3_I2C_CLK_SPEED_HZ int \u0026#34;I2C clock speed (Hz)\u0026#34; default 100000 range 10000 400000 help Set the I2C clock speed in Hz. endmenu endmenu The Kconfig file should be placed on the component root directory. To set the values, you can use the command:\nidf.py menuconfig To configure the I2C, go to the Component config -\u0026gt; Driver SHTC3 Sensor and set the I2C SDA pin, I2C SCL pin, and the I2C clock speed (Hz).\nRunning the application # To run the application, run the command to flash and monitor using the idf.py. The application will print the temperature and humidity.\nidf.py flash monitor Console log output # Conclusion # In this article, we went through the basic steps of creating a component skeleton, adding it to a project, writing the code, testing it, and, finally, adding the configuration menu.\nEven though creating a new component requires a few additional steps, it helps improve the project architecture and make code reusable. This is a very powerful approach not only for creating driver components, but any other code that can work in a modular fashion. In the next article, we will show how this component can be published to the ESP Component Registry to share with the community.\nReference # ESP-Registry ESP-Registry Documentation Compote Documentation Component Examples My Components ","date":"2 December 2024","externalUrl":null,"permalink":"/blog/2024/12/how-to-create-an-esp-idf-component/","section":"Blog","summary":"","title":"How to create an ESP-IDF component","type":"blog"},{"content":"","date":"2 December 2024","externalUrl":null,"permalink":"/tags/i2c/","section":"Tags","summary":"","title":"I2C","type":"tags"},{"content":"","date":"2 December 2024","externalUrl":null,"permalink":"/tags/registry/","section":"Tags","summary":"","title":"Registry","type":"tags"},{"content":"","date":"27 November 2024","externalUrl":null,"permalink":"/tags/drivers/","section":"Tags","summary":"","title":"Drivers","type":"tags"},{"content":"","date":"27 November 2024","externalUrl":null,"permalink":"/tags/esp-iot-solution/","section":"Tags","summary":"","title":"Esp-Iot-Solution","type":"tags"},{"content":"Today, Espressif is excited to announce the release of esp-iot-solution v2.0. The components in the release/v2.0 branch will receive bugfix maintenance for two years (until January 25, 2027, ESP-IDF v5.3 EOL). This version categorizes and organizes commonly used IoT development features, including display, lighting, sensors, audio, motor control, input devices, USB, and more.\nEach category contains multiple feature-rich components that users can install, use, and update individually via the ESP Component Manager. Additionally, this version offers a wealth of example code to help users get started quickly. Below, we introduce some representative components.\nFor more detailed information, please refer to the esp-iot-solution v2.0 documentation.\nBasic Components # button # Buttons are an essential part of IoT devices. In esp-iot-solution v2.0, the button component provides a complete set of button drivers and event handling features, supporting single-click, double-click, long-press, and more. It supports various button types, including standard buttons, ADC buttons, matrix buttons, and custom buttons. Additionally, it offers features like button debounce and sleep mode. With the button component, users can focus on event handling without needing to understand the underlying button drivers.\nled_indicator # LED indicators are also a fundamental and necessary feature in IoT devices, providing timely visual feedback to help users quickly understand device status. The led_indicator component in esp-iot-solution v2.0 offers a comprehensive LED indicator solution, covering LED effect design (including color, brightness, and blinking), LED priority management, and LED effect switching. It is compatible with various LED types, including single-color LEDs, RGB LEDs, and WS2812 LEDs.\nElectrical and Lighting # lightbulb_driver # For professional developers and lighting system integrators, Espressif offers a cost-effective lighting solution that enables users to quickly develop high-performance, low-power smart lighting products. The lightbulb_driver component integrates multiple dimming schemes and simplifies application integration through an abstraction layer, fully supporting all ESP32 series chips. It supports PWM, IIC, and single-wire dimming schemes, including RGB+cool/warm color temperature, RGB+CCT/brightness, and more. The component also provides features like gradient effects, white balance calibration, power-off memory, and configurations for up to five types of LEDs, with power limitation and low power consumption characteristics.\nzero_detection # Zero-cross detection is a crucial part of dimmers, used to detect the zero-crossing point of voltage or current waveforms to adjust the lights at the optimal time. This not only achieves smooth, flicker-free dimming but also reduces electromagnetic interference (EMI) and extends the lifespan of the lights. The zero_detection component uses MCPWM capture or GPIO interrupts to detect signal periods and trigger edges, determine signal validity, and handle signal loss, providing foundational support for dimmer design.\nDisplay Components # display/lcd # Espressif provides developers with a comprehensive LCD driver solution guide, covering the entire process from LCD driver development to GUI applications. Based on the ESP-IDF esp_lcd component, it offers numerous LCD drivers supporting QSPI, RGB, MIPI, and other interfaces. Additionally, this version introduces the innovative esp_lcd_usb_display component, which allows projecting display content onto a PC via USB, significantly enhancing debugging and development efficiency.\ndisplay/tools # For resource-limited devices, esp-iot-solution v2.0 offers a lightweight file system management tool: esp_mmap_assets. This component supports fast loading and displaying of image data. To better support GUI applications, it provides an interface for LVGL to interact with the file system, allowing loading of fonts, images, and other resources from the file system.\nUSB Components # usb_device_uvc # UVC (USB Video Class) is a USB device class standard for video devices. The usb_device_uvc component is a UVC device class library based on the USB-OTG peripheral, supporting the display of ESP\u0026rsquo;s image data on a PC or other host devices via USB-OTG. It supports various resolutions, frame rates, and formats, allowing users to send image data according to the UVC standard by simply registering callback functions. With this component, users can develop standard USB cameras, USB displays, and more. Espressif also provides a complete UVC device example to help users turn the ESP32-S3-EYE development board into a standard webcam.\nesp_msc_ota # esp_msc_ota is a firmware upgrade solution based on USB MSC (Mass Storage Class), supporting automatic firmware updates to ESP32 series devices via USB storage devices. Users can simply copy the firmware file to a USB device (such as a USB flash drive), insert it into the USB host interface of the ESP device, and achieve firmware upgrades. This solution is suitable for devices in non-network environments, such as outdoor advertising screens and lightboxes.\nMotor Control # esp_sensorless_bldc_control # Brushless Direct Current (BLDC) motors, which achieve better speed-torque characteristics and fast dynamic response through electronic commutation, have become an important part of modern industrial and consumer electronics. The esp_sensorless_bldc_control component provides a complete sensorless trapezoidal control solution, supporting both ADC sampling and comparator sampling methods, with features like position estimation, stall protection, overcurrent and undervoltage protection. Additionally, we offer a complete BLDC smart fan solution, supporting stepless speed regulation, natural wind, and Rainmaker remote control.\nesp_simplefoc # SimpleFOC is a popular open-source FOC control library. The esp_simplefoc component is an ESP adaptation of SimpleFOC, encapsulating peripheral interfaces to support any Espressif chip with LEDC or MCPWM, and optimizing FOC floating-point calculations to further improve control efficiency. By referring to the FOC examples provided in esp-iot-solution, users can quickly get started with FOC control and achieve efficient motor control.\nLarge Language Model (LLM) Integration # openai # OpenAI\u0026rsquo;s GPT series models, such as GPT-3, have become significant breakthroughs in the field of natural language processing, providing developers with powerful natural language processing capabilities. The openai component is an LLM integration component based on the OpenAI API, supporting various input methods including text, voice, and images, and multiple output formats including text, voice, and images. Users can quickly integrate OpenAI API with ESP series chips to achieve natural language processing functions. You can refer to the esp-box chatgpt_demo example to learn how to use the openai component.\nQuick Experience with esp-launchpad # esp-iot-solution v2.0 also provides esp-iot-solution-launchpad, allowing users to flash precompiled firmware via a web interface without installing any development environment, enabling a quick experience of the latest features.\nesp-iot-solution Launchpad More Features # Click here to see the complete list of components supported by esp-iot-solution v2.0. We welcome you to download and experience it. If you have any questions or suggestions, please raise them in esp-iot-solution/issues.\n","date":"27 November 2024","externalUrl":null,"permalink":"/blog/release-esp-iot-solution-v2/","section":"Blog","summary":"","title":"Espressif Releases esp-iot-solution v2.0","type":"blog"},{"content":"","date":"27 November 2024","externalUrl":null,"permalink":"/tags/experimental/","section":"Tags","summary":"","title":"Experimental","type":"tags"},{"content":"","date":"27 November 2024","externalUrl":null,"permalink":"/tags/graphics/","section":"Tags","summary":"","title":"Graphics","type":"tags"},{"content":" Introduction # Swift is a powerful and intuitive programming language, renowned for its expressive syntax, modern features, and safety. Originally designed for developing applications across Apple\u0026rsquo;s ecosystem—macOS, iOS, watchOS, and tvOS—Swift has gained popularity for its performance and developer-friendly nature.\nWhat is Embedded Swift? # Embedded Swift is subset of Swift programming language which extends the capabilities of Swift to the realm of embedded systems. It allows developers to write firmware and applications for microcontrollers using Swift, bringing modern programming paradigms to resource-constrained devices. By leveraging Embedded Swift, you can benefit from Swift\u0026rsquo;s features like optionals, generics, and strong type safety, even in an embedded context.\nIn this article, we\u0026rsquo;ll explore how to use Embedded Swift to develop graphical applications for microcontrollers. We\u0026rsquo;ll demonstrate how to integrate C libraries like SDL3 (Simple DirectMedia Layer 3), commonly used in desktop applications, into your Swift projects for embedded systems. With the help of the ESP-IDF (Espressif IoT Development Framework) and ESP-BSP (Board Support Package), we\u0026rsquo;ll create cross-platform applications that can run on various ESP32 boards with minimal effort.\nSpecifically, we\u0026rsquo;ll focus on the ESP32-C3 and ESP32-C6 microcontrollers, showcasing how to build and deploy Swift applications that utilize SDL3 for graphics rendering.\nIf you\u0026rsquo;re new to Embedded Swift, we recommend that you start by checking the article Build Embedded Swift Application for ESP32-C6.\nThe full project is available at GitHub repository.\nNote: Embedded Swift toolchain supports chips with RISC-V architecture (ESP32-C3, H2, C6, P4). Chips with Xtensa architecture are not supported due to missing support in LLVM (ESP32, S2, S3). What is SDL3? # SDL3 (Simple DirectMedia Layer 3) is a cross-platform software development library written in C, designed to provide low-level access to audio, keyboard, mouse, joystick, and graphics hardware. It is widely used for creating multimedia applications, games, and graphical user interfaces on various platforms, including Windows, macOS, and Linux.\nCombining Embedded Swift and SDL3 # Integrating SDL3 with Embedded Swift on the ESP32 platform allows developers to harness the strengths of both technologies.\nLet\u0026rsquo;s explore an example where the main logic is written in Embedded Swift using SDL3 for loading and displaying text and graphical assets.\nPrerequisites # Before getting started, make sure you have the following tools installed:\nSwift 6.1 (nightly): Download and install Swift for your operating system. ESP-IDF 5.5: Clone the ESP-IDF repository and set it up according to the installation guide. Setting Up the Development Environment # Install Swift # Download and install Swift 6.1 (nightly) from the official Swift website or use Swiftly installation tool. Ensure that the swiftc compiler is available in your system\u0026rsquo;s PATH.\nmacOS Linux Configure TOOLCHAINS environment variable with the version of the installed Swift 6.\nexport TOOLCHAINS=$(plutil -extract CFBundleIdentifier raw /Library/Developer/Toolchains/swift-DEVELOPMENT-SNAPSHOT-2024-10-30-a.xctoolchain/Info.plist) # Make sure to have ninja installed sudo apt install ninja-build # Installation using Swiftly - https://swiftlang.github.io/swiftly/ curl -L https://swiftlang.github.io/swiftly/swiftly-install.sh | bash swiftly install main-snapshot Install ESP-IDF # git clone https://github.com/espressif/esp-idf.git cd esp-idf ./install.sh . ./export.sh Integrating SDL3 with Embedded Swift # To use SDL3 in your Swift application, we\u0026rsquo;ll use a wrapper component in ESP-IDF that allows integration with C libraries. This is facilitated through a bridging header.\nUsing BridgingHeader.h # Create a BridgingHeader.h file in your project and include the necessary C headers:\n#include \u0026lt;stdio.h\u0026gt; /* ESP-IDF headers */ #include \u0026#34;freertos/FreeRTOS.h\u0026#34; #include \u0026#34;freertos/task.h\u0026#34; #include \u0026#34;sdkconfig.h\u0026#34; /* SDL3 headers */ #include \u0026#34;SDL3/SDL.h\u0026#34; #include \u0026#34;SDL3_ttf/SDL_ttf.h\u0026#34; /* ESP-IDF pthread support required by SDL3 */ #include \u0026#34;pthread.h\u0026#34; /* ESP-BSP Board support package */ #include \u0026#34;bsp/esp-bsp.h\u0026#34; /* ESP-IDF filesystem stored in flash memory */ #include \u0026#34;esp_vfs.h\u0026#34; #include \u0026#34;esp_littlefs.h\u0026#34; This header enables your Swift code to interact with the included C libraries.\nWriting the Application # Our main Swift file, Main.swift, contains the core logic of the application. The application initializes SDL, loads graphical assets, handles touch events, and renders sprites on the screen.\nOverview of Main.swift # Here\u0026rsquo;s a simplified version of Main.swift with initialization of pthread required by SDL3. ESP-IDF by default uses vTask, so the solution is to wrap the initial SDL call into pthread.\nfunc sdl_thread_entry_point(arg: UnsafeMutableRawPointer?) -\u0026gt; UnsafeMutableRawPointer? { // Initialize SDL if SDL_Init(UInt32(SDL_INIT_VIDEO | SDL_INIT_EVENTS)) == false { print(\u0026#34;Unable to initialize SDL\u0026#34;) return nil } print(\u0026#34;SDL initialized successfully\u0026#34;) guard let window = SDL_CreateWindow(nil, 320, 200, 0) else { return nil } // Create SDL renderer guard let renderer = SDL_CreateRenderer(window, nil) else { print(\u0026#34;Failed to create renderer\u0026#34;) return nil } SDL_SetRenderDrawColor(renderer, 22, 10, 33, 255) SDL_RenderClear(renderer) SDL_RenderPresent(renderer) // ... Main loop } @_cdecl(\u0026#34;app_main\u0026#34;) func app_main() { print(\u0026#34;Initializing SDL3 from Swift.\u0026#34;) // Initialize pthread attributes var sdl_pthread = pthread_t(bitPattern: 0) var attr = pthread_attr_t() pthread_attr_init(\u0026amp;attr) pthread_attr_setstacksize(\u0026amp;attr, 32000) // Set the stack size for the thread // Create the SDL thread let ret = pthread_create(\u0026amp;sdl_pthread, \u0026amp;attr, sdl_thread_entry_point, nil) if ret != 0 { print(\u0026#34;Failed to create SDL thread\u0026#34;) return } // Detach the thread pthread_detach(sdl_pthread) } Loading Assets with LittleFS # To load fonts and images, we use the LittleFS filesystem. The FileSystem.swift file initializes the filesystem, allowing access to assets stored in a flashed partition:\nfunc SDL_InitFS() { print(\u0026#34;Initializing File System\u0026#34;) var config = esp_vfs_littlefs_conf_t( base_path: strdup(\u0026#34;/assets\u0026#34;), partition_label: strdup(\u0026#34;assets\u0026#34;), partition: nil, format_if_mount_failed: 0, read_only: 0, dont_mount: 0, grow_on_mount: 0 ) let result = esp_vfs_littlefs_register(\u0026amp;config) if result != ESP_OK { print(\u0026#34;Failed to mount or format filesystem\u0026#34;) } else { print(\u0026#34;Filesystem mounted\u0026#34;) } } Drawing Sprites Loaded from Files # With the filesystem initialized and assets stored in the LittleFS partition, we can proceed to load images and render them using SDL3. This section demonstrates how to load a sprite from a file and display it on the screen, providing a foundation for creating interactive graphical applications.\nLoading Images with SDL3 # To display images, we need to load them into our application as textures. In our example, we have two types of sprites: coins and dangers (e.g., obstacles). These images are stored in BMP format in the /assets directory.\nHere\u0026rsquo;s how we load these images:\n// Initialize SDL_ttf for font rendering TTF_Init() // Load the font let font = TTF_OpenFont(\u0026#34;/assets/FreeSans.ttf\u0026#34;, 42) if font == nil { print(\u0026#34;Font load failed\u0026#34;) } // Load the coin image let coinSurface = SDL_LoadBMP(\u0026#34;/assets/coin_gold.bmp\u0026#34;) if coinSurface == nil { print(\u0026#34;Failed to load coin image\u0026#34;) } let coinTexture = SDL_CreateTextureFromSurface(renderer, coinSurface) SDL_DestroySurface(coinSurface) // Load the danger image let dangerSurface = SDL_LoadBMP(\u0026#34;/assets/slime_normal.bmp\u0026#34;) if dangerSurface == nil { print(\u0026#34;Failed to load danger image\u0026#34;) } let dangerTexture = SDL_CreateTextureFromSurface(renderer, dangerSurface) SDL_DestroySurface(dangerSurface) Explanation of Font Functions # Initializing SDL_ttf: We call TTF_Init() to initialize the SDL_ttf library, which is necessary for font rendering. Loading the Font: TTF_OpenFont() loads the font file from the filesystem. In this case, we\u0026rsquo;re using FreeSans.ttf. Creating Textures: SDL_CreateTextureFromSurface() converts the surface into a texture for rendering. Displaying a Sprite and Text # After initializing the filesystem with LittleFS and setting up SDL, we can proceed to load an image and display it at a fixed position on the screen. Additionally, we\u0026rsquo;ll render some text to display alongside the image. This simple example demonstrates how to work with sprites and text rendering in SDL3 using Embedded Swift.\nLoading and Displaying an Image # First, we\u0026rsquo;ll load an image from the filesystem and create a texture that can be rendered on the screen.\n// Load the image from the assets directory let imageSurface = SDL_LoadBMP(\u0026#34;/assets/coin_gold.bmp\u0026#34;) if imageSurface == nil { print(\u0026#34;Failed to load image: \\(String(cString: SDL_GetError()))\u0026#34;) } // Create a texture from the surface let imageTexture = SDL_CreateTextureFromSurface(renderer, imageSurface) SDL_DestroySurface(imageSurface) Explanation of Image Functions # SDL_LoadBMP(): Loads a BMP image file from the specified path into an SDL_Surface. SDL_CreateTextureFromSurface(): Converts the surface into an SDL_Texture, which is optimized for rendering. SDL_DestroySurface(): Frees the memory associated with the surface since it\u0026rsquo;s no longer needed after creating the texture. Next, we\u0026rsquo;ll define a rectangle that specifies where and how large the image will appear on the screen.\n// Define the destination rectangle for the image var imageRect = SDL_FRect(x: 100.0, y: 80.0, w: 128.0, h: 128.0) Rendering Text with SDL_ttf # To display text, we\u0026rsquo;ll use the SDL_ttf library, which allows us to render TrueType fonts.\nif TTF_Init() != 0 { print(\u0026#34;Failed to initialize SDL_ttf: \\(String(cString: TTF_GetError()))\u0026#34;) } let font = TTF_OpenFont(\u0026#34;/assets/FreeSans.ttf\u0026#34;, 24) if font == nil { print(\u0026#34;Failed to load font: \\(String(cString: TTF_GetError()))\u0026#34;) } // Create the text to render let message = \u0026#34;Hello, ESP32!\u0026#34; var messageBuffer = Array(message.utf8CString) // Render the text to a surface let textColor = SDL_Color(r: 255, g: 255, b: 255, a: 255) let textSurface = TTF_RenderText_Blended(font, \u0026amp;messageBuffer, 0, textColor) if textSurface == nil { print(\u0026#34;Failed to render text: \\(String(cString: TTF_GetError()))\u0026#34;) } // Create a texture from the text surface let textTexture = SDL_CreateTextureFromSurface(renderer, textSurface) SDL_DestroySurface(textSurface) // Define the destination rectangle for the text var textRect = SDL_FRect(x: 80.0, y: 220.0, w: 160.0, h: 40.0) Using ESP-BSP for Board Support # To make the application portable across different ESP32 boards, we use the ESP-BSP (Board Support Package). This allows us to switch between boards easily.\nConfiguring idf_component.yml # In the idf_component.yml file, we specify dependencies and define rules for different boards:\ndependencies: joltwallet/littlefs: \u0026#34;==1.14.8\u0026#34; georgik/sdl: \u0026#34;==3.1.7~6\u0026#34; georgik/sdl_ttf: \u0026#34;^3.0.0~3\u0026#34; idf: version: \u0026#34;\u0026gt;=5.5.0\u0026#34; espressif/esp32_p4_function_ev_board_noglib: version: \u0026#34;3.0.1\u0026#34; rules: - if: \u0026#34;${BUILD_BOARD} == esp32_p4_function_ev_board_noglib\u0026#34; espressif/esp32_c3_lcdkit: version: \u0026#34;^1.1.0~1\u0026#34; rules: - if: \u0026#34;${BUILD_BOARD} == esp32_c3_lcdkit\u0026#34; espressif/esp_bsp_generic: version: \u0026#34;==1.2.1\u0026#34; rules: - if: \u0026#34;${BUILD_BOARD} == esp_bsp_generic\u0026#34; This configuration allows us to build the project for different targets using the idf.py command with the @boards/\u0026hellip; syntax.\nBuilding and Running the Application # Build for ESP32-P4-Function-Ev-Board:\nidf.py @boards/esp32_p4_function_ev_board.cfg flash monitor Running the Simulation # You can run the application in an online simulation using Wokwi. This allows you to test the application without physical hardware.\nYou can run the simulation also in VS Code or JetBrains IDE with installed Wokwi plugin. Open boards/.../diagram.json and click play button.\nUsing GitHub Actions for CI/CD # To automate the build, test, and release processes of our ESP32 Swift application, we utilize GitHub Actions. Continuous Integration/Continuous Deployment (CI/CD) is essential for maintaining code quality and ensuring that your application works as expected across different environments. In this section, we\u0026rsquo;ll delve into how our CI/CD pipeline is set up, focusing on aspects particularly relevant to embedded developers who may be new to these practices.\nOverview of the CI/CD Pipeline # Our CI/CD process is divided into three main workflows:\nBuild Workflow: Compiles the application for different boards and uploads the build artifacts. Test Workflow: Runs simulations using Wokwi to verify that the application functions correctly. Release Workflow: Creates a GitHub release and attaches the compiled binaries. The key idea is that the build step generates artifacts (compiled binaries), which are then consumed by the test and release steps. This modular approach ensures that each step is isolated and can be debugged or rerun independently.\nBuild Workflow # The build workflow automates the compilation of the application for various ESP32 boards. Here\u0026rsquo;s a simplified snippet of the build.yml file with focus on how we install Swift and set up the ESP-IDF action.\nInstalling Swift Compiler: Before building the project, we download and install the Swift compiler. This step is crucial because the ESP-IDF action doesn\u0026rsquo;t come with Swift support out of the box.\nBuilding with ESP-IDF and Swift: We use the espressif/esp-idf-ci-action GitHub Action to set up the ESP-IDF environment. The command parameter allows us to execute custom build commands, where we specify the build configuration and merge the binaries.\n- name: Install pkg-config run: sudo apt-get update \u0026amp;\u0026amp; sudo apt-get install -y pkg-config - name: Install Swift Compiler run: | wget https://download.swift.org/development/ubuntu2204/swift-DEVELOPMENT-SNAPSHOT-2024-10-30-a/swift-DEVELOPMENT-SNAPSHOT-2024-10-30-a-ubuntu22.04.tar.gz tar xzf swift-DEVELOPMENT-SNAPSHOT-2024-10-30-a-ubuntu22.04.tar.gz export PATH=\u0026#34;$PATH:${{ github.workspace }}/swift-DEVELOPMENT-SNAPSHOT-2024-10-30-a-ubuntu22.04/usr/bin\u0026#34; swiftc --version - name: Build with ESP-IDF and Swift uses: espressif/esp-idf-ci-action@v1.1.0 with: esp_idf_version: latest target: ${{ env.TARGET }} path: \u0026#39;.\u0026#39; command: | idf.py @boards/${{ matrix.board }}.cfg build \u0026amp;\u0026amp; cd build.${{ matrix.board }} \u0026amp;\u0026amp; esptool.py --chip ${{ env.TARGET }} merge_bin -o ${{ github.event.inputs.prefix }}-${{ matrix.board }}.bin \u0026#34;@flash_args\u0026#34; Test Workflow # The test workflow runs simulations of our application using Wokwi, a virtual environment for embedded systems. This step verifies that the application behaves as expected before releasing it.\nUsing Wokwi CI Server: We set up the Wokwi CI server, which allows us to run simulations of our firmware. - name: Use Wokwi CI Server uses: wokwi/wokwi-ci-server-action@v1 Running Simulation with Wokwi: This step runs the actual simulation. Note that we use a secret token WOKWI_CLI_TOKEN for authentication with Wokwi\u0026rsquo;s services. You can obtain this token by signing up at Wokwi CI Dashboard and adding it to your repository\u0026rsquo;s secrets.\n- name: Run Simulation with Wokwi uses: wokwi/wokwi-ci-action@v1 with: token: ${{ secrets.WOKWI_CLI_TOKEN }} path: boards/${{ matrix.board }} elf: build.${{ matrix.board }}/${{ github.event.inputs.prefix }}-${{ matrix.board }}.bin timeout: 20000 expect_text: \u0026#39;Entering main loop...\u0026#39; fail_text: \u0026#39;Rebooting...\u0026#39; serial_log_file: \u0026#39;wokwi-logs-${{ matrix.board }}.txt\u0026#39; Conclusion # By integrating Embedded Swift with SDL3 on the ESP32-C3 and ESP32-C6, you can leverage modern programming languages and desktop-class libraries to develop rich graphical applications for embedded systems. The use of ESP-BSP simplifies targeting multiple boards, making your applications more portable.\nWe encourage you to explore the GitHub repository for the full source code and additional details.\nReferences # Swift for ESP32 - Espressif Developer Portal Using ESP-BSP with DevKits ESP32 SDL3 Swift Example - GitHub VS Code - Wokwi plugin JetBrains IDE - Wokwi plugin ","date":"27 November 2024","externalUrl":null,"permalink":"/blog/integrating-embedded-swift-and-sdl3-on-esp32/","section":"Blog","summary":"","title":"Integrating Embedded Swift and SDL3 on ESP32","type":"blog"},{"content":"","date":"27 November 2024","externalUrl":null,"permalink":"/authors/li-bo/","section":"Developer Portal Authors","summary":"","title":"Li Bo","type":"authors"},{"content":"","date":"27 November 2024","externalUrl":null,"permalink":"/tags/sdl/","section":"Tags","summary":"","title":"SDL","type":"tags"},{"content":"","date":"27 November 2024","externalUrl":null,"permalink":"/tags/swift/","section":"Tags","summary":"","title":"Swift","type":"tags"},{"content":"Embedded systems can be quite complex, depending on the architecture, application size and nature. Even for an experienced embedded developer, understanding the interplay of threads, interrupts, and multiple processes that run in a large application can be challenging. We humans are (mostly) visual by nature, and having the means to visualize what is happening in a given system can really open up possibilities. Without the right tools we are often in the dark, quite literally.\nOne category of tools interesting to learn about is tracing and profiling. Tracing is collecting software execution data - the sequence and timing of execution of functions, threads, ISRs - and logging it for future analysis, without interrupting or interfering (at best) in the application execution. Profiling aims to measure performance metrics such as execution time, CPU usage, and dynamic memory usage. With such tools it is possible to evaluate how well an embedded system is performing, understand if the hardware used is adequate for the application being run and debug eventual problems.\nIn this article we are going to do a brief introduction and show some basic examples of these resources as implemented in Zephyr RTOS. Later we’ll take a look at some of the features offered by Percepio\u0026rsquo;s Tracealyzer, which is a third party solution that extends some of Zephyr\u0026rsquo;s tracing and profiling native functionalities and has a front-end tool to analyze the data.\nZephyr\u0026rsquo;s tracing tool # In order to show how Zephyr\u0026rsquo;s native tracing system works, the sample below can be flashed and run on a physical device such as an ESP32-C6. If you\u0026rsquo;re new to Zephyr please check [1].\nsamples/subsys/tracing\nFor this example, which uses the ESP32-C6\u0026rsquo;s USB JTAG port to output the logged data, the following settings should be configured:\nCONFIG_TRACING=y CONFIG_TRACING_CTF=y CONFIG_TRACING_BACKEND_UART=y CONFIG_TRACING_BUFFER_SIZE=4096 These settings activate the tracing feature, define the data stored format as CTF (Common Trace Format) and configure the output medium (UART). As UART was selected as the medium to transfer data from the device to the host (PC), an overlay config can inform Zephyr where to output data:\n/ { chosen { zephyr,tracing-uart = \u0026amp;usb_serial; }; }; \u0026amp;usb_serial { status = \u0026#34;okay\u0026#34;; }; To build the sample, use the following command:\nwest build -p -b esp32c6_devkitc samples/subsys/tracing/ -DCONF_FILE=prj_uart_ctf.conf Once the sample is flashed and the USB cable is connected to the ESP32-C6\u0026rsquo;s USB port, run Zephyr\u0026rsquo;s Python script to connect to the serial port and store the acquired data in a log file.\npython3 scripts/tracing/trace_capture_uart.py -d /dev/ttyACM0 -b 115200 -o ../tracing/trace_0 The option -o indicates the path and file name for the tracing data, so any path and name can be used. In this example we can use an arbitrary folder called “tracing” just outside Zephyr\u0026rsquo;s main folder.\nAfter some seconds of acquisition we can hit CTRL+C to stop recording and get back to the shell in the host PC.\nThe CTF tracing format requires data typing to be decoded, so the metadata (tracing format description) file needs to be present in the same folder:\ncp subsys/tracing/ctf/tsdl/metadata ../tracing/ Finally, to parse the CTF data and show the actual trace:\nbabeltrace2 ../tracing/ The output is something like:\nSample trace output\nThis log shows the execution order and timing of the traced objects, allowing us to visualize how the software is executing in the acquired interval. This gives the possibility of running statistics on how the CPU resources are used and helps to easily spot functions that are taking too long to execute, or are being executed at wrong moments, or more times than expected.\nObjects monitored # It is possible to control which kinds of objects are monitored. The following are currently supported [2]:\nstruct k_timer *_track_list_k_timer; struct k_mem_slab *_track_list_k_mem_slab; struct k_sem *_track_list_k_sem; struct k_mutex *_track_list_k_mutex; struct k_stack *_track_list_k_stack; struct k_msgq *_track_list_k_msgq; struct k_mbox *_track_list_k_mbox; struct k_pipe *_track_list_k_pipe; struct k_queue *_track_list_k_queue; struct k_event *_track_list_k_event; Kconfig\u0026rsquo;s menu Tracing Configuration will allow selecting which objects will be traced, with options like shown below:\nTRACING_SYSCALL=y/n TRACING_ISR=y/n TRACING_SEMAPHORE=y/n TRACING_HEAP=y/n TRACING_STACK=y/n TRACING_PM=y/n (...) If a large amount of data is to be generated, this might be useful to limit tracing only to the objects of interest, both to save buffer and provide a cleaner data acquisition.\nAnother interesting feature is the possibility of defining user functions to be called at tracing events, such as headers shown below. In a debugging situation or when external equipment (e.g., oscilloscope or data logger) is used, it can be useful to add custom code to the callbacks to drive a GPIO, for instance, in order to sync external acquisition data with the log provided by the tracing subsystem.\nTrace user functions\nThe following macros [3] are placed on Zephyr\u0026rsquo;s subsystems code to track important functions of the operating system:\nSYS_PORT_TRACING_FUNC(type, func, …) SYS_PORT_TRACING_FUNC_ENTER(type, func, …) SYS_PORT_TRACING_FUNC_EXIT(type, func, ...) This means that depending on the functionality being probed, the tracing subsystem might already have hooks that will acquire data by default, as can be seen in the example below:\n/* Called when data needs to be sent to network */ int net_send_data(struct net_pkt *pkt) { int status; int ret; SYS_PORT_TRACING_FUNC_ENTER(net, send_data, pkt); (...) } Instrumenting application, however, is currently not supported without manually implementing some code inside the tracing subsystem. For the time being, there are 3rd party tools that support such feature, and a new tool is expected to be integrated to Zephyr in the future that might as well support it [4].\nZephyr\u0026rsquo;s profiling tool # The current profiling implementation monitors the function stack in order to allow examining the software execution at given intervals. To enable it, the following configs must be defined:\nCONFIG_PROFILING=y CONFIG_PROFILING_PERF=y CONFIG_PROFILING_PERF_BUFFER_SIZE=2048 CONFIG_THREAD_STACK_INFO=y CONFIG_SMP=n CONFIG_SHELL=y CONFIG_FRAME_POINTER=y Using these directives it is possible to obtain a log that can be processed by tools and yield a composed view of what the system is executing:\nProfiling sample graph\nThe graph above shows a timeline of the functions pushed onto the stack, including all sub-function calls. While monitoring the function stack can be useful for analyzing certain kinds of problems, we won’t discuss this feature in detail, as it offers limited functionality for now. As mentioned earlier, a new subsystem is being developed that may provide better functionality [4].\nPercepio\u0026rsquo;s Tracealyzer # Zephyr offers support to third party tools that use the tracing subsystem and extend some of its functionalities in order to provide more resources. One of them is Percepio\u0026rsquo;s Tracealyzer. To enable it, the following configs must be set:\nCONFIG_TRACING=y CONFIG_PERCEPIO_TRACERECORDER=y The directions to configure a streaming port or use a RAM buffer to store the logged data can be found in reference [5].\nTracealyzer offers a front-end tool to analyze and process the collected data, helping visualize how the system is behaving dynamically:\nTracealyzer GUI\nThe process of instrumenting the code and selecting the right data to be acquired is analogous to using an oscilloscope or other kind of probe to evaluate hardware. One might need to place additional hooks (instrumentation for the tracing system to acquire data at a specific point) in the application code and change the base configuration to narrow data acquisition down to the areas of interest.\nThe GUI has tools to inspect the software execution sequence (as seen before with Zephyr\u0026rsquo;s native tracing), charts to evaluate CPU load, and plots to display acquired data. Embedded in the tool are reports that facilitate the evaluation of task/thread performance to check:\nCPU Usage Execution times Response times Periodicity Separation Fragmentation These statistics can help an experienced developer spot problems with any of the subsystems, as well as check timing and CPU load under any execution regime. Any anomaly can lead to a detailed investigation on what\u0026rsquo;s hindering performance, including glitches that will only be visible when enough data is collected.\nAnother interesting capability of Tracealyzer is helping monitor heap utilization. The following graph shows memory allocation/de-allocation over time, and it is paired with the synchronized trace view right below it. This renders possible to see if memory is allocated and freed accordingly or if memory leaks might be happening.\nMemory heap trace example\nIf memory leaks were present, allocation would only increase with time instead of reaching a mean usage level.\nAnother use case can be analysis of the interaction between threads and shared resources, such as message queues. Spotting problems like producers-consumers can be difficult, specially if it\u0026rsquo;s a glitch. If a synchronized signal can be added to the acquisition in order to point to the timestamp where the problem is happening - say, when a symptom is visible to the outside world - the acquired data can be very useful in solving the problem.\nProducer-consumer example\nThe examples below show custom channels added to capture application data:\nCustom channel state transitions\nCustom channel signals\nFinal remarks # While these examples are generic and the amount of possibilities that tracing and profiling tools can offer is vast, this article just scratches the surface in sharing some insights on how powerful these tools can be. Even though these examples may be more applicable to analyzing complex systems, it is well worth knowing them, as they may happen to be just the right tool for a specific problem. Besides that, even for use cases that require high reliability, using them with the intent of profiling the system in order to check how it behaves over time and certify its performance can be probably the best approach, as you\u0026rsquo;ll have real data to back up the perception that it is performing as intended.\nResources # [1] Zephyr\u0026rsquo;s Getting Started [2] Zephyr\u0026rsquo;s tracing subsystem [3] Tracing utility macros [4] Zephyr instrumentation subsystem (RFC) [5] Percepio TraceRecorder and Stream Ports The Microscope for Embedded Code: How Tracealyzer Revealed Our Bug Efficient Firmware Development with Visual Trace Diagnostics Tracealyzer on Zephyr – Examples from AC6 Percepio Tracealyzer\n","date":"15 November 2024","externalUrl":null,"permalink":"/blog/2024/11/zephyr-tracing-and-profiling/","section":"Blog","summary":"This is an introduction to the critical embedded system debugging techniques of tracing and profiling within the Zephyr RTOS. After reading this article, you can use Zephyr\u0026rsquo;s native tracing tools to gain a visual, in-depth understanding of system dynamics, helping to evaluate performance, spot timing issues, and diagnose complex problems like memory leaks or thread interaction glitches.","title":"Introduction to Zephyr OS Tracing and Profiling","type":"blog"},{"content":"","date":"15 November 2024","externalUrl":null,"permalink":"/tags/profiling/","section":"Tags","summary":"","title":"Profiling","type":"tags"},{"content":"","date":"15 November 2024","externalUrl":null,"permalink":"/authors/raffael-rostagno/","section":"Developer Portal Authors","summary":"","title":"Raffael Rostagno","type":"authors"},{"content":"","date":"15 November 2024","externalUrl":null,"permalink":"/tags/tracing/","section":"Tags","summary":"","title":"Tracing","type":"tags"},{"content":"","date":"13 November 2024","externalUrl":null,"permalink":"/tags/simulation/","section":"Tags","summary":"","title":"Simulation","type":"tags"},{"content":"In this article, we will examine how the NuttX real-time operating system (RTOS) can be used on the Wokwi simulator, what adjustments need to be made on the NuttX side for this and what advantages the Wokwi simulator offers.\nNote!\nNote: Reviewing this article together with NuttX on an emulated ESP32 using QEMU article will help the user to distinguish between the two solutions and to determine the most suitable solution for the needs. Additionally, it is recommended to have knowledge of project compilation through the NuttX official documentation and Getting Started with NuttX and ESP32 article. NuttX project build documentation is available at this link.\nWhat is Wokwi? # Wokwi is an online Electronics simulator. You can use it to simulate Arduino, ESP32, STM32, and many other popular boards, parts and sensors.\nWhat are the Advantages of Wokwi? # It provides the opportunity to start the project regardless of the delivery time of the parts required for the project.\nThere is no way to destroy virtual hardware. For that reason cash loss due to connection error is prevented and it provides the opportunity to undo the transaction after a step goes wrong.\nProvides convenience in getting help and feedback through the link to the project.\nHelps distinguish hardware and software based problems. This way, you can focus on the code side.\nIt allows the use of any number of hardware regardless of the project budget.\nSource\nNote: Of course, there will be differences between the simulation and the field. For this reason, the project running in simulation should not be taken to the field without testing.\nSupported devices # Here is the list of supported devices, separated by the core architecture.\nSoC Core Support Stage ESP32 Xtensa Release ESP32-S2 Xtensa Release ESP32-S3 Xtensa Release ESP32-C3 RISC-V Release ESP32-C6 RISC-V Release ESP32-H2 RISC-V Beta ESP32-P4 RISC-V Alpha Source. Apart from these, you can use this link for supported sensors and more.\nAlternatives and Differences # Among others, the most widely-known alternative to Wokwi is QEMU. QEMU stands out with faster operation if special optimizations are used. Wokwi offers more platform support, ease of installation, and simulation features with external parts.\nSimulating NuttX on Wokwi # Creating a NuttX System Image # You can create the development environment for Xtensa-based (ESP32, ESP32-S2, ESP32-S3) microcontrollers using this link. You can create the development environment for RISC-V based (ESP32-C3, ESP32-C6, ESP32-H2) microcontrollers using this link. Wokwi does not support compiling NuttX projects internally like ESP-IDF or Zephyr. Therefore, it is necessary to compile locally and continue the simulation part via Wokwi. In other words, we will simulate the NuttX output compiled in our own development environment via Wokwi.\nIn this article, we will use the nsh application for the ESP32 microcontroller as an example. If there is a previously selected configuration, use the following commands to reset the project and to select the configuration needed for the nsh application on the ESP32.\nmake distclean ./tool/configure.sh esp32-devkitc:nsh With these commands, we have selected the necessary card and configuration. To perform debugging, we need to run make menuconfig to open the Build System menu, select Debug Options, and activate the Generate Debug Symbols option. We can use the following command for the relevant setting:\nmake menuconfig The result will look something like this:\nIn addition to the debugging capability, it is recommended to enable the merge bin option to have one binary file. To enable that option, go to the Board Selection menu and set Merge raw binary files into a single file. The rest of this article assumes that this option is enabled.\nAfter configuration and setup, we can use the following command to compile:\nmake We should see the following output:\nLD: nuttx CP: nuttx.hex CP: nuttx.bin Generated: nuttx.merged.bin After the compilation process is successfully completed, we need the nuttx file for the simulation.\nSimulating NuttX Application in Wokwi # To use Wokwi with Visual Studio Code, you must first download the Wokwi for VS Code plug-in and enter the license key. You can get more detailed information about it here.\nWokwi basically works on two files - wokwi.toml and diagram.json:\nwokwi.toml: A configuration file that tells Wokwi how to run your project. Information such as \u0026rsquo;elf\u0026rsquo; and \u0026lsquo;firmware\u0026rsquo; file paths of the application are saved in this file.\ndiagram.json: A diagram file that describes the circuit. Information such as the microcontroller to be added to the circuit, peripheral units such as the sensor to be connected to the microcontroller, their locations, color and interconnection of the parts in the circuit are recorded in this file. You can use this link for detailed information.\nFor details about Wokwi configuration files, see here.\nIf we go back to the Simulation section after these definitions, we need to do two things:\nAdd the nuttx and nuttx.merged.bin file paths to the wokwi.toml file Add the circuit diagram in the diagram.json file to use in simulation The file contents we need in this example project will be as follows:\nwokwi.toml\n[wokwi] version = 1 firmware = \u0026#39;nuttx.merged.bin\u0026#39; elf = \u0026#39;nuttx\u0026#39; diagram.json\n{ \u0026#34;version\u0026#34;: 1, \u0026#34;author\u0026#34;: \u0026#34;Anonymous maker\u0026#34;, \u0026#34;editor\u0026#34;: \u0026#34;wokwi\u0026#34;, \u0026#34;parts\u0026#34;: [ { \u0026#34;type\u0026#34;: \u0026#34;board-esp32-devkit-c-v4\u0026#34;, \u0026#34;id\u0026#34;: \u0026#34;esp\u0026#34;, \u0026#34;attrs\u0026#34;: { \u0026#34;firmwareOffset\u0026#34;: \u0026#34;0\u0026#34;} } ], \u0026#34;connections\u0026#34;: [ [ \u0026#34;esp:TX\u0026#34;, \u0026#34;$serialMonitor:RX\u0026#34;, \u0026#34;\u0026#34;, [] ], [ \u0026#34;esp:RX\u0026#34;, \u0026#34;$serialMonitor:TX\u0026#34;, \u0026#34;\u0026#34;, [] ] ], \u0026#34;dependencies\u0026#34;: {} } If the merge bin option is not enabled, the firmware variable in wokwi.toml file will be set to nuttx.bin, and the firmwareOffset variable in the diagram.json file will be 0x1000. After creating the necessary files, we can start the simulation by pressing F1 and selecting the Wokwi: Start Simulator option:\nAfter that, Wokwi will be up and running and you can start using NuttX.\nNote: nsh may not appear at first startup. You can switch by pressing the Enter key.\nDebugging with Wokwi # Wokwi comes with built-in debugging support. For this process, first the cpp tools plug-in in the VSCode editor must be installed. Source\nAfterwards, in the wokwi.toml file, we need to add the following line to the [wokwi] section:\ngdbServerPort=3333 As a result of the process, the wokwi.toml file will look like this for this example:\n[wokwi] version = 1 firmware = \u0026#39;nuttx.merged.bin\u0026#39; elf = \u0026#39;nuttx\u0026#39; gdbServerPort=3333 After that, press F1 and select Wokwi: Start Simulator and Wait for Debugger to start the simulator. Wokwi will then go into standby mode to allow the debugger to connect. In a separate terminal tab you can run GDB with xtensa-esp32-elf-gdb or similar commands for Xtensa devices or riscv-none-elf-gdb for RISC-V devices. To establish a proper connection with Wokwi, the following commands need to be applied:\ntarget remote :3333 set remote hardware-watchpoint-limit 2 mon reset halt symbol-file nuttx flushregs c These commands can be entered manually after starting the debugger, or they can be provided as a script file. For example, if the commands are saved in a file named gdbinit, you can run GDB with this command:\nxtensa-esp32-elf-gdb -x gdbinit After running the debugger, you can start to debug with Wokwi using the F5 key in simulator.\nThis is one way to debug using the terminal, but there is also an alternative method that doesn’t require the terminal and everything can be done directly inside Visual Studio Code. If you want to avoid using the terminal-based debugger you need to create a launch configuration file for Visual Studio Code. You can create the file at .vscode/launch.json path or you can use Open user settings (JSON) option with pressing F1 key.\nHere\u0026rsquo;s a template you can use:\n{ \u0026#34;version\u0026#34;: \u0026#34;0.2.0\u0026#34;, \u0026#34;configurations\u0026#34;: [ { \u0026#34;name\u0026#34;: \u0026#34;Wokwi GDB\u0026#34;, \u0026#34;type\u0026#34;: \u0026#34;cppdbg\u0026#34;, \u0026#34;request\u0026#34;: \u0026#34;launch\u0026#34;, \u0026#34;program\u0026#34;: \u0026#34;${workspaceFolder}/nuttx/nuttx\u0026#34;, \u0026#34;cwd\u0026#34;: \u0026#34;${workspaceFolder}\u0026#34;, \u0026#34;MIMode\u0026#34;: \u0026#34;gdb\u0026#34;, \u0026#34;miDebuggerPath\u0026#34;: \u0026#34;/debugger/path/xtensa-esp32-elf-gdb\u0026#34;, \u0026#34;miDebuggerServerAddress\u0026#34;: \u0026#34;localhost:3333\u0026#34; } ] } For more detailed information about the debugging, you can visit this link.\nOf course, our hope is that you will not need this process :)\nConclusion # In this article, we have seen the features of Wokwi and how it can be used with NuttX. Of course, all the features of Wokwi are not limited to these. You can use this link to get more detailed information and examples about Wokwi.\nResources # NuttX Documentation NuttX GitHub NuttX channel on Youtube NuttX Developer Mailing List Wokwi Website Wokwi Documentation ","date":"13 November 2024","externalUrl":null,"permalink":"/blog/2024/11/using-wokwi-with-nuttx/","section":"Blog","summary":"","title":"Using Wokwi with NuttX","type":"blog"},{"content":"When starting a new project, we often reuse existing code, for example from libraries and drivers. This not only saves time but also makes your project easier to maintain.\nIn this article, we will explore what the ESP Component Registry is and the key concepts of components, making it easy to understand not only how to use components but also how to contribute.\nConcept # The architecture of ESP-IDF is modular, making it easier to understand and maintain. Such modules are called components, as opposed to libraries, because they are self-contained and can also communicates with other components. Components are used on top of the ESP-IDF core.\nThere are three concepts that we need to introduce in order to understand the complete solution: component, component manager, and component registry. Let\u0026rsquo;s go through them one by one.\n1. Component # As mentioned above, a component is a self-contained piece of code that offers new functionality and can be added to an application. In most cases, components are used in multiple applications, making it easy to reuse code, improve the efficiency, and reduce development complexity.\nFor example, let\u0026rsquo;s imagine there is an application called my-application in which we want to use a specific sensor that will collect temperature and humidity from the environment. Instead of adding all the logic behind the communication protocol, data collection, conversions, etc. to the application code, you can add a component i.e sensor-component, that has this logic already implemented in code. The important part is that this code has been reviewed and tested multiple times by other developers.\nThe component can be either created directly in the application, inside a specific folder named components, or it can be created in a separated component project and then added as a dependency to the application. Both solutions work but the recommended way is to create a new component project and add it as a dependency.\n2. Component Manager # Single components can quickly go out of hand if not managed properly. The component manager does just that \u0026ndash; it is a CLI tool that allows you to add existing components to your project and create new components.\nWith the component manager you can:\nAdd a component as a dependency to your application . Create new components structure. Downloads the dependencies automatically when running CMake. After adding a component as a dependency to your project and running the build process, the component manager will download the component to your project in a folder named managed_components. All the dependencies will be downloaded directly from the ESP Component Registry repository and will be stored inside this folder.\n3. Component Registry # ESP Component Registry Logo Now we have lots of components that can be managed in a project. But to make these components accessible to everyone, there should be some kind of central repository. This role is played by the ESP Component Registry. It helps maintain ESP-IDF components for users to easily find, install, use examples of, and eventually create and upload their own components.\nESP Component Registry Landing Page Currently, the Registry has 500+ components, developed by Espressif, partners, and the community.\nSome examples of existing components:\nled_strip: Driver designed for the addressable LEDs like WS2812. ds18b20: Driver for the DS18B20 temperature sensor using the 1-Wire protocol. arduino-esp32: Component for the Arduino core for the ESP32 to be used inside the ESP-IDF. esp_insights: Remote diagnostics solution that allows users to remotely monitor the health of ESP devices in the field. To get started with the ESP Component Registry, just search for a component and add it to your project. If you want to publish your component to the Registry, you will also need a GitHub account.\nComponent Page The process for publishing a component will be described in another article.\nAdding components from ESP Component Registry # For adding a component as a dependency to your project, you can use:\nidf.py add-dependency \u0026#34;espressif/led_strip^3.0.0\u0026#34; or you can create a new project from the example:\nidf.py create-project-from-example \u0026#34;espressif/led_strip^3.0.0:led_strip_rmt_ws2812\u0026#34; After running the command, you will need to build the application to download the components to the managed_components folder.\nIf the component is not added to your project after running build command, you can try to run the reconfigure command and build again:\nidf.py reconfigure Advantages of using components # Components are widely used in the ESP-IDF and many other applications based on the ESP-IDF.\nThe main advantages of using components are:\nCode reuse: You can reuse code among different applications by sharing the component.\nModularity: The component reduce the application complexity.\nFlexibility: Each component can be configured using individual Kconfig.\nTest: Each component can be tested individually.\nUsing your own components or components developed by Espressif, other companies, or the community, can speed up your development and it will be easy to maintain the application that uses the components.\nOne example we can use is dealing with a bug in a specific component that has been fixed in the latest version. You can run a command that will update the component to the latest version automatically.\nAdvantages of writing your own components # At this very moment, there might be a developer somewhere in the world searching for a driver, library, or anything that could help them develop their project. If you have what they are looking for but you haven\u0026rsquo;t shared it anywhere, they will have to reinvent the wheel and write it themselves. Next time you can end up in the same situation.\nYou can write many different types of components for your projects, including:\nDrivers Libraries Protocols Encoders/Decoders Parsers Features Utilities Tools Frameworks HAL Board Support Packages Besides that, making components can also help you with other projects that might use the same components, and keeping them in the Registry can save your time looking where the component was stored and how you manage the version, download, etc.\nThe main objective for the ESP Component Registry is to keep a single platform for components, where developers across the world can search and use the shared components, however, the way the components are managed by the Component Manager, makes the use of components very easy for any developer. The components are managed in a way that you can specify them as dependencies for your project and the build system will download the components from the Registry automatically during the first build.\nYou can find more components examples to inspire you at the ESP-BSP and the esp-iot-solution repository.\nConclusion # Using components in your project not only saves development time but also results in project modularity, which allows testing components individually. The ESP Component Registry can be a resource for parts you do not need to develop yourself.\nDeveloping your own components can help other developers and companies looking for similar solutions.\nReference # ESP Component Registry ESP Component Registry Documentation ESP-BSP esp-iot-solution ","date":"8 November 2024","externalUrl":null,"permalink":"/blog/2024/10/what-is-the-esp-registry/","section":"Blog","summary":"","title":"What is the ESP Component Registry?","type":"blog"},{"content":"","date":"4 November 2024","externalUrl":null,"permalink":"/tags/devkit/","section":"Tags","summary":"","title":"DevKit","type":"tags"},{"content":"","date":"4 November 2024","externalUrl":null,"permalink":"/authors/jakub-kocka/","section":"Developer Portal Authors","summary":"","title":"Jakub Kocka","type":"authors"},{"content":"","date":"4 November 2024","externalUrl":null,"permalink":"/tags/usb/","section":"Tags","summary":"","title":"USB","type":"tags"},{"content":"","date":"4 November 2024","externalUrl":null,"permalink":"/tags/windows/","section":"Tags","summary":"","title":"Windows","type":"tags"},{"content":"Released in 2016 by Microsoft, the Windows Subsystem for Linux (WSL) is a feature that allows the use of a Linux environment with no need of a virtual machine, container or dual boot. The WSL is a great way to run Linux alongside Windows.\nIntroduction # In some cases, users can\u0026rsquo;t use Windows PowerShell for developing ESP-IDF applications for ESP SoCs, or when WSL is already in use, the flashing and monitoring steps can be tricky.\nThis article is a step-by-step guide, provided to help you work with Espressif\u0026rsquo;s SoCs when using WSL.\nAlternatives # Many common operations (e.g., flashing, monitoring, etc. ) can be handled by the ESP_RFC2217_server (Telnet) where the host Windows machine acts as the server and the WSL terminal acts as the client. However, tools like OpenOCD (Open On-Chip Debugger) cannot be used with this approach.\nGuide # The following steps describe a serial port forwarding method for WSL using USBIPD-WIN. It is assumed that the latest version of WSL2 is already installed. A detailed guide and troubleshooting can be found in Microsoft documentation.\n(tested with: Windows 11 (23H2), USBIPD-WIN 4.3.0)\n1. Install the USBIPD-WIN # Using package manager in the host terminal, run:\nwinget install usbipd Or download the .msi file from the latest releases and install it manually.\nAfter the installation, the terminal must be restarted.\n2. Attach the USB # With the devkit connected, in the host terminal, run:\nusbipd list In this example, the devkit used is the ESP32-C6-DevKit-C, with the 1-1 is the BUSID, which will be needed in the following commands.\nBUSID VID:PID DEVICE STATE 1-1 303a:1001 USB Serial Device (COM4), USB JTAG/serial debug unit Not shared Now, bind the listed devkit with following command in host terminal (needs administrative privileges).\nusbipd bind --busid 1-1 Attach the device in the host terminal (needs already running instance of WSL).\nusbipd attach --wsl --busid 1-1 Now you should be able to see the devkit in the WSL terminal. You can run lsusb command to check it. You can now start using the attached serial port directly in the WSL.\nTroubleshooting note # If is not possible to use the devkit, even after attaching, but it is visible with the lsusb command, you can run the following command in the WSL terminal:\nsudo modprobe cp210x This will add kernel module with the needed controller only for the current instance.\nTo add this permanently, it can be done with the following command:\necho \u0026#34;cp210x\u0026#34; | sudo tee -a /etc/modules Detach the USB # When you don\u0026rsquo;t need to keep the devkit connected, you can detach the USB with this command:\nusbipd detach --busid 1-1 Conclusion # Working with WSL and Espressif\u0026rsquo;s SoCs, for certain use cases may not be that simple. While for basic operations, using the ESP_RFC2217_server might be enough (where the host machine acts as the server and the WSL terminal as the client) this method may not be always sufficient. In some cases, direct interaction with the devkits from within WSL becomes necessary. When that happens, serial port forwarding can be employed.\nWith the help of this guide, we hope the process is now clearer, making it easier for you to work with Espressif\u0026rsquo;s devkits in a WSL.\nResources # Windows Subsystem for Linux Documentation Microsoft documentation WSL - Connect USB devices USBIPD-WIN ","date":"4 November 2024","externalUrl":null,"permalink":"/blog/espressif-devkits-with-wsl2/","section":"Blog","summary":"","title":"Working with Espressif's SoCs using WSL2","type":"blog"},{"content":"","date":"4 November 2024","externalUrl":null,"permalink":"/tags/wsl/","section":"Tags","summary":"","title":"WSL","type":"tags"},{"content":"","date":"4 November 2024","externalUrl":null,"permalink":"/tags/wsl2/","section":"Tags","summary":"","title":"WSL2","type":"tags"},{"content":"Those acquainted with the ESP32 system-on-chip (SoC) family know the complexity involved in analyzing its booting process. From navigating the embedded ROM bootloader, facilitated by comprehensive tooling, to initiating the 2nd stage bootloader, which subsequently launches the user application. The procedure deviates significantly from the the straightforward \u0026ldquo;jump-to-reset-vector\u0026rdquo; way of starting the user program, as we can see on the ARM architecture.\nIn this article, I\u0026rsquo;ll explore the details of how the Espressif SoC boots up. I\u0026rsquo;ll focus on how it\u0026rsquo;s done specifically within the popular Zephyr RTOS, which has become a go-to choice for many vendors, including Espressif, the brains behind the ESP32.\nIntroduction # Our goal is to understand each boot stage and to recognize and fix the issues that come from the particular component or boot stage. So, let\u0026rsquo;s roll up our sleeves and explore how these pieces fit together!\nThe main building blocks of the article we will be investigating are:\nROM code \u0026amp; loader (image loader, reserved memory regions) 2nd stage loader (build types, bootstrap flow) Building (linking, memory utilization) Tooling (esptool.py, image formats) ROM code # The ESP32 SoCs have external flash memory which need certain attention prior to use. That is one of the reasons why ESP32 has on-chip ROM memory. All necessary startup, communication and the flash access libraries are stored and directly accessed from there.\nThere are certain functions available in the ROM code that are particularly useful (debugging, loading purposes) and can have an impact on the overall code footprint. However, using or not using the ROM functions during the application runtime is completely up to the user.\nROM loader # Main feature of ROM code is to load the image present at the flash non-volatile memory. Therefore we can refer to it as the 1st stage bootloader.\nThe binary image loaded by the ROM code must take a form recognizable by the loader. It uses the ESP image header and ESP segment header to identify the image and its subsequent segments.\nThe ESP image format header (24 Bytes):\ntypedef struct { uint8_t magic; /* Magic word 0xE9 */ uint8_t segment_count; /* Count of memory segments */ uint8_t spi_mode; /* flash read mode */ uint8_t spi_speed: 4; /* flash frequency */ uint8_t spi_size: 4; /* flash chip size */ uint32_t entry_addr; /* Entry address */ uint8_t wp_pin; /* WP pin when SPI pins set via efuse * 0xEE=disabled */ uint8_t spi_pin_drv[3]; /* Drive settings for the SPI flash pins */ uint16_t chip_id; /* Chip identification number */ uint8_t min_chip_rev; /* Minimal chip revision supported by image */ uint16_t min_chip_rev_full; /* format: major * 100 + minor */ uint16_t max_chip_rev_full; /* format: major * 100 + minor */ uint8_t reserved[4]; /* Reserved bytes in additional header space */ uint8_t hash_appended; /* If 1, a SHA256 digest \u0026#34;simple hash\u0026#34; * is appended after the checksum. */ } esp_image_header_t; The ESP image format segment header (8 Bytes):\ntypedef struct { uint32_t load_addr; /* Address of segment */ uint32_t data_len; /* Length of data */ } esp_image_segment_header_t; Graphical representation of the ESP image format:\nThe ESP image format.\nThis binary image format is used in 1st stage image loading, but can be adopted and used for other purposes as well. For example when providing an additional images for asymmetric multi processing (AMP).\n2nd stage # One of the roles of 2nd stage loader code is to initialize hardware for the user application code. The first loader only initialize the basic sets of functionality which is needed to load the code from the external flash memory. There are other peripherals and resources that can be set-up, but they are out of the scope of first loader. Implementation of those additional resources depends on used build scenario.\nSingle image build creates the image that can be processed by the ROM loader (aka Simpleboot)\nMulti image build consist of 2nd stage bootloader and one or more application images\nThe bootloader options we will discuss:\nIDF bootloader MCUboot You can refer to the table with list of features and boot scenarios for the Zephyr RTOS on ESP32 at the end of this article.\nSimpleboot # The default build scenario in Zephyr RTOS port of ESP32. The configuration option indicating the use of this build scenario:\nCONFIG_ESP_SIMPLE_BOOT=y CONFIG_BOOTLOADER_MCUBOOT=n NOTE: Do not confuse Simple Boot with the CONFIG_DIRECT_BOOT, which is native to newest RISC-V based SoCs, such as ESP32-C3.\nflowchart TD ROM .-\u003e|load| FP0; APP .-\u003e|load/map| FP0; subgraph \"ROM code\"; ROM; end; subgraph \"Simpleboot chain\"; ROM ==\u003e APP; end; subgraph \"NV Storage\"; FP0; end; ROM@{ shape: rounded, label: \"**ROM loader**\" }; APP@{ shape: rounded, label: \"**Application** *(ESP image format)*\" }; FP0@{ shape: das, label: \"**Boot\u0026Application** *(Can use entire flash)**DT_NODE_LABEL(boot_partition)**DT_NODE_BY_FIXED_PARTITION_LABEL(mcuboot)*\" }; The default booting (and building) method employed in Zephyr RTOS for ESP32 SoCs is called Simple Boot. This method generates a single application binary output, thereby streamlining the complexity of the process. Although it may lack certain advanced features, its appeal lies in its straightforwardness, offering an out-of-the-box solution for initiating any application. This simplicity makes it an accessible choice for developers seeking an uncomplicated development experience.\nBootloaders # IDF bootloader # NOTE: The IDF bootloader is deprecated in Zephyr RTOS but it is discussed here for the reference and because it has been used in early port of ESP32 on Zephyr RTOS\nThe IDF bootloader is the default 2nd stage bootloader for the ESP-IDF platform provided by Espressif. In the Zephyr RTOS it was used to load the application image (RAM load and flash map), but further functionalities were not ported so it acts as an accessible and simple loader.\nThe reasons for removal of IDF bootloader from the Zephyr RTOS port:\nbuilding during each application build in the ExternalProject stage. Building multiple binaries in single build turn is not allowed in Zephyr RTOS. introduction of MCUboot Zephyr RTOS port, which supports --sysbuild. MCUboot # The MCUboot over the years becomes de-facto standard bootloader in IoT realm and Espressif Systems adopted it in several forms depending on used framework.\nThere are two config options - that are often confused - indicates the usage of the MCUboot bootloader:\nCONFIG_BOOTLOADER_MCUBOOT (it is enabled during the application build, which will be loaded by the MCUboot at runtime) CONFIG_MCUBOOT (it is enabled only during the MCUboot build) Currently there are two ESP32 ports of MCUboot that can be used in Zephyr RTOS.\nMCUboot Zephyr RTOS Port (ZP) - native Zephyr RTOS support via sysbuild MCUboot Espressif Port (EP) - standalone port build separately (*) * There is ongoing effort to unify those two ports\nflowchart TD ROM .-\u003e|load| FP0; BL2 .-\u003e|load| FP1; APP .-\u003e|load/map| FP1; ROM ==\u003e BL2; subgraph RC [\"ROM code\"]; ROM; end; subgraph \"Bootloader chain\"; BL2 ==\u003e APP; end; subgraph \"NV Storage\"; FP0; FP1; end; ROM@{ shape: rounded, label: \"**ROM loader**\" }; BL2@{ shape: rounded, label: \"**MCUboot** *(ESP image format)*\" }; APP@{ shape: rounded, label: \"**Application** *(MCUboot format)*\" }; FP0@{ shape: das, label: \"**Boot partition**DT_NODE_LABEL(boot_partition)DT_NODE_BY_FIXED_PARTITION_LABEL(mcuboot)\" }; FP1@{ shape: das, label: \"**Application partition***DT_NODE_LABEL(slot0_partition)**DT_NODE_BY_FIXED_PARTITION_LABEL(image_0)*\" }; The standard MCUboot header is placed at the offset 0x00. Following structure represent its format:\n/* MCUboot image header. All fields are in little endian byte order. */ struct image_header { uint32_t ih_magic; /* 0x96f3b83d OR 0x96f3b83c (V1) */ uint32_t ih_load_addr; /* Subsequent ESP header is used to hold application entry address */ uint16_t ih_hdr_size; /* Size of image header (bytes) */ uint16_t ih_protect_tlv_size; /* Size of protected TLV area (bytes) */ uint32_t ih_img_size; /* Does not include header */ uint32_t ih_flags; /* Image flags */ struct image_version ih_ver; /* Image version */ uint32_t _pad1; /* Padding */ } __packed; The application image loaded by the MCUboot has an additional header with the information about used SRAM segments, which is placed at the offset 0x20, just after the standard MCUboot header.\ntypedef struct esp_image_load_header { uint32_t header_magic; /* Magic number 0xace637d3 */ uint32_t entry_addr; /* Application entry address */ uint32_t iram_dest_addr; /* VMA of IRAM region */ uint32_t iram_flash_offset; /* LMA of IRAM region */ uint32_t iram_size; /* Size of IRAM region */ uint32_t dram_dest_addr; /* VMA of DRAM region */ uint32_t dram_flash_offset; /* LMA of DRAM region */ uint32_t dram_size; /* Size of DRAM region */ } esp_image_load_header_t; Additional information on the flash and/or SPIRAM regions are provided as a linker symbols and are embedded inside the application image.\nMemory utilization # Before we build some example applications, let’s take a moment to discuss how the linking process utilizes SRAM on the ESP32-S3. It’s important to note that different Espressif SoCs can have unique memory layouts, which can affect how resources are allocated. Therefore each SoC is using slightly different linker script.\nThe images below illustrate the process of application linking, focusing on how the ROM code interacts with SRAM. Key details, such as I-Cache and D-Cache allocations, are highlighted for clarity. Important linker symbols, crucial to understanding the memory layout, are shown in green bubbles.\nYellow area is the memory used by the 2nd stage bootloader that can be re-claimed by the application code run-time. Orange area is the memory used by the 1st stage bootloader (or ROM-loader), that can be re-claimed after the application loading is done. Red area is the memory that is not available for the user and should not be used by the linker to spill the code or data. ESP32-S3 use-case # Here we are using the ESP32-S3 to illustrate memory utilization, which is suitable as a reference for most of the newer SoCs.\nThe following picture illustrates the memory utilization for an single CPU scenario.\nThe ESP32-S3 \u0026lsquo;default\u0026rsquo; memory utilization.\nThe following picture illustrates memory utilization in a multi-CPU scenario.\nThe ESP32-S3 \u0026lsquo;AMP\u0026rsquo; memory utilization.\nNOTE: The I-Cache allocation SRAM blocks (0,1) are set by the PMS_INTERNAL_SRAM_ICACHE_USAGE bits and the D-Cache allocation SRAM blocks (9,10) are set by the PMS_INTERNAL_SRAM_DCACHE_USAGE bits, both in the register PMC_INTERNAL_SRAM_USAGE_1_REG\nESP32 use-case # Here is the memory utilization for the ESP32 platform as its memory model is significantly different from other Espressif SoCs.\nThe following picture illustrates memory utilization in a single CPU scenario.\nThe ESP32 \u0026lsquo;default\u0026rsquo; memory layout.\nFollowing picture illustrates the memory utilization in the multi CPU scenario.\nThe ESP32-S3 \u0026lsquo;AMP\u0026rsquo; memory layout.\nTooling - esptool.py # The esptool.py is the essential tool used to manipulate the binaries for the ESP32 SoCs. Among the other features our focus is on the --elf2image command, which is used to convert the .elf images to the loadable .bin images. This tool is used to create the images loadable by the ROM loader.\nProcess of creation of the ESP image format compatible image:\nflowchart LR A --\u003e|linker| B B --\u003e|post build| C C --\u003e D A@{ shape: rounded, label: \"**Build***(west build)*\" } B@{ shape: rounded, label: \"**.elf***(objcpy .bin discarded)*\" } C@{ shape: rounded, label: \"**esptool.py***--elf2image*\" } D@{ shape: rounded, label: \"**.bin***(ESP image format)*\" } Resulting binary can be loaded to any LMA location (in flash). Its segments will be processed at the location and SRAM will be copied to the corresponding SRAM location, and possible FLASH or SPIRAM segments will be mapped to the virtual address space VMA.\nBuilding # Finally let\u0026rsquo;s build some real life examples that can be flashed into the target board to demonstrate what was discussed in previous chapters. Before that it is important to note the image formats used with the Zephyr port of the Espressif SoCs.\nThe table shows the image formats used in various build scenarios:\nImage / core Image format Application (Simple Boot) /\n@PRO_CPU ESP image MCUboot / @PRO_CPU ESP image Application / @PRO_CPU MCUboot image Application / @APP_CPU MCUboot image Simpleboot # Single image builds are used as a default build option in the Zephyr RTOS and the CI (unless --sysbuild is used).\nBuilding and flashing a WiFi sample application using the Simple Boot:\ncd zephyrproject/zephyr west build -b esp32s3_devkitm/esp32s3/procpu samples/net/wifi/shell -p west flash \u0026amp;\u0026amp; west espressif monitor The resulting image when boots and shows the output similar to this:\nESP-ROM:esp32s3-20210327 Build:Mar 27 2021 rst:0x1 (POWERON),boot:0xa (SPI_FAST_FLASH_BOOT) SPIWP:0xee mode:DIO, clock div:2 load:0x3fc946c8,len:0x36dc load:0x40374000,len:0x106a8 entry 0x4037d24c I (98) boot: ESP Simple boot I (98) boot: compile time Oct 27 2024 09:58:26 W (98) boot: Unicore bootloader I (98) spi_flash: detected chip: gd I (99) spi_flash: flash io: dio W (102) spi_flash: Detected size(8192k) larger than the size in the binary image header(2048k). Using the size in the binary image header. I (115) boot: chip revision: v0.2 I (117) boot.esp32s3: Boot SPI Speed : 40MHz I (121) boot.esp32s3: SPI Mode : DIO I (125) boot.esp32s3: SPI Flash Size : 8MB I (129) boot: Enabling RNG early entropy source... I (134) boot: DRAM: lma 0x00000020 vma 0x3fc946c8 len 0x36dc (14044) I (140) boot: IRAM: lma 0x00003704 vma 0x40374000 len 0x106a8 (67240) I (146) boot: padd: lma 0x00013db8 vma 0x00000000 len 0xc240 (49728) I (152) boot: IMAP: lma 0x00020000 vma 0x42000000 len 0x52b68 (338792) I (159) boot: padd: lma 0x00072b70 vma 0x00000000 len 0xd488 (54408) I (165) boot: DMAP: lma 0x00080000 vma 0x3c060000 len 0x1481c (83996) I (171) boot: Image with 6 segments I (174) boot: DROM segment: paddr=00080000h, vaddr=3c060000h, size=14820h ( 84000) map I (182) boot: IROM segment: paddr=00020000h, vaddr=42000000h, size=52B66h (338790) map I (226) heap_runtime: ESP heap runtime init at 0x3fcab850 size 247 kB. *** Booting Zephyr OS build v3.7.0-5030-ge7db0f8aff81 *** uart:~$ MCUboot Zephyr port (ZP) # First lets take a look at how to manually build the MCUboot and the subsequent application. Each west flash in the code is using its own flash partition and it is not overwritten by each other.\nBuilding and flashing the MCUboot separately at its location:\ncd zephyrproject/bootloader/mcuboot west build -b esp32s3_devkitm/esp32s3/procpu boot/zephyr -p west flash \u0026amp;\u0026amp; west espressif monitor Building and flashing the sample application that is loadable by the MCUboot created in previous step:\ncd zephyrproject/zephyr west build -b esp32s3_devkitm/esp32s3/procpu samples/net/wifi -p -DCONFIG_BOOTLOADER_MCUBOOT=y west flash \u0026amp;\u0026amp; west espressif monitor Now, we can rely on the Sysbuild and build all images at once.\nBuilding and flashing the application with MCUboot (ZP) using sysbuild:\ncd zephyrproject/zephyr west build -b esp32s3_devkitm/esp32s3/procpu samples/new/wifi -p --sysbuild west flash \u0026amp;\u0026amp; west espressif monitor In both cases (manual build \u0026amp; using --sysbuild option) we should see the following console output after the image boots:\nESP-ROM:esp32s3-20210327 Build:Mar 27 2021 rst:0x1 (POWERON),boot:0xb (SPI_FAST_FLASH_BOOT) SPIWP:0xee mode:DIO, clock div:2 load:0x3fcc1400,len:0x2c64 load:0x403ba400,len:0xa0d4 load:0x403c6400,len:0x16a0 entry 0x403bd114 I (61) boot: MCUboot 2nd stage bootloader I (61) boot: compile time Oct 27 2024 10:01:14 W (61) boot: Unicore bootloader I (61) spi_flash: detected chip: gd I (63) spi_flash: flash io: dio W (66) spi_flash: Detected size(8192k) larger than the size in the binary image header(2048k). Using the size in the binary image header. I (78) boot: chip revision: v0.2 I (81) boot.esp32s3: Boot SPI Speed : 40MHz I (85) boot.esp32s3: SPI Mode : DIO I (89) boot.esp32s3: SPI Flash Size : 8MB I (93) boot: Enabling RNG early entropy source... I (132) spi_flash: flash io: dio [esp32s3] [INF] Image index: 0, Swap type: none [esp32s3] [INF] Loading image 0 - slot 0 from flash, area id: 1 [esp32s3] [INF] Application start=4037c0f0h [esp32s3] [INF] DRAM segment: paddr=0002b22ch, vaddr=3fc8f210h, size=022e4h ( 8932) load [esp32s3] [INF] IRAM segment: paddr=00020040h, vaddr=40374000h, size=0b1ech ( 45548) load I (165) boot: DROM segment: paddr=00090000h, vaddr=3c060000h, size=14750h ( 83792) map I (165) boot: IROM segment: paddr=00030000h, vaddr=42000000h, size=52D72h (339314) map I (205) heap_runtime: ESP heap runtime init at 0x3fca4f70 size 273 kB. *** Booting Zephyr OS build (tainted) v3.7.0-5030-ge7db0f8aff81 *** uart:~$ MCUboot Espressif port (EP) # To learn how to build the MCUboot Espressif Port, check out this article\nAMP enabled sample code # AMP builds require several images to be built and flashed onto a target SoC. Let\u0026rsquo;s use ESP32-S3 as our test platform and demonstrate the sysbuild capabilities on the sample code provided by the Zephyr RTOS sources. The Zephyr sample code (samples/drivers/ipm/ipm_esp32) uses IPM (Inter-Processor Mailbox) to demonstrate a simple two-way communication between the PRO_CPU core and APP_CPU core. Images for both CPU cores must be loaded using the MCUboot. Note that there is no support for running AMP if the Simple Boot mechanism is used.\nNow we can build and flash a complete set of images running the IPM sample:\ncd zephyrproject/zephyr west build -b esp32s3_devkitm/esp32s3/procpu samples/drivers/ipm/ipm_esp32/ -p --sysbuild west flash \u0026amp;\u0026amp; west espressif monitor As a result, three images should be created:\nipm_esp32 - the image for the PRO_CPU core ipm_esp32_remote - the image for the APP_CPU core mcuboot - the MCUboot image, which is run by PRO_CPU After flashing and connecting to a target using the serial port, we should be able to see the following output in the console:\nESP-ROM:esp32s3-20210327 Build:Mar 27 2021 rst:0x1 (POWERON),boot:0x8 (SPI_FAST_FLASH_BOOT) SPIWP:0xee mode:DIO, clock div:2 load:0x3fcb5400,len:0x2bd8 load:0x403ba400,len:0xa1fc load:0x403c6400,len:0x15c4 entry 0x403bd044 I (61) soc_init: MCUboot 2nd stage bootloader I (61) soc_init: compile time Dec 12 2024 16:26:23 W (61) soc_init: Unicore bootloader I (61) spi_flash: detected chip: generic I (65) spi_flash: flash io: dio W (68) spi_flash: Detected size(8192k) larger than the size in the binary image header(2048k). Using the size in the binary image header. I (80) soc_init: chip revision: v0.1 I (83) flash_init: Boot SPI Speed : 40MHz I (87) flash_init: SPI Mode : DIO I (90) flash_init: SPI Flash Size : 8MB I (94) soc_random: Enabling RNG early entropy source I (99) soc_random: Disabling RNG early entropy source I (103) boot: Disabling glitch detection I (107) boot: Jumping to the main image... I (145) spi_flash: flash io: dio [esp32s3] [INF] Image index: 0, Swap type: none [esp32s3] [INF] Loading image 0 - slot 0 from flash, area id: 1 [esp32s3] [INF] Application start=40378a48h [esp32s3] [INF] DRAM segment: paddr=00026ee8h, vaddr=3fc8aec8h, size=010e4h ( 4324) load [esp32s3] [INF] IRAM segment: paddr=00020040h, vaddr=40374000h, size=06ea8h ( 28328) load I (177) boot: DROM segment: paddr=00040000h, vaddr=3c010000h, size=016A0h ( 5792) map I (177) boot: IROM segment: paddr=00030000h, vaddr=42000000h, size=042A2h ( 17058) map I (193) soc_random: Disabling RNG early entropy source I (193) boot: Disabling glitch detection I (193) boot: Jumping to the main image... I (228) heap_runtime: ESP heap runtime init at 0x3fc8f960 size 154 kB. APPCPU image, area id: 2, offset: 0x170000, hdr.off: 0x20, size: 512 kB IRAM segment: paddr=00170040h, vaddr=403a6400h, size=0571ch ( 22300) load DRAM segment: paddr=0017575ch, vaddr=3fcbbb20h, size=00a58h ( 2648) load Application start=403a6924h *** Booting Zephyr OS build v4.0.0-1981-g5e6b13a7bbff *** PRO_CPU is sending a request, waiting remote response... PRO_CPU received a message from APP_CPU : APP_CPU uptime ticks 501 PRO_CPU is sending a request, waiting remote response... PRO_CPU received a message from APP_CPU : APP_CPU uptime ticks 10503 PRO_CPU is sending a request, waiting remote response... PRO_CPU received a message from APP_CPU : APP_CPU uptime ticks 20504 Bootloader Feature table # The ESP32 port in Zephyr RTOS has variety of booting options.\nFeatures IDFboot (deprecated) MCUboot (Zephyr port) MCUboot (Espressif port) Simple Boot Sysbuild N Y N Y HW Initialization Y Y Y Y Application Loading Y Y Y Y Slots Manipulation N Y Y N OTA N Y Y N Flash Encryption - N Y N Basic Security - Y Y N Secure Boot V2 - N Y N Additional reading # Zephyr RTOS and ESP32 ESP32\u0026rsquo;s memory map ESP32 Programmers memory model ESP32-S3 Technical Reference Manual ","date":"30 October 2024","externalUrl":null,"permalink":"/blog/2024/10/esp32-bootstrapping/","section":"Blog","summary":"This article explains the booting process of Espressif devices up to ESP32-C6 (and probably newer devices).","title":"ESP32 bootstrapping in Zephyr","type":"blog"},{"content":"","date":"24 October 2024","externalUrl":null,"permalink":"/tags/dongle/","section":"Tags","summary":"","title":"Dongle","type":"tags"},{"content":"In modern digital life, we often encounter scenarios where data transfer is not flexible or efficient enough, especially when exporting camera photos, printing files, and sharing videos.\nIn this article, we will have a closer look at the mentioned scenarios and propose a solution - Multi-function USB Dongle based on ESP32-S3.\nScenario: Exporting Camera Photos # After taking photos with a traditional camera, users typically need to remove the camera\u0026rsquo;s SD card, insert it into a card reader, connect the card reader to a computer, and then export the photos through a series of complicated steps. This process is not only multi-step but also time-consuming and laborious, making it cumbersome for users who value convenience.\nScenario: Printing files # When printing files, users often need to transfer the file from a phone or camera to a computer first, then copy the files from the computer to a USB drive, and finally insert the USB drive into the printer to print. This process is not only tedious but also prone to errors due to the involvement of multiple devices and media, which affects printing efficiency and user experience.\nPrinting Process Scenario: Sharing Videos with Multiple People # When sharing videos with multiple people, users typically upload the videos to an email service and then enter multiple email addresses for sharing. However, manually entering email addresses is prone to errors and omissions, and email services often have video size limitations, further increasing the complexity of the operation.\nSome people may choose Bluetooth technology to share videos, but the Bluetooth pairing process is complicated and the transmission speed is slow, making it unsuitable for quickly sharing large videos.\nThese scenarios highlight the inconveniences in data transfer between digital devices, especially when multiple steps and devices are involved. As technology advances, there is a growing expectation for more direct and efficient data management and transfer solutions, such as cloud services, wireless printing technologies, and more advanced direct device connectivity features to simplify these processes.\nOverview of ESP-Dongle # The ESP-Dongle is a multifunctional USB device solution based on the Espressif ESP32-S3 module. It not only has a small size but also seamlessly integrates the functions of a USB MSC wireless disk and a USB wireless network card into one device. It also supports dual-function switching via a sliding switch.\nESP-Dongle\nProduct Display # USB MSC Wireless Disk Mode # The ESP-Dongle can be used as an ordinary USB disk. Users can plug the ESP-Dongle directly into a phone and quickly read or write all files on the SD card via USB, supporting saving files from the SD card to the phone. It also supports uploading files from the phone to the SD card.\nUSB Disk The ESP-Dongle can also be used as a wireless USB disk to read and write SD card data via Wi-Fi using an HTTP server. Users can power the ESP-Dongle with a power bank and switch to USB wireless mode using the sliding switch. In this mode, the ESP-Dongle will create a Wi-Fi hotspot named ESP-Wireless-Disk, allowing multiple phones or computers to connect simultaneously. Users can then browse SD card files or save files to their mobile phones by accessing the ESP-Dongle\u0026rsquo;s HTTP server directly.\nWireless Disk USB Wireless Network Card Mode # Users can insert the ESP-Dongle into a printer, connect their mobile phones to the ESP-Dongle\u0026rsquo;s Wi-Fi hotspot, upload files from the phone via the HTTP server interface, and the printer can read the files directly from the ESP-Dongle for printing.\nPrinter The ESP-Dongle can also be used as a Wi-Fi or Bluetooth network adapter. Users can switch the ESP-Dongle\u0026rsquo;s working mode to a wireless network card using the button. After plugging the ESP-Dongle into a computer, the computer can be directly connected to the Internet.\nWi-Fi Adapter ESP-Dongle Hardware System # The ESP-Dongle is powered through a Type-C port. The hardware system consists of the following parts:\nMain MCU: ESP32-S3-MINI-1-N8 USB Type-C Port SD Card Slot LDO Circuit Slide Switch Tap Button LED ESP-Dongle Hardware Design # The ESP-Dongle hardware schematic is provided below. For hardware design instructions, please refer to ESP Hardware Design Guidelines.\nESP-Dongle Hardware Design\nDescription of different circuit blocks:\nUSB Type-C: The differential signal lines D- and D+ of the USB Type-C interface are connected directly to the USB interface of the ESP32-S3. At the same time, the D-, D+, and VUSB pins are protected against electrostatic discharge through ESD protection components to prevent damage from electrostatic discharge. It should be noted that the CC pin requires a 5.1 kΩ pull-down resistor; otherwise, it will not be recognized by the USB host. LDO: The HE9073A33M5R is a low dropout voltage regulator (LDO) chip used for power voltage regulation. It can be used for stabilizing the input voltage range from 3.3 V to 7 V and outputting a stable 3.3 V to ensure the stability of the system\u0026rsquo;s power supply. MicroSD Card: The SD card interface supports 1-line, 4-line SDIO mode, and SPI mode. To ensure signal stability, each pin needs to be pulled up by a 10 kΩ resistor and use ESD protection devices to prevent damage from electrostatic discharge. Button: The button is used to switch the Wi-Fi or Bluetooth network adapter working mode of the ESP-Dongle. LED: The LED indicator is used for observing the working status of the ESP-Dongle. Switch: The two endpoints of the slide switch are pulled up and pulled down respectively, and the level state is read by GPIO4 to determine the current switch\u0026rsquo;s on/off state. The sliding switch is used to switch between the USB wireless disk or USB wireless network card working modes of the ESP-Dongle. Software Implementation # The complete application functionality is a combination of multiple individual application functions. Espressif provides many application examples for user reference and as a starting point for further development.\nUSB MSC Wireless Disk Mode # For USB MSC wireless disk application, you can refer to the ESP-IDF example:\nesp-iot-solution/examples/usb/device/usb_msc_wireless_disk The example using ESP32-S3 as a USB Disk with Wireless accessibility. HTTP file server can be used with both upload and download capability.\nThe implementation uses espressif/esp_tinyusb component for SD Card access via MSC USB device Class, and espressif/esp32_s3_usb_otg component to develop wireless storage devices, Wi-Fi network cards.\nUSB MSC Wireless Network Card Mode # For USB wireless network card application, you can refer to the ESP-IDF example:\nesp-iot-solution/examples/usb/device/usb_dongle The implementation uses tinyusb_dongle component to support USB Host to surf the Internet wirelessly via USB-ECM/RNDIS, and support hot swap.\nAs one of the simplest output peripherals, LED indicators can indicate the current operating state of the system by blinking in different types. For LED indicator application, you can use the espressif/led_indicator component which can help you define multiple groups of different blink types. For more instructions, please refer to LED Indicator User Guide.\nRecommended documents # USB Device Stack Wi-Fi Driver Programming Guide HTTP Server Programming Guide ","date":"24 October 2024","externalUrl":null,"permalink":"/blog/multi-function-usb-dongle-based-on-esp32-s3/","section":"Blog","summary":"","title":"Multi-function USB Dongle based on ESP32-S3","type":"blog"},{"content":"","date":"22 October 2024","externalUrl":null,"permalink":"/tags/lua/","section":"Tags","summary":"","title":"Lua","type":"tags"},{"content":"","date":"22 October 2024","externalUrl":null,"permalink":"/tags/scripting/","section":"Tags","summary":"","title":"Scripting","type":"tags"},{"content":"Lua is a lightweight and powerful scripting language, making it ideal for use in embedded systems like the ESP32. By integrating Lua into your ESP-IDF project, you can execute scripts directly on the ESP32, offering a flexible way to manage application behavior without recompiling the entire firmware. This guide walks through how to set up Lua 5.4 as a component in an ESP-IDF project, with a focus on running Lua scripts from the filesystem.\nRepository Link # You can find the complete example project at ESP32 Lua Example Repository\nProject Overview # The example project demonstrates:\nIntegrating Lua 5.4 as an ESP-IDF component. Running Lua scripts from files stored in the filesystem (SPIFFS). Monitoring memory usage when Wi-Fi is enabled. Examples of Lua scripts to illustrate how to execute code on the ESP32. Key Components # Lua 5.4 ESP-IDF Component # Lua 5.4 is wrapped as an ESP-IDF component, allowing easy integration with ESP32 applications.Lua’s extensibility makes it suitable for both rapid development and runtime script adjustments.\nFilesystem Support (SPIFFS) # In this project, the SPIFFS filesystem is used to store Lua scripts on the ESP32. This allows scripts to be managed separately from the firmware, enabling easy updates without requiring a full rebuild of the application. Developers can simply upload new Lua scripts to the SPIFFS partition, making it an efficient solution for managing code changes.\nMemory Usage Insights # Memory management is critical in resource-constrained devices like the ESP32, especially when features like Wi-Fi are active. This project logs memory usage at various stages of execution, helping developers monitor and optimize memory consumption. It’s essential for ensuring stability, particularly in applications that demand more resources.\nCode Overview # Below is an example of the core functionality. The application initializes the SPIFFS filesystem and optionally sets up Wi-Fi. Lua scripts are executed from files using a key function that handles file loading and script execution.\nRunning Lua Scripts # The run_lua_file function is responsible for loading and executing a Lua script from the specified file.\nvoid run_lua_file(const char *file_name, const char *description) { ESP_LOGI(TAG, \u0026#34;Running Lua script: %s\u0026#34;, description); lua_State *L = luaL_newstate(); if (L == NULL) { ESP_LOGE(TAG, \u0026#34;Failed to create Lua state\u0026#34;); return; } luaL_openlibs(L); // Set Lua module search path if (luaL_dostring(L, \u0026#34;package.path = package.path .. \u0026#39;;./?.lua;/spiffs/?.lua\u0026#39;\u0026#34;)) { ESP_LOGE(TAG, \u0026#34;Failed to set package.path: %s\u0026#34;, lua_tostring(L, -1)); lua_pop(L, 1); } // Load and execute the Lua script from file if (luaL_dofile(L, file_name) != LUA_OK) { ESP_LOGE(TAG, \u0026#34;Error executing Lua script \u0026#39;%s\u0026#39;: %s\u0026#34;, file_name, lua_tostring(L, -1)); lua_pop(L, 1); } lua_close(L); ESP_LOGI(TAG, \u0026#34;Finished running Lua script: %s\u0026#34;, description); } This function does the following:\nCreates a new Lua state. Opens the standard Lua libraries. Configures the Lua module search path to include the SPIFFS partition. Loads and executes the specified Lua script file. Filesystem Initialization # The init_spiffs function is used to initialize the SPIFFS filesystem, ensuring the ESP32 can store and access Lua scripts.\nvoid init_spiffs(void) { ESP_LOGI(TAG, \u0026#34;Initializing SPIFFS\u0026#34;); esp_vfs_spiffs_conf_t conf = { .base_path = \u0026#34;/spiffs\u0026#34;, .partition_label = NULL, .max_files = 5, .format_if_mount_failed = true }; esp_err_t ret = esp_vfs_spiffs_register(\u0026amp;conf); if (ret != ESP_OK) { ESP_LOGE(TAG, \u0026#34;Failed to mount or format filesystem\u0026#34;); return; } size_t total = 0, used = 0; ret = esp_spiffs_info(NULL, \u0026amp;total, \u0026amp;used); if (ret == ESP_OK) { ESP_LOGI(TAG, \u0026#34;SPIFFS total: %d, used: %d\u0026#34;, total, used); } else { ESP_LOGE(TAG, \u0026#34;Failed to get SPIFFS partition information\u0026#34;); } } Getting Started # To get started with this example, follow these steps\nClone the Repository # First, clone the example project from GitHub:\ngit clone https://github.com/georgik/esp32-lua-example.git cd esp32-lua-example Configure the Project # If needed, run idf.py menuconfig to adjust project settings before building.\nBuild, Flash, and Monitor # Compile and flash the firmware onto your ESP32, then monitor the output:\nidf.py build flash monior You should see output similar to the following:\nThe answer is: 42 Fibonacci of 10 is: 55 QR Code for: https://developer.espressif.com/tags/lua Integrating Lua as an ESP-IDF Component # To integrate Lua into your own ESP-IDF project, follow these steps:\nAdding Lua to Your Project # In your project\u0026rsquo;s main directory, create or edit the main/idf_component.yml file to specify Lua as a dependency:\ndependencies: georgik/lua: \u0026#34;==5.4.7\u0026#34; joltwallet/littlefs: \u0026#34;==1.14.8\u0026#34; idf: version: \u0026#34;\u0026gt;=5.0.0\u0026#34; This configuration ensures the ESP-IDF build system fetches and includes the Lua 5.4.7 component and the LittleFS component for filesystem support.\nUtilizing the ESP-IDF Component Registry # By specifying Lua in your main/idf_component.yml, the ESP-IDF build system will automatically download and integrate the Lua component during the build process. There’s no need to manually manage Lua\u0026rsquo;s source code, making dependency management easier.\nYou can find more information about the Lua component in the ESP-IDF Component Registry and the Lua ESP-IDF Component repository.\nConclusion # Lua provides a powerful yet lightweight way to script and manage ESP32 applications. By using the filesystem to store Lua scripts, you can update code on the fly without having to recompile the firmware. This guide shows you how to easily integrate Lua into your ESP32 projects, manage scripts using SPIFFS, and monitor resource usage, all while keeping your development process flexible and efficient.\nReferences # ESP-IDF Component Registry: Lua Component Lua ESP-IDF Component Repository: esp-idf-component-lua ","date":"22 October 2024","externalUrl":null,"permalink":"/blog/using-lua-as-esp-idf-component-with-esp32/","section":"Blog","summary":"","title":"Using Lua as ESP-IDF Component with ESP32","type":"blog"},{"content":" Explore Embedded Swift on ESP32 at Do iOS 2024 # Espressif Systems will be part of Do iOS 2024, one of Europe\u0026rsquo;s leading iOS developer conferences, where Juraj Michálek will be giving a talk titled Embedded Swift: Using Your Swift Skills for Embedded Development.\nWhen \u0026amp; Where # 📅 Talk: November 13 📍 Location: Nemo Science Museum, Oosterdok 2, 1011 VX Amsterdam\nThe session will introduce developers to the possibilities of using Swift on ESP32 microcontrollers, focusing on the RISC-V ESP32-C, ESP32-H, and ESP32-P families. Swift’s compatibility with C makes it an appealing alternative to languages like C, Rust, and MicroPython, enabling developers to work with mature libraries and explore new protocols such as Matter.\nWhat You\u0026rsquo;ll Learn # How Swift integrates with ESP32 microcontrollers for embedded development. Practical aspects of working with ESP32-C, ESP32-H, and ESP32-P devices. Guidance on getting started with Swift on ESP32 platforms, expanding your development toolkit. This talk is ideal for developers looking to bring their iOS and Swift skills into the embedded world, leveraging the capabilities of ESP32 for a range of applications.\nFor more information about the event and tickets, visit the official Do iOS 2024 website.\n","date":"8 October 2024","externalUrl":null,"permalink":"/events/do-ios-24-netherlands-amsterdam-swift-esp32/","section":"Events","summary":"","title":"Do iOS 2024 - Embedded Swift on ESP32","type":"events"},{"content":"","date":"7 October 2024","externalUrl":null,"permalink":"/tags/eclipse/","section":"Tags","summary":"","title":"Eclipse","type":"tags"},{"content":" Espressif-IDE # Today we announce the new version of the Espressif IDE, the version 3.1.0. This new version adds new functionalities and bug fixes.\nEspressif-IDE New target setup New features # Updated Eclipse Platform Support Support for the Eclipse CDT 2024-06 release, ensuring compatibility with the latest Eclipse features and enhancements. CDT LSP 2.0 Integration Full support for CDT Language Server Protocol (LSP) 2.0, providing enhanced code navigation, syntax highlighting, and error checking. Improved Editor responsiveness and language feature parity for a smoother coding experience. Expanded Hardware Support Added support for ESP32-P4, enabling development and debugging for the new Espressif chipset. Streamlined setup for other Espressif SoCs, improving multi-target project management. Unified Target and Board Configuration Consolidated all target and board configuration options into a single, intuitive interface for easier access and project configuration. Now, you can configure all of them in the ESP Target window. Welcome Page Overhaul Revamped the welcome page and added the ESP-IDF Manager action to help users quickly get started. Added links to key resources, tutorials, and community forums. Build Settings Enhancements Improved Build Settings tab with more flexible configurations, enhanced readability, and easier management of build profiles. Added messages for fields in the Build Settings tab to give some context to the user. The relative custom-build folder path now relates to the project folder instead of the workspace. Change the default name for the debug configuration. Multi-Configuration Support Added support for multi_config setups and allow the developers to run sdkconfig editor from any build folder. New Project Standards Automatic creation of a .clang-format file with default settings when a new project is created. Additionally, if the .clang-format file is missing, it is automatically added after the build. Feedback-Driven UX Improvements Quality and Stability Fixes Various bug fixes and performance enhancements aimed at improving the overall quality, stability, and developer experience. Launch Configuration Improvements Provided a configuration option in the launch configuration to open the serial monitor right after the serial flash. Changing the configuration automatically sets the mode to Run/Debug accordingly. ESP-IDF Manager Improvements Added functionality to remove all versions from the list. Added validations for the ESP-IDF path and improved the UI. Check the full release notes for more detailed information.\nDownload the new version # To install the new version, you can use one of the three options.\nPlugin\nInstalling IDF Plugins using the Update site URL:\nPlugins online install Installing IDF Plugins using the local archive file:\nDownload the plugin Espressif IDE Installer\nDownload the Espressif IDE for your operating system:\nmacosx-cocoa-aarch64 macosx-cocoa-x86_64 win32.win32.x86_64 linux.gtk.x86_64 linux.gtk.aarch64 ESP-IDF Windows Installer\nDownload Includes the Espressif IDE 3.1.0.\n","date":"7 October 2024","externalUrl":null,"permalink":"/blog/espressif-ide/espressif-ide-3-1-0-release/","section":"Blog","summary":"","title":"New Release: Espressif IDE 3.1.0","type":"blog"},{"content":"","date":"4 October 2024","externalUrl":null,"permalink":"/tags/pytest/","section":"Tags","summary":"","title":"Pytest","type":"tags"},{"content":"","date":"4 October 2024","externalUrl":null,"permalink":"/tags/testing/","section":"Tags","summary":"","title":"Testing","type":"tags"},{"content":" Introduction # Testing should be a primary focus in the development process of any embedded system. It significantly reduces the chances of failure, ensures long-term stability—especially in a continuous integration (CI) environment—and can drive development by promoting testable features. This is where test-driven development (TDD) and its many variations come into play.\nIn my experience, testing can be easy to maintain and improve, provided you have a solid test setup.\nTesting software for an embedded product can, to some extent, be done without a target. Unit tests running on the developer\u0026rsquo;s machine can validate parts of the software that do not require hardware interaction. This is often true for tasks like mathematical computations, video and image processing, data parsing, and more. In such cases, tools like CppTest or GoogleTest can handle the job. Even when hardware is involved, interfaces and peripherals can be mocked to simulate some parts of the system.\nWhile this covers a significant portion of testing, at some point, on-target testing becomes essential. With the internal components already tested through unit tests, we focus on testing the overall application while communicating with the device. The most common way to achieve this is through the serial port or JTAG.\nIn this article, I’ll discuss high-level testing using Pytest with the NuttX RTOS.\nPytest # There are several high-level testing tools available today, but we are going to focus on Python, specifically the pytest framework.\nPytest allows us to set up a test environment and scale tests easily, using fixtures to manage test resources (such as serial communication) and parametrization to run multiple test cases efficiently.\nPytest integrates with argparse, enabling us to pass arguments to tests via the command line or by specifying them in an .ini file. These arguments can be accessed by any test case when needed.\nAnother significant advantage of pytest is the large number of available plugins. Pytest provides a standard way to implement plugins using its hooks, allowing contributors to share their plugins with the community.\nSetting Up the Test Environment # If you are running Linux, you probably already have Python installed. If that’s the case, let\u0026rsquo;s create a directory for our tests called embedded_test.\nfdcavalcanti@espubuntu:~$ mkdir embedded_test fdcavalcanti@espubuntu:~$ cd embedded_test/ Inside this directory, we need to create a Python virtual environment. A virtual environment is simply a directory where we install all downloaded packages to avoid conflicts with the system’s default packages.\nTo create the virtual environment, use Python\u0026rsquo;s venv tool and create an environment called \u0026ldquo;venv\u0026rdquo;. Then, activate the environment. Notice that (venv) appears to the left of my prompt, indicating that all Python packages will now come from this virtual environment rather than the system.\nfdcavalcanti@espubuntu:~/embedded_test$ python3 -m venv venv fdcavalcanti@espubuntu:~/embedded_test$ source venv/bin/activate (venv) fdcavalcanti@espubuntu:~/embedded_test$ Next, upgrade pip (Python’s package manager) and install the following packages:\npytest pyserial Once installed, you can verify the packages with pip3 list.\n(venv) fdcavalcanti@espubuntu:~/embedded_test$ pip3 install --upgrade pip (venv) fdcavalcanti@espubuntu:~/embedded_test$ pip3 install pytest (venv) fdcavalcanti@espubuntu:~/embedded_test$ pip3 install pyserial (venv) fdcavalcanti@espubuntu:~/embedded_test$ pip3 list Package Version --------------- ------- iniconfig 2.0.0 packaging 24.1 pip 24.0 pluggy 1.5.0 pyserial 3.5 pytest 8.3.3 Now, the environment is ready, and we can begin setting up our tests.\nEstablishing Communication # Before we can test an application, we need to establish working serial communication that we can use in our tests. First, we’ll create a Python class to handle this, and then we’ll explore how pytest can leverage it.\nSerial Communication Class # Let’s create a file called communication.py. The first step is to import pyserial, which will assist us with serial communication.\nOur class will be called SerialCommunication and will contain the mandatory init method, a write method, and a close method, which are sufficient to get started:\ninit: Receives the arguments to instantiate our communication class, such as the serial port, baud rate, and timeout. write: Accepts a string argument that represents the data we are sending through the serial port. close: Closes the connection. The following is what our initialization looks like. The timeout argument is important to avoid locking our serial port in case of a failure where the device is unresponsive. It can also be adjusted on the fly for long test cases.\nimport serial class SerialCommunication: def __init__(self, port: str, baudrate: int=115200, timeout: int=10): self.port = port self.baudrate = baudrate self.timeout = timeout self.ser = serial.Serial(self.port, baudrate=self.baudrate, timeout=self.timeout) The SerialCommunication class also allows you to set additional parameters such as byte size, parity, stop bits, and hardware flow control. It raises an exception if a parameter is out of range or if the serial device is invalid.\nNext, we have the write method. Since we can’t send a Python string directly to our device, it must be encoded before transmission. Additionally, we need to check for a line break, which corresponds to the \u0026ldquo;Enter\u0026rdquo; key press.\nWhen data is transmitted, we naturally expect a response. In the case of NuttX, when using Nuttshell, the Nutshell prompt (nsh\u0026gt; ) appears whenever we write something and the process ends (or keeps running in background, but are simplifying here). This indicates that the shell is ready for the next command, which, in our context, means our previous command has completed. In simple terms, after sending a command, we should read everything until the prompt appears.\ndef write(self, command: str) -\u0026gt; str: if \u0026#39;\\n\u0026#39; not in command: command += \u0026#39;\\n\u0026#39; data_send = command.encode() self.ser.write(data_send) response = self.ser.read_until(\u0026#34;nsh\u0026gt; \u0026#34;.encode()) return response.decode() Finally, we add a simple close method that releases our serial port:\ndef close(self) -\u0026gt; None: self.ser.close() Testing Communication # I have an ESP32H2 Devkit connected to my serial port at /dev/ttyUSB0 and running the nsh firmware configuration.\nIf you are not familiar with building NuttX, checkout this article on getting started with NuttX and ESP32.\nBelow, we will add a simple main routine to our communication.py file to validate that our communication works by sending the help and uname commands and reading the responses.\nif __name__ == \u0026#34;__main__\u0026#34;: device = SerialCommunication(\u0026#34;/dev/ttyUSB0\u0026#34;) ans = device.write(\u0026#34;uname -a\u0026#34;) print(ans) device.close() Output from the routine above:\n(venv) fdcavalcanti@espubuntu:~/embedded_test$ python3 communication.py uname -a NuttX 10.4.0 4622e4f996-dirty Sep 27 2024 14:52:14 risc-v esp32h2-devkit nsh\u0026gt; So it works. We have the communication basis that allows us to structure our Pytest environment. The same recipe can be followed for communication via telnet, sockets, MQTT, or whatever is needed for the application.\nStructuring the Pytest environment # In pytest, you can run tests using a single file. However, we will be working with tests alongside a conftest.py file. The conftest.py file allows us to dynamically set test case parameters, create fixtures that are shared across all tests, set up community plugins, parse command-line arguments, and more. In this file, we will define a fixture for serial communication that will be used throughout the entire test session.\nBut before proceeding, we need a brief introduction on fixtures.\nFixtures # Fixtures in pytest can be thought of as reusable methods. If we had 100 test cases, it would not be good practice to open and close our serial port 100 times. Instead, it’s simpler to use a serial port fixture that opens once at the beginning of the test session and closes when all tests are completed.\nIn pytest, we signal that a function should be used as a fixture by adding the @pytest.fixture decorator. This decorator can accept several arguments, such as a name and its scope, which can be:\nfunction: This tells pytest to execute the fixture routine entirely every time a function calls it. In our serial fixture, this would mean that the serial port would be opened and closed for each test. module: A module refers to a single test file. If the serial port is initialized in test_uname.py, it would remain open until all tests in that module are complete, at which point it would close. session: The test session begins after tests are collected, and the serial port is opened only once at this point. It closes after all tests have finished. There are also class and package scopes, which follow the same idea. See the documentation for fixture usage examples and other use cases.\nSetting up conftest # This first example\u0026rsquo;s conftest.py file will be responsible for one task: creating the serial port fixture.\nCreate the conftest file:\n(venv) fdcavalcanti@espubuntu:~/embedded_test$ touch conftest.py Then, import the SerialCommunication class and create the fixture using session scope, naming it \u0026ldquo;target\u0026rdquo;.\nimport pytest from communication import SerialCommunication @pytest.fixture(scope=\u0026#34;session\u0026#34;, name=\u0026#34;target\u0026#34;) def serial_comm_fixture(): serial = SerialCommunication(\u0026#34;/dev/ttyUSB0\u0026#34;) yield serial serial.close() Writing the First Test # Now that conftest.py is ready, we can write our first test to check if the information returned from uname is valid. First, create the test_uname.py file, and then write the test to verify that \u0026ldquo;esp32h2-devkit\u0026rdquo; is returned.\n(venv) fdcavalcanti@espubuntu:~/embedded_test$ touch test_uname.py def test_uname_board(target): board = \u0026#34;esp32h2-devkit\u0026#34; ans = target.write(\u0026#34;uname -a\u0026#34;) assert board in ans To execute, call pytest -v and the test should pass.\n(venv) fdcavalcanti@espubuntu:~/embedded_test$ pytest -v ============================== test session starts ============================== platform linux -- Python 3.12.3, pytest-8.3.3, pluggy-1.5.0 -- /home/fdcavalcanti/embedded_test/venv/bin/python3 cachedir: .pytest_cache metadata: {\u0026#39;Python\u0026#39;: \u0026#39;3.12.3\u0026#39;, \u0026#39;Platform\u0026#39;: \u0026#39;Linux-6.8.0-45-generic-x86_64-with-glibc2.39\u0026#39;, \u0026#39;Packages\u0026#39;: {\u0026#39;pytest\u0026#39;: \u0026#39;8.3.3\u0026#39;, \u0026#39;pluggy\u0026#39;: \u0026#39;1.5.0\u0026#39;}, \u0026#39;Plugins\u0026#39;: {\u0026#39;metadata\u0026#39;: \u0026#39;3.1.1\u0026#39;, \u0026#39;html\u0026#39;: \u0026#39;4.1.1\u0026#39;}} rootdir: /home/fdcavalcanti/embedded_test plugins: metadata-3.1.1, html-4.1.1 collected 1 item test_uname.py::test_uname_board PASSED [100%] ============================== 1 passed in 0.14s ============================== This is excellent, our first test executed succesfully. We were able to open the serial port, write a command and verify the results contained the information we expected.\nWith our own version of Hello World done, we can expand into better tests.\nImproving the Tests # There are several ways to enhance our test. We can use parametrization, additional fixtures, configuration files, command-line arguments, dynamic test cases, and more. For now, let’s focus on two examples: parametrization and general fixture improvements.\nTest Case Parametrization # Pytest\u0026rsquo;s documentation on parametrization is an excellent resource for more information. In this example, I’ll focus on the parametrization decorator.\nParametrization of a test allows us to run multiple test cases efficiently. For instance, if we are testing the mkdir functionality and want to validate that our file system can create directories with mixed numbers and letters, we can avoid using a large \u0026ldquo;for loop\u0026rdquo; or writing many test functions for each name combination. Instead, we can parametrize a single test, enabling us to cover multiple test cases in just a few lines of code.\nLet’s create a routine to create a directory, check if it was created, delete it, and verify that it has been deleted.\ndef test_dir_create_delete(target): directory = \u0026#34;testdir\u0026#34; target.write(f\u0026#34;mkdir {directory}\u0026#34;) ans = target.write(\u0026#34;ls\u0026#34;) assert directory in ans target.write(f\u0026#34;rmdir {directory}\u0026#34;) ans = target.write(\u0026#34;ls\u0026#34;) assert directory not in ans test_directory.py::test_dir_create_delete PASSED [ 50%] test_uname.py::test_uname_board PASSED [100%] This is one way to accomplish the task, and it works. However, it only tests a single directory. To expand our testing, we’ll use pytest\u0026rsquo;s parametrization feature. We simply need to add a \u0026ldquo;directory\u0026rdquo; argument to our test function and then apply the parametrize decorator, which will automatically call this test function for all values in the list of directory names.\n@pytest.mark.parametrize(\u0026#34;directory\u0026#34;, [\u0026#34;testdir\u0026#34;, \u0026#34;testdir000\u0026#34;, \u0026#34;0_testdir_1\u0026#34;]) def test_dir_create_delete(target, directory): target.write(f\u0026#34;mkdir {directory}\u0026#34;) ans = target.write(\u0026#34;ls\u0026#34;) assert directory in ans target.write(f\u0026#34;rmdir {directory}\u0026#34;) ans = target.write(\u0026#34;ls\u0026#34;) assert directory not in ans On the output below, we can see that our directory names are treated each as a test case for the dir_create_delete test.\ntest_directory.py::test_dir_create_delete[testdir] PASSED [ 25%] test_directory.py::test_dir_create_delete[testdir000] PASSED [ 50%] test_directory.py::test_dir_create_delete[0_testdir_1] PASSED [ 75%] test_uname.py::test_uname_board PASSED [100%] Using Fixtures for Session Parameters # Now that we know how to run a simple parametrized test, we should leverage pytest to expand our testing efficiency even further. We will continue working on the uname_board test but will use a different fixture to eliminate the constant board = \u0026quot;esp32h2-devkit\u0026quot;, making our test more generic.\nFirst, we need to understand the purpose of our test. The test description is:\n\u0026ldquo;Run uname -a and assert that it shows the correct board we are using.\u0026rdquo;\nOf course, the test won’t know what to expect when we connect a different board, but we, as users, can pass the expected board as a test argument.\nThe first step is to remove the board string and replace it with a fixture. Delete the line containing the board name and add \u0026ldquo;board\u0026rdquo; to the test function arguments, making it look more generic, like this:\ndef test_uname_board(target, board): ans = target.write(\u0026#34;uname -a\u0026#34;) assert board in ans Now go back to conftest.py and create a session scoped fixture that yields the board name.\n@pytest.fixture(scope=\u0026#34;session\u0026#34;, name=\u0026#34;board\u0026#34;) def board_name(): yield \u0026#34;esp32h2-devkit\u0026#34; Run the test again and it should pass.\nAt this point our conftest has two magic strings: the board name in the new fixture and the serial port path in the serial port fixture. Let\u0026rsquo;s fix this.\nAdding Command-Line Options # First, create a function called pytest_addoption. Pytest uses this hook function automatically to append command line arguments.\nWe\u0026rsquo;ll add two command-line options:\nusbport: Receive the target USB port. Defaults to /dev/ttyUSB0. board: Target board name. Must always be passed. def pytest_addoption(parser): parser.addoption(\u0026#34;--usbport\u0026#34;, action=\u0026#34;store\u0026#34;, default=\u0026#34;/dev/ttyUSB0\u0026#34;, help=\u0026#34;USB port\u0026#34;) parser.addoption(\u0026#34;--board\u0026#34;, action=\u0026#34;store\u0026#34;, required=True, help=\u0026#34;Espressif devkit\u0026#34;) Now that our UBS Port and board name are passed from the command-line, we should tell our fixtures to find the values in the request fixture.\n@pytest.fixture(scope=\u0026#34;session\u0026#34;, name=\u0026#34;target\u0026#34;) def serial_comm_fixture(request): serial = SerialCommunication(request.config.getoption(\u0026#34;--usbport\u0026#34;)) yield serial serial.close() @pytest.fixture(scope=\u0026#34;session\u0026#34;, name=\u0026#34;board\u0026#34;) def board_name(request): yield request.config.getoption(\u0026#34;--board\u0026#34;) Time to run the tests again. We know it defaults to /dev/ttyUSB0 so I\u0026rsquo;ll only pass the board name:\n$ pytest -v --board esp32h2-devkit\nAnd now using a different port:\n$ pytest -v --board esp32h2-devkit --usbport /dev/ttyUSB1\nAnd we can see that tests are still passing and the command-line arguments are shown in the test output.\nConclusion # Pytest allows you to quickly setup a test environment for your projects. It is simple, fast, reliable and can help spot mistakes on the long run. At Espressif, we use automated tests on everything we do, and you should too. Have fun testing your projects!\nResources # For more information, refer to the links below.\nPytest getting started Example repository Getting Started with NuttX and ESP32 GoogleTest CppTest Robot Framework ","date":"4 October 2024","externalUrl":null,"permalink":"/blog/2024/10/pytest-testing-with-nuttx/","section":"Blog","summary":"How Pytest is used for testing the NuttX RTOS on Espressif devices.","title":"Testing applications with Pytest and NuttX","type":"blog"},{"content":"The following article explains all necessary steps to create an Embedded Wizard GUI application suitable for the ESP32-S3-BOX from Espressif.\nPlease follow these instructions carefully and step by step in order to ensure that you will get everything up and running on your target. In case you are not familiar with Embedded Wizard, please first read the chapter basic concepts and the Quick Tour tutorial to understand the principles of Embedded Wizard and the GUI development workflow.\nIntroduction: External display controller and partial display updates # The ESP32-S3-BOX combines the ESP32-S3 micro-controller (MCU) with a 320x240 display, connected via SPI. The display is driven by an external display controller, which contains its own display memory. As a result, the entire framebuffer can be located inside the display controller and only a small scratch-pad buffer is needed inside the micro-controller (MCU). For this purpose, Embedded Wizard supports a partial display update, that makes it possible to update the display in sequential small areas. This makes it possible to operate with a scratch-pad buffer of a few kilobytes instead of a full-screen framebuffer within the memory space of the MCU.\nPlease note: The partial display update is intended to be used for extremely memory-constrained systems. Due to the fact that the display update is done in subsequent updates of small areas, moving graphical objects can cause some tearing effects. The UI design should consider this aspect.\nPrerequisites # Although you can combine the ESP32-S3-BOX with many different display controllers or your own hardware, we highly recommend to start first with the following hardware components in order to ensure that you get the entire software up and running. As soon as you have your first UI application working on the recommended environment, you can start porting to your desired display controller.\nFirst, make sure you have all of the following items:\nHardware components # ESP32-S3-BOX from Espressif USB cable to connect the board with your PC Software components # Embedded Wizard Studio Free or Embedded Wizard Studio Pro If you want to use the Free edition of Embedded Wizard Studio please register on our website and download the software.\nAs a customer, please visit the Embedded Wizard Download Center (login/password required) and download Embedded Wizard Studio Pro.\nEmbedded Wizard Build Environment for ESP32-S3-BOX To evaluate Embedded Wizard on the mentioned target, you can find and download the suitable Build Environment for Embedded Wizard’s latest version under the category “software components” from the following link: https://doc.embedded-wizard.de/getting-started-esp32-s3-box\nAs a customer, please visit the Embedded Wizard Download Center (login/password required) and download the latest version of the Build Environment and your licensed Platform Package libraries or source codes.\nInstalling Tools and Software # The following description assumes that you are familiar with ESP32-S3 software development and that you have installed the ESP32 toolchain for Windows.\nIMPORTANT! Before starting the GUI development with Embedded Wizard, please make sure to have the ESP32 software development environment (ESP-IDF) installed and first applications running on your ESP32-S3-BOX. Please follow the ESP32-S3 Get Started documentation from Espressif. Please also make sure that the ESP-IDF installation path (IDF_PATH) does not contain any space characters - otherwise building examples will fail.\nStep 1: Install the latest version of Embedded Wizard Studio. Step 2: Unpack the provided Embedded Wizard Build Environment for ESP32-S3-BOX to your \\\\esp development directory (e.g. C:\\\\ESP32\\\\esp\\\\ESP32-S3-BOX). Exploring the Build Environment # The provided Embedded Wizard Build Environment for ESP32-S3-BOX contains everything you need to create an Embedded Wizard UI application for the ESP32-S3-BOX. After unpacking, you will find the following subdirectories and files within \\\\esp\\\\ESP32-S3-BOX\\\\main:\nApplication\\\\GeneratedCode - This folder is used to receive the generated code from an Embedded Wizard UI project. The template project is building the UI application out of this folder. You can create your own UI project and generate the code into the subdirectory \\\\GeneratedCode without the need to adapt the project.\nApplication\\\\Source - This folder contains the files main.c and ewmain.c. There you will find the initialization of the system and the main loop to drive an Embedded Wizard GUI application. The file ewconfig.h contains general configuration settings for the target system, like memory ranges and display parameter and configuration settings for the Embedded Wizard Graphics Engine and Runtime Environment. Additionally, this folder contains the device driver C/H files used for the DeviceIntegration example.\nExamples\\\\ScreenSize - This folder contains a set of demo applications prepared for a dedicated screen size (320x240 pixel). Each example is stored in a separate folder containing the entire Embedded Wizard UI project. Every project contains the necessary profile settings for the ESP32 target. The following samples are provided:\nHelloWorld - A very simple project that is useful as starting point and to verify that the entire toolchain, your installation and your board is properly working. ColorFormats - This project demonstrates that every UI application can be generated for different color formats: RGB565, Index8 and LumA44. ScreenOrientation - This demo shows, that the orientation of the UI application is independent from the physical orientation of the display. DeviceIntegration - This example shows the integration of devices into a UI application and addresses typical questions: How to start a certain action on the target? How to get data from a device? GraphicsAccelerator - This application demonstrates the graphics performance of the target by using sets of basic drawing operations that are executed permanently and continuously. AnimatedList - This demo shows the implementation of some fancy scrollable list widgets to set a time and a day of the week. The speciality of this sample application is the magnification effect of the centered list items and the soft fade-in/fade-out effects. BrickGame - The sample application BrickGame implements a classic \u0026ldquo;paddle and ball\u0026rdquo; game. In the game, a couple of brick rows are arranged in the upper part of the screen. A ball travels across the screen, bouncing off the top and side walls of the screen. When a brick is hit, the ball bounces away and the brick is destroyed. The player has a movable paddle to bounce the ball upward, keeping it in play. ClimateCabinet - The ClimateCabinet demo shows the implementation of a control panel for a climatic exposure test cabinet. The user can define a heating time, a nominal temperature and humidity, a dwell time and the final cooling time. WaveformGenerator - This WaveformGenerator demo application combines waveforms with different amplitudes and frequencies. The implementation shows the usage of vector graphics to draw a curve based on a list of coordinates. PlatformPackage - This folder contains the necessary source codes and/or libraries of the ESP32 Platform Package: Several Graphics Engines for the different color formats (RGB565, Index8 and LumA44) and the Runtime Environment (in the subdirectory \\\\RTE).\nTargetSpecific - This folder contains all configuration files and platform specific source codes. The different ew_bsp_xxx files implement the bridge between the Embedded Wizard UI application and the underlying board support package (ESP hardware drivers) in order to access the display.\nThirdParty - This folder contains third-party source codes (BSP).\nCreating the UI Examples # For the first bring up of your system, we recommend to use the example \u0026lsquo;HelloWorld\u0026rsquo;:\nPicture: Example \u0026lsquo;HelloWorld\u0026rsquo; within Embedded Wizard Studio.\nThe following steps are necessary to generate the source code of this sample application:\nNavigate to the directory \\\\main\\\\Examples\\\\ScreenSize\\\\HelloWorld.\nOpen the project file HelloWorld.ewp with your previously installed Embedded Wizard Studio. The entire project is well documented inline. You can run the UI application within the Prototyper by pressing Ctrl+F5.\nTo start the code generator, select the menu items Build➤Build this profile - or simply press F8. Embedded Wizard Studio generates now the sources files of the example project into the directory \\\\main\\\\Application\\\\GeneratedCode.\nCompiling, Linking and Flashing # The following steps are necessary to build and flash the Embedded Wizard UI sample application using the MSYS2 MINGW32 toolchain:\nOpen a console (with all necessary settings for building an ESP-IDF project) and navigate to the top level of the Build Environment \\\\esp\\\\ESP32-S3-BOX.\nIf you want to change or inspect the current settings, please insert:\nidf.py menuconfig Start compiling and linking: idf.py build Now you can flash the application (by using the appropriate COM port): idf.py -p COMxx flash In order to get outputs from the application and to provide key inputs, start the monitor: idf.py -p COMxx monitor If everything works as expected, the application should be built and flashed to the ESP32-S3-BOX.\nPicture: Example \u0026lsquo;HelloWorld\u0026rsquo; running on ESP32-S3-BOX.\nAll other examples can be created in the same way: Just open the desired example with Embedded Wizard Studio, generate code and rebuild the whole application using simply:\nidf.py build idf.py -p COMxx flash idf.py -p COMxx monitor Alternatively you can abbreviate it as one command:\nidf.py -p COMxx build flash monitor If you update just application code, you can speed up the flashing part by flashing only the application binary:\nidf.py -p COMxx app-flash monitor Creating your own UI Applications # In order to create your own UI project suitable for the ESP32-S3-BOX, you can create a new project and select the ESP32-S3-BOX project template:\nPicture: Create new Embedded Wizard Project.\nAs a result you get a new Embedded Wizard project, that contains the necessary Profile attributes suitable for the ESP32-S3-BOX:\nPicture: Embedded Wizard Configuration.\nThe following profile settings are important for your target: ★The attribute PlatformPackage should refer to the ESP32 Platform Package. The supported color formats are RGB565, Index8 and LumA44.\nThe attribute ScreenSize should correspond to the display size of the ESP32-S3-BOX.\nThe attributes ModeOfBitmapResources and ModeOfStringConstants should be set to DirectAccess. This ensures that resources are taken directly from flash memory.\nThe attribute OutputDirectory should refer to the \\main\\Application\\GeneratedCode directory within your Build Environment. By using this template, it will be very easy to build the UI project for your target.\nThe attribute CleanOutputDirectories should be set to true to ensure that unused source code within the output directory \\main\\Application\\GeneratedCode will be deleted.\nNow you can use the template project in the same manner as it was used for the provided examples to compile, link and flash the binary.\nAfter generating code, please follow these steps, in order to build your own UI application:\nStart compiling, linking and flashing: idf.py build idf.py -p COMxx flash idf.py -p COMxx monitor Most of the project settings are taken directly out of the generated code, like the color format or the screen orientation. All other settings can be made directly within the file ewconfig.h, which contains general configuration settings for the target system.\nConsole output # In order to receive error messages or to display simple debug or trace messages from your Embedded Wizard UI application, a serial terminal like \u0026lsquo;Putty\u0026rsquo; or \u0026lsquo;TeraTerm\u0026rsquo; should be used or the monitor that is started together with idf.py -p COMxx monitor\nPicture: Console output.\nThis terminal connection can be used for all trace statements from your Embedded Wizard UI applications or for all debug messages from your C code.\nYou can find all release notes and the version history of the Build Environment (including Graphics Engine and Runtime Environment) for the ESP32-S3-BOX at the bottom of this page. These release notes describe only the platform specific aspects - for all general improvements and enhancements please see the Embedded Wizard release notes.\n","date":"2 October 2024","externalUrl":null,"permalink":"/blog/how-to-create-an-ui-application-for-the-esp32-s3/","section":"Blog","summary":"","title":"How to Create an UI Application for the ESP32-S3","type":"blog"},{"content":"Espressif’s Secure Manufacturing Service, which was launched last year, has assisted many customers in simplifying their manufacturing. Since a year from launch, we worked with hundreds of customers and served millions of modules that were manufactured with this service.\nThis service lets customers order modules from Espressif such that they are pre-programmed with all the Matter-specific security configurations, firmware, and other device-unique credentials and certificates that should be flashed on the modules. This saves organizations hassle and time from building their own manufacturing scripts and back-and-forth with factory lines.\nInitially, we had been running a VID-scoped PAA (Product Attestation Authority). Now, Espressif is an approved signing authority for a Non-VID scoped PAA (Product Attestation Authority) also called as Open PAA.\nWhat does being a non-VID scoped PAA mean? # Effectively, we can now support workflows that we previously were not able to support, viz:\nSecure Matter Manufacturing in your Factory (Matter DACs and device-unique data) Upgrading in-field devices to support Matter by generating and delivering DACs securely Matter Manufacturing in your Factory # We announced support for Accelerated Matter Manufacturing last year. This allowed organizations to accelerate the manufacturing of their Matter devices, by allowing Espressif to pre-program the Device Attestation certificates (DACs), the firmware, and security configurations on modules before being shipped out.\nOne request we kept getting was a provision to perform this manufacturing in the customer’s factory of choice. This is now possible with our latest update. We are currently working with select customers to enable their factories to perform Matter manufacturing by themselves. If you are interested in this, please reach out to us for the next steps.\nThe most important part of this is having the ability to securely deliver cryptographically signed Device Attestation Certificates (DACs) to the modules without their private key ever leaving the module.\nThe typical workflow is shown in the following diagram.\nUpgrading In-field Devices to Matter # We also support delivering of DACs to in-field devices, that wish to now incorporate Matter support. For this scenario, it is essential that the in-field devices have a mutually authenticated secure connection to some device cloud platform. The cloud platform is expected to act as the trust broker for the in-field devices. The secure DAC delivery in this case happens as shown in the following diagram.\nIf you are working on building Matter products, please reach out to us to check how this aligns with your product deployment workflow.\n","date":"1 October 2024","externalUrl":null,"permalink":"/blog/matter-improvements-to-espressif-dac-provisioning-service/","section":"Blog","summary":"","title":"Matter: Improvements to Espressif DAC Provisioning Service","type":"blog"},{"content":"In today\u0026rsquo;s rapidly evolving IoT landscape, LCD screens have become indispensable components of smart devices, providing real-time information and facilitating user interaction. As the demand for higher performance, lower power consumption, and more compact designs grows, it is crucial to choose the right technology to drive LCD screens. This article explores a number of Espressif SoCs that support different LCD driver interfaces, suitable for smart home, smart security, and other applications.\nOn top of that, this article touches on Espressif\u0026rsquo;s rich development resources and one-stop AIoT cloud platform ESP-RainMaker which, among others, supports the Matter protocol to build cross-ecosystem solutions. Whether you\u0026rsquo;re an engineer, developer, or product designer, this article will guide you through the unique features and practical applications of Espressif\u0026rsquo;s SoCs with LCD screens.\nCurrent use of LCD Screens # LCD screens are built into all types of modern devices, serving as key components for displaying real-time information and enabling interactive experiences. They are especially important in the AIoT (Artificial Intelligence of Things) sector, where the rapid development of IoT technologies has expanded the application scenarios for LCD screens.\nThese screens are widely used as the main input and output devices for human-computer interaction in various rapidly expanding fields, including:\nSmart Home: Control panels, smart mirrors, and other home automation devices. Smart Security: Displays in surveillance systems, doorbells, and security panels. Industrial Control: Interface screens for machinery and process monitoring. Smart Cities: Public information displays, traffic control systems, and environmental monitoring. The commercial value of LCD screens is increasing as they become more integral to these applications, driven by their ability to meet the growing demands for performance, power efficiency, and compactness in modern electronic devices.\nAdvantages of using Espressif SoCs with LCD screens # Modern products that integrate LCD screens push for high performance, low power consumption, and compact design. Equally important is the ability to handle complex functions such as UI display, screen control, voice interaction, and wireless connectivity (Wi-Fi and Bluetooth). Espressif SoCs are designed to meet and even exceed these demands by integrating multiple functionalities into a single, highly-efficient SoC.\nWith their rich functionality, Espressif SoCs reduce or even eliminate the need for additional hardware. This integration not only reduces hardware costs and power consumption but also minimizes the required physical space, allowing for more compact and efficient device designs.\nEspressif provides comprehensive software tools, such as the ESP-IDF software development framework and the LVGL GUI development framework, which will be covered later in this article. These tools reduce software development time and costs. Additionally, Espressif provides rich and cost-effective LCD application solutions.\nOverview of supported LCD interfaces # Espressif SoCs support commonly used LCD interfaces, including SPI, QSPI, 8080, RGB, and MIPI DSI. The table below provides a high-level overview of the LCD interfaces and which Espressif SoCs support them respectively.\nEspressif SoC support for LCD driver interface The following table provides recommendations for SoC selection based on the required application parameters.\nEspressif SoC recommended for LCD application solution Recommended LCD Screen Solutions # There are three recommended tried-and-true solutions for integrating LCD screens with Espressif SoCs, each tailored to different LCD interfaces and application needs:\nESP32-P4 for MIPI + LCD: Ideal for high-performance displays with extensive IO connectivity, suited for multimedia applications and advanced user interaction. ESP32-S3 for RGB + LCD: Perfect for large screens with high refresh rates, offering robust performance for smart home control panels and other interactive interfaces. ESP32-C3 and ESP32-C6 for SPI + LCD: Designed for small screens with cost and power efficiency in mind, suitable for compact consumer electronics and low-power devices. ESP32-P4 for MIPI + LCD # The MIPI interface offers high data transfer rates and is efficient in handling high-resolution displays. It is particularly suitable for applications requiring fast, high-quality graphics and real-time data processing.\nFor applications using the MIPI interface, the ESP32-P4 SoC is recommended. This SoC is suitable for products that demand extensive I/O connectivity and high performance, such as video doorbells, surveillance cameras, smart home control panels, central control panels, digital price tags, bicycle dashboards, etc.\nThe ESP32-P4 features:\nDual-Core Processor: 400 MHz RISC-V Memory Support: Up to 32 MB PSRAM USB Support: USB 2.0 specification Peripherals: Includes MIPI-CSI/DSI, H264 Encoder, and other relevant peripherals The ESP32-P4-Function-EV-Board is the recommended development board for prototyping MIPI interface LCD solutions. It offers several key features:\nWi-Fi and Bluetooth Module: 2.4 GHz Wi-Fi 6 \u0026amp; Bluetooth 5 (LE) via the integrated ESP32-C6-MINI-1 module Display: 7-inch capacitive touch screen with 1024 x 600 resolution Camera: 2MP camera with MIPI CSI Applications: Suitable for developing low-cost, high-performance, low-power network-connected audio and video products This development board is an excellent choice for evaluating and building prototypes for various MIPI interface LCD applications. You can see the video presentation: Unveiling ESP32-P4: High-performing SoC with extensive IO connectivity, HMI, and security features.\nESP32-S3 for RGB + LCD # The RGB interface is known for its high brush rate, making it ideal for controlling large screens. Its broad application range allows it to support various display sizes and resolutions, ensuring smooth and responsive graphical user interfaces (GUIs).\nFor applications using the RGB interface, the ESP32-S3 SoC is recommended. This SoC is suitable for several smart and interactive applications:\nSmart Home Interfaces: This includes various types of control panels such as device control panels, light switch panels, scene controllers, and temperature management panels. Interactive Remote Controls: Remote controls designed with responsive and engaging displays for improved user interaction. Multi-Function Gateways: Devices that combine several functions, providing comprehensive smart home control and enhanced human-computer interaction. The ESP32-S3 features:\nDual-Core CPU: Provides robust processing power. AI Computing Power: Enables sensitive touch experience and high-performance offline and online human-computer voice interaction. Rich Peripheral Interfaces: Supports communication with a variety of peripheral devices. Smooth GUI Response: Ensures a responsive and fluid graphical user interface. The recommended development boards for building prototypes are as follows:\nESP32-S3-LCD-EV-Board:\nScreen: 3.95-inch 480x480 LCD. Purpose: Ideal for building prototypes and evaluating RGB interface solutions. Features: Designed to work seamlessly with the ESP32-S3 SoC. ESP32-S3-LCD-EV-Board-2:\nScreen: 3.95-inch 800x480 LCD. Purpose: Offers an alternative for higher resolution prototyping. Features: Provides enhanced evaluation capabilities with a larger display resolution. ESP32-S3-LCD-EV-Board and ESP32-S3-LCD-EV-Board-2 ESP32-C3 and ESP32-C6 for SPI + LCD # The SPI interface is well-suited for small screens and low-resolution displays due to its simplicity and cost-effectiveness. It is particularly efficient for small display applications with basic graphical needs. In other words, it is good for straightforward and economical solutions.\nFor applications using the SPI interface, the ESP32-C3 and ESP32-C6 SoCs are recommended. These SoCs are suitable for the following applications:\nHousehold Appliances: Washing machines, body fat scales, personal health devices, electric toothbrushes. Small Display Devices: Knob screens, compact displays used in various consumer electronics. The ESP32-C3 is cost-effective and has industry-leading low-power performance. It can dynamically adjust its operating frequency and switch between low-power modes to extend battery life.\nOn the other hand, the ESP32-C6 offers larger RAM memory than the ESP32-C3 and supports higher resolution displays through the QSPI interface, achieving a low-cost intelligent screen display scheme with medium resolution.\nThe recommended development board for prototyping and evaluation is the ESP32-C3-LCDkit board that can be bought here.\nESP32-C3-LCDkit comes with a 1.28-inch 240*240 LCD Software ecosystem # Espressif’s LCD application solutions come with a comprehensive set of software development resources designed to streamline and enhance the development process.\nThe overall framework for Espressif’s LCD application development is as follows:\nEspressif's LCD application development of the overall framework Development frameworks # Espressif provides ESP-IDF (Espressif IoT Development Framework), a robust environment for developing applications on Espressif SoCs. This framework facilitates efficient programming and integration with various hardware components.\nEspressif’s solutions also incorporate SquareLine Studio GUI development framework. This GUI development framework allows developers to design and implement graphical user interfaces with ease, providing tools for creating visually appealing and interactive applications.\nDevelopment tools and components # The esp_lvgl_port component is specifically designed to work with the ESP-IDF framework, enabling seamless integration of LVGL into your projects. It simplifies graphical interaction functionality and streamlines GUI development.\nEspressif’s ESP Component Registry offers a large number of components that can be easily integrated into new projects. This feature helps developers avoid redundant coding and reduces both development costs and complexity.\nDevelopment boards and BSP components # Development boards like the ESP32-S3-LCD-EV-Board and ESP32-C3-LCDkit come with BSP (Board Support Package) components available in the ESP-BSP repository. These components can be directly added to your projects through the Component Manager, facilitating easy integration and development.\nSupport for cross-ecosystem communication # Espressif’s LCD solutions support the Matter protocol, which enables communication across different ecosystems and brands. This ensures that smart screen devices can seamlessly interact with other smart home devices.\nESP RainMaker® is Espressif’s AIoT cloud platform, providing a comprehensive solution for managing and controlling smart devices. It supports both on-device cloud functionalities and remote control, making it easier to develop and deploy smart HMI (Human-Machine Interface) products.\nContact information # To learn more about Espressif’s LCD application solutions or to discuss commercial project collaboration, don\u0026rsquo;t hesitate to get in touch with us. We are eager to explore how our solutions can meet your needs and contribute to your project’s success.\n","date":"30 September 2024","externalUrl":null,"permalink":"/blog/espressif-socs-lcd-screens/","section":"Blog","summary":"","title":"Espressif SoCs and LCD screens: trends and solutions","type":"blog"},{"content":"","date":"30 September 2024","externalUrl":null,"permalink":"/tags/lcd/","section":"Tags","summary":"","title":"LCD","type":"tags"},{"content":"","date":"30 September 2024","externalUrl":null,"permalink":"/tags/mipi/","section":"Tags","summary":"","title":"MIPI","type":"tags"},{"content":"","date":"30 September 2024","externalUrl":null,"permalink":"/tags/rgb/","section":"Tags","summary":"","title":"RGB","type":"tags"},{"content":" Assignment 2: Create a new project with Components # In this assignment, we will show how to work with Components and how to use them to speed up the development of your projects.\nComponents are similar to libraries (like those from Arduino IDE); they also contain various additional functionality that you wouldn\u0026rsquo;t find in basic ESP-IDF. For example, let\u0026rsquo;s mention various drivers for sensors, protocol components, or BSP, board support package, which will be discussed later. Some components are already a direct part of some ESP-IDF examples, but it is also possible to use external components thanks to the modular structure of ESP-IDF.\nBy using components, not only is project maintainability simplified, but its development is also significantly accelerated. Components also allow the same functionality to be reused across different projects.\nIf you want to create and publish your own component (for example for your specific sensor), we recommend that you watch the talk DevCon23 - Developing, Publishing, and Maintaining Components for ESP-IDF.\nYou can browse components, for example, through the ESP Registry platform.\nWe will demonstrate the use of components on a new project, where we will write a simple application from scratch that will blink the built-in RGB LED using a component for LED strips. Later we will show how we can use a BSP (board support package) component for the same purpose, which was mentioned above.\nWorking with components # We will use the following two components:\nComponent for RGB LED (WS2812) strips, although in our case the LED \u0026ldquo;strip\u0026rdquo; will be only a single built-in LED connected to GPIO8. Remote Control Transceiver (RMT) component, which we will use to control the data flow to the LED. Creating a new project A new project can be created via GUI or command line. For those who don\u0026rsquo;t work much with terminal (CLI), it can be somewhat scary, but in the future it will help you, for example, in situations where you will use ESP-IDF with an IDE other than VSCode (or completely standalone). Both examples are given below.\nGUI\nOpen ESP-IDF Explorer (Espressif icon in taskbar or via View -\u0026gt; Open View -\u0026gt; ESP-IDF: Explorer) and select New Project Wizard command (may be hidden in Advanced menu). Then proceed according to the pictures:\nFirst step of creating a new projectCreating a new project. Serial port is not important, it can be changed later.\nSecond step of creating a new projectIn the next step we choose what template to base our project on. We choose get-started/hello_world and create the project.\nAfter creating the project, an unobtrusive window will appear in the bottom right, which will ask you whether you want to open the newly created project in a new window. Click \u0026ldquo;Yes\u0026rdquo;.\nCLI\nIn the ESP-IDF Explorer in the commands tab, select ESP-IDF Terminal, which will open at the bottom of the screen. To create a new project:\nCreate and go to the folder where we want to have our project Create the project Go to it mkdir ~/my-workshop-folder cd ~/my-workshop-folder idf.py create-project my-workshop-project cd my-workshop-project If the idf.py ... commands don\u0026rsquo;t work for you, make sure you\u0026rsquo;re using ESP-IDF Terminal and not just a regular console.\nNow we need to set the so-called target. This word can have multiple meanings in the context of ESP-IDF, but in our case it will always mean the type of SoC we are using. In our case it is ESP32-C6 chip (via Builtin USB JTAG).\nIn CLI there is a slight problem, as there may be a mismatch between VSCode and ESP-IDF, so it is better to set an environment variable instead of a command.\nexport IDF_TARGET=esp32c6 # idf.py set-target esp32c6 Now we are ready to add the espressif/led_strip component. As already mentioned, the component will take care of all the necessary drivers for our LED \u0026ldquo;strip\u0026rdquo; with one built-in diode.\nAdding a component GUI\nOpen View -\u0026gt; Command Palette (Ctrl + Shift + P or ⇧ + ⌘ + P) and type ESP-IDF: Show ESP Component Registry in the newly opened line. Now search for espressif/led_strip (searching may take a few seconds when seemingly nothing happens), click on the component, select the correct version (2.5.3) and click Install. WARNING: We are using an older version of the component, don\u0026rsquo;t forget to select it from\nInstalling led_strip component 1Component search\nInstalling led_strip component 2Component installation\nCLI\nidf.py add-dependency \u0026#34;espressif/led_strip^2.5.3\u0026#34; You may notice that a new file named idf_component.yml has been created in the main project directory (main). On the first build, the managed_components folder will also be created and the component will be downloaded to it if it was added via CLI. If you added the component via GUI, everything will be created even without build.\n# Contents of idf_component.yml dependencies: espressif/led_strip: \u0026#34;^2.5.3\u0026#34; idf: version: \u0026#34;\u0026gt;=4.4\u0026#34; You can also add dependent components to this file manually, without using any commands.\nNow we will throw ourselves into the programming itself.\nCreating a function that configures the LED and RMT driver Let\u0026rsquo;s open the file hello_world_main.c. First we need to import the led_strip.h library\u0026hellip;\n#include \u0026#34;led_strip.h\u0026#34; \u0026hellip;declare the necessary constants\u0026hellip;\n// 10MHz resolution, 1 tick = 0.1us (led strip needs a high resolution) #define LED_STRIP_RMT_RES_HZ (10 * 1000 * 1000) \u0026hellip;and create a function skeleton for configuration:\nled_strip_handle_t led_strip; void configure_led(void) { // Your code goes here } You will write the following 3 steps into this function in place of the comment Your code goes here.\nLED \u0026ldquo;strip\u0026rdquo; configuration We use the led_strip_config_t structure. For ESP32-C6-DevKit-C, the LED is of type WS2812.\nled_strip_config_t strip_config = { // Set the GPIO8 that the LED is connected .strip_gpio_num = 8, // Set the number of connected LEDs, 1 .max_leds = 1, // Set the pixel format of your LED strip .led_pixel_format = LED_PIXEL_FORMAT_GRB, // LED model .led_model = LED_MODEL_WS2812, // In some cases, the logic is inverted .flags.invert_out = false, }; RMT configuration We use the led_strip_rmt_config_t structure:\nled_strip_rmt_config_t rmt_config = { // Set the clock source .clk_src = RMT_CLK_SRC_DEFAULT, // Set the RMT counter clock .resolution_hz = LED_STRIP_RMT_RES_HZ, // Set the DMA feature (not supported on the ESP32-C6) .flags.with_dma = false, }; Creating RMT device led_strip_new_rmt_device(\u0026amp;strip_config, \u0026amp;rmt_config, \u0026amp;led_strip); Creating an object for the LED \u0026ldquo;strip\u0026rdquo; When we have the configure_led() function ready, we can call it in the main app_main function.\nconfigure_led(); Setting colors To set the color, we use the led_strip_set_pixel function with the following parameters:\nled_strip: our configured LED \u0026ldquo;strip\u0026rdquo; object 0: diode index in the strip (since we only have one, the index will always be 0) 20: red (RED) component with values between 0 and 255 0: green (GREEN) component with values between 0 and 255 0: blue (BLUE) component with values between 0 and 255 led_strip_set_pixel(led_strip, 0, 20, 0, 0); Try different values for R,G,B channels!\nUpdate LED \u0026ldquo;strip\u0026rdquo; values Just setting the pixel value is not enough; for the values set in the previous step to take effect, the entire \u0026ldquo;strip\u0026rdquo; must first be refreshed:\nled_strip_refresh(led_strip); If we want to turn off the entire LED strip, we can use the function led_strip_clear(led_strip);.\nBuilding and uploading code to the board When our code is complete, we need to somehow get it into our board. The entire process can be divided into 4 steps:\nDetermining the target: the specific board we are using. In the ESP-IDF explorer tab in the Commands section, select Set Espressif Device Target (IDF_TARGET), choose esp32c6 and in the subsequent menu select ESP32-C6 chip (via builtin USB-JTAG). Build: building the application and creating a binary file that we will upload. In the same place as last time, click on the Build Project command. Selecting the correct serial port to which our board is connected. We also set the serial port using a command in ESP-IDF Explorer, this time using Select Port to Use. Flash: uploading the binary file to the board. The command of the same name will serve us for this, which can be found right next to the others. If VScode asks us about \u0026ldquo;flash method\u0026rdquo;, we select \u0026ldquo;UART\u0026rdquo;. If someone accidentally selects the wrong flash method (e.g. JTAG), just manually edit \u0026quot;idf.flashType\u0026quot;: to \u0026quot;UART\u0026quot; in the .vscode/settings.json file.\nAll commands can also be invoked using Command Palette, which you open with the key combination Ctrl + Shift + P or ⇧ + ⌘ + P. However, the commands are sometimes named slightly differently (for example, instead of Select Serial Port, the command is called ESP-IDF: Select Port to Use). You can freely combine both approaches.\nComplete code # Below you can find the complete and commented code for this assignment:\n#include \u0026lt;stdio.h\u0026gt; #include \u0026#34;led_strip.h\u0026#34; // 10MHz resolution, 1 tick = 0.1us (led strip needs a high resolution) #define LED_STRIP_RMT_RES_HZ (10 * 1000 * 1000) led_strip_handle_t led_strip; void configure_led(void) { // LED strip general initialization, according to your led board design led_strip_config_t strip_config = { // Set the GPIO that the LED is connected .strip_gpio_num = 8, // Set the number of connected LEDs in the strip .max_leds = 1, // Set the pixel format of your LED strip .led_pixel_format = LED_PIXEL_FORMAT_GRB, // LED strip model .led_model = LED_MODEL_WS2812, // In some cases, the logic is inverted .flags.invert_out = false, }; // LED strip backend configuration: RMT led_strip_rmt_config_t rmt_config = { // Set the clock source .clk_src = RMT_CLK_SRC_DEFAULT, // Set the RMT counter clock .resolution_hz = LED_STRIP_RMT_RES_HZ, // Set the DMA feature (not supported on the ESP32-C6) .flags.with_dma = false, }; // LED Strip object handle led_strip_new_rmt_device(\u0026amp;strip_config, \u0026amp;rmt_config, \u0026amp;led_strip); } void app_main(void) { configure_led(); led_strip_set_pixel(led_strip, 0, 20, 0, 0); led_strip_refresh(led_strip); } Expected result # The built-in LED should light up red.\nPart two: the same, but with BSP # In the previous part, we learned how to add components to a project. Now let\u0026rsquo;s talk about BSP - board support package.\nBSP is a component that allows easy configuration of peripherals (LED, button\u0026hellip;) of some specific development board. Specifically, our ESP32-C6-DevKit has one button connected to GPIO9 and one addressable LED on pin GPIO8. In the BSP for this specific board, these two peripherals will therefore be configured and if we use BSP, we don\u0026rsquo;t have to worry about pin configuration or add any other components that would take care of the given peripherals.\nThe example with our kit is relatively simple for BSP, but there are also more complex development boards, for example ESP32-S3-BOX-3. The BSP for this kit can therefore handle all peripherals, such as displays, sensors, LEDs, but also e.g. audio codecs. Everything in one package and without any additional components.\nThe advantages of using BSP are for example:\nEasy initial configuration Code reuse across different projects with the same development kit Reduces the number of board configuration errors Ensures that all necessary dependencies are part of the project In addition to working with BSP, we will also show how to create a project from some example that is part of a component, in our case the espressif/esp_bsp_generic component and the example examples/generic_button_led. Some components also contain demonstration projects that show how to properly use such a component.\nBelow we will describe how to do it:\nCreating a new project from an example To create a new project from an example that is part of a component, we need to move to the ESP-IDF command line for a while. We can invoke it either as the ESP-IDF: Open ESP-IDF Terminal command in Command Palette or find the ESP-IDF Terminal command as a button in the Commands section of our ESP-IDF Explorer. To avoid creating a project within a project, we first move up one directory.\ncd .. idf.py create-project-from-example \u0026#34;espressif/esp_bsp_generic^1.2.0:generic_button_led\u0026#34; Then we open the project in a new window (it will be in the same folder as the previous one) and check that the main/idf_component.yaml file looks as follows:\ndependencies: esp_bsp_generic: version: ^1.2.0 description: BSP Display example If, for example, the BSP version doesn\u0026rsquo;t match, we change it to ^1.2.0, as shown in the example above.\nSetting peripherals Since we are using generic BSP, we still won\u0026rsquo;t avoid configuration. Again we will work with LED, so we need to set that our board has one LED on pin GPIO8 (and we will control it using RMT).\nESP-IDF uses the Kconfig language and the kconfiglib library to configure projects. We invoke the configuration menu using:\nSDK Configuration Editor (menuconfig) command in ESP-IDF: Explorer By searching for this command in Command Palette (Ctrl + Shift + P) In CLI using the idf.py menuconfig command, called in the project root folder. In the configuration menu, go to Component config -\u0026gt; Board Support Package (generic) and set:\nButtons Number of buttons in BSP to 0 LEDs LED type to Addressable RGB LED Number of LEDs in BSP to 1 Addressable RGB LED GPIO to 8 Addressable RGB LED backend peripheral to RMT Finally, don\u0026rsquo;t forget to save everything with the Save button in the top right.\nThe configuration menu invoked via idf.py menuconfig is controlled with arrows, you enter the menu with enter and exit it with backspace. The final exit is done with the Escape key and subsequent pressing (Y) to confirm saving.\nBuild and flash Copy the code below into the main.c file of our BSP project:\n#include \u0026lt;stdio.h\u0026gt; #include \u0026#34;bsp/esp-bsp.h\u0026#34; #include \u0026#34;led_indicator_blink_default.h\u0026#34; static led_indicator_handle_t leds[BSP_LED_NUM]; void app_main(void) { ESP_ERROR_CHECK(bsp_led_indicator_create(leds, NULL, BSP_LED_NUM)); led_indicator_set_rgb(leds[0], SET_IRGB(0, 0x20, 0x0, 0x0)); } Now you can build and upload the project to your development board.\nIf a problem occurred during assembly, try deleting build files:\nidf.py fullclean\nor Full Clean in ESP-IDF Explorer\nExtra part # If you want to try other functionality from this BSP, try running the following code. You may need to adjust the configuration and add a button.\n#include \u0026lt;stdio.h\u0026gt; #include \u0026#34;bsp/esp-bsp.h\u0026#34; #include \u0026#34;esp_log.h\u0026#34; #include \u0026#34;led_indicator_blink_default.h\u0026#34; static const char *TAG = \u0026#34;example\u0026#34;; #if CONFIG_BSP_LEDS_NUM \u0026gt; 0 static int example_sel_effect = BSP_LED_BREATHE_SLOW; static led_indicator_handle_t leds[BSP_LED_NUM]; #endif #if CONFIG_BSP_BUTTONS_NUM \u0026gt; 0 static void btn_handler(void *button_handle, void *usr_data) { int button_pressed = (int)usr_data; ESP_LOGI(TAG, \u0026#34;Button pressed: %d. \u0026#34;, button_pressed); #if CONFIG_BSP_LEDS_NUM \u0026gt; 0 led_indicator_stop(leds[0], example_sel_effect); if (button_pressed == 0) { example_sel_effect++; if (example_sel_effect \u0026gt;= BSP_LED_MAX) { example_sel_effect = BSP_LED_ON; } } ESP_LOGI(TAG, \u0026#34;Changed LED blink effect: %d.\u0026#34;, example_sel_effect); led_indicator_start(leds[0], example_sel_effect); #endif } void app_main(void) { #if CONFIG_BSP_BUTTONS_NUM \u0026gt; 0 /* Init buttons */ button_handle_t btns[BSP_BUTTON_NUM]; ESP_ERROR_CHECK(bsp_iot_button_create(btns, NULL, BSP_BUTTON_NUM)); for (int i = 0; i \u0026lt; BSP_BUTTON_NUM; i++) { ESP_ERROR_CHECK(iot_button_register_cb(btns[i], BUTTON_PRESS_DOWN, btn_handler, (void *) i)); } #endif #if CONFIG_BSP_LEDS_NUM \u0026gt; 0 /* Init LEDs */ ESP_ERROR_CHECK(bsp_led_indicator_create(leds, NULL, BSP_LED_NUM)); /* Set LED color for first LED (only for addressable RGB LEDs) */ led_indicator_set_rgb(leds[0], SET_IRGB(0, 0x00, 0x64, 0x64)); /* Start effect for each LED (predefined: BSP_LED_ON, BSP_LED_OFF, BSP_LED_BLINK_FAST, BSP_LED_BLINK_SLOW, BSP_LED_BREATHE_FAST, BSP_LED_BREATHE_SLOW) */ led_indicator_start(leds[0], BSP_LED_BREATHE_SLOW); #endif } Next step # Let there be light! When we can do basic tasks with ESP and IDE, we are ready to connect to WiFi too!\nAssignment 3: Connect to Wi-Fi\n","date":"30 September 2024","externalUrl":null,"permalink":"/workshops/esp-idf-with-esp32-c6/assignment-2/","section":"Workshops","summary":"","title":"Workshop: ESP-IDF and ESP32-C6 - Assignment 2","type":"workshops"},{"content":" Assignment 3: Connect to Wi-Fi # Now it\u0026rsquo;s finally time to connect our ESP32-C6 to a Wi-Fi network. ESP32-C6 supports both Wi-Fi 4 and Wi-Fi 6 standards on the 2.4 GHz frequency.\nWi-Fi connectivity is one of the most important features of most chips from the ESP32 family and is one of the essential components of their success. Thanks to Wi-Fi, it is possible to connect your IoT device to the internet and truly use all its features. This doesn\u0026rsquo;t necessarily mean just connecting to cloud services, but also e.g. over-the-air (OTA) updates, remote control and monitoring and much more.\nESP32 supports two modes: Station and SoftAP:\nStation mode: ESP connects to an existing network (like a home router). SoftAP mode: Other devices (like laptop or mobile) connect directly to ESP, where e.g. a web server with control can run. For this assignment, we will reuse the project we worked with in the previous assignment, specifically its second version using BSP, and connect to an existing Wi-Fi 4/Wi-Fi 6 network (so we will use station mode).\nConnecting to Wi-Fi # To be able to start using Wi-Fi, we need to tell the framework that we will use Wi-Fi: in the main/CMakeLists.txt file, specifically in the idf_component_register function, we add the following line:\nREQUIRES esp_wifi esp_netif esp_event nvs_flash Now we need to set up the Wi-Fi driver: we need to specify SSID and password.\nCopy the skeleton #include \u0026lt;stdio.h\u0026gt; #include \u0026#34;bsp/esp-bsp.h\u0026#34; #include \u0026#34;led_indicator_blink_default.h\u0026#34; #include \u0026#34;freertos/FreeRTOS.h\u0026#34; #include \u0026#34;freertos/task.h\u0026#34; #include \u0026#34;freertos/event_groups.h\u0026#34; #include \u0026#34;esp_system.h\u0026#34; #include \u0026#34;esp_wifi.h\u0026#34; #include \u0026#34;esp_event.h\u0026#34; #include \u0026#34;esp_log.h\u0026#34; #include \u0026#34;nvs_flash.h\u0026#34; #include \u0026#34;lwip/err.h\u0026#34; #include \u0026#34;lwip/sys.h\u0026#34; #define WIFI_SSID \u0026#34;network-ssid\u0026#34; #define WIFI_PASS \u0026#34;network-pass\u0026#34; #define WIFI_CONNECTED_BIT BIT0 #define WIFI_FAIL_BIT BIT1 static led_indicator_handle_t leds[1]; static EventGroupHandle_t s_wifi_event_group; static int s_retry_num = 0; static const char *TAG = \u0026#34;workshop\u0026#34;; // TODO handler void wifi_init_sta(void) { s_wifi_event_group = xEventGroupCreate(); //TODO } void app_main(void) { esp_err_t ret = nvs_flash_init(); //TODO ESP_ERROR_CHECK(bsp_led_indicator_create(leds, NULL, BSP_LED_NUM)); led_indicator_set_rgb(leds[0], SET_IRGB(0, 0x20, 0x0, 0x0)); wifi_init_sta(); } Wi-Fi initialization Wi-Fi initialization consists of these steps, which we will add to the wifi_init_sta() function:\nTCP/IP stack initialization: ESP_ERROR_CHECK(esp_netif_init()); ESP_ERROR_CHECK(esp_event_loop_create_default()); esp_netif_create_default_wifi_sta(); Creating default configuration for Wi-Fi initialization and the initialization itself: wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT(); ESP_ERROR_CHECK(esp_wifi_init(\u0026amp;cfg)); Registering event handlers for WIFI_EVENT and IP_EVENT events: esp_event_handler_instance_t instance_any_id; esp_event_handler_instance_t instance_got_ip; esp_event_handler_instance_register(WIFI_EVENT, ESP_EVENT_ANY_ID, \u0026amp;event_handler, NULL, \u0026amp;instance_any_id); esp_event_handler_instance_register(IP_EVENT, IP_EVENT_STA_GOT_IP, \u0026amp;event_handler, NULL, \u0026amp;instance_got_ip); Setting Wi-Fi mode to station using WIFI_MODE_STA: ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_STA)); Setting the connection parameters themselves using the wifi_config_t structure: wifi_config_t wifi_config = { .sta = { // Set the newtork name .ssid = WIFI_SSID, // Set the network pass key .password = WIFI_PASS, // Set WPA as the authentication mode .threshold.authmode = WIFI_AUTH_WPA_PSK, // Set Simultaneous Authentication (SAE) and Password Element (PWE) derivation method .sae_pwe_h2e = WPA3_SAE_PWE_BOTH, // Set the password identifier for H2E (Hash-to-Element) .sae_h2e_identifier = \u0026#34;\u0026#34;, }, }; Now we can call the esp_wifi_set_config function. ESP_ERROR_CHECK(esp_wifi_set_config(WIFI_IF_STA, \u0026amp;wifi_config)); Now that both the Wi-Fi controller and the connection itself are set up, we can turn on Wi-Fi: ESP_ERROR_CHECK(esp_wifi_start()); Now we just need to wait for WIFI_CONNECTED_BIT or WIFI_FAIL_BIT and make sure everything worked: EventBits_t bits = xEventGroupWaitBits(s_wifi_event_group, WIFI_CONNECTED_BIT | WIFI_FAIL_BIT, pdFALSE, pdFALSE, portMAX_DELAY); if (bits \u0026amp; WIFI_CONNECTED_BIT) { ESP_LOGI(TAG, \u0026#34;Connected!\u0026#34;); } else if (bits \u0026amp; WIFI_FAIL_BIT) { ESP_LOGE(TAG, \u0026#34;Failed to connect!\u0026#34;); } Creating Wi-Fi event handler This will not be part of either app_main or wifi_init_sta, but will be at the same level as these two functions. It must be located before wifi_init_sta, in place of the comment //TODO event handler:\nstatic void event_handler(void* arg, esp_event_base_t event_base, int32_t event_id, void* event_data) { if (event_base == WIFI_EVENT \u0026amp;\u0026amp; event_id == WIFI_EVENT_STA_START) { esp_wifi_connect(); } else if (event_base == WIFI_EVENT \u0026amp;\u0026amp; event_id == WIFI_EVENT_STA_DISCONNECTED) { if (s_retry_num \u0026lt; 30) { esp_wifi_connect(); s_retry_num++; ESP_LOGW(TAG, \u0026#34;Trying to connect to WiFi\u0026#34;); led_indicator_set_rgb(leds[0], SET_IRGB(0, 0x0, 0x0, 0x20)); } else { xEventGroupSetBits(s_wifi_event_group, WIFI_FAIL_BIT); } ESP_LOGE(TAG, \u0026#34;Failed to connect to WiFi\u0026#34;); led_indicator_set_rgb(leds[0], SET_IRGB(0, 0x20, 0x0, 0x0)); } else if (event_base == IP_EVENT \u0026amp;\u0026amp; event_id == IP_EVENT_STA_GOT_IP) { ip_event_got_ip_t* event = (ip_event_got_ip_t*) event_data; ESP_LOGI(TAG, \u0026#34;got ip:\u0026#34; IPSTR, IP2STR(\u0026amp;event-\u0026gt;ip_info.ip)); led_indicator_set_rgb(leds[0], SET_IRGB(0, 0x0, 0x20, 0x0)); s_retry_num = 0; xEventGroupSetBits(s_wifi_event_group, WIFI_CONNECTED_BIT); } } NVS initialization check We will discuss NVS in the next assignment, so for now it will be a bit of a blackbox. We will add this code to app_main.\nesp_err_t ret = nvs_flash_init(); if (ret == ESP_ERR_NVS_NO_FREE_PAGES || ret == ESP_ERR_NVS_NEW_VERSION_FOUND) { ESP_ERROR_CHECK(nvs_flash_erase()); ret = nvs_flash_init(); } ESP_ERROR_CHECK(ret); ESP_ERROR_CHECK(bsp_led_indicator_create(leds, NULL, BSP_LED_NUM)); ESP_LOGI(TAG, \u0026#34;LEDs initialized successfully\u0026#34;); led_indicator_set_rgb(leds[0], SET_IRGB(0, 0x0, 0x0, 0x20)); Wi-Fi initialization The last step is calling our function in app_main:\nwifi_init_sta(); Now you can build and upload your code.\nThe ESP_LOGI and ESP_LOGE functions output data to the serial line. After we upload the program to the development board, we can open communication with the board using the Monitor command in ESP-IDF Explorer or using ESP-IDF: Monitor Device via Command Palette.\nComplete code # Below you can find the complete code for this assignment:\n#include \u0026lt;stdio.h\u0026gt; #include \u0026#34;bsp/esp-bsp.h\u0026#34; #include \u0026#34;led_indicator_blink_default.h\u0026#34; #include \u0026#34;freertos/FreeRTOS.h\u0026#34; #include \u0026#34;freertos/task.h\u0026#34; #include \u0026#34;freertos/event_groups.h\u0026#34; #include \u0026#34;esp_system.h\u0026#34; #include \u0026#34;esp_wifi.h\u0026#34; #include \u0026#34;esp_event.h\u0026#34; #include \u0026#34;esp_log.h\u0026#34; #include \u0026#34;nvs_flash.h\u0026#34; #include \u0026#34;lwip/err.h\u0026#34; #include \u0026#34;lwip/sys.h\u0026#34; #define WIFI_SSID \u0026#34;network-ssid\u0026#34; #define WIFI_PASS \u0026#34;network-pass\u0026#34; #define WIFI_CONNECTED_BIT BIT0 #define WIFI_FAIL_BIT BIT1 static led_indicator_handle_t leds[1]; static EventGroupHandle_t s_wifi_event_group; static int s_retry_num = 0; static const char *TAG = \u0026#34;workshop\u0026#34;; static void event_handler(void* arg, esp_event_base_t event_base, int32_t event_id, void* event_data) { if (event_base == WIFI_EVENT \u0026amp;\u0026amp; event_id == WIFI_EVENT_STA_START) { esp_wifi_connect(); } else if (event_base == WIFI_EVENT \u0026amp;\u0026amp; event_id == WIFI_EVENT_STA_DISCONNECTED) { if (s_retry_num \u0026lt; 30) { esp_wifi_connect(); s_retry_num++; ESP_LOGW(TAG, \u0026#34;Trying to connect to WiFi\u0026#34;); led_indicator_set_rgb(leds[0], SET_IRGB(0, 0x0, 0x0, 0x20)); } else { xEventGroupSetBits(s_wifi_event_group, WIFI_FAIL_BIT); } ESP_LOGE(TAG, \u0026#34;Failed to connect to WiFi\u0026#34;); led_indicator_set_rgb(leds[0], SET_IRGB(0, 0x20, 0x0, 0x0)); } else if (event_base == IP_EVENT \u0026amp;\u0026amp; event_id == IP_EVENT_STA_GOT_IP) { ip_event_got_ip_t* event = (ip_event_got_ip_t*) event_data; ESP_LOGI(TAG, \u0026#34;got ip:\u0026#34; IPSTR, IP2STR(\u0026amp;event-\u0026gt;ip_info.ip)); led_indicator_set_rgb(leds[0], SET_IRGB(0, 0x0, 0x20, 0x0)); s_retry_num = 0; xEventGroupSetBits(s_wifi_event_group, WIFI_CONNECTED_BIT); } } void wifi_init_sta(void) { s_wifi_event_group = xEventGroupCreate(); ESP_ERROR_CHECK(esp_netif_init()); ESP_ERROR_CHECK(esp_event_loop_create_default()); esp_netif_create_default_wifi_sta(); wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT(); ESP_ERROR_CHECK(esp_wifi_init(\u0026amp;cfg)); esp_event_handler_instance_t instance_any_id; esp_event_handler_instance_t instance_got_ip; ESP_ERROR_CHECK(esp_event_handler_instance_register(WIFI_EVENT, ESP_EVENT_ANY_ID, \u0026amp;event_handler, NULL, \u0026amp;instance_any_id)); ESP_ERROR_CHECK(esp_event_handler_instance_register(IP_EVENT, IP_EVENT_STA_GOT_IP, \u0026amp;event_handler, NULL, \u0026amp;instance_got_ip)); wifi_config_t wifi_config = { .sta = { .ssid = WIFI_SSID, .password = WIFI_PASS, .threshold.authmode = WIFI_AUTH_WPA_PSK, .sae_pwe_h2e = WPA3_SAE_PWE_BOTH, .sae_h2e_identifier = \u0026#34;\u0026#34;, }, }; ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_STA) ); ESP_ERROR_CHECK(esp_wifi_set_config(WIFI_IF_STA, \u0026amp;wifi_config) ); ESP_ERROR_CHECK(esp_wifi_start() ); EventBits_t bits = xEventGroupWaitBits(s_wifi_event_group, WIFI_CONNECTED_BIT | WIFI_FAIL_BIT, pdFALSE, pdFALSE, portMAX_DELAY); if (bits \u0026amp; WIFI_CONNECTED_BIT) { ESP_LOGI(TAG, \u0026#34;Connected!\u0026#34;); } else if (bits \u0026amp; WIFI_FAIL_BIT) { ESP_LOGE(TAG, \u0026#34;Failed to connect!\u0026#34;); } } void app_main(void) { esp_err_t ret = nvs_flash_init(); if (ret == ESP_ERR_NVS_NO_FREE_PAGES || ret == ESP_ERR_NVS_NEW_VERSION_FOUND) { ESP_ERROR_CHECK(nvs_flash_erase()); ret = nvs_flash_init(); } ESP_ERROR_CHECK(ret); ESP_ERROR_CHECK(bsp_led_indicator_create(leds, NULL, BSP_LED_NUM)); ESP_LOGI(TAG, \u0026#34;LEDs initialized successfully\u0026#34;); led_indicator_set_rgb(leds[0], SET_IRGB(0, 0x0, 0x0, 0x20)); wifi_init_sta(); } Extra # If you want, you can try connecting to Wi-Fi at home using the common_components/protocol_examples_common component. Next step # Now that we have successfully connected to Wi-Fi, let\u0026rsquo;s move on to working with memory!\nAssignment 4: NVS\n","date":"30 September 2024","externalUrl":null,"permalink":"/workshops/esp-idf-with-esp32-c6/assignment-3/","section":"Workshops","summary":"","title":"Workshop: ESP-IDF and ESP32-C6 - Assignment 3","type":"workshops"},{"content":" Assignment 4: The same, but with NVS # In the previous assignment, we used the simplest option for storing SSID and password; we defined constants directly in the code. Not only is this approach not ideal in terms of changes, where every change in SSID or password must be applied directly in the code and reflash our application. This method also brings considerable security risks.\nIn this assignment, we will look at how to work with Non-Volatile-Storage (NVS). NVS is often called \u0026ldquo;emulated EEPROM\u0026rdquo;. However, ESP32 does not have any built-in EEPROM, so NVS uses flash memory (the same one where we also store our application).\nIn this assignment, we will use the same project that we used in the previous two assignments. The principle of data storage in the NVS library is based on key-value pairs (similar to a dictionary in Python), including types integer, string, and blob (binary data of variable length).\nThe size of strings (including the null terminator) is currently limited to 4000 bytes. Blobs are limited to 508,000 bytes or 97.6% of partition size (4000 bytes in our case), whichever is smaller.\nNVS is useful especially when we need to store one or more configurations that need to remain persistent - permanently stored in flash memory.\nPractical demo of NVS # In the demo, we will show how to prepare a partition table, NVS data file and change the code from the previous assignment so that Wi-Fi name and password are read from NVS.\nCreating a partition table As we said, NVS uses flash memory. But it is also used for other data. So we need to modify the partition table and allocate space for our NVS partition.\nUsing the well-known shortcut Ctrl + Shift + P, we open Command Palette and search for Open Partition Table Editor UI.\nIf you cannot open the Partition Table Editor, verify that you have the Partition Table -\u0026gt; Partition Table option set to Custom partition table CSV in the configuration. We fill the table using \u0026ldquo;Add New Row\u0026rdquo; as shown in the image:\nPartition table contentsNVS table contents\nAfter clicking the \u0026ldquo;Save\u0026rdquo; button, the basic partition table partitions.csv will be saved and created, which will look like this:\n# ESP-IDF Partition Table # Name, Type, SubType, Offset, Size, Flags nvs, data, nvs, 0x9000, 0x6000, phy_init, data, phy, 0xf000, 0x1000, factory, app, factory, 0x10000, 1M, Values are also editable directly and individual partitions can be modified according to your own needs.\nCreating NVS file We open the NVS editor similarly: again using Ctrl + Shift + P we open Command Palette and select Open NVS partition editor. Then we enter the file name (nvs.csv) and press Enter. A window similar to the one below will open:\nNVS table contents We change the value Size of partition (bytes) to 0x6000 (same value as in partition table), add rows using \u0026ldquo;Add New Row\u0026rdquo; and fill them according to the image above. Then we press \u0026ldquo;Save\u0026rdquo;.\nFinally, we can open the nvs.csv file and verify that it looks the same as the one below:\nkey,type,encoding,value storage,namespace,, ssid,data,string,\u0026#34;network-ssid\u0026#34; password,data,string,\u0026#34;network-password\u0026#34; Incorporating NVS code into our project We will need a skeleton of a new function esp_err_t get_wifi_credentials, into which we will write code for reading data from NVS:\nchar ssid[32]; char password[64]; esp_err_t get_wifi_credentials(void){ //TODO } After we have already performed NVS initialization in the previous assignment, we can open the NVS partition:\nESP_LOGI(TAG, \u0026#34;Opening Non-Volatile Storage (NVS) handle\u0026#34;); nvs_handle_t my_handle; ret = nvs_open_from_partition(\u0026#34;nvs\u0026#34;, \u0026#34;storage\u0026#34;, NVS_READWRITE, \u0026amp;my_handle); if (ret != ESP_OK) { ESP_LOGE(TAG, \u0026#34;Error (%s) opening NVS handle!\\n\u0026#34;, esp_err_to_name(ret)); return; } ESP_LOGI(TAG, \u0026#34;The NVS handle successfully opened\u0026#34;); Then we can start reading individual values:\nchar ssid[32]; char password[64]; esp_err_t get_wifi_credentials(void){ esp_err_t err; ESP_LOGI(TAG, \u0026#34;Opening Non-Volatile Storage (NVS) handle\u0026#34;); nvs_handle_t nvs_mem_handle; err = nvs_open_from_partition(\u0026#34;nvs\u0026#34;, \u0026#34;storage\u0026#34;, NVS_READWRITE, \u0026amp;nvs_mem_handle); if (err != ESP_OK) { ESP_LOGE(TAG, \u0026#34;Error (%s) opening NVS handle!\\n\u0026#34;, esp_err_to_name(err)); return err; } ESP_LOGI(TAG, \u0026#34;The NVS handle successfully opened\u0026#34;); size_t ssid_len = sizeof(ssid); size_t pass_len = sizeof(password); err = nvs_get_str(nvs_mem_handle, \u0026#34;ssid\u0026#34;, ssid, \u0026amp;ssid_len); ESP_ERROR_CHECK(err); err = nvs_get_str(nvs_mem_handle, \u0026#34;password\u0026#34;, password, \u0026amp;pass_len); ESP_ERROR_CHECK(err); nvs_close(nvs_mem_handle); return ESP_OK; } Now we still need to pass SSID and password to the configuration structure:\nwifi_config_t wifi_config = { .sta = { .ssid = \u0026#34;\u0026#34;, .password = \u0026#34;\u0026#34;, .threshold.authmode = WIFI_AUTH_WPA2_WPA3_PSK, .sae_pwe_h2e = WPA3_SAE_PWE_BOTH, .sae_h2e_identifier = \u0026#34;\u0026#34;, }, }; strncpy((char*)wifi_config.sta.ssid, ssid, sizeof(wifi_config.sta.ssid)); strncpy((char*)wifi_config.sta.password, password, sizeof(wifi_config.sta.password)); Don\u0026rsquo;t forget to call our newly created function get_wifi_credentials before wifi_init_sta in the main function app_main:\nESP_ERROR_CHECK(get_wifi_credentials()); Build configuration Since we are using a custom partition table and NVS, we need to change a few things in CMake as well, specifically in the main/CMakeLists.txt file we call a function that adds the NVS table to its place (nvs_create_partition_image):\nidf_component_register( SRCS main.c # list the source files of this component INCLUDE_DIRS # optional, add here public include directories PRIV_INCLUDE_DIRS # optional, add here private include directories REQUIRES esp_wifi esp_netif esp_event nvs_flash # optional, list the public requirements (component names) PRIV_REQUIRES # optional, list the private requirements ) nvs_create_partition_image(nvs ../nvs.csv FLASH_IN_PROJECT) Partition table configuration Now we still need to tell ESP-IDF to use our partition table. We do this by opening the sdkconfig.defaults file in the project root directory (if it\u0026rsquo;s not there, we create it) and add the following values to it:\nCONFIG_PARTITION_TABLE_CUSTOM=y CONFIG_PARTITION_TABLE_CUSTOM_FILENAME=\u0026#34;partitions.csv\u0026#34; CONFIG_PARTITION_TABLE_FILENAME=\u0026#34;partitions.csv\u0026#34; Now we can change SSID and password without having to intervene directly in the application source code.\nComplete code # #include \u0026lt;stdio.h\u0026gt; #include \u0026#34;bsp/esp-bsp.h\u0026#34; #include \u0026#34;led_indicator_blink_default.h\u0026#34; #include \u0026#34;freertos/FreeRTOS.h\u0026#34; #include \u0026#34;freertos/task.h\u0026#34; #include \u0026#34;freertos/event_groups.h\u0026#34; #include \u0026#34;esp_system.h\u0026#34; #include \u0026#34;esp_wifi.h\u0026#34; #include \u0026#34;esp_event.h\u0026#34; #include \u0026#34;esp_log.h\u0026#34; #include \u0026#34;nvs.h\u0026#34; #include \u0026#34;nvs_flash.h\u0026#34; #include \u0026#34;lwip/err.h\u0026#34; #include \u0026#34;lwip/sys.h\u0026#34; #define WIFI_CONNECTED_BIT BIT0 #define WIFI_FAIL_BIT BIT1 char ssid[32]; char password[64]; static led_indicator_handle_t leds[BSP_LED_NUM]; static EventGroupHandle_t s_wifi_event_group; static int s_retry_num = 0; static const char *TAG = \u0026#34;workshop\u0026#34;; static void event_handler(void* arg, esp_event_base_t event_base, int32_t event_id, void* event_data) { if (event_base == WIFI_EVENT \u0026amp;\u0026amp; event_id == WIFI_EVENT_STA_START) { esp_wifi_connect(); } else if (event_base == WIFI_EVENT \u0026amp;\u0026amp; event_id == WIFI_EVENT_STA_DISCONNECTED) { if (s_retry_num \u0026lt; 30) { esp_wifi_connect(); s_retry_num++; ESP_LOGW(TAG, \u0026#34;Trying to connect to WiFi\u0026#34;); led_indicator_set_rgb(leds[0], SET_IRGB(0, 0x0, 0x0, 0x20)); } else { xEventGroupSetBits(s_wifi_event_group, WIFI_FAIL_BIT); } ESP_LOGE(TAG, \u0026#34;Failed to connect to WiFi\u0026#34;); led_indicator_set_rgb(leds[0], SET_IRGB(0, 0x20, 0x0, 0x0)); } else if (event_base == IP_EVENT \u0026amp;\u0026amp; event_id == IP_EVENT_STA_GOT_IP) { ip_event_got_ip_t* event = (ip_event_got_ip_t*) event_data; ESP_LOGI(TAG, \u0026#34;got ip:\u0026#34; IPSTR, IP2STR(\u0026amp;event-\u0026gt;ip_info.ip)); led_indicator_set_rgb(leds[0], SET_IRGB(0, 0x0, 0x20, 0x0)); s_retry_num = 0; xEventGroupSetBits(s_wifi_event_group, WIFI_CONNECTED_BIT); } } void wifi_init_sta(void) { s_wifi_event_group = xEventGroupCreate(); ESP_ERROR_CHECK(esp_netif_init()); ESP_ERROR_CHECK(esp_event_loop_create_default()); esp_netif_create_default_wifi_sta(); wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT(); ESP_ERROR_CHECK(esp_wifi_init(\u0026amp;cfg)); esp_event_handler_instance_t instance_any_id; esp_event_handler_instance_t instance_got_ip; ESP_ERROR_CHECK(esp_event_handler_instance_register(WIFI_EVENT, ESP_EVENT_ANY_ID, \u0026amp;event_handler, NULL, \u0026amp;instance_any_id)); ESP_ERROR_CHECK(esp_event_handler_instance_register(IP_EVENT, IP_EVENT_STA_GOT_IP, \u0026amp;event_handler, NULL, \u0026amp;instance_got_ip)); wifi_config_t wifi_config = { .sta = { .ssid = \u0026#34;\u0026#34;, .password = \u0026#34;\u0026#34;, .threshold.authmode = WIFI_AUTH_WPA2_WPA3_PSK, .sae_pwe_h2e = WPA3_SAE_PWE_BOTH, .sae_h2e_identifier = \u0026#34;\u0026#34;, }, }; strncpy((char*)wifi_config.sta.ssid, ssid, sizeof(wifi_config.sta.ssid)); strncpy((char*)wifi_config.sta.password, password, sizeof(wifi_config.sta.password)); ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_STA) ); ESP_ERROR_CHECK(esp_wifi_set_config(WIFI_IF_STA, \u0026amp;wifi_config) ); ESP_ERROR_CHECK(esp_wifi_start() ); EventBits_t bits = xEventGroupWaitBits(s_wifi_event_group, WIFI_CONNECTED_BIT | WIFI_FAIL_BIT, pdFALSE, pdFALSE, portMAX_DELAY); if (bits \u0026amp; WIFI_CONNECTED_BIT) { ESP_LOGI(TAG, \u0026#34;Connected!\u0026#34;); } else if (bits \u0026amp; WIFI_FAIL_BIT) { ESP_LOGE(TAG, \u0026#34;Failed to connect!\u0026#34;); } } esp_err_t get_wifi_credentials(void){ esp_err_t err; ESP_LOGI(TAG, \u0026#34;Opening Non-Volatile Storage (NVS) handle\u0026#34;); nvs_handle_t nvs_mem_handle; err = nvs_open_from_partition(\u0026#34;nvs\u0026#34;, \u0026#34;storage\u0026#34;, NVS_READWRITE, \u0026amp;nvs_mem_handle); if (err != ESP_OK) { ESP_LOGE(TAG, \u0026#34;Error (%s) opening NVS handle!\\n\u0026#34;, esp_err_to_name(err)); return err; } ESP_LOGI(TAG, \u0026#34;The NVS handle successfully opened\u0026#34;); size_t ssid_len = sizeof(ssid); size_t pass_len = sizeof(password); err = nvs_get_str(nvs_mem_handle, \u0026#34;ssid\u0026#34;, ssid, \u0026amp;ssid_len); ESP_ERROR_CHECK(err); err = nvs_get_str(nvs_mem_handle, \u0026#34;password\u0026#34;, password, \u0026amp;pass_len); ESP_ERROR_CHECK(err); ESP_LOGI(TAG, \u0026#34;Retrieved ssid: %s, password: %s\u0026#34;, ssid, password); nvs_close(nvs_mem_handle); return ESP_OK; } void app_main(void) { esp_err_t ret = nvs_flash_init(); if (ret == ESP_ERR_NVS_NO_FREE_PAGES || ret == ESP_ERR_NVS_NEW_VERSION_FOUND) { ESP_ERROR_CHECK(nvs_flash_erase()); ret = nvs_flash_init(); } ESP_ERROR_CHECK(ret); ESP_ERROR_CHECK(bsp_led_indicator_create(leds, NULL, BSP_LED_NUM)); led_indicator_set_rgb(leds[0], SET_IRGB(0, 0x0, 0x0, 0x20)); ESP_ERROR_CHECK(get_wifi_credentials()); wifi_init_sta(); } Next step # Does it seem complicated to you? Let\u0026rsquo;s simplify it!\nAssignment 5: Wi-Fi provisioning\n","date":"30 September 2024","externalUrl":null,"permalink":"/workshops/esp-idf-with-esp32-c6/assignment-4/","section":"Workshops","summary":"","title":"Workshop: ESP-IDF and ESP32-C6 - Assignment 4","type":"workshops"},{"content":" Assignment 5: Wi-Fi provisioning # Wi-Fi provisioning is one of the most important aspects of any IoT device. When you bring home a smart socket, for example, you don\u0026rsquo;t have to download code from the manufacturer and manually change SSID and password, but everything is usually handled through some application that provides all this data to the socket. We usually go through Wi-Fi provisioning only once during the initial setup of our device, but it can also come in handy in situations where, for example, a factory reset occurs.\nThere are several methods to ensure Wi-Fi provisioning. Some devices can be switched to so-called provisioning mode by pressing a button, others work through the mentioned application or web page, and some support automatic provisioning using another technology, such as Bluetooth Low Energy (BLE).\nESP32 of course also supports this option. You can encounter it in projects such as our ESP RainMaker.\nPractical demo: How to do Wi-Fi provisioning # In chapter 3, we wrote SSID and password directly into the code, which is the fastest, but also the most complicated variant (with every change we have to compile and upload the entire project).\nStoring data in NVS in chapter 4 shows a somewhat more practical version, where the code reads the data from memory itself, but we still have to write it there manually, which is definitely not ideal.\nNow we will show how to set Wi-Fi data via BLE (Bluetooth Low Energy) using an Android or iOS mobile phone.\nInstalling the mobile application First you need to download the application for BLE provisioning:\nAndroid: ESP BLE Provisioning iOS: ESP BLE Provisioning Creating a new project We will create a new project using the provisioning -\u0026gt; wifi_prov_mgr example. It can be created either using the command below:\nidf.py create-project-from-example \u0026#34;espressif/network_provisioning^1.2.0:wifi_prov\u0026#34; \u0026hellip;or via GUI:\nOpen ESP-IDF Component Registry Search for espressif/network_provisioning Go to the Examples tab Select wifi_prov And choose Create Project from this Example. In the following window, just choose where to save the project. For your existing projects, you can use the espressif/network_provisioning component.\nidf.py add-dependency \u0026#34;espressif/network_provisioning^0.2.0\u0026#34; Build, flash, and monitor We won\u0026rsquo;t change anything in the example, just verify that we have the correct target, erase flash memory (with the Erase Flash command), build the application and flash it.\nIf you added components manually (via CLI), you will need to clean the project first so that everything builds correctly:\nidf.py fullclean\nAfter building and uploading the application, open ESP-IDF Serial Monitor.\nProvisioning In the ESP BLE provisioning app on your mobile phone, follow the steps as shown below:\nThe QR code will be printed by your development board to the serial line (open the serial monitor with the Monitor command in ESP-IDF Explorer).\nAfter the provisioning process is completed, the device will connect to the selected Wi-Fi network.\nNext step # Now that we know how to easily connect to Wi-Fi, let\u0026rsquo;s make it more secure!\nAssignment 6: Protocols\n","date":"30 September 2024","externalUrl":null,"permalink":"/workshops/esp-idf-with-esp32-c6/assignment-5/","section":"Workshops","summary":"","title":"Workshop: ESP-IDF and ESP32-C6 - Assignment 5","type":"workshops"},{"content":" Assignment 6: Protocols # Currently, ESP-IDF supports a bunch of protocols, such as:\nHTTP and HTTPS ICMP CoAP MQTT and MQTT5 PPP (Point-to-Point Protocol) including PPPoS Sockets Modbus SMTP SNTP \u0026hellip;and many more You can explore how to work with protocols directly based on examples in the ESP-IDF examples, esp-protocols, or ESP Registry folders.\nPractical example with protocols # In this example, we will use ESP x509 Certificate Bundle to simplify our work with some protocols that require certificates, such as HTTPS.\nESP x509 Certificate Bundle API provides a collection of certificates for verification on a TLS server, which are automatically generated from Mozilla\u0026rsquo;s NSS root certificates. This bundle contains more than 130 certificates and is constantly updated.\nBy using this bundle, we don\u0026rsquo;t have to manually upload any root certificates for secure HTTPS connection using TLS (ESP-TLS), nor do we have to renew them when they expire.\nVerify that the previous steps work as they should In this assignment, we will continue to modify the project we have been working on so far. It is therefore good to verify that at this point the project can be built, uploaded and that the board successfully connects to Wi-Fi.\nDuring this assignment we will need an Internet connection.\nConfiguration modification Open the configuration menu (Ctrl + Shift + P and search for SDK Configuration Editor) and in the configuration menu go to Component config -\u0026gt; mbedTLS -\u0026gt; Certificate Bundle. There check that:\nEnable trusted root certificate bundle is checked In the Default certificate bundle options menu, the Use the full default certificate bundle option is selected Code for TLS connection We add the necessary #includes\u0026hellip;\n#include \u0026#34;lwip/err.h\u0026#34; #include \u0026#34;lwip/sockets.h\u0026#34; #include \u0026#34;lwip/sys.h\u0026#34; #include \u0026#34;lwip/netdb.h\u0026#34; #include \u0026#34;lwip/dns.h\u0026#34; #include \u0026#34;esp_tls.h\u0026#34; #include \u0026#34;esp_crt_bundle.h\u0026#34; \u0026hellip;and definitions of URL links that we will try to connect to using the certificate:\n#define MAX_URLS 4 static const char *web_urls[MAX_URLS] = { \u0026#34;https://www.github.com\u0026#34;, \u0026#34;https://espressif.com\u0026#34;, \u0026#34;https://youtube.com\u0026#34;, \u0026#34;https://seznam.cz\u0026#34;, }; If you want, you can change the list and put your own pages there.\nCreating a task that will try to connect to URLs from the previous step This task will try to connect to each of the URLs from the list above.\nstatic void event_handler(void* arg, esp_event_base_t event_base, int32_t event_id, void* event_data) { if (event_base == WIFI_EVENT \u0026amp;\u0026amp; event_id == WIFI_EVENT_STA_START) { esp_wifi_connect(); } else if (event_base == WIFI_EVENT \u0026amp;\u0026amp; event_id == WIFI_EVENT_STA_DISCONNECTED) { if (s_retry_num \u0026lt; 100) { esp_wifi_connect(); s_retry_num++; ESP_LOGW(TAG, \u0026#34;Trying to connect to WiFi\u0026#34;); led_indicator_set_rgb(leds[0], SET_IRGB(0, 0x0, 0x0, 0x20)); } else { xEventGroupSetBits(s_wifi_event_group, WIFI_FAIL_BIT); } ESP_LOGE(TAG, \u0026#34;Failed to connect to WiFi\u0026#34;); led_indicator_set_rgb(leds[0], SET_IRGB(0, 0x20, 0x0, 0x0)); } else if (event_base == IP_EVENT \u0026amp;\u0026amp; event_id == IP_EVENT_STA_GOT_IP) { ip_event_got_ip_t* event = (ip_event_got_ip_t*) event_data; ESP_LOGI(TAG, \u0026#34;got ip:\u0026#34; IPSTR, IP2STR(\u0026amp;event-\u0026gt;ip_info.ip)); led_indicator_set_rgb(leds[0], SET_IRGB(0, 0x0, 0x20, 0x0)); s_retry_num = 0; xEventGroupSetBits(s_wifi_event_group, WIFI_CONNECTED_BIT); } } We create the task after calling the wifi_init_sta function:\nxTaskCreate(\u0026amp;https_get_task, \u0026#34;https_get_task\u0026#34;, 8192, NULL, 5, NULL); Complete code # #include \u0026lt;stdio.h\u0026gt; #include \u0026#34;bsp/esp-bsp.h\u0026#34; #include \u0026#34;led_indicator_blink_default.h\u0026#34; #include \u0026#34;freertos/FreeRTOS.h\u0026#34; #include \u0026#34;freertos/task.h\u0026#34; #include \u0026#34;freertos/event_groups.h\u0026#34; #include \u0026#34;esp_system.h\u0026#34; #include \u0026#34;esp_wifi.h\u0026#34; #include \u0026#34;esp_event.h\u0026#34; #include \u0026#34;esp_log.h\u0026#34; #include \u0026#34;nvs.h\u0026#34; #include \u0026#34;nvs_flash.h\u0026#34; #include \u0026#34;lwip/err.h\u0026#34; #include \u0026#34;lwip/sys.h\u0026#34; #include \u0026#34;lwip/err.h\u0026#34; #include \u0026#34;lwip/sockets.h\u0026#34; #include \u0026#34;lwip/sys.h\u0026#34; #include \u0026#34;lwip/netdb.h\u0026#34; #include \u0026#34;lwip/dns.h\u0026#34; #include \u0026#34;esp_tls.h\u0026#34; #include \u0026#34;esp_crt_bundle.h\u0026#34; #define WIFI_CONNECTED_BIT BIT0 #define WIFI_FAIL_BIT BIT1 #define MAX_URLS 4 static const char *web_urls[MAX_URLS] = { \u0026#34;https://www.github.com\u0026#34;, \u0026#34;https://espressif.com\u0026#34;, \u0026#34;https://youtube.com\u0026#34;, \u0026#34;https://acesso.gov.br\u0026#34;, }; char ssid[32]; char password[64]; static led_indicator_handle_t leds[BSP_LED_NUM]; static EventGroupHandle_t s_wifi_event_group; static int s_retry_num = 0; static const char *TAG = \u0026#34;workshop\u0026#34;; static void event_handler(void* arg, esp_event_base_t event_base, int32_t event_id, void* event_data) { if (event_base == WIFI_EVENT \u0026amp;\u0026amp; event_id == WIFI_EVENT_STA_START) { esp_wifi_connect(); } else if (event_base == WIFI_EVENT \u0026amp;\u0026amp; event_id == WIFI_EVENT_STA_DISCONNECTED) { if (s_retry_num \u0026lt; 100) { esp_wifi_connect(); s_retry_num++; ESP_LOGW(TAG, \u0026#34;Trying to connect to WiFi\u0026#34;); led_indicator_set_rgb(leds[0], SET_IRGB(0, 0x0, 0x0, 0x20)); } else { xEventGroupSetBits(s_wifi_event_group, WIFI_FAIL_BIT); } ESP_LOGE(TAG, \u0026#34;Failed to connect to WiFi\u0026#34;); led_indicator_set_rgb(leds[0], SET_IRGB(0, 0x20, 0x0, 0x0)); } else if (event_base == IP_EVENT \u0026amp;\u0026amp; event_id == IP_EVENT_STA_GOT_IP) { ip_event_got_ip_t* event = (ip_event_got_ip_t*) event_data; ESP_LOGI(TAG, \u0026#34;got ip:\u0026#34; IPSTR, IP2STR(\u0026amp;event-\u0026gt;ip_info.ip)); led_indicator_set_rgb(leds[0], SET_IRGB(0, 0x0, 0x20, 0x0)); s_retry_num = 0; xEventGroupSetBits(s_wifi_event_group, WIFI_CONNECTED_BIT); } } void wifi_init_sta(void) { s_wifi_event_group = xEventGroupCreate(); ESP_ERROR_CHECK(esp_netif_init()); ESP_ERROR_CHECK(esp_event_loop_create_default()); esp_netif_create_default_wifi_sta(); wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT(); ESP_ERROR_CHECK(esp_wifi_init(\u0026amp;cfg)); esp_event_handler_instance_t instance_any_id; esp_event_handler_instance_t instance_got_ip; ESP_ERROR_CHECK(esp_event_handler_instance_register(WIFI_EVENT, ESP_EVENT_ANY_ID, \u0026amp;event_handler, NULL, \u0026amp;instance_any_id)); ESP_ERROR_CHECK(esp_event_handler_instance_register(IP_EVENT, IP_EVENT_STA_GOT_IP, \u0026amp;event_handler, NULL, \u0026amp;instance_got_ip)); wifi_config_t wifi_config = { .sta = { .ssid = \u0026#34;\u0026#34;, .password = \u0026#34;\u0026#34;, .threshold.authmode = WIFI_AUTH_WPA2_WPA3_PSK, .sae_pwe_h2e = WPA3_SAE_PWE_BOTH, .sae_h2e_identifier = \u0026#34;\u0026#34;, }, }; strncpy((char*)wifi_config.sta.ssid, ssid, sizeof(wifi_config.sta.ssid)); strncpy((char*)wifi_config.sta.password, password, sizeof(wifi_config.sta.password)); ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_STA) ); ESP_ERROR_CHECK(esp_wifi_set_config(WIFI_IF_STA, \u0026amp;wifi_config) ); ESP_ERROR_CHECK(esp_wifi_start() ); EventBits_t bits = xEventGroupWaitBits(s_wifi_event_group, WIFI_CONNECTED_BIT | WIFI_FAIL_BIT, pdFALSE, pdFALSE, portMAX_DELAY); if (bits \u0026amp; WIFI_CONNECTED_BIT) { ESP_LOGI(TAG, \u0026#34;Connected!\u0026#34;); } else if (bits \u0026amp; WIFI_FAIL_BIT) { ESP_LOGE(TAG, \u0026#34;Failed to connect!\u0026#34;); } } esp_err_t get_wifi_credentials(void){ esp_err_t err; ESP_LOGI(TAG, \u0026#34;Opening Non-Volatile Storage (NVS) handle\u0026#34;); nvs_handle_t nvs_mem_handle; err = nvs_open_from_partition(\u0026#34;nvs\u0026#34;, \u0026#34;storage\u0026#34;, NVS_READWRITE, \u0026amp;nvs_mem_handle); if (err != ESP_OK) { ESP_LOGE(TAG, \u0026#34;Error (%s) opening NVS handle!\\n\u0026#34;, esp_err_to_name(err)); return err; } ESP_LOGI(TAG, \u0026#34;The NVS handle successfully opened\u0026#34;); size_t ssid_len = sizeof(ssid); size_t pass_len = sizeof(password); err = nvs_get_str(nvs_mem_handle, \u0026#34;ssid\u0026#34;, ssid, \u0026amp;ssid_len); ESP_ERROR_CHECK(err); err = nvs_get_str(nvs_mem_handle, \u0026#34;password\u0026#34;, password, \u0026amp;pass_len); ESP_ERROR_CHECK(err); nvs_close(nvs_mem_handle); return ESP_OK; } static void https_get_task(void *pvParameters) { while (1) { int conn_count = 0; ESP_LOGI(TAG, \u0026#34;Connecting to %d URLs\u0026#34;, MAX_URLS); for (int i = 0; i \u0026lt; MAX_URLS; i++) { esp_tls_cfg_t cfg = { .crt_bundle_attach = esp_crt_bundle_attach, }; esp_tls_t *tls = esp_tls_init(); if (!tls) { ESP_LOGE(TAG, \u0026#34;Failed to allocate esp_tls handle!\u0026#34;); goto end; } if (esp_tls_conn_http_new_sync(web_urls[i], \u0026amp;cfg, tls) == 1) { ESP_LOGI(TAG, \u0026#34;Connection established to %s\u0026#34;, web_urls[i]); conn_count++; } else { ESP_LOGE(TAG, \u0026#34;Could not connect to %s\u0026#34;, web_urls[i]); } esp_tls_conn_destroy(tls); end: vTaskDelay(1000 / portTICK_PERIOD_MS); } ESP_LOGI(TAG, \u0026#34;Completed %d connections\u0026#34;, conn_count); ESP_LOGI(TAG, \u0026#34;Starting over again...\u0026#34;); } } void app_main(void) { esp_err_t ret = nvs_flash_init(); if (ret == ESP_ERR_NVS_NO_FREE_PAGES || ret == ESP_ERR_NVS_NEW_VERSION_FOUND) { ESP_ERROR_CHECK(nvs_flash_erase()); ret = nvs_flash_init(); } ESP_ERROR_CHECK(ret); ESP_ERROR_CHECK(bsp_led_indicator_create(leds, NULL, BSP_LED_NUM)); led_indicator_set_rgb(leds[0], SET_IRGB(0, 0x0, 0x0, 0x20)); ESP_ERROR_CHECK(get_wifi_credentials()); wifi_init_sta(); xTaskCreate(\u0026amp;https_get_task, \u0026#34;https_get_task\u0026#34;, 8192, NULL, 5, NULL); } Next step # Have you exhausted all your energy? Let\u0026rsquo;s save some!\nAssignment 7: Low Power Core\n","date":"30 September 2024","externalUrl":null,"permalink":"/workshops/esp-idf-with-esp32-c6/assignment-6/","section":"Workshops","summary":"","title":"Workshop: ESP-IDF and ESP32-C6 - Assignment 6","type":"workshops"},{"content":" Assignment 7: Low Power core # ESP32-C6 has two cores: a high-power (HP) core for standard use and a low-power (LP) core to minimize consumption.\nThe second core is often called Ultra-Low-Power (ULP) core mainly in English and is designed primarily to handle simple tasks while the main (HP) core is in sleep mode, which significantly reduces electrical energy consumption. This function will certainly be appreciated by those who build battery-powered projects, where it\u0026rsquo;s not so much about performance, but rather about efficiency.\nThe ULP core can function independently of the HP core, where it can, for example, collect data from sensors and perform their basic processing, or control GPIO, all with absolutely minimal consumption and a 20 MHz clock, which is comparable to, for example, an Arduino UNO. If you are interested in a complete overview of what this core can do, visit the documentation on ULP LP-Core Coprocessor Programming.\n(U)LP core # 32-bit RISC-V core @20MHz 16KB LP SRAM RISC-V IMAC instruction set Act as a co-processor Access to peripherals, including GPIO UART I2C You can watch the DevCon23 talk Low-Power Features of ESP32-C6: Target Wake Time + LP Core, which covers some aspects of the LP core and TWT.\nULP pinout # The ULP core uses a specific set of pins. If you need to know the details, use the pin layout to know which pins will work with the LP core.\nPractical work with LP core # In this demo, we will write code that blinks an LED. Once the \u0026ldquo;big\u0026rdquo; HP core will take care of the control, the second time the ULP core will do the same job. We will try to compare consumption at the same time.\nFor this assignment, we will create a new empty project. For more detailed instructions, visit chapter 1 (creating a project from the hello world example). Create the main/ulp folder and a main.c file inside #include \u0026lt;stdint.h\u0026gt; #include \u0026lt;stdbool.h\u0026gt; #include \u0026#34;ulp_lp_core.h\u0026#34; #include \u0026#34;ulp_lp_core_utils.h\u0026#34; #include \u0026#34;ulp_lp_core_gpio.h\u0026#34; #include \u0026#34;ulp_lp_core_interrupts.h\u0026#34; #define WAKEUP_PIN LP_IO_NUM_0 #define RED_PIN LP_IO_NUM_4 #define GREEN_PIN LP_IO_NUM_5 static uint32_t wakeup_count; uint32_t start_toggle; void LP_CORE_ISR_ATTR ulp_lp_core_lp_io_intr_handler(void) { ulp_lp_core_gpio_clear_intr_status(); wakeup_count++; } int main (void) { /* Register interrupt for the wakeup pin */ ulp_lp_core_intr_enable(); ulp_lp_core_gpio_intr_enable(WAKEUP_PIN, LP_IO_INTR_POSEDGE); int level = 0; while (1) { /* Toggle the Red LED GPIO */ ulp_lp_core_gpio_set_level(GREEN_PIN, 0); ulp_lp_core_gpio_set_level(RED_PIN, level); level = level ? 0 : 1; ulp_lp_core_delay_us(1000000); /* Wakeup the main processor after 4 toggles of the button */ if (wakeup_count \u0026gt;= 4) { ulp_lp_core_gpio_set_level(RED_PIN, 0); ulp_lp_core_wakeup_main_processor(); wakeup_count = 0; } } /* ulp_lp_core_halt() is called automatically when main exits */ return 0; } In this code, we enable interrupts on the LP core using ulp_lp_core_intr_enable, while setting GPIO0 as an input pin, activated by a rising edge (signal transition from LOW to HIGH state). We use the ulp_lp_core_gpio_intr_enable function to connect the pin and interrupt. The Wake up counter will be handled by the interrupt handler ulp_lp_core_lp_io_intr_handler.\nNow a loop for blinking and wake up counter starts. The value of our GPIO is set by the ulp_lp_core_gpio_set_level function. If the number of button presses is 4 or more, the HP core is started by the ulp_lp_core_wakeup_main_processor function.\nChange the main/CMakeLists.txt file In CMake we need to set the ULP application name, source files and more\u0026hellip;\n# Set usual component variables set(app_sources \u0026#34;hello_world_main.c\u0026#34;) idf_component_register(SRCS ${app_sources} REQUIRES ulp WHOLE_ARCHIVE) # # ULP support additions to component CMakeLists.txt. # # 1. The ULP app name must be unique (if multiple components use ULP). set(ulp_app_name ulp_${COMPONENT_NAME}) # # 2. Specify all C and Assembly source files. # Files should be placed into a separate directory (in this case, ulp/), # which should not be added to COMPONENT_SRCS. set(ulp_sources \u0026#34;ulp/main.c\u0026#34;) # # 3. List all the component source files which include automatically # generated ULP export file, ${ulp_app_name}.h: set(ulp_exp_dep_srcs ${app_sources}) # # 4. Call function to build ULP binary and embed in project using the argument # values above. ulp_embed_binary(${ulp_app_name} \u0026#34;${ulp_sources}\u0026#34; \u0026#34;${ulp_exp_dep_srcs}\u0026#34;) Change the main/hello_world_main.c file for the HP core #include \u0026lt;stdio.h\u0026gt; #include \u0026#34;esp_sleep.h\u0026#34; #include \u0026#34;driver/gpio.h\u0026#34; #include \u0026#34;driver/rtc_io.h\u0026#34; #include \u0026#34;ulp_lp_core.h\u0026#34; #include \u0026#34;ulp_main.h\u0026#34; #include \u0026#34;freertos/FreeRTOS.h\u0026#34; #include \u0026#34;freertos/task.h\u0026#34; extern const uint8_t ulp_main_bin_start[] asm(\u0026#34;_binary_ulp_main_bin_start\u0026#34;); extern const uint8_t ulp_main_bin_end[] asm(\u0026#34;_binary_ulp_main_bin_end\u0026#34;); static void init_ulp_program(void); #define WAKEUP_PIN GPIO_NUM_0 #define RED_PIN GPIO_NUM_4 #define GREEN_PIN GPIO_NUM_5 void app_main(void) { /* If user is using USB-serial-jtag then idf monitor needs some time to * re-connect to the USB port. We wait 1 sec here to allow for it to make the reconnection * before we print anything. Otherwise the chip will go back to sleep again before the user * has time to monitor any output. */ vTaskDelay(pdMS_TO_TICKS(1000)); /* ULP caused wakeup */ esp_sleep_wakeup_cause_t cause = esp_sleep_get_wakeup_cause(); if (cause == ESP_SLEEP_WAKEUP_ULP) { printf(\u0026#34;ULP woke up the main CPU! \\n\u0026#34;); ulp_lp_core_stop(); } printf(\u0026#34;In active mode\\n\u0026#34;); printf(\u0026#34;Long press the wake button to put the chip to sleep and run the ULP\\n\u0026#34;); /* Initialize selected GPIOs */ rtc_gpio_init(WAKEUP_PIN); rtc_gpio_set_direction(WAKEUP_PIN, RTC_GPIO_MODE_INPUT_ONLY); rtc_gpio_pulldown_dis(WAKEUP_PIN); rtc_gpio_pullup_dis(WAKEUP_PIN); rtc_gpio_init(RED_PIN); rtc_gpio_set_direction(RED_PIN, RTC_GPIO_MODE_OUTPUT_ONLY); rtc_gpio_pulldown_dis(RED_PIN); rtc_gpio_pullup_dis(RED_PIN); rtc_gpio_init(GREEN_PIN); rtc_gpio_set_direction(GREEN_PIN, RTC_GPIO_MODE_OUTPUT_ONLY); rtc_gpio_pulldown_dis(GREEN_PIN); rtc_gpio_pullup_dis(GREEN_PIN); int gpio_level = 0; int previous_gpio_level = 0; int cnt = 0; while (1) { /* Toggle the Green LED GPIO */ rtc_gpio_set_level(RED_PIN, 0); rtc_gpio_set_level(GREEN_PIN, 1); vTaskDelay(pdMS_TO_TICKS(1000)); rtc_gpio_set_level(GREEN_PIN, 0); vTaskDelay(pdMS_TO_TICKS(1000)); /* Read the wakeup pin continuously */ gpio_level = rtc_gpio_get_level(WAKEUP_PIN); if (gpio_level != previous_gpio_level) { previous_gpio_level = gpio_level; cnt++; if (cnt \u0026gt; 1) { rtc_gpio_set_level(GREEN_PIN, 0); cnt = 0; break; /* break and run the LP core code */ } } } /* Load and run the ULP program */ init_ulp_program(); /* Go back to sleep, only the ULP will run */ printf(\u0026#34;Entering Deep-sleep mode\\n\\n\u0026#34;); printf(\u0026#34;Press the wake button at least 3 or 4 times to wake up the main CPU again\\n\u0026#34;); vTaskDelay(10); ESP_ERROR_CHECK( esp_sleep_enable_ulp_wakeup()); esp_deep_sleep_start(); } static void init_ulp_program(void) { esp_err_t err = ulp_lp_core_load_binary(ulp_main_bin_start, (ulp_main_bin_end - ulp_main_bin_start)); ESP_ERROR_CHECK(err); /* Start the program */ ulp_lp_core_cfg_t cfg = { .wakeup_source = ULP_LP_CORE_WAKEUP_SOURCE_HP_CPU, }; err = ulp_lp_core_run(\u0026amp;cfg); ESP_ERROR_CHECK(err); } Enable the LP core in the configuration To enable the LP core and be able to compile for it, we need to set the following configuration parameters in the project configuration. For example, by creating sdkconfig.defaults with the following content:\n# Enable ULP CONFIG_ULP_COPROC_ENABLED=y CONFIG_ULP_COPROC_TYPE_LP_CORE=y CONFIG_ULP_COPROC_RESERVE_MEM=4096 # Set log level to Warning to produce clean output CONFIG_BOOTLOADER_LOG_LEVEL_WARN=y CONFIG_BOOTLOADER_LOG_LEVEL=2 CONFIG_LOG_DEFAULT_LEVEL_WARN=y CONFIG_LOG_DEFAULT_LEVEL=2 Hardware setup For this example, you will also need 2 LEDs and one button connected to the following pins:\nRed LED -\u0026gt; GPIO4 Green LED -\u0026gt; GPIO5 Button (pull-down, active high) -\u0026gt; GPIO0. In other words, we connect one \u0026ldquo;side\u0026rdquo; of the button to 3.3V and the other to GPIO0. Additionally, we connect a resistor between GPIO0 and GND. Button pinoutButton pinout\nBuild, flash, and monitor output from the board Check that you are using the USB port labeled UART for uploading and subsequent monitoring of output. You won\u0026rsquo;t break anything by erasing the flash memory (command Erase Flash) before we upload this example.\nWhat should happen\u0026hellip; # After flashing, the green LED should start blinking every second with the following output:\nIn active mode Long press the wake button to put the chip to sleep and run the ULP If we press and hold the button for a few seconds, the LP core should be activated and the HP core should switch to Deep-sleep mode. The red LED starts blinking at a frequency of one second with the following output:\nEntering Deep-sleep mode Press the wake button at least 3 or 4 times to wake up the main CPU again To wake up from Deep-sleep mode, press the push button four times:\nULP woke up the main CPU! In active mode Long press the wake button to put the chip to sleep and run the ULP For power consumption measurement, we use the exposed J5 connector and a suitable tool, such as JouleScope PPK2.\nLED blinking with HP core\nUsing the \u0026ldquo;big\u0026rdquo; HP core, the average consumption over 10 seconds is approximately 22.32mA.\nLED blinking with LP core\nBut if we transfer the application to the LP core, the average power consumption in a 10 seconds window lowers by the order of magnitude: 2.97mA.\nWhen we switch cores, we achieve savings of (up to) 86.7% for the same task. However, the example is only indicative and the actual values will of course differ.\nMore examples with LP core (in English):\nLP Core simple example with GPIO Polling LP Core Pulse Counting Example LP-Core example with interrupt triggered from HP-Core LP I2C Example LP UART Examples Conclusion # Thank you very much for participating in our workshop and we hope it brought you something useful!\nDuring the workshop, we went through several different topics:\nAssignment 1: We successfully installed ESP-IDF and learned the basics of its use. Assignment 2: We learned how to create a new project, what components are and how to work with them. Assignment 3: We connected to Wi-Fi, which is probably the most important step in the entire IoT world. Assignment 4: We tried NVS (Non-Volatile Storage) and working with persistent data. We also talked about what a partition table is and how to modify it. Assignment 5: We tried Wi-Fi provisioning and learned how to take Wi-Fi configuration on our devices to the next level. Assignment 6: We dove into some of the protocols that ESP32-C6 supports, including TLS certificates for secure communication. Assignment 7: We tried the LP core and learned how to control consumption. Even though we went through several quite diverse topics, we barely scratched the surface. Both ESP32 and ESP-IDF offer much more. However, we all hope that with this workshop we have given you a solid foundation on which you will be able to continue working and developing your projects on your own.\nThank you once again for participating and we look forward to your projects!\n","date":"30 September 2024","externalUrl":null,"permalink":"/workshops/esp-idf-with-esp32-c6/assignment-7/","section":"Workshops","summary":"","title":"Workshop: ESP-IDF and ESP32-C6 - Assignment 7","type":"workshops"},{"content":"","date":"30 September 2024","externalUrl":null,"permalink":"/cs/series/ws001cz/","section":"Series","summary":"","title":"WS001CZ","type":"series"},{"content":"","date":"30 September 2024","externalUrl":null,"permalink":"/series/ws001en/","section":"Series","summary":"","title":"WS001EN","type":"series"},{"content":"","date":"27 September 2024","externalUrl":null,"permalink":"/tags/bsp/","section":"Tags","summary":"","title":"BSP","type":"tags"},{"content":" Introduction # The BSP (Board Support Package) from Espressif is ready to use package for selected boards (usually for Espressif\u0026rsquo;s and M5Stack boards). This package contains main initialization functions for features, which the board contains. For example display and touch initialization, file system initialization, audio if available, LEDs and buttons. This is the easy way, how to start developing with your board. Except initialization functions, there are examples for selected board too.\nMore about using common BSP, you can read here\nMainly, the BSP was only for boards with display or audio. Now, you can use it for any DevKit!\nGeneric and DevKit BSP # Classic DevKits usually contains only LEDs and buttons. There isn\u0026rsquo;t any BSP for specific DevKit, there are special BSPSs esp_bsp_generic and esp_bsp_devkit. These BPSs can be set by menuconfig for any Espressif\u0026rsquo;s DevKit. Differences between esp_bsp_generic and esp_bsp_devkit are in table below.\nesp_bsp_generic esp_bsp_devkit :heavy_check_mark: Up to 5 buttons :heavy_check_mark: Up to 5 buttons :heavy_check_mark: Up to 5 GPIO LEDs :heavy_check_mark: Up to 5 GPIO LEDs :heavy_check_mark: One RGB GPIO LED :heavy_check_mark: One RGB GPIO LED :heavy_check_mark: Unlimited addressable RGB LEDs :heavy_check_mark: Unlimited addressable RGB LEDs :heavy_check_mark: uSD File System :heavy_check_mark: uSD File System :heavy_check_mark: SPIFFS File System :heavy_check_mark: SPIFFS File System :heavy_check_mark: LVGL ready :x: LVGL ready :heavy_check_mark: SPI LCD Display :x: SPI LCD Display :heavy_check_mark: I2C LCD Touch :x: I2C LCD Touch DevKit BSP # Basic BSP for DevKits is esp_bsp_devkit and there can be set only LEDs, buttons and file system.\nSettings in menuconfig:\nButtons Count (maximum 5) Each button can be type ADC or GPIO LEDs Type (GPIO, RGB GPIO, Addressable RGB) SPIFFS - Virtual File System uSD card - Virtual File System This BSP can emulate any Espressif\u0026rsquo;s DevKit.\nGeneric BSP # Generic BSP esp_bsp_generic can set all same as esp_bsp_devkit plus selected LCD and touch.\nSettings in menuconfig:\nButtons Count (maximum 5) Each button can be type ADC or GPIO LEDs Type (GPIO, RGB GPIO, Addressable RGB) Display Connection (only SPI is supported) Driver (ST7789, ILI9341, GC9A01) Display Touch Connection (only I2C is supported) Driver (TT21100, GT1151, GT911, CST816S, FT5X06) SPIFFS - Virtual File System uSD card - Virtual File System This BSP can emulate simple development boards with SPI LCD display.\nExample and preconfigured settings # Mentioned BSPs have one very simple example with one button and one LED, which is included in component or you can find it in GitHub. Example shows breathing LED and you can change breathing/blinking effect by button click.\nThis example contains preconfigured settings for these DevKits:\nESP32-DevKitC ESP32-S2-DevKitM-1 ESP32-S3-DevKitC-1 ESP8684-DevKitM-1 (ESP32-C2) Conclusion # ESP-BSP is ready to kickstart your projects. It is maintained by Espressif and designed to deliver optimal performance for your needs. If your board is not listed, you can easily create your own BSP or use the Generic/DevKit BSP for simpler boards. Start developing with BSP today!\n","date":"27 September 2024","externalUrl":null,"permalink":"/blog/using-esp-bsp-with-devkits/","section":"Blog","summary":"","title":"Using ESP-BSP with DevKits","type":"blog"},{"content":"","date":"27 September 2024","externalUrl":null,"permalink":"/authors/vilem-zavodny/","section":"Developer Portal Authors","summary":"","title":"Vilém Závodný","type":"authors"},{"content":"","date":"23 September 2024","externalUrl":null,"permalink":"/tags/flash-encryption/","section":"Tags","summary":"","title":"Flash Encryption","type":"tags"},{"content":"","date":"23 September 2024","externalUrl":null,"permalink":"/tags/nvs-encryption/","section":"Tags","summary":"","title":"NVS Encryption","type":"tags"},{"content":"","date":"23 September 2024","externalUrl":null,"permalink":"/tags/secure-boot/","section":"Tags","summary":"","title":"Secure Boot","type":"tags"},{"content":" Introduction # This tutorial is a step-by-step guide on how to set the \u0026ldquo;Flash Encryption plus the Secure Boot V2 and NVS Encryption\u0026rdquo; functions on the ESP32-S3 using the Flash Download Tool.\nFlash Encryption Overview # Flash Encryption is a crucial security feature for ESP32 series products, designed to encrypt the firmware stored on the external Flash chip. This encryption protects the integrity and confidentiality of the firmware, safeguarding your application against unauthorized access, tampering, or reverse-engineering. Flash Encryption is especially important in scenarios where secure data transmission and firmware protection are essential.\nFor more detailed instructions and configuration steps, please refer to the official Flash Encryption User Guide\nSupported SoCs # Here is the list of SoCs that supports the Flash Encryption and the supported key types.\nChip Supported Key Types ESP32 XTS_AES_128 ESP32-S2 XTS_AES_128 \u0026amp; XTS_AES_256 ESP32-S3 XTS_AES_128 \u0026amp; XTS_AES_256 ESP32-C2 SHA256 \u0026amp; XTS_AES_128 ESP32-C3 XTS_AES_128 ESP32-C6 XTS_AES_128 ESP32-H2 XTS_AES_128 Each SoC in the ESP32 family uses a hardware-accelerated 256-bit AES-XTS encryption key to protect the data stored in external flash. These keys are securely stored in the One-Time Programmable (OTP) memory of the chip and are inaccessible from user applications.\nNote: This guide will focus on the ESP32-S3 and its Flash Encryption features, providing step-by-step instructions tailored for this SoC.\nSecure Boot V2 Overview # Secure Boot V2 is a security feature that ensures a device only runs authorized, signed code. It protects against unauthorized code execution by verifying the digital signature of each piece of software during the boot process. This prevents the execution of malicious or tampered firmware and helps maintain the integrity of the device.\nFor more detailed instructions and configuration steps, please refer to the official Secure Boot V2 User Guide.\nSupported SoCs # Here is the list of SoCs that supports the Secure Boot V2 and the supported version.\nProduct Secure Boot Version ESP32 ECO V3 and above versions Secure Boot V1 \u0026amp; Secure Boot V2 （ RSA-PSS ） ESP32-S2 All versions Secure Boot V2 （ RSA-PSS ） ESP32-S3 All versions Secure Boot V2 （ RSA-PSS ） ESP32-C2 All versions Secure Boot V2 （ ECDSA ） ESP32-C3 ECO V3 and above versions Secure Boot V2 （ RSA-PSS） ESP32-C6 All versions Secure Boot V2 （RSA-PSS or ECDSA） ESP32-H2 All versions Secure Boot V2 （RSA-PSS or ECDSA） NVS Encryption Overview # NVS Encryption provides secure storage for sensitive data in the Non-Volatile Storage (NVS) system of ESP32 devices. It supports two primary encryption schemes: the HMAC Peripheral-Based Scheme and the Flash Encryption-Based Scheme. These schemes ensure that sensitive information, such as device credentials or user data, is encrypted before being written to flash memory.\nFor more detailed information, refer to the NVS Encryption User Guide.\nIn this guide, we will focus on the NVS Encryption that is based on the Flash Encryption scheme, which leverages the same mechanism used for securing firmware in the external flash.\nStep-by-step Guide # This guide will walk you through enabling Flash Encryption and Secure Boot V2 on the ESP32-S3, enhancing the security of your application.\nWarning: Be careful when following this guide. Once you \u0026ldquo;burn\u0026rdquo; the eFuse, this operation cannot be reverted. eFuses are one-time programmable, and any changes made to them are permanent.\n1 - Create a Partition Table for Your Project # The Flash memory on a single ESP chip can store multiple applications and various types of data, including calibration data, filesystems, and parameter storage. To organize this effectively, it\u0026rsquo;s necessary to create a partition table that defines how the Flash space will be allocated for your project. Proper partitioning ensures that your application has the necessary space for both code and data storage.\nFor detailed partition table instructions, please refer to the Partition Tables User Guide.\nIn this guide, we\u0026rsquo;ll use the following partition table setup:\n# Name, Type, SubType, Offset, Size, Flags # Note: if you have increased the bootloader size, make sure to update the offsets to avoid overlap nvs, data, nvs, 0x10000 , 0x4000 , otadata, data, ota, 0x14000 , 0x2000 , phy_init, data, phy, 0x16000 , 0x1000 , encrypted factory, app, factory, 0x20000 , 1M , ota_0, app, ota_0, 0x120000 , 1M , ota_1, app, ota_1, 0x220000 , 1M , nvs_key, data, nvs_keys, 0x320000 , 0x1000 , encrypted # Custom NVS data partition custom_nvs, data, nvs, 0x321000 , 0x6000 , This partition table setting includes two NVS partitions, the default nvs and the custom_nvs partitions.\nThe default nvs partition is used to store per-device PHY calibration data (different to initialization data) and store Wi-Fi data if the esp_wifi_set_storage(WIFI_STORAGE_FLASH) initialization function is used. As well as write data through the nvs_set API on the software. This nvs partition does not need to download the corresponding nvs.bin when the firmware is downloaded. The default nvs partition will be encrypted while writing data to the nvs partition via the nvs_set API (Note: The nvs_get (read) API does not support NVS encryption).\nThe custom_nvs partition can used to store multiple files which by the custom_nvs.csv file managed . The types of files that can be managed can refer to the CSV File Format instructions. And the custom_nvs.bin needs to be encrypted with nvs_key and downloaded the encrypt_custom_nvs.bin to the custom_nvs partition. Use a custom_nvs.csv file to Manage multiple files as follows:\nkey,type,encoding,value server_cert,namespace,, server_cert,file,binary,E:\\esp\\test\\customized\\server_cert\\server_cert.crt server_key,namespace,, server_key,file,binary,E:\\esp\\test\\customized\\server_key\\server.key server_ca,namespace,, server_ca,file,binary,E:\\esp\\test\\customized\\server_ca\\server_ca.crt You can also refer to esp-idf/examples/storage/nvsgen example. This example use a nvs_data.csv file to manage some data to write in nvs partition.\nWith Flash Encryption enabled, the following types of data are encrypted by default:\nSecond Stage Bootloader (Firmware Bootloader) Partition Table NVS Key Partition Otadata All app type partitions The NVS key partition (nvs_key partition) is used to store the nvs_key, and the nvs_key is used to encrypt the nvs type partitions. In this case，default nvs and the custom_nvs partitions.\nOther types of data can be encrypted conditionally:\nAny partition marked with the encrypted flag in the partition table. For details, see Encrypted Partition Flag. If Secure Boot is enabled，the public key digest will be encrypted. Flash Download Tool\nIf you are using the ESP32 series chip and want to enable Flash Encryption, Secure Boot V2, and NVS Encryption for mass production, we recommend using the Flash Download Tool to automate the process.\nUsing the Flash Download Tool for enabling these security features offers several advantages:\nOnce the firmware download is completed, the Flash Encryption, Secure Boot, and NVS Encryption processes are automatically finalized. Upon the first power-up, the device will directly run the encrypted firmware. Risks related to power failure or instability during the encryption and security processes are minimized. The operational steps for using the Flash Download Tool to enable Flash Encryption, Secure Boot V2, and NVS Encryption are as follows:\nObtain the Necessary Keys:\nBefore starting, you need to generate or obtain the encryption keys for Flash Encryption, Secure Boot, and NVS Encryption. Enable Security Features in the Software:\nConfigure the Flash Encryption, Secure Boot V2, and NVS Encryption options in your project and ensure your firmware is signed appropriately. Encrypt and Flash the Firmware:\nWhen downloading the firmware, make sure to manually encrypt the custom_nvs.bin if needed. This file must be encrypted separately if it contains sensitive data. By following these steps, you can securely provision and encrypt your ESP32 devices in a mass production environment using the Flash Download Tool.\n2 - Obtain the different keys # How to Obtain different types of Flash Encryption Keys?\nUsers can use the esptool by running the generate_flash_encryption_key commands to generate the different types Flash Encryption keys.\nYou can use command with --help to query the commands instructions:\nespsecure.py generate_flash_encryption_key --help Run the following command to generate the SHA-256 key:\nespsecure.py generate_flash_encryption_key --keylen 128 flash_encrypt_key.bin To generate the AES-128 key, run\nPlease note:\nThe Flash Download Tool only support AES-128 key on ESP32-S3, so we recommend to use the AES-128 key for ESP32-S3 Flash Encryption . espsecure.py generate_flash_encryption_key flash_encrypt_key.bin When the --keylen parameter is not specified, It will generated the AES-128 key by default\nRunning the follows command to generate the AES-256 key espsecure.py generate_flash_encryption_key --keylen 512 flash_encrypt_key.bin How to Obtain Secure Boot V2 key ? # Base on the ESP32S3 chip to enable Secure Boot V2 function will requires a rsa3072 type key.\nUsers can use the esptool ，and running the espsecure.py generate_signing_key command to generate the Secure Boot V2 key.\nYou can use espsecure.py generate_signing_key --help command to query the commands instructions.\nespsecure.py generate_signing_key secure_boot_signing_key.pem --version 2 --scheme rsa3072 Alternatively, you can also install the OpenSSL environment and to generate an RSA 3072 type private key for Secure Boot signing with the following command:\nopenssl genrsa -out secure_boot_signing_key.pem 3072 How to Obtain Secure Boot V2 public key digest? # When enable Secure Boot V2 function on Flash Download Tool ， you need to add the Secure Boot V2 Key Digest. So you need to base on the Secure Boot V2 Key to generate the digest of the public key. Please see: Enable Secure Boot V2 Externally.\nYou can use espsecure.py digest_rsa_public_key --help command to query the commands instructions.\nFor example:\nespsecure.py digest_rsa_public_key --keyfile secure_boot_signing_key.pem --output public_key_digest.bin How to Obtain nvs_key ? # You can use the nvs partition tool （esp-idf/components/nvs_flash/nvs_partition_generator）and running the nvs_partition_gen.py command to obtain the nvs_key file.\nYou can use nvs_partition_gen.py --help command to query the commands instructions.\nFor example:\npython E:\\esp\\Espressif\\frameworks\\esp-idf-5.2.1\\esp-idf\\components\\nvs_flash\\nvs_partition_generator\\nvs_partition_gen.py generate-key --keyfile nvs_key.bin How to use nvs_key to encrypt the custom_nvs.csv file ? # If you need to download custom_nvs.bin when you download all firmware, you also need to manually encrypt custom_nvs.bin use nvs_key. You can running the follows command to use nvs_key.bin to encrypt the custom_nvs.csv file and get the encrypted encrypt_custom_nvs.bin.\nFor example:\npython E:\\esp\\Espressif\\frameworks\\esp-idf-5.2.1\\esp-idf\\components\\nvs_flash\\nvs_partition_generator\\nvs_partition_gen.py encrypt custom_nvs.csv encrypt_custom_nvs.bin 0x6000 --inputkey keys\\nvs_key.bin 0x6000 is size of encrypt_custom_nvs.bin firmware 3 - Software Configuration # On the Software Configuration side，you will need to enable Flash Encryption, Secure Boot V2 and NVS Encryption setting.\nidf.py menuconfig Go to Security features then set the options as the image below:\nEnable Secure Boot V2 Please note you need to add the secure_boot_signing_key.pem path.\nSet the Enable Flash Encryption options:\nEnable Flash Encryption Flash Encryption Modes # Flash Encryption supports two modes: Release and Development (NOT SECURE).\nRelease Mode:\nWhen Release mode is selected, the SPI_BOOT_CRYPT_CNT eFuse bit is set to 0b111, permanently enabling Flash Encryption. This mode is recommended for mass production, as it provides full security by locking the encryption settings after the first flash. Development Mode (NOT SECURE):\nIn Development (NOT SECURE) mode, the SPI_BOOT_CRYPT_CNT eFuse bit is set to 0b001. This mode allows for testing and debugging, offering the flexibility to flash firmware multiple times with encryption enabled. However, this mode is not secure and is intended only for development purposes. If Flash Encryption is enabled in Development (NOT SECURE) mode, there is one chance to disable it. To disable Flash Encryption after it has been enabled in this mode, you can run the following command: espefuse.py -p port burn_efuse SPI_BOOT_CRYPT_CNT 0x3 Because the Flash Download Tool only supports AES-128 on the ESP32-S3, you should select the AES-128 key option in the software.\nAdditionally, pay attention to the UART ROM download mode setting. If you prefer not to disable the download mode, it is recommended to select the configuration option UART ROM download mode (Enabled, not recommended). For more details on different download mode configuration options, refer to the CONFIG_SECURE_UART_ROM_DL_MODE documentation.\nEnable NVS Encryption # To enable the NVS Encryption, set the following in the configuration menu:\nGo to Component config → NVS and set the Enable NVS encryption.\nEnable NVS Encryption Increase the partition table offset # Since the Flash Encryption and Secure Boot V2 function will increase the size of the bootloader firmware, so you need to increase the partition table offset(Default is 0x8000) setting. As follows:\nGo to Partition Table and set the offset to (0xF000) in the Offset of partition table.\nIncrease Partition Table Offset Build the project # Now you need to build the project to get the compiled firmware.\nRun the build command:\nidf.py build Since the secure boot function is enabled, after compilation, you will generate several firmware files, including bootloader.bin, bootloader-unsigned.bin, app.bin, app-unsigned.bin, and other partition firmware files.\nThe bootloader.bin and app.bin are signed firmware, while bootloader-unsigned.bin and app-unsigned.bin are the unsigned versions. You need to download the signed firmware files (bootloader.bin and app.bin) along with the other partition firmware files.\nFrom the compilation log, you can find the firmware file paths and the corresponding download addresses. These firmware files and their download addresses need to be imported into the Flash Download Tool, as shown below:\nFirmware Offset Addresses Firmware paths:\nFirmware path 4 - Flash Download Tool Configuration # On this step, we will show how to configure the Flash Download Tool with the generated keys. This tool is only available for Windows.\nFirst, put the Flash Encryption Key and the digest of the Secure boot V2 public key into the flash_download_tool\\secure directory, as following：\nSecure Keys In the configure\\esp32s3\\security.conf configuration file of the Flash Download Tool, enable the Flash Encryption and Secure Boot V2 configuration options.\nSecurity Config File The security configurations to be modified are:\n[SECURE BOOT] secure_boot_en = True \\\\ Enable Secure Boot public_key_digest_path = .\\bin\\public_key_digest.bin \\\\ Setting public_key_digest.bin path for Secure Boot public_key_digest_block_index = 0 \\\\ Index of the eFuse block where the public key digest file is stored. Default: 0. [FLASH ENCRYPTION] flash_encryption_en = True \\\\ Enable Flash Encryption reserved_burn_times = 0 \\\\ Configures how many times [0 in this case when config Flash Encryption Release mode on the software] are reserved for the flashing operation flash_encrypt_key_block_index = 1 \\\\ Index of the eFuse block where the Flash Encrypt Key file is stored. Default: 0. Range: 0~4. Note that this option can only be set to 0 for ESP32-C2. [SECURE OTHER CONFIG] flash_encryption_use_customer_key_enable = True \\\\ Configures whether to enable the use of a customer-specified encryption key flash_encryption_use_customer_key_path = .\\bin\\flash_encrypt_key.bin \\\\ Setting customer-specified Flash Encryption key file path flash_force_write_enable = True \\\\ Configures whether to skip encryption and secure boot checks during flashing. If it is set to False (default), an error message may pop up when attempting to flash products with enabled flash encryption or secure boot. [FLASH ENCRYPTION KEYS LOCAL SAVE] keys_save_enable = False encrypt_keys_enable = False encrypt_keys_aeskey_path = // On the first boot, the flash encryption process burns by default the following eFuses: [ESP32S3 EFUSE BIT CONFIG] dis_usb_jtag = True \\\\ Configures whether to disable USB JTAG hard_dis_jtag = True \\\\ Configures whether to hard-disable JTAG soft_dis_jtag = 7 \\\\ Configures whether to soft-disable JTAG dis_usb_otg_download_mode = False \\\\ Configures whether to disable USB OTG download dis_direct_boot = True \\\\ Configures whether to disable direct boot mode dis_download_icache = True \\\\ Configures whether to disable the entire MMU flash instruction cache when running in UART bootloader mode dis_download_dcache = True \\\\ Configures whether to disable the entire MMU flash data cache in the UART bootloader mode dis_download_manual_encrypt = True \\\\ Configures whether to disable flash encryption operation when running in UART bootloader boot mode Restart the Flash Download Tool # Before proceeding with the process, restart the Flash Download Tool software. After restarting, the new configuration file located in configure\\esp32s3\\security.conf will be read, and the updated configuration will be loaded.\nIf everything is working correctly, a warning message will be displayed:\nFlash Download Tool Boot Security Config Now you can click OK.\nImport All Firmware to be Downloaded # Based on the partition table settings, add all the firmware files and their respective download addresses. The interface should look similar to the following:\nAdd Bin Files Downloading All Firmware # During the firmware download process, the Flash Download Tool will write the following to the chip\u0026rsquo;s eFuse blocks:\nThe Flash encryption key and the Secure Boot V2 public key digest. The SPI_BOOT_CRYPT_CNT eFuse bit will be set to enable Flash Encryption, and the SECURE_BOOT_EN eFuse bit will be set to enable Secure Boot V2. The tool will also apply all configuration settings from the configure\\esp32s3\\security.conf file to the chip\u0026rsquo;s eFuses. You will see a log similar to the one below from the tool\u0026rsquo;s output:\ntest offset : 0 0x0 case ok test offset : 61440 0xf000 case ok test offset : 81920 0x14000 case ok test offset : 90112 0x16000 case ok test offset : 131072 0x20000 case ok test offset : 3276800 0x320000 case ok test offset : 3280896 0x321000 case ok . Uploading stub... Running stub... Stub running... Changing baud rate to 115200 Changed. NO XMC flash detected! SPI_BOOT_CRYPT_CNT 0 SECURE_BOOT_EN False ESP32 secure boot v2 skip generate key Encrypting bin file ...please wait!!! Using 256-bit key Encrypting bin file ...please wait!!! Using 256-bit key Encrypting bin file ...please wait!!! Using 256-bit key Encrypting bin file ...please wait!!! Using 256-bit key Encrypting bin file ...please wait!!! Using 256-bit key Encrypting bin file ...please wait!!! Using 256-bit key Encrypting bin file ...please wait!!! Using 256-bit key burn secure key ... Burn keys to blocks: - BLOCK_KEY1 -\u0026gt; [5f 4d 93 00 10 24 fd c4 3e ff 04 49 53 e2 88 83 c0 bc 2b d6 7e f1 81 0e f6 84 cd b7 0b 72 ae df] Reversing byte order for AES-XTS hardware peripheral \u0026#39;KEY_PURPOSE_1\u0026#39;: \u0026#39;USER\u0026#39; -\u0026gt; \u0026#39;XTS_AES_128_KEY\u0026#39;. Disabling write to \u0026#39;KEY_PURPOSE_1\u0026#39;. Disabling read to key block Disabling write to key block - BLOCK_KEY0 -\u0026gt; [c3 f6 4b 2e 84 92 f1 fc 86 d0 17 17 fe 62 04 6f e0 83 17 36 19 1a f4 9e 86 df e5 50 74 44 86 bf] \u0026#39;KEY_PURPOSE_0\u0026#39;: \u0026#39;USER\u0026#39; -\u0026gt; \u0026#39;SECURE_BOOT_DIGEST0\u0026#39;. Disabling write to \u0026#39;KEY_PURPOSE_0\u0026#39;. Disabling write to key block Check all blocks for burn... idx, BLOCK_NAME, Conclusion [00] BLOCK0 is not empty (written ): 0x0000000000000000000000000000d1f50000000000000000 (to write): 0x000000000000000000000000490000000000000201800300 (coding scheme = NONE) [04] BLOCK_KEY0 is empty, will burn the new value [05] BLOCK_KEY1 is empty, will burn the new value . This is an irreversible operation! BURN BLOCK5 - OK (write block == read block) BURN BLOCK4 - OK (write block == read block) BURN BLOCK0 - OK (all write block bits are set) Reading updated efuses... Successful The efuses to burn: from BLOCK0 - SPI_BOOT_CRYPT_CNT - SECURE_BOOT_EN Burning efuses: - \u0026#39;SPI_BOOT_CRYPT_CNT\u0026#39; (Enables flash encryption when 1 or 3 bits are set and disabled otherwise) 0b000 -\u0026gt; 0b111 - \u0026#39;SECURE_BOOT_EN\u0026#39; (Set this bit to enable secure boot) 0b0 -\u0026gt; 0b1 Check all blocks for burn... idx, BLOCK_NAME, Conclusion [00] BLOCK0 is not empty (written ): 0x0000000000000000000000004900d1f50000000201800300 (to write): 0x000000000000000000100000001c00000000000000000000 (coding scheme = NONE) . This is an irreversible operation! BURN BLOCK0 - OK (all write block bits are set) Reading updated efuses... Checking efuses... Successful WARNING: - compress and encrypt options are mutually exclusive Will flash uncompressed is stub and send flash finish The efuses to burn: from BLOCK0 - DIS_USB_JTAG - DIS_PAD_JTAG - SOFT_DIS_JTAG - DIS_DIRECT_BOOT - DIS_DOWNLOAD_ICACHE - DIS_DOWNLOAD_DCACHE - DIS_DOWNLOAD_MANUAL_ENCRYPT Burning efuses: - \u0026#39;DIS_USB_JTAG\u0026#39; (Set this bit to disable function of usb switch to jtag in module of usb device) 0b0 -\u0026gt; 0b1 - \u0026#39;DIS_PAD_JTAG\u0026#39; (Set this bit to disable JTAG in the hard way. JTAG is disabled permanently) 0b0 -\u0026gt; 0b1 - \u0026#39;SOFT_DIS_JTAG\u0026#39; (Set these bits to disable JTAG in the soft way (odd number 1 means disable ). JTAG can be enabled in HMAC module) 0b000 -\u0026gt; 0b111 - \u0026#39;DIS_DIRECT_BOOT\u0026#39; (Disable direct boot mode) 0b0 -\u0026gt; 0b1 - \u0026#39;DIS_DOWNLOAD_ICACHE\u0026#39; (Set this bit to disable Icache in download mode (boot_mode[3:0] is 0; 1; 2; 3; 6; 7)) 0b0 -\u0026gt; 0b1 - \u0026#39;DIS_DOWNLOAD_DCACHE\u0026#39; (Set this bit to disable Dcache in download mode ( boot_mode[3:0] is 0; 1; 2; 3; 6; 7)) 0b0 -\u0026gt; 0b1 - \u0026#39;DIS_DOWNLOAD_MANUAL_ENCRYPT\u0026#39; (Set this bit to disable flash encryption when in download boot modes) 0b0 -\u0026gt; 0b1 Check all blocks for burn... idx, BLOCK_NAME, Conclusion [00] BLOCK0 is not empty (written ): 0x000000000000000000100000491cd1f50000000201800300 (to write): 0x00000000000000020040000000000000001f0c0000000000 (coding scheme = NONE) . This is an irreversible operation! BURN BLOCK0 - OK (all write block bits are set) Reading updated efuses... Checking efuses... Successful After the firmware is downloaded, the Flash Encryption and Secure Boot V2 processes are completed. The firmware download process performs the following steps:\nWriting the Secure Boot V2 public key digest to chip eFuse BLOCK_KEY0 (KEY_PURPOSE_0) Writing the Flash Encryption key to chip eFuse BLOCK_KEY1 (KEY_PURPOSE_1) Setting the SPI_BOOT_CRYPT_CNT eFuse bit to 0b111 to enable Flash Encryption Setting the SECURE_BOOT_EN eFuse bit to 0b1 to enable Secure Boot V2 Setting the DIS_USB_JTAG eFuse bit to 0b1 to disable USB JTAG Setting the DIS_PAD_JTAG eFuse bit to 0b1 to disable PAD JTAG Setting the SOFT_DIS_JTAG eFuse bit to 0b111 to disable JTAG functionality Setting the DIS_DIRECT_BOOT eFuse bit to 0b1 to disable direct boot Setting the DIS_DOWNLOAD_ICACHE eFuse bit to 0b1 to disable instruction cache during download Setting the DIS_DOWNLOAD_DCACHE eFuse bit to 0b1 to disable data cache during download Setting the DIS_DOWNLOAD_MANUAL_ENCRYPT eFuse bit to 0b1 to disable manual encryption during download Running the Firmware # During the first startup (power-up), the firmware will go through the following checks:\nVerify if the Secure Boot V2 feature is enabled. Verify if the Flash Encryption feature is enabled. Verify if the NVS Encryption feature is enabled. Validate the signed and encrypted firmware. If all checks and verification processes succeed, the firmware will run normally.\nThe firmware running log on the first startup will appear as follows:\nESP-ROM:esp32s3-20210327 Build:Mar 27 2021 rst:0x1 (POWERON),boot:0x8 (SPI_FAST_FLASH_BOOT) SPIWP:0xee mode:DIO, clock div:1 Valid secure boot key blocks: 0 secure boot verification succeeded load:0x3fce3980,len:0x3a1c load:0x403c9700,len:0x4 load:0x403c9704,len:0xcbc load:0x403cc700,len:0x52a0 entry 0x403c9914 I (73) boot: ESP-IDF v5.2.2-520-g9d6583f763 2nd stage bootloader I (73) boot: compile time Aug 16 2024 15:58:33 I (74) boot: Multicore bootloader I (78) boot: chip revision: v0.1 I (81) boot.esp32s3: Boot SPI Speed : 80MHz I (86) boot.esp32s3: SPI Mode : DIO I (91) boot.esp32s3: SPI Flash Size : 8MB I (96) boot: Enabling RNG early entropy source... I (101) boot: Partition Table: I (105) boot: ## Label Usage Type ST Offset Length I (112) boot: 0 nvs WiFi data 01 02 00010000 00004000 I (120) boot: 1 otadata OTA data 01 00 00014000 00002000 I (127) boot: 2 phy_init RF data 01 01 00016000 00001000 I (135) boot: 3 factory factory app 00 00 00020000 00100000 I (142) boot: 4 ota_0 OTA app 00 10 00120000 00100000 I (150) boot: 5 ota_1 OTA app 00 11 00220000 00100000 I (157) boot: 6 nvs_key NVS keys 01 04 00320000 00001000 I (165) boot: 7 custom_nvs WiFi data 01 02 00321000 00006000 I (173) boot: End of partition table I (177) boot: Defaulting to factory image I (182) esp_image: segment 0: paddr=00020020 vaddr=3c090020 size=20e68h (134760) map I (217) esp_image: segment 1: paddr=00040e90 vaddr=3fc98700 size=047f8h ( 18424) load I (221) esp_image: segment 2: paddr=00045690 vaddr=40374000 size=0a988h ( 43400) load I (233) esp_image: segment 3: paddr=00050020 vaddr=42000020 size=81db8h (531896) map I (339) esp_image: segment 4: paddr=000d1de0 vaddr=4037e988 size=09cd0h ( 40144) load I (349) esp_image: segment 5: paddr=000dbab8 vaddr=00000000 size=04518h ( 17688) I (353) esp_image: Verifying image signature... I (354) secure_boot_v2: Verifying with RSA-PSS... I (360) secure_boot_v2: Signature verified successfully! I (371) boot: Loaded app from partition at offset 0x20000 I (371) secure_boot_v2: enabling secure boot v2... I (374) secure_boot_v2: secure boot v2 is already enabled, continuing.. I (382) boot: Checking flash encryption... I (386) flash_encrypt: flash encryption is enabled (0 plaintext flashes left) I (394) boot: Disabling RNG early entropy source... I (411) cpu_start: Multicore app I (421) cpu_start: Pro cpu start user code I (421) cpu_start: cpu freq: 160000000 Hz I (421) cpu_start: Application information: I (424) cpu_start: Project name: wifi_softAP I (430) cpu_start: App version: v5.2.2-520-g9d6583f763 I (436) cpu_start: Compile time: Aug 16 2024 15:58:16 I (442) cpu_start: ELF file SHA256: d89b197be... Warning: checksum mismatch between flashed and built applications. Checksum of built application is 6d559abf84b1d704bc99214866ff8708cf910cc472ec5ec9ca1557ca7d430710 I (447) cpu_start: ESP-IDF: v5.2.2-520-g9d6583f763 I (454) cpu_start: Min chip rev: v0.0 I (458) cpu_start: Max chip rev: v0.99 I (463) cpu_start: Chip rev: v0.1 I (468) heap_init: Initializing. RAM available for dynamic allocation: I (475) heap_init: At 3FCA0AF8 len 00048C18 (291 KiB): RAM I (481) heap_init: At 3FCE9710 len 00005724 (21 KiB): RAM I (487) heap_init: At 3FCF0000 len 00008000 (32 KiB): DRAM I (494) heap_init: At 600FE010 len 00001FD8 (7 KiB): RTCRAM I (501) spi_flash: detected chip: generic I (504) spi_flash: flash io: dio I (509) flash_encrypt: Flash encryption mode is RELEASE I (515) efuse: Batch mode of writing fields is enabled W (520) secure_boot: Unused SECURE_BOOT_DIGEST1 should be revoked. Fixing.. W (528) secure_boot: Unused SECURE_BOOT_DIGEST2 should be revoked. Fixing.. I (536) efuse: BURN BLOCK0 I (541) efuse: BURN BLOCK0 - OK (all write block bits are set) I (546) efuse: Batch mode. Prepared fields are committed I (551) secure_boot: Fixed I (555) nvs_sec_provider: NVS Encryption - Registering Flash encryption-based scheme... I (564) sleep: Configure to isolate all GPIO pins in sleep state I (570) sleep: Enable automatic switching of GPIO sleep configuration I (578) main_task: Started on CPU0 I (588) main_task: Calling app_main() I (628) nvs: NVS partition \u0026#34;nvs\u0026#34; is encrypted. I (628) wifi softAP: ESP_WIFI_MODE_AP I (628) pp: pp rom version: e7ae62f I (628) net80211: net80211 rom version: e7ae62f I (658) wifi:wifi driver task: 3fcaae94, prio:23, stack:6656, core=0 I (658) wifi:wifi firmware version: e60360a19 I (658) wifi:wifi certification version: v7.0 I (658) wifi:config NVS flash: enabled I (658) wifi:config nano formating: disabled I (668) wifi:Init data frame dynamic rx buffer num: 32 I (668) wifi:Init static rx mgmt buffer num: 5 I (678) wifi:Init management short buffer num: 32 I (678) wifi:Init dynamic tx buffer num: 32 I (678) wifi:Init static tx FG buffer num: 2 I (688) wifi:Init static rx buffer size: 1600 I (688) wifi:Init static rx buffer num: 10 I (698) wifi:Init dynamic rx buffer num: 32 I (698) wifi_init: rx ba win: 6 I (698) wifi_init: tcpip mbox: 32 I (708) wifi_init: udp mbox: 6 I (708) wifi_init: tcp mbox: 6 I (708) wifi_init: tcp tx win: 5760 I (718) wifi_init: tcp rx win: 5760 I (718) wifi_init: tcp mss: 1440 I (728) wifi_init: WiFi IRAM OP enabled I (728) wifi_init: WiFi RX IRAM OP enabled I (1258) phy_init: phy_version 680,a6008b2,Jun 4 2024,16:41:10 W (1258) phy_init: failed to load RF calibration data (0x1102), falling back to full calibration W (1318) phy_init: saving new calibration data because of checksum failure, mode(2) I (1338) wifi:mode : softAP (68:b6:b3:4e:3f:f1) I (1388) wifi:Total power save buffer number: 16 I (1388) wifi:Init max length of beacon: 752/752 I (1398) wifi:Init max length of beacon: 752/752 I (1398) wifi softAP: wifi_init_softap finished. SSID:myssid password:mypassword channel:1 I (1398) esp_netif_lwip: DHCP server started on interface WIFI_AP_DEF with IP: 192.168.4.1 I (1408) main_task: Returned from app_main() Conclusion # Enabling Flash Encryption, Secure Boot V2, and NVS Encryption on the ESP32-S3 is critical for ensuring the security and integrity of your firmware and data. By following this guide, you can successfully configure and implement these features in both development and production environments. Utilizing tools like the Flash Download Tool simplifies the process, making it efficient and secure, especially in mass production settings. Always verify your configurations and ensure that the correct eFuse settings are applied, as they are irreversible.\nFor further exploration and testing, refer to the provided code examples and documentation links.\nReferences # For more information on implementing and verifying Flash Encryption, as well as practical examples, refer to the following resources:\nVerify Flash Encryption Code: Detailed source code for verifying the Flash Encryption process can be found in the ESP-IDF repository: esp-idf/components/bootloader_support/src/flash_encrypt.c\nFlash Encryption Test Example: A comprehensive example demonstrating Flash Encryption in action is available in the ESP-IDF examples section: esp-idf/examples/security/flash_encryption\n","date":"23 September 2024","externalUrl":null,"permalink":"/blog/flash-encryption-and-secure-boot/","section":"Blog","summary":"","title":"Using the ESP Flash Download Tool to finish the Flash Encryption + Secure Boot + NVS Encryption","type":"blog"},{"content":"","date":"20 September 2024","externalUrl":null,"permalink":"/tags/connectivity/","section":"Tags","summary":"","title":"Connectivity","type":"tags"},{"content":"","date":"20 September 2024","externalUrl":null,"permalink":"/tags/microcontrollers/","section":"Tags","summary":"","title":"Microcontrollers","type":"tags"},{"content":"","date":"20 September 2024","externalUrl":null,"permalink":"/tags/wifi/","section":"Tags","summary":"","title":"Wifi","type":"tags"},{"content":"The ESP32-P4 is a powerful system-on-chip (SoC) from Espressif, designed for high-performance applications that demand robust features. While the ESP32-P4 offers a range of advanced capabilities, it does not have integrated wireless connectivity and may require additional connectivity solutions to meet the diverse needs of modern embedded systems. Espressif provides three main connectivity solutions for the ESP32-P4: ESP-AT , ESP-Hosted , and ESP-Extconn . Let’s explore each solution\u0026rsquo;s advantages, limitations, and use cases.\nESP-AT # ESP-AT allows the ESP32-P4 to connect with external wireless modules using AT commands. It’s a simple and effective way to integrate wireless connectivity without extensive software development.\nAdvantages :- Simple and easy to use, with a well-established AT command interface- Supports a wide range of WiFi and Bluetooth features- Readily available and widely used in the Espressif ecosystem- Some minor customization is possible on the AT interface to add new commands.\nLimitations :- Limited to basic connectivity functions, with less flexibility for advanced applications- Low performance in terms of throughput, QoS as well as latency\nApplications and Scenarios :- Suitable for simple IoT devices or applications with basic connectivity requirements- Ideal for quick prototyping or projects where a straightforward, out-of-the-box solution is preferred\nESP-Hosted-FG # ESP-Hosted-FG provides a standard 802.3 (Ethernet) network interface to the host. This setup ensures the microcontroller can handle more complex or demanding processes without compromising wireless performance.\nAdvantages: - Provides flexibility in choosing different interfaces based on the performance requirement of the application- Supports advanced wireless features compared to ESP-AT like VLAN, Multiple Network interfaces, Network and performance tuning configurations, etc. - Source code in open-source and the slave can be customized to utilize other features of the SoC like peripherals, GPIOs, etc.\nLimitations: - Requires additional development effort to integrate the ESP-Hosted solution with the main application- May have higher resource requirements compared to ESP-AT\nApplications and Scenarios: - Suitable for complex IoT devices or applications that demand advanced wireless features- Useful for applications that require high-performance or resource-intensive wireless feature\nESP-Extconn # ESP-Extconn provides external wireless connectivity(Wi-Fi \u0026amp; Bluetooth) for ESP chips that do not have built-in wireless capabilities. This component\u0026rsquo;s APIs are compatible with the Wi-Fi and Bluetooth component APIs in the ESP-IDF.\nAdvantages :- Provides the most flexible and extensible connectivity solution- Allows for ease of integration with the main application logic due to familiarity with the ESP-IDF wireless components APIs.\nLimitations: - Requires more development effort compared to the other solutions.- There may be higher resource requirements for the host- It has zero flexibility in terms of customization of co-processor functionality.\nApplications and Scenarios: - Ideal for applications where the main application logic needs to be tightly integrated with the connectivity features- Useful for projects that require a high degree of flexibility and configurability in the connectivity solution\nComparison of the different solutions: # Choosing the Right Solution # When selecting a connectivity solution for the ESP32-P4, consider the following factors:\n1. Connectivity Requirements: Assess the specific wireless and connectivity needs of your application. If basic Wi-Fi and Bluetooth features are sufficient, ESP-AT may be the most suitable choice. For more advanced wireless requirements, ESP-Hosted or ESP-Extconn may be better options.\n2. Application Complexity: If your main application logic is straightforward and can be easily combined with the connectivity tasks, ESP-AT may be the simplest solution. For complex applications that require a clear separation between the main logic and connectivity, ESP-Hosted or ESP-Extconn may be more appropriate.\n3. Development Resources: If you have a smaller team or limited development resources, ESP-AT may be the easiest solution to integrate. ESP-Hosted and ESP-Extconn require more development effort but offer greater flexibility and configurability.\n4. Performance Constraints: For high-performance applications, the trade-offs between the solutions should be carefully evaluated. ESP-AT may be more resource-efficient, while ESP-Hosted and ESP-Extconn will provide better performance and throughput.\n5. Interface Considerations: ESP-Hosted provides flexibility to choose from SDIO, SPI, and UART interfaces for your connectivity solution based on the performance requirement of the application.\nCo-processor resource usage: If there is a requirement to use other features of the co-processor like GPIOs, peripherals, etc., ESP-Hosted provides the most flexibility in terms of customization of the slave as to the requirement. If using the ESP-AT, users can create custom AT commands for some basic operations. By considering these factors, you can determine the most suitable connectivity solution for your ESP32-P4-based application, ensuring the optimal balance between ease of use, flexibility, and performance.\n","date":"20 September 2024","externalUrl":null,"permalink":"/blog/wireless-connectivity-solutions-for-esp32-p4/","section":"Blog","summary":"","title":"Wireless Connectivity Solutions for ESP32-P4","type":"blog"},{"content":" Introduction # In today’s fast-paced world of IoT and embedded systems, creating an intuitive and responsive Graphical User Interface (GUI) can make or break the user experience of your product. Espressif’s powerful microcontrollers, like the ESP32-S2 or the ESP32-S3, offer incredible capabilities for embedded applications. However, developing a professional-grade GUI that leverages these capabilities can be challenging. That’s where Embedded Wizard comes into play. Embedded Wizard is an award-winning GUI development solution by independent software company TARA Systems that enables engineers to create high-performance, visually appealing interfaces with ease. In this article, we\u0026rsquo;ll explore how Embedded Wizard integrates seamlessly with Espressif\u0026rsquo;s ecosystem, helping you to rapidly create and deploy stunning GUIs on your ESP32-based projects.\nEasily Develop Graphical User Interfaces (GUIs) with Espressif Microcontrollers (MCUs) - Picture Why Choose Embedded Wizard for Your Espressif Project? # 1. Optimized Performance and Efficiency # Embedded Wizard is designed to run efficiently on resource-constrained devices, making it an ideal choice for Espressif’s microcontrollers. The framework only requires a minimum of 16KB of RAM and includes an advanced graphics engine that ensures smooth animations and transitions even on devices with limited processing power and memory. Embedded Wizard’s lightweight runtime library ensures that your GUIs run smoothly, with support for complex animations, transitions, and real-time data visualization.\n2. Cross-Platform Development # One of the standout features of Embedded Wizard is its ability to generate platform-independent code. This means you can develop your GUI once and deploy it across multiple devices, including various Espressif microcontrollers. This cross-platform capability not only saves development time but also simplifies the process of maintaining and updating your GUI across different hardware.\n3. Rich Set of Features # Embedded Wizard offers a comprehensive set of ready-to-use widgets, effects, and animations which can be customized to create a unique user experience. Whether you need touch input, multi-language support, or scalable vector graphics, Embedded Wizard has you covered.\n4. Seamless Integration with Espressif’s Hardware # Embedded Wizard has been optimized for Espressif microcontrollers, providing direct support for Espressif platforms. This seamless integration allows you to leverage the full potential of Espressif hardware, from touch inputs to display outputs, with minimal setup. In addition, Embedded Wizard comes with a comprehensive Knowledge Base, with easy-to-follow tutorials for Espressif platforms like the ESP-WROVER-KIT, ESP32-S2-Kaluga, and ESP32-S3-BOX. This ensures that you can get started quickly without needing to worry about low-level implementation details.\nGetting Started: Building Your GUI on ESP32 # Let’s walk through a simple step-by-step guide of building a GUI with Embedded Wizard. While this example uses the ESP32-S3-BOX, the principles outlined here can be applied to any hardware you are working with.\n1. Design the GUI Application # Start by downloading Embedded Wizard and using the Embedded Wizard Studio to design the look and behavior of your GUI application. This Integrated Development Environment (IDE) allows you to easily create interfaces by clicking, dragging, and connecting visual and logical components. Application logic is written in Chora, a platform-independent language similar to C++ and JavaScript. The design process leverages the Mosaic framework, which includes essential components like ready-to-use widgets and event handlers.\n2. Prototype, Test, and Debug # Throughout the design process, use the integrated Prototyper to instantly evaluate your application\u0026rsquo;s appearance and behavior. This enables real-time simulation without needing to compile or upload binaries to the target hardware.\n3. Generate Optimized Code # After finalizing the design, instruct the Embedded Wizard Studio to generate source code optimized for your ESP32-S3-BOX. This step translates your Chora logic and the Mosaic framework into target-specific code, optimizing images and fonts used in your application. The generated output includes a set of .c and .h files that define the GUI application\u0026rsquo;s appearance and functionality.\n4. Integrate and Build # Incorporate the generated files into your build system. Include files from the Embedded Wizard SDK, which ensure proper hardware function utilization for correct drawing operations. Compile and link all files into a single binary, adding any additional software components as needed.\n5. Deploy and Run # Deploy the compiled binary to your ESP32-S3-BOX by writing it to the device\u0026rsquo;s flash memory. The GUI application runs natively on the device without requiring interpreters or just-in-time compilers, thanks to the efficient source code generation process. This ensures minimal flash and RAM usage, providing optimal performance.\nConclusion # Embedded Wizard and Espressif’s ESP32 family are a powerful combination for creating high-quality, responsive GUIs in embedded systems. By leveraging Embedded Wizard’s advanced features and seamless integration with Espressif hardware, you can accelerate your development process and bring your IoT products to market faster.\nIf you\u0026rsquo;re ready to take your GUI development to the next level, download the free version of Embedded Wizard today and see how it can transform your projects on Espressif platforms.\nResources # Download Embedded Wizard Embedded Wizard Website Embedded Wizard YouTube Channel Getting Started with ESP32 Overview: Embedded Wizard Integration with ESP32 ","date":"17 September 2024","externalUrl":null,"permalink":"/blog/easily-develop-graphical-user-interfaces-with-mcus/","section":"Blog","summary":"","title":"Easily Develop Graphical User Interfaces (GUIs) with Espressif Microcontrollers (MCUs)","type":"blog"},{"content":" Developing a Project with Existing Applications # The process of building an application in NuttX - whether it is a custom application or one that already exists and targets other operating systems - follows the principles of the NuttX build system. Although the NuttX documentation covers aspects of the application compilation process in various articles and documents, we will delve deeper into some of these options in this article.\nFor those who are not familiar with NuttX, I recommend reading the article Getting Started with NuttX and ESP32 or referring to the Getting Started section in the official NuttX documentation. I would like to highlight NuttX\u0026rsquo;s great advantage: being a POSIX-compliant system allows for easy integration of many applications into the system. About that, there\u0026rsquo;s an old saying:\nDon\u0026rsquo;t reinvent the wheel. Someone may have already developed an application to solve your problem!\nIn this sense, developing a product with NuttX is greatly facilitated by using commonly used applications and libraries that can be easily adapted to NuttX (if it hasn\u0026rsquo;t already been done). Thus, the developer can focus on developing the end application of the product based on extensively tested, validated, and well-documented applications and libraries.\nThis series of articles explains how applications and libraries can be integrated into NuttX using the build system, and based on that explanation, we will integrate the RTP Tools application into NuttX. This application is a set of utilities that, among other things, allows receiving Real-Time Protocol (RTP) packets over the network. The final application that will use RTP Tools will be further detailed in another article.\nGiving a glimpse about it: have you ever thought about how cool it would be to turn an ESP32 into a low-cost, high-fidelity sound server? Well, we might need RTP Tools for that :wink:.\nCompiling an Application in NuttX # Applications in NuttX are separated from the kernel source code of the operating system. Similarly to other operating systems, they interact with the NuttX kernel through public APIs compatible with the POSIX standard. It\u0026rsquo;s worth noting, however, that applications need to use the NuttX build system to be integrated into the final firmware. Thus, the Apache NuttX project also provides the nuttx-apps repository, which is a collection of applications available for NuttX.\nThe applications in this repository are public and can be used by any user. NuttX also provides means to compile applications outside this repository, allowing proprietary applications (not public) to be integrated into the system.\nNot every application needs to be made publicly available in nuttx-apps. It\u0026rsquo;s possible to keep non-public applications, but that is a topic for another article (or if you\u0026rsquo;re very curious, refer to the official documentation). Hello Word! # The most commonly used application as an example by operating systems and programming languages is perhaps the Hello World!: an application that prints those words to the user interface. It isn’t different with NuttX, and this application can be found in apps/examples/hello in the nuttx-apps repository [1].\nThe section entitled Application Configuration File (from the nuttx-apps repository description [2]) and the Extend the apps directory to include a new custom directory section in the Custom Apps How-to guide [3] explain some of the NuttX\u0026rsquo;s build system and how to add an application to NuttX. Based on these documents, we will explain here the compilation of the Hello World! application.\nThe apps/examples/hello directory of the nuttx-apps repository contains the following files:\n./examples/hello ├──CMakeLists.txt ├── hello_main.c ├── Kconfig ├── Make.defs └── Makefile The hello_main.c file refers to the source code. The others are related to the NuttX build system, which configures and selects this application to be compiled and integrated into NuttX.\nThe Build System # NuttX uses kconfig-frontends (or, more recently, kconfiglib) to generate the NuttX configuration file (.config), which resides in the NuttX OS\u0026rsquo;s main directory. For example, when compiling the Hello World! example, this file will have:\nCONFIG_EXAMPLES_HELLO=y But how do we \u0026ldquo;register\u0026rdquo; this application to be compiled in NuttX?\nKconfig # The configuration CONFIG_EXAMPLES_HELLO=y is made available for selection by the build system through the apps/examples/hello/Kconfig file in the application repository. It’s this file - through the config EXAMPLES_HELLO line (as we’ll see soon) - that allows the NuttX build system to be aware of the existence of this application. The Kconfig file of the Hello World! application has the following content:\n# # For a description of the syntax of this configuration file, # see the file kconfig-language.txt in the NuttX tools repository. # config EXAMPLES_HELLO tristate \u0026#34;\\\u0026#34;Hello, World!\\\u0026#34; example\u0026#34; default n ---help--- Enable the \\\u0026#34;Hello, World!\\\u0026#34; example if EXAMPLES_HELLO config EXAMPLES_HELLO_PROGNAME string \u0026#34;Program name\u0026#34; default \u0026#34;hello\u0026#34; ---help--- This is the name of the program that will be used when the NSH ELF program is installed. config EXAMPLES_HELLO_PRIORITY int \u0026#34;Hello task priority\u0026#34; default 100 config EXAMPLES_HELLO_STACKSIZE int \u0026#34;Hello stack size\u0026#34; default DEFAULT_TASK_STACKSIZE endif Make.defs # Based on this configuration, the NuttX build system includes the apps/examples/Make.defs file, which, in turn, adds the apps/examples/hello directory to the CONFIGURED_APPS variable as follows:\nifneq ($(CONFIG_EXAMPLES_HELLO),) CONFIGURED_APPS += $(APPDIR)/examples/hello endif Once the application directory is added to the CONFIGURED_APPS variable, the apps/examples/hello/Makefile is included in the build system.\nMakefile # Finally, the apps/examples/hello/Makefile provides the guidelines to compile the application for NuttX. Considering this example, the content of the file is:\ninclude $(APPDIR)/Make.defs # Hello, World! built-in application info PROGNAME = $(CONFIG_EXAMPLES_HELLO_PROGNAME) PRIORITY = $(CONFIG_EXAMPLES_HELLO_PRIORITY) STACKSIZE = $(CONFIG_EXAMPLES_HELLO_STACKSIZE) MODULE = $(CONFIG_EXAMPLES_HELLO) # Hello, World! Example MAINSRC = hello_main.c include $(APPDIR)/Application.mk Note that the Make recipe defines some variables such as PROGNAME, PRIORITY, STACKSIZE, and MODULE. These variables are set to values configured by Kconfig in the example.\nHowever, the most important one is the MAINSRC variable, which defines the source files to be compiled (in this case, hello_main.c). Note that although not present in this example, other variables can be defined, such as CSRCS, which includes other auxiliary C code, and ASRCS, which includes assembly files (*.asm), for example.\nThe Example Application # The last file in the apps/examples/hello directory is finally the source code of the application. The content of hello_word.c is:\n/**************************************************************************** * Included Files ****************************************************************************/ #include \u0026lt;nuttx/config.h\u0026gt; #include \u0026lt;stdio.h\u0026gt; /**************************************************************************** * Public Functions ****************************************************************************/ /**************************************************************************** * hello_main ****************************************************************************/ int main(int argc, FAR char *argv[]) { printf(\u0026#34;Hello, World!!\\n\u0026#34;); return 0; } Note that the source code of this application is as simple as it would be for the same application to be compiled on any other operating system supporting the C language and POSIX-compliant. The entry point of the application is defined similarly, represented by the main() function.\nIntegrating External Applications # The Hello World! example is a great introduction to how the NuttX build system allows to simply and quickly compile applications. However, note that the source code of the application (hello_main.c in this case) is integrated into the apps repository, and thus we could infer that the example application was written for NuttX (although it is very similar to a generic application). In this section, let\u0026rsquo;s explore the integration of an external application (or library) whose source code was originally designed for other UNIX-based systems. So, how can we compile Mbed TLS for NuttX?\nMbed TLS # The Mbed TLS repository defines it as:\nMbed TLS is a C library that implements cryptographic primitives, X.509 certificate manipulation and the SSL/TLS and DTLS protocols. Its small code footprint makes it suitable for embedded systems.\u0026quot;\nIn other words, Mbed TLS is a library that provides cryptographic functions that can be used by other applications. Let\u0026rsquo;s see how it can be integrated into NuttX!\nThe apps/crypto/mbedtls/Makefile directory in the apps repository contains the files that allow compiling this library in NuttX:\n./crypto/mbedtls ├── Kconfig ├── Make.defs └── Makefile Note that there are no source files (.c) or header files (.h) present in this repository! This is possible because the Mbed TLS source code is downloaded to be compiled only when the application is selected in the NuttX build system. But how does it work?\nMakefile # The provided Makefile in each application directory not only defines \u0026ldquo;default\u0026rdquo; variables used in the compilation but also allows writing (and overwriting) commonly used recipes in the make language. Take a look at the content of the apps/crypto/mbedtls/Makefile:\ninclude $(APPDIR)/Make.defs # Mbed TLS crypto library # Set up build configuration and environment MBEDTLS_URL ?= \u0026#34;https://github.com/ARMmbed/mbedtls/archive\u0026#34; MBEDTLS_VERSION = $(patsubst \u0026#34;%\u0026#34;,%,$(strip $(CONFIG_MBEDTLS_VERSION))) MBEDTLS_ZIP = v$(MBEDTLS_VERSION).zip MBEDTLS_UNPACKNAME = mbedtls UNPACK ?= unzip -q -o MBEDTLS_UNPACKLIBDIR = $(MBEDTLS_UNPACKNAME)$(DELIM)library MBEDTLS_UNPACKPROGDIR = $(MBEDTLS_UNPACKNAME)$(DELIM)programs # This lets Mbed TLS better use some of the POSIX features we have CFLAGS += ${DEFINE_PREFIX}__unix__ mbedtls/library/bignum.c_CFLAGS += -fno-lto # Build break on Assemble compiler if -fno-omit-frame-pointer and -O3 enabled at same time # {standard input}: Assembler messages: # {standard input}:2560: Error: branch out of range # make[2]: *** [apps/Application.mk:170: mbedtls/library/sha256.o] Error 1 ifeq ($(CONFIG_FRAME_POINTER),y) ifeq ($(CONFIG_DEBUG_OPTLEVEL),\u0026#34;-O3\u0026#34;) mbedtls/library/sha256.c_CFLAGS += -O2 endif endif ifeq ($(CONFIG_ARCH_SIM),y) CFLAGS += -O0 endif CSRCS = $(wildcard $(MBEDTLS_UNPACKLIBDIR)$(DELIM)*.c) $(MBEDTLS_ZIP): @echo \u0026#34;Downloading: $(MBEDTLS_URL)/$(MBEDTLS_ZIP)\u0026#34; $(Q) curl -O -L $(MBEDTLS_URL)/$(MBEDTLS_ZIP) $(MBEDTLS_UNPACKNAME): $(MBEDTLS_ZIP) @echo \u0026#34;Unpacking: $(MBEDTLS_ZIP) -\u0026gt; $(MBEDTLS_UNPACKNAME)\u0026#34; $(Q) $(UNPACK) $(MBEDTLS_ZIP) $(Q) mv\tmbedtls-$(MBEDTLS_VERSION) $(MBEDTLS_UNPACKNAME) $(Q) patch -p1 -d $(MBEDTLS_UNPACKNAME) \u0026lt; 0001-mbedtls-entropy_poll-use-getrandom-to-get-the-system.patch $(Q) patch -p1 -d $(MBEDTLS_UNPACKNAME) \u0026lt; 0002-mbedtls-add-mbedtls-x509-crt-pool.patch $(Q) touch $(MBEDTLS_UNPACKNAME) # Download and unpack tarball if no git repo found ifeq ($(wildcard $(MBEDTLS_UNPACKNAME)/.git),) context:: $(MBEDTLS_UNPACKNAME) distclean:: $(call DELDIR, $(MBEDTLS_UNPACKNAME)) $(call DELFILE, $(MBEDTLS_ZIP)) endif # Configuration Applications ifneq ($(CONFIG_MBEDTLS_APPS),) MODULE = $(CONFIG_MBEDTLS_APPS) ifeq ($(CONFIG_MBEDTLS_APP_BENCHMARK),y) PROGNAME += $(CONFIG_MBEDTLS_APP_BENCHMARK_PROGNAME) PRIORITY += $(CONFIG_MBEDTLS_APP_BENCHMARK_PRIORITY) STACKSIZE += $(CONFIG_MBEDTLS_APP_BENCHMARK_STACKSIZE) MAINSRC += $(MBEDTLS_UNPACKPROGDIR)/test/benchmark.c endif ifeq ($(CONFIG_MBEDTLS_APP_SELFTEST),y) PROGNAME += $(CONFIG_MBEDTLS_APP_SELFTEST_PROGNAME) PRIORITY += $(CONFIG_MBEDTLS_APP_SELFTEST_PRIORITY) STACKSIZE += $(CONFIG_MBEDTLS_APP_SELFTEST_STACKSIZE) MAINSRC += $(MBEDTLS_UNPACKPROGDIR)/test/selftest.c endif endif # Configuration alternative implementation ifeq ($(CONFIG_MBEDTLS_ENTROPY_HARDWARE_ALT),y) CSRCS += $(APPDIR)/crypto/mbedtls/source/entropy_alt.c endif ifeq ($(CONFIG_MBEDTLS_ALT),y) CSRCS += $(APPDIR)/crypto/mbedtls/source/dev_alt.c ifeq ($(CONFIG_MBEDTLS_AES_ALT),y) CSRCS += $(APPDIR)/crypto/mbedtls/source/aes_alt.c endif ifeq ($(CONFIG_MBEDTLS_MD5_ALT),y) CSRCS += $(APPDIR)/crypto/mbedtls/source/md5_alt.c endif ifeq ($(CONFIG_MBEDTLS_SHA1_ALT),y) CSRCS += $(APPDIR)/crypto/mbedtls/source/sha1_alt.c endif ifeq ($(CONFIG_MBEDTLS_SHA256_ALT),y) CSRCS += $(APPDIR)/crypto/mbedtls/source/sha256_alt.c endif ifeq ($(CONFIG_MBEDTLS_SHA512_ALT),y) CSRCS += $(APPDIR)/crypto/mbedtls/source/sha512_alt.c endif endif include $(APPDIR)/Application.mk Downloading the Source Code # According to the Built-In Applications section of the nuttx-apps repository:\nThe build occurs in several phases as different build targets are executed: (1) context, (2) depend, and (3) default (all). Application information is collected during the make context build phase. [4]\nNote that the context recipe is always executed by the NuttX build system, and it usually prepares the compilation of an application. For the Mbed TLS, it depends on the $(MBEDTLS_UNPACKNAME) file, which depends on the $(MBEDTLS_ZIP) file that is downloaded by the recipe:\n$(MBEDTLS_ZIP): @echo \u0026#34;Downloading: $(MBEDTLS_URL)/$(MBEDTLS_ZIP)\u0026#34; $(Q) curl -O -L $(MBEDTLS_URL)/$(MBEDTLS_ZIP) The build system can download a compressed file containing the Mbed TLS source code directly from the library\u0026rsquo;s repository. Once downloaded, this code will be unpacked into a folder and will be available to be compiled by NuttX.\nApplications and Library # Unlike the previous example, we can see that this Makefile also adds source files to the CSRS variable:\nCSRCS = $(wildcard $(MBEDTLS_UNPACKLIBDIR)$(DELIM)*.c) Source files from the library folder of the Mbed TLS are added to the CSRCS variable. In other words, files from the Mbed TLS library will be compiled even though they are not executable applications per se. The Mbed TLS library provides cryptographic APIs to other applications in the system. However, to test the library\u0026rsquo;s functionalities, the Mbed TLS repository also provides test applications, which can be activated through the configurations in apps/crypto/mbedtls/Kconfig:\n# Configuration Applications ifneq ($(CONFIG_MBEDTLS_APPS),) MODULE = $(CONFIG_MBEDTLS_APPS) ifeq ($(CONFIG_MBEDTLS_APP_BENCHMARK),y) PROGNAME += $(CONFIG_MBEDTLS_APP_BENCHMARK_PROGNAME) PRIORITY += $(CONFIG_MBEDTLS_APP_BENCHMARK_PRIORITY) STACKSIZE += $(CONFIG_MBEDTLS_APP_BENCHMARK_STACKSIZE) MAINSRC += $(MBEDTLS_UNPACKPROGDIR)/test/benchmark.c endif This portion of the Makefile compiles the Mbed TLS benchmark application if selected. Note that if CONFIG_MBEDTLS_APP_BENCHMARK=y, the source code in programs/test/benchmark.c of the library\u0026rsquo;s repository will be added to MAINSRC Similarly, the self-test application in programs/test/selftest.c can be compiled if CONFIG_MBEDTLS_APP_SELFTEST=y.\nKconfig # The Kconfig file for the Mbed TLS selects, in addition to the library version to be downloaded, the test applications that will also be compiled and configs that may be enabled in the library\u0026rsquo;s config. The full content of the Kconfig file can be found at crypto/mbedtls/Kconfig. Part of it is as follows:\nmenuconfig CRYPTO_MBEDTLS bool \u0026#34;Mbed TLS Cryptography Library\u0026#34; default n ---help--- Enable support for Mbed TLS. if CRYPTO_MBEDTLS config MBEDTLS_VERSION string \u0026#34;Mbed TLS Version\u0026#34; default \u0026#34;3.4.0\u0026#34; config MBEDTLS_DEBUG_C bool \u0026#34;This module provides debugging functions.\u0026#34; default DEBUG_FEATURES ---help--- This module provides debugging functions. config MBEDTLS_SSL_IN_CONTENT_LEN int \u0026#34;Maximum length (in bytes) of incoming plaintext fragments.\u0026#34; default 16384 ---help--- Maximum length (in bytes) of incoming plaintext fragments. config MBEDTLS_SSL_OUT_CONTENT_LEN int \u0026#34;Maximum length (in bytes) of outgoing plaintext fragments.\u0026#34; default 16384 ---help--- Maximum length (in bytes) of outgoing plaintext fragments. config MBEDTLS_SSL_SRV_C bool \u0026#34;This module is required for SSL/TLS server support.\u0026#34; default y ---help--- This module is required for SSL/TLS server support. config MBEDTLS_PLATFORM_MEMORY bool \u0026#34;Enable the memory allocation layer.\u0026#34; depends on MBEDTLS_PLATFORM_C default n config MBEDTLS_ENTROPY_HARDWARE_ALT bool \u0026#34;Uncomment this macro to let mbed TLS use your own implementation of a hardware entropy collector.\u0026#34; default n depends on DEV_RANDOM select MBEDTLS_NO_PLATFORM_ENTROPY config MBEDTLS_AES_ROM_TABLES bool \u0026#34;Store the AES tables in ROM.\u0026#34; default n config MBEDTLS_NO_PLATFORM_ENTROPY bool \u0026#34;Do not use built-in platform entropy functions.\u0026#34; default n config MBEDTLS_ECP_RESTARTABLE bool \u0026#34;Enable the restartable ECC.\u0026#34; depends on MBEDTLS_ECP_C default n config MBEDTLS_SELF_TEST bool \u0026#34;Enable the checkup functions (*_self_test).\u0026#34; default n Make.defs # Finally, the last file in the folder is Make.defs. By comparing it with the one of the Hello World! example, the Make.defs file of the Mbed TLS additionally defines the header files (.h) of the library to be used by other NuttX applications by adding the content of the mbedtls/include folder to the CFLAGS and CXXFLAGS variables of the NuttX build system:\nifneq ($(CONFIG_CRYPTO_MBEDTLS),) CONFIGURED_APPS += $(APPDIR)/crypto/mbedtls # Allows `\u0026lt;mbedtls/\u0026lt;\u0026gt;.h\u0026gt;` import. CFLAGS += ${INCDIR_PREFIX}$(APPDIR)/crypto/mbedtls/include CFLAGS += ${INCDIR_PREFIX}$(APPDIR)/crypto/mbedtls/mbedtls/include CFLAGS += ${DEFINE_PREFIX}MBEDTLS_CONFIG_FILE=\u0026#34;\u0026lt;mbedtls/mbedtls_config.h\u0026gt;\u0026#34; CXXFLAGS += ${INCDIR_PREFIX}$(APPDIR)/crypto/mbedtls/include CXXFLAGS += ${INCDIR_PREFIX}$(APPDIR)/crypto/mbedtls/mbedtls/include CXXFLAGS += ${DEFINE_PREFIX}MBEDTLS_CONFIG_FILE=\u0026#34;\u0026lt;mbedtls/mbedtls_config.h\u0026gt;\u0026#34; endif To Be Continued\u0026hellip; # The purpose of this article is to take a look into the NuttX build system. We started by showing how an application can be defined and built using the nuttx-apps (the Hello World! examples). Also, it was shown how an external library (with its testing applications) - the Mbed TLS - can be compiled for NuttX.\nA Quick Demonstration of Mbed TLS # Please check the Mbed TLS library (and its testing applications) being selected to be built for NuttX on ESP32-S3-DevKit-1 board:\nIn the following series of this article, we will port a not-yet available application to NuttX. Stay tuned for the upcoming articles in this series. Any questions, criticisms, or suggestions? Leave your comment on the page :wink:\nUseful Links # NuttX Documentation NuttX GitHub NuttX channel on Youtube Developer Mailing List ","date":"16 September 2024","externalUrl":null,"permalink":"/blog/2024/09/building-applications-on-nuttx-understanding-the-build-system/","section":"Blog","summary":"This article shows how to port and build an application form other Posix-compliant systems to NuttX.","title":"Building Applications on NuttX: Understanding the Build System","type":"blog"},{"content":"Last updated: Loading... This page lists the projects in which the ESP32-C61 is supported.\nTo show the status of features, the following icons are used:\n:white_check_mark: Supported feature :hourglass_flowing_sand: Unsupported feature (IDF-1234) \u0026quot;IDF-1234\u0026quot; indicates an internal issue reference to help us keep this list up to date :question: Support status unknown Such status issues will be checked and fixed shortly This page will be periodically updated to reflect the current support status for the ESP32-C61.\nSome links provided below might appear invalid due to being generated as placeholders for documents to be added later. ESP-IDF # The initial mass production support for ESP32-C61 has been rescheduled from ESP-IDF v5.4 to ESP-IDF v5.5.1, in line with the updated chip production plan. ESP-IDF v5.5.1 is planned for release on Augest 31, 2025.\nIn the meantime, the ESP-IDF master branch contains the latest preview support for ESP32-C61 v1.0. To start developing with v1.0 chips now, please pull the latest commits to your ESP-IDF master branch.\nThe support for earlier engineering samples \u0026ndash; ESP32-C61 v0.2 \u0026ndash; has been removed starting from commit 884e54a8. If you need to continue developing with v0.2 chips, please check out the earlier commit b1b99b30 from the master branch by running git checkout b1b99b30.\nIf you have an issue to report about any of the ESP32-C61 features, please create an issue in ESP-IDF GitHub issue tracker.\nLoading... Other Projects # If you have an issue to report about any of the ESP32-C61 features, please create an issue in the issue tracker of a respective project.\nLoading... ","date":"29 August 2024","externalUrl":null,"permalink":"/hardware/esp32c61/","section":"Hardware","summary":"","title":"ESP32-C61 status","type":"hardware"},{"content":"","date":"28 August 2024","externalUrl":null,"permalink":"/tags/community-meeting/","section":"Tags","summary":"","title":"Community Meeting","type":"tags"},{"content":"","date":"28 August 2024","externalUrl":null,"permalink":"/tags/czech-transcript-only/","section":"Tags","summary":"","title":"Czech Transcript Only","type":"tags"},{"content":" New event! Další komunitní event se blíží # Ano! Tento rok jsme se rozhodli uspořádat dva komunitní eventy. Na základě našich i Vašich zpětných vazeb chceme tento pojmout trochu jinak a dát větší prostor workshopu. Pro event jsme také zvolili nové příjemné místo, a to hned nad prostory naší české kanceláře v Bochnerově paláci v areálu Vlněny. Pokud tě baví bastlení, programování, zkrátka cokoli kolem našich ESPéček, nebo si prostě zvědavý na naše novinky a chceš si popovídat s našimi vývojáři, tohle si nesmíš nechat ujít!\nNa co se můžeš těšit: # Přednášky: Čekají tě inspirativní přednášky od vývojářů z Espressifu, lokálních firem a zapálených nadšenců do ESP! Přijď si poslechnout nejnovější trendy, tipy a triky přímo od lidí, kteří tvoří budoucnost těchto technologií.\nWorkshop: Připravili jsme pro tebe dvouhodinový praktický workshop, kde si budeš moci osahat vývoj na našem novém čipu ESP32-C6 s ESP-IDF frameworkem. Důraz bude kladen na snadný přechod od jednodušších frameworků, jako jsou Arduino nebo MicroPython. Budeš mít jedinečnou příležitost ponořit se do vývoje s podporou odborníků! Nezapomeň si vzít vlastní notebook, a pokud máš, přibal si s sebou kabel s USB-C koncovkou. O vše ostatní se postaráme my a devkit je po workshopu tvůj.\nPraktická dema: Sestrojili jsme funkční ukázky nových čipů, které nejsou jen na obdivování, ale můžeš si je rovnou sám vyzkoušet! Přijď objevit co všechno ESP dokážou.\nNetworking: Uvolněná atmosféra u pivka s lidmi, kteří sdílejí stejné nadšení! Poznej nové přátele, popovídej si s tech influencery a promluv si s našimi vývojáři. Toto je ideální příležitost navázat nové kontakty a sdílet své nápady s komunitou.\nDůležité informace: # Kdy: 18. 10. 2024 od 15:00 do 21:00 Kde: Akce proběhne v Bochnerově paláci v areálu Vlněna na adrese Přízova 3 (vstup je z vnitrobloku Vlněny) Místa jsou omezená, zajisti si to své co nejdříve ve formuláři níže! Vstup je zdarma, ale vyžaduje registraci. Tu prosím vyplň jen tehdy, pokud se opravdu chystáš přijít.\nNačítání… Podrobnější informace o akci zveřejníme brzy, takže sleduj tuto stránku a naše další kanály. Na místě bude samozřejmě zajištěno občerstvení, pivo i nealko, takže se můžeš těšit na pohodový večer plný technologií a skvělé atmosféry!\nTěšíme se na Tebe!\nTeam Espressif Systems\ngps systems ","date":"28 August 2024","externalUrl":null,"permalink":"/events/community-autumn-24-czechia-brno/","section":"Events","summary":"","title":"Meeting ESP komunity - podzimní edice 2024","type":"events"},{"content":"","date":"22 August 2024","externalUrl":null,"permalink":"/tags/diy/","section":"Tags","summary":"","title":"DIY","type":"tags"},{"content":" Introduction # For most people, one of the first tasks of the day is toothbrushing. This task is usually done by a conventional nylon toothbrush, invented in 1938 but used in different forms and materials even before.\nToday, you can easily find electronic toothbrushes and some start toothbrushes that helps you to keep track how you are brushing your tooth.\nOur goal here is not just to build a smart toothbrush, but to create a true oral health companion—one that combines cutting-edge technology with user-centric design. Through careful innovation, we aim to deliver a more comfortable, personalized dental care experience for everyday life.\nOverview of ESP-Toothbrush # The ESP-Toothbrush is a smart electric toothbrush powered by the ESP32-C2 chip from Espressif. It features a 0.96-inch LCD display with an SPI interface, displaying important information such as battery level, network connectivity, brushing time, and brushing status.\nDesigned with simplicity in mind, the ESP-Toothbrush has a single button to activate its ultrasonic motor and a buzzer for audio prompts. Additionally, it connects to Wi-Fi and integrates with ESP-RainMaker, allowing users to track detailed brushing data and configure the toothbrush via the ESP-RainMaker app on their smartphone.\nFor ease of use, the toothbrush includes a USB Type-C port for both firmware updates and charging. It also supports charging via a magnetic stylus, offering flexibility and convenience.\nBlock Diagram # The block diagram for the ESP-ToothBrush project clearly outlines the key functional components and how they interact. The main sections include:\nESP-Toothbrush Block Diagram Power Supply Modes # The ESP-ToothBrush supports two versatile power supply modes, ensuring flexibility and reliability:\n18350 Lithium Battery (Default Power Supply, Recommended): The toothbrush is primarily powered by a rechargeable 18350 lithium battery, offering portability and long-lasting use. This battery is the recommended power source due to its high energy density and suitability for compact devices like the ESP-ToothBrush.\nUSB Power Supply (via ESP32-C2 USB Interface): Alternatively, the toothbrush can be powered through its USB Type-C interface, connected directly to the ESP32-C2. This interface is not only used for power supply but also enables convenient charging of the 18350 lithium battery when connected to a USB power source, making it a dual-purpose port for both power and charging.\nDescription of Different Circuit Blocks # Battery Manager: The TP4056 chip is used for battery management, providing charging functionality while preventing over charge and over discharge. It also includes reverse connection protection. The CHRG pin is pulled up via a 10K resistor. During charging, the CHRG pin is at a low level, while in other states, it is high. The CHRG pin is connected to the ESP32-C2\u0026rsquo;s GPIO5, enabling the microcontroller to monitor the battery\u0026rsquo;s charging status by detecting the GPIO5 pin\u0026rsquo;s level.\nBattery Power Monitor: The ESP32-C2\u0026rsquo;s ADC (Analog-to-Digital Converter) operates within a range of 0–3.3V, while the 18350 lithium battery can reach up to 4.2V, which exceeds this limit. To safely measure the battery voltage, two equivalent resistors are used to divide the battery voltage. The divided voltage is read by the ESP32-C2\u0026rsquo;s ADC on GPIO4 (channel 4). The measured value is then multiplied by 2 to determine the actual battery voltage, allowing for real-time monitoring of the battery\u0026rsquo;s power level.\nLDO Voltage Regulator: The HE9073A33M5R LDO (Low Dropout) voltage regulator chip is employed to convert the lithium battery\u0026rsquo;s variable input voltage to a stable 3.3V output. This supplies power to the ESP32-C2 and its peripherals, ensuring consistent operation across different battery levels.\nLCD: A 0.96-inch LCD screen (80x160 resolution) is used to display key information such as battery level, network status, brushing time, and brushing status. The display communicates with the ESP32-C2 via an SPI interface for fast and efficient data transmission.\nMotor Driver: The ultrasonic motor is driven by the TC118S DC motor driver chip, known for its low power consumption and cost efficiency. This chip is ideal for controlling the toothbrush’s ultrasonic vibration motor with precision.\nUSB-UART Bridge: A CP2102N USB-to-UART bridge is used for programming and debugging the ESP32-C2. It interfaces via a USB Type-C port, providing a modern, high-speed connection for flashing firmware and debugging the system.\nButton: A single multifunctional button is implemented to switch between different operating modes of the toothbrush, simplifying user interaction and control.\nBuzzer: A passive buzzer is used to provide audio feedback and prompts. This component plays specific sounds to notify the user of status changes or important actions, enhancing the user experience.\nHardware Design # For each functional module of the smart toothbrush, we need to develop detailed hardware schematics. This step is crucial to ensure that every part of the circuit operates reliably and efficiently. The design process will involve careful planning of the layout for each circuit, along with the strategic selection of electronic components to optimize the performance and stability of the system.\nESP-Toothbrush Hardware Design For further guidance on the best practices and specific requirements for the ESP32-C2 and its associated components, please refer to the official ESP Hardware Design Guidelines. These guidelines provide in-depth information on layout strategies, power supply recommendations, and more to ensure the successful design and implementation of hardware projects using\nPCB Layout # Once the hardware design is complete, we focus on the precise placement of each component to ensure optimal functionality while maintaining a compact overall design. Every element is carefully positioned to maximize performance without increasing the PCB size unnecessarily. Through meticulous adjustments, we achieve a balance between functionality, efficiency, and minimal space, ensuring that all components work seamlessly together in a small form factor.\nLayout\nESP-Toothbrush PCB Layout Front\nESP-Toothbrush PCB Front Back\nESP-Toothbrush PCB Back 3D Design # To ensure the ESP-Toothbrush is both visually appealing and practical, we developed its design using 3D printing. The design process went through several iterations, refining both the form and function to create a final product that is not only ergonomic but also user-friendly.\nEach revision was aimed at enhancing both the aesthetic and practical aspects of the toothbrush, resulting in a sleek and functional device.\nESP-Toothbrush 3D Part ESP-Toothbrush 3D Model Software Implementation # After the hardware design, we focus on the software development to ensure the ESP-Toothbrush is both functional and practical for everyday use. The software integrates various individual functions, utilizing multiple resources provided by Espressif for seamless operation.\nLCD Display: To implement the LCD functionality, we used the example codes provided in the ESP-IDF examples, which cover various LCD interfaces. We also used the esp_lv_spng component to efficiently display PNG images on the LCD. The LCD Screen User Guide offers additional insights into LCD integration.\nMotor Driver and Buzzer: The motor driver and buzzer are controlled via the PWM interface. Espressif provides a LEDC example that demonstrates how to implement PWM for such applications. The LEDC Programming Guide offers further details. For controlling the buzzer, we utilized the hayschan/buzzer component to simplify the software development and achieve better sound effects.\nBattery Power Monitoring: We implemented battery voltage monitoring using the ADC interface, referring to the ADC oneshot read example. The ADC Oneshot Mode Driver Guide provides further instructions on how to read ADC data in oneshot mode.\nWi-Fi Connection: For the WiFi functionality, the ESP32-C2 is set to WiFi Station mode. You can refer to the WiFi Station example to learn how to connect to an Access Point. The WiFi Driver Guide provides additional information for setting up WiFi connections.\nESP-RainMaker Integration: For cloud control and monitoring, the ESP-Rainmaker SDK allows remote control of the toothbrush. You can directly use the ESP RainMaker component for integration, and refer to the ESP-Rainmaker Get Started Guide for detailed instructions.\nESP-Rainmaker # Now it\u0026rsquo;s time to connect the toothbrush to the ESP RainMaker.\nUI Design # In designing the ESP-Toothbrush, we prioritized the user\u0026rsquo;s experience, ensuring that every interaction with the device is intuitive and seamless. By connecting the toothbrush to the ESP-RainMaker cloud, we carefully crafted the UI of the ESP-RainMaker app to provide smooth, user-friendly control over the toothbrush’s features.\nESP-RainMaker is a lightweight IoT cloud solution that is tightly integrated with Amazon Cloud Technologies\u0026rsquo; serverless architecture. This serverless framework offers tremendous flexibility in data storage and transmission, dynamically allocating resources based on actual traffic. This design minimizes the strain on cloud storage, ensuring efficient and scalable performance as data demands grow.\nFor more information about ESP-RainMaker and its capabilities, refer to the official ESP-RainMaker Introduction.\nOn ESP-RainMaker mobile application side, following interfaces were created:\nLow battery pop-up and home screen on ESP-Rainmaker interface ESP-RainMaker Home Page Brushing time log on ESP-RainMaker interface Brushing Time Page Control interface ESP-Toothbrush Control Page Product Display # After meticulous design and extensive testing, we have successfully completed the production of the ESP-Toothbrush. The final product is a perfect blend of practicality and aesthetic appeal. Now, let’s take a moment to appreciate the sleek and functional design that brings cutting-edge technology into your daily routine.\nPlease see the video below for a closer look at the final product in action.\nBasic Functions # 3-minute regular brushing. 3-minute Regular Brushing Double click the button to switch four gear to switch the vibration intensity. Switch Modes Long press the button to power on and power off to saving power consumption. Power On Lithium battery power supply and wireless charging. Charging Feature to view the battery, time, animation, Bluetooth and Wi-Fi connect to network status through the LCD screen. LCD Dispaly Interactive Functions # Once the ESP-Toothbrush is connected to WiFi, it can be controlled via the ESP-Rainmaker app to perform the following interactive functions:\nBattery Monitoring: Monitor the battery level with a low battery reminder when below 20%. Brushing Mode Control: Switch between four vibration intensity levels. Power Control: Remotely turn the toothbrush on or off. Brushing Duration Setting: Customize the brushing duration according to user preferences. Brushing History Tracking: Record daily brushing time and duration, with data stored for up to a month. ESP-Rainmaker Controller ESP-Rainmaker Duration Conclusion # The ESP-Toothbrush combines smart technology with everyday practicality, offering a seamless and personalized dental care experience. Through careful hardware design, intuitive software integration, and interactive features, it brings convenience and innovation to oral hygiene.\nWith WiFi connectivity and ESP-Rainmaker support, users can easily control and monitor their brushing habits, making it a truly modern solution for daily care.\n","date":"22 August 2024","externalUrl":null,"permalink":"/blog/esp32c2-smart-electric-toothbrush/","section":"Blog","summary":"","title":"DIY Smart Electric Toothbrush using ESP32-C2 and RainMaker","type":"blog"},{"content":"","date":"22 August 2024","externalUrl":null,"permalink":"/tags/spi/","section":"Tags","summary":"","title":"SPI","type":"tags"},{"content":"","date":"22 August 2024","externalUrl":null,"permalink":"/tags/toothbrush/","section":"Tags","summary":"","title":"Toothbrush","type":"tags"},{"content":"The performance and memory capabilities of the microcontrollers are increasing, and so is their complexity, especially when the users are responsible for mapping external memory chips such as flash or SPIRAM by configuring a memory management unit.\nWhen I started to use Espressif ESP32’s series SoC’s with the Zephyr RTOS, quickly I realized that these SoC’s are a very different world, compared to my previous MCU experiences, which were mostly ARM-related. ARM Cortex-M’s - in most cases - uses Von-Neumann memory architecture, while the ESP32’s series of microcontrollers uses the Harvard memory architecture, which adds complexity.\nThe primary source of knowledge about any SoC was always the datasheet or Technical Reference Manual of the part. Indeed it still is, but I found the ESP32\u0026rsquo;s TRM — although very useful — quite challenging to read. Especially because there is a significant portion of important information buried in the long textual descriptions.\nThis sparked the motivation to compile a visually rich and informative depiction of crucial information from the current versions of a TRM. This is intended to be used together with the SoC’s datasheets and TRM to help better understand the internals of the ESP32\u0026rsquo;s series of SoCs internals, which is crucial during the system and driver development - for example when porting to other platforms such as Zephyr RTOS.\nESP32 # The ESP32 is the Xtensa LX6 dual-core microcontroller, and it is the oldest SoC from the ESP32’s series of SoCs.\nThe SoC has access to external flash memory using the SPI interface. It can also access the external SPIRAM, but only on the data bus.\nZephyr-RTOS support for the ESP32 devkit board can be found here.\nROM\nROM memories hold the primary bootloader code and other library functions available to the end users. The content of the ROM memories is baked during the manufacturing process and cannot be changed. Please refer to the chip versions of the ESP32 microcontroller for more detailed information. In short, please use the lastest chip revision (v3) when working with the ESP32 on Zephyr RTOS.\nSRAM\nThe ESP32 has three internal SRAM modules. The SRAM0 is 192kB, and it can be configured to use the first 64kB as MMU cache for the external memory access. When not used as a cache, the first 64kB can be read and written by either CPU from the instruction bus.\nThe capacity of Internal SRAM1 is 128 KB. Either CPU can read and write this memory using the data and instruction bus.\nThe address ranges of the instruction and the data bus are in reverse order (word-wise).\nRTC-SRAM\nRTC-Fast Memory can be read and written by PRO_CPU only, at a given address range on the data bus or at the instruction bus. Unlike most other memory regions, RTC Fast memory cannot be accessed by the APP_CPU.\nRTC-Slow memory is r/w memory that can be accessed by either CPU via the instruction and data bus.\nThe RTC memories can hold the data during the deep sleep period.\nInstruction \u0026amp; data cache\nThe instruction and data cache address space is a virtual address space where the external memories such as flash or SPIRAM modules can be accessed by the instruction or the data bus.\nInternal memories and cache address space # The ESP32 memory map.\nPeripheral registers # The ESP32 has 41 peripherals. Nearly all peripheral modules can be accessed by either CPU at the same address with a single exception of the PID controller which exists for each CPU and can be accessed only by its own CPU.\nThe ESP32 peripherals map.\ne-Fuse blocks # The eFuse memory is the OTP (one-time-programmable) memory where hardware and encryption settings are stored. Fundamentally, an eFuse is a single bit of non-volatile memory with the restriction that once an eFuse bit is programmed to 1, it can never be reverted to 0.\nThe ESP32 e-fuse map.\nFor further information and all the details about the ESP32 SoC please refer to the latest ESP32 Technical Reference Manual.\nESP32-S2 # The ESP32-S2 microcontroller is the successor of ESP32 and although very similar it has a single core and slightly different memory composition.\nOne of the improvements from ESP32 is the ability to access external SPI-ram on data and instruction buses, which means it can run programs and access the data.\nZephyr-RTOS support for the ESP32-S2 devkit board can be found here.\nROM\nROM memories hold the primary bootloader code and other library functions available to the end users. The content of the ROM memories is baked during the manufacturing process and cannot be changed.\nSRAM\nThe ESP32-S2 consists of SRAM0 which can be configured as a hardware cache to access external memories. SRAM1 is r/w memory space addressed by the CPU on the data and instruction bus in the same order.\nRTC-SRAM\nRTC-Slow memory can be accessed by the CPU via the instruction and data bus. But is also accessible via the peripheral bus 1 and 2.\nRTC-Fast is r/w memory that can be accessed by the CPU via the instruction and data bus.\nInstruction \u0026amp; data cache\nThe CPU accesses the external memories using the cache. Up to 7.5MB of address space can be accessed via the I-cache. Up to 4MB of address space can be used to access the I-Cache as read-only via the data bus. Up to 10.5MB of address space can be used to access the external flash or SPIRAM.\nInternal memories and cache address space # The ESP32 memory map.\nPeripheral registers # The peripherals on ESP32-S2 are accessed using two peripheral busses: PeriBus1 and PeriBus2. Each has its own address space at the data bus.\nThe PeriBus1 features speculative reads to improve performance. This also means that not every access is valid. Therefore we need to use the volatile statement, or access registers such as FIFOs using the PeriBus2, which is slower but safe.\nThe ESP32-S2 peripherals.\neFuse blocks # The eFuse memory consists of 4096 bits of OTP (one-time-programmable) memory where hardware and encryption settings are stored. Fundamentally, an eFuse is a single bit of non-volatile memory with the restriction that once an eFuse bit is programmed to 1, it can never be reverted to 0.\nThe ESP32-S2 e-fuse block.\nFor further information and all the details about the ESP32-S2 SoC please refer to the latest ESP32-S2 Technical Reference Manual.\nESP32-S3 # The ESP32-S3 is the latest Xtensa LX7 CPU with a dual-core design. Besides two main cores, it has two ultra-low-power coprocessors based on Risc-V architecture. The SoC has a built-in JTAG debugger accessible via a USB interface. It can access external SPIRAM on data and instruction buses, which means it can run programs and access the data.\nZephyr-RTOS support for the ESP32-S3 devkit board can be found here.\nROM\nROM memories hold the primary bootloader code and other library functions available to the end users. The content of the ROM memories is baked during the manufacturing process and cannot be changed.\nSRAM\nThere are three internal SRAM modules. The SRAM0 can be configured as an I-Cache buffer to access instructions from external memory or be used as static r/w memory via the instruction bus. SRAM1 is the r/w memory which can be accessed via the instruction and data bus. SRAM2 can be configured as D-Cache, or it can be accessed as static r/w memory via the data bus\nRTC-SRAM\nRTC-Slow is r/w memory that can be accessed via the instruction and data bus. RTC-Fast is the r/w memory that can be accessed via the instruction and data bus on a given address range.\nInstruction \u0026amp; data cache\nThe CPUs can access external memories via the cached MMU address space. Memories can be accessed using I-Cache or D-Dache via instruction or data bus respectively.\nInternal memories and cache address space # The ESP32 memory map.\nPeripheral registers # The peripherals (modules) can be accessed at their address range using the data and instruction bus. Each peripheral module has its own memory boundaries given by its base address and block size. Blocks size is usually 4kB long. For more details refer to device TRM.\nThe ESP32-S3 peripherals.\neFuse blocks # The eFuse memory consists of 4096 bits of OTP (one-time-programmable) memory where hardware and encryption settings are stored. Fundamentally, an eFuse is a single bit of non-volatile memory with the restriction that once an eFuse bit is programmed to 1, it can never be reverted to 0.\nThe ESP32-S3 e-fuse block.\nFor further information and all the details about the ESP32-S3 SoC please refer to the latest ESP32-S3 Technical Reference Manual.\nESP32-C3 # The ESP32-C3 is a 32-bit RISC-V microcontroller. The address space of ESP32-C3 is significantly simpler compared to its Xtensa counterparts. It supports JTAG debugging via the on-chip USB interface.\nZephyr-RTOS support for the ESP32-C3 devkit board can be found here.\nROM\nROM memories hold the primary bootloader code and other library functions available to the end users. The content of the ROM memories is baked during the manufacturing process and cannot be changed.\nSRAM\nThe ESP32-C3 has two SRAM modules. SRAM0 can be configured as the instruction cache buffer, or accessed as static r/w memory. The SRAM1 is a general-purpose r/w memory that can be accessed via instruction and data bus.\nRTC-SRAM\nRTC-Fast memory is r/w memory that can be accessed via CPU instruction and data bus.\nInstruction \u0026amp; data cache\nThe ESP32-C3 supports SPI, dual-SPI, quad-SPI, and QPI interfaces to access the external flash memory. It supports manual encryption and automatic decryption. The external flash can be accessed by the I-Cache or D-Cache on instruction or data bus respectively.\nInternal memories and cache address space # The ESP32-C3 memory map.\nPeripheral registers # The CPU can access the peripherals (modules) using the data or instruction bus on a given address space. Each peripheral has its own memory boundaries given by the base address and block size, which is usually 4kB. For details please refer to the TRM.\nThe ESP32-C3 peripherals.\neFuse blocks # The eFuse memory consists of 4096 bits of OTP (one-time-programmable) memory where hardware and encryption settings are stored. Fundamentally, an eFuse is a single bit of non-volatile memory with the restriction that once an eFuse bit is programmed to 1, it can never be reverted to 0.\nThe ESP32-C3 e-fuse block.\nFor further information and all the details about the ESP32-C3 SoC please refer to the latest ESP32-C3 Technical Reference Manual.\nESP32-C6 # The ESP32-C6 is a 32-bit RISC-V microcontroller with the “IMAC” extensions. The address space of ESP32-C6 is also significantly simpler compared to its Xtensa counterparts. It supports JTAG debugging via the on-chip USB interface.\nZephyr-RTOS support for the ESP32-C6 devkit board can be found here.\nROM\nROM memories hold the primary bootloader code and other library functions available to the end users. The content of the ROM memories is baked during the manufacturing process and cannot be changed.\nSRAM\nThe ESP32-C6 has two SRAM modules.\nHP-SRAM is static r/w memory that can be accessed by the HP CPU or LP CPU via the data bus or instruction bus in the same order.\nLP-SRAM is static r/w memory that can be accessed by the HP CPU or LP CPU via the data bus or instruction bus. It can be accessed using high-speed more or low-speed more.\nInstruction \u0026amp; data cache\nESP32-C6 supports SPI, dual-SPI, quad-SPI, or QPI interface to connect external flash memory. It also supports manual encryption and automatic decryption to protect user data and code.\nInternal memories and cache address space # The ESP32-C6 memory map.\nPeripheral registers # The CPU can access the peripherals (modules) using the data or instruction bus on a given address space. Each peripheral has its own memory boundaries given by the base address and block size, which is usually 4kB. For details please refer to the TRM.\nThe ESP32-C6 peripherals block.\neFuse blocks # The eFuse memory consists of 4096 bits of OTP (one-time-programmable) memory where hardware and encryption settings are stored. Fundamentally, an eFuse is a single bit of non-volatile memory with the restriction that once an eFuse bit is programmed to 1, it can never be reverted to 0.\nThe ESP32-C6 e-fuse block.\nFor further information and all the details about the ESP32-C6 SoC please refer to the latest ESP32-C6 Technical Reference Manual.\nDownloads # Printable versions of the images in PDF format can be downloaded here:\nESP32 ESP32-S2 ESP32-S3 ESP32-C3 ESP32-C6 Conclusion # Sometimes, when we need to understand something in-depth, we need to do a deep dive into very technical documents and extract the information in a way that we can use. Technical documents can be challenging to understand, especially when you are not familiar with a particular architecture or if you are not from that specific area. I hope that with this article, you will be able to easily understand the memory map of the ESP32 series of SoCs and use it as a guide when diving deep into the TRMs and datasheets.\n","date":"20 August 2024","externalUrl":null,"permalink":"/blog/2024/08/esp32-memory-map-101/","section":"Blog","summary":"This article addresses the complexity of Espressif SoCs by offering a visual, structured compilation of crucial technical data from their datasheets and TRMs. The main takeaway for the reader is a simplified, actionable understanding of the memory maps, caches, peripherals, and eFuse blocks, which is essential for low-level system and driver development.","title":"ESP32's family Memory Map 101","type":"blog"},{"content":"","date":"20 August 2024","externalUrl":null,"permalink":"/tags/memory/","section":"Tags","summary":"","title":"Memory","type":"tags"},{"content":"ESP-NOW is a connectionless Wi-Fi communication protocol developed by Espressif for its microcontrollers. It allows for efficient, low-power, and low-latency peer-to-peer communication. This article will guide you through the essentials of using the new ESP-NOW library included in Arduino 3.0.0, from basic setup to advanced features.\nWhat is ESP-NOW? # ESP-NOW enables direct communication between multiple devices without needing a router, ideal for applications requiring real-time data transfer with minimal delay. Key features include:\nLow Latency: Real-time data transfer. Low Power Consumption: Suitable for battery-powered devices. Peer-to-Peer Communication: Direct device-to-device communication. Scalability: Supports multiple peers in a network. Security: Built-in encryption for secure data transfer. The ESP-NOW protocol model. Source: Espressif.\nSome examples of applications that can benefit from ESP-NOW include home automation, sensor networks, remote control systems, and IoT devices. The project ESP-Drone, for example, uses ESP-NOW to provide a low-latency and reliable connection.\nGetting Started with ESP-NOW in Arduino # To use ESP-NOW with Arduino, you need:\nAny ESP32 board supported by Arduino with Wi-Fi capabilities (note that the H series chips are not supported as they lack Wi-Fi); Arduino IDE installed on your computer; Arduino Core for ESP32 installed (v3.0.0 or later). If you still haven\u0026rsquo;t installed the Arduino Core for ESP32, you can do so by following the steps in the official documentation.\nNote that this guide focuses on the new ESP-NOW library and assumes you are familiar with Arduino/C++ programming and the ESP32 platform.\nBasic ESP-NOW Setup # The ESP-NOW library in Arduino provides a set of classes and functions to simplify the setup and management of ESP-NOW communication. The library includes classes for handling peers, sending and receiving data, and managing the ESP-NOW network.\nThe basic setup for ESP-NOW involves creating a custom class that inherits from the ESP_NOW_Peer class to handle the communication with a peer device. This class will define the send and receive callbacks and manage the ESP-NOW communication.\nAfter creating the custom class, you can create an instance of it passing the MAC address of the peer device, the Wi-Fi channel, the Wi-Fi interface, and the Local Master Key (LMK). Then, you can call the ESP_NOW.begin() and add() methods to initialize the ESP-NOW communication and register the peer device. Finally, you can use the send() method to send data to the peer device and the onReceive() method to handle received data.\nBe sure to check the ESP-NOW Library Documentation for detailed information on the classes and methods available in the ESP-NOW library.\nLet\u0026rsquo;s show the capabilities of the ESP-NOW library with some examples.\nTwo-Device Communication # flowchart LR A[/Terminal/] \u003c--\u003e|Serial| B[Device 1] B\u003c-....-\u003e|ESP-NOW| C C[Device 2] \u003c--\u003e|Serial| D[/Terminal/] Let\u0026rsquo;s start with the basics by sending and receiving data between two devices using ESP-NOW. This example is based on the ESP_NOW_Serial sketch provided by the ESP-NOW library. You can find it in the Arduino IDE under File \u0026gt; Examples \u0026gt; ESP_NOW \u0026gt; ESP_NOW_Serial.\nNormally, you would need to set up an ESP-NOW peer class and define the send and receive callbacks. However, for communication between only two devices, the ESP_NOW_Serial_Class is provided to simplify the setup process. To use this class, you need to include the ESP32_NOW_Serial.h header file.\nWe can create a new instance of the ESP_NOW_Serial_Class and use it to send and receive data. Let\u0026rsquo;s create a basic sketch to demonstrate this.\n#include \u0026#34;ESP32_NOW_Serial.h\u0026#34; #include \u0026#34;MacAddress.h\u0026#34; #include \u0026#34;WiFi.h\u0026#34; #include \u0026#34;esp_wifi.h\u0026#34; #define ESPNOW_WIFI_CHANNEL 1 // WiFi channel to be used by ESP-NOW. The available channels will depend on your region. #define ESPNOW_WIFI_MODE WIFI_STA // WiFi mode to be used by ESP-NOW. Any mode can be used. #define ESPNOW_WIFI_IF WIFI_IF_STA // WiFi interface to be used by ESP-NOW. Any interface can be used. // Set the MAC address of the peer device to communicate with. // Change this for each device when uploading the code. // For example: F4:12:FA:40:64:4C const MacAddress peer_mac({0xF4, 0x12, 0xFA, 0x40, 0x64, 0x4C}); // Create an instance of the ESP-NOW Serial Class. Parameters: peer MAC address, WiFi channel, WiFi interface. ESP_NOW_Serial_Class NowSerial(peer_mac, ESPNOW_WIFI_CHANNEL, ESPNOW_WIFI_IF); void setup() { // Start the Serial Monitor Serial.begin(115200); while (!Serial) { delay(10); } // Set the WiFi to the mode and channel to be used by ESP-NOW Serial.println(\u0026#34;Setting up WiFi...\u0026#34;); WiFi.mode(ESPNOW_WIFI_MODE); WiFi.setChannel(ESPNOW_WIFI_CHANNEL, WIFI_SECOND_CHAN_NONE); // Wait for the WiFi to start while (!WiFi.STA.started()) { delay(100); } // Print the MAC address of this device Serial.print(\u0026#34;MAC Address: \u0026#34;); Serial.println(WiFi.macAddress()); // Start the ESP-NOW communication Serial.println(\u0026#34;ESP-NOW communication starting...\u0026#34;); NowSerial.begin(115200); Serial.println(\u0026#34;You can now send data to the peer device using the Serial Monitor.\\n\u0026#34;); } void loop() { // Read data received from the peer device and print it to the Serial Monitor if available while (NowSerial.available()) { Serial.write(NowSerial.read()); } // Send data received from the Serial Monitor to the peer device if available while (Serial.available() \u0026amp;\u0026amp; NowSerial.availableForWrite()) { if (NowSerial.write(Serial.read()) \u0026lt;= 0) { Serial.println(\u0026#34;Failed to send data\u0026#34;); break; } } delay(1); } Using our newly created object NowSerial, we can send and receive data between the two devices. The ESP_NOW_Serial_Class handles the setup and communication details, making it easier to work with ESP-NOW.\nAny data sent from the Serial Monitor will be transmitted to the peer device, and any data received from the peer device will be printed to the Serial Monitor.\nTo properly test this example, you need to upload the code to two ESP32 devices, each with the MAC address of the other device set in the peer_mac variable.\nThe data received can be properly displayed in the Serial Monitor of the Arduino IDE by selecting Both NL \u0026amp; CR as the line ending.\nAfter loading the code to both devices, you can open the Serial Monitor for each device and start sending data between them.\nFor example:\nDevice 1: Device 2: Broadcasting Data # To broadcast data to multiple devices, you can use the broadcast address FF:FF:FF:FF:FF:FF. This address will send data to all devices in the network. This address is available as ESP_NOW.BROADCAST_ADDR in the ESP-NOW library to simplify its use.\nflowchart TB A[Broadcaster 1] -...-\u003e|ESP-NOW| C[Receiver] B[Broadcaster 2] -...-\u003e|ESP-NOW| C[Receiver] C --\u003e D[/Terminal/] The following examples are based, respectively, on the ESP-NOW Broadcast Master and ESP-NOW Broadcast Slave sketches provided by the ESP-NOW library. You can find them in the Arduino IDE under the File \u0026gt; Examples \u0026gt; ESP_NOW sub-menu.\nBroadcaster Device # To demonstrate broadcasting, let\u0026rsquo;s create a new example using a custom class to handle the ESP-NOW communication. First let\u0026rsquo;s create a new class called ESP_NOW_Broadcast_Peer that will handle the setup and communication details. It will be used by the broadcaster device to send data to all receiver devices.\n#include \u0026#34;ESP32_NOW.h\u0026#34; #include \u0026#34;WiFi.h\u0026#34; /* Definitions */ #define ESPNOW_WIFI_CHANNEL 6 /* Classes */ // Creating a new class that inherits from the ESP_NOW_Peer class is required. class ESP_NOW_Broadcast_Peer : public ESP_NOW_Peer { public: // Constructor of the class using the broadcast address // The ESP_NOW_Peer constructor expects the following parameters: // MAC address of the peer device, the WiFi channel, the WiFi interface, and the Local Master Key (LMK). // In this case, the MAC address will be the broadcast address. ESP_NOW_Broadcast_Peer(uint8_t channel, wifi_interface_t iface, const uint8_t *lmk) : ESP_NOW_Peer(ESP_NOW.BROADCAST_ADDR, channel, iface, lmk) {} // Destructor of the class ~ESP_NOW_Broadcast_Peer() { remove(); // Remove the peer from the ESP-NOW network (list of peers). // Method from the ESP_NOW_Peer class. } // Function to properly initialize the ESP-NOW and register the broadcast peer bool begin() { // The ESP-NOW communication must be started before adding the peer by calling ESP_NOW.begin(). // The add() method from the ESP_NOW_Peer class is used to register the peer in the ESP-NOW network. if (!ESP_NOW.begin() || !add()) { log_e(\u0026#34;Failed to initialize ESP-NOW or register the broadcast peer\u0026#34;); return false; } return true; } // Function to send a message to all devices within the network bool send_message(const uint8_t *data, size_t len) { if (!send(data, len)) { // The send(const uint8_t *data, size_t len) method from the ESP_NOW_Peer class is used to send data to the peer. log_e(\u0026#34;Failed to broadcast message\u0026#34;); return false; } return true; } // We will use the default onReceive() and onSent() methods from the ESP_NOW_Peer class. // These methods are called when a message is received or sent, respectively. }; To use this class, we need to create an instance of it and call the begin() method to initialize the ESP-NOW communication and register the broadcast peer. Then, we can use the send_message() method to broadcast data to all devices in the network. Let\u0026rsquo;s finish the example by creating the setup and loop functions for the broadcaster device.\n/* Global Variables */ // Message counter uint32_t msg_count = 0; // Create a broadcast peer object ESP_NOW_Broadcast_Peer broadcast_peer(ESPNOW_WIFI_CHANNEL, WIFI_IF_STA, NULL); /* Main */ void setup() { // Start the Serial Monitor Serial.begin(115200); while (!Serial) { delay(10); } // Initialize the Wi-Fi module WiFi.mode(WIFI_STA); WiFi.setChannel(ESPNOW_WIFI_CHANNEL); while (!WiFi.STA.started()) { delay(100); } Serial.println(\u0026#34;ESP-NOW Example - Broadcaster\u0026#34;); Serial.println(\u0026#34;Wi-Fi parameters:\u0026#34;); Serial.println(\u0026#34; Mode: STA\u0026#34;); Serial.println(\u0026#34; MAC Address: \u0026#34; + WiFi.macAddress()); Serial.printf(\u0026#34; Channel: %d\\n\u0026#34;, ESPNOW_WIFI_CHANNEL); // Register the broadcast peer if (!broadcast_peer.begin()) { Serial.println(\u0026#34;Failed to initialize broadcast peer\u0026#34;); Serial.println(\u0026#34;Reebooting in 5 seconds...\u0026#34;); delay(5000); ESP.restart(); } Serial.println(\u0026#34;Setup complete. Broadcasting messages every 5 seconds.\u0026#34;); } void loop() { char data[32]; // Create a message with a counter snprintf(data, sizeof(data), \u0026#34;Hello, World! #%lu\u0026#34;, msg_count++); Serial.printf(\u0026#34;Broadcasting message: %s\\n\u0026#34;, data); // Send the message to all devices if (!broadcast_peer.send_message((uint8_t *)data, sizeof(data))) { Serial.println(\u0026#34;Failed to broadcast message\u0026#34;); } // Wait 5 seconds before broadcasting the next message delay(5000); } After uploading the code to the broadcaster device, you can create a similar code for the receiver devices. The receiver devices will obtain the messages from the broadcaster device.\nReceiver Device # The receiver device will acquire the messages from the broadcaster devices. If a new broadcaster device is added to the network, the receiver device will automatically register it as a peer and start receiving messages. We can create a similar class to handle the ESP-NOW communication for the receiver device.\n#include \u0026#34;ESP32_NOW.h\u0026#34; #include \u0026#34;WiFi.h\u0026#34; #include \u0026lt;esp_mac.h\u0026gt; // For the MAC2STR and MACSTR macros #include \u0026lt;vector\u0026gt; /* Definitions */ #define ESPNOW_WIFI_CHANNEL 6 /* Classes */ // Creating a new class that inherits from the ESP_NOW_Peer class is required. class ESP_NOW_Peer_Class : public ESP_NOW_Peer { public: // Constructor of the class. Note that the MAC address of peer is not the broadcast address. // The ESP_NOW_Peer constructor expects the following parameters: // MAC address of the peer device, the WiFi channel, the WiFi interface, and the Local Master Key (LMK). ESP_NOW_Peer_Class(const uint8_t *mac_addr, uint8_t channel, wifi_interface_t iface, const uint8_t *lmk) : ESP_NOW_Peer(mac_addr, channel, iface, lmk) {} // Destructor of the class ~ESP_NOW_Peer_Class() { // We will avoid the remove() method here to avoid accidentally removing the peer in the new broadcaster callback. // If needed, the remove() method can be called explicitly. // In this case, the peer will be removed when the receiver device is turned off. } // Function to register the new broadcaster peer bool add_peer() { if (!add()) { // The add() method from the ESP_NOW_Peer class is used to register the peer in the ESP-NOW network. log_e(\u0026#34;Failed to register the broadcast peer\u0026#34;); return false; } return true; } // Function to print the received messages from the broadcaster // The default onReceive() method from the ESP_NOW_Peer will be overridden to handle the received messages. void onReceive(const uint8_t *data, size_t len, bool broadcast) { // addr() method from the ESP_NOW_Peer class is used to get the MAC address of the current peer. Serial.printf(\u0026#34;Received a message from broadcaster \u0026#34; MACSTR \u0026#34; (%s)\\n\u0026#34;, MAC2STR(addr()), broadcast ? \u0026#34;broadcast\u0026#34; : \u0026#34;unicast\u0026#34;); Serial.printf(\u0026#34; Message: %s\\n\u0026#34;, (char *)data); } // We will use the default onSent() method from the ESP_NOW_Peer class. }; We will also need a place to store the peers that will be added to the network and a callback function to handle the addition of unknown peers. Let\u0026rsquo;s create them.\n/* Global Variables */ // List of all the broadcasters. It will be populated when a new broadcaster is registered std::vector\u0026lt;ESP_NOW_Peer_Class\u0026gt; broadcasters; /* Callbacks */ // Callback called when an unknown peer sends a message // The callback for registering new peers must have the following signature: // void (*)(const esp_now_recv_info_t *info, const uint8_t *data, int len, void *arg) // The info parameter contains information about the received message, such as the MAC addresses of the sender and receiver. // The data parameter contains the message data. // The len parameter contains the length of the message data. // The arg parameter is an optional argument that can be passed to the callback. void register_new_broadcaster(const esp_now_recv_info_t *info, const uint8_t *data, int len, void *arg) { if (memcmp(info-\u0026gt;des_addr, ESP_NOW.BROADCAST_ADDR, 6) == 0) { // Check if the message was sent to the broadcast address Serial.printf(\u0026#34;Unknown peer \u0026#34; MACSTR \u0026#34; sent a broadcast message\\n\u0026#34;, MAC2STR(info-\u0026gt;src_addr)); Serial.println(\u0026#34;Registering the peer as a broadcaster\u0026#34;); // Create a new broadcaster object // This auxiliary object will be destroyed after the callback execution. // That\u0026#39;s why we avoid the use of remove() in the destructor of the ESP_NOW_Peer_Class. ESP_NOW_Peer_Class new_broadcaster(info-\u0026gt;src_addr, ESPNOW_WIFI_CHANNEL, WIFI_IF_STA, NULL); // Add the new broadcaster to the list of broadcasters broadcasters.push_back(new_broadcaster); // Register the new broadcaster in the ESP-NOW network if (!broadcasters.back().add_peer()) { Serial.println(\u0026#34;Failed to register the new broadcaster\u0026#34;); return; } } else { // The receiver will only receive broadcast messages log_v(\u0026#34;Received a unicast message from \u0026#34; MACSTR, MAC2STR(info-\u0026gt;src_addr)); log_v(\u0026#34;Igorning the message\u0026#34;); } } Now, we can create the setup and loop functions for the receiver device. Note that, as we are already using the onReceive() method from the ESP_NOW_Peer_Class to handle the received messages, we don\u0026rsquo;t need to do anything in the loop function.\nvoid setup() { // Start the Serial Monitor Serial.begin(115200); while (!Serial) { delay(10); } // Initialize the Wi-Fi module WiFi.mode(WIFI_STA); WiFi.setChannel(ESPNOW_WIFI_CHANNEL); while (!WiFi.STA.started()) { delay(100); } Serial.println(\u0026#34;ESP-NOW Example - Receiver\u0026#34;); Serial.println(\u0026#34;Wi-Fi parameters:\u0026#34;); Serial.println(\u0026#34; Mode: STA\u0026#34;); Serial.println(\u0026#34; MAC Address: \u0026#34; + WiFi.macAddress()); Serial.printf(\u0026#34; Channel: %d\\n\u0026#34;, ESPNOW_WIFI_CHANNEL); // Initialize the ESP-NOW protocol if (!ESP_NOW.begin()) { Serial.println(\u0026#34;Failed to initialize ESP-NOW\u0026#34;); Serial.println(\u0026#34;Reeboting in 5 seconds...\u0026#34;); delay(5000); ESP.restart(); } // Register the new peer callback that we created before // The NULL parameter is an optional argument that can be passed to the callback. ESP_NOW.onNewPeer(register_new_broadcaster, NULL); Serial.println(\u0026#34;Setup complete. Waiting for a broadcast message...\u0026#34;); } void loop() { delay(1000); // Delay to avoid watchdog reset } After uploading the code to the receiver device, you can start the broadcaster device. The receiver device will automatically register the broadcaster device and start receiving the messages.\nFor example:\nBroadcaster Device: Receiver Device: As you can see, the receiver device automatically registers the broadcaster device and starts receiving the messages. If you add more broadcaster devices to the network, the receiver device will also register them and start receiving their messages. This way, you can easily create a network of devices using ESP-NOW.\nThis example was based on the ESP_NOW_Broadcast_Master and ESP_NOW_Broadcast_Slave examples provided in the ESP-NOW library. You can find them in the Arduino IDE under File \u0026gt; Examples \u0026gt; ESP_NOW.\nAdvanced Examples # To create more complex applications using ESP-NOW, you can explore the advanced examples provided in the ESP-NOW library. These examples demonstrate how to create a network of devices, send and receive data between multiple devices, handle different types of messages, add encryption to the communication, automatically decide the role of the device in the network without hardcoding it, and more.\nAs the code for these examples is more extensive, we recommend checking the commented code directly in the Arduino IDE under File \u0026gt; Examples \u0026gt; ESP_NOW. You can find sketches, such as ESP_NOW_Network, that highlight many of the previously mentioned features.\nNetwork of Devices # Let\u0026rsquo;s briefly demonstrate the ESP_NOW_Network example. Its aim is to demonstrate how to create a more complex network of devices using the ESP-NOW protocol.\nFirst, all devices will be set up ESP-NOW with cryptography enabled and define a master device that will manage the network.\nThe main device will receive the data from the secondary devices and print it to the Serial Monitor. From time to time, the main device will calculate the average of the data of the secondary devices and send it to all the secondary devices.\nThe secondary devices will broadcast random data to the master device every 5 seconds and, from time to time, they will ping the other secondary devices with a \u0026ldquo;Hello!\u0026rdquo; message.\nflowchart LR A[Master Device] B[Device 2] C[Device 3] A \u003c-...-\u003e|ESP-NOW| B A \u003c-...-\u003e|ESP-NOW| C B \u003c-..-\u003e C Here is the output of the example running on three devices:\nDevice 1 (Master): Device 2: Device 3: Conclusion # ESP-NOW is a powerful protocol that enhances the capabilities of ESP32 microcontrollers. By following this guide, you can leverage the new ESP-NOW library in Arduino to create efficient and reliable communication networks for your projects. Experiment with the examples provided, explore advanced features, and unlock the full potential of the ESP32 SoCs with ESP-NOW in your wireless applications.\nWith ESP-NOW, you can create low-latency, low-power, and secure peer-to-peer communication networks for a wide range of applications, from home automation to IoT devices. Start exploring the possibilities of ESP-NOW in your projects today!\nAdditional Resources # Arduino Core for ESP32 ESP-NOW Library Documentation ESP-NOW Broadcast Master Example ESP-NOW Broadcast Slave Example ESP-NOW Network Example ESP-NOW Serial Example ","date":"6 August 2024","externalUrl":null,"permalink":"/blog/2024/08/arduino-esp-now-lib/","section":"Blog","summary":"This article presents information on how to use ESP-NOW with the Arduino core for Espressif devices.","title":"Using ESP-NOW in Arduino","type":"blog"},{"content":"","date":"31 July 2024","externalUrl":null,"permalink":"/authors/cheah-hao-yi/","section":"Developer Portal Authors","summary":"","title":"Cheah Hao Yi","type":"authors"},{"content":"[If you have been following the Espressif blogs and announcements, you must already be aware of ESP RainMaker and its various features. If not, please check out the info here so that you get an idea about what ESP RainMaker is before you proceed further.]\nAdmin users in ESP RainMaker can look at some basic node data like type, model, firmware version, etc. and push OTA firmware upgrades. They can view additional diagnostics data if linked with ESP Insights. However, there was no way for them to send some data to the nodes. The set params operations were available to only end users.\nThe command — response framework introduced in ESP RainMaker now provides a new way to communicate with the nodes. It is available to admin as well as end users (both, primary and secondary). It also provides better access control on node side and allows more reliable communication with explicit error reporting from the firmware.\nWorkflow # A high level workflow is shown here:\nTo explain in short,\nClient generates request payload and sends to cloud. Cloud assigns it a request id and returns it back to the client, which can then be used to track the status. The request is forwarded to the node right away if it is online or is sent later if the node is offline at that time. The response of the node is tracked against the request id so that the status can be queried by the client. You can read more about the specifications here.\nAdvantages # This new framework enables many new use cases and workflows\nOne of the key advantages is that it allows admins to send some data or commands to the nodes, which was earlier not possible. Moreover, on the firmware side, you can specify which type of users (admin, primary, secondary user) should have access to the commands, giving better access control. Eg. You may allow admins and secondary users to reboot a device, but only primary users will be able to reset the Wi-Fi. You can let only primary users to create schedules, but not admins or secondary users.\nAnother major advantage is that you can trigger a command even when a node is offline. This allows to push certain configurations and other information at any time and let the nodes get them whenever they come back online.\nThe framework not only provides reliable information about delivery of commands to a node, but also lets users check the status (Eg. request timed out, value out of bounds, operation not permitted, etc.)\nWe hope that this new framework will unlock new use cases and workflows. Do give this a try by looking into the docs and let us know if you find this useful. Command-response sample usage is also available in the led_light example\n","date":"31 July 2024","externalUrl":null,"permalink":"/blog/command-response-framework-in-esp-rainmaker/","section":"Blog","summary":"","title":"Command — Response Framework in ESP RainMaker","type":"blog"},{"content":" Learning Objectives # This tutorial is an introduction to how to develop applications with ESP-IDF and an Espressif development board, in our case ESP32-C3-DevKitM-1.\nNote: The tutorial is compatible with any Espressif SoCs. Just be mindful during the setup process that the commands might differ slightly for other SoCs. The differences will be highlighted in this tutorial. By the end of this tutorial, we will be able to:\nHave general understanding of how ESP-IDF works Able to set up ESP-IDF Able to run a simple program on an Espressif SoC Recommended prerequisite # This tutorial serves as the foundation of all the other tutorials using Espressif SoCs, such as the ESP32, hence no prerequisite knowledge is required for this tutorial.\nIntroduction # ESP-IDF is Espressif\u0026rsquo;s official IoT Development Framework for most of the Espressif SoCs. It provides a self-sufficient SDK for any generic application development on Espressif SoCs.\nThe primary programming language used in ESP-IDF is C. Also, there is support for C++ and R that will be described in other guides.\nRequirements # Hardware:\nComputer running Windows, Linux, or macOS ESP32-C3-DevKitM-1 development board USB cable (data + power) compatible with your development board Software\nESP-IDF version 5.2.2 Step-by-step Guide # Step 1: Install relevant drivers (Windows only) # The first step in running application on an Espressif SoC is to ensure that the computer is able to recognize and communicate with the SoCs. If you use Windows, this involves installing the relevant driver.\nNote: For Linux and MacOS computer, this step is not necessary. Kindly proceed to Step 2\n1.1 Connect the SoC # Let\u0026rsquo;s first check if the computer can recognize your SoC.\nConnect the USB cable to your Espressif SoC and open up the Device Manager. (Window\u0026rsquo;s Icon \u0026gt; Search for \u0026ldquo;Device Manager\u0026rdquo;)\nUnder Other devices, there is an entry called CP2102N USB to UART Bridge Controller with a warning icon, this is normal. This implies that the computer is unable to communicate with the SoC just yet. Hence it is necessary to install the driver.\n1.2 Get the driver files # Navigate to CP210x USB to UART Driver page.\nUnder the Downloads tab, select the CP210x Universal Windows Driver, this will download the drivers in a zip file.\nNavigate to the downloaded zip file, and unzip it.\n1.3 Install the driver # Go back to the Device Manager, right click on the \u0026ldquo;CP2102N USB to UART Bridge Controller\u0026rdquo;, and click update driver.\nNext, as the driver files have been downloaded and extracted, select the option \u0026ldquo;Browse my computer for drivers\u0026rdquo;\nNext, select the top level driver file (CP210x_Universal_Windows_Driver) and click next.\nThe driver will be installed and you should see the following message.\nClose the pop up. In the device manager, we can see that the entry for the SoC is now updated. It should appear as below.\nThe entry will specify which COM Port number is connected to the SoC. Try to disconnect and reconnect to double-check the port number.\nTake note of which COM Port the Espressif SoC is connected to. This will be important when uploading the application in the later steps. The port can differ across different computers. For the rest of this guide, COMx will refer to the COM port that the Espressif SoC is connected to.\nStep 2: Install the ESP-IDF # Navigate to the ESP-IDF Programming Guide. Under Manual Installation, select the guide that corresponds to your operating system.\nFor Linux and macOS # In the ESP-IDF Getting Started guide, complete Step 1. Install Prerequisites to Step 4. Set up the Environment Variables. We will continue on the running the blink example in the next step.\nFor Windows # Under the installation guide for Windows, as shown in the image below, select Windows Installer Download, then Online Universal Installer, and run the executable file.\nFollow through with the installation step, the installation can be customized if needed (for example: select another destination for installation)\nOnce the command prompt icon is available on the desktop screen, we will have the necessary application to program the Espressif SoC!\nStep 3: Learn ESP-IDF file hierarchy # For Linux and macOS # Open the terminal and navigate to the ESP-IDF directory (should be located at ~/esp if you didn\u0026rsquo;t change the settings proposed in the installation guide).\nFor Windows # Click on the ESP-IDF terminal icon (either one is fine).\nThe output above is normal, the terminal is setting up the environment necessary to develop on the SoC.\n3.1 Listing the IDF # For this section of the guide, we will be showing the output using the Windows terminal. There shouldn\u0026rsquo;t be much difference for Linux and macOS.\nOn the Windows terminal, run dir. (ls for Linux and macOS user), below is the expected output.\nAs you can see, the folders here repeat the folders in the ESP-IDF Github repository.\n3.2 Go to the project directory # We will be running the blink example, which is located under examples \u0026gt; get-started \u0026gt; blink.\nRun cd examples\\get-started\\blink to change directory into the blink project. Listing the directory will show the following output:\nFor an overview of the components in the project directory, see the explanation here.\nStep 4: Run the blink example # We will now go through the workflow for uploading and running a sample project.\n4.1 Set the target SoC # We will first configure the IDF such that the project will be build for the specific target (SoC) that we have.\nFor this example, we are using an ESP32-C3-DevKitM-1. Hence, in the terminal, run idf.py set-target esp32c3\nNote: Remember to change the argument for set-target according to the hardware available!\nFor example, if an ESP32-S3 development board is used, you need to run idf.py set-target esp32s3 instead.\nIt is important to set the chips now to avoid encountering errors while uploading the binaries to the SoC.\nFor more information on target selection, see here\n4.2 Build the binaries # Next, we need to build our blink example project to get a binary.\nIn the terminal, go to the root of your project directory (in this case, the blink folder), and run idf.py build.\nAll the relevant source code and dependencies will compile at this stage. Pay attention to the line Project build complete. To flash, run this command: near the end of the output.\nAt this stage, any syntatic errors or dependencies errors will be flagged out by the compiler if the build fails. The build stage will compile the source code into an executable program for the Espressif SoCs.\nFor more information on the build command, see here\n4.3 Upload the binaries to the Espressif SoC # Next, we will upload the binaries to the Espressif SoC.\nIn the terminal, run idf.py -p COMx flash\nNote: Windows: Please enter the COM Port number available from the device manager in step 1.3. For this example, the COM port used is COM11, but the COM Port number might be different across devices.\nNote: Linux and macOS users should replace COMx with the serial port to which the board is connected. The serial ports have the following naming patterns.\nLinux: starting with /dev/tty macOS: starting with /dev/cu If the flashing is successful, the following should be observed:\n4.4 View the console output of the Espressif SoC # To view the serial monitor:\nWindows: run idf.py -p COMx monitor Linux: run idf.py -p /dev/ttyx monitor macOS: run idf.py -p /dev/cu.x monitor For the above, x refer to the serial port connected to the Espressif SoC. Try to disconnect and reconnect to double-check the port number.\nFor Windows: check the port number via the Device Manager\nFor Linux: run ls /dev/tty* to list the serial ports\nFor macOS: run ls /dev/cu.* to list the serial ports\nFor the blink example, the output should correspond to the LED blinking on the Espressif SoC.\nTo exit from the serial monitor, the key combination is Ctrl + ].\nQuick tip: the commands can be run in sucession such as idf.py build flash monitor\nCode Reference # Here is a brief overview of the example code under blink/main/blink_example_main.c\nvoid app_main(void) { /* Configure the peripheral according to the LED type */ configure_led(); while (1) { ESP_LOGI(TAG, \u0026#34;Turning the LED %s!\u0026#34;, s_led_state == true ? \u0026#34;ON\u0026#34; : \u0026#34;OFF\u0026#34;); blink_led(); /* Toggle the LED state */ s_led_state = !s_led_state; vTaskDelay(CONFIG_BLINK_PERIOD / portTICK_PERIOD_MS); } } void app_main(void)\nThis is the main entry point of the project.\nconfigure_led()\nThis is a function that initializes the hardware required to blink the LED.\nConclusion # Throughout this guide, we\u0026rsquo;ve explored the capabilities of the Espressif IoT Development Framework (ESP-IDF) and the Espressif SoCs.\nWe\u0026rsquo;ve delved into the installation of the VCP driver. We\u0026rsquo;ve also installed ESP-IDF\u0026rsquo;s prerequisites using the ESP-IDF Tools installer. Moreover, we explored the ESP-IDF environment, where we walked through the different steps in building, uploading, and running a simple application on an Espressif development board!\nBy following this guide, we have gained a deeper understanding of the Espressif SoCs and ESP-IDF, and how they can be leveraged to build efficient and powerful IoT applications. We hope this knowledge serves as a solid foundation for any future project with the Espressif hardware!\nFeel free to explore the other examples available in ESP-IDF and explore what Espressif SoCs can offer! Also, check out various solutions offered by Espressif to build even more impressive projects!\nIf you would like to understand more about how ESP-IDF is structured and how to build even more robust applications with it, feel free to check out the Espressif Developer Conference 2023 Talk on the topic here.\nError \u0026amp; Troubleshooting # Here are some common errors:\nError 1: Gibberish output during monitor # Some may encounter random garbage output after running idf.py monitor To resolve: Exit the monitor Run idf.py menuconfig Select Component Config \u0026gt; Hardware Settings \u0026gt; Main XTAL Config \u0026gt; Main XTAL Frequency Set CONFIG_XTAL_FREQ_SEL to 26 MHz Build and flash the application again. Some other errors are also described in the ESP-IDF Programming Guide.\nReferences # References: ESP-IDF Programming Guide ESP-IDF Github Repository Espressif Developer Conference 2023: ESP-IDF Getting Started ","date":"31 July 2024","externalUrl":null,"permalink":"/blog/getting-started-with-esp-idf/","section":"Blog","summary":"","title":"Getting Started With ESP-IDF","type":"blog"},{"content":" Learning Objectives # In this tutorial, we will be exploring how to connect an Espressif SoC to a Wi-Fi Access Point (AP) using ESP-IDF.\nBy the end of this tutorial, you will be able to:\nUnderstand the background of the Wi-Fi technology Understand the necessary component needed to enable Wi-Fi connection Set up a simple Wi-Fi connection with the Espressif Soc Able to implement Wi-Fi connections from scratch on ESP-IDF Recommended prerequisite # The ESP-IDF framework is used extensively for this tutorial, hence it is important to have the framework installed and to have some basic familiarity with it.\nTo install and get started with ESP-IDF, kindly refer to the tutorial here.\nIntroduction # Wi-Fi technology, short for Wireless Fidelity, is a method of wirelessly connecting devices to the internet and to each other through a local area network (LAN). It uses radio waves to provide high-speed internet and network connections to a wide array of devices, including smartphones, laptops, tablets, and IoT gadgets.\nWi-Fi has revolutionized how we access information and communicate, enabling seamless internet connectivity without the need for physical cables. As a cornerstone of modern communication, Wi-Fi continues to evolve, bringing faster speeds, greater reliability, and enhanced security features to meet the ever-growing demands of digital connectivity.\nEspressif offers various series of SoCs that provides Wi-Fi functionalities. From ESP32-S3 that supports Wi-Fi 4 to ESP32-C6 that supports Wi-Fi 6, there are many options available to integrate Espressif products into projects that builds on Wi-Fi technology.\nIf you would to like to understand the operating mechanism and various configuration options specified for the Wi-Fi technology, do feel free to consult Chapter 7 of the ESP32-C3 Wireless Adventure book written by Espressif Engineers! We have also prepared the documentation on the ESP32 Wi-Fi Driver where it describes in-depth on the principles of using the Wi-Fi APis.\nRequired hardware # Computer running Windows, Linux, or macOS ESP32-C3-DevKitM-1 development board USB cable (data + power) compatible with your development board Other compatible hardware includes:\nESP32-S Series SoCs ESP32-C Series SoCs ESP32 Series SoCs Wi-Fi technology is not supported on the following SoC Series.\nESP32-P Series SoCs ESP32-H Series SoCs For more information about what wireless technology is supported by Espressif products, you can consult the ESP Product Selector.\nRequired software # This tutorial will be using the following software:\nESP-IDF version 5.2.2 Step-by-step Guide # For this tutorial, we will be establishing Wi-Fi connection on the Espressif SoC via 2 methods:\nUsing the simplified helper function example_connect() (more on this function here) Using the Wi-Fi APIs Comparison between the 2 methods:\nexample_connect() allows user to easily integrate the Wi-Fi functionality without worrying about the details of the Wi-Fi APIs, which allows for quick prototying with the Espressif SoC. The Wi-Fi APIs allow user to have finer controls over the behaviour of the Wi-Fi functionality on the Espressif SoC, this includes beacon interval, Channel Switch Announcement Count, FTM Responder mode, and more. This is more appropriate for developing larger and more complex applications. Part 1: Using the example_connect() function # Step 1: Set up the project # For Linux and macOS user: remember to set up the ESP-IDF environment in the terminal session where idf.py is used! This can be done with the command . $HOME/esp/esp-idf/export.sh.\nRefer here for more information on the set up of environment variables for ESP-IDF. It is recommended to create an alias to set up ESP-IDF.\nWe need to create a new empty ESP-IDF project. Let\u0026rsquo;s name the project simple_connect. For this, we can run:\nidf.py create-project simple_connect This command creates a minimal blank ESP-IDF project, with the following structure\n├── CMakeLists.txt # Build configuration declaring entire project ├── main # Contains project source code │ ├── CMakeLists.txt # File that registers the main component │ └── simple_connect.c # Contains the main entry point of the program └── README.md # File to describe the project A brief overview of the files created:\nTop-level simple_connect/CMakeLists.txt: this file sets project-wide CMake variable and integrate the project with the rest of the build system. main directory: this directory contains the source code of the project. Project-level main/CMakeLists.txt: this file sets the variable definition to control the build process of the project. simple_connect.c : this file contain the main entry point of the program, app_main(). We will write our source code here. To understand how an ESP-IDF project is structured, see here. For the list of available commands in the idf.py command-line tool, see here.\nStep 2: Add dependencies # First, go to the root of your project directory (in this case, the simple_connect folder), and run idf.py create-manifest\nThis would create a manifest file (main/idf_component.yml) that defines the dependencies of the project. For more information regarding dependencies and component management in ESP-IDF, see here\nAdd the protocol_examples_common dependency in idf_component.yml with the following:\ndependencies: protocol_examples_common: path: ${IDF_PATH}/examples/common_components/protocol_examples_common Step 3: Set up the target SoC # We need to configure the ESP-IDF to build the project for the specifc target (SoC) used.\nAt the root of the project directory, run idf.py set-target esp32XX\nNote: esp32XX refers to the target SoC used. For this example, we are using an ESP32-C3-DevKitM-1, hence we run the command idf.py set-target esp32c3.\nA full list of supported targets in your version of ESP-IDF can be seen by running idf.py --list-targets.\nStep 4: Edit Wi-FI credentials # To edit Wi-Fi credentials, do the following (also see the asciinema video below):\nOpen the ESP-IDF project configuration tool by running idf.py menuconfig Go to Example Connection Configuration, and update WiFi SSID and WiFi Password to your respective values QuickTip:\nPress Enter to save the changes to the SSID and Password Press S to save all the changes made Press Q to quit from the project configuration tool Step 5: Edit the source code # Now, let us write a simple program that connects to the Wi-Fi acccess point, then shortly after disconnects from the Wi-Fi access point. The complete code to be placed in main/simple_connect.c can be found here, and below some explanations are provided.\nHeader files and Macros\nWe\u0026rsquo;ll include the following files and define some macros\n#include \u0026#34;esp_log.h\u0026#34; #include \u0026#34;nvs_flash.h\u0026#34; #include \u0026#34;esp_netif.h\u0026#34; #include \u0026#34;esp_event.h\u0026#34; #include \u0026#34;protocol_examples_common.h\u0026#34; #include \u0026#34;esp_wifi.h\u0026#34; #define TAG \u0026#34;simple_connect_example\u0026#34; System Initalization\nBefore we utilize any resources for Wi-Fi connections, some initialization steps are required.\n// System initialization ESP_ERROR_CHECK(nvs_flash_init()); ESP_ERROR_CHECK(esp_netif_init()); ESP_ERROR_CHECK(esp_event_loop_create_default()); Explanation:\nnvs_flash_init() : Initializes the Non-Volatile-Storage (NVS) partition in flash, which allows user to store (a small amount of) information needed across reboots. Some common FAQs regarding the NVS are addressed here esp_netif_int(): Initialize the network interface (netif), which is the underlying TCP/IP stack. esp_event_loop_create_default(): Creates a default event loop to allow components to declare events so that other components can register handlers. Connecting and Disconnecting from Wi-Fi\nThe functions to connect and disconnect from Wi-Fi are simply:\nESP_ERROR_CHECK(example_connect()); ESP_ERROR_CHECK(example_disconnect()); Print Access Point information\nAfter stablishing a Wi-Fi connection, we can print out some information about the AP with the following functions.\n// Print out Access Point Information wifi_ap_record_t ap_info; ESP_ERROR_CHECK(esp_wifi_sta_get_ap_info(\u0026amp;ap_info)); ESP_LOGI(TAG, \u0026#34;--- Access Point Information ---\u0026#34;); ESP_LOG_BUFFER_HEX(\u0026#34;MAC Address\u0026#34;, ap_info.bssid, sizeof(ap_info.bssid)); ESP_LOG_BUFFER_CHAR(\u0026#34;SSID\u0026#34;, ap_info.ssid, sizeof(ap_info.ssid)); ESP_LOGI(TAG, \u0026#34;Primary Channel: %d\u0026#34;, ap_info.primary); ESP_LOGI(TAG, \u0026#34;RSSI: %d\u0026#34;, ap_info.rssi); The documentation on wifi_ap_record_t and esp_wifi_sta_get_ap_info() can be found here. It is useful to take a look at the ESP Logging Library too!\nStep 6: Run the application # The full source code for this example can be found here.\nOnce we are done writing the source code in simple_connect.c, we can build the binaries and flash them onto the Espressif SoC.\nThis can be done with the following commands:\nBuilding the binaries: idf.py build Flashing the binaries onto the Espressif SoC: idf.py flash Reading the output from the serial port: idf.py monitor The source code provided will output the following on the terminal: The example_connect() provides a good starting point for establishing Wi-Fi connection on the Espressif SoC.\nIn the next section, we will look at how to write full Wi-Fi handling code that is more robust, configurable and is able to deal with various error conditions.\nPart 2: Using the Wi-Fi APIs # The example_connect() function provides us with a simple method to establish a Wi-Fi connection. However, for developing real applications or more complex projects, it is worth the time and effort to write more robust Wi-Fi code.\nIn this section, we will go through the various components of the Wi-Fi driver and APIs, then build the Wi-Fi code from scratch.\nFor additional examples, feel free to refer to the following sources:\nESP-IDF Example Connect Implementation ESP-IDF Wi-Fi Station example ESP32-C3 IoT book chapter on Wi-Fi configuration Step 1: Set up the project # Let\u0026rsquo;s create another empty ESP-IDF project and call it wifi_tutorial. For this, we can run:\nidf.py create-project wifi_tutorial\nStep 2: Add files to the project # For this example, let\u0026rsquo;s demonstrate how to add more header and source code files in an ESP-IDF project.\nIn the main folder, create a header file named tutorial.h and another file named tutorial.c. The project will be structured as such:\n├── CMakeLists.txt ├── main │ ├── CMakeLists.txt │ └── wifi_tutorial.c # Source file that contains the entry point │ └── tutorial.c # Create this source file │ └── tutorial.h # Create this header file └── README.md We need to edit main/CMakeLists.txt so that the files added will be included in the build process. For more information about the ESP-IDF build system, you can refer to this document.\nInclude the folowing in main/CMakeLists.txt\nidf_component_register(SRCS \u0026#34;tutorial.c\u0026#34; \u0026#34;wifi_tutorial.c\u0026#34; INCLUDE_DIRS \u0026#34;.\u0026#34;) In the main/tutorial.h file, we will first declare the following functions:\n#pragma once #include \u0026#34;esp_err.h\u0026#34; #include \u0026#34;esp_log.h\u0026#34; #include \u0026#34;nvs_flash.h\u0026#34; #include \u0026#34;esp_event.h\u0026#34; #include \u0026#34;esp_wifi.h\u0026#34; #include \u0026#34;freertos/FreeRTOS.h\u0026#34; esp_err_t tutorial_init(void); esp_err_t tutorial_connect(char* wifi_ssid, char* wifi_password); esp_err_t tutorial_disconnect(void); esp_err_t tutorial_deinit(void); In the subsequent sections, we will go in detail through the steps of properly setting up, connecting, and terminating a Wi-Fi connection in the Espressif SoC.\nStep 3: Wi-Fi initialization # We will first define the various headers, macros, and static variables in tutorial.c needed for the initialization step.\nIn tutorial.c, we first define the following:\n// tutorial.c #include \u0026#34;tutorial.h\u0026#34; #include \u0026lt;inttypes.h\u0026gt; #include \u0026lt;string.h\u0026gt; #include \u0026#34;freertos/event_groups.h\u0026#34; #define TAG \u0026#34;tutorial\u0026#34; #define WIFI_AUTHMODE WIFI_AUTH_WPA2_PSK #define WIFI_CONNECTED_BIT BIT0 #define WIFI_FAIL_BIT BIT1 static const int WIFI_RETRY_ATTEMPT = 3; static int wifi_retry_count = 0; static esp_netif_t *tutorial_netif = NULL; static esp_event_handler_instance_t ip_event_handler; static esp_event_handler_instance_t wifi_event_handler; static EventGroupHandle_t s_wifi_event_group = NULL; In tutorial_init(), we will initialize the hardware and interface needed to set up Wi-FI as shown below:\nesp_err_t tutorial_init(void) { // Initialize Non-Volatile Storage (NVS) esp_err_t ret = nvs_flash_init(); if (ret == ESP_ERR_NVS_NO_FREE_PAGES || ret == ESP_ERR_NVS_NEW_VERSION_FOUND) { ESP_ERROR_CHECK(nvs_flash_erase()); ret = nvs_flash_init(); } s_wifi_event_group = xEventGroupCreate(); ret = esp_netif_init(); if (ret != ESP_OK) { ESP_LOGE(TAG, \u0026#34;Failed to initialize TCP/IP network stack\u0026#34;); return ret; } ret = esp_event_loop_create_default(); if (ret != ESP_OK) { ESP_LOGE(TAG, \u0026#34;Failed to create default event loop\u0026#34;); return ret; } ret = esp_wifi_set_default_wifi_sta_handlers(); if (ret != ESP_OK) { ESP_LOGE(TAG, \u0026#34;Failed to set default handlers\u0026#34;); return ret; } tutorial_netif = esp_netif_create_default_wifi_sta(); if (tutorial_netif == NULL) { ESP_LOGE(TAG, \u0026#34;Failed to create default WiFi STA interface\u0026#34;); return ESP_FAIL; } // Wi-Fi stack configuration parameters wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT(); ESP_ERROR_CHECK(esp_wifi_init(\u0026amp;cfg)); ESP_ERROR_CHECK(esp_event_handler_instance_register(WIFI_EVENT, ESP_EVENT_ANY_ID, \u0026amp;wifi_event_cb, NULL, \u0026amp;wifi_event_handler)); ESP_ERROR_CHECK(esp_event_handler_instance_register(IP_EVENT, ESP_EVENT_ANY_ID, \u0026amp;ip_event_cb, NULL, \u0026amp;ip_event_handler)); return ret; } In particular, we can notice that the initialization step is similar to the previous example that uses example_connect(). Furthermore, there are additional initialization steps, such as defining the event loop, registering the event handler, and creating the network interface. The documentation for these additional steps can be found here:\nEvent Loop Library Event Handler Netif (Network Interface) In this tutorial, we also use Event Bits to indicate what Wi-Fi event has occurred. The details on Event Bits and Event Groups can be found here.\nStep 4: Wi-Fi configuration and connection # To establish a Wi-Fi connection, we can configure the type of connection, security level and hardware mode using the following method:\nesp_err_t tutorial_connect(char* wifi_ssid, char* wifi_password) { wifi_config_t wifi_config = { .sta = { // this sets the weakest authmode accepted in fast scan mode (default) .threshold.authmode = WIFI_AUTHMODE, }, }; strncpy((char*)wifi_config.sta.ssid, wifi_ssid, sizeof(wifi_config.sta.ssid)); strncpy((char*)wifi_config.sta.password, wifi_password, sizeof(wifi_config.sta.password)); ESP_ERROR_CHECK(esp_wifi_set_ps(WIFI_PS_NONE)); // default is WIFI_PS_MIN_MODEM ESP_ERROR_CHECK(esp_wifi_set_storage(WIFI_STORAGE_RAM)); // default is WIFI_STORAGE_FLASH ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_STA)); ESP_ERROR_CHECK(esp_wifi_set_config(WIFI_IF_STA, \u0026amp;wifi_config)); ESP_LOGI(TAG, \u0026#34;Connecting to Wi-Fi network: %s\u0026#34;, wifi_config.sta.ssid); ESP_ERROR_CHECK(esp_wifi_start()); EventBits_t bits = xEventGroupWaitBits(s_wifi_event_group, WIFI_CONNECTED_BIT | WIFI_FAIL_BIT, pdFALSE, pdFALSE, portMAX_DELAY); if (bits \u0026amp; WIFI_CONNECTED_BIT) { ESP_LOGI(TAG, \u0026#34;Connected to Wi-Fi network: %s\u0026#34;, wifi_config.sta.ssid); return ESP_OK; } else if (bits \u0026amp; WIFI_FAIL_BIT) { ESP_LOGE(TAG, \u0026#34;Failed to connect to Wi-Fi network: %s\u0026#34;, wifi_config.sta.ssid); return ESP_FAIL; } ESP_LOGE(TAG, \u0026#34;Unexpected Wi-Fi error\u0026#34;); return ESP_FAIL; } We can configure the Wi-Fi connection via wifi_config_t. To set up a Wi-Fi station on an Espressif SoC, we will need to configure the fields in wifi_sta_config_t. Here are some fields that are commonly configured:\nwifi_config.ssid : The SSID of target AP wifi_config.password : The password of target AP wifi_config.scan_method: Method of AP discovery wifi_config.threshold.authmode : The weakest authentication mode required to accept the Wi-Fi connection. The documentation for STA configuration can be found here. The relative strength of authmodes and the configuration options for each of the field in the Wi-Fi config can be found in esp_wifi_types_generic.h here\nWe can also configure the hardware resources allocated for managing Wi-Fi. For instance, we disable any power saving mode using esp_wifi_set_ps() in this tutorial to maximize reception and transmission of Wi-Fi data packets. However, there are some scenarios require that we set a specific power safe type, such as those requiring power saving modes and RF coexistence.\nNote that xEventGroupWaitBits() in the code above is a blocking process that waits until one of the bits are set by the event handlers. The documentation can be found here.\nSome familiarity with FreeRTOS concepts will be helpful to understand the behaviour of the program, refer to the documentation here. For advanced use cases, it is possible to run the Wi-Fi routine as a RTOS task to avoid it from blocking the rest of the application while waiting for a Wi-Fi connection to be established.\nEvent Handler for Wi-FI and IP events\nFor this example, we created simple event handlers to log events related to Wi-Fi (defined under wifi_event_t) or IP layer (defined under ip_event_t).\nThe important notable events in establishing Wi-Fi are:\nWIFI_EVENT_STA_START : The configuration for STA is completed WIFI_EVENT_STA_CONNECTED : The STA managed to establish a connection with the Wi-Fi Access Point WIFI_EVENT_STA_DISCONNECTED: The STA lost a connection with an AP or timeout IP_EVENT_STA_GOT_IP: The Espressif SoC received an IP address assigned by the AP, the Wi-Fi connection is complete. Step 5: Wi-Fi shutdown and cleanup # To disconnect from Wi-Fi, we can simply call the Wi-Fi APIs in the following sequence:\nesp_wifi_disconnect() esp_wifi_stop() esp_wifi_deinit() We will need to clear the driver, network interface and unregister the event handlers as well.\nHence, tutorial_disconnect() and tutorial_deinit() are implemented as follows:\nesp_err_t tutorial_disconnect(void) { if (s_wifi_event_group) { vEventGroupDelete(s_wifi_event_group); } return esp_wifi_disconnect(); } esp_err_t tutorial_deinit(void) { esp_err_t ret = esp_wifi_stop(); if (ret == ESP_ERR_WIFI_NOT_INIT) { ESP_LOGE(TAG, \u0026#34;Wi-Fi stack not initialized\u0026#34;); return ret; } ESP_ERROR_CHECK(esp_wifi_deinit()); ESP_ERROR_CHECK(esp_wifi_clear_default_wifi_driver_and_handlers(tutorial_netif)); esp_netif_destroy(tutorial_netif); ESP_ERROR_CHECK(esp_event_handler_instance_unregister(IP_EVENT, ESP_EVENT_ANY_ID, ip_event_handler)); ESP_ERROR_CHECK(esp_event_handler_instance_unregister(WIFI_EVENT, ESP_EVENT_ANY_ID, wifi_event_handler)); return ESP_OK; } Step 6: Put everything together # We have finished implementing the Wi-Fi connection according to the desired configuration. To demonstrate the Wi-Fi functionality, we will do the following:\nInitialization Establish Wi-Fi connection Once connection is established, print out information about the Access Point Terminate Wi-Fi connection Release the resources used for Wi-Fi connection We encourage you to code out wifi_tutorial.c without referring to the answer! The complete code snippet can be found in the next section.\nHere is a demonstration of the tutorial:\nCode Reference # Part 1: Using the example_connect() function # // simple_connect.c #include \u0026lt;stdio.h\u0026gt; #include \u0026#34;esp_log.h\u0026#34; #include \u0026#34;nvs_flash.h\u0026#34; #include \u0026#34;esp_netif.h\u0026#34; #include \u0026#34;esp_event.h\u0026#34; #include \u0026#34;protocol_examples_common.h\u0026#34; #include \u0026#34;esp_wifi.h\u0026#34; #define TAG \u0026#34;simple_connect_example\u0026#34; void app_main(void) { ESP_LOGI(TAG, \u0026#34;Hello from ESP32!\u0026#34;); // System initialization ESP_ERROR_CHECK(nvs_flash_init()); ESP_ERROR_CHECK(esp_netif_init()); ESP_ERROR_CHECK(esp_event_loop_create_default()); // Establish Wi-Fi connection ESP_ERROR_CHECK(example_connect()); // Print out Access Point Information wifi_ap_record_t ap_info; ESP_ERROR_CHECK(esp_wifi_sta_get_ap_info(\u0026amp;ap_info)); ESP_LOGI(TAG, \u0026#34;--- Access Point Information ---\u0026#34;); ESP_LOG_BUFFER_HEX(\u0026#34;MAC Address\u0026#34;, ap_info.bssid, sizeof(ap_info.bssid)); ESP_LOG_BUFFER_CHAR(\u0026#34;SSID\u0026#34;, ap_info.ssid, sizeof(ap_info.ssid)); ESP_LOGI(TAG, \u0026#34;Primary Channel: %d\u0026#34;, ap_info.primary); ESP_LOGI(TAG, \u0026#34;RSSI: %d\u0026#34;, ap_info.rssi); // Disconnect from Wi-Fi ESP_ERROR_CHECK(example_disconnect()); } Part 2: Using the Wi-Fi APIs # // tutorial.h #pragma once #include \u0026#34;esp_err.h\u0026#34; #include \u0026#34;esp_log.h\u0026#34; #include \u0026#34;nvs_flash.h\u0026#34; #include \u0026#34;esp_event.h\u0026#34; #include \u0026#34;esp_wifi.h\u0026#34; #include \u0026#34;freertos/FreeRTOS.h\u0026#34; esp_err_t tutorial_init(void); esp_err_t tutorial_connect(char* wifi_ssid, char* wifi_password); esp_err_t tutorial_disconnect(void); esp_err_t tutorial_deinit(void); // tutorial.c #include \u0026#34;tutorial.h\u0026#34; #include \u0026lt;inttypes.h\u0026gt; #include \u0026lt;string.h\u0026gt; #include \u0026#34;freertos/event_groups.h\u0026#34; #define TAG \u0026#34;tutorial\u0026#34; #define WIFI_AUTHMODE WIFI_AUTH_WPA2_PSK #define WIFI_CONNECTED_BIT BIT0 #define WIFI_FAIL_BIT BIT1 static const int WIFI_RETRY_ATTEMPT = 3; static int wifi_retry_count = 0; static esp_netif_t *tutorial_netif = NULL; static esp_event_handler_instance_t ip_event_handler; static esp_event_handler_instance_t wifi_event_handler; static EventGroupHandle_t s_wifi_event_group = NULL; static void ip_event_cb(void *arg, esp_event_base_t event_base, int32_t event_id, void *event_data) { ESP_LOGI(TAG, \u0026#34;Handling IP event, event code 0x%\u0026#34; PRIx32, event_id); switch (event_id) { case (IP_EVENT_STA_GOT_IP): ip_event_got_ip_t *event_ip = (ip_event_got_ip_t *)event_data; ESP_LOGI(TAG, \u0026#34;Got IP: \u0026#34; IPSTR, IP2STR(\u0026amp;event_ip-\u0026gt;ip_info.ip)); wifi_retry_count = 0; xEventGroupSetBits(s_wifi_event_group, WIFI_CONNECTED_BIT); break; case (IP_EVENT_STA_LOST_IP): ESP_LOGI(TAG, \u0026#34;Lost IP\u0026#34;); break; case (IP_EVENT_GOT_IP6): ip_event_got_ip6_t *event_ip6 = (ip_event_got_ip6_t *)event_data; ESP_LOGI(TAG, \u0026#34;Got IPv6: \u0026#34; IPV6STR, IPV62STR(event_ip6-\u0026gt;ip6_info.ip)); wifi_retry_count = 0; xEventGroupSetBits(s_wifi_event_group, WIFI_CONNECTED_BIT); break; default: ESP_LOGI(TAG, \u0026#34;IP event not handled\u0026#34;); break; } } static void wifi_event_cb(void *arg, esp_event_base_t event_base, int32_t event_id, void *event_data) { ESP_LOGI(TAG, \u0026#34;Handling Wi-Fi event, event code 0x%\u0026#34; PRIx32, event_id); switch (event_id) { case (WIFI_EVENT_WIFI_READY): ESP_LOGI(TAG, \u0026#34;Wi-Fi ready\u0026#34;); break; case (WIFI_EVENT_SCAN_DONE): ESP_LOGI(TAG, \u0026#34;Wi-Fi scan done\u0026#34;); break; case (WIFI_EVENT_STA_START): ESP_LOGI(TAG, \u0026#34;Wi-Fi started, connecting to AP...\u0026#34;); esp_wifi_connect(); break; case (WIFI_EVENT_STA_STOP): ESP_LOGI(TAG, \u0026#34;Wi-Fi stopped\u0026#34;); break; case (WIFI_EVENT_STA_CONNECTED): ESP_LOGI(TAG, \u0026#34;Wi-Fi connected\u0026#34;); break; case (WIFI_EVENT_STA_DISCONNECTED): ESP_LOGI(TAG, \u0026#34;Wi-Fi disconnected\u0026#34;); if (wifi_retry_count \u0026lt; WIFI_RETRY_ATTEMPT) { ESP_LOGI(TAG, \u0026#34;Retrying to connect to Wi-Fi network...\u0026#34;); esp_wifi_connect(); wifi_retry_count++; } else { ESP_LOGI(TAG, \u0026#34;Failed to connect to Wi-Fi network\u0026#34;); xEventGroupSetBits(s_wifi_event_group, WIFI_FAIL_BIT); } break; case (WIFI_EVENT_STA_AUTHMODE_CHANGE): ESP_LOGI(TAG, \u0026#34;Wi-Fi authmode changed\u0026#34;); break; default: ESP_LOGI(TAG, \u0026#34;Wi-Fi event not handled\u0026#34;); break; } } esp_err_t tutorial_init(void) { // Initialize Non-Volatile Storage (NVS) esp_err_t ret = nvs_flash_init(); if (ret == ESP_ERR_NVS_NO_FREE_PAGES || ret == ESP_ERR_NVS_NEW_VERSION_FOUND) { ESP_ERROR_CHECK(nvs_flash_erase()); ret = nvs_flash_init(); } s_wifi_event_group = xEventGroupCreate(); ret = esp_netif_init(); if (ret != ESP_OK) { ESP_LOGE(TAG, \u0026#34;Failed to initialize TCP/IP network stack\u0026#34;); return ret; } ret = esp_event_loop_create_default(); if (ret != ESP_OK) { ESP_LOGE(TAG, \u0026#34;Failed to create default event loop\u0026#34;); return ret; } ret = esp_wifi_set_default_wifi_sta_handlers(); if (ret != ESP_OK) { ESP_LOGE(TAG, \u0026#34;Failed to set default handlers\u0026#34;); return ret; } tutorial_netif = esp_netif_create_default_wifi_sta(); if (tutorial_netif == NULL) { ESP_LOGE(TAG, \u0026#34;Failed to create default WiFi STA interface\u0026#34;); return ESP_FAIL; } // Wi-Fi stack configuration parameters wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT(); ESP_ERROR_CHECK(esp_wifi_init(\u0026amp;cfg)); ESP_ERROR_CHECK(esp_event_handler_instance_register(WIFI_EVENT, ESP_EVENT_ANY_ID, \u0026amp;wifi_event_cb, NULL, \u0026amp;wifi_event_handler)); ESP_ERROR_CHECK(esp_event_handler_instance_register(IP_EVENT, ESP_EVENT_ANY_ID, \u0026amp;ip_event_cb, NULL, \u0026amp;ip_event_handler)); return ret; } esp_err_t tutorial_connect(char* wifi_ssid, char* wifi_password) { wifi_config_t wifi_config = { .sta = { // this sets the weakest authmode accepted in fast scan mode (default) .threshold.authmode = WIFI_AUTHMODE, }, }; strncpy((char*)wifi_config.sta.ssid, wifi_ssid, sizeof(wifi_config.sta.ssid)); strncpy((char*)wifi_config.sta.password, wifi_password, sizeof(wifi_config.sta.password)); ESP_ERROR_CHECK(esp_wifi_set_ps(WIFI_PS_NONE)); // default is WIFI_PS_MIN_MODEM ESP_ERROR_CHECK(esp_wifi_set_storage(WIFI_STORAGE_RAM)); // default is WIFI_STORAGE_FLASH ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_STA)); ESP_ERROR_CHECK(esp_wifi_set_config(WIFI_IF_STA, \u0026amp;wifi_config)); ESP_LOGI(TAG, \u0026#34;Connecting to Wi-Fi network: %s\u0026#34;, wifi_config.sta.ssid); ESP_ERROR_CHECK(esp_wifi_start()); EventBits_t bits = xEventGroupWaitBits(s_wifi_event_group, WIFI_CONNECTED_BIT | WIFI_FAIL_BIT, pdFALSE, pdFALSE, portMAX_DELAY); if (bits \u0026amp; WIFI_CONNECTED_BIT) { ESP_LOGI(TAG, \u0026#34;Connected to Wi-Fi network: %s\u0026#34;, wifi_config.sta.ssid); return ESP_OK; } else if (bits \u0026amp; WIFI_FAIL_BIT) { ESP_LOGE(TAG, \u0026#34;Failed to connect to Wi-Fi network: %s\u0026#34;, wifi_config.sta.ssid); return ESP_FAIL; } ESP_LOGE(TAG, \u0026#34;Unexpected Wi-Fi error\u0026#34;); return ESP_FAIL; } esp_err_t tutorial_disconnect(void) { if (s_wifi_event_group) { vEventGroupDelete(s_wifi_event_group); } return esp_wifi_disconnect(); } esp_err_t tutorial_deinit(void) { esp_err_t ret = esp_wifi_stop(); if (ret == ESP_ERR_WIFI_NOT_INIT) { ESP_LOGE(TAG, \u0026#34;Wi-Fi stack not initialized\u0026#34;); return ret; } ESP_ERROR_CHECK(esp_wifi_deinit()); ESP_ERROR_CHECK(esp_wifi_clear_default_wifi_driver_and_handlers(tutorial_netif)); esp_netif_destroy(tutorial_netif); ESP_ERROR_CHECK(esp_event_handler_instance_unregister(IP_EVENT, ESP_EVENT_ANY_ID, ip_event_handler)); ESP_ERROR_CHECK(esp_event_handler_instance_unregister(WIFI_EVENT, ESP_EVENT_ANY_ID, wifi_event_handler)); return ESP_OK; } // wifi_tutorial.c #include \u0026lt;stdio.h\u0026gt; #include \u0026#34;esp_log.h\u0026#34; #include \u0026#34;esp_wifi.h\u0026#34; #include \u0026#34;tutorial.h\u0026#34; #include \u0026#34;freertos/task.h\u0026#34; #define TAG \u0026#34;main\u0026#34; // Enter the Wi-Fi credentials here #define WIFI_SSID \u0026#34;SSID\u0026#34; #define WIFI_PASSWORD \u0026#34;PASSWORD\u0026#34; void app_main(void) { ESP_LOGI(TAG, \u0026#34;Starting tutorial...\u0026#34;); ESP_ERROR_CHECK(tutorial_init()); esp_err_t ret = tutorial_connect(WIFI_SSID, WIFI_PASSWORD); if (ret != ESP_OK) { ESP_LOGE(TAG, \u0026#34;Failed to connect to Wi-Fi network\u0026#34;); } wifi_ap_record_t ap_info; ret = esp_wifi_sta_get_ap_info(\u0026amp;ap_info); if (ret == ESP_ERR_WIFI_CONN) { ESP_LOGE(TAG, \u0026#34;Wi-Fi station interface not initialized\u0026#34;); } else if (ret == ESP_ERR_WIFI_NOT_CONNECT) { ESP_LOGE(TAG, \u0026#34;Wi-Fi station is not connected\u0026#34;); } else { ESP_LOGI(TAG, \u0026#34;--- Access Point Information ---\u0026#34;); ESP_LOG_BUFFER_HEX(\u0026#34;MAC Address\u0026#34;, ap_info.bssid, sizeof(ap_info.bssid)); ESP_LOG_BUFFER_CHAR(\u0026#34;SSID\u0026#34;, ap_info.ssid, sizeof(ap_info.ssid)); ESP_LOGI(TAG, \u0026#34;Primary Channel: %d\u0026#34;, ap_info.primary); ESP_LOGI(TAG, \u0026#34;RSSI: %d\u0026#34;, ap_info.rssi); ESP_LOGI(TAG, \u0026#34;Disconnecting in 5 seconds...\u0026#34;); vTaskDelay(pdMS_TO_TICKS(5000)); } ESP_ERROR_CHECK(tutorial_disconnect()); ESP_ERROR_CHECK(tutorial_deinit()); ESP_LOGI(TAG, \u0026#34;End of tutorial...\u0026#34;); } Conclusion # In this tutorial, we learned various ways to establish a basic Wi-Fi connection from our Espressif Soc to an Access Point.\nWe delved into the intricacies of initializing the resources needed for the Wi-Fi capabilities on the Espressif Soc, where we explored the sequence of steps in detail needed for a robust configuration.\nTo gain a better understanding of the Wi-Fi capabilities on Espressif Soc, we invite you to experiment with different Wi-Fi configurations, such as WPA3 or DPP. We hope that this tutorial has given you the necessary tools to explore them!\nEspressif SoCs have so much more to offer! Do feel free to explore the other networking examples such as bluetooth or zigbee or build further with protocol examples on ESP-IDF!\nError \u0026amp; Troubleshooting # Here are some common errors:\nError 1: Missing header file for simple connect example # /home/haoyi/esp/simple_connect/main/main.c:3:10: fatal error: protocol_examples_common.h: No such file or directory 3 | #include \u0026#34;protocol_examples_common.h\u0026#34; | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~ compilation terminated. ninja: build stopped: subcommand failed. Ensure that the dependency path in idf_component.yml is correct. Then run idf.py fullclean and build again by running idf.py build Error 2: NVS not initialized # ESP_ERROR_CHECK failed: esp_err_t 0x1101 (ESP_ERR_NVS_NOT_INITIALIZED) at 0x42008226 file: \u0026#34;/IDF/examples/common_components/protocol_examples_common/wifi_connect.c\u0026#34; line 138 func: example_wifi_start expression: esp_wifi_init(\u0026amp;cfg) abort() was called at PC 0x40385c3b on core 0 Call nvs_flash_init() before calling example_connect() Error 3: Fail to initialize Wi-Fi due to invalid state # I (487) phy_init: phy_version 1110,9c20f0a,Jul 27 2023,10:42:54 I (527) wifi:mode : sta (48:27:e2:b5:5c:64) I (527) wifi:enable tsf E (527) wifi:failed to post WiFi event=2 ret=259 ESP_ERROR_CHECK failed: esp_err_t 0x103 (ESP_ERR_INVALID_STATE) at 0x420089ec file: \u0026#34;/IDF/examples/common_components/protocol_examples_common/wifi_connect.c\u0026#34; line 183 func: example_wifi_sta_do_connect expression: esp_event_handler_register(WIFI_EVENT, WIFI_EVENT_STA_DISCONNECTED, \u0026amp;example_handler_on_wifi_disconnect, NULL) abort() was called at PC 0x40386345 on core 0 Call esp_netif_init() and esp_event_loop_create_default() before calling example_connect() References # References: The ESP Journal: Leveraging Wi-Fi 6 Features for IoT Applications ESP32-C3 Wireless Adventure: A Comprehensive Guide to IoT Espressif Wi-Fi Driver Documentation Espressif Wi-Fi APIs References ","date":"31 July 2024","externalUrl":null,"permalink":"/blog/getting-started-with-wifi-on-esp-idf/","section":"Blog","summary":"","title":"Getting Started with Wi-Fi on ESP-IDF","type":"blog"},{"content":"Security is one of the most important aspects of any IoT system and at Espressif, we take it very seriously. The ESP RainMaker platform offers a secure way to onboard a device onto Wi-Fi network and then control and monitor it through cloud. However, the security of the hardware itself is also critical for the overall system to be secure. Espressif MCUs come with various security features like secure boot, flash encryption, etc.\nThe secure boot feature is especially important as it allows only authorised firmware to run on the MCUs. ESP IDF has made enabling secure boot very easy. However, managing the secure boot keys is still the developer’s responsibility. Some questions that commonly come up for our customers include:\nHow to generate the secure boot key? Where to store the key securely, is it stored on the developer’s machine or a server? How to protect the key from leakage? What if our engineers leave the organisation? How do I know which key is programmed on a device, so I don’t accidentally upgrade with the incorrect keys? How to manage a fleet of devices with similar firmware but different secure boot keys? The recent addition of “Secure Signing” feature in ESP RainMaker addresses all its concerns. It offers a way to\ngenerate and manage keys simplify signing bootloader and firmware images before device manufacturing supports transparently “Auto Signing” before deploying OTA firmware upgrades Auto Sign for OTA # The auto-signing feature in ESP RainMaker allows developers to just upload their unsigned firmware to ESP RainMaker, and deploy an OTA firmware upgrade. The ESP RainMaker backend transparently handles the signing with the correct keys during OTA firmware upgrades.\nIf your fleet includes devices that use distinct keys for key verification, ESP RainMaker will ensure that the correctly signed firmware goes to the right device.\nThe developer no more needs to keep track of the keys (or should even have the visibility of the keys), making the fleet management simpler.\nAdditionally, since the key management is handled in the cloud, this decouples the development activity from the device-management activity, providing better role based separation.\nKey Management # The secure boot signing keys are created and maintained in the cloud with ESP RainMaker. The private key itself is not accessible to the user but can be used only for signing requests. On private deployments, RainMaker uses a FIPS compliant HSM for added security. Access control, for who can trigger signing requests, ensures that only authorised persons in your organisation can utilise this for signing firmware images. This adds another layer of security to the system.\nFirst-Time Signing # Once the signing key is created in ESP RainMaker, you need to sign the firmware images (bootloader and firmware) that gets flashed on your production devices. This is achieved by uploading unsigned images of secure-boot enabled bootloader and firmware and getting them signed for the first time.\nESP RainMaker provides detailed instruction for flashing and setting up your SoC with the appropriate security configurations for secure boot.\nThe secure signing feature is available in public as well as private RainMaker deployments. Use backend release 2.1.0 or later and frontend release 2.0.1 or later for this.\nCheck out more usage details in the ESP RainMaker docs. Go ahead and use this to secure your RainMaker powered IoT devices. Let us know (at esp-rainmaker-support@espressif.com) if you have any queries.\n","date":"29 July 2024","externalUrl":null,"permalink":"/blog/secure-boot-with-auto-signing-in-esp-rainmaker-ota/","section":"Blog","summary":"","title":"Secure boot with auto-signing in ESP RainMaker OTA","type":"blog"},{"content":" Introduction # The ESP32 microcontroller is a versatile and powerful device, widely used in IoT and embedded applications. One of its advanced features is the ability to store multiple firmware images in its flash memory and switch between them. This capability can be leveraged for various purposes, such as testing different firmware versions, running multiple applications, or maintaining a backup firmware.\nIn this article, we will explore how to use the ESP32 Graphical Bootloader to switch between multiple firmware images stored in the flash memory. This bootloader serves as the primary application, allowing you to select and run different firmware images. We will also demonstrate how each application can switch back to the bootloader.\nHow It Works # The bootloader allows the user to select an application from a graphical menu. Once an application is selected, the corresponding partition is chosen, and the chip reboots. The bootloader then switches to the newly selected application. During the startup of this application, there is a code segment that switches the boot partition back to the original application containing the bootloader. Consequently, after another restart, the original bootloader application is displayed again. The bootloader is using OTA mechanism, just the applications are already present in the flash memory.\nPartition Table # To enable multiple firmware images, we need a custom partition table. Below is an example of a file partitions.csv that accommodates the bootloader and five OTA (Over-The-Air) partitions, designed for a 16MB flash memory commonly used in ESP32-S3-BOX-3 and M5Stack-CoreS3:\n# Name, Type, Subtype, Offset, Size, Flags nvs, data, nvs, 0x9000, 24K, otadata, data, ota, , 8K, phy_init, data, phy, , 4K, factory, app, factory, , 2M, ota_0, app, ota_0, , 2816K, ota_1, app, ota_1, , 2816K, ota_2, app, ota_2, , 2816K, ota_3, app, ota_3, , 2816K, ota_4, app, ota_4, , 2816K, This partition table should be defined in your project and the following option must be enabled in your sdkconfig file:\nCONFIG_PARTITION_TABLE_CUSTOM=y Set Up the Graphical Bootloader # Quick Start with Pre-built Firmware # The example application is available as a binary image in Releases.\nIt can be flashed to the device from address 0x0\nesptool.py --chip esp32s3 write_flash 0x0000 graphical_bootloader_esp32-s3-box-3.bin You can also run the simulation of the application in the web browser using Wokwi.\nRun on-line in Wokwi Simulator\nClone the Repository # If you\u0026rsquo;d like to build your own version, please follow the instructions in this chapter.\nStart by cloning the project repository:\ngit clone https://github.com/georgik/esp32-graphical-bootloader.git cd esp32-graphical-bootloader Select the Target Board # Set the appropriate board using BUILD_BOARD variable. For example, to configure for ESP32-S3-BOX-3, use:\ncmake -DBUILD_BOARD=esp-box-3 -Daction=build_all_apps -P Bootloader.cmake List of other supported boards could be found in boards directory.\nMerge Binaries into a Single Image # After building, merge the binaries into a single image:\nesptool.py --chip esp32s3 merge_bin -o build.esp-box-3/combined.bin --flash_mode dio --flash_size 16MB \\ 0x0 build.esp-box-3/bootloader/bootloader.bin \\ 0x8000 build.esp-box-3/partition_table/partition-table.bin \\ 0xf000 build.esp-box-3/ota_data_initial.bin \\ 0x20000 build.esp-box-3/esp32-graphical-bootloader.bin \\ 0x220000 apps/tic_tac_toe/build.esp-box-3/tic_tac_toe.bin \\ 0x4E0000 apps/wifi_list/build.esp-box-3/wifi_list.bin \\ 0x7A0000 apps/calculator/build.esp-box-3/calculator.bin \\ 0xA60000 apps/synth_piano/build.esp-box-3/synth_piano.bin \\ 0xD20000 apps/game_of_life/build.esp-box-3/game_of_life.bin Flash the Merged Binary to the ESP32 # Finally, flash the combined binary to the ESP32:\nesptool.py --chip esp32s3 write_flash 0x0 build.esp-box-3/combined.bin How to Use the Bootloader # Once flashed, the ESP32 will boot into the graphical bootloader. This bootloader allows you to select which application to run. The user interface is intuitive, and you can navigate through the different applications stored in the OTA partitions.\nCreate a Custom Application # The following steps will explain how to create a custom ESP-IDF application for ESP32-S3-BOX-3 which works with the Graphical Bootloader.\nidf.py create-project hello_app cd hello_app idf.py set-target esp32s3 idf.py add-dependency \u0026#34;espressif/esp-box-3^1.2.0\u0026#34; idf.py add-dependency \u0026#34;espressif/esp_codec_dev==1.1.0\u0026#34; cp ../calculator/sdkconfig.defaults . cp ../calculator/sdkconfig.defaults.esp-box-3 . Switch to Application Stored in OTA Partition # The following code snippet from the bootloader shows how to switch to another application. This is particularly useful for managing multiple applications stored in different OTA partitions:\n// For button 1, next_partition will not change, thus pointing to \u0026#39;ota_0\u0026#39; if (next_partition \u0026amp;\u0026amp; esp_ota_set_boot_partition(next_partition) == ESP_OK) { printf(\u0026#34;Setting boot partition to %s\\\\n\u0026#34;, next_partition-\u0026gt;label); esp_restart(); // Restart to boot from the new partition } else { printf(\u0026#34;Failed to set boot partition\\\\n\u0026#34;); } Returning to the Original Application in Factory Partition # Each application can include a mechanism to switch back to the original application (bootloader). Here is an example function from one of the sub-applications:\n#include \u0026#34;esp_ota_ops.h\u0026#34; void reset_to_factory_app() { // Get the partition structure for the factory partition const esp_partition_t *factory_partition = esp_partition_find_first(ESP_PARTITION_TYPE_APP, ESP_PARTITION_SUBTYPE_APP_FACTORY, NULL); if (factory_partition != NULL) { if (esp_ota_set_boot_partition(factory_partition) == ESP_OK) { printf(\u0026#34;Set boot partition to factory, restarting now.\\\\n\u0026#34;); } else { printf(\u0026#34;Failed to set boot partition to factory.\\\\n\u0026#34;); } } else { printf(\u0026#34;Factory partition not found.\\\\n\u0026#34;); } fflush(stdout); } This function can be called at the beginning of the application to ensure that the device reverts to the factory firmware (bootloader) in case of a crash. After this operation, any reset will boot into the original firmware.\nIn your application\u0026rsquo;s CMakeLists.txt, ensure that you include the required dependency:\nidf_component_register(SRCS \u0026#34;hello_app.c\u0026#34; INCLUDE_DIRS \u0026#34;.\u0026#34; REQUIRES app_update) Application Code # Update the code of main/hello_app.c to switch to factory app and display a message on the screen.\n#include \u0026lt;stdio.h\u0026gt; #include \u0026#34;freertos/FreeRTOS.h\u0026#34; #include \u0026#34;freertos/task.h\u0026#34; #include \u0026#34;esp_log.h\u0026#34; #include \u0026#34;lvgl.h\u0026#34; #include \u0026#34;bsp/esp-bsp.h\u0026#34; #include \u0026#34;esp_ota_ops.h\u0026#34; void reset_to_factory_app() { // Get the partition structure for the factory partition const esp_partition_t *factory_partition = esp_partition_find_first(ESP_PARTITION_TYPE_APP, ESP_PARTITION_SUBTYPE_APP_FACTORY, NULL); if (factory_partition != NULL) { if (esp_ota_set_boot_partition(factory_partition) == ESP_OK) { printf(\u0026#34;Set boot partition to factory, restarting now.\\\\n\u0026#34;); } else { printf(\u0026#34;Failed to set boot partition to factory.\\\\n\u0026#34;); } } else { printf(\u0026#34;Factory partition not found.\\\\n\u0026#34;); } fflush(stdout); } void app_main(void) { reset_to_factory_app(); // Initialize the BSP bsp_i2c_init(); bsp_display_start(); // Create a label and set its text lv_obj_t *label = lv_label_create(lv_scr_act()); lv_label_set_text(label, \u0026#34;Hello ESP32-S3-BOX-3\u0026#34;); lv_obj_align(label, LV_ALIGN_CENTER, 0, 0); // Start the display backlight bsp_display_backlight_on(); printf(\u0026#34;Hello ESP32-S3-BOX-3\\n\u0026#34;); // Handle LVGL tasks while (1) { lv_task_handler(); vTaskDelay(pdMS_TO_TICKS(10)); } } Flash the Application # You can build and flash the application directly to the OTA partition.\nidf.py @../../boards/esp-box-3.cfg build esptool.py --chip esp32s3 write_flash 0x220000 build.esp-box-3/hello_app.bin Change an Application Icon # Icons displayed in Graphical Bootloader are part of the bootloader firmware, it\u0026rsquo;s not part of an application. Icons are stored in resources/images.\nYou can simply replace one of existing png files.\nIf you\u0026rsquo;d like to use your own name for icon, then update the bootloader code main/bootloader_ui.c:\nLV_IMG_DECLARE(icon_hello_app) Register the icon to main/CMakeLists.txt. IDF build process will convert the icon to proper format.\nlvgl_port_create_c_image(\u0026#34;../resources/images/icon_hello_app.png\u0026#34; \u0026#34;images/gen/\u0026#34; \u0026#34;ARGB8888\u0026#34; \u0026#34;NONE\u0026#34;) After the change of the icon, you need to rebuild and flash the main application:\nidf.py @boards/esp-box-3 fullclean idf.py @boards/esp-box-3 app-flash Useful Links # ESP32 Graphical Bootloader GitHub Repository ESP-IDF Documentation ESP-BSP Components Conclusion # The ESP32 Graphical Bootloader provides a powerful way to manage multiple applications on a single device. By leveraging OTA partitions, you can store and switch between different applications with ease. Whether you\u0026rsquo;re a maker looking to experiment with different projects or a professional needing multiple application environments, this bootloader simplifies the process.\n","date":"24 July 2024","externalUrl":null,"permalink":"/blog/switch-between-firmware-binaries/","section":"Blog","summary":"","title":"How to switch between multiple ESP32 firmware binaries stored in the flash memory","type":"blog"},{"content":"","date":"24 July 2024","externalUrl":null,"permalink":"/tags/ota/","section":"Tags","summary":"","title":"OTA","type":"tags"},{"content":" Introduction # Embedded Swift brings the power and expressivity of the Swift programming language to constrained environments such as microcontrollers and other embedded systems. Announced during WWDC24, Embedded Swift aims to provide a lightweight, efficient subset of Swift that maintains the language\u0026rsquo;s core features while significantly reducing its footprint and dependencies. This makes Swift a viable option for developers working in resource-constrained environments, allowing them to leverage Swift\u0026rsquo;s modern syntax and safety features in new and exciting ways.\nWhat is Embedded Swift? # Embedded Swift is an experimental specialized compilation mode of Swift designed to produce small, freestanding binaries suitable for embedded systems and bare-metal programming. It strips down unnecessary features and focuses on essential functionality to generate minimal and efficient code. Key goals include eliminating the large code size associated with the full Swift runtime, simplifying the generated code, and allowing effective dead-code stripping.\nEmbedded Swift is not a complete SDK or HAL; rather, it provides the tools to compile Swift code into object files that can be integrated with existing embedded development workflows. It supports environments with and without a dynamic heap and aims to remain a subset of Swift, ensuring code compatibility with regular Swift projects.\nGetting Started with Swift for ESP32-C6 # The following example covers steps for building Embedded Swift application for ESP32-C6.\nHardware Setup # Ensure you have the following hardware:\nESP32-C6 development board. USB-C Cable for power and programming. Prerequisites # Before you begin, make sure you have the following:\nESP-IDF: The official development framework for the ESP32, properly installed and sourced in your shell. This tutorial has been tested with ESP-IDF v6.0. Swiftly: The Swift toolchain installer and manager. Swift 6.2 development snapshot (installed via swiftly). Note: This article has been updated and tested with Swift 6.2-dev snapshot from August 2025. Building an Example Project # First, let\u0026rsquo;s see the whole build process in Asciinema recording: Install Swift toolchain:\nFirst, install Swiftly by following the official installation guide at swift.org/install, then install the Swift 6.2 development snapshot:\n# Install Swift 6.2 development snapshot swiftly install 6.2-snapshot Clone Sample Project:\nThe repository contains two ESP32 examples. Let\u0026rsquo;s use the LED strip example which demonstrates more advanced functionality:\ngit clone https://github.com/swiftlang/swift-embedded-examples.git --single-branch --branch main cd swift-embedded-examples/esp32-led-strip-sdk # Use the 6.2 snapshot for this project swiftly use 6.2-snapshot Available ESP32 Examples:\nesp32-led-blink-sdk: Simple LED blinking example esp32-led-strip-sdk: NeoPixel LED strip control example (used in this tutorial) Set the Target:\nEnsure the correct target is set for your project:\nidf.py set-target esp32c6 Note: It\u0026rsquo;s possible to build the project also for other RISC-V based targets, like ESP32-C3.\nBuild and Flash the Project:\nCompile and flash your application to the ESP32-C6-DevKit:\nidf.py build flash monitor Note: Use Ctrl+] to quit the monitor application.\nExploring the Example # Let\u0026rsquo;s look at the source code of the example: Main.swift\n//===----------------------------------------------------------------------===// // // This source file is part of the Swift open source project // // Copyright (c) 2023 Apple Inc. and the Swift project authors. // Licensed under Apache License v2.0 with Runtime Library Exception // // See https://swift.org/LICENSE.txt for license information // //===----------------------------------------------------------------------===// @_cdecl(\u0026#34;app_main\u0026#34;) func app_main() { print(\u0026#34;Hello from Swift on ESP32-C6!\u0026#34;) let n = 8 let ledStrip = LedStrip(gpioPin: 0, maxLeds: n) ledStrip.clear() var colors: [LedStrip.Color] = .init(repeating: .off, count: n) while true { colors.removeLast() colors.insert(.lightRandom, at: 0) for index in 0 ..\u0026lt; n { ledStrip.setPixel(index: index, color: colors[index]) } ledStrip.refresh() let blinkDelayMs: UInt32 = 500 vTaskDelay(blinkDelayMs / (1000 / UInt32(configTICK_RATE_HZ))) } } This code initializes an LED strip connected to an ESP32-C6 microcontroller. The app_main function starts by printing a message, then sets up an LED strip on GPIO pin 0 with a maximum of 8 LEDs. It clears the strip and enters an infinite loop where it cycles a random light color through the LEDs. Each iteration updates the LED colors, refreshes the strip, and delays for 500 milliseconds.\nSimulation in Wokwi # The examples for ESP32-C6 could be easily simulated by Wokwi:\nEmbedded Swift - ESP32-C6 - Led Blink Embedded Swift - ESP32-C6 - Led Strip Conclusion # Embedded Swift even in experimental stage represents a significant advancement in bringing Swift\u0026rsquo;s powerful features to embedded systems and constrained environments. By focusing on reducing runtime dependencies and optimizing code size, Embedded Swift allows developers to leverage Swift\u0026rsquo;s modern programming paradigms even on MCUs.\nWhat\u0026rsquo;s New Since the Original Article (Updated September 2025) # Since the original publication in July 2024, several important improvements have been made to the Embedded Swift ecosystem:\nToolchain Management # Swiftly Integration: The recommended way to install and manage Swift toolchains is now through Swiftly, which simplifies toolchain management significantly. Swift 6.2 Development: The examples now work with Swift 6.2 development snapshots, providing access to the latest language features and improvements. ESP-IDF Compatibility # ESP-IDF 6.0 Support: The examples have been tested and work with ESP-IDF v6.0, which includes many improvements and new features. Updated Dependencies: All component dependencies are automatically managed and updated to their latest versions. Repository Changes # Organization Move: The swift-embedded-examples repository has moved from apple/swift-embedded-examples to swiftlang/swift-embedded-examples. Documentation Improvements: Enhanced documentation with better installation guides and troubleshooting information. Useful Links # WWDC24 - Go small with Embedded Swift Embedded Swift Example Projects A Vision for Embedded Swift Embedded Swift Documentation Installing Embedded Swift Blog Post Introducing Embedded Swift Examples Swiftly - Swift Toolchain Manager ","date":"22 July 2024","externalUrl":null,"permalink":"/blog/build-embedded-swift-application-for-esp32c6/","section":"Blog","summary":"","title":"Build Embedded Swift Application for ESP32-C6","type":"blog"},{"content":"","date":"12 July 2024","externalUrl":null,"permalink":"/authors/brian-ignacio/","section":"Developer Portal Authors","summary":"","title":"Brian Ignacio","type":"authors"},{"content":" Introduction # ESP-IDF VS Code Extension v1.8.0 has been released! It introduces new features and many improvements. If you face any issue or improvement ideas please share them as a Github issue.\nThis article covers the following key features:\nEclipse CDT GDB Debug Adapter ESP-IDF version switcher Code navigation without full project build ESP-IDF Hints viewer For other updates please review v1.8.0 Release notes. Now let\u0026rsquo;s look into the key features one by one.\nEclipse CDT GDB Debug Adapter # First, we will briefly talk about the implementation of debug adapters in VS Code and then will move on to the actual Eclipse CDT GDB Debug Adapter.\nWhat is a debug adapter in VS Code? # VS Code implements a generic (language-agnostic) Debugger UI that is based on an abstract protocol. That protocol was specifically introduced to communicate with debugger backends. As debuggers typically use their own long-established protocols, some \u0026ldquo;adapter\u0026rdquo; is needed to allow debugger UI to communicate with debugger backends. This is described in the debugging architecture of VS Code documentation.\nThis adapter is typically a standalone process with its own protocol. Both the Debug Adapter (DA) and the abstract protocol that is used between the VS Code\u0026rsquo;s Debugger UI and DA \u0026ndash; the Debug Adapter Protocol (DAP) \u0026ndash; have already been implemented by independent contributors. The diagram below illustrates it better:\nThe image is borrowed from VS Code documentation.\nThe actual Eclipse CDT GDB Debug Adapter # Up until this version, only ESP-IDF Debug Adapter implemented in python by Espressif has been available in ESP-IDF VS Code Extension. While it works, our users have reported many issues regarding configuration, responsiveness and runtime errors.\nIn search of a better solution, we chose the CDT GDB Adapter implemented by the Eclipse CDT Cloud team in TypeScript that uses NPM serialport package underneath. We only made a few minor updates to make it work with our tools. In our plugin, this adapter is called Eclipse CDT GDB Debug Adapter and is used in launch.json when configuration type is gdbtarget.\nTo use the Eclipse CDT GDB Adapter in an ESP-IDF project, add the following configuration in .vscode/launch.json:\n{ \u0026#34;configurations\u0026#34;: [ { \u0026#34;type\u0026#34;: \u0026#34;gdbtarget\u0026#34;, \u0026#34;request\u0026#34;: \u0026#34;attach\u0026#34;, \u0026#34;name\u0026#34;: \u0026#34;Eclipse CDT GDB Adapter\u0026#34; } ] } To start debugging the project, do the following:\nBuild (command palette: ESP-IDF: Build your Project) Flash (command palette: ESP-IDF: Flash your Project) In the Run menu, press Start debugging. You can also check how to use the new debugger by following the debug tutorial.\nThe following figure shows an active debug session with the Eclipse CDT GDB Debug Adapter in VS Code. You can see the list of variables, call stack, breakpoints, debug console and debug controls such as step in, step out, etc.\nAdvanced configuration of Eclipse CDT GDB Debug Adapter # There are many configurable options to customize the debug adapter if desired. You can view a deeper description in the debugging documentation.\nESP-IDF version switcher # Whenever you install ESP-IDF in your system using the command ESP-IDF: Configure ESP-IDF Extension, the installations are saved in our extension as global state IDF setup. Now you can use ESP-IDF: Select Current ESP-IDF Version to set the ESP-IDF version you want to use in your current project (workspace folder in VS Code terminology). If you want to delete these IDF setups from the extension global state, you can use ESP-IDF: Clear Saved ESP-IDF Setups.\nThe current ESP-IDF version for currently open ESP-IDF project is shown in the status bar items like this:\nCode navigation without full project build # VS Code extensions for code navigation are dependent on a compile_commands.json file. Before this version, you could only generate such a file by fully building your project. Starting from this version, the file can be generated by running a dedicated command ESP-IDF: idf.py reconfigure task. It saves much time. Read on for more beginner-friendly explanation.\nOne of the key features of an IDE is code navigation. While working on your project, you usually want to benefit from such common language features as syntax highlight, code completion, go to definition/declaration, and others. For C/C++ language support, usually the extensions like C/C++ extension or clangd extension are used.\nSuch extensions usually rely on a compile_commands.json file \u0026ndash; a JSON compilation database which consist of an array of command objects, where each command object specifies one way in which a translation unit is compiled in the project. More information about a JSON compilation database can be found here.\nNow you can enable code navigation by using the command ESP-IDF: idf.py reconfigure task to generate a compile_commands.json file without the need to wait for the whole project to build. This command executes the ESP-IDF reconfigure task, hence its name.\nESP-IDF Hints viewer # ESP-IDF will try to show hints to resolve errors as described in idf.py documentation. It works with a database of hints stored in tools/idf_py_actions/hints.yml and the hints will be printed if a match is found for the given error.\nIn the source code editor, errors that match a line will be shown when the user mouse is hovering that line.\nThe ESP-IDF bottom panel automatically updates to display ESP-IDF hints based on the errors in your currently opened file.\nYou can manually search for any ESP-IDF hint with the ESP-IDF: Search Error Hint. It will search from available hints listed in $IDF_PATH/tools/idf_py_actions/hints.yml.\nConclusion # In this article, we introduced the key features implemented in ESP-IDF VS Code Extension v1.8.0 release. We are working hard to make the developer experience as smooth and convenient as possible, and this release moved us a few steps forward in this endeavor. We hope this version brings what you expected. If not, feel free to leave your feedback in GitHub issues, and let\u0026rsquo;s keep improving this extension together!\n","date":"12 July 2024","externalUrl":null,"permalink":"/blog/vscode-esp-idf-v1.8.0/","section":"Blog","summary":"","title":"ESP-IDF VS Code Extension v1.8.0 release","type":"blog"},{"content":"Welcome to the IoT workshop with ESP RainMaker. The ESP RainMaker was designed to empower you to build, develop, and deploy customized AIoT solutions effortlessly. ESP RainMaker ensures you can achieve your goals with minimal coding and maximum security.\nJoin us as we explore how ESP RainMaker can transform your AIoT projects, offering a seamless blend of innovation, security, and scalability. Whether you are looking to streamline maintenance, enhance security, or scale your operations, this workshop will equip you with the knowledge and tools to harness the full potential of ESP RainMaker.\nAbout this workshop # On this workshop, you will have an introduction to the ESP RainMaker with 6 assignments that cover a range of essential skills:\nAssignment 1: Install the Espressif-IDE \u0026ndash; installation of necessary tools to start development Assignment 2: Install ESP RainMaker \u0026ndash; installation of the SDK itself and the mobile phone application to deploy and control devices Assignment 3: Build the IoT device \u0026ndash; this device will be controlled locally or via the cloud integration with the mobile application Assignment 4: Google Home integration \u0026ndash; set up the Voice Assistant to control your devices via Google Home Assignment 5: Over-the-air update \u0026ndash; update the device firmware remotely using OTA Assignment 6: Introduction to Matter \u0026ndash; brief overview of the Matter protocol for connected home devices By participating in this workshop, you will gain comprehensive understanding of ESP RainMaker, and how to build powerful AIoT applications. We hope this knowledge will form a solid foundation for your future projects.\nThank you for your time and engagement in this workshop. We look forward to seeing the innovative solutions you’ll create with the ESP RainMaker.\nPrerequisites # To follow this workshop, make sure you meet the prerequisites described below.\nHardware Prerequisites # Computer running Windows, Linux, or macOS ESP32-C6-DevKit-C or ESP32-C6-DevKit-M development board USB cable (data + power) compatible with your development board Software Prerequisites # ESP-IDF v5.2.2 Espressif-IDE 3.0.0 ESP RainMaker (GitHub) Effort # Estimated time: 180 min RainMaker introduction # The ESP RainMaker is a cloud-based end-to-end solution that provides an easy-to-use platform for IoT devices.\nFrom the device side, the open-source SDK provides easy-to-use APIs to build your devices, such as switches, lights, fans, and more. Check the project repository for examples on how to use and develop your ESP RainMaker based product.\nESP RainMaker also provides two types of phone apps: ESP RainMaker App and the Nova Home App.\nYou can use ESP RainMaker for free for a small number of nodes. For commercial use, please contact Espressif Sales.\nBasic concepts # The backend is built using AWS serverless architecture, which offers unparalleled flexibility and scalability in terms of computing, data storage and transmission capacity.\nThe RainMaker SDK is built on top of ESP-IDF and provides simple APIs to build applications based on ESP RainMaker.\nNode # A node is a single ESP32-based product. It has an associated identifier (Node ID) and a set of credentials provided by the Claiming Service.\nYou can give a friendly name to the node. A single node can have exposure to multiple devices.\nNode Attributes\nNode Attributes are optional and exist as custom metadata for a given node, something like a serial number.\nDevice # A device is a logical user-controllable entity like Switch, Lightbulb, Thermostat, Temperature Sensor, etc. A simple node generally has a single device. However, an ESP32 may also have multiple devices.\nFor example, it might integrate two switches on a single board, or act as a bridge for other devices such as BLE sensors. Each device must have a unique name within the node, and, optionally, a type.\nDevice Attributes\nSimilar to node attributes, device attributes are name-value pairs that act as metadata for the device. These name-value pairs are additional, user-defined, and read-only that can include information such as firmware version, serial number.\nDevice attributes are particularly useful when there are multiple devices bridged to the node, such as Wi-Fi to wired network, BLE, Zigbee, etc.\nParameters # Parameters are monitoring parameters of a device, such as the ON/OFF power state, brightness, current/target temperature, etc. All such parameters must have a unique name within the device.\nThey can also have additional fields like value, type, bounds, UI information, etc. The parameter values can be boolean, integer, float, or string.\nSee the full list of supported device types.\nServices # A service is an entity very similar to a device in terms of its structure. The main difference is that services are designed for operations that the user might not necessarily need to interact with.\nA typical example of this is the OTA Firmware Upgrade Service, which can have parameters like url, status, etc.\nCloud # For the cloud, you can get access to the devices via the RainMaker dashboard, where you can:\nSee all the nodes Create node groups Manage the firmware updates (OTA) Manage keys With the RainMaker dashboard, you can\u0026rsquo;t control the device parameters. This is only possible with the RainMaker mobile application, CLI, or via REST APIs.\nClient Cloud Communication\nRelated documents # ESP RainMaker website ESP RainMaker GitHub repository RainMaker documentation RainMaker Programming Guide RainMaker dashboard You can also use the phone apps, supported on Android and iOS.\nRainMaker Android App RainMaker iOS App Assignment 1: Install the Espressif-IDE # To get started and perform all the workshop assignments, you will need to install the Espressif-IDE. This IDE will be used to create the project, then flash and debug the code.\nAs an alternative, you can use the VS Code extension for ESP-IDF or you can use the Command-Line-Interface (CLI) directly, however, this workshop is based on the Espressif-IDE and all the assignments will follow the steps using this IDE.\nInstall the Espressif-IDE # This assignment will be done by the following tutorial: Getting Started with IDEs Workshop.\nYou will need to:\nInstall all the necessary drivers for Windows Install the Espressif-IDE Install the ESP-IDF Create the first project Build Flash Debug Now that you know how to use the Espressif-IDE, let\u0026rsquo;s get started with ESP-IDF and create a new RainMaker project.\nAssignment 2: Install ESP RainMaker # After installing the Espressif-IDE and ESP-IDF, we need to clone the RainMaker repository. Right now there are no ways to install it directly from the Espressif-IDE.\nTo manually install, you will need to clone the esp-rainmaker repository on GitHub.\nClone the repository\n$ git clone --recursive https://github.com/espressif/esp-rainmaker.git Clone this repository in the same folder as ESP-IDF. Usually c:/esp or at your home directory. Avoid long paths!\nInstall the mobile phone application\nAndroid App iOS App Assignment 3: Build the IoT device # To get started with ESP RainMaker, we will build the application in 3 steps:\nLED light bulb Switch Thermostat LED light bulb: This device represents the LED light bulb where you can set Name, Power, Brightness, Color Temperature, Hue, Saturation, Intensity, Light Mode.\nSwitch: This device is the light switch and you will need to set Name and Power parameters. The power parameter is a boolean type and represents the on and off state.\nThermostat This device is a thermostat and you will need to set Name, Setpoint Temperature, Temperature, AC Mode, and Power parameters.\nSteps # The typical code for any ESP RainMaker based application is as follows:\nInitialize Wi-Fi (app_wifi_init()), which also initializes the MAC address that will act as the unique node identifier (node_id) for self-claiming. Initialize the ESP RainMaker node (esp_rmaker_node_init()) by passing to it a configuration (esp_rmaker_config_t), node name, and type. Create a device (esp_rmaker_device_create()). The RainMaker node in itself has no specific value, unless it has a device under it. In our example, we create a device named \u0026ldquo;Switch\u0026rdquo;, for which we also provide a write callback. The callback will be invoked if a write request is received for any parameter under the Switch device. Add parameters and other metadata. A switch device, at the minimum, will have at least the standard power parameter. Marking some parameter as primary gives it prominence in the phone apps. Add the device to the node. Start the RainMaker Agent (esp_rmaker_start()). This will start the RainMaker core task which will wait for Wi-Fi, do the claiming (if required), connect to the RainMaker cloud over MQTT, report the node configuration, report the values of parameters, and then wait for commands. Start Wi-Fi (app_wifi_start()). If the ESP32 is already provisioned, it will join the configured Wi-Fi network. Else, it will start the Wi-Fi provisioning. Note that rainmaker should be initialized and started before this call. Node # To create the node, we need to set the following parameters in the esp_rmaker_node_init function:\nconfig: Configuration to be used by the ESP RainMaker, set as the structure rainmaker_cfg. name: Name of the node set as \u0026ldquo;Espressif Workshop Light\u0026rdquo;. type: Type of the node set as \u0026ldquo;Lightbulb\u0026rdquo;. Example:\nesp_rmaker_node_t *node = esp_rmaker_node_init(\u0026amp;rainmaker_cfg, \u0026#34;Espressif Workshop Light\u0026#34;, \u0026#34;Lightbulb\u0026#34;); Call the function esp_rmaker_node_init to initialize the node.\nFunction esp_rmaker_node_init reference.\nDevice # To create the light bulb device, you can use the function esp_rmaker_lightbulb_device_create which will facilitate the device creation. You will see later how to create the device manually.\nExample:\nesp_rmaker_device_t *light_device; light_device = esp_rmaker_lightbulb_device_create(\u0026#34;Light\u0026#34;, NULL, DEFAULT_POWER); esp_rmaker_device_add_bulk_cb(light_device, bulk_write_cb, NULL); See the reference here.\nParameters # Once you create the device, it\u0026rsquo;s time to create the device parameters. The device parameters will be created to control the functionalities, like brightness, hue, and saturation.\nIt\u0026rsquo;s important to mention that on this example, the LED (WS2812) control will be handled by app_driver.c.\nExample:\nesp_rmaker_device_add_param(light_device, esp_rmaker_brightness_param_create(ESP_RMAKER_DEF_BRIGHTNESS_NAME, DEFAULT_BRIGHTNESS)); esp_rmaker_device_add_param(light_device, esp_rmaker_hue_param_create(ESP_RMAKER_DEF_HUE_NAME, DEFAULT_HUE)); esp_rmaker_device_add_param(light_device, esp_rmaker_saturation_param_create(ESP_RMAKER_DEF_SATURATION_NAME, DEFAULT_SATURATION)); The function esp_rmaker_device_add_param will add parameter to the light_device, including the param name and default value.\nAfter adding all the parameters, you can add the device to the node.\nExample:\nesp_rmaker_node_add_device(node, light_device); Custom device # To create the device manually, you will need to call different functions.\nCreate the device by calling esp_rmaker_device_create. Add the callback function to handle the received command using the function esp_rmaker_device_add_cb. Set the parameters with esp_rmaker_device_add_param then esp_rmaker_param_create. Add the UI (esp_rmaker_param_add_ui_type) type to be used with the RainMaker application and assign the primary parameter with esp_rmaker_device_assign_primary_param. Define the parameter limits (boundary) with esp_rmaker_param_add_bounds if applicable to the parameter. In this example, the device is a light with 2 parameters, the on/off with a toggle widget and the brightness with a slider that goes from 0 to 100 in steps of 1.\nesp_rmaker_device_t *device = esp_rmaker_device_create(\u0026#34;Light\u0026#34;, NULL, NULL); esp_rmaker_device_add_cb(device, write_cb, NULL); esp_rmaker_device_add_param(device, esp_rmaker_param_create(\u0026#34;name\u0026#34;, NULL, esp_rmaker_str(\u0026#34;Light\u0026#34;), PROP_FLAG_READ | PROP_FLAG_WRITE | PROP_FLAG_PERSIST)); esp_rmaker_param_t *power_param = esp_rmaker_param_create(\u0026#34;power\u0026#34;, NULL, esp_rmaker_bool(true), PROP_FLAG_READ | PROP_FLAG_WRITE); esp_rmaker_param_add_ui_type(power_param, ESP_RMAKER_UI_TOGGLE); esp_rmaker_device_add_param(device, power_param); esp_rmaker_device_assign_primary_param(device, power_param); esp_rmaker_param_t *brightness_param = esp_rmaker_param_create(\u0026#34;brightness\u0026#34;, NULL, esp_rmaker_int(100), PROP_FLAG_READ | PROP_FLAG_WRITE); esp_rmaker_param_add_ui_type(brightness_param, ESP_RMAKER_UI_SLIDER); esp_rmaker_param_add_bounds(brightness_param, esp_rmaker_int(0), esp_rmaker_int(100), esp_rmaker_int(1)); esp_rmaker_device_add_param(device, brightness_param); Hands on session to create a device # Let\u0026rsquo;s now create the device!\nFirst, you will need to import the project into your Espressif IDE workspace. Go to File -\u0026gt; Import -\u0026gt; Espressif -\u0026gt; Existing IDF Project and select the workshop-rainmaker located inside the workshop shared folder or in the ESP Workshop repository.\nOpen the project and change the CMakeLists.txt to point to your RainMaker folder: # The following lines of boilerplate have to be in your project\u0026#39;s CMakeLists # in this exact order for cmake to work correctly cmake_minimum_required(VERSION 3.5) if(DEFINED ENV{RMAKER_PATH}) set(RMAKER_PATH $ENV{RMAKER_PATH}) else() set(RMAKER_PATH \u0026lt;PATH-TO-RAINMAKER-FOLDER\u0026gt;/esp-rainmaker) endif(DEFINED ENV{RMAKER_PATH}) # Add RainMaker components and other common application components set(EXTRA_COMPONENT_DIRS ${RMAKER_PATH}/components/esp-insights/components ${RMAKER_PATH}/components ${RMAKER_PATH}/examples/common) set(PROJECT_VER \u0026#34;1.0\u0026#34;) include($ENV{IDF_PATH}/tools/cmake/project.cmake) project(workshop-rainmaker) Change the app_main.c file and add the RainMaker code to the app_main: void app_main() { esp_rmaker_console_init(); app_driver_init(); /* Initialize NVS. */ esp_err_t err = nvs_flash_init(); if (err == ESP_ERR_NVS_NO_FREE_PAGES || err == ESP_ERR_NVS_NEW_VERSION_FOUND) { ESP_ERROR_CHECK(nvs_flash_erase()); err = nvs_flash_init(); } ESP_ERROR_CHECK( err ); app_wifi_init(); esp_rmaker_config_t rainmaker_cfg = { .enable_time_sync = false, }; esp_rmaker_node_t *node = esp_rmaker_node_init(\u0026amp;rainmaker_cfg, \u0026#34;Espressif Workshop Light\u0026#34;, \u0026#34;Lightbulb\u0026#34;); if (!node) { ESP_LOGE(TAG, \u0026#34;Could not initialise node. Aborting!!!\u0026#34;); vTaskDelay(5000/portTICK_PERIOD_MS); abort(); } // Enable the OTA with the default configuration esp_rmaker_ota_enable_default(); // Enable the timezone service to get the correct time at the given timezone esp_rmaker_timezone_service_enable(); // Enable the scheduling service esp_rmaker_schedule_enable(); // Enable the scenes service esp_rmaker_scenes_enable(); // Start RainMaker esp_rmaker_start(); // Start WiFi err = app_wifi_start(POP_TYPE_RANDOM); if (err != ESP_OK) { ESP_LOGE(TAG, \u0026#34;Could not start Wifi. Aborting!!!\u0026#34;); vTaskDelay(5000/portTICK_PERIOD_MS); abort(); } } Add the light bulb device: esp_rmaker_device_t *light_device; void device_create_lightbulb(esp_rmaker_node_t *node) { light_device = esp_rmaker_lightbulb_device_create(\u0026#34;Light\u0026#34;, NULL, DEFAULT_POWER); esp_rmaker_device_add_bulk_cb(light_device, bulk_write_cb, NULL); esp_rmaker_device_add_param(light_device, esp_rmaker_brightness_param_create(ESP_RMAKER_DEF_BRIGHTNESS_NAME, DEFAULT_BRIGHTNESS)); esp_rmaker_device_add_param(light_device, esp_rmaker_hue_param_create(ESP_RMAKER_DEF_HUE_NAME, DEFAULT_HUE)); esp_rmaker_device_add_param(light_device, esp_rmaker_saturation_param_create(ESP_RMAKER_DEF_SATURATION_NAME, DEFAULT_SATURATION)); esp_rmaker_node_add_device(node, light_device); } Also, add the callback function to handle the light bulb:\nstatic esp_err_t bulk_write_cb(const esp_rmaker_device_t *device, const esp_rmaker_param_write_req_t write_req[], uint8_t count, void *priv_data, esp_rmaker_write_ctx_t *ctx) { if (ctx) { ESP_LOGI(TAG, \u0026#34;Received write request via : %s\u0026#34;, esp_rmaker_device_cb_src_to_str(ctx-\u0026gt;src)); } ESP_LOGI(TAG, \u0026#34;Light received %d params in write\u0026#34;, count); for (int i = 0; i \u0026lt; count; i++) { const esp_rmaker_param_t *param = write_req[i].param; esp_rmaker_param_val_t val = write_req[i].val; const char *device_name = esp_rmaker_device_get_name(device); const char *param_name = esp_rmaker_param_get_name(param); if (strcmp(param_name, ESP_RMAKER_DEF_POWER_NAME) == 0) { ESP_LOGI(TAG, \u0026#34;Received value = %s for %s - %s\u0026#34;, val.val.b? \u0026#34;true\u0026#34; : \u0026#34;false\u0026#34;, device_name, param_name); app_light_set_power(val.val.b); } else if (strcmp(param_name, ESP_RMAKER_DEF_BRIGHTNESS_NAME) == 0) { ESP_LOGI(TAG, \u0026#34;Received value = %d for %s - %s\u0026#34;, val.val.i, device_name, param_name); app_light_set_brightness(val.val.i); } else if (strcmp(param_name, ESP_RMAKER_DEF_HUE_NAME) == 0) { ESP_LOGI(TAG, \u0026#34;Received value = %d for %s - %s\u0026#34;, val.val.i, device_name, param_name); app_light_set_hue(val.val.i); } else if (strcmp(param_name, ESP_RMAKER_DEF_SATURATION_NAME) == 0) { ESP_LOGI(TAG, \u0026#34;Received value = %d for %s - %s\u0026#34;, val.val.i, device_name, param_name); app_light_set_saturation(val.val.i); } else { ESP_LOGI(TAG, \u0026#34;Updating for %s\u0026#34;, param_name); } esp_rmaker_param_update(param, val); } return ESP_OK; } Add the switch device as a custom device for multi-device feature: void device_create_switch(esp_rmaker_node_t *node) { esp_rmaker_device_t *switch_device = esp_rmaker_device_create(\u0026#34;Switch\u0026#34;, ESP_RMAKER_DEVICE_SWITCH, NULL); esp_rmaker_device_add_cb(switch_device, write_cb, NULL); esp_rmaker_param_t *power_param = esp_rmaker_param_create(\u0026#34;Power\u0026#34;, ESP_RMAKER_PARAM_POWER, esp_rmaker_bool(false), PROP_FLAG_READ | PROP_FLAG_WRITE); esp_rmaker_param_add_ui_type(power_param, ESP_RMAKER_UI_TOGGLE); esp_rmaker_device_add_param(switch_device, power_param); esp_rmaker_node_add_device(node, switch_device); } Add the thermostat device: void device_create_thermostat(esp_rmaker_node_t *node) { esp_rmaker_device_t *thermo_device = esp_rmaker_device_create(\u0026#34;Thermostat\u0026#34;, ESP_RMAKER_DEVICE_THERMOSTAT, NULL); esp_rmaker_device_add_cb(thermo_device, write_cb, NULL); esp_rmaker_param_t *power_param = esp_rmaker_param_create(\u0026#34;Power\u0026#34;, ESP_RMAKER_PARAM_POWER, esp_rmaker_bool(false), PROP_FLAG_READ | PROP_FLAG_WRITE); esp_rmaker_param_add_ui_type(power_param, ESP_RMAKER_UI_TOGGLE); esp_rmaker_device_add_param(thermo_device, power_param); esp_rmaker_param_t *temp_param = esp_rmaker_param_create(ESP_RMAKER_DEF_TEMPERATURE_NAME, ESP_RMAKER_PARAM_TEMPERATURE, esp_rmaker_float(20.0), PROP_FLAG_READ); esp_rmaker_param_add_ui_type(temp_param, ESP_RMAKER_UI_TEXT); esp_rmaker_device_add_param(thermo_device, temp_param); esp_rmaker_param_t *setpoint_param = esp_rmaker_param_create(\u0026#34;Temperature Set\u0026#34;, ESP_RMAKER_PARAM_TEMPERATURE, esp_rmaker_int(20), PROP_FLAG_READ | PROP_FLAG_WRITE); esp_rmaker_param_add_ui_type(setpoint_param, ESP_RMAKER_UI_SLIDER); esp_rmaker_param_add_bounds(setpoint_param, esp_rmaker_int(15), esp_rmaker_int(30), esp_rmaker_int(1)); esp_rmaker_device_add_param(thermo_device, setpoint_param); esp_rmaker_node_add_device(node, thermo_device); } Create the callback function for the custom devices: static esp_err_t write_cb(const esp_rmaker_device_t *device, const esp_rmaker_param_t *param, const esp_rmaker_param_val_t val, void *priv_data, esp_rmaker_write_ctx_t *ctx) { if (ctx) { ESP_LOGI(TAG, \u0026#34;Received write request via : %s\u0026#34;, esp_rmaker_device_cb_src_to_str(ctx-\u0026gt;src)); } return ESP_OK; } For the final assignment code, please use the workshop-rainmaker-final\nExtra\nCreate a function to update the temperature values for the thermostat parameter.\nstatic void device_thermo_temp_update(esp_rmaker_device_t *device, float temp) { esp_rmaker_param_update_and_report( esp_rmaker_device_get_param_by_type(device, ESP_RMAKER_PARAM_TEMPERATURE), esp_rmaker_float(temp)); } Wi-Fi provisioning # After configuring the node, device, and parameters, you can call esp_rmaker_start to trigger the claiming process, establish Wi-Fi and then MQTT connection, and report the node parameters, values, and configuration.\nTo do the claiming/provisioning, we will use the RainMaker mobile phone application.\nAfter the provisioning process, you can reset to factory mode by pressing and holding the BOOT button on the DevKit-C.\nESP Insights # The RainMaker is integrated with ESP Insights.\nESP Insights allows developers to view stack back-traces and register dumps for firmware running on devices.\nWith Insights you can:\nTrack Metrics: Pre-defined system metrics or record your own custom metrics. Crash Backtraces: Inspect device crashes with detailed backtraces. Device Logs: Check all kinds of logs like Errors, Warnings, Reboots, etc. To enable the ESP Insights you need to:\nCall app_insights_enable: app_insights_enable(); In sdkconfig, set Enable ESP Insights: In Component config -\u0026gt; ESP Insights, set Enable ESP Insights .\nNow you will have access to see the device metrics in the ESP Insights Dashboard.\nAssignment 4: Google Home integration # One important features for an IoT device user experience is the ecosystem integration. This is important to keep all the controls in just on place.\nIf you are using Google Voice Assistant or Alexa to control your devices, RainMaker offers the integration that will allow you to control and do the automations via the voice assistant application.\nTo configure the integration with Google Home application, follow the steps below.\nOn your mobile phone, open the Google Home app. Tap on + -\u0026gt; Set up Device. Select the option Works with Google meant for devices that are already set up. Search for ESP RainMaker and sign in using your RainMaker credentials. Once the Account linking is successful, your RainMaker devices will show up and you can start using them. For Alexa, please use this documentation: Enabling Alexa.\nAfter linking your RainMaker account with the Google Home app, you will be able to see and control all devices in your RainMaker account.\nAssignment 5: Over-the-air update # If your device is connected, you must be able to update it remotely.\nIn a connected world, devices can fail, and security breaches can be discovered. If you have issues with your firmware in the field, you must be able to fix and update the devices without physical intervention.\nTo do that, Over-The-Air (OTA) updates solves this issue.\nRainMaker supports OTA with just one line of code:\nesp_rmaker_ota_enable_default(); Then on the backend side, you can upload the firmware image and create a new OTA task and trigger the OTA update.\nGo to Firmware Images -\u0026gt; Add Image. Fill out the image name, type, and select the image file (.bin). In the Advanced section, you can also define the secure sign keys, bootloader file, firmware version, and model. Once you add the image to the RainMaker backend, you can create the OTA job.\nIn the list of uploaded images, select Start OTA in the selected image. Enter the job name. Select the node group or nodes that will be updated. Check Force Push if you need to run the OTA right away. Start OTA. You can use the Advanced option to schedule the OTA.\nIf everything if properly configured, the firmware update will start and this action will take a while to complete.\nYou can check the task progress in the OTA Jobs. Once the OTA is completed, you can check the firmware version in the Nodes list.\nAssignment 6: Introduction to Matter # Espressif’s SDK for Matter has been developed over the open-source Matter SDK to provide a simplified API and the required tools for building Matter-compatible devices with Espressif SoCs. This SDK defines periodic releases and support structures that ensure maintaining the in-field devices effectively.\nMaking your devices Matter-compatible with ESP-ZeroCode Modules is as simple as just adding these modules to your devices.\nESP ZeroCode supports different kinds of products like lightbulbs, lighting fixtures, led strips, sockets, switches, roller blinds, refrigerator, laundry washer, thermostat and more.\nChoose any Espressif module from the ESP32-C2, ESP32-C3, ESP32-C6 and ESP32-H2 series.\nMake changes as per your hardware configurations and visualize them on your selected module.\nValidate your end-user workflow by testing it directly on your hardware.\nOrder modules pre-programmed with Matter-certified firmware as per your configuration. Mount the modules on your PCBs and launch.\nCreate ESP ZeroCode account Create product Flash using ESP Launchpad Provision using Google Home mobile application In order to use the Espressif vendor for development purpose, you need to enable your Google account as developer and create the Matter device types into your account using the console.\nGoogle Matter Developer Console\nFeedback # If you have any feedback for this workshop, please start a new discussion on GitHub.\n","date":"8 July 2024","externalUrl":null,"permalink":"/workshops/iot-introduction-with-rainmaker/","section":"Workshops","summary":"","title":"IoT Introduction with RainMaker","type":"workshops"},{"content":" Lecture: ESP-IDF introduction # The ESP-IDF (Espressif IoT Development Framework) is the official operating system and development framework for the ESP32 series of microcontrollers by Espressif Systems. It provides a comprehensive environment for building IoT applications with robust networking, security, and reliability features.\nESP-IDF framework includes FreeRTOS that allows developers to create real-time, multitasking applications. With extensive libraries, components, protocols, tools, and documentation, ESP-IDF simplifies the development process enabling seamless integration with hardware peripherals, such as Wi-Fi, Bluetooth, Thread, ZigBee, and cloud services.\nESP-IDF includes almost 400 examples, covering a wide range of use cases and helping developers quickly get started on their projects.\nArchitecture # The ESP-IDF platform architecture is mainly divided into 3 layers:\nESP-IDF platform Contains the core components required and all the operating system. Includes the FreeRTOS, drivers, build system, protocols, etc. Middleware Adds new featured to the ESP-IDF, for example the audio framework and HMI. AIoT Application This is your application. All the necessary blocks for building your application will be included on the ESP-IDF platform.\nFrameworks # Several other frameworks use ESP-IDF as a base, including:\nArduino for ESP32 ESP-ADF (Audio Development Framework): Designed for audio applications. ESP-WHO (AI Development Framework): Focused on face detection and recognition. ESP-RainMaker: Simplifies building connected devices with cloud capabilities. ESP-Matter SDK: Espressif\u0026rsquo;s SDK for Matter is the official Matter development framework for ESP32 series SoCs. To see all the supported frameworks, please visit our GitHub organization page.\nCurrent supported versions # Visit the ESP-IDF project on GitHub to get the updated list of supported versions and the maintenance period.\nespressif/esp-idf Espressif IoT Development Framework. Official development framework for Espressif SoCs. C 17733 8184 Introduction to the ESP32-C6 # The ESP32-C6 is a Ultra-low-power SoC with RISC-V single-core microprocessor, 2.4 GHz Wi-Fi 6 (802.11ax), Bluetooth® 5 (LE), Zigbee and Thread (802.15.4). It has an optional 4 MB flash in the chip’s package, 30 or 22 GPIOs, rich set of peripherals including:\n30 GPIOs (QFN40), or 22 GPIOs (QFN32) 5 strapping GPIOs 6 GPIOs needed for in-package flash Analog interfaces: 12-bit SAR ADC, up to 7 channels Temperature sensor Digital interfaces: Two UARTs Low-power (LP) UART Two SPI ports for communication with flash General purpose SPI port I2C Low-power (LP) I2C I2S Pulse count controller USB Serial/JTAG controller Two TWAI® controllers, compatible with ISO 11898-1 (CAN Specification 2.0) SDIO 2.0 slave controller LED PWM controller, up to 6 channels Motor Control PWM (MCPWM) Remote control peripheral (TX/RX) Parallel IO interface (PARLIO) General DMA controller, with 3 transmit channels and 3 receive channels Event task matrix (ETM) Timers: 52-bit system timer Two 54-bit general-purpose timers Three digital watchdog timers Analog watchdog timer For more details, please see the product ESP32-C6 Datasheet.\nWi-Fi 6 (IEEE 802.11ax) # Wi-Fi 6, also known as IEEE 802.11ax, represents the latest generation of Wi-Fi technology, designed to improve efficiency, capacity, and performance in various environments. Key features of Wi-Fi 6, as seen in devices like the ESP32-C6, include:\n20 MHz-only Non-AP Mode: This mode operates in a non-access point capacity, utilizing a 20 MHz channel width. MCS0 ~ MCS9: Support for modulation and coding schemes ranging from MCS0 to MCS9, which dictate data rates and signal robustness. Uplink and Downlink OFDMA: Orthogonal Frequency Division Multiple Access enables efficient simultaneous connections, particularly beneficial in high-density environments such as stadiums or large office buildings. Downlink MU-MIMO: Multi-user, multiple input, multiple output technology increases network capacity by allowing the transmission of data to multiple devices at the same time. Beamforming: This feature enhances signal quality by focusing the Wi-Fi signal towards the receiving device. Channel Quality Indication (CQI): Provides real-time feedback on the channel conditions, aiding in dynamic adjustments for optimal performance. DCM (Dual Carrier Modulation): Enhances link robustness by using dual carriers, reducing the likelihood of signal degradation. Spatial Reuse: Maximizes parallel transmissions by allowing multiple devices to communicate simultaneously on the same frequency without significant interference. Target Wake Time (TWT): Optimizes power-saving mechanisms by scheduling specific times for devices to wake up and communicate, extending battery life, especially for IoT devices. These advanced features make Wi-Fi 6 a robust and efficient choice for modern wireless communication needs, ensuring better performance, reliability, and energy efficiency.\nWi-Fi MAC support for the 802.11ax:\nTarget wake time (TWT) requester Multiple BSSIDs Triggered response scheduling Uplink power headroom Operating mode Buffer status report Multi-user Request-to-Send (MU-RTS), Multi-user Block ACK Request (MU-BAR), and Multi-STA Block ACK (M-BA) frame Intra-PPDU power saving mechanism Two network allocation vectors (NAV) BSS coloring Spatial reuse Uplink power headroom Operating mode control Buffer status report TXOP duration RTS threshold UL-OFDMA random access (UORA) Resources # ESP32-C6 Datasheet ESP32-C6 Documentation ESP32-C6-DevKit-C Documentation ESP32-C6-DevKit-C Schematic Introduction to the ESP32-C6-DevKit-C # The ESP32-C6-DevKitC-1 is a beginner-friendly development board featuring the ESP32-C6-WROOM-1(U) module, which includes an 8 MB SPI flash. This board offers comprehensive Wi-Fi, Bluetooth LE, Zigbee, and Thread capabilities.\nTo facilitate easy interfacing, most of the I/O pins are accessible through pin headers on both sides. Developers can connect peripherals using jumper wires or mount the ESP32-C6-DevKitC-1 on a breadboard.\nFeatures # Here is the development board feature list:\nESP32-C6-WROOM-1 module Pin Header 5 V to 3.3 V LDO 3.3 V Power On LED USB-to-UART Bridge ESP32-C6 USB Type-C Port for flashing and debug Boot Button Reset Button USB Type-C to UART Port RGB LED connected to the GPIO8 J5 jumper used for current measurement. Board description # Board pin-layout # J1 connector # No. Name Type Function 1 3V3 P 3.3 V power supply 2 RST I High: enables the chip; Low: disables the chip. 3 4 I/O/T MTMS, GPIO4, LP_GPIO4, LP_UART_RXD, ADC1_CH4, FSPIHD 4 5 I/O/T MTDI, GPIO5, LP_GPIO5, LP_UART_TXD, ADC1_CH5, FSPIWP 5 6 I/O/T MTCK, GPIO6, LP_GPIO6, LP_I2C_SDA, ADC1_CH6, FSPICLK 6 7 I/O/T MTDO, GPIO7, LP_GPIO7, LP_I2C_SCL, FSPID 7 0 I/O/T GPIO0, XTAL_32K_P, LP_GPIO0, LP_UART_DTRN, ADC1_CH0 8 1 I/O/T GPIO1, XTAL_32K_N, LP_GPIO1, LP_UART_DSRN, ADC1_CH1 9 8 I/O/T GPIO8 10 10 I/O/T GPIO10 11 11 I/O/T GPIO11 12 2 I/O/T GPIO2, LP_GPIO2, LP_UART_RTSN, ADC1_CH2, FSPIQ 13 3 I/O/T GPIO3, LP_GPIO3, LP_UART_CTSN, ADC1_CH3 14 5V P 5 V power supply 15 G G Ground 16 NC – No connection J3 connector # No. Name Type Function 1 G G Ground 2 TX I/O/T U0TXD, GPIO16, FSPICS0 3 RX I/O/T U0RXD, GPIO17, FSPICS1 4 15 I/O/T GPIO15 5 23 I/O/T GPIO23, SDIO_DATA3 6 22 I/O/T GPIO22, SDIO_DATA2 7 21 I/O/T GPIO21, SDIO_DATA1, FSPICS5 8 20 I/O/T GPIO20, SDIO_DATA0, FSPICS4 9 19 I/O/T GPIO19, SDIO_CLK, FSPICS3 10 18 I/O/T GPIO18, SDIO_CMD, FSPICS2 11 9 I/O/T GPIO9 12 G G Ground 13 13 I/O/T GPIO13, USB_D+ 14 12 I/O/T GPIO12, USB_D- 15 G G Ground 16 NC – No connection Next step # After this introduction, it\u0026rsquo;s time to get started and install the development environment.\nAssignment 1: Install the Espressif-IDE\n","date":"1 July 2024","externalUrl":null,"permalink":"/workshops/esp-idf-with-esp32-c6/introduction/","section":"Workshops","summary":"","title":"ESP-IDF and ESP32-C6 Workshop - Introduction","type":"workshops"},{"content":" Assignment 1: Install Visual Studio Code and ESP-IDF plugin # You will need Visual Studio Code and the installed ESP-IDF framework for this workshop. The first task will therefore be to install all the necessary tools.\nIn both cases, we will follow the instructions on the GitHub pages of the ESP-IDF plugin for VS Code.\nWindows Linux and Mac Installation for Windows\nInstall Visual Studio Code Install the necessary drivers In VS Code, open Extensions (Ctrl + Shift + X or ⇧ + ⌘ + X) Find the ESP-IDF plugin and install it Open View -\u0026gt; Command Palette (Ctrl + Shift + P or ⇧ + ⌘ + P) and type Configure ESP-IDF Extension in the newly opened line Select the Express option and then select Github as download server and release/v5.5 as ESP-IDF version Click \u0026ldquo;Install\u0026rdquo; Installation for Linux and Mac\nInstall Visual Studio Code Install prerequisites according to your distribution (Only step 1, the entire guide deals with installing standalone ESP-IDF, which we don\u0026rsquo;t need right now) In VS Code, open Extensions (Ctrl + Shift + X or ⇧ + ⌘ + X) Find the ESP-IDF plugin and install it Open View -\u0026gt; Command Palette (Ctrl + Shift + P or ⇧ + ⌘ + P) and type Configure ESP-IDF Extension in the newly opened line Select the Express option and then select Github as download server and release/v5.5 as ESP-IDF version Click \u0026ldquo;Install\u0026rdquo; Installing ESP BLE Prov # During one of the tasks, we will also try Wi-Fi provisioning. For this we will need an application through which we will tell our ESP chip the SSID and password for the network.\nYou can either search for the app in the app store of the respective system, or through the links below:\nAndroid: ESP BLE Provisioning iOS: ESP BLE Provisioning VSCode, ESP-IDF plugin and ESP-IDF itself # You may have noticed that during the ESP-IDF plugin installation, you also selected the version of ESP-IDF itself and had the option to choose a local ESP-IDF installation. So how do the ESP-IDF plugin and ESP-IDF itself relate?\nESP-IDF is a standalone framework that can be used without VSCode and plugin. It is controlled from the command line (so it has no GUI) and contains all the logic for building, flashing and monitoring the application. So when you press e.g. the Build button in ESP-IDF Explorer (don\u0026rsquo;t worry, we\u0026rsquo;ll explain what that means in the next lessons), the idf.py build command is called in the end.\nThe ESP-IDF VSCode plugin is a wrapper/adapter that makes ESP-IDF functionality available in VSCode. In other words, it connects VSCode and the ESP-IDF framework: it creates a GUI in the form of ESP-IDF Explorer and at the same time ensures that the buttons perform their function, the output of commands is correctly displayed in VSCode, that the framework configuration is correctly reflected and so on. However, it needs the framework that runs in the background to function.\nThe ESP-IDF framework itself can be used in other ways than just with the VSCode plugin. It has support for Clion, Eclipse, and last but not least, you can use it standalone, directly from the command line.\nHowever, in this workshop we will be using exclusively the VSCode plugin.\nYou should now have a working ESP-IDF plugin for VSCode and ESP-IDF set up. So we can start with the second part of the tutorial:\nAssignment 2: Create a new project with Components\n","date":"30 June 2024","externalUrl":null,"permalink":"/workshops/esp-idf-with-esp32-c6/assignment-1/","section":"Workshops","summary":"","title":"ESP-IDF and ESP32-C6 Workshop - Assignment 1: Install the Espressif-IDE","type":"workshops"},{"content":"This article briefly covers the most important features introduced in Espressif-IDE v3.0.0 and some of their implementation details. If you have further improvement ideas or if you encounter any issues while using Espressif-IDE, do not hesitate to report them in the project\u0026rsquo;s GitHub issues.\nThe article consists of the following major sections:\nIntroduction Deciphering the alphabet soup Why moving to LSP-based editor? clangd setup LSP C/C++ Editor features Conclusion Introduction # We are excited to announce the release of Espressif-IDE v3.0.0 - a cross-platform integrated development environment (IDE) which simplifies and enhances the development experience of IoT applications for Espressif chips, such as the ESP32 or the ESP32-P4.\nEspressif-IDE v3.0.0 is a significant update that brings the long-awaited features:\nEclipse CDT-LSP plugins bringing support for the latest C/C++ standards New LSP C/C++ Editor powered by the LLVM clangd C/C++ language server and offering advanced editor features for ESP-IDF developers For other updates, see the Release notes.\nDeciphering the alphabet soup # The article includes a number of concepts and abbreviations that might look somewhat intimidating, such as LLVM, LSP, CDT-LSP, Clang, clangd, esp-clang, etc. The uninitiated reader might easily get lost. Let\u0026rsquo;s go through those quickly.\nESP-IDF Eclipse Plugin (a.k.a. IEP plugin) is an easy-to-use Eclipse-based development environment which simplifies and enhances standard Eclipse CDT for developing IoT applications on Espressif chips. Espressif-IDE is a cross-platform integrated development environment that combines Eclipse CDT, Eclipse CDT LSP, the ESP-IDF Eclipse Plugin, and more. It is the recommended way to install and use the ESP-IDF Eclipse Plugin. Eclipse CDT (C/C++ Development Tooling) is a fully functional C and C++ Integrated Development Environment (IDE). However, it integrates the GCC (GNU Compiler Collection) development tools that are not as advanced or user-friendly as Clang tools. Although, Clang tools can only be accessed using the Language Server Protocol (LSP) which is missing here. Eclipse CDT LSP (LSP based C/C++ Editor) integrates the Language Server Protocol (LSP) within the Eclipse CDT environment. It enables access to Clang tools that support newer C/C++ standards required by more recent versions of ESP-IDF. Clang is a compiler front-end and tooling infrastructure for C, C++ and other C family languages within the LLVM project. Compared to the GCC (GNU Compiler Collection), Clang offers better support for the newer C++ standards. Instead of Clang, we use its customized version \u0026ndash; esp-clang. esp-clang is a customized version of the Clang compiler specifically tailored for developing IoT applications on Espressif chips. It also includes the clangd server required by the LSP protocol for communication. The esp-clang toolchain is installed as a dependency of ESP-IDF. clangd is a language server that provides IDE-like features, such as code completion, navigation, and documentation, for C, C++, and C family languages. It is part of the LLVM project and leverages the Clang front end to parse and analyze code. In our case, it fetches information from esp-clang and uses the Language Server Protocol (LSP) to communicate with the LSP C/C++ editor. LLVM (just for completeness) is an open-source collection of modular and reusable compiler and toolchain technologies. Initially designed as a set of compiler tools, LLVM has evolved to encompass a broad range of components for developing compilers and other language-related tools. Even though the C/C++ editor uses esp-clang for editor features in Espressif-IDE 3.0.0, the projects are built with the GCC toolchain. Building projects using the esp-clang toolchain is currently an experimental feature. Why moving to LSP-based editor? # Many users have been reporting that the Eclipse CDT Editor/Indexer is unable to resolve headers and compilation units when working with ESP-IDF v5.0 and higher. This issue arises because the Eclipse CDT only supports the versions up to C++14. However, ESP-IDF v5.0 uses C++20 (with GCC 11.2) and ESP-IDF v5.2 uses C++23 (with GCC 13.1).\nBy adopting an LSP-based editor, Espressif-IDE v3.0.0 enables support for newer C/C++ standards required by more recent versions of ESP-IDF. Conversely, the old CDT C/C++ editor and its Indexer are not supported for ESP-IDF projects anymore. However, you can still use the CDT C/C++ editor for non-ESP-IDF projects as-is.\nclangd setup # The LSP C/C++ Editor is configured to work with LSP and clangd by default. Here are some additional setup instructions that might be helpful if you encounter any challenges.\nclangd server setup # The clangd path is configured in the preferences. The Drivers path and --compile-commands-dir path will be set based on the selected target (e.g., esp32, esp32c6) and the project you’re building.\nHowever, if there are any issues with the configuration, see the clangd configuration document.\n.clangd configuration # For a new project, a .clangd configuration file is created by default with the contents provided below. For an existing project, create a .clangd file in its root folder yourself and add required parameters.\nCompileFlags: CompilationDatabase: build Remove: [-m*, -f*] CompileFlags: This key indicates the start of a dictionary (or map) containing compilation flag settings.\nCompilationDatabase: This key specifies the location of the compilation database, which, in our case, is the compile_commands.json file generated by CMake. The value indicates that compile_commands.json is located in the build directory relative to the root of the project. For other paths, see Custom build directory.\nA compilation database (compile_commands.json) is a file that contains an array of command objects, each representing a single compilation unit, providing details like the compiler executable, the compiler flags used, the source files, and the working directory. This database is used by clangd to determine how the source code is compiled.\nRemove: This key lists the patterns, meaning that any compilation flags that start with -m or -f should be removed from the compilation commands. This is needed to remove some errors reported by clangd because Espressif-IDE uses the GCC toolchain by default to build projects. If you choose to use the experimental esp-clang toolchain, this key is not needed.\nHere are the errors you may find in the file if you haven’t added the remove flags as mentioned above.\nFor information about other .clangd configuration options, see Configuration.\nCustom build directory # If you use a custom build directory:\nSet the CompilationDatabase key in the .clangd config file. Set the correct build directory --compile-commands-dir in the additional args in the clangd preferences. Normally, these settings are configured by default, but if something goes wrong, you can double-check them.\nLSP C/C++ Editor features # Errors and warnings # The clangd server runs your code through esp-clang as you type and displays errors and warnings in-place.\nFixes # The clangd server can suggest fixes for many common problems automatically and update the code for you.\nCode completion # As you type, you will see suggestions based on the methods, variables, etc. available in this context.\nFind definition/declaration # To jump to the definition or declaration of a specific compilation unit, hold Ctrl and click the desired unit.\nHover # Hover over a compilation unit to see more information about it, such as its type, documentation, and definition.\nFormatting # The clangd server can reformat your code \u0026ndash; fix indentation, break lines, and reflow comments \u0026ndash; by using the embedded ClangFormat. The clangd language server searches for a .clang-format config in the source folder and its parents.\nA file can be formatted using two ways:\nRight-click your file and choose Source \u0026gt; Format\nOR\nOn file save if you enable Save Actions in the preferences.\nNote that you cannot use the CDT C/C++ formatting styles with the LSP C/C++ editor. However, you can use a feature of ClangFormat to generate the default formatting styles, such as LLVM, GNU, Google, Chromium, Microsoft,Mozilla, WebKit. For example, to generate the GNU formatting style, run in your terminal:\nclang-format -style=GNU -dump=config \u0026gt; .clang-format Editor colors # The LSP C/C++ Editor is derived from the standard Eclipse Text Editor, so you can change the editor color options from the Text Editor preferences. For example, you can modify the line number foreground color and the current line highlight color, among other options available in the Text Editor preferences.\nConclusion # We believe that the new features and enhancements in Espressif-IDE v3.0.0 will significantly improve the development experience for ESP-IDF developers. The transition to an LSP-based editor brings robust support for the latest C/C++ standards and offers powerful IDE-like capabilities that address previous limitations.\n","date":"28 June 2024","externalUrl":null,"permalink":"/blog/espressif-ide-lsp-support/","section":"Blog","summary":"","title":"Espressif-IDE v3.0.0 — LSP Support for C/C++ Editor","type":"blog"},{"content":"","date":"28 June 2024","externalUrl":null,"permalink":"/tags/llvm/","section":"Tags","summary":"","title":"LLVM","type":"tags"},{"content":"Those who develop IoT applications based on Zephyr OS often need to optimize the communication performance. It can be done by tweaking the Wi-Fi network stack parameters. However, how do you evaluate the resulting changes and find the most suitable configuration? In this article, we will overview a method to optimize communication performance by using the iperf and zperf tools.\niperf is a tool that allows generating network traffic to measure the maximum achievable network bandwidth. zperf is a very similar tool but designed for Zephyr OS.\n1. Prepare the testing environment # To evaluate the communication performance, we are going to use the following setup:\nWi-Fi home router ESP32-S3-DevKitC-1 Computer running Ubuntu 22.04 To simplify packet generation and consumption on the Wi-Fi network, we will use iperf on the computer and zperf on the ESP32-S3-DevKitC-1. zperf is included in the standard Zephyr distribution.\nThis structured testing approach allows to systematically analyze the impact of Zephyr parameter adjustments on Wi-Fi communication in various real-world scenarios, including:\nESP32 Sending UDP Packets to PC: PC Sending UDP Packets to ESP32 ESP32 Sending TCP Packets to PC PC sending TCP Packets to ESP32: 2. Configure your computer # We are going to install the following on the computer:\niperf Zephyr OS 2.1. Install iperf # On a terminal window, execute the following command:\nsudo apt-get install iperf Please note that administrator privileges are required to successfully complete this installation.\n2.2. Install Zephyr OS # To setup Zephyr OS and its dependencies, follow the instructions in the subsections.\n2.2.1. Install Dependencies # On a terminal window, execute the following command:\nsudo apt install --no-install-recommends \\ git cmake ninja-build gperf ccache dfu-util device-tree-compiler wget \\ python3-dev python3-pip python3-setuptools python3-tk python3-wheel \\ xz-utils file make gcc gcc-multilib g++-multilib libsdl2-dev libmagic1 2.2.2. Install West # Install the Python script that manages the Zephyr OS build system by running:\npip install west 2.2.3. Initialize Zephyr # Now, initialize Zephyr on your machine by running:\nwest init ~/zephyrproject cd ~/zephyrproject west update 2.2.4. Install Python dependencies # After initializing Zephyr, install additional Python dependencies by running:\npip install -r ~/zephyrproject/zephyr/scripts/requirements.txt 2.2.5. Download and Install Zephyr SDK # For cross-compiling zperf, download and install the Zephyr SDK by running:\ncd ~ wget https://github.com/zephyrproject-rtos/sdk-ng/releases/download/v0.16.8/zephyr-sdk-0.16.8_linux-x86_64.tar.xz wget -O - https://github.com/zephyrproject-rtos/sdk-ng/releases/download/v0.16.8/sha256.sum | shasum --check --ignore-missing tar xvf zephyr-sdk-0.16.8_linux-x86_64.tar.xz cd zephyr-sdk-0.16.8 ./setup.sh 2.2.6. Install Espressif binary blobs # To successfully build your ESP32-S3 Wi-Fi application on Zephyr, install the hal_espressif binary blobs:\nwest blobs fetch hal_espressif 2.2.7. Install udev rules # Additionally, install udev rules to allow flashing ESP32-S3 as a regular user:\nsudo cp /opt/zephyr-sdk-0.16.4/sysroots/x86_64-pokysdk-linux/usr/share/openocd/contrib/60-openocd.rules /etc/udev/rules.d sudo udevadm control --reload 3. Configure your ESP32-S3-DevKitC-1 # To run zperf on your ESP32-S3-DevKitC-1, do the following:\nCreate the overlay file Build and flash zperf 3.1. Create the overlay file # Create the file zephyr/samples/net/zperf/boards/esp32s3_devkitc.overlay and add the following content: /* * Copyright (c) 2024 Espressif Systems (Shanghai) Co., Ltd. * * SPDX-License-Identifier: Apache-2.0 */ \u0026amp;wifi { status = \u0026#34;okay\u0026#34;; }; To the file zephyr/samples/net/zperf/prj.conf, add the following: CONFIG_NET_BUF_DATA_SIZE=1500 CONFIG_NET_IF_UNICAST_IPV4_ADDR_COUNT=1 CONFIG_NET_MAX_CONTEXTS=5 CONFIG_NET_TC_TX_COUNT=1 CONFIG_NET_SOCKETS=y CONFIG_NET_SOCKETS_POSIX_NAMES=y CONFIG_NET_SOCKETS_POLL_MAX=4 CONFIG_POSIX_MAX_FDS=8 CONFIG_INIT_STACKS=y CONFIG_TEST_RANDOM_GENERATOR=y CONFIG_NET_L2_ETHERNET=y CONFIG_NET_SHELL=y CONFIG_NET_L2_WIFI_SHELL=y CONFIG_NET_CONFIG_SETTINGS=y CONFIG_LOG=y CONFIG_SHELL_CMDS_RESIZE=n CONFIG_NET_IPV6=n CONFIG_NET_DHCPV4=n CONFIG_NET_CONFIG_MY_IPV4_ADDR=\u0026#34;\u0026lt;STATION IP ADDRESS\u0026gt;\u0026#34; CONFIG_NET_CONFIG_MY_IPV4_GW=\u0026#34;\u0026lt;GATEWAY IP ADDRESS\u0026gt;\u0026#34; CONFIG_NET_CONFIG_MY_IPV4_NETMASK=\u0026#34;255.255.255.0\u0026#34; CONFIG_NET_TCP_MAX_RECV_WINDOW_SIZE=50000 Replace \u0026lt;STATION IP ADDRESS\u0026gt; and \u0026lt;GATEWAY IP ADDRESS\u0026gt; with the actual IP addresses relevant to your network configuration. 3.2. Build and flash zperf # Note: After updating any configuration parameters in zephyr/samples/net/zperf/prj.conf , build zperf and flash it onto the ESP32-S3-DevKitC-1.\nEnsure that the ESP32-S3-DevKitC-1 is connected to the computer via USB, then run a testing sequence using the following west commands:\nwest build -b esp32s3_devkitc/esp32s3/procpu zephyr/samples/net/zperf --pristine west flash west espressif monitor 4. Run the tests # Before starting the testing sequence, always remember to build and flash zperf.\nAfter the build and flash commands, you will access the zperf terminal. Connect the ESP32-S3-DevKitC-1 to the Wi-Fi router using the following steps:\nwifi connect \u0026lt;SSID\u0026gt; \u0026lt;PASSWORD\u0026gt; net ping \u0026lt;PC_IP\u0026gt; Testing run output:\n*** Booting Zephyr OS build zephyr-v3.5.0-2714-g031c842ecb76 *** [00:00:00.387,000] \u0026lt;inf\u0026gt; net_config: Initializing network [00:00:00.387,000] \u0026lt;inf\u0026gt; net_config: Waiting interface 1 (0x3fcc8810) to be up... [00:00:00.388,000] \u0026lt;inf\u0026gt; net_config: Interface 1 (0x3fcc8810) coming up [00:00:00.388,000] \u0026lt;inf\u0026gt; net_config: IPv4 address: 192.168.15.2 uart:~$ wifi connect \u0026lt;SSID\u0026gt; \u0026lt;PASSWORD\u0026gt; Connection requested Connected uart:~$ net ping 192.168.15.8 PING 192.168.15.8 28 bytes from 192.168.15.8 to 192.168.15.2: icmp_seq=1 ttl=64 time=219 ms 28 bytes from 192.168.15.8 to 192.168.15.2: icmp_seq=2 ttl=64 time=434 ms 28 bytes from 192.168.15.8 to 192.168.15.2: icmp_seq=3 ttl=64 time=356 ms uart:~$ Now, open a second terminal where you will run iperf.\n4.1. ESP32 Sending UDP Packets to PC: # On the iperf terminal, type:\niperf -s -l 1K -u -B 192.168.15.8 On the zperf terminal, type:\nzperf udp upload 192.168.15.6 5001 10 1K 5M 4.2. PC Sending UDP Packets to ESP32: # On the zperf terminal, type:\nzperf udp download 5001 On the iperf terminal, type:\niperf -l 1K -u -c 192.168.15.2 -b 10M 4.3. ESP32 Sending TCP Packets to PC # On the iperf terminal, type:\niperf -s -l 1K -B 192.168.15.8 On the zperf terminal, type:\nzperf tcp upload 192.168.15.8 5001 10 1K 5M 4.4. C Sending TCP Packets to ESP32 # On the zperf terminal, type:\nzperf tcp download 5001 On the iperf terminal, type:\nzperf tcp download 5001 5. Results # To illustrate the tangible impact of adjusting network-sensitive parameters for ESP32-S3 Wi-Fi throughput, we conducted a series of tests, each time modifying the parameter CONFIG_NET_TCP_MAX_RECV_WINDOW_SIZE. The result highlights the performance progression before and after parameter changes:\n5.1. Initial Configuration # The parameter CONFIG_NET_TCP_MAX_RECV_WINDOW_SIZE commented out.\nDEVICE PROTOCOL ROLE DIRECTION RATE ESP32-S3 UDP SERVER DOWNLOAD 10.05 Mbps CLIENT UPLOAD 4.78 Mbps TCP SERVER DOWNLOAD 2.83 Mbps CLIENT UPLOAD 4.22 Mbps 5.2. Modified Configuration (Increased Window Size): # The parameter CONFIG_NET_TCP_MAX_RECV_WINDOW_SIZE=20000\nDEVICE PROTOCOL ROLE DIRECTION RATE ESP32-S3 UDP SERVER DOWNLOAD 10.05 Mbps CLIENT UPLOAD 4.78 Mbps TCP SERVER DOWNLOAD 3.62 Mbps CLIENT UPLOAD 4.22 Mbps 5.3. Further Modified Configuration (Increased Window Size): # The parameter CONFIG_NET_TCP_MAX_RECV_WINDOW_SIZE=50000\nDEVICE PROTOCOL ROLE DIRECTION RATE ESP32-S3 UDP SERVER DOWNLOAD 10.05 Mbps CLIENT UPLOAD 4.78 Mbps TCP SERVER DOWNLOAD 4.07 Mbps CLIENT UPLOAD 4.22 Mbps 5.4. Comparative results chart # These results are provided below.\nThese are valuable insights into the dynamic relationship between network parameters and ESP32-S3 Wi-Fi throughput. It is possible to fine-tune these parameters to achieve optimal performance in diverse network scenarios.\n6. Conclusion # This article presented how to measure communication performance in response to changes in the values of the Zephyr OS Wi-Fi network stack configuration parameter. The ESP32-S3-DevKitC-1 development board was used.\nBy installing, configuring, and utilizing the iperf and zperf tools, and following the procedure outlined in this article, it is possible to tangibly observe the performance evolution as the configuration parameters are modified.\n","date":"24 June 2024","externalUrl":null,"permalink":"/blog/2024/06/zephyr-max-wifi-throughput/","section":"Blog","summary":"How to improve the throuput of network applications with Zephyr on Espressif devices.","title":"Maximizing Wi-Fi Throughput: Fine-Tuning Zephyr for Peak Performance with ESP32 SoCs in IoT Applications","type":"blog"},{"content":" 1. Introduction # Over 2.25 billion cups of coffee are consumed in the world daily [1]. For some people, coffee is part of their daily routine and is just a way to kick things off for a busy day. For others, it is a bit more than this, and can be a tasty source of pleasure at break time. Yet there are also the coffee aficionados, who are notorious for engaging in extensive discussions online regarding the best preparation practices and the complicated physics behind coffee extraction.\nBeing a (sort of) aficionado myself, I have been puzzled by my experience when using my dirty cheap espresso machine at home and noticing how inconsistently I was able to produce a good cup. Sometimes it tasted really delicious, others quite underwhelming and bland. With the same coffee beans and setup, of course.\nAfter some research and observation it became clear to me that one of the main issues is what is called channeling. Channeling is the natural tendency of water to flow through the path of least resistance of a coffee puck (this applies to unpressurized coffee baskets, so please check reference [2] if you are unfamiliar with the term). Much like an electrical current will flow proportionally more through the path of least resistance in a circuit, water will do the same in any physical setting. If during preparation coffee isn’t properly distributed and tamped, channeling is very likely to happen.\nChanneling in an espresso coffee puck [3] One of the strategies employed by more expensive espresso coffee machines to reduce channeling is to do a process called pre-infusion [4]. It consists of dispensing a small amount of water at the start of the brewing process, then wait for some seconds for the coffee puck to absorb water and become soaked. When the water pump is turned on again for the rest of the extraction, channeling is less likely to occur. The reasoning, besides the fact that the grounds are soaked and extraction is already underway, is that as the coffee puck swells it might redistribute better by filling gaps of lesser density in the basket.\nAlthough more expensive equipment will probably allow for better control of the variables involved in the brewing process, there is a limit on how much this yields to better tasting coffee. Cheap and expensive machines are built alike, except for these sometimes sophisticated resources, some whistles and bells and good looks for a premium market and price.\nBasic elements of an espresso machine [5] With these considerations in mind, I decided to use a PID controller algorithm (please check reference [6] if you are unfamiliar with how a PID works) and pre-infusion mechanism for my espresso machine using an ESP32 and RainMaker, in order to verify if it can really help consistently produce better tasting coffee and to play around a bit with control strategies.\n1.1 A word about extraction # One of the most important factors that affect espresso taste is how well it was extracted. Extraction percentage is a measure of how much of the grind solids was successfully diluted by water and went to the cup in the brewing process. This can be assessed using an equipment (refractometer) or by taste. A well extracted cup is clearly tastier than a badly (under) extracted one.\nBelow are the most relevant factors that affect extraction, besides grind quality and size:\nWater temperature: a higher water temperature improves extraction, as it is able to dissolve more solids. A temperature that is too high will affect flavor however, leaving a burnt taste and reducing complexity of flavor by the breakdown of aromatic compounds originally in the coffee. So it is essential to control temperature properly. Coffee ground distribution in the basket: this is a mechanical factor which has a big impact in channeling and thus consistency and richness of flavor. Pre-infusion: if the machine supports it, using this feature helps wetting the coffee puck and diminishes the occurrence of channeling [4]. It is only possible to properly do pre-infusion when temperature is well controlled, because leaving the coffee grounds for an extended period of time in contact with water that is too hot will effectively burn it. Equipment quality: machines that are designed to distribute water evenly through the shower screen (the piece that dispenses water above the grounds) will produce better extracted coffee by passing water evenly through the coffee puck. The purpose of this project is to attempt to improve extraction consistency by proper control of the espresso machine’s boiler temperature and by adding a pre-infusion feature by means of an Embedded device.\n2. Hardware and software # For this project I used a Delonghi EC220 espresso coffee machine, an ESP32 embedded device, a dimmer circuit operated by zero-cross detection to control the boiler’s heating element, a simple relay board to control the water pump and a temperature sensor (thermocouple type K) for probing. The list of materials can be found in the List of Materials section. The GitHub source code can be found at the link provided in GitHub source code.\n2.1 General diagram # The general diagram with the project components can be seen below:\nGeneral diagram for the project 2.2 Prototype build # The following prototype was built for testing. All components and boards are readily available and can be assembled with simple jumper wiring:\nPrototype build 2.3 Prototype fitting # This is a Delonghi EC220 espresso machine. As shown in the picture below, it has a large empty chamber in the right side of the body’s column. It can be used to safely house the prototype components as it is dry and virtually unaffected by the boiler’s heat or humidity.\nPrototype fitting suggestion (source) As this project can be implemented in other espresso machines, the only suggestion made is to safely insulate and fasten all components and avoid housing them near the boiler or where there’s humidity or vapor.\n2.4 RainMaker interface # The following interface was created to allow for a good range of extraction settings, including the machine’s boiler temperature control and a pre-infusion feature. It is created automatically in the mobile application by the RainMaker platform when the project is provisioned (connected to the local wifi):\nRainMaker control settings 3. Results # 3.1 Initial setup # Before trying to control the boiler temperature with the PID and dimmer circuit, I decided to register the temperature curve of the machine in its original state:\nBoiler temperature readings (°C) on the machine without modifications From the chart it is clearly visible how the boiler’s temperature oscillates through a wild wide range after reaching operating temperature (around 103 °C). After running the water pump for some time (around 748 seconds in the chart) the temperature stabilized on an even higher level (105.5 °C), which demonstrates how poor the original temperature management is. Understandably, it operates using electromechanical parts only, which provide limited control capability.\nIdle Brew Max temp 105.50 103 Min temp 97.25 91 delta 8.25 12 Table 1. Temperature (°C) ranges and delta in both idle and brewing state\nWhen the water pump is ON, heat is extracted quickly from the boiler as cold water constantly flow through it. As a consequence, a sharp temperature drop is observed as the electromechanical switch is designed to switch at a specific temperature reading.\n3.2 PID controller # As can be seen below, using a PID controller to control the heating element of the boiler greatly improved temperature stability:\nBoiler temperature readings (°C) on the machine with PID control The temperature ranges in idle and brewing operation are as follows:\nIdle Brew Max temp 100.0 100 Min temp 94.5 96 delta 5.5 4 Temperature (°C) ranges and delta with PID controller\nTo avoid a sharp temperature drop while brewing, a simple strategy of keeping the heating element ON for the whole brewing process produced good results.\nCalibrating a PID controller however is not a simple task, and doing it empirically with no good experience in such type of controllers can be challenging. Next, I show the results of using a different type of controller, based on a Lookup table.\n3.3 P controller (lookup table) # Given the nature of slow change in temperature of such a system and the knowledge necessary to properly calibrate a PID controller, I tested a lookup table algorithm, which is a simple linear interpolation strategy largely used in many control systems. It corresponds to a P control system (proportional only).\nBoiler temperature readings (°C) on the machine with Lookup table control The temperature ranges and delta can be seen in the table below:\nIdle Brew Max temp 96.75 96.50 Min temp 94.50 94.75 delta 2.25 1.75 Table 3. Temperature (°C) ranges and delta with P controller (Lookup)\nWith temperatures oscillating in a much narrower range (around 2.25 °C), it is possible to start brewing virtually anytime after the machine warmed up. The temperature is stable enough to always produce a nice shot without being a variable other than the chosen setpoint.\n4. Conclusion # It is certainly possible to produce delicious coffee using cheap equipment. If anything, as obvious as it may sound, the importance of the quality and freshness of the coffee beans cannot be overstated. Second comes the quality of the grinder, as the physics behind coffee extraction will heavily rely upon this factor to produce a good shot. As a third factor comes the process of extraction and the equipment setup. Enters this project. In my experience using the modified machine over time, it clearly helped consistently extracting tastier coffee. With the versatility and affordability of platforms like the ESP32, combined with creative thinking, simple yet effective IoT solutions can be created to tackle everyday problems. These solutions not only enhance daily life experiences, they help scratch our good old curiosity itch and also provide a fun time.\n5. List of Materials # ESP32 DevKitC v4 board Dimmer control circuit with Triac and zero-crossing signal Thermocouple type K with MAX6675 module Simple relay board (3.3V or 5V) with 3A or 5A current rating, 220V or 110V voltage rating ULN2003 or similar with free-wheeling diode, to drive relay Rapid prototype PCB for water pump drive assembly AC to 5V power supply to power Embedded devices Jumper wiring 6. GitHub source code # Source code for this project can be found in the following address:\nhttps://github.com/raffarost/espresso\n7. Contact info # Author Raffael Rostagno Date March 2024 email raffael.rostagno@espressif.com 8. References # [1] Economics of coffee [2] Pressurized Vs. Non-Pressurized Espresso Baskets [3] How to Prevent Espresso Channeling \u0026amp; Achieve The Perfect Espresso Extraction [4] Why is pre-infusion so important for espresso? [5] BLUKER: How it Works [6] Basics of PID Controllers: Design, Applications, Advantages \u0026amp; Disadvantages ","date":"19 June 2024","externalUrl":null,"permalink":"/blog/2024/06/espresso-machine/","section":"Blog","summary":"This article is about upgrading a regular low cost Espresso machine by adding an ESP32 for both control and connectivity.","title":"Espresso Machine PID controller using ESP32 and RainMaker","type":"blog"},{"content":" Introduction # Are you a maker or an embedded systems enthusiast looking to create applications that work across different development boards with Espressif SoCs like ESP32 or ESP32-S3? Whether you’re using the ESP-WROVER-KIT, M5Stack-CoreS3, ESP32-S3-BOX-3, or other compatible boards, the ESP Board Support Package (ESP-BSP) makes your life easier. In this article, we’ll walk you through how to get started with ESP-BSP, enabling you to focus on your project’s functionality without worrying about hardware differences.\nWhat is ESP-BSP? # ESP-BSP is a collection of Board Support Packages featuring Espressif’s or M5Stack development boards. It provides a convenient way to start a ESP-IDF based project for a specific development board without the need to manually look for drivers and other details. By using ESP-BSP, you can:\nStreamline Hardware Integration: Simplify code and reduce complexity. Enhance Development Speed: Quickly set up and start working on your projects. Access Standardized APIs: Ensure consistency across your projects. Getting Started with ESP-BSP # The following example covers steps for building application for ESP32-S3-BOX-3 which is supported by ESP-BSP.\nHardware Setup # Ensure you have the following hardware:\nESP32-S3-BOX-3 development board. USB-C Cable for power and programming. Prerequisites # Before you begin, make sure you have ESP-IDF v5.3, the official development framework for the ESP32, properly installed and sourced in your shell.\nPre-compiled binaries # The pre-compiled binaries for the following example are also available via ESP Launchpad and can be flashed directly from the web browser.\nTry it with ESP Launchpad Creating Project from Example # Let’s create a simple project using the display_audio_photo example, which is available for the ESP32-S3-BOX-3. This example showcases how to use the display, touch, and audio features.\nFirst, let\u0026rsquo;s see the whole build in Asciinema recording: Initialize a New Project:\nUse the idf.py tool to create a new project from the example:\nidf.py create-project-from-example \u0026#34;espressif/esp-box-3^1.2.0:display_audio_photo\u0026#34; cd display_audio_photo Set the Target:\nEnsure the correct target is set for your project:\nidf.py set-target esp32s3 Note: For users of ESP-IDF 5.3 or newer, it is necessary to add the following dependency with the corrected I2C driver (error message at runtime: CONFLICT! driver_ng):\nidf.py add-dependency \u0026#34;espressif/esp_codec_dev==1.1.0\u0026#34; Check the Configuration of Dependencies:\nCheck that file main/idf_component.yml contains dependency on BSP specific to you board.\nConfiguration for ESP32-S3-BOX-3:\n## IDF Component Manager Manifest File dependencies: espressif/esp-box-3: \u0026#34;^1.2.0\u0026#34; esp_jpeg: \u0026#34;^1.0.5~2\u0026#34; esp_codec_dev: public: true version: \u0026#34;==1.1.0\u0026#34; ## Required IDF version idf: version: \u0026#34;\u0026gt;=5.0.0\u0026#34; Configuration for ESP32-S3-BOX:\n## IDF Component Manager Manifest File dependencies: espressif/esp-box: \u0026#34;^3.1.0\u0026#34; esp_jpeg: \u0026#34;^1.0.5~2\u0026#34; esp_codec_dev: public: true version: \u0026#34;==1.1.0\u0026#34; ## Required IDF version idf: version: \u0026#34;\u0026gt;=5.0.0\u0026#34; Configuration for M5Stack-CoreS3:\n## IDF Component Manager Manifest File dependencies: espressif/m5stack_core_s3: \u0026#34;^1.1.0\u0026#34; esp_jpeg: \u0026#34;^1.0.5~2\u0026#34; esp_codec_dev: public: true version: \u0026#34;==1.1.0\u0026#34; ## Required IDF version idf: version: \u0026#34;\u0026gt;=5.0.0\u0026#34; Build and Flash the Project:\nCompile and flash your application to the ESP32-S3-BOX-3:\nidf.py build flash monitor Note: Use Ctrl+] to quit the monitor application.\nNote: Some models of M5Stack CoreS3 have QUAD SPI RAM, in that case please use the following command for the build, which will take into account specific settings for M5Stack CoreS3 from the file:\nidf.py build -DSDKCONFIG=sdkconfig.bsp.m5stack_core_s3 Exploring the Example # Once the application is running, you’ll see the following features in action:\nDisplay: Shows images, text files, and more. Touch: Interacts with the display. Audio: Plays sound files. Let\u0026rsquo;s look at the source code of the example. The Board Support Package provides an API that allows you to initialize a board. The application code is cleaner and does not require board-specific details, such as pins hard-coded in the application code.\n#include \u0026#34;esp_log.h\u0026#34; #include \u0026#34;bsp/esp-bsp.h\u0026#34; #include \u0026#34;app_disp_fs.h\u0026#34; static const char *TAG = \u0026#34;example\u0026#34;; void app_main(void) { /* Initialize and mount SPIFFS */ bsp_spiffs_mount(); /* Initialize I2C (for touch and audio) */ bsp_i2c_init(); /* Initialize display and LVGL */ bsp_display_start(); /* Set default display brightness */ bsp_display_brightness_set(APP_DISP_DEFAULT_BRIGHTNESS); /* Add and show LVGL objects on display */ app_disp_lvgl_show(); /* Initialize SPI flash file system and show list of files on display */ app_disp_fs_init(); /* Initialize audio */ app_audio_init(); ESP_LOGI(TAG, \u0026#34;Example initialization done.\u0026#34;); } Simulating the ESP32-S3-BOX-3 with Wokwi # You can also simulate the application with ESP-BSP for ESP32-S3-BOX-3 using the Wokwi simulator from your development environment using a plugin for VS Code, Espressif IDE, or JetBrains IDEs. This allows you to test your applications without needing the physical hardware.\nTo set up the simulation, you need to add two files to your project: wokwi.toml and diagram.json in the root of the project.\nContent of wokwi.toml\n[wokwi] version = 1 elf = \u0026#34;build/uf2.bin\u0026#34; firmware = \u0026#34;build/uf2.bin\u0026#34; Content of diagram.json\n{ \u0026#34;version\u0026#34;: 1, \u0026#34;author\u0026#34;: \u0026#34;Wokwi.com\u0026#34;, \u0026#34;editor\u0026#34;: \u0026#34;wokwi\u0026#34;, \u0026#34;parts\u0026#34;: [ { \u0026#34;type\u0026#34;: \u0026#34;board-esp32-s3-box-3\u0026#34;, \u0026#34;id\u0026#34;: \u0026#34;esp32\u0026#34;, \u0026#34;top\u0026#34;: -24.91, \u0026#34;left\u0026#34;: -388.54, \u0026#34;attrs\u0026#34;: { \u0026#34;psramSize\u0026#34;: \u0026#34;16\u0026#34;, \u0026#34;flashSize\u0026#34;: \u0026#34;16\u0026#34; } } ], \u0026#34;connections\u0026#34;: [ [ \u0026#34;$serialMonitor:RX\u0026#34;, \u0026#34;esp32:G14\u0026#34;, \u0026#34;\u0026#34;, [] ], [ \u0026#34;$serialMonitor:TX\u0026#34;, \u0026#34;esp32:G11\u0026#34;, \u0026#34;\u0026#34;, [] ] ], \u0026#34;dependencies\u0026#34;: {} } Use the following command to build the UF2 image for your project. The Wokwi simulator will pick up this binary and run it.\nidf.py uf2 Now you can start the simulation in your favorite IDE.\nConclusion # With ESP-BSP, you can quickly develop and port your applications across various boards with Espressif SoC, saving time and effort. Whether you’re building a new project or upgrading an existing one, ESP-BSP simplifies your development process.\nUseful Links # Board Support Packages at Component Registry ESP-BSP GitHub Repository ESP-BSP Documentation ESP-BOX-3 BSP Example ESP-IDF Installation Guide Wokwi Simulator with ESP32-BOX-3 support ","date":"18 June 2024","externalUrl":null,"permalink":"/blog/simplify-embedded-projects-with-esp-bsp/","section":"Blog","summary":"","title":"Simplify Your Embedded Projects with ESP-BSP","type":"blog"},{"content":" DevCon24 # Espressif DevCon24, the third edition of Developers conference made by Developers for Developers!\nThe DevCon24, was broadcasted online from September 3 to 5, 13.00 - 18.00 CEST. During the three-day online conference, we provided you with nearly 30 talks created by Espressif technical experts, covering a wide range of topics, including Thread, Matter, ESP-IDF, Arduino Core for ESP32, ESP RainMaker Cloud solution, RUST and more.\nFor more information, please visit DevCon24\nThis event was streamed on Espressif\u0026rsquo;s YouTube channel.\nHere is the first day of DevCon24:\nHere is the second day of DevCon24:\nHere is the third day of DevCon24:\n","date":"11 June 2024","externalUrl":null,"permalink":"/events/devcon24/","section":"Events","summary":"","title":"Espressif DevCon24","type":"events"},{"content":" Espressif Summit Brazil 2024 # We are pleased to announce the first in-person Espressif event in Brazil, taking place in Campinas from July 17 to 18, 9 am - 6 pm. On the first day, we will present talks about our most recent products, including the ESP32-P4, ESP32-C5, ESP-IDF, Nuttx, Zephyr, low-power applications, Arduino, MQTT, and more.\nThe activities are as follows:\nDay 1: we will present talks about our most recent products, including the ESP32-P4, ESP32-C5, ESP-IDF, Nuttx, Zephyr, low-power applications, Arduino, MQTT, and more. Day 2: workshops will be presented in two different tracks. The topics include “Introduction to ESP-IDF with the ESP32-C6,” “IoT Workshop with RainMaker and Matter,” and “Zephyr with ESP32.” For details, please refer to Registration. All the talks and workshops will be presented by Espressif experts and will be mostly in Portuguese.\nLocation # Vitoria Hotel Concept, Campinas, SP\nTime: Starting from 9 am\nUse the promotional code ESPRESSIF and get a 12% discount on your stay.\nAgenda for July 17 # Time Activity Speaker 9:00 Credenciamento e welcome coffee Espressif 9:30 Abertura e keynote Ricardo Tafas - Software Manager, Pedro Minatel - DevRel Manager 10:00 Apresentação dos novos produtos e soluções Espressif Pedro Minatel - DevRel Manager 11:00 Introdução ao desenvolvimento com o ESP-IDF v5.3 Ivan Grokhotkov - VP Platforms 11:30 Ferramentas de desenvolvimento Espressif Ivan Grokhotkov - VP Platforms 12:00 Almoço (não incluso no evento) 13:00 Aplicações de baixo consumo com o ESP32-C6 e WiFi6 Euripedes Rocha - Networking Manager 13:30 Aplicações IHM e os novos recursos do ESP32-P4 Pedro Minatel - DevRel Manager 14:00 Introdução ao NuttX Tiago Medicci - Software Engineer 15:00 Coffee Break 15:30 Desenvolvimento Arduino como componente do ESP-IDF Rodrigo Garcia - Software Engineer 16:00 Boas práticas de rede e MQTT com o ESP32 Euripedes Rocha - Networking Manager 17:00 Introdução ao Zephyr e debugging com openOCD Lucas Tamborrino - Software Engineer 18:00 Q\u0026amp;A geral e networking Espressif Systems Registration # The event is free for any participant, and registration can be done for each day and workshop with the following links:\nAll the tickets are sold-out for now. Talks on July 17: Espressif Summit Brazil 2024 Workshops July 18:\nTrack 1: Workshop: Introdução ao ESP-IDF com o ESP32-C6 (EN) - 10:00 – 13:00 Workshop: Introdução ao ESP-IDF com o ESP32-C6 (PT) – 14:00 – 17:00 Track 2: Workshop: Introdução em IoT com RainMaker e Matter - 10:00 – 13:00 Workshop: Desenvolvendo aplicações com Zephyr e ESP32 – 14:00 – 17:00 ","date":"10 June 2024","externalUrl":null,"permalink":"/events/summit-brazil-24/","section":"Events","summary":"","title":"Espressif Summit Brazil 2024","type":"events"},{"content":"","date":"7 June 2024","externalUrl":null,"permalink":"/tags/book/","section":"Tags","summary":"","title":"Book","type":"tags"},{"content":"","date":"7 June 2024","externalUrl":null,"permalink":"/tags/review/","section":"Tags","summary":"","title":"Review","type":"tags"},{"content":" Simplified Embedded Rust: A Comprehensive Guide to Embedded Rust Development # By Omar Hiari # Omar Hiari\u0026rsquo;s \u0026ldquo;Simplified Embedded Rust\u0026rdquo; series offers two books, each tailored to different stages of a developer\u0026rsquo;s Rust and embedded systems journey. The two books, \u0026ldquo;ESP Core Library Edition\u0026rdquo; and \u0026ldquo;ESP Standard Library Edition,\u0026rdquo; provide comprehensive guidance on using Rust for embedded development on Espressif chips, specifically the ESP32-C3.\nWhy Two Books? # The Core Library Edition focuses on a no_std environment, giving developers complete control over their code, ideal for performance-critical applications. The Standard Library Edition, on the other hand, leverages the ESP-IDF framework, making it easier for beginners by providing access to all features supported by ESP-IDF.\nKey Features of Both Books # Comprehensive Content: Each book spans 200+ pages, covering topics such as GPIO, ADCs, Timers, PWM, Serial Communication, and many more. Hands-On Learning: Each chapter includes conceptual background, configuration steps, practical examples, and exercises. Example Compatibility with Wokwi: All examples can run on the Wokwi simulator, accessible via web, VS Code, and JetBrains. This allows learners to simulate projects without physical hardware, using pre-wired templates to simplify the learning process. ESP Core Library Edition # Overview: The ESP Core Library Edition is designed for developers with some embedded experience. This book uses the no_std environment, offering a lean and efficient approach suitable for performance-critical applications.\nExpectations: Readers should be aware that this edition is ideal for those who are comfortable with Rust and looking to leverage its performance in a bare-metal environment. The focus on no_std means it’s geared towards developers who need complete control over their code for efficiency and performance.\nESP Standard Library Edition # Overview: The ESP Standard Library Edition is aimed at beginners in embedded systems and Rust developers transitioning to embedded development. This book uses the standard library, making it easier to grasp fundamental concepts without the complexities of a no_std environment.\nExpectations: This edition is perfect for those new to embedded systems or Rust. It provides a gentle introduction to embedded Rust development using the standard library, making it accessible and less daunting for beginners.\nConclusion # Omar Hiari’s \u0026ldquo;Simplified Embedded Rust\u0026rdquo; series is a valuable resource for developers at various stages of their learning journey. Both books offer structured and practical insights into embedded Rust development, suited for different levels of expertise. For anyone looking to dive into embedded Rust with Espressif chips, these books provide a robust foundation, leveraging the power of the Wokwi simulator for an accessible and immersive learning experience.\nAdditionally, while the books are written with the ESP32-C3 in mind, the knowledge and skills gained from these resources are applicable to other Espressif chips, including the newly announced ESP32-P4, ensuring that developers are well-prepared for future projects.\nRecent Developments # An update has been rolled out on 10/20/2024 to support the latest ESP crate and Rust compiler versions, along with expanded support for more ESP devices. Updates include the following:\nno-std edition: compatibility with the esp-hal v0.21 crate. std edition: compatibility with the esp-idf-svc v0.49 crate. no-std repositories: new embassy-sync examples added compatible with the esp-hal-embassy 0.4.0 crate. std and no-std repositories: Expanded support for ESP32, ESP32-S2, ESP32-S3, and the existing ESP32-C3. Various typo, code, and reference fixes across both editions. Additional Resources # The Core Library Edition The Standard Library Edition The Embedded Rustacean Blog The Embedded Rustacean Newsletter Wokwi Simulator ESP-RS Community Resources By addressing the community\u0026rsquo;s needs and continuously updating content, \u0026ldquo;Simplified Embedded Rust\u0026rdquo; aims to be an indispensable guide for mastering embedded Rust development on Espressif devices.\n","date":"7 June 2024","externalUrl":null,"permalink":"/blog/books-simplified-embedded-rust/","section":"Blog","summary":"","title":"Simplified Embedded Rust: A Comprehensive Guide to Embedded Rust Development","type":"blog"},{"content":"Welcome to the Espressif workshops! Here you can find workshops prepared by Espressif and partners for the community.\n","date":"3 June 2024","externalUrl":null,"permalink":"/workshops/","section":"Workshops","summary":"","title":"Workshops","type":"workshops"},{"content":"Welcome to the Espressif IoT Development Framework (ESP-IDF) workshop!\nAbout this workshop # By participating in this workshop, you will gain a deeper understanding of how the Espressif IoT Development Framework (ESP-IDF) and ESP32-C6 System on a Chip (SoC) work. Through a number of hands-on assignments covering a range of essential skills, you will learn to create even better and more efficient IoT applications for your projects!\nSpecifically, in this workshop we will go through the installation of the ESP-IDF framework and ESP-IDF plugin for VSCode. Then we will move on to creating our own project, which we will try to build, upload and debug. In the following chapters, we will learn how to use components in your projects, blink with addressable LEDs, configure ESP-IDF, connect to Wi-Fi and finally some tricks for working with the low-power core that is part of the ESP32-C6 SoC.\nThis workshop will certainly bring a lot of interesting information even to those who use other chips from the ESP32 family. However, keep in mind that not all chips support everything that ESP32-C6 supports!\nAgenda # If you have met the prerequisites, we can start with the individual chapters:\nIntroduction: ESP-IDF Presentation: Initial introduction to our ESP-IDF framework, followed by basic information about the ESP32-C6 chip and the devkit on which this tutorial will be demonstrated. Assignment 1: Install ESP-IDF in VSCode: Installing the necessary tools to start development. Assignment 2: Create a New Project with Components: How to efficiently create, structure and organize a project. Assignment 3: Connect to Wi-Fi: The absolute basics for most IoT projects. Assignment 4: NVS (Non-Volatile Storage): Storing persistent data. Assignment 5: Wi-Fi provisioning: More detailed work with Wi-Fi: setting up and configuring Wi-Fi networks. Assignment 6: Protocols: Demonstration of several communication protocols that ESP32-C6 supports, including TLS implementation for secure communication. Assignment 7: Experiments with low-power core: Demonstration of working with low-power core for applications where energy consumption is an important factor. Prerequisites # To follow this workshop, you will need both hardware and software equipment.\nRequired hardware:\nComputer running Linux, Windows or macOS operating system ESP32-C6-DevKitC or ESP32-C6-DevKitM USB cable (supporting power + data) compatible with the devkit above Visual Studio Code with ESP-IDF plugin (installation is described in the next section) Required software:\nVisual Studio Code ESP-IDF plugin for VS Code ESP BLE Prov app: Android: ESP BLE Prov iOS: ESP BLE Prov Time Requirements # Estimated time: 180 min Feedback # If you have any feedback about the workshop, feel free to start a new discussion on GitHub.\nConclusion # We hope that the workshop will bring you knowledge that will serve as a solid foundation for your future projects. Thank you for the time and effort you devoted to the workshop, and we look forward to the projects you will create with our chips in the future!\n","date":"3 June 2024","externalUrl":null,"permalink":"/workshops/esp-idf-with-esp32-c6/","section":"Workshops","summary":"","title":"ESP-IDF and ESP32-C6 Workshop","type":"workshops"},{"content":"","date":"3 June 2024","externalUrl":null,"permalink":"/tags/espressif-vscode-plugin/","section":"Tags","summary":"","title":"Espressif VSCode Plugin","type":"tags"},{"content":"This hands-on series of workshops introduces the Espressif IoT Development Framework (ESP-IDF) through the Integrated Development Environments (IDE). After this workshop, you will be able to use the IDEs to enhance the development performance of your projects.\nEspressif-IDE # We will learn how to install and configure the Espressif-IDE on various operating systems, including Windows, Linux, and macOS. The workshop also covers the hardware prerequisites, such as the ESP32 board with a USB to serial interface and/or debug port, and software prerequisites, including Java, Python, Git, and specific versions of Espressif-IDE and ESP-IDF.\nThe workshop is estimated to take between 30 to 45 minutes to complete. It is designed to be interactive and engaging, providing participants with practical skills and knowledge that they can apply in their own IoT development projects.\nIn this part, the Eclipse bundle, Espressif-IDE, will be introduced.\nPrerequisites # To follow this workshop, ensure you meet the prerequisites described below.\nHardware Prerequisites # Computer running Windows, Linux, or macOS ESP32 board with a USB to serial interface and/or debug port USB CDC/JTAG USB cable (data + power) compatible with your development board Software prerequisites # Required for manual installation\nUsbDriverTool Java 17 or above Python 3.6 or above Git Espressif-IDE 3.0.0 ESP-IDF v5.2.2 Downloads # ESP-IDF Offline Installer for Windows (recommended for Windows users) Espressif-IDE v3.0.0 macOS aarch64 Espressif-IDE v3.0.0 macOS x86-64 Espressif-IDE v3.0.0 Windows Espressif-IDE v3.0.0 Linux Extra resources # espressif/idf-eclipse-plugin Espressif-IDE (ESP-IDF Eclipse Plugin) for ESP-IDF CMake based projects 5.x and above Java 359 133 Completion time # Estimated completion time: 30 to 45 min Installation # Now it\u0026rsquo;s time to install the Espressif-IDE. Please follow the instructions according to your operating system.\nWindows # For Windows, the recommended method is to install using the ESP-IDF offline installer. If you already have the ESP-IDF installed on your system and you are currently working with it, you can reuse the installation and proceed directly with the Espressif-IDE installation.\nPlease follow the instructions in the step-by-step guide:\nLinux and macOS # If your system is Linux or macOS, you can install the Espressif-IDE using the links provided in the downloads section.\nMake sure to install all prerequisites before continuing with the Espressif-IDE installation.\nInstalling ESP-IDF # To install the ESP-IDF, you can do it in two different ways:\nManual installation ESP-IDF Manager (Espressif-IDE tool) Depending on your operating system, we recommend installing via the offline installer. If your operating system does not support it, then the installation can be done via the ESP-IDF Manager inside the Espressif-IDE.\nThe manual installation can also be used as an alternative solution.\nFor this workshop, we will skip the manual installation, however, you can see how it works in our Get Started Guide.\nAfter the installation process is completed, you will be able to open the Espressif-IDE.\nThe first step is to select your workspace folder. This folder is where all your projects will be stored.\nOnce you have selected it, you can proceed by clicking on the Launch button. If everything is running as expected, you will see the welcome screen.\nInstalling, upgrading or downgrading ESP-IDF versions # Before creating the first project, we need to install ESP-IDF.\nGo to Espressif -\u0026gt; ESP-IDF Manager\nSelect Add ESP-IDF to install the SDK.\nNow you can select how and where ESP-IDF will be installed or selected from the existing installation.\nIf you are installing a new SDK, you can select the version and the path to which it will be installed.\nYou can install ESP-IDF by selecting the version you want to install or you can use a pre-existing installation.\nHowever, if you want to use the existing ESP-IDF, select the path where it is located. Click on Finish to start the installation process.\nThe installer will download and install all pre-requisites.\nAfter the installation process completes, you will see the installed version in the ESP-IDF Manager list.\nIf you decide to install multiple versions, the list will show all the installed versions. You can select only one version at once.\nCreating a new project # To create a new project, go to File -\u0026gt; New -\u0026gt; Project.\nOn the New Project screen, select Espressif -\u0026gt; Espressif IDF Project and click Finish.\nNow we need to set the option Create a project using one of the templates and select the blink project.\nSelect the target for this project, in this case, the ESP32-C6.\nClick Finish to create the project in the selected workspace.\nBuilding the Project # Building the project is done by clicking the button with a hammer icon, as shown in the next image.\nBy clicking the build button, the build process will start. This operation can take a while depending on your operating system.\nAfter the build is complete, you will be able to flash the application to the device.\nProject Configuration # If you need to change any project or ESP-IDF configuration, this can be done by opening the sdkconfig file. After opening this file, you will see the SDK configuration interface, as shown in the image.\nPlease note that if you change anything in this file, the build process will rebuild everything.\nCreating a new configuration menu # ESP-IDF uses a method to configure the SDK based on the kconfiglib, a Python extension of the Kconfig system, called esp-idf-kconfig.\nESP-IDF configuration # This is one of the most important steps before flashing your application onto the device. You will need to change some of the default configurations in order to better fit the SoC or module in use to the SDK.\nA good example of a setting you will probably need to change is the flash memory size. As default, some SoCs come with the 2MB flash size selected. To change that, you will need to use the SDK configuration.\nTo make your project easier to configure, there are different ways to set default configurations or to create custom menus for the SDK configuration tool.\nHands-on session # For this hands-on session, we will create a new configuration menu to set the Wi-Fi credentials (SSID and password). We will also understand how to pre-define some configurations as default, improving the configuration process by avoiding configuration mistakes.\nCreating a new configuration menu First, we need to create a new file called Kconfig.projbuild inside the main folder.\nmenu \u0026#34;WiFi Configuration\u0026#34; config ESP_WIFI_SSID string \u0026#34;WiFi SSID\u0026#34; default \u0026#34;default_ssid\u0026#34; help SSID (network name) to connect to. config ESP_WIFI_PASSWORD string \u0026#34;WiFi Password\u0026#34; default \u0026#34;default_password\u0026#34; help WiFi password (WPA, WPA2, or WPA3). endmenu Here the menu name is WiFi Configuration with 2 configuration parameters:\nConfig ESP_WIFI_SSID with string data type named \u0026ldquo;WiFi SSID\u0026rdquo; with the default value of \u0026ldquo;default_ssid\u0026rdquo;. Config ESP_WIFI_PASSWORD with string data type named \u0026ldquo;WiFi Password\u0026rdquo; with the default value of \u0026ldquo;default_password\u0026rdquo;. There are more data types, such as bool and int. This file will be used by this project when calling the SDK configuration interface.\nTo use the new configuration entries, you can do:\n1 2 #define WIFI_SSID CONFIG_ESP_WIFI_SSID #define WIFI_PASS CONFIG_ESP_WIFI_PASSWORD As you can see, you will need to include the prefix CONFIG_ to the config name.\nNow, run the configuration menu to see the recently created menu for the Wi-Fi credentials. If you are not able to see the menu, you can try to do a Project Full Clean and build again.\nEvery time you change the SDK configuration, the build system will rebuild and it might take a while depending on your system. Important: This configuration menu will be used for the next assignment.\nSetting the default configuration You might have noticed that you will need to change the new configuration entries manually, if you are not going to define your default values. To overcome this, you can define the default SDK configuration values. This is valid for all the configuration values, not only for those you have just created.\nTo do this, in the folder where you have the sdkconfig file, create the sdkconfig.defaults file. We do not recommend that you change the sdkconfig file manually, so the way to define your own default configuration values is through the sdkconfig.defaults file.\nCONFIG_ESPTOOLPY_FLASHSIZE_8MB CONFIG_ESP_WIFI_SSID=\u0026#34;EspressifWorkshop\u0026#34; CONFIG_ESP_WIFI_PASSWORD=\u0026#34;espressifsummit\u0026#34; When you run the SDK configuration for the first time, the values from the defaults file will be applied. You can also use the reconfigure to apply again the default values or you can delete the sdkconfig file manually.\nIf you have different targets, you can define default configuration files based on the selected target. To do that, the file name should contain the target name. For example, for the ESP32-C6 chip, the file name should be sdkconfig.defaults.esp32c6.\nFlashing the Device # Before flashing the device, we need to define the communication port by clicking the gear icon.\nIf your board is already connected to your computer, and the operating system is able to recognize it, you will see the available COM ports in the drop-down menu.\nIf you have a devkit with more than one port, make sure you are using the one labeled USB You can also debug using an external JTAG, like ESP-PROG.\nPlease select the one recognized as USB JTAG/serial debug unit.\nOnce you select the correct communication port, the board will be detected as shown in the image.\nNow to flash, you can click on the green orb with a \u0026ldquo;play\u0026rdquo; icon labeled as Launch in 'run' mode.\nAfter a successful flashing procedure, you will see the message in the console output:\nIf everything worked correctly, you will see the RGB LED blinking in white color.\nTODO: Add a gif with the board blinking.\nMonitoring the Serial Output # In this project, the application will print some log output from the USB serial interface.\nDebugging # Debugging is a crucial part of software development. It allows you to find and fix issues in your code. When working with the ESP32, the Espressif-IDE provides a built-in debugger that can be used to debug your applications.\nSome ESP32 SoCs come with a build-in USB JTAG and USB CDC interfaces. On the ESP32-C6 devkit, the USB JTAG port is the USB port with the label USB. Make sure you are using a good quality USB cable with data.\nYou can use an external compatible JTAG, like ESP-PROG or build your own using the ESP USB Bridge with an ESP32-S2 or ESP32-S3.\nHands-on debugging # Change the mode and the configuration to debug The first step before debugging is to change the Launch Mode to Debug and set Launch Configuration to blink Configuration.\nChange the default debug configuration Now open the debug Edit Configuration by clicking the gear icon in Launch Configuration.\nOn the tab Main select the application to be debugged on the C/C++ Application. Select the blink.elf on the Search Project... button. On the tab Debugger, check if the correct SoC and the board debug device are selected. On the tab Startup, clear the Flash every time with application binaries box. This is done to avoid building the application and flashing the device again. Launch in \u0026lsquo;Debug\u0026rsquo; mode Once the project is built, you can start a debugging session by clicking on the bug icon in the IDE. This will launch the debugger and attach it to your ESP32 device. There is an option to build and flash every time you start debugging, however, we will disable this option for this workshop to save time.\nDebug During a debugging session, you can control the execution of your program by setting breakpoints, stepping through your code, inspecting variables, and watching expressions. Breakpoints can be set by clicking in the margin of the code editor next to the line of code where you want the breakpoint.\nWhen the program execution hits a breakpoint, it will pause, and you can inspect the current state of your program. The IDE provides several views to inspect the state of your program, such as the Variables view, the Call Stack view, and the Watch view.\nRemember, debugging is a powerful tool that can help you understand how your code is executing and where problems may be occurring.\nTroubleshooting # If you have issues debugging, please read our Espressif-IDE\u0026rsquo;s Troubleshooting guide.\nTools # Partition table editor # \u0026hellip;\nNVS editor # \u0026hellip;\nComponents # \u0026hellip;\nConclusion # In this workshop, we have walked through the process of setting up and using the Espressif-IDE for ESP32 development. We\u0026rsquo;ve covered the installation process, project creation, building and flashing the project to the device, and using the built-in debugger to troubleshoot your code.\nWe\u0026rsquo;ve also briefly touched on some of the additional tools provided by the IDE, such as the partition table editor and component manager/registry. These tools further enhance the development experience by providing more control and customization options for your IoT projects.\nBy now, you should have a solid understanding of how to use the Espressif-IDE for your ESP32 projects. Remember, the key to mastering any new tool is practice. Don\u0026rsquo;t hesitate to experiment with different settings and features, and always be on the lookout for ways to improve your workflow.\nThank you for participating in this workshop. We hope you found it informative and helpful. Happy coding!\nNext steps # ESP-IDF Workshop ","date":"3 June 2024","externalUrl":null,"permalink":"/workshops/espressif-ide/","section":"Workshops","summary":"","title":"Espressif-IDE Workshop","type":"workshops"},{"content":"","date":"3 June 2024","externalUrl":null,"permalink":"/series/ide/","section":"Series","summary":"","title":"IDE","type":"series"},{"content":"","date":"13 May 2024","externalUrl":null,"permalink":"/tags/community/","section":"Tags","summary":"","title":"Community","type":"tags"},{"content":"We will explore the following topics:\nMotives for creating the portal Goals to be achieved with the portal Content categories published on the portal Collaboration and contribution scenarios for the community Motives # Historically, the community around Espressif\u0026rsquo;s ESP8266 and ESP32 chips played the key role in making Espressif well-known and respected worldwide. Independent enthusiasts popularized our products through the word of mouth, countless projects, and articles on embedded technology blogs.\nOwing to these independent enthusiasts, lots of learning materials have been generated and published online. Such materials have been offering a helping hand to those making the first steps with our products and to seasoned developers alike. This, in turn, allowed us to dedicate more resources to developing new products and let the community spread the word.\nOne long-term drawback of such arrangement is that not up-to-date or otherwise inadequate information about Espressif\u0026rsquo;s hardware and software products, their features, or usage is bound to slip into the community articles. This happens due to lack of direct access to the engineers who create the products. Conversely, trying to spot such faulty details and fix them is a never-ending uphill battle.\nIn addition, as our hardware products, such as chips, modules, and development boards, grow in variety and acquire new features, so does the software ecosystem around them. Apart from the well-known in the community Espressif AIoT Development Framework (ESP-IDF), lots of other frameworks, components, and libraries are being developed.\nWith such richness and variety of products, it takes a great deal of effort to keep everyone updated even within Espressif itself, let alone the community. Unfortunately, in today\u0026rsquo;s world where software and even hardware design is permeated with the agile approach, circulation of outdated or inadequate information is a big and solid part of reality, and, for better or worse, it is impossible to version the collective knowledge in a git repository.\nIn an effort to disseminate the most up-to-date information about all Espressif products, we have been increasingly dedicated not only to improving documentation but also to publishing articles in the ESP journal on Medium, creating videos (YouTube, BiliBili), answering questions on the ESP32 forum. We even established our own annual conference \u0026ndash; DevCon.\nNevertheless, all these sources of information may sometimes appear siloed, like an orchestra without a conductor. To further improve the quality of information, keep it up to date, and further enrich content, we decided to launch our own developer portal. The Espressif Developer Portal is conceived as a conductor that will unify all sources of information from within Espressif into a cohesive and harmonious orchestra.\nAlso, the portal should become the forum in its true sense \u0026ndash; the public meeting place for open discussions between our engineers and community. This is where the community will share ideas, concerns, feedback, and offer solutions. The ripples from these activities will at least improve documentation and the user experience and at most will have potential influence on our upcoming products.\nGoals # The main goals for the Espressif Developer Portal are as follows:\nReduce the distance between Espressif engineers and the community and let the community drive the developer portal Create an up-to-date knowledge base about Espressif products verified and endorsed by the engineers Facilitate discussions to further improve Espressif products and their user experience Map out and unify all Espressif content and resources scattered around multiple places Simplify the process of contributing content for both Espressif engineers and community members to share knowledge and exert influence on the community Identify and fill in the gaps in documentation and learning materials Proactively create content covering problematic areas to reduce the number of questions and GitHub issues Build awareness of lesser known Espressif products and solutions Content categories # As it is seen now, the main content categories on the portal will be:\nAwesome: Links to relevant content or resources related to a particular product. News: Announcements about upcoming products, their releases, reviews, demos, project sharing, etc. Tutorials: Hands-on content, such as step-by-step guides, how-to, etc. for using popular products and their features. Articles: Overviews of products, in-depth explanations of features and concepts, etc., overview of notable applications based on Espressif products. Workshops: Content to be used for training purposes, event workshops, online webinar, etc. Events: Announcements about upcoming internal and external related events. These categories are preliminary and may change over time according to the community preferences.\nCollaboration and contribution # You, dear members of the community, are very welcome to collaborate on the portal and contribute in any way. Some of the possible scenarios are:\nContribute original content Request articles and initiate discussions Leave comments about existing content Improve infrastructure and functionality For details, see the Contribution Guide.\nConclusion # In summary, the Espressif Developer Portal is here to create a verified knowledge base about Espressif products and solutions, unify all Espressif resources, and bring Espressif engineers and the community closer.\nWith that said, let\u0026rsquo;s team up, roll up the sleeves, and start working side by side to make the experience of using our products and solutions as efficient and frictionless as possible.\nIdeally, we expect the community to take the front seats and navigate the development of the portal! No matter how the roles and responsibilities will be divided in the end, this is going to be an exciting journey!\n","date":"13 May 2024","externalUrl":null,"permalink":"/blog/meet-espressif-developer-portal/","section":"Blog","summary":"This article introduces the Espressif Developer Portal, discusses its purpose, the expected content, and how we\u0026ndash;the community\u0026mdash;can contribute and collaborate.","title":"Meet the Espressif Developer Portal","type":"blog"},{"content":" Overview # The contribution diagram below shows how contributions can be done to espressif / developer-portal, marked as Public Upstream. It is Developer Portal\u0026rsquo;s public GitHub repo.\nflowchart RL id1[Public\nUpstream] id2[Private\nmirror] id3[Public\nFork] id4[Private\nmirror] id5[Public\nFork] subgraph sg1 [GitHub] id1 id3 id5 end subgraph sg2 [Espressif GitLab] id2 end subgraph sg3 [Anywhere] id4 end id2 -- Internal\ncontributions\n(private) ---\u003e id1 id3 -. External\ncontributions\n(public) .-\u003e id1 id4 -. External\ncontributions\n(private) .-\u003e id5 id5 -.-\u003e id1 style id1 fill:#99f classDef dashedStyle stroke-width:1px,stroke-dasharray: 5 5; class id3,id4,id5 dashedStyle; The internal contributions from Espressif will be prepared in the private mirror on Espressif\u0026rsquo;s GitLab, because during writing and editing, some sensitive information might be mentioned, such as the details of the upcoming products, speculations about future plans, etc.\nThe external contributions can be done in the following ways:\nPublic: External contributors create a fork of espressif / developer-portal and offer a PR. Private: External contributors create a private mirror anywhere they want, prepare the material to contribute, and either invite Espressif\u0026rsquo;s reviewers to their private mirror or offer a PR via a fork and have the review done publicly. Usage # The workflows for contributions are as follows:\nFor public contributions from a forked repo to espressif / developer-portal, follow the standard GitHub procedures. For private contributions, see How to contribute from Espressif GitLab How to contribute from Anywhere How to set up a private mirror How to contribute from Espressif GitLab # To contribute from the private mirror on Espressif GitLab to espressif / developer-portal, do the following:\nIn GitLab mirror, create a new branch and make the desired updates Invite Espressif\u0026rsquo;s reviewers to do the review Once the private work on the new branch is done, do the following in the GitLab mirror: # Pull latest updates from upstream main if any git fetch upstream main \u0026amp;\u0026amp; git pull upstream main # ! Replace \u0026lt;new-branch\u0026gt; with your branch name git rebase upstream/main \u0026lt;new-branch\u0026gt; # Push the branch with contributions to the public repo git push upstream \u0026lt;new-branch\u0026gt; In espressif / developer-portal, create a PR from your \u0026lt;new-branch\u0026gt; to main Remove the merged branch in GitLab mirror How to contribute from Anywhere # For private contributions from anywhere, do the following:\nSet up a private mirror as described in How to set up a private mirror In your private mirror, create a new branch and make the desired updates Invite Espressif\u0026rsquo;s reviewers to your private mirror to do the review Once the private work on the new branch is finished, do the following in the private mirror: # Pull latest updates from upstream main if any git fetch upstream main \u0026amp;\u0026amp; git pull upstream main # ! Replace \u0026lt;new-branch\u0026gt; with your branch name git rebase upstream/main \u0026lt;new-branch\u0026gt; # Push the branch with contributions to the public repo git push upstream \u0026lt;new-branch\u0026gt; After that, fork espressif / developer-portal and create a PR from your \u0026lt;new-branch\u0026gt; to main of espressif / developer-portal (public review will be done at this stage) How to set up a private mirror # To set up a private mirror of espressif / developer-portal, do the following:\nCreate a private mirror of espressif / developer-portal (GitHub only) In the private mirror, consider disabling the existing GitHub workflows as no developer portal deployment can be done from a mirror anyway On GitHub, create a fork of espressif / developer-portal In the private mirror, add your fork from the previous step as the upstream remote; you will want to push your contributions upstream to create a PR to espressif / developer-portal ","date":"30 April 2024","externalUrl":null,"permalink":"/pages/contribution-guide/contrib-workflow/","section":"","summary":"","title":"Contribution workflow","type":"pages"},{"content":"For now, the Contribution Guide offers the following materials:\nContribution workflow Writing content These workflows might be applicable partially or fully to the contribution scenarios.\nContribution Scenarios # You, dear members of the community, are very welcome to collaborate on the portal and contribute in any way. Some of the possible scenarios are:\nContribute original content Request articles and initiate discussions Leave comments about existing content Improve infrastructure and functionality Contribute original content # You can contribute the content directly or indirectly related to Espressif products and solutions. For example, you can contribute articles or tutorials that facilitate learning or articles about your projects based on Espressif products.\nAfter a review from Espressif technical editors, this content will be published in the author\u0026rsquo;s name. The review is mainly needed to make sure that the content fits the purpose of the Espressif Developer Portal and follows the Espressif Manual of Style.\nAs a result, the author will become an Espressif Developer Portal contributor!\nRequest articles and initiate discussions # In the past, if you had questions about certain wider subjects, your best bet would be to create an issue on GitHub or ask a question on the ESP32 forum. Accordingly, you would usually get help regarding a specific issue, because in-depth explanations are not a thing in such places.\nNow if you want to know more about certain subjects or functionalities of Espressif products and solutions insufficiently covered in other places, or if you simply want to discuss anything related to Espressif, you can do it all through the Developer Portal\u0026rsquo;s discussions on GitHub.\nDepending on the number of requests for articles, more in-depth explanations, how-to guides, or tutorials, the requests might need to be prioritized through voting, then the content will be created and published accordingly.\nLeave comments about existing content # Another way for you to contribute is to leave comments with constructive criticism of the content, indication of typos or pointing out other issues. The content will be updated accordingly to make the user experience as smooth and efficient as possible.\nImprove infrastructure and functionality # The Espressif Developer Portal is a static website created with Hugo and hosted on GitHub. If you want to propose improvements or use certain functionality in your content that is not yet implemented on the portal, you are very welcome to create a discussion to agree on the details. It will be even better if you can offer a pull request yourself.\n","date":"29 April 2024","externalUrl":null,"permalink":"/pages/contribution-guide/","section":"","summary":"","title":"Contribution guide","type":"pages"},{"content":" Before you start writing # There are the following prerequisites before you start writing content:\nDecide how you want to contribute by choosing the contribution workflow and get a copy of the espressif / developer-portal repo To view the built version of the website, install Hugo in your environment and go through Getting started if required Create and view an article # To create a new article, go to your cloned developer portal git repo and run:\n# Blog article # (if specified folders don\u0026#39;t exist, they will be created) hugo new content blog/YYYY/MM/\u0026lt;article-folder-name\u0026gt;/index.md # Blog article example hugo new content blog/2025/04/ulp-lp-core-get-started/index.md # Non-blog articles (workshops, events etc.) hugo new content \u0026lt;path\u0026gt;/index.md See also the official Hugo docs.\nThe commands above assume that you want to write a single article (leaf bundle). The recommended article folder structure is as follows:\n📂 \u0026lt;article-folder-name\u0026gt;/ ├── 📝 index.md ├── 📊 featured.webp ├── 📂 img/ │ ├── 📊 image1.webp │ └── 📊 image2.webp └── 📂 asciinema/ ├── 💻 asciinema1.cast └── 💻 asciinema2.cast For multi-article entries, such as workshops, etc., use the branch bundle.\nTo preview the changes:\nRun in your project folder: hugo server In the log, find the preview web address and open it: Web Server is available at http://localhost:1313/ Fill out the blog article header # After creating a blog article using hugo new content blog/..., go to your article file index.md and fill out its YAML header according to the instructions in comments.\nOne of the YAML header parameters is summary \u0026mdash; the article summary that appears just below the article title (summary example) and also in the article card (card example) where articles are listed. On how to write the article summary, check the additional guidelines below.\nWrite an article summary # Before you begin writing your article, it is a good exercise to summarize in one paragraph:\nThe main topic of your article (1 or 2 sentences). What value it brings to the reader (1 or 2 sentences). Don\u0026rsquo;t include links in summaries as they are not supported by design. Also, avoid formatting text as it doesn\u0026rsquo;t look good in general. This exercise might help you better understand how to structure and write your content. It will also help readers decide if they want to read your article as well as to set expectations.\nAfter you finish writing, revisit your summary to see if it needs any adjustments. You might be surprised by how the focus of your writing can shift during the process without you realizing it.\nAdd youself as an author # To add yourself as an author, create an article and follow the instructions in the article\u0026rsquo;s index.md YAML header.\nIf the article already exists and you want to edit the authors, here are the same instructions:\nCreate your author entry\nReplace all author-name and Author Name instances below with your own name, for example john-doe and John Doe respectively Create your page at content/authors/author-name/_index.md --- title: Author Name --- \u0026lt;!-- (optional) Add a few words about yourself --\u0026gt; (optional) Add your image in WebP format at the path assets/img/authors/author-name.webp Add your personal data at data/authors/author-name.json\nimage \u0026ndash; add your image or use the default img/authors/espressif.webp type \u0026ndash; set author type to espressif, partner, or community { \u0026#34;name\u0026#34;: \u0026#34;Author Name\u0026#34;, \u0026#34;type\u0026#34;: \u0026#34;espressif\u0026#34;, \u0026#34;image\u0026#34; : \u0026#34;img/authors/author-name.webp\u0026#34;, \u0026#34;bio\u0026#34;: \u0026#34;(optional) Your role at Espressif\u0026#34;, \u0026#34;social\u0026#34;: [ { \u0026#34;linkedin\u0026#34;: \u0026#34;https://www.linkedin.com/...\u0026#34; }, { \u0026#34;github\u0026#34;: \u0026#34;https://github.com/...\u0026#34; } ] } Add author name(s) to your article\u0026rsquo;s YAML header authors: - \u0026#34;author-name\u0026#34; # same as in the file paths above - \u0026#34;another-author\u0026#34; In some cases, it might be better to add the default Espressif author:\nIf the author prefers to stay anonymous For posts generated by scripts, such as automatic compilations, release notes, and so on For articles generated with AI To add the default author, include this in your article\u0026rsquo;s YAML header:\nshowAuthor: true Write the content # This is totally up to you how you write the content as long as it is valuable for the community.\nFor writing and formatting conventions, the contributors at Espressif usually follow the Espressif Manual of Style and the Chicago Manual of Style. You might find these guidelines useful, but you are not required to follow them.\nPrepare a featured image # A featured image appears above the article\u0026rsquo;s title. A nice and relevant image attracts readers like a magnet, that is why consider giving more thought to it.\nA featured image can be added in the following ways from the highest to lowest priority:\nArticle-specific image file: In the same folder as your article\u0026rsquo;s index.md, place your featured image and make sure its file name includes the substring feature, for example: featured-lcd-screen.webp. Image from a URL: In the article\u0026rsquo;s front matter, add the parameter featureimage and assign a URL to it, for example: featureimage: \u0026#34;https://espressif.com/logo-guidelines/chinese-horizontal-logo.png\u0026#34; This parameter is from Blowfish theme\u0026rsquo;s Front Matter. Generic image file: If you have no chance to create your own image, try to find a generic image in assets/img/featured and assign the path to featureAsset, for example: featureAsset: \u0026#34;img/featured/image.webp\u0026#34; Please have your featured image converted to WebP as requested in Use WebP for raster images.\nInject dynamic content # If your page is going to be updated frequently, consider implementing injection of dynamic content. Usually, it is used for product status pages, such as ESP32-C61 status.\nFor more information, see Dynamic content.\nUse additional content types # Apart from the usual content types supported by markdown, such as visuals or code blocks, you can use other content types enabled by Hugo shortcodes. This section briefly introduces the most relevant shortcodes implemented on the Espressif Developer Portal.\nIn addition to that, you can also use the standard Hugo embedded shortcodes and Blowfish theme shortcodes.\nIf you need other content types or shortcodes implemented, either create a discussion on GitHub or offer a PR with the required functionality. It will be very much appreciated!\nImages # Adding images # You can add an image using a standard markdown syntax:\n![Alt text](path/to/image.webp \u0026#34;Optional tooltip\u0026#34;) However, the Blowfish theme used on this website provides the figure shortcode that offers more control over image display and render. An example of a shortcode is given below, but more parameters are available:\n{{\u0026lt; figure src=\u0026#34;image.webp\u0026#34; alt=\u0026#34;\u0026#34; caption=\u0026#34;\u0026#34; \u0026gt;}} By default, the Blowfish theme optimizes the images for different device resolutions. For some images, the processing adds grey background. To fix it, disable the processing of such images by adding the parameter default=\u0026quot;true\u0026quot; to the figure shortcode.\nUse WebP for raster images # For raster images, please use the WebP format only. The Developer Portal\u0026rsquo;s CI blocks the images in PNG anf JPEG format.\nThe WebP format was chosen for the following reasons:\nThe images in WebP are comparable in quality to PNG and JPEG but are 5-7 times smaller in size Smaller image size is important It prevents the git repo from growing out of proportion very fast It allows serving web pages faster To convert your images to WebP, use one of the following ways:\nUse imagemagick:\nconvert image.jpg -quality 60 image.webp Use cwebp:\ncwebp -q 60 image.jpg -o image.webp The quality value 60 usually yields good results. For very good quality, you can use the value 80.\nAsciinema casts # Asciinema allows you to record terminal sessions using a lightweight text-based format.\nIf you want to use an asciinema cast in your article, see asciinema casts.\nCode blocks with tabs # Tabbed code blocks look neat:\nLinux macOS Linux code block Update homebrew, then run:\nmacOS code block At the same time, the markup is very simple:\n{{\u0026lt; tabs groupId=\u0026#34;config\u0026#34; \u0026gt;}} {{% tab name=\u0026#34;Linux\u0026#34; %}} ```md Linux code block ``` {{% /tab %}} {{% tab name=\u0026#34;macOS\u0026#34; %}} Update homebrew, then run: ```md macOS code block ``` {{% /tab %}} {{\u0026lt; /tabs \u0026gt;}} Some explanations:\nUse the tabs shortcode to create a tabbed code block Use the nested tab shortcode to create as many tabs as you need Within a tab, place any markdown content you want, it will be rendered like any other markdown content For a real example, see this page.\nAs you can see, the tabs shortcode has the parameter groupId. It creates association between all tabbed code blocks bearing the same groupId on a webpage. Once you choose a certain tab, all associated code blocks will switch to the same tab. It can be useful in tutorials covering multiple operating systems, programming languages, etc.\nYou can also easily indent a tabbed code block, by preceding the tabs and tab shortcodes with the required number of spaces. This is exactly what was done in the linked example above.\nDiagrams as code # A number of Diagrams as code formats are supported, including Mermaid.\nFor example, a Mermaid diagram is used on this page (see also the raw version).\nVideo # To embed a video in your article, upload it to a video streaming platform such as YouTube and use the YouTube shortcode provided by Hugo to include it in your content. If you don\u0026rsquo;t have your own YouTube channel, we can upload your video to ours.\nIf you give your consent and share the video file with us, we can also upload it to BiliBili to make it accessible in more geographic areas.\nTag the content # Assign tags to your content following the guidelines in Tagging content.\nUse pre-commit # This project has a pre-commit hook that can perform the following checks:\nEnforce coding standards and best practices in the project\u0026rsquo;s codebase Check links using lychee Important: this check requires Docker as a dependency, please make sure it is installed If you want to use pre-commit, in your project folder, run:\n# Install requirements pip install -r requirements.txt # Set up git hook scripts pre-commit install # Remove git hook scripts (if not needed) pre-commit uninstall Ask for review # To publish your content on the Espressif Developer Portal, please create a discussion in espressif / developer-portal invite reviewers from Espressif so that they can make sure your content is in-line with Espressif\u0026rsquo;s writing conventions.\nAfter the review is done, create a PR following the contribution workflow.\n","date":"29 April 2024","externalUrl":null,"permalink":"/pages/contribution-guide/writing-content/","section":"","summary":"","title":"Writing content","type":"pages"},{"content":"The Fastest Way to Launch Matter-enabled Products\nIt’s been about 8 months since we launched ESP ZeroCode. For all these months, continuous interest and customer activity has kept us busy. Let’s look at some of the highlights of what’s new with ESP ZeroCode.\nCustomer Interest # Over 11,000 users across 125 countries have visited ESP ZeroCode, building various kinds of Matter-enabled products. Every week we get numerous queries and requests for samples or product-related queries. Many of these have now become products that have completed certification and selling in their respective market places.\nAlong the way we have Matter-certified over 100 ESP ZeroCode powered devices.\nQuality # We have been rigorously conducting automated QA tests and making continuous fixes in the ZeroCode firmware. These include a variety of tests including,\nlong-duration tests over 30 days tests under network stress and RF interference tests with multiple simultaneous ecosystem operations OTA and rollback tests Overall the test framework runs over 1000 tests, and most of these are run for over 50 different products.\nNumerous issues for memory footprint, corner cases, commissioning/uncommissioning have been identified and fixed.\nProduct Enhancements # We now support 2 different solution types through ESP ZeroCode.\nsingle-chip solution: This is the typical solution that we launched with, which today, runs on Wi-Fi (ESP32-C3, ESP32-C2, ESP32) and Thread (ESP32-H2). This solution is the most cost optimised solution and is recommended for all lighting categories. two-chip (hosted) solution: Our ESP ZeroCode ExL is a hosted solution that is ideal for Appliances . Appliances often consider connectivity through a “connectivity co-processor”, and work with it over a UART interface. Our two-chip solution addresses the typical Appliance scenarios, particularly MQTT connectivity to cloud platforms (AWS IoT). Read more about it here: Announcing ESP ZeroCode ExL. We also extended our portfolio of partnerships. All ESP ZeroCode products can now be easily certified with all of the following ecosystem programs:\nWorks with Alexa Works with Apple Home Works with Google Home Works with Home Assistant Works with SmartThings We also collaborated with Amazon with Alexa Connect Kit (ACK) for Matter and created ZeroCode devices using the ACK for Matter. Through the ESP ZeroCode portal, you can now choose ACK for Matter as a solution for the firmware of your devices.\nDevice Catalogue # As Matter standard evolved from v1.0 to v1.1 and v1.2, it kept introducing support for new device types. We have kept pace with the standard’s evolution and have been incorporating newer device types and a variety of device drivers in our product catalogue.\nToday, with ESP ZeroCode, you can quickly build the following Matter-enabled products:\nWindow Blinds (automatic and manual calibration) Sockets: 1, 2, 3, 4 channel Power outlets: 1, 2, 3, 4 channel LED Lights with options for RGB, RGBW, RGBWW, RGBCW and RGBCCT with the following drivers are supported: WS2812, PWM, BP5758D, BP5758D, BP1658CJ, BP1658CJ, SM2135E, SM2135E, SM2135EH, SM2135EH, SM2135EGH, SM2135EGH, SM2335EGH Filament bulbs, Candle bulb, Reflector bulb, Downlights, Flat Panels (Full Colour, Tunable White) Dimmers Appliances (hosted mode solutions) like Thermostat, Air Conditioner, Laundry Washer, and Refrigerator All the above device types are available on both Wi-Fi as well as Thread/802.15.4 transport.\nRicher Customisations # With the introduction of text mode configurability, ESP ZeroCode now allows richer set of customisations.\nYou can now create multi-channel outlets or sockets. You can also create multi-endpoint device types, like a socket and a light in the same accessory and such.\nA variety of driver specific customisations have been included. A few of these include,\nVarious configurations for lightbulbs, viz: current, gamma, low power Configuring indicator colours and patterns for all the device states, viz: setup mode, device ready, network disconnected The state of the device after turning the power on, viz: power, brightness, colour Factory reset trigger mechanism Shorter Time To Market # A number of optimisations in our manufacturing and certification processes have been made to provide the shortest production time.\nIn the fastest case, some of our customers have gone from concept to production-start (including certification) within 3 weeks.\nAll in all, we are taking great strides to make ESP ZeroCode the fastest, most secure and robust tool to launch Matter products. If you are looking to develop and maintain your own Matter-enabled products, with your specific customisation, please head over to ESP ZeroCode to get started.\nFor additional information about ESP ZeroCode, check out this podcast:\n","date":"28 April 2024","externalUrl":null,"permalink":"/blog/whats-new-with-esp-zerocode/","section":"Blog","summary":"","title":"What’s New with ESP ZeroCode","type":"blog"},{"content":"","date":"28 April 2024","externalUrl":null,"permalink":"/tags/zero-code/","section":"Tags","summary":"","title":"Zero Code","type":"tags"},{"content":"","date":"4 April 2024","externalUrl":null,"permalink":"/tags/emulator/","section":"Tags","summary":"","title":"Emulator","type":"tags"},{"content":"","date":"4 April 2024","externalUrl":null,"permalink":"/tags/latest-release/","section":"Tags","summary":"","title":"Latest Release","type":"tags"},{"content":"","date":"4 April 2024","externalUrl":null,"permalink":"/tags/releases-section/","section":"Tags","summary":"","title":"Releases Section","type":"tags"},{"content":" Overview # ESP32 series of SoCs supports multiple security features like trusted boot, flash encryption, secure storage etc. There are also dedicated peripherals to support use-cases like HMAC and digital signature. For most of these features the eFuse storage in the ESP32-C3 is responsible for storing the private keys and also the configuration bits.\neFuse memory is one time programmable and hence care must be taken whilst enabling the security features. eFuse programming being an irreversible operation, it is desired to have some playground available to first try out security features (e.g., under emulator) and then move to the real hardware.\nThis article talks about exercising different security features in ESP32-C3 under QEMU (emulator).\nQEMU # QEMU, which stands for Quick EMUlator, is an open-source virtualization tool that allows users to create and run virtual machines (VMs) on a host system. It can emulate various architectures, including x86, ARM, RISCV, and others, enabling users to run operating systems and software designed for different hardware platforms.\nEspressif has been developing a system-level emulation of RISC-V based ESP32-C3 using QEMU and its latest release supports all the security features for ESP32-C3. Binary compatibility has been maintained to directly run the firmware built for ESP32-C3 target under QEMU.\nEmulator approach provides an advantage to iterate various security configurations without risk of bricking the hardware. Once the workflow is established under QEMU, it can be easily adapted for the real hardware.\nHow does QEMU help in trying out the security features? # QEMU is a system-level emulator composed of instruction set emulation, memory and MMU emulation, and peripheral emulation. It also supports various virtual disk formats and networking configurations as well.\nThis helps us to emulate the complete hardware SoC that includes peripherals emulation as well. Peripherals like eFuses, XTS-AES, RSA play a key role in supporting security features.\nWe will deep-dive into how to use these emulated host files while using QEMU in the upcoming sections.\nTrying out the security features # Espressif’s security guide mentions two workflows for enabling the security features:\nInternal first boot-up workflow Host-based workflow We will use a demo example which enabled and allows us to try out all the supported security features:\nSecure Boot V2 Flash Encryption NVS Encryption (using the HMAC based workflow) Let us check out the boot internal first boot-up workflow:\nInstalling QEMU release versions # # Linux wget https://github.com/espressif/qemu/releases/download/esp-develop-8.2.0-20240122/qemu-riscv32-softmmu-esp_develop_8.2.0_20240122-x86_64-linux-gnu.tar.xz -P ~/Downloads tar xvf ~/Downloads/qemu-riscv32-softmmu-esp_develop_8.2.0_20240122-x86_64-linux-gnu.tar.xz -C ~/Downloads # MacOS (M1 silicon) wget https://github.com/espressif/qemu/releases/download/esp-develop-8.2.0-20240122/qemu-riscv32-softmmu-esp_develop_8.2.0_20240122-aarch64-apple-darwin.tar.xz -P ~/Downloads tar xvf ~/Downloads/qemu-riscv32-softmmu-esp_develop_8.2.0_20240122-aarch64-apple-darwin.tar.xz -C ~/Downloads You could also consider adding it to your environment’s $PATH variable for ease of use. For example, in case of Linux/MacOS, if after extracting the downloaded release file is in the Downloads directory, you may run following command:\nexport PATH=$PATH:~/Downloads/qemu/bin In case you are interested in trying out the development versions you could also opt for cloning and building Espressif’s GitHub QEMU fork using the configuration instructions mentioned in the documentation.\nIn case you are using ESP-IDF’s master branch for developing your firmware, the easiest way to install the QEMU is getting the release binaries that are packaged with ESP-IDF (master) using the following command:\npython $IDF_PATH/tools/idf_tools.py install qemu-riscv32 The above command exports the path to the ESP-IDF packaged QEMU release binaries into your $PATH variable as well.\nInternal first boot-up workflow # In this workflow, the security features are incrementally enabled during the first boot up by the bootloader.\nClone the demo project In a new terminal window, activate the ESP-IDF environment, using the . ./export.sh as mentioned in the ESP-IDF installation section.\nUse the following commands to clone the demo project:\ngit clone https://github.com/Harshal5/esp-idf-security-example.git cd esp-idf-security-example Enable the security related configs Starting off with the first step, set project target to esp32c3 by entering the command:\nidf.py set-target esp32c3 The project we are using already has all the security configs listed below enabled by default (sdkconfig.defaults), so you do not need to enable them by yourselves.\nSecurity-related configs that have been enabled:\n# Secure Boot related configs CONFIG_SECURE_SIGNED_ON_BOOT=y CONFIG_SECURE_SIGNED_ON_UPDATE=y CONFIG_SECURE_SIGNED_APPS=y CONFIG_SECURE_BOOT_V2_RSA_ENABLED=y CONFIG_SECURE_SIGNED_APPS_RSA_SCHEME=y CONFIG_SECURE_BOOT=y CONFIG_SECURE_BOOT_V2_ENABLED=y CONFIG_SECURE_BOOT_BUILD_SIGNED_BINARIES=y CONFIG_SECURE_BOOT_SIGNING_KEY=\u0026#34;secure_boot_signing_key.pem\u0026#34; CONFIG_SECURE_BOOT_FLASH_BOOTLOADER_DEFAULT=y # Flash Encryption related configs CONFIG_SECURE_FLASH_ENC_ENABLED=y CONFIG_FLASH_ENCRYPTION_ENABLED=y CONFIG_SECURE_FLASH_ENCRYPTION_MODE_RELEASE=y CONFIG_SECURE_FLASH_HAS_WRITE_PROTECTION_CACHE=y CONFIG_SECURE_FLASH_ENCRYPT_ONLY_IMAGE_LEN_IN_APP_PART=y CONFIG_SECURE_FLASH_CHECK_ENC_EN_IN_APP=y CONFIG_SECURE_ENABLE_SECURE_ROM_DL_MODE=y # NVS Encryption related configs CONFIG_NVS_ENCRYPTION=y CONFIG_NVS_SEC_KEY_PROTECT_USING_HMAC=y CONFIG_NVS_SEC_HMAC_EFUSE_KEY_ID=3 Setting these configs assume that we have a pre-generated secure boot key named secure_boot_signing_key.pem, flash encryption key would be generated by the device (esp32c3), and an HMAC key (say hmac_key.bin) that would be used to derive the NVS encryption key needs to be pre-burnt in the eFuse KEY_BLOCK3.\nThe secure boot signing key being an RSA key, can be generated using the command:\nespsecure.py generate_signing_key --version 2 secure_boot_signing_key.pem whereas the NVS encryption key being an HMAC key can be created using the command:\ndd if=/dev/random of=hmac_key.bin bs=1 count=32 Generate the flash image Once we are done with the configurations, we need to build the firmware using the command:\nidf.py build that would create the bootloader, partition-table, and the application images individually in the build directory.\nThe QEMU flash image should be generated by merging the boot loader, partition-table and the application binary images present in the project\u0026rsquo;sbuild directory of the project. A straightforward way to generate such a flash image is by using the esptool.py merge_bin command with the parameter flash_args file, which contains the entries of all the binary images that are needed to be flash using the command idf.py flash.\nUse the below command to generate a complete flash image (flash_image) for the firmware:\n(cd build; esptool.py --chip esp32c3 merge_bin --fill-flash-size 4MB -o flash_image.bin @flash_args) As we have already enabled the config CONFIG_SECURE_BOOT_FLASH_BOOTLOADER_DEFAULT, the bootloader entry gets added into the flash_args file, which is needed because as mentioned in secure boot guide, bootloader does not get flashed by default with the idf.py flash command when secure boot is enabled.\nGet the eFuses file ready A simple eFuses file could be created using:\ndd if=/dev/zero bs=1K count=1 of=build/qemu_efuse.bin This command creates a 1KB (1024 bytes) file, which is the total size of ESP32-C3 eFuse blocks, filled with zeros.\nNow you have your eFuse file ready and you can view the eFuses summary by running QEMU ESP32-C3 in download mode and attaching the above generated eFuses file. Run QEMU in the download mode using the following command in the terminal in which we have updated the *PATH *variable:\nqemu-system-riscv32 -nographic \\ -machine esp32c3 \\ -global driver=esp32c3.gpio,property=strap_mode,value=0x02 \\ -drive file=build/qemu_efuse.bin,if=none,format=raw,id=efuse \\ -global driver=nvram.esp32c3.efuse,property=drive,value=efuse \\ -serial tcp::5555,server,nowait (Once you run the above command you will be able to see the version of the QEMU binary in such format QEMU 8.2.0 monitor. Make sure the version is ≥ 8.2.0)\nOnce QEMU is up running in the download mode, you should be able to check the eFuses summary using espefuse.py in the ESP-IDF environment terminal window:\nexport ESPPORT=socket://localhost:5555 espefuse.py -p $ESPPORT --before=no_reset summary Note: While running QEMU in the download mode the serial output can be redirected to a TCP port. As done in the above QEMU command we have used port 5555, thus you need to set the variable ESPPORT to socket://localhost:5555 or use the port directly for all the related operations.\nYou should now be able to view an empty or clean eFuses summary similar to a physical hardware chip.\nYou would also need to set the ECO version as required . For example, if an ESP32-C3 v0.3 is to be used, you need to set the eFuse WAFER_VERSION_MINOR_LO to value 3.\nespefuse.py -p $ESPPORT --before=no_reset burn_efuse WAFER_VERSION_MINOR_LO 3 Finally burn the HMAC key in KEY_BLOCK3 with the key purpose HMAC_UP that would be used for NVS encryption:\nespefuse.py -p $ESPPORT --before=no_reset burn_key BLOCK_KEY3 hmac_key.bin HMAC_UP Once you are done with burning all the required eFuses, you need to close QEMU by entering the “quit” command.\nRun the firmware using QEMU We are now ready to run the firmware by running QEMU in the boot mode using the command:\nqemu-system-riscv32 -nographic \\ -M esp32c3 \\ -drive file=build/flash_image.bin,if=mtd,format=raw \\ -drive file=build/qemu_efuse.bin,if=none,format=raw,id=efuse \\ -global driver=nvram.esp32c3.efuse,property=drive,value=efuse \\ -serial mon:stdio Note: Supply the same merged flash image and the updated eFuses file generated in the previous steps.\nAs we have used stdio as output destination to the serial port, we should now be able to see the following success logs of enabling secure boot, flash encryption and NVS encryption respectively along with their corresponding eFuses burned in the eFuse file, and the merged flash_image being encrypted:\n\u0026gt; qemu-system-riscv32 -nographic \\ -M esp32c3 \\ -drive file=build/flash_image.bin,if=mtd,format=raw \\ -drive file=build/qemu_efuse.bin,if=none,format=raw,id=efuse \\ -global driver=nvram.esp32c3.efuse,property=drive,value=efuse \\ -serial mon:stdio Adding SPI flash device ESP-ROM:esp32c3-api1-20210207 Build:Feb 7 2021 rst:0x1 (POWERON),boot:0x8 (SPI_FAST_FLASH_BOOT) SPIWP:0xee mode:DIO, clock div:1 load:0x3fcd5990,len:0x3b48 load:0x403cc710,len:0xb9c load:0x403ce710,len:0x5b78 entry 0x403cc71a I (1) boot: ESP-IDF v5.3-dev-2547-g8b3821ca67 2nd stage bootloader I (2) boot: compile time Mar 14 2024 15:09:57 I (5) boot: chip revision: v0.3 I (7) boot.esp32c3: SPI Speed : 80MHz I (7) boot.esp32c3: SPI Mode : SLOW READ I (8) boot.esp32c3: SPI Flash Size : 2MB I (11) boot: Enabling RNG early entropy source... I (17) boot: Partition Table: I (17) boot: ## Label Usage Type ST Offset Length I (18) boot: 0 nvs WiFi data 01 02 0000e000 00006000 I (18) boot: 1 storage Unknown data 01 ff 00014000 00001000 I (19) boot: 2 factory factory app 00 00 00020000 00100000 I (19) boot: 3 nvs_key NVS keys 01 04 00120000 00001000 I (20) boot: 4 custom_nvs WiFi data 01 02 00121000 00006000 I (20) boot: End of partition table I (22) esp_image: segment 0: paddr=00020020 vaddr=3c030020 size=0c1d8h ( 49624) map I (36) esp_image: segment 1: paddr=0002c200 vaddr=3fc8b600 size=01548h ( 5448) load I (38) esp_image: segment 2: paddr=0002d750 vaddr=40380000 size=028c8h ( 10440) load I (42) esp_image: segment 3: paddr=00030020 vaddr=42000020 size=21034h (135220) map I (76) esp_image: segment 4: paddr=0005105c vaddr=403828c8 size=08c84h ( 35972) load I (86) esp_image: segment 5: paddr=00059ce8 vaddr=00000000 size=062e8h ( 25320) I (93) esp_image: Verifying image signature... I (95) secure_boot_v2: Secure boot V2 is not enabled yet and eFuse digest keys are not set I (97) secure_boot_v2: Verifying with RSA-PSS... I (103) secure_boot_v2: Signature verified successfully! I (104) boot: Loaded app from partition at offset 0x20000 I (105) secure_boot_v2: enabling secure boot v2... I (109) efuse: Batch mode of writing fields is enabled I (110) esp_image: segment 0: paddr=00000020 vaddr=3fcd5990 size=03b48h ( 15176) I (114) esp_image: segment 1: paddr=00003b70 vaddr=403cc710 size=00b9ch ( 2972) I (116) esp_image: segment 2: paddr=00004714 vaddr=403ce710 size=05b78h ( 23416) I (122) esp_image: Verifying image signature... I (124) secure_boot_v2: Secure boot V2 is not enabled yet and eFuse digest keys are not set I (125) secure_boot_v2: Verifying with RSA-PSS... I (127) secure_boot_v2: Signature verified successfully! I (127) secure_boot_v2: Secure boot digests absent, generating.. I (141) secure_boot_v2: Digests successfully calculated, 1 valid signatures (image offset 0x0) I (141) secure_boot_v2: 1 signature block(s) found appended to the bootloader. I (142) secure_boot_v2: Burning public key hash to eFuse I (143) efuse: Writing EFUSE_BLK_KEY0 with purpose 9 I (208) secure_boot_v2: Digests successfully calculated, 1 valid signatures (image offset 0x20000) I (209) secure_boot_v2: 1 signature block(s) found appended to the app. I (210) secure_boot_v2: Application key(0) matches with bootloader key(0). I (210) secure_boot_v2: Revoking empty key digest slot (1)... I (211) secure_boot_v2: Revoking empty key digest slot (2)... I (211) secure_boot_v2: blowing secure boot efuse... I (212) secure_boot: Enabling Security download mode... I (212) secure_boot: Disable hardware \u0026amp; software JTAG... I (215) efuse: BURN BLOCK4 I (236) efuse: BURN BLOCK4 - OK (write block == read block) I (236) efuse: BURN BLOCK0 I (256) efuse: BURN BLOCK0 - OK (all write block bits are set) I (259) efuse: Batch mode. Prepared fields are committed I (259) secure_boot_v2: Secure boot permanently enabled I (260) boot: Checking flash encryption... I (263) efuse: Batch mode of writing fields is enabled I (264) flash_encrypt: Generating new flash encryption key... I (265) efuse: Writing EFUSE_BLK_KEY1 with purpose 4 I (266) flash_encrypt: Disable UART bootloader encryption... I (266) flash_encrypt: Disable UART bootloader cache... I (266) flash_encrypt: Disable JTAG... I (267) efuse: BURN BLOCK5 I (293) efuse: BURN BLOCK5 - OK (write block == read block) I (293) efuse: BURN BLOCK0 I (313) efuse: BURN BLOCK0 - OK (all write block bits are set) I (316) efuse: Batch mode. Prepared fields are committed I (316) esp_image: segment 0: paddr=00000020 vaddr=3fcd5990 size=03b48h ( 15176) I (321) esp_image: segment 1: paddr=00003b70 vaddr=403cc710 size=00b9ch ( 2972) I (322) esp_image: segment 2: paddr=00004714 vaddr=403ce710 size=05b78h ( 23416) I (329) esp_image: Verifying image signature... I (331) secure_boot_v2: Verifying with RSA-PSS... I (333) secure_boot_v2: Signature verified successfully! I (479) flash_encrypt: bootloader encrypted successfully I (492) flash_encrypt: partition table encrypted and loaded successfully I (493) flash_encrypt: Encrypting partition 1 at offset 0x14000 (length 0x1000)... I (505) flash_encrypt: Done encrypting I (505) esp_image: segment 0: paddr=00020020 vaddr=3c030020 size=0c1d8h ( 49624) map I (518) esp_image: segment 1: paddr=0002c200 vaddr=3fc8b600 size=01548h ( 5448) I (520) esp_image: segment 2: paddr=0002d750 vaddr=40380000 size=028c8h ( 10440) I (524) esp_image: segment 3: paddr=00030020 vaddr=42000020 size=21034h (135220) map I (558) esp_image: segment 4: paddr=0005105c vaddr=403828c8 size=08c84h ( 35972) I (567) esp_image: segment 5: paddr=00059ce8 vaddr=00000000 size=062e8h ( 25320) I (574) esp_image: Verifying image signature... I (575) secure_boot_v2: Verifying with RSA-PSS... I (577) secure_boot_v2: Signature verified successfully! I (577) flash_encrypt: Encrypting partition 2 at offset 0x20000 (length 0x100000)... I (3532) flash_encrypt: Done encrypting I (3532) flash_encrypt: Encrypting partition 3 at offset 0x120000 (length 0x1000)... I (3544) flash_encrypt: Done encrypting I (3545) flash_encrypt: Setting CRYPT_CNT for permanent encryption I (3548) efuse: BURN BLOCK0 I (3568) efuse: BURN BLOCK0 - OK (all write block bits are set) I (3573) flash_encrypt: Flash encryption completed I (3574) boot: Resetting with flash encryption enabled... ESP-ROM:esp32c3-api1-20210207 Build:Feb 7 2021 rst:0x3 (RTC_SW_SYS_RST),boot:0x8 (SPI_FAST_FLASH_BOOT) SPIWP:0xee mode:DIO, clock div:1 Valid secure boot key blocks: 0 secure boot verification succeeded load:0x3fcd5990,len:0x3b48 load:0x403cc710,len:0xb9c load:0x403ce710,len:0x5b78 entry 0x403cc71a I (3657) boot: ESP-IDF v5.3-dev-2547-g8b3821ca67 2nd stage bootloader I (3658) boot: compile time Mar 14 2024 15:09:57 I (3662) boot: chip revision: v0.3 I (3664) boot.esp32c3: SPI Speed : 80MHz I (3664) boot.esp32c3: SPI Mode : SLOW READ I (3665) boot.esp32c3: SPI Flash Size : 2MB I (3668) boot: Enabling RNG early entropy source... I (3673) boot: Partition Table: I (3673) boot: ## Label Usage Type ST Offset Length I (3674) boot: 0 nvs WiFi data 01 02 0000e000 00006000 I (3674) boot: 1 storage Unknown data 01 ff 00014000 00001000 I (3675) boot: 2 factory factory app 00 00 00020000 00100000 I (3675) boot: 3 nvs_key NVS keys 01 04 00120000 00001000 I (3676) boot: 4 custom_nvs WiFi data 01 02 00121000 00006000 I (3676) boot: End of partition table I (3678) esp_image: segment 0: paddr=00020020 vaddr=3c030020 size=0c1d8h ( 49624) map I (3694) esp_image: segment 1: paddr=0002c200 vaddr=3fc8b600 size=01548h ( 5448) load I (3698) esp_image: segment 2: paddr=0002d750 vaddr=40380000 size=028c8h ( 10440) load I (3704) esp_image: segment 3: paddr=00030020 vaddr=42000020 size=21034h (135220) map I (3741) esp_image: segment 4: paddr=0005105c vaddr=403828c8 size=08c84h ( 35972) load I (3752) esp_image: segment 5: paddr=00059ce8 vaddr=00000000 size=062e8h ( 25320) I (3761) esp_image: Verifying image signature... I (3765) secure_boot_v2: Verifying with RSA-PSS... I (3767) secure_boot_v2: Signature verified successfully! I (3768) boot: Loaded app from partition at offset 0x20000 I (3769) secure_boot_v2: enabling secure boot v2... I (3769) secure_boot_v2: secure boot v2 is already enabled, continuing.. I (3770) boot: Checking flash encryption... I (3770) flash_encrypt: flash encryption is enabled (0 plaintext flashes left) I (3771) boot: Disabling RNG early entropy source... I (3776) cpu_start: Unicore app I (3802) cpu_start: Pro cpu start user code I (3802) cpu_start: cpu freq: 160000000 Hz I (3803) app_init: Application information: I (3803) app_init: Project name: security I (3803) app_init: App version: 26b03ca I (3803) app_init: Compile time: Mar 14 2024 15:09:53 I (3803) app_init: ELF file SHA256: 5ed173a2f... I (3804) app_init: ESP-IDF: v5.3-dev-2547-g8b3821ca67 I (3804) efuse_init: Min chip rev: v0.3 I (3804) efuse_init: Max chip rev: v1.99 I (3804) efuse_init: Chip rev: v0.3 I (3805) heap_init: Initializing. RAM available for dynamic allocation: I (3806) heap_init: At 3FC8DCD0 len 00032330 (200 KiB): RAM I (3806) heap_init: At 3FCC0000 len 0001C710 (113 KiB): Retention RAM I (3806) heap_init: At 3FCDC710 len 00002950 (10 KiB): Retention RAM I (3806) heap_init: At 50000010 len 00001FD8 (7 KiB): RTCRAM I (3815) spi_flash: detected chip: gd I (3815) spi_flash: flash io: dio W (3816) spi_flash: Detected size(4096k) larger than the size in the binary image header(2048k). Using the size in the binary image header. I (3817) flash_encrypt: Flash encryption mode is RELEASE I (3820) nvs_sec_provider: NVS Encryption - Registering HMAC-based scheme... I (3821) sleep: Configure to isolate all GPIO pins in sleep state I (3822) sleep: Enable automatic switching of GPIO sleep configuration I (3827) main_task: Started on CPU0 I (3827) main_task: Calling app_main() Example to check Flash Encryption status This is esp32c3 chip with 1 CPU core(s), WiFi/BLE, silicon revision v0.3, 2MB external flash FLASH_CRYPT_CNT eFuse value is 7 Flash encryption feature is enabled in RELEASE mode Erasing partition \u0026#34;storage\u0026#34; (0x1000 bytes) Writing data with esp_partition_write: I (3827) example: 0x3fc8fa00 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f |................| I (3827) example: 0x3fc8fa10 10 11 12 13 14 15 16 17 18 19 1a 1b 1c 1d 1e 1f |................| Reading with esp_partition_read: I (3837) example: 0x3fc8fa20 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f |................| I (3837) example: 0x3fc8fa30 10 11 12 13 14 15 16 17 18 19 1a 1b 1c 1d 1e 1f |................| Reading with esp_flash_read: I (3837) example: 0x3fc8fa20 75 75 ca b0 e6 09 a7 c1 bd c0 8a 08 e3 24 25 47 |uu...........$%G| I (3837) example: 0x3fc8fa30 a5 e7 94 b4 04 1e 55 d5 ff 04 c9 b8 55 a7 0a 7f |......U.....U...| I (3847) nvs: NVS partition \u0026#34;nvs\u0026#34; is encrypted. I (3857) example: NVS partition \u0026#34;custom_nvs\u0026#34; is encrypted. I (3857) main_task: Returned from app_main() You can terminate the QEMU session, using control+A and then pressing X.\nJust to verify :\nAs we have selected Flash Encryption Release mode, if you try checking out the eFuses summary by running QEMU in the download mode, you will come across the following error:\nA fatal error occurred: Secure Download Mode is enabled. The tool can not read eFuses. As you have the eFuses file with yourself, you can always modify it, and this opens a lot of possibilities to test your firmware with different eFuses combinations.\nFuture Work # Currently, you can quickly try out any ESP-IDF (master branch) based application using QEMU by just running the command idf.py qemu. This command handles all the intermediary steps like generation of eFuses file and the merged binary. But as of now it does not support using a pre-programmed eFuses file, instead it creates a new one for every instance of the run. We are trying to support usage of pre-programmed eFuses file as this will surely increase the user experience of using the emulator approach for such use-cases.\nSummary # Thus, we have seen that the emulator approach surely provides an advantage to iterate over and debug various security configurations and speed up the testing process to finally develop a production-ready configuration that can be tested on the real hardware, without the risk of bricking it due to any misconfigurations.\nIn part 2 of this blog, we would go through the host-based workflow for enabling the security features using QEMU.\nTill then, in case you are unsure about the boot loader boot workflow to enable security features, you could safely try it out using ESP32-C3 QEMU first to avoid any hardware damage.\nWe are actively working to enable support for any other remaining peripherals of an ESP32-C3 as well, do let us know your feedback and if you come across any issues, feel free to open a discussion/issue at our GitHub repository.\n","date":"4 April 2024","externalUrl":null,"permalink":"/blog/trying-out-esp32-c3s-security-features-using-qemu/","section":"Blog","summary":"","title":"Trying out ESP32-C3’s security features using QEMU","type":"blog"},{"content":" Overview # asciinema allows you to record terminal sessions using a lightweight text-based format. You can easily embed asciinema casts on the Developer Portal.\nNotable features # Copy text and commands directly from the video Add Markers similar to Youtube chapters Edit casts by manipulating the file contents or using asciinema-edit Word of caution # Use asciinema casts for output logs or to demonstrate things in action. Avoid using asciinema casts for interactive guides as users in general prefer scrolling through commands and copying them from code snippets instead of fishing the commands out of an asciinema cast.\nUsage # How to upload and embed a cast # Install asciinema and record a terminal session following the Quick start guide. Edit the .cast file if required. Add the .cast file in the same directory as your article. Embed a Hugo shortcode in your article.\nFor example, the shortcode below embeds the file demo.cast and adjusts some asciinema player options: {{\u0026lt; asciinema key=\u0026#34;demo\u0026#34; idleTimeLimit=\u0026#34;2\u0026#34; speed=\u0026#34;1.5\u0026#34; poster=\u0026#34;npt:0:09\u0026#34; \u0026gt;}} The above shortcode will be rendered as follows:\nHow to embed a cast from asciinema.org # You can embed a cast hosted on asciinema.org:\nUnder the video, click the Share button Copy the code snippet provided under Embed the player and paste where needed, for example\n\u0026lt;script src=\u0026ldquo;https://asciinema.org/a/342851.js\" id=\u0026ldquo;asciicast-342851\u0026rdquo; async=\u0026ldquo;true\u0026rdquo;\u0026gt;\u0026lt;/script\u0026gt; The above shortcode will be rendered as follows:\nResources # Embedding asciinema cast in your Hugo site ","date":"18 March 2024","externalUrl":null,"permalink":"/pages/contribution-guide/asciinema-casts/","section":"","summary":"","title":"asciinema casts","type":"pages"},{"content":"“Developing IoT Projects with ESP32” by Vedat Ozan Oner serves as a key guide, especially in its second edition, which has been thoughtfully updated to reflect the latest trends in IoT development.\nTargeted at C++ developers who want to create powerful applications using the ESP-IDF. The book explains step by step the complexities of IoT development with the ESP32. Vedat Ozan Oner, the author, is recognized for his passion for IoT, ability of making tricky topics easy to understand.\nContent and Structure # The book is well-organized into twelve detailed chapters, each focusing on a specific area of ESP32 development. Starting with a basic introduction to IoT and the ESP32 platform in the first chapter and moving to advanced discussions on Machine Learning and Edge Impulse Development in later chapters, the book provides a step-by-step learning path. Oner introduces complex concepts like LittleFS or FlatBuffers at just the right time, allowing readers to build their knowledge gradually.\nWho is it for? # While the book is a valuable source of information for students and hobbyist makers, the readers are expected to have a basic knowledge of software development. The book content breaks down complex concepts and code into smaller, manageable parts, which are then put together into larger applications. This approach makes the learning process smoother and shows how to apply theory to real-life projects.\nKey Highlights # One of the book’s important points is coverage of security in IoT, a critical yet often neglected topic. Chapter 7 dives into essential security features needed for any large-scale IoT project, including secure boot processes and Over-the-Air (OTA) updates.\nThe chapters on Smart Home solutions and Machine Learning bring the book up to date with the latest trends in AI and IoT. These sections are especially notable, offering a peek into the future of IoT devices that are not just connected but also smart.\nPracticality and Relevance # “Developing IoT Projects with ESP32” is packed with practical examples, source code, and advice that can be used right away in real projects. The use of diagrams and code snippets helps clarify complex topics, making this book a hands-on guide for developers looking to improve their IoT development skills.\nConclusion # Overall, “Developing IoT Projects with ESP32” is a comprehensive and current guide. Whether you are a student, a hobbyist maker or an experienced developer, this book is a valuable resource, offering insights into security, OTA, AI, and ML, ensuring that your IoT projects are not only functional but also secure and forward-looking.\n","date":"29 January 2024","externalUrl":null,"permalink":"/blog/book-review-developing-iot-projects-with-esp32-2nd-edition/","section":"Blog","summary":"","title":"Book review: Developing IoT Projects with ESP32 (2nd Edition)","type":"blog"},{"content":"","date":"29 January 2024","externalUrl":null,"permalink":"/tags/books/","section":"Tags","summary":"","title":"Books","type":"tags"},{"content":"Announcing ESP ZeroCode ExL powered by AWS IoT ExpressLink — Simplifying Matter-compatible Cloud-connected Devices\nAs a part of our efforts to make the development of Matter protocol-enabled devices easy, Espressif announced ESP ZeroCode modules and ESP ZeroCode Console earlier this year. These ESP ZeroCode modules are well-suited for Matter connectivity for simple devices such as lighting fixtures, switches, sockets, blind controllers, and sensors. You can use ESP ZeroCode Console to configure, evaluate, and order ESP ZeroCode modules.\nIn continuation of these efforts, Espressif, in collaboration with Amazon Web Services (AWS), is glad to announce the ESP ZeroCode ExL connectivity module powered by AWS IoT ExpressLink. This module is based on Espressif’s ESP32-C6 system-on-chip (SoC) providing Wi-Fi 6, Bluetooth 5 (LE), and 802.15.4 connectivity. It contains built-in Matter and cloud connectivity software providing a simple AT commands-based serial interface to the host. With such a simplified integration, you can build Matter-compliant, secure IoT devices that connect to AWS IoT Core and other AWS services.\nWhy ESP ZeroCode ExL? # When device makers want to build cloud-connected devices, they have to write and maintain a significant amount of software. It also needs a deep understanding of connectivity, security, OTA upgrades, and device management. The addition of the Matter protocol adds to this making the development, maintenance, and certification even more complex. The ESP ZeroCode ExL module moves this important yet undifferentiated workload onto a separate module, allowing device makers to easily build the hardware interfacing and business logic onto the host MCU. On the other hand, AWS IoT ExpressLink is designed and built with the best security and cloud connectivity practices and the Espressif implementation went through rigorous security and functionality testing. The ESP ZeroCode ExL firmware by Espressif extends the AWS IoT ExpressLink with Matter protocol implementation. This significantly reduces the efforts and time required for building and maintaining connected products by device makers.\nTarget Devices # The Matter 1.2 specification adds support for new device types including appliances like refrigerators, laundry washers, air purifiers, and air conditioners. Additionally, some of the other device types are already supported such as dimmers, touch switches, and thermostats. Many of these types of devices have a dedicated MCU responsible for building the device logic. Also, cloud connectivity is a major feature for many of these device types especially in the appliance domain. ESP ZeroCode ExL offers simplified Matter and cloud connectivity for these devices and is even well-positioned for retrofitting existing designs to Matter-compliant and cloud-connected ones. It is important to note that ESP ZeroCode ExL can also enable Matter and cloud connectivity to devices beyond these types, supporting devices even with small, resource-constrained host MCUs.\nKey Features # ESP ZeroCode ExL implements AWS IoT ExpressLink specification version 1.2 and Matter protocol specification version 1.2.\nAWS IoT ExpressLink Features: # Matter protocol features # Security # ESP ZeroCode ExL modules are security hardened with hardware root of trust based on Secure Boot and Digital Signature Peripheral. All the sensitive data such as device identity and Wi-Fi network credentials are encrypted and secured using hardware security features such as flash encryption, digital signature peripheral, and HMAC peripheral. ESP ZeroCode ExL firmware is tested with the AWS-provided regression test suite. Communication interfaces such as Wi-Fi, BLE, and serial interface are verified against memory corruption attacks. Secure OTA ensures only the trusted firmware gets executed on the module as well as on the host. These security features add significant value and make the job of device makers significantly easier.\nReady for Evaluation? # Espressif provides an easy evaluation through the ESP ZeroCode Console for the ESP ZeroCode ExL module. You can use any ESP32-C6 development board to quickly try out the functionality completely in the web browser. ESP ZeroCode Console supports a refrigerator, laundry washer, air conditioner, thermostat, and dimmer device types with ESP ZeroCode ExL module. We will be soon expanding on these device types.\nIf you need more information about ESP ZeroCode ExL modules, please reach out to us at zerocode@espressif.com and we will get back to you as quickly as we can.\n","date":"12 November 2023","externalUrl":null,"permalink":"/blog/esp-zerocode-exl-module-powered-by-aws-iot-expresslink-simplifying-matter-compatible/","section":"Blog","summary":"","title":"Announcing ESP ZeroCode ExL Module","type":"blog"},{"content":"","date":"12 November 2023","externalUrl":null,"permalink":"/authors/developer-portal/","section":"Developer Portal Authors","summary":"","title":"Developer Portal","type":"authors"},{"content":" ESP ZeroCode allows device makers to instantly specify, build and launch connected products, right through their browsers. A wide variety of products such as lightbulbs, lighting fixtures, led strips, sockets, switches, roller blinds, refrigerators, laundry washers, thermostats and more are supported.\nArticles # The various articles on ESP ZeroCode are available below:\nMatter based connected devices: Announcing ESP ZeroCode Appliances with Matter and Cloud Connectivity: Announcing ESP ZeroCode ExL Module What’s new with ESP ZeroCode Podcast # ","date":"12 November 2023","externalUrl":null,"permalink":"/blog/esp-zerocode/","section":"Blog","summary":"","title":"ESP ZeroCode","type":"blog"},{"content":"","date":"2 November 2023","externalUrl":null,"permalink":"/tags/aiot/","section":"Tags","summary":"","title":"AIoT","type":"tags"},{"content":"Espressif Systems is announcing the new release of the Arduino ESP32 core including support for the ESP32-C6 and ESP32-H2 with the most recent ESP-IDF 5.1\nBack in September 2021, Arduino ESP32 Core version 2.0.0 was announced and introduced the support for the ESP32-S2, ESP32-S3 (in a later release) and ESP32-C3. This release was a huge milestone for the community not only because of the new SoCs (System on Chips) support but also because of the new era for the project, including an enormous number of new features, bug fixes, new examples, drivers, and the core documentation in 14 releases, 800 commits have been added by 88 contributors after the 2.0.0 release.\nSince the Arduino ESP32 core version 2.0.0, new chips became available, and new features are now needed to keep and improve the developer’s experience and the integration with Arduino IDE (Integrated Development Environment). To continue with the remarkable success of version 2.0.0, the Arduino ESP32 core team is working hard in cooperation with the community to not stop making history.\nNow it is time to announce the Arduino ESP32 Core major version 3.0.0 release with new SoC’s support (now including support for ESP32-C6 and ESP32-H2), API improvements and breaking changes.\nESP32-C6 # nnounced in 2022, this new SoC from the C-series introduced the Wi-Fi 6 and the 802.15.4.\nA low-power and cost-effective 2.4 GHz Wi-Fi 6 + Bluetooth 5 (LE) + Thread/Zigbee SoC, with a 32-bit RISC-V core, for securely connected devices.\nESP32-C6 Datasheet\nESP32-H2 # This new SoC from the new H-series is the latest 802.15.4 (Thread and Zigbee) with Bluetooth, however, this time without Wi-Fi connectivity.\nEspressif’s IEEE 802.15.4 + Bluetooth 5 (LE) SoC, powered by a 32-bit RISC-V core, designed for low power and secure connectivity.\nESP32-H2 Datasheet\nMoving from 2.0.X version to 3.0.0 # The new Arduino ESP32 core is still under development, however, you can test the development version.\nSince this is a development version, you might encounter some issues. You can report them to Arduino ESP32 GitHub issue tracker.\nThe expected stable release of the latest version is December 2023 and the 2.0.x will be under support maintenance until July 2024 then will be discontinued.\nSome of the major changes in version 3.0.0 are related to APIs. The changes include the updated examples to be compatible with the new APIs.\nMake sure to review and test your application. To help the migration from the Arduino ESP32 core 2.0.x to 3.0.0, we prepared a guide that will assist you with the migration process. Here is the Migration Guide.\nIf you want to see all the changes in the development release alpha, here is the full change log.\nMajor Changes from the 2.0.x to 3.0.0 # Here are the major changes from version 2.0.x to 3.0.0.\nPeripheral Manager # The Peripheral Manager was created to help users and avoid peripheral configuration with GPIOs mistakes. This new functionality will be transparent to the user; however, it will warn the user about the current peripheral configuration.\nManages the peripherals initialization and avoid common issues like:\nSame GPIO being used on two peripherals at the same time Restricted GPIOs being used on some other peripherals, like FLASH and PSRAM Prints the report after the initialization to show all peripherals being used Helps on the peripheral management on different ESPs families ome ESPs have a different number of peripherals, channels, and limits.\nFor example, if you configure the GPIO18 for the SPI peripheral and then after the SPI initialization you set the same GPIO18 for the RMT peripheral, the SPI will be deinitialized.\nThe Peripheral Manager prints in the Verbose Debug Level, a full report including chip information, memory allocation, partitions, software information, board details, and the GPIO mapping. Here is an example of the Peripheral Manager report when the following peripherals are initialized:\nESP-ROM:esp32c3-api1-20210207 Build:Feb 7 2021 rst:0x1 (POWERON),boot:0xc (SPI_FAST_FLASH_BOOT) SPIWP:0xee mode:DIO, clock div:1 load:0x3fcd5820,len:0x458 load:0x403cc710,len:0x814 load:0x403ce710,len:0x2878 entry 0x403cc710 =========== Before Setup Start =========== Chip Info: ------------------------------------------ Model : ESP32-C3 Package : 0 Revision : 3 Cores : 1 Frequency : 160 MHz Embedded Flash : No Embedded PSRAM : No 2.4GHz WiFi : Yes Classic BT : No BT Low Energy : Yes IEEE 802.15.4 : No ------------------------------------------ INTERNAL Memory Info: ------------------------------------------ Total Size : 341480 B ( 333.5 KB) Free Bytes : 312940 B ( 305.6 KB) Allocated Bytes : 24960 B ( 24.4 KB) Minimum Free Bytes: 312940 B ( 305.6 KB) Largest Free Block: 294900 B ( 288.0 KB) ------------------------------------------ Flash Info: ------------------------------------------ Chip Size : 4194304 B (4 MB) Block Size : 65536 B ( 64.0 KB) Sector Size : 4096 B ( 4.0 KB) Page Size : 256 B ( 0.2 KB) Bus Speed : 80 MHz Bus Mode : QIO ------------------------------------------ Partitions Info: ------------------------------------------ nvs : addr: 0x00009000, size: 20.0 KB, type: DATA, subtype: NVS otadata : addr: 0x0000E000, size: 8.0 KB, type: DATA, subtype: OTA app0 : addr: 0x00010000, size: 1280.0 KB, type: APP, subtype: OTA_0 app1 : addr: 0x00150000, size: 1280.0 KB, type: APP, subtype: OTA_1 spiffs : addr: 0x00290000, size: 1408.0 KB, type: DATA, subtype: SPIFFS coredump : addr: 0x003F0000, size: 64.0 KB, type: DATA, subtype: COREDUMP ------------------------------------------ Software Info: ------------------------------------------ Compile Date/Time : Nov 2 2023 10:06:48 Compile Host OS : windows ESP-IDF Version : v5.1.1-577-g6b1f40b9bf-dirty Arduino Version : 3.0.0 ------------------------------------------ Board Info: ------------------------------------------ Arduino Board : ESP32C3_DEV Arduino Variant : esp32c3 Arduino FQBN : esp32:esp32:esp32c3:JTAGAdapter=default,CDCOnBoot=default,PartitionScheme=default,CPUFreq=160,FlashMode=qio,FlashFreq=80,FlashSize=4M,UploadSpeed=921600,DebugLevel=debug,EraseFlash=none ============ Before Setup End ============ [ 380][I][esp32-hal-i2c.c:99] i2cInit(): Initialising I2C Master: sda=8 scl=9 freq=100000 =========== After Setup Start ============ INTERNAL Memory Info: ------------------------------------------ Total Size : 341480 B ( 333.5 KB) Free Bytes : 314976 B ( 307.6 KB) Allocated Bytes : 22508 B ( 22.0 KB) Minimum Free Bytes: 312360 B ( 305.0 KB) Largest Free Block: 286708 B ( 280.0 KB) ------------------------------------------ GPIO Info: ------------------------------------------ 8 : I2C_MASTER 9 : I2C_MASTER 20 : UART_RX 21 : UART_TX ============ After Setup End ============= ESP-IDF 5.1 # The Arduino ESP32 core 3.0.0 is based on the ESP-IDF 5.1 which includes the support for the new SoCs (ESP32-C6 and ESP32-H2). This version also brings new features that could be implemented on the following versions without the need to update the ESP-IDF core like the 802.15.4 features.\nSPI Ethernet Support # From now on, the SPI Ethernet is supported with the ESP-IDF SPI library and Arduino SPI. This new support includes the W5500, DM9051 and the KSZ8851SNL Ethernet ICs.\nNew I2S Library # The new I2S library has been added based on the ESP-IDF API.\nWake Word and Command Recognition (ESP32-S3 only) # Based on the ESP-SR, the ESP32-S3 will support voice recognition, being capable of wake word and command recognition.\nTensorFlowLite Micro support # TensorFlow is now supported, and examples were added.\nImproved APIs # The APIs improved includes:\nADC BLE I2S LEDC RMT SigmaDelta Timer UART (HardwareSerial) Deprecated: The Hall Sensor is no longer supported.\nNew boards added # New boards have been added, including from Adafruit, Arduino.cc, M5Stack, LILYGO, and many others.\nHow to Install the development version of the Arduino ESP32 Core # To install the development version of Arduino ESP32 Core on the Arduino IDE, you can follow the installation instructions in our documentation.\nDevelopment release link for Arduino IDE:\nhttps://espressif.github.io/arduino-esp32/package_esp32_dev_index.json Keep Updated # If you want to keep updated about the Arduino ESP32 Core development releases, you can follow us on GitHub, Gitter channel or participate in our monthly community meetings.\nGitHub Repository Gitter Community Meetings A special thank you to all our community that motivated us to keep improving the Arduino ESP32 core support!\n","date":"2 November 2023","externalUrl":null,"permalink":"/blog/2023/11/announcing-the-arduino-esp32-core-version-3-0-0/","section":"Blog","summary":"Announcing the version 3.0.0 of the Arduino Core for Espressif devices, as well the Arduino Component for ESP-IDF. Now, ESP32-C6 and ESP32-H2 are supported.","title":"Announcing the Arduino ESP32 Core version 3.0.0","type":"blog"},{"content":" Overview # The “software bill of materials” (SBOM) has emerged as a key building block in software security and software supply chain risk management. An SBOM is a comprehensive list of all the software components, dependencies, and metadata associated with an application.\nEspressif believes that this information is a key step towards ensuring the security of the connected devices. And as such, we have now enabled easy to use tools and solutions to track and analyze this information.\nIn this blog post, we shall look through the Espressif’s SBOM generator and analysis tool, ESP-IDF-SBOM .\nSBOM # According to National Telecommunications and Information Administration’s (NTIA) SBOM FAQ, the official definition of SBOM goes as follows:\nA Software Bill of Materials (SBOM) is a complete, formally structured list of components, libraries, and modules that are required to build (i.e., compile and link) a given piece of software and the supply chain relationships between them. These components can be open source or proprietary, free or paid, and widely available or restricted access.\nKey data fields for each component includes:\nSupplier Name Component Name Version of the Component Other Unique Identifiers Dependency Relationship Author of SBOM Data Timestamp SBOM data needs to be presented in consistent and digestible formats. Some formats to handle the data representation are SPDX, CycloneDX etc.\nSimple conceptual SBOM tree for wifi_provisioning component from ESP-IDF looks like below:\nSPDX # Software Package Data Exchange (SPDX) is an open standard for communicating software bill of materials (SBOM) information that supports accurate identification of software components, explicit mapping of relationships between components, and the association of security and licensing information with each component.\nThe image below outlines what data can be found in an SPDX document.\nESP-IDF-SBOM # ESP-IDF-SBOM is a SBOM generator tool. It generates SPDX format SBOM for ESP-IDF based applications. This tool also allows to check the generated SBOM for known security vulnerabilities against National Vulnerabilitiy Database (NVD).\nSBOM Generator Workflow # Brief tool workflow goes like:\nCollect sbom.yml (a manifest file) files from dependant components Parse project description file generated by the ESP-IDF build system Generate SPDX report Scan generated SPDX against the CVE databse to generate final report Getting Started # Install the tool and checkout its help:\n$ pip install esp-idf-sbom $ esp-idf-sbom --help usage: esp-idf-sbom [-h] [-q] [-n] [-f] [-v] [-d] [--no-progress] {create,check,manifest} ... ESP-IDF SBOM tool positional arguments: {create,check,manifest} sub-command help create Create SBOM file based on the ESP-IDF project_description.json file. check Check components/submodules in the ESP-IDF SBOM file for possible vulnerabilities reported in the National Vulnerability Database. manifest Commands operating atop of manifest files. options: -h, --help show this help message and exit -q, --quiet By default auxiliary messages like errors, warnings, debug messages or progress are reported to the standard error stream. With this option set, all such messages are suppressed. -n, --no-colors Do not emit color codes. By default color codes are used when stdout or stderr is connected to a terminal. -f, --force-colors Emit color codes even when stdout or stderr is not connected to a terminal. -v, --verbose Be verbose. Messages are printed to standard error output. -d, --debug Print debug information. Messages are printed to standard error output. --no-progress Disable progress bar. Generate the SBOM file:\n$ cd esp-idf/examples/provisioning/wifi_prov_mgr $ idf.py build $ esp-idf-sbom create \u0026lt;project description file\u0026gt; --output-file prj.spdx The project description file is a path to the project_description.json file, which is by default created by the ESP-IDF build system in the project\u0026rsquo;s build directory.\nCheck SBOM against the security vulnerabilities:\n$ esp-idf-sbom check prj.spdx Report summary ┌───────────────────────────────────┬─────────────────────────────────────────────────────────┐ │ Date: │ 2023-10-10T08:21:39Z │ │ Project name: │ project-wifi_prov_mgr │ │ Project version: │ v5.2-dev-3250-g7d8f015a4c │ │ Vulnerability database: │ NATIONAL VULNERABILITY DATABASE (https://nvd.nist.gov) │ │ Generated by tool: │ esp-idf-sbom (0.8.0) │ │ Generated with command: │ esp-idf-sbom check prj.spdx │ │ Number of scanned packages: │ 57 │ ├───────────────────────────────────┼─────────────────────────────────────────────────────────┤ │ CRITICAL CVEs found: │ │ │ Packages affect by CRITICAL CVEs: │ │ │ Number of CRITICAL CVEs: │ 0 │ ├───────────────────────────────────┼─────────────────────────────────────────────────────────┤ │ HIGH CVEs found: │ │ │ Packages affect by HIGH CVEs: │ │ │ Number of HIGH CVEs: │ 0 │ ├───────────────────────────────────┼─────────────────────────────────────────────────────────┤ │ MEDIUM CVEs found: │ │ │ Packages affect by MEDIUM CVEs: │ │ │ Number of MEDIUM CVEs: │ 0 │ ├───────────────────────────────────┼─────────────────────────────────────────────────────────┤ │ LOW CVEs found: │ │ │ Packages affect by LOW CVEs: │ │ │ Number of LOW CVEs: │ 0 │ ├───────────────────────────────────┼─────────────────────────────────────────────────────────┤ │ UNKNOWN CVEs found: │ │ │ Packages affect by UNKNOWN CVEs: │ │ │ Number of UNKNOWN CVEs: │ 0 │ ├───────────────────────────────────┼─────────────────────────────────────────────────────────┤ │ All CVEs found: │ │ │ All packages affect by CVEs: │ │ │ Total number of CVEs: │ 0 │ └───────────────────────────────────┴─────────────────────────────────────────────────────────┘ Packages with No Identified Vulnerabilities ┏━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓ ┃ Package ┃ Version ┃ CPE ┃ ┡━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┩ │ project-wifi_prov_mgr │ v5.2-dev-3250-g7d8f015a4c │ cpe:2.3:a:espressif:esp-idf:5.2-dev-325 │ │ │ │ 0-g7d8f015a4c:*:*:*:*:*:*:* │ ├───────────────────────┼───────────────────────────┼─────────────────────────────────────────┤ │ lwip │ 2.1.3 │ cpe:2.3:a:lwip_project:lwip:2.1.3:*:*:* │ │ │ │ :*:*:*:* │ ├───────────────────────┼───────────────────────────┼─────────────────────────────────────────┤ │ cjson │ 1.7.16 │ cpe:2.3:a:cjson_project:cjson:1.7.16:*: │ │ │ │ *:*:*:*:*:* │ ├───────────────────────┼───────────────────────────┼─────────────────────────────────────────┤ │ protobuf-c │ 1.4.1 │ cpe:2.3:a:protobuf-c_project:protobuf-c │ │ │ │ :1.4.1:*:*:*:*:*:*:* │ ├───────────────────────┼───────────────────────────┼─────────────────────────────────────────┤ │ mbed_tls │ 3.4.1 │ cpe:2.3:a:arm:mbed_tls:3.4.1:*:*:*:*:*: │ │ │ │ *:* │ ├───────────────────────┼───────────────────────────┼─────────────────────────────────────────┤ │ freertos │ 10.4.3 │ cpe:2.3:o:amazon:freertos:10.4.3:*:*:*: │ │ │ │ *:*:*:* │ └───────────────────────┴───────────────────────────┴─────────────────────────────────────────┘ ...snip Some highlights from the SBOM vulnerability check:\nwifi_prov_mgr application from ESP-IDF v5.2-dev was used for the exercise It is possible to scan the components which are not linked into final executable by adding \u0026ndash;check-all-packages in the check command shown above It is also possible to generate the SBOM report for the ESP-IDF bootloader. Bootloader specific build description file can be found in the build/bootloader directory inside the project Some key components like RTOS, Networking Stack, TLS Stack etc. having Common Platform Enumeration entries have been highlighted in the above output Tool also displays information about other component and libraries (not shown in the above log) which are part of the build process Report Format # This tool supports multiple formats for the generated output report like JSON, CSV etc. Please refer to the tool help for more details.\nCompatibility # SPDX being a standard format for SBOM, also offers compatibility with the external tools. SBOM files generated from esp-idf-sbom can also be scanned using tools like cve-bin-tool. This offers an added advantage if you already have any external tools integrated in your system and want to take advantage of its specific features (e.g., more extended scan against different CVE databases).\nSummary # To summarize, some key advantages of SBOM are:\nForms inventory of the components building the software artifacts Lists software licenses, component versions and helps to keep them up-to-date Helps to perform security vulnerability analysis Becoming a pre-requisite in many security related certifications ESP-IDF-SBOM tool is useful to generate SBOM for ESP-IDF based projects. The tool can also further help to scan and setup process for continuous security vulnerability scanning of the project.\nWe are actively working on to enable wider SBOM coverage across our software solutions and looking for feedback on the ESP-IDF-SBOM tool.\nPlease do try and share your experience!\n","date":"2 November 2023","externalUrl":null,"permalink":"/blog/software-bill-of-materials/","section":"Blog","summary":"","title":"Software Bill of Materials","type":"blog"},{"content":"","date":"23 October 2023","externalUrl":null,"permalink":"/authors/deepakumar-v-u/","section":"Developer Portal Authors","summary":"","title":"Deepakumar V U","type":"authors"},{"content":"Espressif Matter Series #10\nIn the previous blogs, we discussed various aspects of Matter. One of which was the Matter Security Model. Matter’s Security Model is based on PKI infrastructure, a widely used security model for securing communications and establishing trust and identity in the digital world. (To know more about Matter’s Security Model you can read this blog).\nWhy is Revocation required? # In Matter, every device has its own unique identity in the form of a DAC (Device Attestation Certificate), which is used to identify itself as a valid Matter device. What if this identity gets stolen, compromised, or is no longer valid? That’s where revocation comes into play. Certificate revocation helps us mark a certificate as revoked before its scheduled expiration.\nIn the PKI world, there are various ways to maintain and circulate the status of the certificate. One such mechanism is the CRL (Certificate Revocation List), which CSA has decided to go ahead with for managing revoked certificates in Matter. A CRL will maintain a list of certificates that have been revoked per Certificate Authority. And pointers to these CRLs are maintained in DCL.\nEffect of certificate revocation # When a certificate is revoked, all the certificate’s issued under it, including itself, will be revoked, i.e., if a PAI is revoked, then the PAI and all the DACs issued under it will stand revoked irrespective of their scheduled expiry.\nMatter will support the revocation of PAI and DACs via CRLs.\nThe User Experience # Each device that is being commissioned will be checked for its revocation status during the commissioning stage. The commissioner may also carry out periodic checks to ensure the device’s revocation status if it has already been commissioned.\nUpon discovering the revoked status of the device, the commissioner can notify the user. It is then the user’s responsibility to make a conscious decision regarding whether to allow the device to operate with limited functionality or not. Ultimately, the problem can be resolved by the vendor, who has the ability to replace the device’s DAC.\nThe Trust # Without revocation, counterfeiters may exploit compromised keys and certificates to create convincing imitations of genuine products. These unauthorised devices often employ low-quality components, compromising performance and security. Customers, lacking a means to distinguish between fake and real products, may unwittingly purchase counterfeits, thus leading to an increased presence of fake devices on the market and eroding trust.\nEffective revocation mechanisms can disable devices misusing compromised keys, ensuring customers receive only genuine, reliable products. This maintains trust in product authenticity and Matter as a whole.\nEspressif’s Matter Pre-Provisioning Service # Espressif’s Matter Pre-Provisioning Service allows you to order modules from Espressif that are securely pre-programmed with the unique details (DAC) that every Matter device needs to have. To ensure trust and reliability, our solution will soon support PAI and DAC revocation too.\nNow that we understand how revocation can help every stakeholder in the Matter Ecosystem, let’s deep-dive into some technical details.\nWhat is CRL? # A CRL is a signed blob that has a list of certificates that are issued by the CA but are not to be trusted anymore. These CRLs are signed by the issuing certificate authority or by a dedicated CRL signer for that CA. In the case of DACs, it will be the PAI (Product Attestation Intermediate) that will be issuing the CRL. These CRLs will be further hosted by the CA vendors for easy access.\nBelow is an example of what a CRL will have.\nIn the above CRL, the certificate with serial number “490B5C02EAF6285B60D5344076AA7204” is revoked because of “Key Compromise”, where the serial number acts as a unique identifier for the certificate the CA issued.\nDCL in Revocation # With Matter being adopted widely, there are a large number of PAAs and PAIs, and that number has been growing continuously. And each of these CAs will have their own CRL published and maintained, respectively. Now the consumers of the CRL, i.e., commissioners, need a single source of truth to get the CRL of all the CAs, so that the commissioner can determine if the device is to be trusted or not.\nTo construct this single source of truth, CSA has decided to go ahead with DCL (Distributed Compliance Ledger), where each CA will have URLs pointing to their CRL, and the onus is on the CA administrators to keep the CRL updated. To learn more about DCL, you can read this blog.\nGiven the large number of CRLs, commissioners are advised to maintain a revocation set that is constructed by combining all the available CRLs in the DCL so that the commissioners can easily identify the revocation status for a given certificate without the need to process all the CRLs in real time. This will ensure the smooth commissioning and functioning of the device. This revocation set can exist in the commissioner’s cloud or locally in the commissioner’s application.\nInclusion in Matter Specification # The Certificate Revocation has been included in Matter Specification version 1.2 (released in Fall 2023), which mandates the CAs to publish and maintain the CRLs in DCL, effective September 1st, 2024. Given the benefits it brings to the table, this is a pivotal inclusion.\n","date":"23 October 2023","externalUrl":null,"permalink":"/blog/matter-and-certificate-revocation/","section":"Blog","summary":"","title":"Matter and Certificate Revocation","type":"blog"},{"content":" DevCon23 # If you missed the second DevCon edition, you can watch here!\nDay 1 # Day 2 # ","date":"13 September 2023","externalUrl":null,"permalink":"/events/devcon23/","section":"Events","summary":"","title":"Espressif DevCon23","type":"events"},{"content":" Today Espressif is launching the ESP ZeroCode. This is a web application that lets you quickly prepare Matter-certifiable firmware, as per your requirements, in just a few clicks. You describe the kind of product you wish to create, the features you want to have, and its hardware configuration, that’s it. You can instantly try out the generated firmware on the physical hardware. If you don’t like something, you go back and tweak it all you want. This is truly a magical experience, try creating a product now at the ESP ZeroCode Console.\nOnce you are satisfied, you can directly place orders, and get the ESP ZeroCode modules delivered to you. The ESP ZeroCode modules are pre-flashed with the firmware and all the contents required to make this a fully functional Matter device. All the complexities of unique manufacturing and programming are already taken care of.\nWith ESP ZeroCode, you skip the development, as well as the maintenance phase of a typical product cycle. You directly manufacture and launch your products in the market. Espressif continues to maintain the firmware with the latest updates and security fixes to ensure that your in-field devices are always secure and Matter compatible.\nExceptional End-User Experience # All ESP ZeroCode modules are Matter certified, they work out of the box with any other Matter ecosystem of your choice. For all these platforms your users do not need a separate phone app to talk to these devices. The devices can be configured and controlled directly through leading ecosystem vendor apps or through the respective voice assistants; guaranteeing the best experience your users can have with your products.\nCost-optimized # Matter standard compatibility results in reduced direct and indirect product costs.\nFor direct cost savings— Matter compatible devices don’t necessarily need to have an always-on cloud connectivity. They can be controlled remotely using the ecosystem hubs (such as Amazon Echo, Apple HomePod, Apple TV, or Google Nest hubs). The voice control too doesn’t require cloud-to-cloud messaging as voice assistants control the devices using Matter protocol in the local network.\nIn terms of indirect cost savings — You don’t have to develop and maintain phone apps or voice assistant skills. Activities like Matter-compatible firmware development, maintenance, certification, and device manufacturing, which otherwise can add to the cost, is handled by Espressif in this ZeroCode offering.\nSimplified Manufacturing # When you order ESP ZeroCode modules, the hardware modules are pre-flashed with all the specific details necessary for your product and its configuration. The per-device unique configurations like Device Attestation Certificates, QR codes, device identifiers, and other details, which usually take longer on the factory line, are also pre-programmed.\nSpecifically, Device Attestation Certificates provisioning requires setting up engagement with some signing service and a secure manufacturing setup which otherwise can add to the cost and time significantly. With ZeroCode modules you get this out of the box.\nThis means all you have to do is mount these modules on your PCBs, apply the corresponding QR code stickers, and you are good to go. Everything else is already taken care of.\nProduct Branding # The ESP ZeroCode modules are so certified that you may use the Matter badge on your product packaging (actual logos may vary). This logo helps the consumers choose products which they can be assured of having Matter compliance and hence greater interoperability.\nThe ESP ZeroCode modules are, optionally, certified to work well with ecosystem vendors as well. This allows for more seamless integration with these ecosystems. If opted, additional badges of Works with Apple Home, and Works With Google Home, may be used on your product packaging subject to your product meeting the guidelines as highlighted in the respective programs\nSecure, Robust and Well-maintained # The ESP ZeroCode modules, by default, have the highest possible security settings, like secure boot and flash encryption, configured on them.\nAdditionally, the firmware is closely aligned with Matter’s open-source repository. Espressif ensures that the ESP ZeroCode modules will continue to get over-the-air (OTA) firmware upgrades for the next 3 years so that the latest security fixes are deployed on these devices as early as possible.\nSupported Device Types # Today, the ESP ZeroCode portal supports a wide variety of devices including light bulbs, panels, downlights, lamps, LED strips, switches, wall sockets, and blind controllers among others. For all these devices, you may choose either Wi-Fi or 802.15.4/Thread-based connectivity.\nWe are currently working on supporting more configurable device features as well as device types. If you are looking for a specific device type, please reach out to zerocode@espressif.com with your request.\nGet Going # If you find this exciting, head over to the ESP ZeroCode console and start creating your product. With the *Try in ESP Launchpad *feature you can instantly try the configured product, and once satisfied place volume orders.\nWe are excited about the launch of ESP ZeroCode and look forward to enabling great end-user experiences!\nWe would love to hear any feedback you may have or any new product/feature requests at: zerocode@espressif.com.\nDisclaimers: All trademarks and copyrights are property of their respective owners.\nAmazon Alexa is a trademark of Amazon.com, Inc, or its affiliates.\nApple and Apple Home are trademarks of Apple Inc., registered in the U.S. and other countries and regions.\nGoogle and Google Home are trademarks of Google LLC.\n","date":"20 August 2023","externalUrl":null,"permalink":"/blog/announcing-esp-zerocode/","section":"Blog","summary":"","title":"Announcing ESP ZeroCode","type":"blog"},{"content":"","date":"27 July 2023","externalUrl":null,"permalink":"/tags/core-dump/","section":"Tags","summary":"","title":"Core Dump","type":"tags"},{"content":"Zephyr OS is an open-source, scalable, and adaptable real-time operating system (RTOS) for multiple hardware platforms, including Espressif’s SoCs ESP32, ESP32S2, ESP32C3, and ESP32S3. Zephyr OS provides a wide range of features for embedded systems development, including support for generating and analyzing core dumps on unrecoverable software errors.\nA core dump is a snapshot of the state of a program’s memory when it crashes. It can be used to debug the program and find the cause of the crash. So, it is possible to find out what task, at what instruction (line of code), and what call stack of that program led to the crash. It is also possible to dump variables content on demand if previously attributed accordingly.\nZephyr OS provides support for multiple core dump backends, including the logging backend. The logging backend dumps core dumps to the UART, which can then be saved to a file and analyzed using a custom GDB server and the GDB provided by the SDK.\nHow To Use # To use the logging backend for core dumps, you need to enable the following Kconfig options:\nCONFIG_DEBUG_COREDUMP=y CONFIG_DEBUG_COREDUMP_BACKEND_LOGGING=y Once you have enabled the logging backend, the application will generate the core dump during a fatal error. CPU registers and memory content will be printed to the console.\nCopy and paste the content into a file called coredump.log .\nWe need to convert this text file to a binary that can be parsed by the custom GDB server. To do that just run the coredump_serial_log_parser.py script\n./scripts/coredump/coredump_serial_log_parser.py coredump.log coredump.bin The script will output the binary file to coredump.bin .\nStart the custom GDB server with the .elf file from the zephyr application and the binary core dump file as parameters:\n./scripts/coredump/coredump_gdbserver.py build/zephyr/zephyr.elf coredump.bin In another terminal just run Xtensa’s GDB from the Zephyr SDK with the .elf file as parameter:\n~/zephyr-sdk-0.16.0/xtensa-espressif_esp32_zephyr-elf/bin/xtensa-espressif_esp32_zephyr-elf-gdb build/zephyr/zephyr.elf Inside GDB, attach to the custom server with:\n(gdb) target remote localhost:1234 Now you can examine the state of the program at the time of the crash, read variables values, backtraces and register values.\nExample # Here is an example of how to use the logging backend for core dumps to debug a program.\nWe will build and flash the coredump test located in tests/subsys/debug/coredump\nThe program defines three functions: func_1, func_2, and func_3. func_1 calls func_2, which calls func_3. func_3 attempts to dereference a null pointer. This will cause the program to crash.\nThe crash will generate a core dump file, which we will use to debug the program.\nwest build -p -b esp32 tests/subsys/debug/coredump Flash and monitor the ESP32 board: west flash \u0026amp;\u0026amp; west espressif monitor Here is the expected output:\n*** Booting Zephyr OS build zephyr-v3.3.0-3986-gebf86941118f *** Coredump: esp32 E: ** FATAL EXCEPTION E: ** CPU 0 EXCCAUSE 29 (store prohibited) E: ** PC 0x400d0435 VADDR (nil) E: ** PS 0x60620 E: ** (INTLEVEL:0 EXCM: 0 UM:1 RING:0 WOE:1 OWB:6 CALLINC:2) E: ** A0 0x80081716 SP 0x3ffe65e0 A2 0x3f401cb8 A3 (nil) E: ** A4 0x3f401cb8 A5 0xff A6 0x3ffb1ad8 A7 0x3ffe5dfc E: ** A8 (nil) A9 0x3ffe6590 A10 0x3f400968 A11 0x3f4012d0 E: ** A12 0x3ffb1ad8 A13 0x60420 A14 0x3ffe5dd8 A15 0x3ffe5e30 E: ** LBEG (nil) LEND (nil) LCOUNT (nil) E: ** SAR 0x1b E: #CD:BEGIN# E: #CD:5a4501000500050000000000 E: #CD:4101006800 E: #CD:0202000135040d401d000000000000001b000000200606000000000016170880 E: #CD:e065fe3fb81c403f00000000b81c403fff000000d81afb3ffc5dfe3f00000000 E: #CD:9065fe3f6809403fd012403f000000009065fe3f6809403fd012403f00000000 E: #CD:0000000000000000 E: #CD:4d0100d81afb3f581bfb3f E: #CD:d81cfb3fd81cfb3f000000000180000000000000000000000000000000000000 E: #CD:000000000000000000000000000000000000000000000000101bfb3f101bfb3f E: #CD:6d61696e00000000000000000000000000000000000000000000000000000000 E: #CD:00000000305efe3f0008000000000000f5ffffff0864fe3f080afb3fffffffff E: #CD:4d0100305efe3f3066fe3f E: #CD:f4b6dbfcd7903c37a5f85ffb73a1c5ad7da3432d420e03142b7673dc1f70a451 E: #CD:e4165f6f2491c43b0aae041aa6bad45d0d019d7bd7061165478aa8e8e9dfb05d E: #CD:5e9ca79574bd8eee1a446b5919d39bbdc7a78c067dd9348e7dd99f3bc0ae0e59 E: #CD:05a5d5e1459c6325d537dd4db75d0210f30e67e7e292f5af90ea8bab11d9090c E: #CD:14bacecb11dc47c19ae8d3922a290fcbe82ff95e23d63ad210459e8fc79dc78a E: #CD:e443c9dbf22b94b0ed95e23bba0f6006022225d48e85ba76d148caff2b2fd519 E: #CD:324d6de3d17410eeae3d5a6513bfc8eed68141495be8c069e69dcea9748fd38e E: #CD:59fc1f6e57f36d52ba51d383d2df4ab9746d893b9bf276879d2182cfd03fe1fe E: #CD:fce68691b4df96c5ac234d34a8eb21f199191138061a17245042ab8ac94e14ac E: #CD:0e017619e4b42895aec67da7fdfb525168850547d0f2530247b1995dfaf9ddc5 E: #CD:168588d974a379bcc3ddbead2edba5571dcbdd29c06ab11b41793d3ba2e15ab4 E: #CD:da808c516438cd28215077c160bb5e0221b6c2d827db238850687d5cad9736f4 E: #CD:60f9f777da01758a56b11a2fa9fc4bd9eaddb172f844223ea356ac0d5f77324f E: #CD:14417a13726f99d28c42bdedf33cc9a198dbe361b4974d152256806c0db076f8 E: #CD:12b3e2c95e5dc84dd6d028065abf26054ff992b205ca641e249417dd7368bd92 E: #CD:d8faf9e19687346bf31e315db64a05c049b23cf3a10eb60d6472211fdd43e8cc E: #CD:7b334dbb3b549c5b91bea3352ac68b3f6b199e2967344cc07da7d79c4bdc884c E: #CD:6ebcd3093df87d7633ccb583b036864cc48166283095024d592b16600f4ed38f E: #CD:bd1e1bdaf1538c6134c078d1f7b69f9467774e910b318854a0fcdd8841b12e0d E: #CD:74ca51cad7c6b020789c6affacc31d39a034d13c0ebaa3a07b53f81091d7b704 E: #CD:8641f161cbaacd75c8aa1bd1b557470083e87921b4ae92960764aa2ad6eff203 E: #CD:c32fa391df51c8c38aa88c5a54bf130009f26b64a8b2a15418b4286ab0edc3ec E: #CD:08d9c9c133fad8213c38e9ccb7505e2940c9612ceeb772440786012cddf5bbaf E: #CD:435c265247afa7e2cdb315fa23e47a45b9050d8cb61b4a72646f58febc81773f E: #CD:cbf027958c8a67478a2f9441bc94767ec90f446ba54ff82b893dddaddd42a004 E: #CD:2a26cb016dfb2c1e0c691e319505c4167e83031ee83cd0843165c00b63fa4e96 E: #CD:01f75bce679271064f56595a83ca5ae00ea79ba5c396f560a709dfa617e1dd14 E: #CD:714ee1c87b95a422386d41a70f88df76019315875cc82b030dd005ba35af53bc E: #CD:029df20768fe4612c91133a5f38602715c05ef9b330ea662402b4779b8de6e8b E: #CD:6d8cad92e2fe7600ea3c4c83744186abc127d75f6f9334365e0c6b8c2ea6c82b E: #CD:7ea6b0095adbdbc82ba150a670db718a67d5fe5d8b9f04a48eafff8d2200e075 E: #CD:d18277cc7bcbd8419bb21b15cfddc8340bd7721707bd54ff04fb72c71ec12ce7 E: #CD:8ce9635cf260717cbe2cf8392f7796c24a2384dd9db2142dc00e7dc83c9b8119 E: #CD:3e8a971d612a603e88062e7679ada4082e8fddc80cdd34bfd9df64f4a887d9b0 E: #CD:920fff4ae8ee63e1e48e611e887334929a89ccce5ecb250c03ca59178b3eb5dc E: #CD:d88de936c368020f892357c7700d2b9ac237affbe9aad454736025fc37e7a4f0 E: #CD:b60103116de8e418f17b1ffea7c3840ce9b5de74f2714451e7c774b0fc94d2d1 E: #CD:8c3e9f17ac30161adf79c9cee52cfa79e62cc228781234124557f6463fe95228 E: #CD:80d4d0b905bc05fb54e134ced7f84ac128ba82cda103f29f9a62e4c5f4105021 E: #CD:80f085cb993e77c86f82ecf01dac257e25942f840eccd2e11385a946fd7b508c E: #CD:71e13192d9b4ceba06ae199b77127b529791be9b878657590a3c5a263d9c8319 E: #CD:b9f9487e4086539f1e4758b87ca24b70887d185c7e617ff288bde4944e2c6cf3 E: #CD:fb23feb7aadf90c80c6d00f66d287f80f52c7d593a108e9ff178fc30defc40d4 E: #CD:3b59f4efbd708b0f0192d457450ad657d3b45fc4d254406d7ac94f4eafdc5be4 E: #CD:ba1719090cbed14af915ca7991db7b87027ced573a0e6aff7078a83139df611f E: #CD:3fa23f95b5c39b7e15c92108a5322206fb74ee59e39327b66180c48dd9cbc1cb E: #CD:00c04eeb3550aa7e24de68fa4aa720be1ee74e8dc10a57a93c64fe3f00000000 E: #CD:00c050eb0000000000000000703d088000c04eeb010000006d00000000000000 E: #CD:3266fe3f0000000000000000db32008c00c050eb010000000000000000000000 E: #CD:0a0000000000000020020600703d0840093d0880001008406d000000a01c403f E: #CD:7c330880a064fe3f6d00000000000000fedf99ececff33aec26b3658ed9c5be5 E: #CD:283d0880c064fe3f6d00000006000000c01cfb3fd81afb3fd81afb3fd865fe3f E: #CD:4c3d08804065fe3f6809403fc065fe3fd012403f000000008000037300000000 E: #CD:00000000000000001a2488bc891e7d358fc4ecfa81e597aa9df65bb7a6a74806 E: #CD:c065fe3fa065fe3f04000000c065fe3fa065fe3ffc3c0840000000007509403f E: #CD:000000007209403fdb8a502716f5e7f50400000025000000a065fe3f04000000 E: #CD:30040d809065fe3f6809403fd012403f000000003b4bed4f08035fadadc14494 E: #CD:0a1751af3f39a63cf90f74b2820658d1cbb50403fb4800949c65fe3fd81afb3f E: #CD:20040600d85dfe3f305efe3f000000009065fe3f6809403fd012403fb81c403f E: #CD:ff000000d81afb3ffc5dfe3fdf2daf23000000001d0000000000000000000000 E: #CD:000000001b0000002006060035040d401617088000100840b81c403f00000000 E: #CD:56040d800066fe3f0000000000000000b81c403fff000000d81afb3ffc5dfe3f E: #CD:000000002066fe3ff81608400000000000000000000000007f00000000000000 E: #CD:000000004066fe3f000000000000000000000000000000000000000000000000 E: #CD:END# E: \u0026gt;\u0026gt;\u0026gt; ZEPHYR FATAL ERROR 0: CPU exception on CPU 0 E: Current thread: 0x3ffb1ad8 (main) E: Halting system The core dump content begins with #CD:BEGIN# and ends with #CD:END#. We need to copy the content in between to a new file called coredump.log\nCopy core dump to coredump.log E: #CD:BEGIN# E: #CD:5a4501000500050000000000 E: #CD:4101006800 E: #CD:0202000135040d401d000000000000001b000000200606000000000016170880 E: #CD:e065fe3fb81c403f00000000b81c403fff000000d81afb3ffc5dfe3f00000000 E: #CD:9065fe3f6809403fd012403f000000009065fe3f6809403fd012403f00000000 E: #CD:0000000000000000 E: #CD:4d0100d81afb3f581bfb3f E: #CD:d81cfb3fd81cfb3f000000000180000000000000000000000000000000000000 E: #CD:000000000000000000000000000000000000000000000000101bfb3f101bfb3f E: #CD:6d61696e00000000000000000000000000000000000000000000000000000000 E: #CD:00000000305efe3f0008000000000000f5ffffff0864fe3f080afb3fffffffff E: #CD:4d0100305efe3f3066fe3f E: #CD:f4b6dbfcd7903c37a5f85ffb73a1c5ad7da3432d420e03142b7673dc1f70a451 E: #CD:e4165f6f2491c43b0aae041aa6bad45d0d019d7bd7061165478aa8e8e9dfb05d E: #CD:5e9ca79574bd8eee1a446b5919d39bbdc7a78c067dd9348e7dd99f3bc0ae0e59 E: #CD:05a5d5e1459c6325d537dd4db75d0210f30e67e7e292f5af90ea8bab11d9090c E: #CD:14bacecb11dc47c19ae8d3922a290fcbe82ff95e23d63ad210459e8fc79dc78a E: #CD:e443c9dbf22b94b0ed95e23bba0f6006022225d48e85ba76d148caff2b2fd519 E: #CD:324d6de3d17410eeae3d5a6513bfc8eed68141495be8c069e69dcea9748fd38e E: #CD:59fc1f6e57f36d52ba51d383d2df4ab9746d893b9bf276879d2182cfd03fe1fe E: #CD:fce68691b4df96c5ac234d34a8eb21f199191138061a17245042ab8ac94e14ac E: #CD:0e017619e4b42895aec67da7fdfb525168850547d0f2530247b1995dfaf9ddc5 E: #CD:168588d974a379bcc3ddbead2edba5571dcbdd29c06ab11b41793d3ba2e15ab4 E: #CD:da808c516438cd28215077c160bb5e0221b6c2d827db238850687d5cad9736f4 E: #CD:60f9f777da01758a56b11a2fa9fc4bd9eaddb172f844223ea356ac0d5f77324f E: #CD:14417a13726f99d28c42bdedf33cc9a198dbe361b4974d152256806c0db076f8 E: #CD:12b3e2c95e5dc84dd6d028065abf26054ff992b205ca641e249417dd7368bd92 E: #CD:d8faf9e19687346bf31e315db64a05c049b23cf3a10eb60d6472211fdd43e8cc E: #CD:7b334dbb3b549c5b91bea3352ac68b3f6b199e2967344cc07da7d79c4bdc884c E: #CD:6ebcd3093df87d7633ccb583b036864cc48166283095024d592b16600f4ed38f E: #CD:bd1e1bdaf1538c6134c078d1f7b69f9467774e910b318854a0fcdd8841b12e0d E: #CD:74ca51cad7c6b020789c6affacc31d39a034d13c0ebaa3a07b53f81091d7b704 E: #CD:8641f161cbaacd75c8aa1bd1b557470083e87921b4ae92960764aa2ad6eff203 E: #CD:c32fa391df51c8c38aa88c5a54bf130009f26b64a8b2a15418b4286ab0edc3ec E: #CD:08d9c9c133fad8213c38e9ccb7505e2940c9612ceeb772440786012cddf5bbaf E: #CD:435c265247afa7e2cdb315fa23e47a45b9050d8cb61b4a72646f58febc81773f E: #CD:cbf027958c8a67478a2f9441bc94767ec90f446ba54ff82b893dddaddd42a004 E: #CD:2a26cb016dfb2c1e0c691e319505c4167e83031ee83cd0843165c00b63fa4e96 E: #CD:01f75bce679271064f56595a83ca5ae00ea79ba5c396f560a709dfa617e1dd14 E: #CD:714ee1c87b95a422386d41a70f88df76019315875cc82b030dd005ba35af53bc E: #CD:029df20768fe4612c91133a5f38602715c05ef9b330ea662402b4779b8de6e8b E: #CD:6d8cad92e2fe7600ea3c4c83744186abc127d75f6f9334365e0c6b8c2ea6c82b E: #CD:7ea6b0095adbdbc82ba150a670db718a67d5fe5d8b9f04a48eafff8d2200e075 E: #CD:d18277cc7bcbd8419bb21b15cfddc8340bd7721707bd54ff04fb72c71ec12ce7 E: #CD:8ce9635cf260717cbe2cf8392f7796c24a2384dd9db2142dc00e7dc83c9b8119 E: #CD:3e8a971d612a603e88062e7679ada4082e8fddc80cdd34bfd9df64f4a887d9b0 E: #CD:920fff4ae8ee63e1e48e611e887334929a89ccce5ecb250c03ca59178b3eb5dc E: #CD:d88de936c368020f892357c7700d2b9ac237affbe9aad454736025fc37e7a4f0 E: #CD:b60103116de8e418f17b1ffea7c3840ce9b5de74f2714451e7c774b0fc94d2d1 E: #CD:8c3e9f17ac30161adf79c9cee52cfa79e62cc228781234124557f6463fe95228 E: #CD:80d4d0b905bc05fb54e134ced7f84ac128ba82cda103f29f9a62e4c5f4105021 E: #CD:80f085cb993e77c86f82ecf01dac257e25942f840eccd2e11385a946fd7b508c E: #CD:71e13192d9b4ceba06ae199b77127b529791be9b878657590a3c5a263d9c8319 E: #CD:b9f9487e4086539f1e4758b87ca24b70887d185c7e617ff288bde4944e2c6cf3 E: #CD:fb23feb7aadf90c80c6d00f66d287f80f52c7d593a108e9ff178fc30defc40d4 E: #CD:3b59f4efbd708b0f0192d457450ad657d3b45fc4d254406d7ac94f4eafdc5be4 E: #CD:ba1719090cbed14af915ca7991db7b87027ced573a0e6aff7078a83139df611f E: #CD:3fa23f95b5c39b7e15c92108a5322206fb74ee59e39327b66180c48dd9cbc1cb E: #CD:00c04eeb3550aa7e24de68fa4aa720be1ee74e8dc10a57a93c64fe3f00000000 E: #CD:00c050eb0000000000000000703d088000c04eeb010000006d00000000000000 E: #CD:3266fe3f0000000000000000db32008c00c050eb010000000000000000000000 E: #CD:0a0000000000000020020600703d0840093d0880001008406d000000a01c403f E: #CD:7c330880a064fe3f6d00000000000000fedf99ececff33aec26b3658ed9c5be5 E: #CD:283d0880c064fe3f6d00000006000000c01cfb3fd81afb3fd81afb3fd865fe3f E: #CD:4c3d08804065fe3f6809403fc065fe3fd012403f000000008000037300000000 E: #CD:00000000000000001a2488bc891e7d358fc4ecfa81e597aa9df65bb7a6a74806 E: #CD:c065fe3fa065fe3f04000000c065fe3fa065fe3ffc3c0840000000007509403f E: #CD:000000007209403fdb8a502716f5e7f50400000025000000a065fe3f04000000 E: #CD:30040d809065fe3f6809403fd012403f000000003b4bed4f08035fadadc14494 E: #CD:0a1751af3f39a63cf90f74b2820658d1cbb50403fb4800949c65fe3fd81afb3f E: #CD:20040600d85dfe3f305efe3f000000009065fe3f6809403fd012403fb81c403f E: #CD:ff000000d81afb3ffc5dfe3fdf2daf23000000001d0000000000000000000000 E: #CD:000000001b0000002006060035040d401617088000100840b81c403f00000000 E: #CD:56040d800066fe3f0000000000000000b81c403fff000000d81afb3ffc5dfe3f E: #CD:000000002066fe3ff81608400000000000000000000000007f00000000000000 E: #CD:000000004066fe3f000000000000000000000000000000000000000000000000 E: #CD:END# Convert to binary format: ./scripts/coredump/coredump_serial_log_parser.py coredump.log coredump.bin Start the custom GDB server: ./scripts/coredump/coredump_gdbserver.py build/zephyr/zephyr.elf coredump.bin -v Expected output:\n[INFO][gdbstub] Log file: coredump.bin [INFO][gdbstub] ELF file: build/zephyr/zephyr.elf [INFO][parser] Reason: K_ERR_CPU_EXCEPTION [INFO][parser] Pointer size 32 [INFO][parser] Memory: 0x3ffb1ad8 to 0x3ffb1b58 of size 128 [INFO][parser] Memory: 0x3ffe5e30 to 0x3ffe6630 of size 2048 [INFO][parser] ELF Section: 0x0 to 0x1f of size 32 (read-only data) [INFO][parser] ELF Section: 0x20 to 0x3b of size 28 (read-only data) [INFO][parser] ELF Section: 0x40080000 to 0x400803ff of size 1024 (text) [INFO][parser] ELF Section: 0x40080400 to 0x40083e7b of size 14972 (text) [INFO][parser] ELF Section: 0x3f400040 to 0x3f401bff of size 7104 (read-only data) [INFO][parser] ELF Section: 0x3f401c00 to 0x3f401c3f of size 64 (read-only data) [INFO][parser] ELF Section: 0x3f401c40 to 0x3f401cb7 of size 120 (read-only data) [INFO][parser] ELF Section: 0x3f401cb8 to 0x3f401cd9 of size 34 (read-only data) [INFO][parser] ELF Section: 0x3ffb0a20 to 0x3ffb0a57 of size 56 (read-only data) [INFO][parser] ELF Section: 0x400d0020 to 0x400d3d53 of size 15668 (text) [INFO][gdbstub] Waiting GDB connection on port 1234... In a new terminal, start the Xtensa ESP32 GDB that is located in Zephyr’s SDK: ~/zephyr-sdk-0.16.0/xtensa-espressif_esp32_zephyr-elf/bin/xtensa-espressif_esp32_zephyr-elf-gdb build/zephyr/zephyr.elf Inside GDB, attach to the remote server: (gdb) target remote localhost:1234 Remote debugging using localhost:1234 0x400d0435 in func_3 (addr=0x0) at zephyr/tests/subsys/debug/coredump/src/main.c:27 27 *addr = 0; Run bt command to see the backtrace in the moment of the crash: (gdb) bt #0 0x400d0435 in func_3 (addr=0x0) at zephyr/tests/subsys/debug/coredump/src/main.c:27 #1 func_2 (addr=0x0) at zephyr/tests/subsys/debug/coredump/src/main.c:40 #2 func_1 (addr=0x0) at zephyr/tests/subsys/debug/coredump/src/main.c:45 #3 main () at zephyr/tests/subsys/debug/coredump/src/main.c:52 Conclusion # Core dump is a powerful tool for debugging programs in Zephyr with ESP32 boards. By using the logging backend for core dumps, you can easily generate core dump files that can be analyzed using a debugger. This can help you to identify the cause of a program crash and fix the bug in your program quickly and easily.\n","date":"27 July 2023","externalUrl":null,"permalink":"/blog/2023/07/core-dump-a-powerful-tool-for-debugging-programs-in-zephyr-with-esp32-boards/","section":"Blog","summary":"How to use Zephyr Core Dump feature with Espressif Devices.","title":"Core Dump: A Powerful Tool for Debugging Programs in Zephyr with ESP32 Boards","type":"blog"},{"content":"","date":"27 July 2023","externalUrl":null,"permalink":"/tags/debug/","section":"Tags","summary":"","title":"Debug","type":"tags"},{"content":"","date":"27 July 2023","externalUrl":null,"permalink":"/tags/debugging-tools/","section":"Tags","summary":"","title":"Debugging Tools","type":"tags"},{"content":"","date":"27 July 2023","externalUrl":null,"permalink":"/authors/lucas-tamborrino/","section":"Developer Portal Authors","summary":"","title":"Lucas Tamborrino","type":"authors"},{"content":"","date":"24 July 2023","externalUrl":null,"permalink":"/authors/ali-hassan-shah/","section":"Developer Portal Authors","summary":"","title":"Ali Hassan Shah","type":"authors"},{"content":"","date":"24 July 2023","externalUrl":null,"permalink":"/tags/esp/","section":"Tags","summary":"","title":"Esp","type":"tags"},{"content":"","date":"24 July 2023","externalUrl":null,"permalink":"/tags/esp-box/","section":"Tags","summary":"","title":"Esp Box","type":"tags"},{"content":"","date":"24 July 2023","externalUrl":null,"permalink":"/tags/openai/","section":"Tags","summary":"","title":"OpenAI","type":"tags"},{"content":"Integrating OpenAI capabilities into projects has become increasingly trends in today’s fast-paced technological landscape. OpenAI offers a wide range of powerful APIs for natural language processing. However, the process of integrating these APIs can be complex and time-consuming, often requiring substantial effort and expertise. To simplify this integration process, we introduce the OpenAI Component, a powerful library that streamlines the incorporation of OpenAI APIs into projects.\nIn this article, we will demonstrating how it enables developers to easily add OpenAI capabilities to their projects without having to handle all the implementation tasks.\nThis article consists of three main sections. The initial section “ESP Component Registry ”provides information on step involve in adding appropriate components into your ESP-IDF project. The second section focuses on providing details about the “OpenAI Component” and the last section gives and update on “ESP-Box * ChatGPT * ” demo example.\nESP Component Registry # The ESP Component Registry ____ acts as a central hub for an extensive array of open-source components that can turbocharge your IoT projects. By simply performing a quick search and a few clicks, you can effortlessly obtain the desired components and seamlessly incorporate them into your IDF projects. This efficient workflow expedites your development cycle, enabling you to concentrate on creating groundbreaking IoT solutions without the burden of complex setup procedures.\nSteps to Follow # idf.py add-dependency \u0026#34;espressif/Component name^verison\u0026#34; OpenAI Component # To provide developers with comprehensive coverage of OpenAI API features, a simple yet powerful ESP-IDF component is introduced. This component offers extensive support, focusing on a wide range of functionalities while excluding file operations and fine-tuning capabilities. There is comprehensive documentation accessible to assist developers in comprehending the APIs effortlessly.\nUsage Example # The first step is to instantiate an object and provide a secure “API key” as a parameter. The OpenAPI key is accessible through the OPENAI website. To gain access to OpenAI services, you must first create an account, purchase tokens, and obtain your unique API key.\nopenai = OpenAICreate(key); After creating the OpenAI object, the code calls the chatCompletion API. It sets the required parameters, sends a message (indicating it’s not the last message), and retrieves the generated response for further use or processing.\nchatCompletion = openai-\u0026gt;chatCreate(openai); chatCompletion-\u0026gt;setModel(chatCompletion, \u0026#34;gpt-3.5-turbo\u0026#34;); chatCompletion-\u0026gt;setSystem(chatCompletion, \u0026#34;Code geek\u0026#34;); chatCompletion-\u0026gt;setMaxTokens(chatCompletion, CONFIG_MAX_TOKEN); chatCompletion-\u0026gt;setTemperature(chatCompletion, 0.2); chatCompletion-\u0026gt;setStop(chatCompletion, \u0026#34;\\r\u0026#34;); chatCompletion-\u0026gt;setPresencePenalty(chatCompletion, 0); chatCompletion-\u0026gt;setFrequencyPenalty(chatCompletion, 0); chatCompletion-\u0026gt;setUser(chatCompletion, \u0026#34;OpenAI-ESP32\u0026#34;); OpenAI_StringResponse_t *result = chatCompletion-\u0026gt;message(chatCompletion, \u0026#34;Hello!, World\u0026#34;, false); //Calling Chat completion api char *response = result-\u0026gt;getData(result, 0); Similarly, after instantiating the OpenAI object, the code calls the audioTranscriptionCreate API. It sets the necessary parameters, such as the audio file and language, followed by initiating the audio transcription process. Finally, it retrieves the transcription result for further use or processing.\naudioTranscription = openai-\u0026gt;audioTranscriptionCreate(openai); audioTranscription-\u0026gt;setResponseFormat(audioTranscription, OPENAI_AUDIO_RESPONSE_FORMAT_JSON); audioTranscription-\u0026gt;setLanguage(audioTranscription,\u0026#34;en\u0026#34;); audioTranscription-\u0026gt;setTemperature(audioTranscription, 0.2); char *text = audioTranscription-\u0026gt;file(audioTranscription, (uint8_t *)audio, audio_len, OPENAI_AUDIO_INPUT_FORMAT_WAV); // Calling transcript api To explore more APIs and their functionalities, please refer to the documentation.\nESP-BOX ChatGPT Demo Example # The updated version of the ESP-BOX ChatGPT example incorporates the OpenAI component, replacing the older version. Further details on the development process can be found in the Blog. Notably, in the newer version, we have implemented a secure method to store the Wi-Fi and OpenAI keys in non-volatile storage (NVS) using a esp_tinyuf2 component.\nDuring the initial boot, the first binary is executed, allowing the user to enter secure credentials such as Wi-Fi and OpenAI keys. Once the credentials are entered, the system restarts, and the ChatGPT binary takes control. This binary is responsible for running the ChatGPT functionality, utilizing the secure credentials provided during the initial boot. The workflow for this process is illustrated in the figure below, providing an overview of the overall process.\nAdditionally, users have the option to try out the newer version of the ESP-BOX ChatGPT example using the ESP-Launchpad without the need to compile the project locally on the machines. This option offers a convenient means for individuals to experience the improvements and advancements made in the implementation.\n","date":"24 July 2023","externalUrl":null,"permalink":"/blog/openai-component-accelerating-the-integration-of-openai-apis-in-projects/","section":"Blog","summary":"","title":"OpenAI Component | Accelerating the integration of OpenAI APIs in projects","type":"blog"},{"content":"We are glad to announce that the Espressif Thread Border Router (ESP Thread BR) solution has received certification from the Thread Group, and the accompanying development kit has now been officially released.\nThis blog post will delve into the technical aspects of the solution and explore the benefits it offers, facilitating faster time-to-market for our customers’ products.\nWhat’s a Thread Border Router? # As defined in the Thread Border Router White Paper:\nA Border Router is a device that can route packets to and from the mesh. This routing happens between the Thread mesh and any other IPbearing interfaces like Wi-Fi, Ethernet, and Cellular.\nESP Thread BR Architecture # ESP Thread BR solution is based on the combination of Espressif’s Wi-Fi and 802.15.4 SoCs, built on the ESP-IDF and open-source OpenThread stack.\nUnlike the well-known ot-br-posix solution that is Linux/Unix-based, the ESP Thread BR is built on the ESP-IDF framework, incorporating integrated components such as Wi-Fi and 802.15.4 stacks, LwIP, mDNS, and more.\nIn the solution, the Host Wi-Fi SoC operates the Espressif Thread BR and OpenThread Core stack, while the 802.15.4 SoC runs the OpenThread RCP (Radio Co-processor). Communication between the two is established through the Spinel protocol.\nESP Thread BR Features # Networking Features # A previous blog Thread Border Router in Matter introduces the role of the Thread Border Router in Matter scenario. Here are the key networking features supported by the ESP Thread BR:\nBi-directional IPv6 connectivity Enable bi-directional IPv6 communication across Thread and non-Thread networks, it currently supports both Wi-Fi and Ethernet as the backbone link.\nService Discovery Implements the functions for bi-directional service discovery, including the Service Registry Protocol (SRP) server, Advertising Proxy, and Discovery Proxy. These functions facilitate zero-configuration discovery of services offered by Thread Devices, as well as services offered by non-Thread devices.\nMulticast Forwarding Implements the Multicast Listener Discovery v2 (MLDv2) protocol and enables seamless IPv6 multicast across Thread, Wi-Fi, and Ethernet networks.\nNAT64 The Thread devices can access the IPv4 internet via the ESP Thread BR.\nNote: Although NAT64 is not a mandatory feature for the Matter scenario, as Matter is primarily designed for local network applications, it does facilitate point-to-point communication between Thread devices and cloud services.\nProduction Features # In addition to the networking features, the Espressif Thread BR SDK also supports multiple useful features for productization.\nRCP Update As the solution involves two SoCs, it requires the download of two matching firmware for over-the-air (OTA) updates. The SDK offers a mechanism that combines the two firmware into a single binary. With a streamlined one-step OTA process, the host SoC will automatically download the RCP firmware to the 802.15.4 SoC during the initial boot.\nRF Coexistence The coexistence design is often a challenging aspect for devices that incorporate multiple radios. The Espressif Thread BR addresses this issue by leveraging an integrated hardware and software design, offering the 3-wires PTA Coexistence feature in the SDK. This feature greatly simplifies the complexity of the customer’s application.\nWeb GUI Additionally, the SDK offers a user-friendly web-based GUI for easy configuration by the user. Moreover, the provided REST APIs are compliant with the APIs offered by ot-br-posix, ensuring compatibility and seamless integration.\nHW Reference and SW SDK # The Espressif Thread BR SDK is available on GitHub:\nhttps://github.com/espressif/esp-thread-br\nhttps://docs.espressif.com/projects/esp-thread-br\nThe Hardware reference design and dev kits are also available (link):\n","date":"14 June 2023","externalUrl":null,"permalink":"/blog/espressif-thread-border-router/","section":"Blog","summary":"","title":"Espressif Thread Border Router","type":"blog"},{"content":"","date":"14 June 2023","externalUrl":null,"permalink":"/tags/open-thread/","section":"Tags","summary":"","title":"Open Thread","type":"tags"},{"content":"In recent years, connected devices have become increasingly prevalent in our daily lives. From smart home devices to industrial automation systems, IoT technology is transforming the way we interact with the world around us. As IoT devices continue to proliferate, the need for reliable, high-capacity, and low-power wireless connectivity has become paramount. This is where Wi-Fi 6 (also known as 802.11ax) comes in, and its adoption in residential and enterprise settings reflects this need.\nAccording to a report by the Wi-Fi Alliance , Wi-Fi 6 reached 50% market adoption more rapidly than any of the previous Wi-Fi generations. This was fuelled by the demand for high-quality Wi-Fi and more efficient, reliable connectivity [1]. Global tech market advisory firm ABI Research expects Wi-Fi 6 access points to increase from 9% of total Wi-Fi consumer premise equipment (CPE) shipments in 2020 to account for nearly 81% of the entire total Wi-Fi market in 2026 [2].\nIt is clear that the adoption rate for Wi-Fi 6 is on the rise, and it is the right time for new products to start utilizing the various features of 802.11ax that are incorporated into the specifications for various IoT applications.\nTo explain the impact of Wi-Fi 6 on IoT applications, it is essential to understand the different features introduced by Wi-Fi 6 and how they enhance network reliability, stability, and performance, enabling IoT applications to benefit from them.\nTarget Wake Time (TWT) # Target Wake Time (TWT) is a feature of Wi-Fi 6 that allows devices to schedule when they will communicate with the wireless network. TWT lets a device turn on its radio interface only when it needs to communicate with the network, thereby reducing power consumption and extending the battery life of IoT devices.TWT works by allowing devices to negotiate a time slot with the access point for communication. This means that devices can plan when they need to wake up to communicate with the network, and the access point can plan its resources to accommodate the communication. TWT thus allows devices to stay in low-power modes for most of the time, which is especially important for battery-operated IoT devices that may not have access to a power source.\nFor IoT applications, TWT can enable the development of battery-operated Wi-Fi devices or sensors for certain applications that do not require fast response times. This feature can also be beneficial for IoT devices that only need to send small amounts of data at infrequent intervals. With TWT, these devices can operate with minimal power consumption, extending their battery life and reducing maintenance requirements.\nWi-Fi Protected Access 3 (WPA3) # WPA3 is the latest security protocol for Wi-Fi networks, designed to address security weaknesses in WPA2. While it is available as an option for Wi-Fi 5 and earlier devices and routers, it is a mandatory requirement for Wi-Fi 6 certification by the Wi-Fi Alliance. This means that all Wi-Fi 6 devices must have WPA3 compatibility to obtain certification, ensuring that they meet the industry standard for security.\nFor IoT applications, the adoption of WPA3 provides several benefits. One is the ability to use QR codes for easy connection to Wi-Fi networks. With WPA3, devices can generate a QR code that can be scanned by a smartphone or tablet to easily connect to a Wi-Fi network. This simplifies the setup process and reduces the risk of errors or security vulnerabilities that can arise from manually entering network credentials.In addition to easy-connect features, WPA3 provides stronger security measures than previous protocols, including protection against offline password-guessing attacks, stronger encryption, and enhanced protection for public Wi-Fi networks. This is particularly important for IoT applications, where security is crucial to prevent unauthorized access or malicious attacks that can compromise the integrity of the system. Overall, the adoption of WPA3 in Wi-Fi 6 devices provides a more robust and secure platform for IoT applications to operate on.\nMU-MIMO Downlink and Uplink (multi-user multiple input multiple output) # MU-MIMO is a wireless technology that allows multiple devices to communicate simultaneously with a single access point (AP). MU-MIMO takes advantage of spatial separation to enable simultaneous communication with multiple devices. By using multiple antennas, the AP can create separate “beam-forming” paths toward different devices, enhancing signal strength and reducing interference. This is a significant improvement over SU-MIMO, which could communicate with only one device at a time. In a congested network where devices have to wait for their turn to communicate with the AP, there can be increased latency and potential timeouts. With MU-MIMO, the wait time is significantly reduced as devices can transmit and receive data concurrently, leading to improved responsiveness. With the support of MU-MIMO on 20MHz Channels as well as for 1SS devices, in Wi-Fi 6, IoT devices can also take advantage of this useful feature.\nMU-MIMO can provide considerable benefits to IoT applications. MU-MIMO impacts the number of devices connected to a single AP by enabling simultaneous communication, utilizing spatial separation, and optimizing resource allocation. These factors collectively increase the network capacity, reduce delays, and enhance overall efficiency, allowing for a larger number of devices to stay connected while maintaining satisfactory performance. This is particularly important in residential and commercial environments with a good number of smart devices connected to the Wi-Fi network. In addition, MU-MIMO can help to reduce latency, which is important for applications that require real-time data transmission, such as industrial automation, security monitoring, and healthcare. With reduced latency, the overall performance and responsiveness of the network can be improved.\nOFDMA (Orthogonal Frequency Division Multiple Access) # OFDMA is a key feature of Wi-Fi 6 that improves the way data is transmitted between access points and multiple IoT devices. OFDMA divides the Wi-Fi channel into smaller sub-channels, known as resource units (RUs), and assigns each RU to a specific device or group of devices. This way, an AP can communicate with multiple devices simultaneously, and each device gets a fair share of the channel’s capacity.\nWith OFDMA, IoT devices can enjoy more consistent attention from the AP, as the resources are allocated more efficiently and predictably. This reduces the chances of packet loss and improves the throughput and overall performance of the network.Furthermore, OFDMA reduces the reliance on the contention methodology that was used in previous Wi-Fi standards, where devices would have to compete with each other for access to the channel. In contrast, OFDMA allows devices to receive their data without waiting for the transmission to other devices to finish. This results in less latency and better responsiveness for time-sensitive IoT applications, such as smart home devices, industrial automation, and healthcare applications.In summary, with this technology, IoT devices can enjoy a more stable and consistent connection, a higher density of device connections, and lower latency of communication.\nBSS Coloring # BSS coloring is a feature introduced in the 802.11ax Wi-Fi standard that helps reduce interference from neighboring access points (APs) and improve coexistence between multiple APs. The basic idea behind BSS coloring is that each BSS or AP uses a unique color (6-bit code) which is carried by the signal preamble or SIG field. The color allows client devices to differentiate between the signals of neighboring APs and avoid interference.In more technical terms, BSS coloring helps reduce co-channel interference (CCI) and adjacent-channel interference (ACI) between neighboring APs. With BSS coloring, each AP is assigned a unique color, which is added to the preamble of each transmitted packet. When a client device receives a packet, it can check the color of the received preamble and use this information to distinguish between the signals of different APs.\nIn dense IoT deployments or environments with a high concentration of devices and interfering Access Points, BSS coloring can be particularly beneficial. It helps prevent unnecessary retransmissions and collisions caused by neighboring networks, thus improving the overall network efficiency and potentially extending the usable range for IoT devices. Overall, BSS coloring is a useful feature in Wi-Fi 6 that helps improve network performance and reliability, particularly in environments with high AP density.\n1024 QAM, 8 SS, 160MHz Band # Other important features introduced in Wi-Fi 6 are focused on increasing the network bandwidth. For example, Wi-Fi 6 uses a higher modulation scheme of 1024 QAM compared to 256 QAM as used in previous generations. This translates to an encoding of 10-bit instead of 8-bit data thus increasing the overall bandwidth by 25%. Similarly, support for up to 8 parallel spacial streams and the addition of 160MHz channel bandwidth also increases the overall physical bandwidth of the network significantly. In general, such high data rates typically are not required for IoT applications. By increasing the available bandwidth and improving the efficiency of data transmission, these features can help ensure that the network can handle high traffic from multiple clients, including IoT devices, without experiencing slowdowns or congestion. This can be particularly important in dense IoT deployments or environments with high levels of network activity.\nEspressif’s ESP32-C6 with Wi-Fi 6 # ESP32-C6 is Espressif’s first Wi-Fi 6 SoC integrating 2.4 GHz Wi-Fi 6, Bluetooth 5 (LE), and the 802.15.4 protocol. ESP32-C6 achieves an industry-leading RF performance, with reliable security features and multiple memory resources for IoT products. ESP32-C6 consists of a high-performance 32-bit RISC-V processor which can be clocked up to 160 MHz, and a low-power 32-bit RISC-V processor which can be clocked up to 20 MHz. ESP32-C6 has a 320KB ROM, and a 512KB SRAM, and works with external flash.\nESP32-C6 has an integrated 2.4 GHz Wi-Fi 6 (802.11ax) radio, which is backward compatible with the 802.11b/g/n standard. ESP32-C6 supports the OFDMA mechanism for both uplink and downlink communications, while also supporting MU-MIMO for downlink traffic. Both of these techniques allow working with high efficiency and low latency, even in congested wireless environments. Additionally, the Target Wake Time (TWT) feature of the 802.11ax standard enables ESP32-C6 customers to build battery-operated connected devices that can last for years, while staying connected throughout.\nIn conclusion, Wi-Fi 6 technology offers a range of features and capabilities that can help maximize IoT performance in various settings, from residential homes to large-scale enterprises. The improved capacity, range, and efficiency of Wi-Fi 6 can support the growing number of IoT devices and advanced applications that are increasingly common in today’s connected world. With the use of the Target Wake Time feature, it is now possible to build battery-operated Wi-Fi devices that are always connected.\nFurthermore, the enhanced security features of Wi-Fi 6, including WPA3 certification, can help protect against potential security threats and ensure that sensitive data remains secure. As the adoption rate of Wi-Fi 6 technology continues to grow, more and more IoT devices and applications will likely rely on Wi-Fi 6 to deliver optimal performance and security.\nOverall, understanding the implications of Wi-Fi 6 features and how they can impact IoT performance is crucial for anyone looking to maximize the potential of IoT technology. By staying up to date with the latest developments in Wi-Fi technology and adopting best practices for IoT connectivity, businesses and consumers alike can ensure that their IoT devices and applications perform at their best, both now and in the future.\nReferences: # ","date":"13 June 2023","externalUrl":null,"permalink":"/blog/leveraging-wi-fi-6-features-for-iot-applications/","section":"Blog","summary":"","title":"Leveraging Wi-Fi 6 Features for IoT Applications","type":"blog"},{"content":"","date":"13 June 2023","externalUrl":null,"permalink":"/tags/low-latency/","section":"Tags","summary":"","title":"Low Latency","type":"tags"},{"content":"","date":"13 June 2023","externalUrl":null,"permalink":"/tags/wi-fi-6/","section":"Tags","summary":"","title":"Wi Fi 6","type":"tags"},{"content":"","date":"12 June 2023","externalUrl":null,"permalink":"/tags/chatgpt/","section":"Tags","summary":"","title":"ChatGPT","type":"tags"},{"content":"","date":"12 June 2023","externalUrl":null,"permalink":"/tags/chatgpt-chatbot/","section":"Tags","summary":"","title":"Chatgpt Chatbot","type":"tags"},{"content":"The world is witnessing a technological revolution, and OpenAI is at the forefront of this change. One of its most exciting innovations is ChatGPT — that utilizes natural language processing to create more engaging and intuitive user experiences. The integration of OpenAI APIs with IoT devices has opened up a world of possibilities.\nIn this article, we will explore the potential of ChatGPT with ESP-BOX, a powerful combination that can take IoT devices to the next level.\nESP-BOX # The ESP-BOX is a new generation AIoT development platform that includes the ESP32-S3-BOX and ESP32-S3-BOX-Lite development boards. These boards are based on the ESP32-S3 Wi-Fi + Bluetooth 5 (LE) SoC and provide a flexible and customizable solution for developing AIoT applications that integrate with various sensors, controllers, and gateways.\nThe ESP-BOX is packed with a wide range of features that make it an ideal AIoT development platform. Let’s take a closer look at some of the key features\nCase Study # Developing a Voice-Controlled Chatbot using ESP-BOX and OpenAI APIs.\nDescription # This case study outlines the development process for a voice-controlled chatbot that utilizes the combination of ESP-BOX and OpenAI API. The system is capable of receiving speech commands from users, displaying them on the screen, and processing them through the OpenAI APIs to generate a response. The response is then displayed on the screen and played through the ESP-BOX. The step-by-step workflow provides a detailed explanation of how to integrate these technologies to create an efficient and effective voice-controlled chatbot.\nEnvironment Setup # Setting up a suitable environment and installing the correct version is critical to avoid errors.\nESP-IDF In this demonstration, we’ll be utilizing ESP-IDF version 5.0 (master branch). If you need guidance on how to set up ESP-IDF, please refer to the official IDF Programming guide for detailed information.\n**As of writing of this blog, the current IDF commit head is df9310ada2.*\nChatGPT API To utilize ChatGPT, a powerful language model based on the GPT-3.5 architecture, you must first obtain a secure API key. This can be achieved by creating an account on the OpenAI platform and obtaining tokens through creation or purchase. With an API key, you gain access to a wide range of features and capabilities that can be customized to meet your specific needs, such as natural language processing and generation, text completion, and conversation modeling. Follow the official API reference link.\n**Maintaining the confidentiality and security of the API key is crucial to prevent unauthorized access to the user’s account and data.*\nAdding Offline Speech Recognition # Espressif Systems, has as developed an innovative speech recognition framework called ESP-SR. This framework is designed to enable devices to recognize spoken words and phrases without relying on external cloud-based services, making it an ideal solution for offline speech recognition applications.\nESP-SR framework consists of various modules, including the Audio Front-end (AFE), Wake Word Engine (WakeNet), Speech Command Word Recognition (MultiNet), and Speech Synthesis (which currently only supports the Chinese language). Follow the official Documentation for more information.\nIntegrating OpenAI API # The OpenAI API provides numerous functions that developers can leverage to enhance their applications. In our project, we utilized the Audio-to-Text and Completion APIs and implemented them using C-language code based on ESP-IDF. The following section provides a brief overview of the code we employed.\nAudio to Text To extract text from audio, we utilize HTTPS and OpenAI Audio API. The following code is used for this task.\nesp_err_t create_whisper_request_from_record(uint8_t *audio, int audio_len) { // Set the authorization headers char url[128] = \u0026#34;https://api.openai.com/v1/audio/transcriptions\u0026#34;; char headers[256]; snprintf(headers, sizeof(headers), \u0026#34;Bearer %s\u0026#34;, OPENAI_API_KEY); // Configure the HTTP client esp_http_client_config_t config = { .url = url, .method = HTTP_METHOD_POST, .event_handler = response_handler, .buffer_size = MAX_HTTP_RECV_BUFFER, .timeout_ms = 60000, .crt_bundle_attach = esp_crt_bundle_attach, }; // Initialize the HTTP client esp_http_client_handle_t client = esp_http_client_init(\u0026amp;config); // Set the headers esp_http_client_set_header(client, \u0026#34;Authorization\u0026#34;, headers); // Set the content type and the boundary string char boundary[] = \u0026#34;boundary1234567890\u0026#34;; char content_type[64]; snprintf(content_type, sizeof(content_type), \u0026#34;multipart/form-data; boundary=%s\u0026#34;, boundary); esp_http_client_set_header(client, \u0026#34;Content-Type\u0026#34;, content_type); // Set the file data and size char *file_data = NULL; size_t file_size; file_data = (char *)audio; file_size = audio_len; // Build the multipart/form-data request char *form_data = (char *)malloc(MAX_HTTP_RECV_BUFFER); assert(form_data); ESP_LOGI(TAG, \u0026#34;Size of form_data buffer: %zu bytes\u0026#34;, sizeof(*form_data) * MAX_HTTP_RECV_BUFFER); int form_data_len = 0; form_data_len += snprintf(form_data + form_data_len, MAX_HTTP_RECV_BUFFER - form_data_len, \u0026#34;--%s\\r\\n\u0026#34; \u0026#34;Content-Disposition: form-data; name=\\\u0026#34;file\\\u0026#34;; filename=\\\u0026#34;%s\\\u0026#34;\\r\\n\u0026#34; \u0026#34;Content-Type: application/octet-stream\\r\\n\u0026#34; \u0026#34;\\r\\n\u0026#34;, boundary, get_file_format(file_type)); ESP_LOGI(TAG, \u0026#34;form_data_len %d\u0026#34;, form_data_len); ESP_LOGI(TAG, \u0026#34;form_data %s\\n\u0026#34;, form_data); // Append the audio file contents memcpy(form_data + form_data_len, file_data, file_size); form_data_len += file_size; ESP_LOGI(TAG, \u0026#34;Size of form_data: %zu\u0026#34;, form_data_len); // Append the rest of the form-data form_data_len += snprintf(form_data + form_data_len, MAX_HTTP_RECV_BUFFER - form_data_len, \u0026#34;\\r\\n\u0026#34; \u0026#34;--%s\\r\\n\u0026#34; \u0026#34;Content-Disposition: form-data; name=\\\u0026#34;model\\\u0026#34;\\r\\n\u0026#34; \u0026#34;\\r\\n\u0026#34; \u0026#34;whisper-1\\r\\n\u0026#34; \u0026#34;--%s--\\r\\n\u0026#34;, boundary, boundary); // Set the headers and post field esp_http_client_set_post_field(client, form_data, form_data_len); // Send the request esp_err_t err = esp_http_client_perform(client); if (err != ESP_OK) { ESP_LOGW(TAG, \u0026#34;HTTP POST request failed: %s\\n\u0026#34;, esp_err_to_name(err)); } // Clean up client esp_http_client_cleanup(client); // Return error code return err; } This code is a function named “whisper_from_record”, which takes in a pointer to a buffer containing the audio data and an integer “*audio_len *” that represents the length of the audio data. This function sends a POST request to the OpenAI API endpoint to transcribe the given audio data.\nThe function starts by initializing the URL of the OpenAI API and setting the authorization headers with the bearer token “OPENAI_API_KEY”. Then, an HTTP client is configured and initialized with the provided configuration, including the URL, HTTP method, event handler, buffer size, timeout, and SSL certificate.\nAfter that, the content type and the boundary string for the multipart form-data request are set as headers to the HTTP client. The file data and its size are also set, and a multipart/form-data request is built. The “form_data” buffer is allocated with a malloc() function, and the necessary information is added to it. This includes the filename and Content-Type of the audio file, the file contents, and the name of the model that will be used for transcription.\nOnce the “*form_data *”is built, it is set as the post field in the HTTP client, and the client sends the POST request to the OpenAI API endpoint. If there is an error during the request, the function logs an error message. Finally, the HTTP client is cleaned up, and the resources allocated for form_data are freed.\nThe function returns an esp_err_t error code, which indicates whether the HTTP request was successful or not.\nChat Completion The OpenAI Chat Completion API is utilized to send HTTPS requests for chat completion. This process involves utilizing the create_chatgpt_request function, which takes in a content parameter representing the input text to the GPT-3.5 model.\nesp_err_t create_chatgpt_request(const char *content) { char url[128] = \u0026#34;https://api.openai.com/v1/chat/completions\u0026#34;; char model[16] = \u0026#34;gpt-3.5-turbo\u0026#34;; char headers[256]; snprintf(headers, sizeof(headers), \u0026#34;Bearer %s\u0026#34;, OPENAI_API_KEY); esp_http_client_config_t config = { .url = url, .method = HTTP_METHOD_POST, .event_handler = response_handler, .buffer_size = MAX_HTTP_RECV_BUFFER, .timeout_ms = 30000, .crt_bundle_attach = esp_crt_bundle_attach, }; // Set the headers esp_http_client_handle_t client = esp_http_client_init(\u0026amp;config); esp_http_client_set_header(client, \u0026#34;Content-Type\u0026#34;, \u0026#34;application/json\u0026#34;); esp_http_client_set_header(client, \u0026#34;Authorization\u0026#34;, headers); // Create JSON payload with model, max tokens, and content snprintf(json_payload, sizeof(json_payload), json_fmt, model, MAX_RESPONSE_TOKEN, content); esp_http_client_set_post_field(client, json_payload, strlen(json_payload)); // Send the request esp_err_t err = esp_http_client_perform(client); if (err != ESP_OK) { ESP_LOGW(TAG, \u0026#34;HTTP POST request failed: %s\\n\u0026#34;, esp_err_to_name(err)); } // Clean up client esp_http_client_cleanup(client); // Return error code return err; } The function first sets up the URL, model, and headers needed for the HTTP POST request, and then creates a JSON payload with the model, max tokens, and content.\nNext, the function sets the headers for the HTTP request and sets the JSON payload as the post field for the request.\nThe HTTP POST request is then sent using “esp_http_client_perform()”, and if the request fails, an error message is logged.\nFinally, the HTTP client is cleaned up and the error code is returned.\nHandling Response Callback function “*response_handler *”that is used by the ESP-IDF HTTP client library to handle events that occur during an HTTP request/response exchange.\nesp_err_t response_handler(esp_http_client_event_t *evt) { static char *data = NULL; // Initialize data to NULL static int data_len = 0; // Initialize data to NULL switch (evt-\u0026gt;event_id) { case HTTP_EVENT_ERROR: ESP_LOGI(TAG, \u0026#34;HTTP_EVENT_ERROR\u0026#34;); break; case HTTP_EVENT_ON_CONNECTED: ESP_LOGI(TAG, \u0026#34;HTTP_EVENT_ON_CONNECTED\u0026#34;); break; case HTTP_EVENT_HEADER_SENT: ESP_LOGI(TAG, \u0026#34;HTTP_EVENT_HEADER_SENT\u0026#34;); break; case HTTP_EVENT_ON_HEADER: if (evt-\u0026gt;data_len) { ESP_LOGI(TAG, \u0026#34;HTTP_EVENT_ON_HEADER\u0026#34;); ESP_LOGI(TAG, \u0026#34;%.*s\u0026#34;, evt-\u0026gt;data_len, (char *)evt-\u0026gt;data); } break; case HTTP_EVENT_ON_DATA: ESP_LOGI(TAG, \u0026#34;HTTP_EVENT_ON_DATA (%d +)%d\\n\u0026#34;, data_len, evt-\u0026gt;data_len); ESP_LOGI(TAG, \u0026#34;Raw Response: data length: (%d +)%d: %.*s\\n\u0026#34;, data_len, evt-\u0026gt;data_len, evt-\u0026gt;data_len, (char *)evt-\u0026gt;data); // Allocate memory for the incoming data data = heap_caps_realloc(data, data_len + evt-\u0026gt;data_len + 1, MALLOC_CAP_SPIRAM | MALLOC_CAP_8BIT); if (data == NULL) { ESP_LOGE(TAG, \u0026#34;data realloc failed\u0026#34;); free(data); data = NULL; break; } memcpy(data + data_len, (char *)evt-\u0026gt;data, evt-\u0026gt;data_len); data_len += evt-\u0026gt;data_len; data[data_len] = \u0026#39;\\0\u0026#39;; break; case HTTP_EVENT_ON_FINISH: ESP_LOGI(TAG, \u0026#34;HTTP_EVENT_ON_FINISH\u0026#34;); if (data != NULL) { // Process the raw data parsing_data(data, strlen(data)); // Free memory free(data); data = NULL; data_len = 0; } break; case HTTP_EVENT_DISCONNECTED: ESP_LOGI(TAG, \u0026#34;HTTP_EVENT_DISCONNECTED\u0026#34;); break; default: break; } return ESP_OK; } In case of “HTTP_EVENT_ON_DATA”, the function allocates memory for the incoming data, copies the data into the buffer and increments the “*data_len *”variable accordingly. This is done to accumulate the response data.\nIn case of “HTTP_EVENT_ON_FINISH”, the function prints a message indicating that the HTTP exchange has finished, and then calls the “*parsing_data *”function to process the accumulated/raw data. It then frees the memory and resets the data and “*data_len *”variables to zero. It then frees the allocated memory and resets the buffer and its length to zero.\nFinally, the function returns “*ESP_OK *”indicating that the operation was successful.\nParsing Raw Data The JSON parser component is utilized to parse the raw response obtained from ChatGPT API and Whisper AI API over HTTPS. To perform this task, a function is used, which employs the parser component. Further details about this tool can be found on GitHub.\nvoid parse_response (const char *data, int len) { jparse_ctx_t jctx; int ret = json_parse_start(\u0026amp;jctx, data, len); if (ret != OS_SUCCESS) { ESP_LOGE(TAG, \u0026#34;Parser failed\u0026#34;); return; } printf(\u0026#34;\\n\u0026#34;); int num_choices; /* Parsing Chat GPT response*/ if (json_obj_get_array(\u0026amp;jctx, \u0026#34;choices\u0026#34;, \u0026amp;num_choices) == OS_SUCCESS) { for (int i = 0; i \u0026lt; num_choices; i++) { if (json_arr_get_object(\u0026amp;jctx, i) == OS_SUCCESS \u0026amp;\u0026amp; json_obj_get_object(\u0026amp;jctx, \u0026#34;message\u0026#34;) == OS_SUCCESS \u0026amp;\u0026amp; json_obj_get_string(\u0026amp;jctx, \u0026#34;content\u0026#34;, message_content, sizeof(message_content)) == OS_SUCCESS) { ESP_LOGI(TAG, \u0026#34;ChatGPT message_content: %s\\n\u0026#34;, message_content); } json_arr_leave_object(\u0026amp;jctx); } json_obj_leave_array(\u0026amp;jctx); } /* Parsing Whisper AI response*/ else if (json_obj_get_string(\u0026amp;jctx, \u0026#34;text\u0026#34;, message_content, sizeof(message_content)) == OS_SUCCESS) { ESP_LOGI(TAG, \u0026#34;Whisper message_content: %s\\n\u0026#34;, message_content); } else if (json_obj_get_object(\u0026amp;jctx, \u0026#34;error\u0026#34;) == OS_SUCCESS) { if (json_obj_get_string(\u0026amp;jctx, \u0026#34;type\u0026#34;, message_content, sizeof(message_content)) == OS_SUCCESS) { ESP_LOGE(TAG, \u0026#34;API returns an error: %s\u0026#34;, message_content); } } } Integrating TTS API # At the moment, OpenAI doesn’t offer public access to their Text-to-Speech (TTS) API. However, there are various other TTS APIs available, including Voicerss, TTSmaker, and TalkingGenie. These APIs can generate speech from text input, and you can find more information about them on their respective websites.\nFor the purposes of this tutorial, we will be using the TalkingGenie API, which is one of the best options available for generating high-quality, natural-sounding speech both in English and Chinese. One of the unique features of TalkingGenie is its ability to translate mixed language text, such as Chinese and English, into speech seamlessly. This can be a valuable tool for creating content that appeals to a global audience. The following code sends a text response generated by ChatGPT to the TalkingGenie API using HTTPS, and then plays the resulting speech through an ESP-BOX.\nesp_err_t text_to_speech_request(const char *message, AUDIO_CODECS_FORMAT code_format) { int j = 0; size_t message_len = strlen(message); char *encoded_message; char *language_format_str, *voice_format_str, *codec_format_str; // Encode the message for URL transmission encoded_message = heap_caps_malloc((3 * message_len + 1), MALLOC_CAP_SPIRAM | MALLOC_CAP_8BIT); url_encode(message, encoded_message); // Determine the audio codec format if (AUDIO_CODECS_MP3 == code_format) { codec_format_str = \u0026#34;MP3\u0026#34;; } else { codec_format_str = \u0026#34;WAV\u0026#34;; } // Determine the required size of the URL bu int url_size = snprintf(NULL, 0, \u0026#34;https://dds.dui.ai/runtime/v1/synthesize?voiceId=%s\u0026amp;text=%s\u0026amp;speed=1\u0026amp;volume=%d\u0026amp;audiotype=%s\u0026#34;, \\ VOICE_ID, \\ encoded_message, \\ VOLUME, \\ codec_format_str); // Allocate memory for the URL buffer char *url = heap_caps_malloc((url_size + 1), MALLOC_CAP_SPIRAM | MALLOC_CAP_8BIT); if (url == NULL) { ESP_LOGE(TAG, \u0026#34;Failed to allocate memory for URL\u0026#34;); return ESP_ERR_NO_MEM; } // Format the URL string snprintf(url, url_size + 1, \u0026#34;https://dds.dui.ai/runtime/v1/synthesize?voiceId=%s\u0026amp;text=%s\u0026amp;speed=1\u0026amp;volume=%d\u0026amp;audiotype=%s\u0026#34;, \\ VOICE_ID, \\ encoded_message, \\ VOLUME, \\ codec_format_str); // Configure the HTTP client esp_http_client_config_t config = { .url = url, .method = HTTP_METHOD_GET, .event_handler = http_event_handler, .buffer_size = MAX_FILE_SIZE, .buffer_size_tx = 4000, .timeout_ms = 30000, .crt_bundle_attach = esp_crt_bundle_attach, }; // Initialize and perform the HTTP request esp_http_client_handle_t client = esp_http_client_init(\u0026amp;config); esp_err_t err = esp_http_client_perform(client); if (err != ESP_OK) { ESP_LOGE(TAG, \u0026#34;HTTP GET request failed: %s\u0026#34;, esp_err_to_name(err)); } // Free allocated memory and clean up the HT heap_caps_free(url); heap_caps_free(encoded_message); esp_http_client_cleanup(client); // Return the result of the function call return err; } The function “*text_to_speech *” takes a message string and an “AUDIO_CODECS_FORMAT” parameter as input. The message string is the text that will be synthesized into speech, while the “*AUDIO_CODECS_FORMAT *” parameter specifies whether the speech should be encoded in MP3 or WAV format.\nThe function first encodes the message string using “url_encode” function that replace some non-valid characters to its ASCII code, and then converts that code to a two-digit hexadecimal representation. Next allocates memory for the resulting encoded string. It then checks the “AUDIO_CODECS_FORMAT” parameter and sets the appropriate codec format string to be used in the “url”.\nNext, the function determines the size of the “url” buffer needed to make a GET request to the TalkingGenie API, and allocates memory for the “url” buffer accordingly. It then formats the “url” string with the appropriate parameters, including the voiceId (which specifies the voice to be used), the encoded text, the speed and volume of the speech, and the audiotype (either “MP3” or “WAV”).\nThe function then sets up an “esp_http_client_config_t” struct with the “url” and other configuration parameters, initializes an esp_http_client_handle_t with the struct, and performs a GET request to the TalkingGenie API using “esp_http_client_perform”. If the request is successful, the function returns ESP_OK, otherwise it returns an error code.\nFinally, the function frees the memory allocated for the “url” buffer and the encoded message, cleans up the “esp_http_client_handle_t”, and returns the error code.\nHandling TTS Response In the similar fashion Callback function “http_event_handler” is defined to handle events that occur during an HTTP request/response exchange.\nstatic esp_err_t http_event_handler(esp_http_client_event_t *evt) { switch (evt-\u0026gt;event_id) { // Handle errors that occur during the HTTP request case HTTP_EVENT_ERROR: ESP_LOGE(TAG, \u0026#34;HTTP_EVENT_ERROR\u0026#34;); break; // Handle when the HTTP client is connected case HTTP_EVENT_ON_CONNECTED: ESP_LOGI(TAG, \u0026#34;HTTP_EVENT_ON_CONNECTED\u0026#34;); break; // Handle when the header of the HTTP request is sent case HTTP_EVENT_HEADER_SENT: ESP_LOGI(TAG, \u0026#34;HTTP_EVENT_HEADER_SENT\u0026#34;); break; // Handle when the header of the HTTP response is received case HTTP_EVENT_ON_HEADER: ESP_LOGI(TAG, \u0026#34;HTTP_EVENT_ON_HEADER\u0026#34;); file_total_len = 0; break; // Handle when data is received in the HTTP response case HTTP_EVENT_ON_DATA: ESP_LOGI(TAG, \u0026#34;HTTP_EVENT_ON_DATA, len=%d\u0026#34;, evt-\u0026gt;data_len); if ((file_total_len + evt-\u0026gt;data_len) \u0026lt; MAX_FILE_SIZE) { memcpy(record_audio_buffer + file_total_len, (char *)evt-\u0026gt;data, evt-\u0026gt;data_len); file_total_len += evt-\u0026gt;data_len; } break; // Handle when the HTTP request finishes case HTTP_EVENT_ON_FINISH: ESP_LOGI(TAG, \u0026#34;HTTP_EVENT_ON_FINISH:%d, %d K\u0026#34;, file_total_len, file_total_len / 1024); audio_player_play(record_audio_buffer, file_total_len); break; // Handle when the HTTP client is disconnected case HTTP_EVENT_DISCONNECTED: ESP_LOGI(TAG, \u0026#34;HTTP_EVENT_DISCONNECTED\u0026#34;); break; // Handle when a redirection occurs in the HTTP request case HTTP_EVENT_REDIRECT: ESP_LOGI(TAG, \u0026#34;HTTP_EVENT_REDIRECT\u0026#34;); break; } return ESP_OK; } “HTTP_EVENT_ON_DATA” event is used to handle the audio data received from the server. The audio data is stored in a buffer called “*record_audio_buffer” *and the total length of the audio data received is stored in a variable called “file_total_len”. If the total length of the audio data received is less than a predefined “MAX_FILE_SIZE”, the data is copied into the “record_audio_buffer”.\nFinally, the “*HTTP_EVENT_ON_FINISH *”event is used to handle the end of the HTTP response. In this case, the “*record_audio_buffer” *is passed to a function called “audio_player_play”which plays the audio.\nDisplay # For display we uses LVGL, an open-source embedded graphics library that is gaining popularity for its powerful and visually appealing features and low memory footprints. LVGL has also released a visual drag-and-drop UI editor called SquareLine Studio. It’s a powerful tool that makes it easy to create beautiful GUIs for your applications.To integrate LVGL with your project, Espressif Systems provides an official package manager tool. This tool allows you to directly add LVGL and related porting components to your project, saving you time and effort. For more information follow the official blogs and documentations.\nConclusion # The integration of OpenAI’s ChatGPT with Espressif’s ESP-BOX has opened up new possibilities for creating powerful and intelligent IoT devices. The ESP-BOX provides a flexible and customizable AIoT development platform with features like far-field voice interaction, offline speech commands recognition, and a reusable GUI framework. By combining these capabilities with the OpenAI API, developers can create voice-controlled chatbots and enhance user experiences in IoT applications.\nDon’t forget to check out Espressif Systems’ GitHub repository for more open-source demos on ESP-IoT-Solution, ESP-SR, and ESP-BOX. The source code for this project will be found here . As part of our future plans, we aim to introduce a component for the OpenAI API that will offer a user-friendly functions.\n","date":"12 June 2023","externalUrl":null,"permalink":"/blog/unleashing-the-power-of-openai-and-esp-box-a-guide-to-fusing-chatgpt-with-espressif-socs/","section":"Blog","summary":"","title":"Unleashing the Power of OpenAI and ESP-BOX: A Guide to Fusing ChatGPT with Espressif SOCs","type":"blog"},{"content":"Edge computing is a distributed computing paradigm that brings computation and data storage closer to the device’s location. Edge Artificial Intelligence (edge-AI) is an exciting development within edge computing because it allows traditional technologies to run more efficiently, with higher performance and less power. Trained neural networks are used to make inferences on small devices. The potential applications areas of edge AI includes manufacturing, healthcare, the retail industry, surveillance, smart home, and finance banking.\nEspressif System provides a framework ESP-DL that can be used to deploy your high-performance deep learning models on ESP32-S3.\nIn this article, you will understand how to read sensor data and using ESP-DL to deploy a deep-learning model on ESP32-S3.\nPrerequisite for using ESP-DL # Before getting a deep dive into ESP-DL, we assume that readers have knowledge about:\nBuilding and training neural networks. (Check out the basics of deep learning) ESP-IDF release/v4.4 environment. (For more details, follow setting-up ESP-IDF environment or tool chain for ESP-IDF) Working knowledge of basic C and C++ language Converting model into ESP-DL formate Note: Please use ESP-IDF release/v4.4 on the commit “cc71308e2fdce1d6d27fc52d39943f5d0fb83f35” to reproduce the same results\n1. Model Deployment # A convolution neural network is designed using accelerometer data to recognize human activity.\n*In this blog we will not focus on the development and conversion of neural networks to ESP-Dl format.\n1.1 ESP-IDF Project Hierarchy # The Project directory should look like this:\n├── CMakeLists.txt ├── components │ ├── bus │ ├── mpu6050 │ └── esp-dl ├── dependencies.lock ├── main │ ├── app_main.cpp │ └── CMakeLists.txt ├── model │ ├── Activity_coefficient.cpp │ ├── Activity_coefficient.hpp │ └── model_define.hpp ├── partitions.csv ├── sdkconfig ├── sdkconfig.defaults ├── sdkconfig.defaults.esp32 ├── sdkconfig.defaults.esp32s2 └── sdkconfig.defaults.esp32s3 2. Model Define # We will define our model in the ‘model_define.hpp’ file. Following the steps below with detailed explanation. When open in Netron our model looks like Figure 1 below.\n2.1 Import Libraries # Import all the relevant libraries. Please check here for all the currently supported libraries by ESP-DL.\n#pragma once #include \u0026#34;dl_layer_model.hpp\u0026#34; #include \u0026#34;dl_layer_base.hpp\u0026#34; #include \u0026#34;dl_layer_max_pool2d.hpp\u0026#34; #include \u0026#34;dl_layer_conv2d.hpp\u0026#34; #include \u0026#34;dl_layer_concat.hpp\u0026#34; #include \u0026#34;Activity_coefficient.hpp\u0026#34; #include \u0026#34;dl_layer_reshape.hpp\u0026#34; #include \u0026#34;dl_layer_softmax.hpp\u0026#34; #include \u0026lt;stdint.h\u0026gt; using namespace dl; using namespace layer; using namespace Activity_coefficient; 2.2 Declare Layers # The next step is to declare each layer.\nInput is not considered a layer so it is not defined here. Except for the output layer, all the layers are declared as private layers. class ACTIVITY : public Model\u0026lt;int16_t\u0026gt; { private: Conv2D\u0026lt;int16_t\u0026gt; l1; Conv2D\u0026lt;int16_t\u0026gt; l2; Reshape\u0026lt;int16_t\u0026gt; l3; Conv2D\u0026lt;int16_t\u0026gt; l4; Conv2D\u0026lt;int16_t\u0026gt; l5; public: Softmax\u0026lt;int16_t\u0026gt; l6; 2.3 Initialize Layers # After declaring the layers, Initialize each layer with its weight, biases, activation functions and shape.\nACTIVITY () : l1(Conv2D\u0026lt;int16_t\u0026gt;(-13, get_statefulpartitionedcall_sequential_1_conv2d_2_biasadd_filter(), get_statefulpartitionedcall_sequential_1_conv2d_2_biasadd_bias(), get_statefulpartitionedcall_sequential_1_conv2d_2_biasadd_activation(), PADDING_VALID, {}, 1,1, \u0026#34;l1\u0026#34;)), l2(Conv2D\u0026lt;int16_t\u0026gt;(-13, get_statefulpartitionedcall_sequential_1_conv2d_3_biasadd_filter(), get_statefulpartitionedcall_sequential_1_conv2d_3_biasadd_bias(), get_statefulpartitionedcall_sequential_1_conv2d_3_biasadd_activation(), PADDING_VALID, {}, 1,1, \u0026#34;l2\u0026#34;)), l3(Reshape\u0026lt;int16_t\u0026gt;({1,1,2496},\u0026#34;l2_reshape\u0026#34;)), l4(Conv2D\u0026lt;int16_t\u0026gt;(-11, get_fused_gemm_0_filter(), get_fused_gemm_0_bias(), get_fused_gemm_0_activation(), PADDING_VALID, {}, 1, 1, \u0026#34;l3\u0026#34;)), l5(Conv2D\u0026lt;int16_t\u0026gt;(-9, get_fused_gemm_1_filter(), get_fused_gemm_1_bias(), NULL, PADDING_VALID,{}, 1,1, \u0026#34;l4\u0026#34;)), l6(Softmax\u0026lt;int16_t\u0026gt;(-14,\u0026#34;l5\u0026#34;)){} 2.4 Building Layers # The next step is to build each layer. For more information about building layers please check the build function of each layer.\nvoid build(Tensor\u0026lt;int16_t\u0026gt; \u0026amp;input) { this-\u0026gt;l1.build(input); this-\u0026gt;l2.build(this-\u0026gt;l1.get_output()); this-\u0026gt;l3.build(this-\u0026gt;l2.get_output()); this-\u0026gt;l4.build(this-\u0026gt;l3.get_output()); this-\u0026gt;l5.build(this-\u0026gt;l4.get_output()); this-\u0026gt;l6.build(this-\u0026gt;l5.get_output()); } 2.5 Call Layers # In the end, connect these layers and call them one by one by using a call function. For more information about calling layers please check the call function of each layer.\nvoid call(Tensor\u0026lt;int16_t\u0026gt; \u0026amp;input) { this-\u0026gt;l1.call(input); input.free_element(); this-\u0026gt;l2.call(this-\u0026gt;l1.get_output()); this-\u0026gt;l1.get_output().free_element(); this-\u0026gt;l3.call(this-\u0026gt;l2.get_output()); this-\u0026gt;l2.get_output().free_element(); this-\u0026gt;l4.call(this-\u0026gt;l3.get_output()); this-\u0026gt;l3.get_output().free_element(); this-\u0026gt;l5.call(this-\u0026gt;l4.get_output()); this-\u0026gt;l4.get_output().free_element(); this-\u0026gt;l6.call(this-\u0026gt;l5.get_output()); this-\u0026gt;l5.get_output().free_element(); } }; 3. Model Run # Once our model is built, declare the input to our model and run the model on ESP32-S3 in ‘app_main.cpp’.\n3.1 Import libraries # #include \u0026lt;stdio.h\u0026gt; #include \u0026lt;stdlib.h\u0026gt; #include \u0026#34;esp_system.h\u0026#34; #include \u0026#34;freertos/FreeRTOS.h\u0026#34; #include \u0026#34;freertos/task.h\u0026#34; #include \u0026#34;dl_tool.hpp\u0026#34; #include \u0026#34;model_define.hpp\u0026#34; #include \u0026#34;i2c_bus.h\u0026#34; #include \u0026#34;mpu6050.h\u0026#34; #include \u0026#34;driver/i2c.h\u0026#34; #include \u0026#34;esp_log.h\u0026#34; 3.2 Declare Input # The input to our neural network is taken from the MPU6050 accelerometer sensor. To read sensor data in real time, we use the mpu6050 driver from espressif. Every 4 seconds, the data will be stored in an array and fed to the network for predictions.\nint input_height = 80; int input_width = 3; int input_channel = 1; int input_exponent = -13; float acc_xyz[240] = {0}; int index_acc=0; #define I2C_MASTER_SCL_IO 16 /*!\u0026lt; gpio number for I2C master clock */ #define I2C_MASTER_SDA_IO 17 /*!\u0026lt; gpio number for I2C master data */ #define I2C_MASTER_NUM I2C_NUM_0 /*!\u0026lt; I2C port number for master dev */ #define I2C_MASTER_FREQ_HZ 400000 /*!\u0026lt; I2C master clock frequency */ static i2c_bus_handle_t i2c_bus = NULL; static mpu6050_handle_t mpu6050 = NULL; extern \u0026#34;C\u0026#34; void app_main(void) { i2c_config_t conf = { .mode = I2C_MODE_MASTER, .sda_io_num = I2C_MASTER_SDA_IO, .scl_io_num = I2C_MASTER_SCL_IO, .sda_pullup_en = GPIO_PULLUP_ENABLE, .scl_pullup_en = GPIO_PULLUP_ENABLE, .clk_flags = 0, }; conf.master.clk_speed = I2C_MASTER_FREQ_HZ; i2c_bus = i2c_bus_create(I2C_MASTER_NUM, \u0026amp;conf); mpu6050 = mpu6050_create(i2c_bus, MPU6050_I2C_ADDRESS); uint8_t mpu6050_deviceid; mpu6050_acce_value_t acce; mpu6050_get_deviceid(mpu6050, \u0026amp;mpu6050_deviceid); printf(\u0026#34;mpu6050 device ID is: 0x%02x\\n\u0026#34;, mpu6050_deviceid); mpu6050_set_acce_fs(mpu6050, ACCE_FS_4G); while(1){ for (int i=0 ;i\u0026lt;80; i++) { mpu6050_get_acce(mpu6050, \u0026amp;acce); acc_xyz[index_acc]=acce.acce_x; index_acc=index_acc+1; acc_xyz[index_acc]=acce.acce_y; index_acc=index_acc+1; acc_xyz[index_acc]=acce.acce_z; index_acc=index_acc+1; vTaskDelay(50 / portTICK_RATE_MS); } index_acc=0; int16_t *model_input = (int16_t *)dl::tool::malloc_aligned_prefer(input_height*input_width*input_channel, sizeof(int16_t *)); for(int i=0 ;i\u0026lt;input_height*input_width*input_channel; i++){ float normalized_input = acc_xyz[i] / 1.0; //normalization model_input[i] = (int16_t)DL_CLIP(normalized_input * (1 \u0026lt;\u0026lt; -input_exponent), -32768, 32767); } 3.3 Set Input shape # Set the data in a tensor to feed the neural network.\nTensor\u0026lt;int16_t\u0026gt; input; input.set_element((int16_t *) model_input).set_exponent(input_exponent).set_shape({input_height,input_width,input_channel}).set_auto_free(false); 3.4 Call model # Call the model by calling the method forward and passing input to it. Use latency to calculate the time taken by ESP32-S3 to run the neural network.\nACTIVITY model; dl::tool::Latency latency; latency.start(); model.forward(input); latency.end(); latency.print(\u0026#34;\\nActivity model\u0026#34;, \u0026#34;forward\u0026#34;);3. Future Directions 3.5 Monitor output # The output is taken out from the public layer i.e l6. The result can be printed in the terminal.\nfloat *score = model.l6.get_output().get_element_ptr(); float max_score = score[0]; int max_index = 0; for (size_t i = 0; i \u0026lt; 6; i++) { printf(\u0026#34;%f, \u0026#34;, score[i]*100); if (score[i] \u0026gt; max_score) { max_score = score[i]; max_index = i; } } printf(\u0026#34;\\n\u0026#34;); switch (max_index) { case 0: printf(\u0026#34;0: Downstairs\u0026#34;); break; case 1: printf(\u0026#34;1: Jogging\u0026#34;); break; case 2: printf(\u0026#34;2: Sitting\u0026#34;); break; case 3: printf(\u0026#34;3: Standing\u0026#34;); break; case 4: printf(\u0026#34;4: Upstairs\u0026#34;); break; case 5: printf(\u0026#34;5: Walking\u0026#34;); break; default: printf(\u0026#34;No result\u0026#34;); } printf(\u0026#34;\\n\u0026#34;); } } 4. Conclusion # In conclusion, the current project offers exciting possibilities for various applications, including predictive maintenance in industrial settings, boxing punch recognition in sports using an accelerometer, and fall detection in healthcare. These are just a few examples that can be explored further. For those interested in accessing the source code, it is available on the GitHub repository.\n","date":"6 June 2023","externalUrl":null,"permalink":"/blog/esp32-s3-edge-ai-human-activity-recognition-using-accelerometer-data-and-esp-dl/","section":"Blog","summary":"","title":"ESP32-S3 Edge-AI｜Human Activity Recognition Using Accelerometer Data and ESP-DL","type":"blog"},{"content":"The awareness, as well as the associated concerns, about connected device security, is ever-increasing. With the European Union’s Cyber Resilience Act also coming into effect soon, it has become ever so important to have security features built-in to the devices in hardware.\nThe Espressif ESP32-H2 has been built to provide an affordable security solution to all and thus integrates a variety of security features. The ESP32-H2 Platform security considerations can be broadly classified into the following categories.\nSecure Boot Flash Encryption Protecting Debug Interfaces Secure Storage Memory Protection Device Identity protection These security features are implemented using a variety of different HW accelerators as well as SW flows to go along with them. Let’s go over each of the security features in a little bit more details.\nSecure Boot # Secure Boot protects a device from running any unauthorized (i.e., unsigned) code by checking that each piece of software being booted is signed. On an ESP32-H2, these pieces of software include the second stage bootloader and each application binary. Note that the first stage bootloader does not require signing as it is ROM code and thus cannot be changed.\nThe Secure Boot process on the ESP32-H2 involves the following steps:\nThe ESP32-H2 has provisions to choose between an RSA-PSS or ECDSA-based secure boot verification scheme. ECDSA provides similar security strength compared to RSA with shorter key lengths. Current estimates suggest that ECDSA with curve P-256 has an approximate equivalent strength to RSA with 3072-bit keys. However, ECDSA signature verification takes considerably more time compared to RSA signature verification.\nThe RSA-PSS or ECDSA public key is stored in the eFuse on the device. The corresponding RSA-PSS or ECDSA private key is kept at a secret place and is never accessed by the device. Up to three public keys can be generated and stored in the chip during manufacturing. ESP32-H2 provides the facility to permanently revoke individual public keys.\nFlash Encryption # Flash encryption is intended to encrypt the contents of the ESP32-H2’s off-chip flash memory. Once this feature is enabled, firmware is flashed as plaintext, and then the data is encrypted in place on the first boot. As a result, physical readout of flash will not be sufficient to recover most flash contents.\nWhen flash encryption is enabled, all memory-mapped read accesses to flash are transparently, and at runtime, decrypted. The ESP32-H2 uses the XTS-AES block cipher mode with a 256-bit key size for flash encryption. The flash controller uses the key stored in the eFUSE to perform the decryption. Similarly, any memory-mapped write operation causes the corresponding data to be transparently encrypted before being written to flash.\nDuring the development stage, there is a frequent need to program different plaintext flash images and test the flash encryption process. This requires that Firmware Download mode can load new plaintext images as many times as needed. However, during the manufacturing or production stages, Firmware Download mode should not be allowed to access flash contents for security reasons. Hence, two different flash encryption configurations were created.\nIn “Development” mode, it is still possible to flash new plaintext firmware to the device, and the stub code downloaded via UART DL mode will transparently encrypt this firmware using the key stored in hardware. This allows, indirectly, to read out the plaintext of the firmware in flash. In “Release” mode, flashing plaintext firmware to the device without knowing the encryption key is no longer possible. For production use, flash encryption should be enabled in the “Release” mode only.\neFuse based OTP memory # eFuse plays a very important role in the overall security aspects. It provides a secure storage space on the device itself as well as also a mechanism to disable potential back-doors for on-field deployed devices.\nThe eFuse is a type of one-time programmable (OTP) memory region which, once programmed from 0 to 1, can never be changed back to 0. The eFuse plays an important role in the functioning of the security features of the SoC as it is used to store user data and hardware parameters, including control parameters for hardware modules, calibration parameters, the MAC address, and keys used for the encryption and decryption module.\nThe ESP32-H2 contains a 4096-bit eFuse memory, out of which 1792 bits are reserved for custom use and can be utilized by the application. Once the keys are stored in the eFuse, it can be configured such that any software running cannot read these keys, and only the various permitted hardware peripherals can read and use these keys. The eFuse can also be used to control the disabling of USB debug as well as JTAG debug.\nMemory Protection # The permission management of ESP32-H2 can be divided into two parts: PMP (Physical Memory Protection) and APM (Access Permission Management) .\nPMP manages the CPU’s access to all address spaces. APM does not manage the CPU’s access to ROM and SRAM. If the CPU needs to access ROM and HP SRAM, it needs permission only from PMP; if it needs to access to other address spaces, it needs to pass PMP’s permission management first and then the APM’s. If the PMP check fails, APM check will not be triggered.\nThe APM module contains two parts: the TEE (Trusted Execution Environment) controller and the APM controller.\nThe TEE controller is responsible for configuring the security mode of a particular master in ESP32-H2 to access memory or peripheral registers. There are four security modes supported. When the RISC-V core is in Machine mode, the security mode is set to Trusted(TEE). When the core is in User mode, the security mode can se set to any of the 3 REE based on the register configurations. The APM controller is responsible for managing a master’s permission (read/write/execute) when accessing memory and peripheral registers. By comparing the pre-configured address ranges and corresponding access permissions with the information carried on the bus, such as Master ID, security mode, access address, access permissions, etc, the APM controller determines whether access should be allowed or blocked. The total memory space including internal memory, external memory and peripheral space can be configured into 16 address regions to define the different access permissions to each of these regions. When ever there is an illegal access, if enabled, an interrupt is be generated and the details of the illegal access are recorded. The APM controller will record relevant information including the master ID, security mode, access address, reasons for illegal access (address out of bounds or permission restrictions), and permission management result of each access path.\nDevice Identity protection # The Digital Signature (DS) peripheral is a security feature included in the ESP32-H2 and enhanced from the previous version in the Espressif’s SoC. It produces hardware accelerated digital signatures, without the private key being accessible by software. This allows the private key to be kept secured on the device without anyone other than the device hardware being able to access it. You can read more in details about in a previous blog post.\nDigital Signature Peripheral allows the manufacturer to generate the symmetric encryption key that can be unique to each device and then encrypt the device private key with the same encryption key. At runtime, the Digital Signature Peripheral allows application to perform signing operation with this encrypted device private key without software being able to access the plaintext private key.\nIt uses pre-encrypted parameters to calculate a signature. The parameters are encrypted using HMAC as a key-derivation function. In turn, the HMAC uses eFuses as input key. The whole process happens in hardware so that neither the decryption key nor the input key for the HMAC key derivation function can be seen by the software while calculating the signature.\nECDSA Accelerator With ESP32-H2, supports ECDSA based private keys as well on top of the RSA based keys. This is particularly important with regards to Matter. The Matter security model is based on Public Key Infrastructure(PKI), a cryptographic mechanism widely adopted in the Internet and uses the ECC with the “P-256” curve for digital signatures and key exchanges. This makes ECDSA based signatures mandatory for certificate exchanges.\nElliptic Curve Digital Signature Algorithm, or ECDSA, is one of the more complex public key cryptography encryption algorithms. Keys are generated via elliptic curve cryptography, which are smaller than the average keys generated by digital signing algorithms. ECDSA’s use of smaller keys to achieve the same level of security as other digital signature algorithms is a major advantage, reducing implementation overheads such as key storage and exchange.\nCryptographic Accelerators # The ESP32-H2 includes a wide range of cryptographic accelerators to offload the CPU for all commonly required cryptographic functions for the above features as well as other common application scenarios. The ESP32-H2 continues to have the common accelerators found in the ESP32 series, including:\nAES-128/256 : ESP32-H2 integrates an Advanced Encryption Standard (AES) accelerator supporting AES-128/AES-256 encryption and decryption specified in FIPS PUB 197 for protection against DPA attack. The peripheral also supports block cipher modes ECB, CBC, OFB, CTR, CFB8, and CFB128 under NIST SP 800–38A.\nSHA Accelerator: The ESP32-H2 integrates a HW to accelerate the Secure Hashing Algorithm (SHA) hash algorithms SHA-1, SHA-224 and SHA-256 introduced in FIPS PUB 180–4 Spec. Secure Hashing Algorithms are required in all digital signatures and certificates relating to SSL/TLS connection nd is also used by the Digital Signature Peripheral internally.\nRSA Accelerator: The RSA algorithm is a public-key signature algorithm based on the Public Key cryptography. The RSA accelerator provides hardware support for high-precision computation used in various RSA asymmetric cipher algorithms, significantly improving their run time and reducing their software complexity. The RSA accelerator also supports operands of different lengths, which provides more flexibility during the computation.\nHMAC: The HMAC (Hash-based Message Authentication Code) module provides hardware acceleration for SHA256-HMAC, as described in RFC 2104,* *generation. The 256-bit HMAC key is stored in an eFuse key block and can be set as read-protected. HMACs work with pre-shared secret keys and provide authenticity and integrity to a message.\n*ECC Accelerator : * Elliptic Curve Cryptography (ECC) is an approach to public-key cryptography based on the algebraic structure of elliptic curves. ECC uses smaller keys compared to RSA cryptography while providing equivalent security. ESP32-H2’s ECC Accelerator can complete various calculations based on 2 different elliptic curves, namely P-192 and P-256 defined in FIPS 186–3, thus accelerating the ECC algorithm and ECC-derived algorithms. The HW supports up to 11 working modes.\nThis summarises the various security features present in the ESP32-H2 which can enable the development of affordable secure connected devices for varied applications.\nFurther Readings:\n*IDF security guide: *https://docs.espressif.com/projects/esp-idf/en/latest/esp32h2/security/security.html *Secure Boot v2 guide : *https://docs.espressif.com/projects/esp-idf/en/latest/esp32h2/security/secure-boot-v2.html *Flash Encryption guide : *https://docs.espressif.com/projects/esp-idf/en/latest/esp32h2/security/flash-encryption.html *Digital Signature guide : *https://docs.espressif.com/projects/esp-idf/en/latest/esp32h2/api-reference/peripherals/ds.html *eFuse Manager guide : *https://docs.espressif.com/projects/esp-idf/en/latest/esp32h2/api-reference/system/efuse.html ","date":"11 May 2023","externalUrl":null,"permalink":"/blog/build-affordable-secure-connected-devices-with-esp32-h2/","section":"Blog","summary":"","title":"Build affordable Secure connected devices with ESP32-H2","type":"blog"},{"content":"","date":"11 May 2023","externalUrl":null,"permalink":"/tags/mcu/","section":"Tags","summary":"","title":"Mcu","type":"tags"},{"content":"","date":"19 April 2023","externalUrl":null,"permalink":"/authors/juraj-sadel/","section":"Developer Portal Authors","summary":"","title":"Juraj Sadel","type":"authors"},{"content":" Beginning of Rust\nThe initial idea of a Rust programming language was born because of an accident. In 2006, in Vancouver, Mr. Graydon Hoare was returning to his apartment but the elevator was again out of order, because of a software bug. Mr. Hoare lived on the 21st floor and as he climbed the stairs, he started thinking “We computer people couldn’t even make an elevator that works without crashing!”. This accident led Mr. Hoare to work on the design of a new programming language he hoped, would be possible to write small, fast code without memory bugs [1].If you are interested in the more detailed and technical history of Rust, please visit [2] and [3].\nAlmost eighteen years later, Rust has become the hottest new language in the world with more and more people interested every year. In Q1 2020 there were around 600,000 Rust developers and in Q1 2022 the number increased to 2.2 million [4]. Huge tech companies like Mozilla, Dropbox, Cloudflare, Discord, Facebook(Meta), Microsoft, and others are using Rust in their codebase.\nIn the past six years, the Rust language remained the most “loved” programming language based on [5].\nProgramming languages in Embedded development\nEmbedded development is not as popular as web development or desktop development and these are a few examples of why this might be the case:\nHardware constraints : The embedded systems will most likely have limited hardware resources, such as performance and memory. This can make it more challenging to develop software for these systems. Limited and niche market : The embedded market is more limited than web and desktop applications and it can make it less financially rewarding for developers specializing in embedded programming. Specialized low-level knowledge : Specialized knowledge of concrete hardware and low-level programming languages is a must-to-have in embedded development Longer development cycles : Developing software for embedded systems can take longer than developing software for web or desktop applications, due to the need for testing and optimization of the code for the specific hardware requirements. Low-level programming languages : These languages, such as assembly or C do not provide much of an abstraction to the developer and provide direct access to hardware resources and memory which will lead to memory bugs. These are only a few examples of why and how is embedded development unique and is not as famous and lucrative for young programmers as web development. If you are used to the most common and modern programming languages like Python, JavaScript, or C# where you do not have to count every processor cycle and every kilobyte used in memory, it is a very brutal change to start with embedded, that can be very discouraging for coming into the embedded world not even for beginners but also experienced web/desktop/mobile developers. That is why it would be very interesting and needed to have a modern programming language in embedded development.\nWhy Rust?\nRust is a modern and relatively young language with a focus on memory and thread safety that with an intention to produce reliable and secure software. Also, Rust\u0026rsquo;s support for concurrency and parallelism is particularly relevant for embedded development, where efficient use of resources is critical. Rust\u0026rsquo;s growing popularity and ecosystem make it an attractive option for developers, especially those who are looking for a modern language that is both efficient and safe. These are the main reasons why Rust is becoming an increasingly popular choice not only in embedded development but especially for projects that prioritize safety , security , and reliability .\nAdvantages of Rust (compared with C and C++)\nMemory safety : Rust offers strong memory safety guarantees through its ownership and borrowing system which is very helpful in preventing common memory-related bugs like null pointer dereferences or buffer overflow , for example. In other words, Rust guarantees memory safety at compile time through ownership and borrowing system. This is especially important in embedded development where memory/resource limitations can make such bugs more challenging to detect and resolve. Concurrency : Rust provides excellent support for zero-cost abstractions and safe concurrency and multi-threading, with a built-in async/await syntax and a powerful types system that prevents common concurrency bugs like data races. This can make it easier to write safe and efficient concurrent code not only in embedded systems. Performance : Rust is designed for high performance and can go toe-to-toe with C and C++ in performance measures while still providing strong memory safety guarantees and concurrency support. Readability : Rust’s syntax is designed to be more readable and less error-prone than C and C++, with features like pattern matching, type inference, and functional programming constructs. This can make it easier to write and maintain code, especially for larger and more complex projects. Growing ecosystem : Rust has a growing ecosystem of libraries (crates), tools, and resources for (not only) embedded development, which can make it easier to get started with Rust and find necessary support and resources for a particular project. Package manager and build system : Rust distribution includes an official tool called Cargo, which is used____ to automate the build, test, and publish process together with creating a new project and managing its dependencies. Disadvantages of Rust (compared with C and C++)\nOn the other hand, Rust is not a perfect language and has also some disadvantages over other programming languages (not only C and C++).\nLearning curve : Rust has a steeper learning curve than many programming languages, including C. Its unique features, such as already mentioned ownership and borrowing, may take some time to understand and get used to and therefore are more challenging to get started with Rust. Compilation time : Rust’s advanced type system and borrow checker can result in longer compilation times compared to other languages, especially for large projects. Tooling : While Rust’s ecosystem is growing rapidly, it may not yet have the same level of tooling support as more established programming languages. For example, C and C++ have been around for decades and have a vast codebase. This can make it more challenging to find and use the right tools for a particular project. Lack of low-level control : Rust’s safety features can sometimes limit low-level control to C and C++. This can make it more challenging to perform certain low-level optimizations or interact with hardware directly, but it is possible. Community size : Rust is still a relatively new programming language compared to more established languages like C and C++, which means that it may have a smaller community of developers and contributors, and fewer resources, libraries, and tools. Overall, Rust offers many advantages over traditional embedded development languages like C and C++, including memory safety, concurrency support, performance, code readability, and a growing ecosystem. As a result, Rust is becoming an increasingly popular choice for embedded development, especially for projects that prioritize safety, security, and reliability. The disadvantages of Rust compared to C and C++ tend to be related to Rust’s relative newness as a language and its unique features. However, many developers find that Rust’s advantages make it a compelling choice for certain projects.\nHow can Rust run?\nThere are several ways to run the Rust based firmware, depending on the environment and requirements of the application. The Rust based firmware can typically be used in one of two modes: hosted-environment or bare-metal, let’s look at what these are.\nWhat is hosted-environment?\nIn Rust, the hosted-environment is close to a normal PC environment [6] which means, you are provided with an Operating System. With the operating system, it is possible to build the Rust standard library (std). The std refers to the standard library, which can be seen as a collection of modules and types that are included with every Rust installation. The std provides a set of multiple functionalities for building Rust programs, including data structures , networking , mutexes and other synchronization primitives , input/output , and more.\nWith the hosted-environmentapproach you can use the functionality from the C-based development framework called the ESP-IDF because it provides a newlib* *environment that is “powerful” enough to build the Rust standard library on top of it. In other words, with the hosted-environment (sometimes called just std) approach, we use the ESP-IDF as an operating system and build the Rust application on top of it. In this way, we can use all the standard library features listed above and also already implement C functionality from the ESP-IDF API.\nAn example, how a blinky example running on top of ESP-IDF (FreeRTOS) may look like (more examples can be found in esp-idf-hal):\n// Import peripherals we will use in the example use esp_idf_hal::delay::FreeRtos; use esp_idf_hal::gpio::*; use esp_idf_hal::peripherals::Peripherals; // Start of our main function i.e entry point of our example fn main() -\u0026gt; anyhow::Result\u0026lt;()\u0026gt; { // Apply some required ESP-IDF patches esp_idf_sys::link_patches(); // Initialize all required peripherals let peripherals = Peripherals::take().unwrap(); // Create led object as GPIO4 output pin let mut led = PinDriver::output(peripherals.pins.gpio4)?; // Infinite loop where we are constantly turning ON and OFF the LED every 500ms loop { led.set_high()?; // we are sleeping here to make sure the watchdog isn\u0026#39;t triggered FreeRtos::delay_ms(1000); led.set_low()?; FreeRtos::delay_ms(1000); } } When you might want to use hosted-environment\nRich functionality : If your embedded system requires lots of functionality like support for networking protocols, file I/O, or complex data structures, you will likely want to use hosted-environment approach because std libraries provide a wide range of functionality that can be used to build complex applications relatively quickly and efficiently Portability : The std crate provides a standardized set of APIs that can be used across different platforms and architectures, making it easier to write code that is portable and reusable. Rapid development : The std crate provides a rich set of functionality that can be used to build applications quickly and efficiently, without worrying about low-level details. What is bare-metal?\nBare-metal means we do not have any operating system to work with. When a Rust program is compiled with the no_std attribute, it means that the program will not have access to certain features (some are listed in the std chapter). This does not necessarily mean that you cannot use networking or complex data structures with no_std, you can do anything without std that you can do with std but it is more complex and challenging. no_std programs rely on a set of core language features that are available in all Rust environments, for example, data types, control structures or low-level memory management. This approach is useful for embedded programming where memory usage is often constrained and low-level control over hardware is required.\nAn example, how a blinky example running on bare-metal (no operating system) may look like (more examples can be found in esp-hal):\n#![no_std] #![no_main] // Import peripherals we will use in the example use esp32c3_hal::{ clock::ClockControl, gpio::IO, peripherals::Peripherals, prelude::*, timer::TimerGroup, Delay, Rtc, }; use esp_backtrace as _; // Set a starting point for program execution // Because this is `no_std` program, we do not have a main function #[entry] fn main() -\u0026gt; ! { // Initialize all required peripherals let peripherals = Peripherals::take(); let mut system = peripherals.SYSTEM.split(); let clocks = ClockControl::boot_defaults(system.clock_control).freeze(); // Disable the watchdog timers. For the ESP32-C3, this includes the Super WDT, // the RTC WDT, and the TIMG WDTs. let mut rtc = Rtc::new(peripherals.RTC_CNTL); let timer_group0 = TimerGroup::new( peripherals.TIMG0, \u0026amp;clocks, \u0026amp;mut system.peripheral_clock_control, ); let mut wdt0 = timer_group0.wdt; let timer_group1 = TimerGroup::new( peripherals.TIMG1, \u0026amp;clocks, \u0026amp;mut system.peripheral_clock_control, ); let mut wdt1 = timer_group1.wdt; rtc.swd.disable(); rtc.rwdt.disable(); wdt0.disable(); wdt1.disable(); // Set GPIO4 as an output, and set its state high initially. let io = IO::new(peripherals.GPIO, peripherals.IO_MUX); // Create led object as GPIO4 output pin let mut led = io.pins.gpio5.into_push_pull_output(); // Turn on LED led.set_high().unwrap(); // Initialize the Delay peripheral, and use it to toggle the LED state in a // loop. let mut delay = Delay::new(\u0026amp;clocks); // Infinite loop where we are constantly turning ON and OFF the LED every 500ms loop { led.toggle().unwrap(); delay.delay_ms(500u32); } } When you might want to use bare-metal\nSmall memory footprint : If your embedded system has limited resources and needs to have a small memory footprint, you will likely want to use bare-metal because std features add a significant amount of final binary size and compilation time. Direct hardware control : If your embedded system requires more direct control over the hardware, such as low-level device drivers or access to specialized hardware features you will likely want to use bare-metal because std adds abstractions that can make it harder to interact directly with the hardware. Real-time constraints or time-critical applications : If your embedded system requires real-time performance or low-latency response times because std can introduce unpredictable delays and overhead that can affect real-time performance. Custom requirements : bare-metal allows more customization and fine-grained control over the behavior of an application, which can be useful in specialized or non-standard environments. TL;DR Should I switch from C to Rust?\nIf you are starting a new project or a task where memory safety or concurrency is required, it may be worth considering moving from C to Rust. However, if your project is already well-established and functional in C, the benefits of switching to Rust may not outweigh the costs of rewriting and retesting your whole codebase. In this case, you can consider keeping the current C codebase and start writing and adding new features, modules, and functionality in Rust — it is relatively simple to call C functions from Rust code. It is also possible to write ESP-IDF components in Rust. In the end, the final decision to move from C to Rust should be based on a careful evaluation of your specific needs and the trade-offs involved.\nReferences1. How Rust went from a side project to the world’s most-loved programming language | MIT Technology Review2. Announcing Rust 1.0 | Rust Blog (rust-lang.org)3. 4 years of Rust | Rust Blog (rust-lang.org)\nThe state of the Rust market in 2023 (yalantis.com)\nStack Overflow Developer Survey 2021\nhttps://docs.rust-embedded.org/book/intro/no-std.html#hosted-environments\n","date":"19 April 2023","externalUrl":null,"permalink":"/blog/rust-embedded-a-development-power-duo/","section":"Blog","summary":"","title":"Rust + Embedded: A Development Power Duo","type":"blog"},{"content":"","date":"19 April 2023","externalUrl":null,"permalink":"/tags/rust-programming-language/","section":"Tags","summary":"","title":"Rust Programming Language","type":"tags"},{"content":" The Espressif Web IDE is an implementation of the Eclipse Theia framework with the ESP-IDF extension for Visual Studio Code and few additional tools. You can see it in action in the Espressif DevCon22 presentation below.\nIf you haven’t used Eclipse Theia before, it is an open-source framework to develop Cloud \u0026amp; Desktop IDEs and tools in TypeScript with a Visual Studio Code UI and Visual Studio Code extensions support or extensions implemented in the OpenVSX registry.\nMost of the features of ESP-IDF extension for Visual Studio Code are also available for the Espressif Web IDE. Specific commands are the chip serial port connection. For that we have implemented two additional tools:\nOn the Web IDE side, there a couple commands implemented for each tool:\nFor ESP-IWIDC , click the menu Remote and then Remote Flash or Remote Monitor. For esptool-js, click the the menu Remote and then Flash with Webserial or Monitor with Webserial. You will need to select the serial device before the flashing or monitor starts.\nYou can use the Espressif Web IDE in 2 ways, running directly from source code compilation or using the attached Dockerfile to build a docker container.\ngit clone https://github.com/espressif/idf-web-ide.git cd idf-web-ide yarn cd browser-app yarn run start — port=8080 Open 127.0.0.1:8080 in your browser (Use Chrome for best experience).\nTo run using Docker do: Pull the latest docker image using\ndocker pull espbignacio/idf-web-ide or build the docker image from the IDF-Web-IDE repository with:\ndocker build . — tag espressif/idf-web-ide — platform linux/amd64 Run the container with:\ndocker run -d -e IWI_PORT=8080 -p 8080:8080 --platform linux/amd64 -v ${PWD}:/home/projects espressif/idf-web-ide Open 127.0.0.1:8080 in your browser (Use Chrome for best experience).\nIf you want to use the ESP-IWIDC you can get a built executable from Windows here or use the Python script from the repository.\nRun the executable to start the ESP-IWIDC:\n.\\dist\\main.exe — port PORT and to see available ports.\n.\\dist\\main.exe If you are using the ESP-IWIDC python script directly, make sure to install required python packages with:\npip3 install -r ${ESP-IWIDC}/requirements.txt python3 main.py python3 main.py - port [SERIAL_PORT_OF_ESP_32] For the esptool-js commands you don’t need to install anything.\nThe advantage of using the docker container is that you have a ESP-IDF ready docker container, the ESP32 QEMU fork and you don’t need to configure ESP-IDF for the IDE. Just open any ESP-IDF project and start coding!\nThe Espressif Web IDE uses the Clang OpenVSX plugin to provide C/C++ language support. This plugin uses the build/compile_commands.json file to provide Go to declaration and other language features.\nConclusion # Give the Espressif Web IDE a try and let us know what can we add or improve here! You can also look at our previous post about the ESP-IDF extension for Visual Studio Code.\nRelated links: # ESP-IDF Web IDE Eclipse Theia ESP-IDF extension for Visual Studio Code Espressif IDF Web Desktop Companion (ESP-IWIDC) esptool-js OpenVSX registry Clang OpenVSX plugin ","date":"17 April 2023","externalUrl":null,"permalink":"/blog/accelerate-your-iot-development-with-the-espressif-webide/","section":"Blog","summary":"","title":"Accelerate Your IoT Development with the Espressif WebIDE","type":"blog"},{"content":"","date":"17 April 2023","externalUrl":null,"permalink":"/tags/docker/","section":"Tags","summary":"","title":"Docker","type":"tags"},{"content":"","date":"17 April 2023","externalUrl":null,"permalink":"/tags/eclipse-theia/","section":"Tags","summary":"","title":"Eclipse Theia","type":"tags"},{"content":"","date":"16 April 2023","externalUrl":null,"permalink":"/tags/2.9.0/","section":"Tags","summary":"","title":"2.9.0","type":"tags"},{"content":"The Espressif IDE version 2.9.0 has recently been released, introducing a new feature for the Espressif community who want to use the Wokwi simulator directly from within the IDE.\nWhat is Wokwi?\nWokwi is an online electronics simulator that allows users to simulate various boards, parts, and sensors, including the ESP32. With a browser-based interface, Wokwi offers a simple and intuitive way to start coding your next IoT project within seconds.\nHow does the integration work between Wokwi and Espressif-IDE?\nEspressif-IDE provides a development environment for building IoT applications using ESP-IDF with various Espressif boards. While you can build, flash, monitor, and debug your applications within the IDE, visualizing the serial output requires an esp32-based development board. This is where the Wokwi simulator comes in.\nEspressif-IDE provides a Wokwi integration plugin that allows the IDE to communicate with the Wokwi Server over a websocket, enabling the flashing of the .bin file of the project built in the IDE. Based on the chip target and project ID provided by the IDE, the Wokwi server launches the simulator in the system browser for the specified target. As a result, users can view the serial monitor output in the IDE console while communicating with the simulator.\nTo use the Wokwi simulator from the Espressif-IDE, you need to follow these simple steps:\nConclusion\nIn summary, the integration of the Wokwi simulator into Espressif-IDE provides a seamless experience for users to build and test their IoT projects without the need for a physical development board. This integration opens up new possibilities for developers looking to streamline their workflow and experiment with new ideas in a cost-effective manner.\n","date":"16 April 2023","externalUrl":null,"permalink":"/blog/how-to-use-wokwi-simulator-with-espressif-ide/","section":"Blog","summary":"","title":"How to use Wokwi Simulator with Espressif-IDE","type":"blog"},{"content":"Espressif Matter Series #9\nGiven the latest developments in the IoT industry, there is a strong rush towards building Matter enabled smart devices. (If you are new to Matter, please read up about Matter in our series of blog posts here).\nWe have been actively working on creating solutions that help accelerate our customers to build and launch Matter-enabled devices faster and that too in a cost-effective way. An often overlooked, but important, part of the device production process is how fast can you manufacture devices on the line. This becomes especially important in the case of Matter, which places some unique requirements on each device.\nThis blog post will talk about Espressif’s Matter Pre-Provisioning Service that allows you to quickly manufacture Matter-enabled devices.\nMatter Pre-Provisioning Service # Espressif’s Matter Pre-Provisioning Service allows you to order modules from Espressif that are securely pre-programmed with the unique details that every Matter device needs to have. Once you receive the modules, you can directly put them on your PCBs and you are ready to go. Everything from DAC, to secure enablement is already taken care of on the modules.\nLet’s understand why such a service is even required and what it offers.\n1. Device Attestation # When any Matter device is being commissioned, the commissioning agent (phone app) will ensure that this is a genuine Matter device. This process is called Device Attestation.\nFor Device Attestation to happen, all Matter devices must have a unique set of certificates, called Device Attestation Certificates (DAC), that are programmed in them (You may read more about DACs in the Matter Security Model post). The DACs ascertain that the product, that is being commissioned, genuinely comes from Vendor X.\nThese DACs are X.509 certificates that should chain back to a valid Product Attestation Authority (PAA) that is registered with the Connectivity Standards Alliance (CSA). This ensures that only some authority that is approved by the CSA can generate and distribute these DACs, thus ensuring authenticity of the devices.\nEspressif is an authorised PAA that can generate DACs for your devices. You can request modules that are securely pre-provisioned at Espressif’s end with the DACs created for your devices, before they are shipped out to you. Care is taken that the private key of the DACs never leaves the module, and the modules are securely locked before they are shipped out.\nFor implementing this, Espressif uses 2 components:\nThis ensures that the entire process is maintained and operated with the highest levels of security and compliance.\n2. Uniqueness # Matter manufacturing requires a few unique objects to be programmed on each device. This includes the DACs as we discussed earlier. Every Matter device also requires a unique QR Code that allows it to get commissioned. Unique secrets corresponding to this QR Code should also be programmed into each device that allow apps to securely commission the device.\nAs you may be aware, mass flashing common images on a high volume run is fairly easy. Having to program unique images per-device becomes costlier. Additionally, mapping those unique images, to the corresponding QR Code, that should be pasted on each device, is another task.\nEspressif’s Matter Pre-Provisioning Service will configure the modules with the DACs and the appropriate authentication credentials that are required for the proper operation of Matter. We will provide a manifest file that captures the details that are configured on all the modules. This typically includes information about the MAC Address of modules, serial numbers, if any, and the corresponding QR Codes that should go along with these modules.\n3. Security # Finally, the DAC Certificates and the operational secrets need to be protected on the device from unauthorized access. It must be ensured that only trusted firmware, that executes on the chipset, has access to the DAC certificate. This requires the enablement of secure boot, flash encryption and other security settings on all the chipsets. The Espressif manufacturing process is set up in such a way that these features are enabled in Espressif’s factory, but still enabling customers to program their production and test firmware on their own.\nEspressif’s Matter Pre-Provisioning Service will securely lock the modules, before being shipped out to you.\n4. Firmware Flashing # Many of our customers also prefer that their modules are pre-programmed with their bootloader and firmware images (along with the other data that is configured so far).\nIf you opt for this option, you can point us to your signed bootloader and the signed firmware that should be pre-programmed on all the modules before locking and shipping them out to you.\nWe are very glad to see that this service is proving to be a significant accelerator for customers building Matter-enabled devices. If you are interested in this service, please reach out to sales@espressif.com with your request.\nThis article is part of a series of articles Espressif Matter Series.\n","date":"19 February 2023","externalUrl":null,"permalink":"/blog/accelerating-matter-device-manufacturing/","section":"Blog","summary":"","title":"Accelerating Matter Device Manufacturing","type":"blog"},{"content":"","date":"18 February 2023","externalUrl":null,"permalink":"/tags/esp-privilege-separation/","section":"Tags","summary":"","title":"Esp Privilege Separation","type":"tags"},{"content":"","date":"18 February 2023","externalUrl":null,"permalink":"/authors/sachin-parekh/","section":"Developer Portal Authors","summary":"","title":"Sachin Parekh","type":"authors"},{"content":"In the previous post, we demonstrated the ability to independently update the user application in the ESP Privilege Separation framework. With the separation and isolation of the protected app and user app, it becomes convenient to decouple the ownership of each of these apps and their updates. This also potentially allows the possibility of having multiple user applications for a single protected application, somewhat like an “application store” for user app. As the functionality of these applications increases, the security of these apps becomes mandatory.\nIn this post, we will describe the secure boot mechanism implemented for the user application. This mechanism ensures that only the trusted and authorized user application can execute on the device.\nSecure boot # Secure boot is a process that guarantees that only authorized and trusted code executes on the device. This is ensured by building a chain of trust starting from an entity that is trusted and cannot be changed, e.g. one-time programmable memory in hardware\nA project using the ESP Privilege Separation framework has two separate application binaries — protected_app and user_app, which can have independent update cycles.\nThe framework supports secure boot for both of these apps. Protected app and user app binaries are verified by establishing a chain of trust with the root of trust.\nSecure boot for protected app # Secure boot for protected application follows the secure boot scheme of the traditional application in ESP-IDF.\nThe overview of secure boot process is as follows:\nFor more details, please refer to the Secure boot section in the ESP-IDF documentation\nSecure boot for user app # As previously mentioned, both of these apps can be developed independently so the ownership of these apps can be with different entities. This could mean that both of these apps require separate signing keys. For verifying the protected app, we burn the hash of the protected app public key in eFuse. While we can do the same for the user app public key, it is not scaleable as eFuse memory is scarce.\nWe have designed a certificate-based verification mechanism for user app secure boot.\nCertificate-based verification scheme # In this scheme, the protected application is considered trusted and thus the protected app will have some information embedded in its firmware that will be used to verify the authenticity of the user app.\nRequisites # Let’s look at the requisites for protected app and user app for this scheme\nProtected app:\nUser app:\nVerification process # The verification flow of this scheme is as follows:\nFor more details about the implementation, please refer to the Secure boot section in the ESP Privilege Separation documentation.\n","date":"18 February 2023","externalUrl":null,"permalink":"/blog/securely-booting-user-application-in-esp-privilege-separation/","section":"Blog","summary":"","title":"Securely booting user application in ESP Privilege Separation","type":"blog"},{"content":"Hi everyone,\nExciting times lie ahead, as Espressif Systems will be an official exhibitor at Embedded World 2023. So, between 14 and 16 March 2023, Espressif’s team will be in Nuremberg, Germany, among 720 exhibitors from 39 countries. The Embedded World exhibition-and-conference brings the entire embedded community together once a year, providing a unique overview of some state-of-the-art technologies in the industry.\nThis year, Espressif will focus on three areas mainly:\nEspressif’s team in Nuremberg will demonstrate our unique combination of high-performance hardware, software, and complete solutions, with which we make it easy for our customers to build Matter-enabled smart-home devices of various types. In fact, Espressif provides the most comprehensive such solutions, including support for Wi-Fi or Thread end-point devices, Thread Border Routers, and Matter gateway reference designs. Espressif’s SDK for Matter is based on the official open-source Matter SDK, and includes an easy-to-use API as well as all the required mass-production tools. Then, the ESP-ZeroCode module, based on ESP32-C3/C2/H2, provides Matter connectivity out-of-the-box.\nWe also provide certificate-generation and pre-provisioning services for Matter-compatible devices, thus reducing for our customers the complexity they would otherwise face when producing such devices from scratch. On this note, it is also worth mentioning that Espressif has already helped many customers pass the Matter 1.0 certification for their products.\nAdditionally, ESP32-C6 combines 2.4 GHz Wi-Fi 6, Bluetooth 5 (LE) and 802.15.4, thus ensuring that any ESP32-C6-powered IoT devices have a high transmission efficiency. ESP32-C6 also supports uplink, downlink OFDMA and downlink MU-MIMO mechanisms. Its TWT (Target Wake Time) function is suitable for building ultra-low power IoT devices, so that even those powered by batteries can continue their operation for longer than usual. Last, but not least, ESP32-C6 has a high standard of security with such mechanisms as secure boot, flash encryption, digital signatures, encryption accelerators, etc.\nIn general, Espressif’s SoCs enable a series of HMI functions, such as data visualization, touch or knob control, voice wake-up and recognition, and multi-mode gateway among other features. ESP32-S3, in particular, is suitable for RGB-interface displays with a maximum resolution of 800x480, while ESP32-C3 supports SPI-interface displays. Espressif’s HMI smart displays support standard GUI development frameworks including LVGL, SquareLine Studio and QT.\nIn Nuremberg, we will also demonstrate ESP RainMaker (Espressif’s one-stop private Cloud platform), along with ESP Insights (our remote monitoring platform), Espressif’s AWS IoT ExpressLink module, the ACK SDK device, and ESP-NOW (our low-power communication protocol).\nSo, if you happen to be in Nuremberg from 14 to 16 March, don’t forget to get your free tickets and visit our booth (Hall 3A, Booth 625).\nKeep reading this month’s newsletter, so you can learn more exciting news from Espressif:\nEspressif Launches HMI Smart Displays Espressif’s HMI smart displays, based on ESP32-S3and ESP32-C3, are designed to support RGB and SPI interfaces, respectively. These solutions ensure smart interaction and unlimited communication!\nEspressif Has Revealed ESP32-P4 At last month’s CES in Las Vegas, Espressif revealed ESP32-P4 and it went viral! Our new high-performance MCU is designed for IO-rich, HMI and AIoT applications. For all the details, click on the link above.\nESP32-C6 Officially Available ESP32-C6 is Espressif’s Wi-Fi 6 SoC that combines 2.4 GHz Wi-Fi 6, Bluetooth 5 (LE) and the 802.15.4 protocol. It is our first Wi-Fi 6 SoC achieving an industry-leading RF performance, with reliable security features and multiple memory resources for AIoT products.\nESP-Based Products Earn Matter 1.0 Certification Espressif Systems (SSE: 688018.SH) is pleased to announce that the company has successfully completed the Matter 1.0 certification program. Build your Matter devices with ease using Espressif SoCs (the entire ESP32 and ESP32-C series, as well as ESP32-S3).\nESP32-Based Smart Watch Independent maker Philippe Cadic has created a smart watch based on Espressif’s ESP32-PICO-D4. It can be connected to a mobile phone or other smart devices, while also producing exciting visual effects with a total of 192 LEDs.\nRead More \u0026gt;\nHope you enjoy reading this month’s newsletter. Keep sending us your messages and requests on Facebook, Twitter, GitHub, Instagram, LinkedIn, and YouTube.\nYou can also contact us through our website or you can email us. We try to respond to all of your messages as quickly as possible!\nBest wishes,John LeeSenior Customer Support Officer.\n","date":"15 February 2023","externalUrl":null,"permalink":"/blog/feb-2023/","section":"Blog","summary":"","title":"Feb 2023","type":"blog"},{"content":"","date":"15 February 2023","externalUrl":null,"permalink":"/tags/instagram/","section":"Tags","summary":"","title":"Instagram","type":"tags"},{"content":"","date":"15 February 2023","externalUrl":null,"permalink":"/tags/newsletter/","section":"Tags","summary":"","title":"Newsletter","type":"tags"},{"content":" Overview # ESP32 series of chips supports secure boot scheme to allow only trusted firmware to execute from its flash storage. However, this requires careful management of the secure signing key, it must be generated and stored in a secure manner by the signing entity.\nExternal HSM (Hardware Security Module) is specially designed cryptographic device that safeguards and manages secrets. HSM also provides specialised cryptographic services like encryption, digital signing etc. Now a days, there are cloud services being offered that provide cloud HSM based solutions.\nExternal HSM Signing # External HSM offers a standard PKCS #11 based cryptographic interface for availing various services like signing the firmware. With PKCS #11 interface, external HSM could also be a remote cloud HSM based service over the network.\nEspsecure.py script (part of Esptool project) has been integrated with standard PKCS #11 interface and thus ensures interoperability with any external HSM for getting the ESP32\u0026rsquo;s firmware signed. Please note that, as shown in the above diagram path of the vendor specific PKCS #11 library must be provided in the Espsecure.py configuration to use HSM mode. The initial support allows to generate signed application as per our Secure Boot V2 scheme with either RSA-PSS 3072 or ESDSA NISTP256 algorithm. Signing Using YubiKey # We will be using YubiKey 5 Series as an external HSM for demonstration here.\nInstallation # Please find detailed setup guide for YubiKey host tool and PKCS #11 library setup here.\nNote: Following are verified steps for Ubuntu 22.10 OS\n# Install esptool 4.5 release along with HSM dependencies pip install esptool[hsm]==4.5.dev3 # Install tools and PKCS#11 interface library sudo apt install yubico-piv-tool ykcs11 # Generate ECC P256 private key in the 9c (digital signature) slot yubico-piv-tool -a generate -s 9c -A ECCP256 HSM config file # Following is a HSM config file that we shall pass to espsecure.py\n$ cat hsm_cfg.ini # Config file for the external YubiKey based Hardware Security Module [hsm_config] # PKCS11 shared object/library pkcs11_lib = /usr/lib/x86_64-linux-gnu/libykcs11.so # HSM login credentials (default YubiKey pin) credentials = 123456 # Slot number to be used (default YubiKey slot) slot = 0 # Label of the object used to store the private key (default) label = Private key for Digital Signature # Label of the object used to store corresponding public key (default) label_pubkey = Public key for Digital Signature Please check directory where libykcs11.so is installed on your system and update the path accordingly.\nGenerate signature # Following command helps to sign the binary using configuration supplied in the hsm_cfg.ini file\n$ espsecure.py sign_data --version 2 --hsm --hsm-config hsm_cfg.ini --output signed.bin unsigned.bin espsecure.py v4.5-dev Trying to establish a session with the HSM. Session creation successful with HSM slot 0. Trying to extract public key from the HSM. Got public key with label Public key for Digital Signature. Connection closed successfully Trying to establish a session with the HSM. Session creation successful with HSM slot 0. Got private key metadata with label Private key for Digital Signature. Signing payload using the HSM. Signature generation successful. Connection closed successfully Pre-calculated signatures found 1 signing key(s) found. Signed 65536 bytes of data from unsigned.bin. Signature sector now has 1 signature blocks. Verify signature # For sanity purpose, we can verify the signature using public key from the external HSM\n$ espsecure.py verify_signature --version 2 --hsm --hsm-config hsm_cfg.ini signed.bin espsecure.py v4.5-dev Trying to establish a session with the HSM. Session creation successful with HSM slot 0. Trying to extract public key from the HSM. Got public key with label Public key for Digital Signature. Connection closed successfully Signature block 0 is valid (ECDSA). Signature block 0 verification successful using the supplied key (ECDSA). Documentation # Please refer to the Esptool documentation here for more details.\nPlease note that this feature shall be available in Esptool v4.5 release. For now, you may use Esptool dev release using pip install esptool[hsm]==4.5.dev3to try out this feature.\n","date":"9 February 2023","externalUrl":null,"permalink":"/blog/secure-signing-using-external-hsm/","section":"Blog","summary":"","title":"Secure Signing Using External HSM","type":"blog"},{"content":"","date":"1 February 2023","externalUrl":null,"permalink":"/tags/bug-fixes/","section":"Tags","summary":"","title":"Bug Fixes","type":"tags"},{"content":"","date":"1 February 2023","externalUrl":null,"permalink":"/tags/espresif-ide/","section":"Tags","summary":"","title":"Espresif-IDE","type":"tags"},{"content":"","date":"1 February 2023","externalUrl":null,"permalink":"/tags/espressif-ide-2.8.0/","section":"Tags","summary":"","title":"Espressif-IDE 2.8.0","type":"tags"},{"content":" Espressif-IDE 2.8.0 was released recently, featuring a Partition table editor NVS Partition Editor along with enhancements in the Debugger Configuration and many more bug fixes to stabilize and improve the overall quality of the plugin.\nYou can get the latest version using the update site, but if you’re starting for the first time and you’re a Windows user, I would recommend using the Espressif-IDE Windows Offline installer which does most of the work of installing all the prerequisites, esp-idf, esp-idf tools, and device drivers required to work with espressif chips. Here is the current version of Espressif-IDE 2.8.0 with ESP-IDF 5.0 Installer. If you’re a mac or Linux user, get Espresif-IDE instead of Eclipse CDT and then installing the IDF Eclipse Plugin separately.\nEspressif-IDE 2.8.0 is bundled with the Eclipse CDT 2022–09 package and it has Java 11 support. We would recommend not updating to the latest version of Eclipse CDT 2022–12 as we have not added support yet.\nHere are the new features and improvements added in the 2.8.0 release # Partition Table Editor # Eclipse Plugin offers UI for editing your partition table and flash it to your chip, instead of editing the CSV files directly. This offer editing the existing Partition table and creating a new one.\nTo launch the Partition editor\nNVS Table Editor # NVS Table Editor can help you to edit NVS Partition CSV file, and generate encrypted and non-encrypted partitions through UI without interacting directly with the CSV files.\nEclipse plugin uses the nvs_partition_gen.py utility from esp-idf for creating a binary file based on key-value pairs provided in the editor.\nTo launch the NVS Partition editor\nMultiple Build configurations # The plugin offers to configure the customized build configuration settings using the Build Settings tab in the launch configuration wizard. This would enable the user to define the multiple build configurations with different settings — for example, debug and release configurations.\nThere were issues reported earlier on this where changing additional CMake Arguments in one configuration is reflected in the other configuration so there is no way one could configure different settings and this release address this issue.\nGDB Client Remote Timeout # There were numerous reports from clients saying that GDB Client was unable to connect with the default timeout which was 2 seconds that is to wait for the remote target to respond, otherwise, it use to drop the GDB connection with an error.\nNow the default GDB Client remote timeout is set for 20 seconds! You could see this in the new OpenOCD Debugger configuration window.\nBelow are the most notable bug fixes in the new version # Please find more about other bug fixes that were part of 2.8.0.\nA way forward for IDEs and what you could expect in H1 2023 # It’s been 3 years since we started working on the plugin for Eclipse and VSCode and we have built IDEs with a great set of features to support end-to-end application building with esp-idf using espressif chips. However, we realized it’s time to go back and retrospect ourselves and make a foundation much stronger. Hence we decided to focus more on code refactoring, design changes, automation, test cases, quality, onboarding, and revamping some wizards(for example OpenOCD Debugger configuration has a lot of duplicate config parameters) before we take up any new developments.\nHowever, will work on news chips support as and when needed. For example, C6 and H2 in H1.2023 and P4 and C5 in H2.2023\nHow about Eclipse CDT 2022–12 support? # Eclipse CDT 2022–12 comes with CDT 11.0 which is a major release and has some breaking changes in our IDF Eclipse Plugin and which also comes with Java 17 dependency.\nConsidering our priority on fixing bugs, improving onboarding workflows, and UX/UI we thought of pushing this bit late. Importantly, this brings a Java 17 dependency and that’s a big thing to consider for most of us as we need to update from current Java 11 to Java 17. We started work on this, probably we could expect this by end of H1.2023 or earlier.\nIf you’ve some feedback on IDEs and would like to share it with us, please write a mail directly to ide.support@espressif.com or raise an issue on the project GitHub issues section and we will be happy to connect with you!\nThank you!\n","date":"1 February 2023","externalUrl":null,"permalink":"/blog/whats-new-in-espressif-ide-2-8-0-and-a-way-forward/","section":"Blog","summary":"","title":"What’s New in Espressif-IDE 2.8.0 and a Way Forward","type":"blog"},{"content":"Over-The-Air (OTA) firmware update is one of the most important feature of any connected device. It enables the developers to ship out new features and bug fixes by remotely updating the application. In ESP Privilege Separation, there are two applications — protected_app and user_app for which the framework provides the ability to independently update both the application binaries. In this post we will describe the independent OTA update feature under ESP Privilege Separation.\nOTA update workflow under ESP-IDF # Over the Air updates in ESP-IDF uses two partition system to achieve fail-safe firmware updates.\nWe have already covered it in detail in one of our previous blog posts: OTA update frameworks\nOTA update workflow under ESP Privilege Separation # The ESP Privilege Separation framework extends the ESP-IDF OTA mechanism for protected_app and user_app. The partition table is augmented to enable independent updates of protected_app and user_app.\n# ESP Privilege Separation Partition table # Name, Type, SubType, Offset, Size , Flags nvs, data, nvs, , 0x6000, phy_init, data, phy, , 0x1000, otadata, data, ota, , 0x2000, uotadata, data, user_ota, , 0x2000, ota_0, app, ota_0, , 1500K, ota_1, app, ota_1, , 1500K, user_0, app, user_0, , 256K, user_1, app, user_1, , 256K, otadata partition is responsible for selection of active firmware for the protected app. otadata partition is of size 4KiB. uotadata partition is responsible for selection of active firmware for the user app. uotadata partition is of size 4KiB. Partitions ota_0 and ota_1 denote active and passive partitions for the protected app. These partitions are of size 1500KiB as the protected app binary has bulk of the code. Partitions user_0 and user_1 denote active and passive partitions for the user app. These partitions are of size 256KiB as the user app is a lightweight application containing business logic. User App OTA Update Workflow # As the OTA feature is critical to the functioning of the device, the entire OTA functionality is a part of the protected application which protects it from any unintended usage. This also makes the development of user app easier as it does not have to deal with the OTA updates.\nUser app initiates an OTA update by sending a URL, which contains the latest user app firmware, to the protected app. Protected app does sanity tests on received URL and schedules a job to perform OTA update in background and returns to user app. The job downloads firmware image in passive user partition, updates uotadata entries for the user app and reboots the device. The framework also supports secure OTA where the authenticity of the user application is also verified by verifying the signature of the user application.\nUser App Boot-Up Flow # ESP Privilege Separation boot-up flow is slightly different from the traditional ESP-IDF boot-up flow. The second stage bootloader boots the protected app and the protected app is responsible for booting the user app. The protected app refers the uotadatapartition to select the active user partition. The protected app also has a option, which if enabled, verifies the signature of the user application before booting user_app Protected app also has provision to rollback user application in case of unexpected behaviour of newly updated user app. Highlights # The OTA functionality is entirely handled by the protected application and user application need not worry about its implementation. Both, protected_app and user_app can be updated independently allowing different release timelines. Protected application has provision for secure OTA which ensures that only trusted user application can be executed on the device. It also has a fail-safe option of “Application rollback” in case the user application is incorrectly downloaded or shows unexpected behavior during bootup. User OTA example is available in the ESP Privilege Separation Repository . Please give it a try and feel free to report any issues or feedback by raising an issue tracker on the GitHub repository.\nHere’s a video demonstrating a real world use case of user app OTA update using ESP Rainmaker and ESP Privilege Separation.\n","date":"29 January 2023","externalUrl":null,"permalink":"/blog/ota-firmware-updates-with-esp-privilege-separation/","section":"Blog","summary":"","title":"OTA Firmware Updates with ESP Privilege Separation","type":"blog"},{"content":"Happy holidays everyone!\nOn behalf of all employees and the Board of Directors, I am sending you my warmest wishes for a restful, peaceful and meaningful holiday season. We truly hope that 2023 will be a better year for everyone! Despite its difficulties, 2022 was an especially productive year for us at Espressif, during which we reached new milestones that we can be proud of. We will present these at the Consumer Electronics Show (CES 2023) in Las Vegas, USA, from 5 to 8 January, 2023.\nIt is widely known that CES® is the most influential tech event in the world. It is, in fact, the proving ground for breakthrough technologies and global innovators. This is where the world’s sharpest innovators hit the stage, and where the biggest brands do business and meet new partners.\nA central theme of CES 2023 will be diversity and inclusion. For innovation to reach its full potential, diverse voices and perspectives must be heard and amplified. This is how businesses in the tech industry can really flourish. Women, people of color, as well as people with disabilities and age-related challenges are making a difference, despite a traditional lack of representation and funding in the technology field. Therefore, their contribution to today’s tech world will be duly highlighted at CES 2023, in Las Vegas.\nAmong these remarkable contributors, Espressif will present its own unique achievements. Here are a few of them:\nEspressif’s solutions for the Matter protocol, which ensure the secure and seamless connectivity of smart-home devices. The ESP-ZeroCode modules, which provide out-of-the-box Matter connectivity, based on our innovative SoCs: ESP32-C3 (ESP8685), ESP32-C2 (ESP8684), and ESP32-H2. ESP32-C6, Espressif’s first Wi-Fi 6 SoC integrating 2.4 GHz Wi-Fi 6, Bluetooth 5 (LE) and the 802.15.4 protocol. ESP RainMaker®, based on the AWS serverless architecture, for private Cloud deployment. ESP Insights, which is Espressif’s remote observability and diagnostics platform for field-deployed devices. ESP32-S3, Espressif’s dual-core XTensa LX7 MCU, designed for AIoT applications. You still have time to book an appointment with Espressif’s team at CES 2023, so you can get all the information you need about our products and services. Just click on the photograph below and provide the required information.\nKeep reading this month’s newsletter, so you can learn more exciting news from Espressif:\nEspressif Launches Matter-Related Services Espressif’s new Matter-compatible Device Certificate Generation and Pre-provisioning Services aim to reduce manufacturing complexities while also safeguarding CSA standards.\nESP-IDF Release v5.0 Is a Major Update ESP-IDF v5.0 is a major update for ESP-IDF v4.x., and is the latest stable release. It is mostly compatible with apps written for ESP-IDF v4.x, but there are some breaking changes and removal of deprecated functionality, as well.\nGet Hands-On Experience with RISC-V, Using ESP32-C3 Warren Gay, in his new book, explains how the availability of Espressif’s ESP32-C3 provides a way to get hands-on experience with RISC-V. Furthermore, the open-sourced QEMU emulator adds a 64-bit experience in RISC-V under Linux.\nRead More \u0026gt;\nHope you enjoy reading this month’s newsletter. Keep sending us your messages and requests on Facebook, Twitter, GitHub, Instagram, LinkedIn, and YouTube.\nYou can also contact us through our website or you can email us. We try to respond to all of your messages as quickly as possible!\nBest wishes,John LeeSenior Customer Support Officer.\n","date":"1 January 2023","externalUrl":null,"permalink":"/blog/december-2022/","section":"Blog","summary":"","title":"December 2022","type":"blog"},{"content":"Hi everyone,\nelectronica 2022, the world’s leading trade fair and conference for electronics, is taking place in Munich, from 15 to 18 November 2022 and, of course, Espressif Systems will be there!\nAnticipation in the industry is high, since the last in-person trade fair took place four years ago, due to the global pandemic. electronica is the world’s most important industry gathering (and the only one this year) which will seamlessly cover the entire spectrum of electronics by bringing together key players, decision makers and visionaries from the global electronics community. More than 2,000 exhibitors covering a wide range of topics have already registered to present their latest technologies and solutions at this year’s trade fair.\nIn terms of content, not only will electronica cover a huge range of topics through the offerings of its exhibitors, but it will also feature an extensive supporting program in which industry experts will impart their wealth of specialist knowledge. As is tradition, the trade fair will be complemented by the electronica Conferences, which this year will deal with the topics of Automotive, Embedded Platforms, and Wireless Systems and Applications. The electronica Forums will focus, in particular, on applications and solutions, providing a valuable source of inspiration for visitors, thanks to the practical presentations and panel discussions in those Forums.\nIn 2022, the trade fair will be held under the motto ‘Driving sustainable progress,’ as the electronics industry plays a vital role in paving the way for future social issues and for the transition to a high-tech society. The CEOs of leading semiconductor companies will also discuss the industry’s contribution to protecting the climate at the CEO Roundtable. Additional topics of global relevance running through the trade fair include electric mobility, cybersecurity, embedded systems, industrial IoT, sustainability, smart energy, connectivity, AI, sensors and measurement technology. All in all, electronica offers a platform that will bring together experts and users demonstrating practice-oriented and sustainable solutions to combating the challenges of our time.\nEspressif’s presence at this year’s electronica aims to highlight the latest ESP-based solutions, while also emphasising Espressif’s contribution to the development of high-tech solutions to some of the most pressing problems of the present-day world. To this end, Espressif is bringing to electronica its comprehensive Matter solution, along with the ESP-ZeroCode Modules, which have been designed for building Matter-compatible, smart-home devices with ease. Based on ESP32-C3 (ESP8685), ESP32-C2 (ESP8684), and ESP32-H2 SoCs, Espressif’s ESP-ZeroCode Modules offer flexibility in terms of hardware design, while also providing a ready-made, plug-and-play solution for building Matter-compatible products.\nKeep reading this month’s newsletter, so you can learn more about:\nESP-ZeroCode Modules for Out-of-the-Box Matter Connectivity Espressif is pleased to announce ESP-ZeroCode Modules for building Matter-compatible devices based on Espressif hardware with Wi-Fi and Thread (802.15.4) wireless communication protocols.\nESP RainMaker Officially Available in AWS Marketplace ESP RainMaker is available in AWS Marketplace, marking yet another major milestone for Espressif in the field of IoT cloud solutions.\nESP32-H2 \u0026amp; Thread SDK Officially Recognized as “Thread-Certified 1.3.0 Component” Espressif can now provide its customers with the latest and most rigorously-tested Thread solutions (1.3.0).\nDeveloping User Interfaces for ESP-Based Custom-Made Dev Boards This article explains how you can use SquareLine Studio for developing UIs on custom-made boards with LCDs, which are based on an Espressif MCU.\nEsPiFF: An ESP32 in the Raspberry Pi 4 Form Factor For applications where Raspberry Pi 4 is not robust enough, or consumes excessive power, you can consider the EsPiFF — a powerful ESP32-based development board built by MDC-Service, which is a start-up by Michael Schmid and Steffen Wittenburg.\nRead More \u0026gt;\nHope you enjoy reading this month’s newsletter. Keep sending us your messages and requests on Facebook, Twitter, GitHub, Instagram, LinkedIn, and YouTube.\nYou can also contact us through our website or you can email us. We try to respond to all of your messages as quickly as possible!\nBest wishes,John LeeSenior Customer Support Officer.\n","date":"1 January 2023","externalUrl":null,"permalink":"/blog/november-2022/","section":"Blog","summary":"","title":"November 2022","type":"blog"},{"content":"Hi everyone,\nEspressif’s first official online conference is about to get started. We will start the live broadcast on Wednesday 19 Oct at 10:00 am (Central European Summer Time). To ensure you can attend the conference, please register here: https://devcon.espressif.com. Registered attendees will have already received by now the YouTube links for the live event, which will enable them to not only watch the live broadcast but also participate in the Q\u0026amp;A session after each presentation by asking their questions in the conference chat.\nA nearly six-month preparation is reaching its culmination with a rich program. You can expect over 30 talks on topics including Matter, RainMaker, ESP-IDF, Privilege Separation, Embedded Rust, Components Manager, Board Support Packages, third-party frameworks, and more! The speakers who are also Espressif engineers include: Scott Mabin, Darian Leung, Brian Ignacio, Marius Vikhammer with Sudeep Mohanty, Yi Ying, David Cermak, Rodrigo Garcia, Ricardo Tafas with Sylvio Alves, Tomas Rezucha, Zim Kalinowski, Sergei Silnov, Denys Almazov, Mahavir Jain with Sachin Parekh, Sonika Rathi with Yogesh Mantri, Adwait Patankar along with Vikram Dattu and Shubham Rastogi, Piyush Shah, Radim Karniš, Martin Gaño, Juraj Michálek with Sergio Gasquez, Jakob Hasse, Alan Carvalho, and finally Chen Shu along with Hrishikesh Dhayagude and Shubham Patil.\nThe daily schedule of the conference is divided into four sections lasting two hours each. Every presentation is allocated a 30-minute slot which will comprise a talk and a five-minute Q\u0026amp;A session at the end of it. A 15-minute break will follow each two-hour section. At the end of each day, we will have a 15-minute General Q\u0026amp;A session for any questions from the audience. This will be handled by Espressif’s Director of Technical Marketing Amey Inamdar, and Senior Director of Engineering Kedar Sovani at the end of the first day at 19:30 CEST. The General Q\u0026amp;A session at the end of the second day will be handled by Espressif’s VP of Software Platforms Ivan Grokhotkov at 19:45 CEST. Then, at the end of the entire conference, Espressif’s Developer Advocate and Conference Organiser Pedro Minatel will share with us his closing remarks at 20:00 CEST. We will kick off our conference with none other than Espressif’s Founder and CEO, Teo Swee Ann, who will deliver his welcome speech . Teo Swee Ann needs no special introductions. He established Espressif in 2008 and his name has become synonymous with technological innovation ever since. It is always interesting to listen to what he has to say. Our second keynote speaker is going to be our VP of Software Platforms Ivan Grokhotkov, who will talk us through all the new features of ESP-IDF v5.0., at 10:00am on Thursday, 21 October.\nWatch our conference trailer by clicking on the photo above.\nWe also have several guest speakers, such as:\nMicrosoft ’s Principal Program Manager Wellington Duraes , and Senior Software Engineer Ewerton Scaboro da Silva , whose presentation is entitled: “OTA for Your ESP32 Using Azure Divide Update”. Their presentation will be broadcast at 19:20 CEST on 20 October . Arduino ’s Head of Maker Products, Open Source \u0026amp; Community Alessandro Ranellucci , will present “News from Arduino: IDE 2.0 and Command Line Tools” at 18:20 CEST on 20 October . Toit ’s CEO and Co-Founder Kasper Lund , will speak about “Live Reloading of Micro-Services on Your ESP32 at 14:00 CEST on 20 October. WOKWI ’s Founder Uri Shaked will give a talk entitled: “Your Browser is ESP32”at 14:30 CEST on 19 October . Adafruit ’s Founder and Engineer Limor “Ladyada” Fried will talk about “CircuitPython for ESP32” at 19:00 CEST on 19 October. Golioth ’s Developer Relations Lead Chris Gammell, and Developer Relations Engineer Mike Szczys, will present “Thousands of ESP32s: Device Management for ESP-IDF-Based Devices”, at 16:40 CEST on 19 October. Read More \u0026gt;\nHope you enjoy both attending and participating in Espressif DevCon22. Once again, you can ensure this by registering via https://devcon.espressif.com.\nOtherwise, keep sending us your messages and requests on Facebook, Twitter, GitHub, Instagram, LinkedIn, and YouTube.\nYou can also contact us through our website or you can email us. We try to respond to all of your messages as quickly as possible!\nBest wishes,John LeeSenior Customer Support Officer.\n","date":"1 January 2023","externalUrl":null,"permalink":"/blog/october-2022/","section":"Blog","summary":"","title":"October 2022","type":"blog"},{"content":"Hi everyone,\nWe are very excited this month, as we are hard at work preparing for Espressif Systems’ first online conference, Espressif DevCon2022, which will hopefully become an annual tradition. The event will be broadcast live on 19 and 20 October 2022, starting at 10:00am (Central European Summer Time) and finishing at 20:00 on both days.\nThis two-day online conference will highlight certain products and solutions created by Espressif and its partners. This event is designed, structured and put together by Espressif’s developers who wish to communicate and exchange ideas with the global community of developers. Espressif has always been close to the community, not only by offering its solutions on open-source platforms, but also by communicating directly with makers from around the world, responding to their questions and feedback.\nThat said, the aim of Espressif DevCon2022 is to bring together the global community of developers in real time, and share with them new insights, knowledge and tech tips, along with information about new projects and products. Not only will this event give the opportunity to ESP users from around the world to learn more about Espressif, its products and services, but it will also give Espressif the chance to collect feedback and listen to the needs and questions of its global community of supporters during the live broadcast.\nYou can expect more than 30 talks on such topics as Matter, ESP RainMaker, ESP-IDF, Privilege Separation, Embedded Rust, Components Manager, Board Support Packages, third-party frameworks, and more! This conference is open to anyone with a stable connection to the internet at no cost whatsoever. However, prospective attendees need to register in advance. As ever, Espressif actively supports the spreading of tech knowledge far and wide to people from all walks of life, thus contributing to the democratization of technology.\nOur keynote speakers include Espressif’s Founder and CEO, Teo Swee Ann, and Espressif’s VP of Software Platforms, Ivan Grokhotkov, while we also have invited speakers from Microsoft, Arduino, Adafruit, Golioth, Toit, and Wokwi. Their presentations will be complemented by those of dozens of Espressif engineers whose expertise will keep our global audience spellbound. To view the entire program of the conference and fill in the registration form, please visit the official website of Espressif DevCon2022.\nWe can’t wait to chat with as many of you as possible on 19 and 20 October! If you already have any questions or topics you would like to discuss, just drop us a line on our Facebook event page.\nKeep reading this month’s newsletter, so you can also learn about:\nEspressif Is Now a QuickTrack Solution Provider Certified by Wi-Fi Alliance With ESP32-C2 as a QuickTrack-qualified solution, Espressif has made it easier for its customers to achieve Wi-Fi CERTIFIEDTM status for their products.\nImpressive UIs for ESP Projects with SquareLine Studio By following our guide and using the free-for-personal-use SquareLine Studio you can create a great-looking user interface for your next ESP project with ease.\nESP32-S2/S3/C3 Now Supported by Arduino Cloud Arduino is committed to making the list of devices it supports on its platforms grow; hence, ESP32-S2, S3, and C3 have been added to this list.\nESP32-DevKitC V4 with Dual-Antenna Module Hits the Market Espressif’s IoT dev board, ESP32-DevKitC V4, which has an embedded ESP32-WROOM-DA, has become commercially available. With two complementary antennas and the coexistence of Wi-Fi and Bluetooth (Classic \u0026amp; Low-Energy) connectivity, ESP32-DevKitC V4 enhances the quality of wireless connectivity across large areas.\nRead More \u0026gt;\nHope you enjoy reading this month’s newsletter. Keep sending us your messages and requests on Facebook, Twitter, GitHub, Instagram, LinkedIn, and YouTube.\nYou can also contact us through our website or you can email us. We try to respond to all of your messages as quickly as possible!\nBest wishes,John LeeSenior Customer Support Officer.\n","date":"1 January 2023","externalUrl":null,"permalink":"/blog/september-2022/","section":"Blog","summary":"","title":"September 2022","type":"blog"},{"content":"","date":"2 December 2022","externalUrl":null,"permalink":"/tags/deep-learning/","section":"Tags","summary":"","title":"Deep Learning","type":"tags"},{"content":"","date":"2 December 2022","externalUrl":null,"permalink":"/tags/esp-id/","section":"Tags","summary":"","title":"ESP-ID","type":"tags"},{"content":"Artificial intelligence transforms the way computers interact with the real world. Decisions are carried by getting data from Tiny low-powered devices and sensors into the cloud. Connectivity, high cost and data privacy are some of the demerits of this method. Edge artificial intelligence is another way to process the data right on the physical device without sending data back and forth improving the latency and security and reducing the bandwidth and power.\nEspressif System provides a framework ESP-DL that can be used to deploy your high-performance deep learning models on Espressif chip ESP32-S3.\nIn this article, we will understand how to use ESP-DL and deploy a deep-learning model on ESP32-S3.\nPrerequisite for using ESP-DL # Before getting a deep dive into ESP-DL, we assume that readers have;\nKnowledge about building and training neural networks. (Check out basics of deep-learning) Configure the ESP-IDF release 4.4 environment. (Follow setting-up ESP-IDF environment or tool chain for ESP-IDF for more details) Working knowledge of basic C and C++ language.’ Note: Please use ESP-IDF release/v4.4 on the commit “cc71308e2fdce1d6d27fc52d39943f5d0fb83f35” to reproduce the same results\nModel Development # For the sake of simplicity, a classification problem is selected and developed a simple deep-learning model to classify 6 different hand gestures. Many open-source pre trained models are available however for this demonstration we prefer to build a model from scratch to get a better understanding of each layer of the model.\nwe are using Google Co-lab for model development Dataset # For this classification problem, We are using an open-source dataset from the Kaggle Hand Gesture recognition Dataset. The original dataset includes 10 classes however we are using only 6 classes that are easy to recognize and more useful in daily life. The hand gesture classes are represented in the table below. One more difference is related to the image size, the original dataset has an image size of (240 , 640) however for the sake of simplicity resized the dataset to (96 , 96). The dataset used in this article can be found at ESP-DL repo.\nTest/Train Split # We need to divide our dataset into test, train and calibration datasets. These datasets are nothing but the subsets of our original dataset. The training dataset is used to train the model while the testing dataset is to test the model performance similarly calibration dataset is used during the model quantization stage for calibration purposes. The procedure to generate all these datasets is the same. We used train_test_split for this purpose.\nfrom sklearn.model_selection import train_test_split ts = 0.3 # Percentage of images that we want to use for testing. X_train, X_test1, y_train, y_test1 = train_test_split(X, y, test_size=ts, random_state=42) X_test, X_cal, y_test, y_cal = train_test_split(X_test1, y_test1, test_size=ts, random_state=42) *For more details about how train_test_split works please check out scikit-learn.org.\nFor the reproduction of this tutorial you can find the data from (GitHub) and open data in your working environment.\nimport pickle with open(\u0026#39;X_test.pkl\u0026#39;, \u0026#39;rb\u0026#39;) as file: X_test = pickle.load(file) with open(\u0026#39;y_test.pkl\u0026#39;, \u0026#39;rb\u0026#39;) as file: y_test = pickle.load(file) with open(\u0026#39;X_train.pkl\u0026#39;, \u0026#39;rb\u0026#39;) as file: X_train = pickle.load(file) with open(\u0026#39;y_train.pkl\u0026#39;, \u0026#39;rb\u0026#39;) as file: y_train = pickle.load(file) Building a Model # import tensorflow as tf from tensorflow import keras from keras.models import Sequential from keras.layers.convolutional import Conv2D, MaxPooling2D from keras.layers import Dense, Flatten, Dropout print(tf.__version__) model = Sequential() model.add(Conv2D(32, (5, 5), activation=\u0026#39;relu\u0026#39;, input_shape=(96, 96, 1))) model.add(MaxPooling2D((2, 2))) model.add(Dropout(0.2)) model.add(Conv2D(64, (3, 3), activation=\u0026#39;relu\u0026#39;)) model.add(MaxPooling2D((2, 2))) model.add(Dropout(0.2)) model.add(Conv2D(64, (3, 3), activation=\u0026#39;relu\u0026#39;)) model.add(MaxPooling2D((2, 2))) model.add(Flatten()) model.add(Dense(128, activation=\u0026#39;relu\u0026#39;)) model.add(Dense(6, activation=\u0026#39;softmax\u0026#39;)) model.compile(optimizer=\u0026#39;adam\u0026#39;,loss=\u0026#39;sparse_categorical_crossentropy\u0026#39;,metrics=[\u0026#39;accuracy\u0026#39;]) model.summary() Training a Model # The model is running for 5 epochs, with a final accuracy of around 99%.\nhistory=model.fit(X_train, y_train, epochs=5, batch_size=64, verbose=1, validation_data=(X_test, y_test)) Saving a Model # The trained model is saved in Hierarchical Data format (.h5). For more details on how the Keras model be saved check out click tensorflow.org.\nmodel.save(\u0026#39;handrecognition_model.h5\u0026#39;) Model Conversion # ESP-DL uses model in Open Neural Network Exchange (ONXX) format. For more details on how ONNX is working click here. To be compatible with ESP-DL convert the trained .h5 format of the model into ONXX format by using the below lines of code.\nmodel = tf.keras.models.load_model(\u0026#34;/content/handrecognition_model.h5\u0026#34;) tf.saved_model.save(model, \u0026#34;tmp_model\u0026#34;) !python -m tf2onnx.convert --saved-model tmp_model --output \u0026#34;handrecognition_model.onnx\u0026#34; !zip -r /content/tmp_model.zip /content/tmp_model In the end, H5 format model, ONNX format model and model checkpoints are downloaded for future use.\nfrom google.colab import files files.download(\u0026#34;/content/handrecognition_model.h5\u0026#34;) files.download(\u0026#34;/content/handrecognition_model.onnx\u0026#34;) files.download(\u0026#34;/content/tmp_model.zip\u0026#34;) ESP-DL format # Once the ONNX format of the model is ready, follow the steps below to convert the model into ESP-DL format.\nWe are using Pychram IDE for ESP-DL format conversion. Requirements # Setting up an environment and installing the correct version of the modules is always a key to start with. If the modules are not installed in the correct version it gives an error.\nNext, need to download ESP-DL. clone the ESP-DL from the GitHub repository.\ngit clone --recursive https://github.com/espressif/esp-dl.git Optimization and Quantization # To run the optimizer provided by ESP-DL, we need to find and\ncalibrator.pyd calibrator_acc.pyd evaluator.pyd optimizer.py place these files into the working directory of pychram — IDE. Furthermore, also place the calibration dataset generated in the previous section 1.2 and ONNX format model saved in previous section 1.5 .\nFollow the below steps for generating optimized and quantize model.\nfrom optimizer import * from calibrator import * from evaluator import * # Load the ONNX model onnx_model = onnx.load(\u0026#34;handrecognition_model.onnx\u0026#34;) optimized_model_path = optimize_fp_model(\u0026#34;handrecognition_model.onnx\u0026#34;) # Load Calibration dataset with open(\u0026#39;X_cal.pkl\u0026#39;, \u0026#39;rb\u0026#39;) as f: (test_images) = pickle.load(f) with open(\u0026#39;y_cal.pkl\u0026#39;, \u0026#39;rb\u0026#39;) as f: (test_labels) = pickle.load(f) calib_dataset = test_images[0:1800:20] pickle_file_path = \u0026#39;handrecognition_calib.pickle\u0026#39; # Calibration model_proto = onnx.load(optimized_model_path) print(\u0026#39;Generating the quantization table:\u0026#39;) calib = Calibrator(\u0026#39;int16\u0026#39;, \u0026#39;per-tensor\u0026#39;, \u0026#39;minmax\u0026#39;) # calib = Calibrator(\u0026#39;int8\u0026#39;, \u0026#39;per-channel\u0026#39;, \u0026#39;minmax\u0026#39;) calib.set_providers([\u0026#39;CPUExecutionProvider\u0026#39;]) # Obtain the quantization parameter calib.generate_quantization_table(model_proto,calib_dataset, pickle_file_path) # Generate the coefficient files for esp32s3 calib.export_coefficient_to_cpp(model_proto, pickle_file_path, \u0026#39;esp32s3\u0026#39;, \u0026#39;.\u0026#39;, \u0026#39;handrecognition_coefficient\u0026#39;, True) If everything is alright, at this stage two files with an extension .cpp and .hpp is generated in the path, and the output should look like this.\nEvaluate # This step is not necessary however if you want to evaluate the performance of the optimized model the following code can be used.\nprint(\u0026#39;Evaluating the performance on esp32s3:\u0026#39;) eva = Evaluator(\u0026#39;int16\u0026#39;, \u0026#39;per-tensor\u0026#39;, \u0026#39;esp32s3\u0026#39;) eva.set_providers([\u0026#39;CPUExecutionProvider\u0026#39;]) eva.generate_quantized_model(model_proto, pickle_file_path) output_names = [n.name for n in model_proto.graph.output] providers = [\u0026#39;CPUExecutionProvider\u0026#39;] m = rt.InferenceSession(optimized_model_path, providers=providers) batch_size = 64 batch_num = int(len(test_images) / batch_size) res = 0 fp_res = 0 input_name = m.get_inputs()[0].name for i in range(batch_num): # int8_model [outputs, _] = eva.evalaute_quantized_model(test_images[i * batch_size:(i + 1) * batch_size], False) res = res + sum(np.argmax(outputs[0], axis=1) == test_labels[i * batch_size:(i + 1) * batch_size]) # floating-point model fp_outputs = m.run(output_names, {input_name: test_images[i * batch_size:(i + 1) * batch_size].astype(np.float32)}) fp_res = fp_res + sum(np.argmax(fp_outputs[0], axis=1) == test_labels[i * batch_size:(i + 1) * batch_size]) print(\u0026#39;accuracy of int8 model is: %f\u0026#39; % (res / len(test_images))) print(\u0026#39;accuracy of fp32 model is: %f\u0026#39; % (fp_res / len(test_images) Model Deployment # Model deployment is the final and crucial step. In this step, we will implement our model in C-language to run on the top of ESP32-S3 micro-controller and gets the results.\nESP-IDF Project Hierarchy # The first step is to create a new project in VS-Code based on ESP-IDF standards. For more details about how to create a VS-Code project for ESP32 please click here or here\nCopy the files.cpp and .hpp generated in the previous section 2.2 to your current working directory.\nAdd all the dependent components to the components folder of your working directory. sdkconfig files are default files from ESP-WHO example. These files are also provided in linked GitHub repository.\nThe Project directory should look like this;\n├── CMakeLists.txt ├── components │ ├── esp-dl │ └── esp-who ├── dependencies.lock ├── main │ ├── app_main.cpp │ └── CMakeLists.txt ├── model │ ├── handrecognition_coefficient.cpp │ ├── handrecognition_coefficient.hpp │ └── model_define.hpp ├── partitions.csv ├── sdkconfig ├── sdkconfig.defaults ├── sdkconfig.defaults.esp32 ├── sdkconfig.defaults.esp32s2 └── sdkconfig.defaults.esp32s3 Model define # We will define our model in the ‘model_define.hpp’ file. Follow the below steps for a details explanation of defining the model.\nImport libraries # Firstly import all the relevant libraries. Based on our model design or another way to know which particular libraries need to use an open source tool Netron and open your optimized ONNX model generated at the end of previous section 2.2 . Please check here for all the currently supported libraries by ESP-DL.\n#pragma once #include \u0026lt;stdint.h\u0026gt; #include \u0026#34;dl_layer_model.hpp\u0026#34; #include \u0026#34;dl_layer_base.hpp\u0026#34; #include \u0026#34;dl_layer_max_pool2d.hpp\u0026#34; #include \u0026#34;dl_layer_conv2d.hpp\u0026#34; #include \u0026#34;dl_layer_reshape.hpp\u0026#34; #include \u0026#34;dl_layer_softmax.hpp\u0026#34; #include \u0026#34;handrecognition_coefficient.hpp\u0026#34; using namespace dl; using namespace layer; using namespace handrecognition_coefficient; Declare layers # The next is to declare each layer.\nInput is not considered a layer so not defined here.\nExcept for the output layer, all the layers are declared as private layers.\nRemember to place each layer in order as defined in previous section 1.3 while building the model.\nclass HANDRECOGNITION : public Model\u0026lt;int16_t\u0026gt; { private: Reshape\u0026lt;int16_t\u0026gt; l1; Conv2D\u0026lt;int16_t\u0026gt; l2; MaxPool2D\u0026lt;int16_t\u0026gt; l3; Conv2D\u0026lt;int16_t\u0026gt; l4; MaxPool2D\u0026lt;int16_t\u0026gt; l5; Conv2D\u0026lt;int16_t\u0026gt; l6; MaxPool2D\u0026lt;int16_t\u0026gt; l7; Reshape\u0026lt;int16_t\u0026gt; l8; Conv2D\u0026lt;int16_t\u0026gt; l9; Conv2D\u0026lt;int16_t\u0026gt; l10; public: Softmax\u0026lt;int16_t\u0026gt; l11; // output layer Initialize layers # After declaring the layers, we need to initialize each layer with its weight, biases activation functions and shape. let us check each layer in detail.\nBefore getting into details, let us look into how our model looks like when opening in Netron that is somehow imported to get some parameters for initializing.\nThe first layer is reshaped layer (note that the input is not considered as a layer) and gives an output shape of (96 , 96, 1) for this layer. These parameters must be the same as you used during model training see section 1.3. Another way to know the parameter and layer is to use an open source tool Netron and open your optimized ONNX model generated at the end of previous section 2.2.\nFor the convolution 2D layer we can get the name of this layer for the filter, bias and activation function from the .hpp file generated at the end of the previous section 2.2, However for the exponents, we need to check the output generated in section 2.2.5.\nFor the max-pooling layer, we can use the same parameters as we use during building our model see section 1.3. or another way to know the parameter and layer is to use an open-source tool Netron and open your optimized ONNX model generated at the end of the previous section 2.2.\nFor the dense layer or fully connected layer, conv2D block is used and we can get the name of this layer for the filter, bias and activation function from the .hpp file generated at the end of previous section 2.2, However for the exponents, we need to check the output generated in section 2.2.5.\nThe output layer is a SoftMax layer weight and the name can be taken from the output generated in section 2.2.5.\nHANDRECOGNITION () : l1(Reshape\u0026lt;int16_t\u0026gt;({96,96,1})), l2(Conv2D\u0026lt;int16_t\u0026gt;(-8, get_statefulpartitionedcall_sequential_1_conv2d_3_biasadd_filter(), get_statefulpartitionedcall_sequential_1_conv2d_3_biasadd_bias(), get_statefulpartitionedcall_sequential_1_conv2d_3_biasadd_activation(), PADDING_VALID, {}, 1,1, \u0026#34;l1\u0026#34;)), l3(MaxPool2D\u0026lt;int16_t\u0026gt;({2,2},PADDING_VALID, {}, 2, 2, \u0026#34;l2\u0026#34;)), l4(Conv2D\u0026lt;int16_t\u0026gt;(-9, get_statefulpartitionedcall_sequential_1_conv2d_4_biasadd_filter(), get_statefulpartitionedcall_sequential_1_conv2d_4_biasadd_bias(), get_statefulpartitionedcall_sequential_1_conv2d_4_biasadd_activation(), PADDING_VALID,{}, 1,1, \u0026#34;l3\u0026#34;)), l5(MaxPool2D\u0026lt;int16_t\u0026gt;({2,2},PADDING_VALID,{}, 2, 2, \u0026#34;l4\u0026#34;)), l6(Conv2D\u0026lt;int16_t\u0026gt;(-9, get_statefulpartitionedcall_sequential_1_conv2d_5_biasadd_filter(), get_statefulpartitionedcall_sequential_1_conv2d_5_biasadd_bias(), get_statefulpartitionedcall_sequential_1_conv2d_5_biasadd_activation(), PADDING_VALID,{}, 1,1, \u0026#34;l5\u0026#34;)), l7(MaxPool2D\u0026lt;int16_t\u0026gt;({2,2},PADDING_VALID,{}, 2, 2, \u0026#34;l6\u0026#34;)), l8(Reshape\u0026lt;int16_t\u0026gt;({1,1,6400},\u0026#34;l7_reshape\u0026#34;)), l9(Conv2D\u0026lt;int16_t\u0026gt;(-9, get_fused_gemm_0_filter(), get_fused_gemm_0_bias(), get_fused_gemm_0_activation(), PADDING_VALID, {}, 1, 1, \u0026#34;l8\u0026#34;)), l10(Conv2D\u0026lt;int16_t\u0026gt;(-9, get_fused_gemm_1_filter(), get_fused_gemm_1_bias(), NULL, PADDING_VALID,{}, 1,1, \u0026#34;l9\u0026#34;)), l11(Softmax\u0026lt;int16_t\u0026gt;(-14,\u0026#34;l10\u0026#34;)){} Build layers # The next step is to build each layer.\nvoid build(Tensor\u0026lt;int16_t\u0026gt; \u0026amp;input) { this-\u0026gt;l1.build(input); this-\u0026gt;l2.build(this-\u0026gt;l1.get_output()); this-\u0026gt;l3.build(this-\u0026gt;l2.get_output()); this-\u0026gt;l4.build(this-\u0026gt;l3.get_output()); this-\u0026gt;l5.build(this-\u0026gt;l4.get_output()); this-\u0026gt;l6.build(this-\u0026gt;l5.get_output()); this-\u0026gt;l7.build(this-\u0026gt;l6.get_output()); this-\u0026gt;l8.build(this-\u0026gt;l7.get_output()); this-\u0026gt;l9.build(this-\u0026gt;l8.get_output()); this-\u0026gt;l10.build(this-\u0026gt;l9.get_output()); this-\u0026gt;l11.build(this-\u0026gt;l10.get_output()); } Call layers # In the end, we need to connect these layers and call them one by one by using a call function.\noid call(Tensor\u0026lt;int16_t\u0026gt; \u0026amp;input) { this-\u0026gt;l1.call(input); input.free_element(); this-\u0026gt;l2.call(this-\u0026gt;l1.get_output()); this-\u0026gt;l1.get_output().free_element(); this-\u0026gt;l3.call(this-\u0026gt;l2.get_output()); this-\u0026gt;l2.get_output().free_element(); this-\u0026gt;l4.call(this-\u0026gt;l3.get_output()); this-\u0026gt;l3.get_output().free_element(); this-\u0026gt;l5.call(this-\u0026gt;l4.get_output()); this-\u0026gt;l4.get_output().free_element(); this-\u0026gt;l6.call(this-\u0026gt;l5.get_output()); this-\u0026gt;l5.get_output().free_element(); this-\u0026gt;l7.call(this-\u0026gt;l6.get_output()); this-\u0026gt;l6.get_output().free_element(); this-\u0026gt;l8.call(this-\u0026gt;l7.get_output()); this-\u0026gt;l7.get_output().free_element(); this-\u0026gt;l9.call(this-\u0026gt;l8.get_output()); this-\u0026gt;l8.get_output().free_element(); this-\u0026gt;l10.call(this-\u0026gt;l9.get_output()); this-\u0026gt;l9.get_output().free_element(); this-\u0026gt;l11.call(this-\u0026gt;l10.get_output()); this-\u0026gt;l10.get_output().free_element(); } }; Model Run # Import Libraries # After building our Model need to run and give input to our model. ‘app_main.cpp’ file is used to generate the input and run our model on ESP32-S3.\n#include \u0026lt;stdio.h\u0026gt; #include \u0026lt;stdlib.h\u0026gt; #include \u0026#34;esp_system.h\u0026#34; #include \u0026#34;freertos/FreeRTOS.h\u0026#34; #include \u0026#34;freertos/task.h\u0026#34; #include \u0026#34;dl_tool.hpp\u0026#34; #include \u0026#34;model_define.hpp\u0026#34; Declare Input # We trained our model by giving an input of size (96, 96, 1) see section 1.3. However, the input_exponent can get its exponent value from the output generated in section 2.2.5. Another thing is to write the pixels of the input/test picture here.\nint input_height = 96; int input_width = 96; int input_channel = 1; int input_exponent = -7; __attribute__((aligned(16))) int16_t example_element[] = { //add your input/test image pixels }; Set Input Shape # Each pixel of the input is adjusted based on the input_exponent declared above.\nextern \u0026#34;C\u0026#34; void app_main(void) { Tensor\u0026lt;int16_t\u0026gt; input; input.set_element((int16_t *)example_element).set_exponent(input_exponent).set_shape({input_height,input_width,input_channel}).set_auto_free(false); Call a Model # Call the model by calling the method forward and passing input to it. Latency is used to calculate the time taken by ESP32-S3 to run the neural network.\nHANDRECOGNITION model; dl::tool::Latency latency; latency.start(); model.forward(input); latency.end(); latency.print(\u0026#34;\\nSIGN\u0026#34;, \u0026#34;forward\u0026#34;); Monitor Output # The output is taken out from the public layer i.e. l11. and you can print the result in the terminal.\nfloat *score = model.l11.get_output().get_element_ptr(); float max_score = score[0]; int max_index = 0; for (size_t i = 0; i \u0026lt; 6; i++) { printf(\u0026#34;%f, \u0026#34;, score[i]*100); if (score[i] \u0026gt; max_score) { max_score = score[i]; max_index = i; } } printf(\u0026#34;\\n\u0026#34;); switch (max_index) { case 0: printf(\u0026#34;Palm: 0\u0026#34;); break; case 1: printf(\u0026#34;I: 1\u0026#34;); break; case 2: printf(\u0026#34;Thumb: 2\u0026#34;); break; case 3: printf(\u0026#34;Index: 3\u0026#34;); break; case 4: printf(\u0026#34;ok: 4\u0026#34;); break; case 5: printf(\u0026#34;C: 5\u0026#34;); break; default: printf(\u0026#34;No result\u0026#34;); } printf(\u0026#34;\\n\u0026#34;); The model latency is around 0.7 Seconds on ESP32-S3, whereas each neuron output and finally the predicted result is shown.\nFuture Work # In future, we will design a model for ESP32-S3 EYE devkit which could capture images in real time and performs hand gesture recognition. Check out the GitHub repository for source code.\n","date":"2 December 2022","externalUrl":null,"permalink":"/blog/hand-gesture-recognition-on-esp32-s3-with-esp-deep-learning/","section":"Blog","summary":"","title":"Hand Gesture Recognition on ESP32-S3 with ESP-Deep Learning","type":"blog"},{"content":"“I would like to start a new product design with my favorite chip but it’s out of stock! Oh, no! I’ll have to design a new layout and develop new drivers for it!” Every designer knows that feeling very well these days…\nThe good news is you don’t have to worry about a such thing anymore, at least in terms of ESP-IDF Ethernet PHY driver support. In this article, I’ll demonstrate to you how simple it is to create a new Ethernet PHY driver.\nFirst of all, you need to find a replacement for your current PHY chip. I have a friend working for a semiconductors distribution company so I just picked up my phone and asked him for some advice. He recommended ADIN1200. It’s a robust industrial-grade chip with a wide set of features. It’s an ideal candidate for our demonstration purposes, since an evaluation board exists, the chip is from a vendor which is currently not supported by ESP-IDF (i.e. we limit the possibility of vendor locking for our customers) and the chip is IEEE 802.3 compliant. The last fact will help us the most to reduce the effort needed for a new driver creation since a management interface between EMAC and PHY is standardized and the ESP-IDFv5.0 takes advantage of it. The ESP-IDF Ethernet driver basically consists of three layers:\nThe Ethernet objects itself which is the public API and which wraps MAC and PHY layers into one functional unit. The MAC layer controls the behavior of the Media Access Controller and provides a data interface to the driver application. The PHY layer controls physical layer properties and gathers the status of the link. The “22.2.4 Management Functions” section of the IEEE 802.3 standard defines provisions of the so-called “MII Management Interface” for the purposes of controlling the PHY and gathering status from the PHY by MAC. A set of management registers is defined and this basic management functionality is addressed by the ESP-IDF Ethernet driver as a set of common functions. Therefore, you as an author of the new PHY driver can focus only on chip-specific features like:\nLink status indication which is almost always chip-specific. Chip initialization. This part is not strictly required, since it’s most common. It’s good to be added to ensure that the expected chip is used. Chip-specific features configuration (such as Wake on LAN, Energy Efficient Ethernet, various diagnostics capabilities, etc). Let’s demonstrate the creation of the driver step by step # In terms of hardware, it is easiest to start with the EVAL-ADIN1200 evaluation board. This evaluation board only requires a few modifications to be connected to ESP32 via RMII. (You can, of course, start with a new PCB design if you find it more appropriate.)\nSteps to prepare the hardware:\nStudy materials at the ADIN1200 product page and get familiar with the chip and the evaluation board.\nOnce you are familiar with the evaluation board, the following modifications are required:\nADIN1200 requires an external 50 MHz RMII REF_CLK, therefore de-solder the Y1 oscillator and its associated coupling capacitors. Solder R120 with 0R resistor Solder 10K pull-ups at RX_CTL(High) and RX_CLK (High) to configure ADIN1200 into RMII mode. For additional configuration options, consult “*Table 5. EVAL-ADIN1200FMCZ Configuration Setting” *in the EVAL-ADIN1200FMCZ User Guide. Connect ADIN1200 RMII interface to ESP32. I soldered wires to the exposed 0R resistors as shown in the below Table. Try to keep wires as short as possible and all with the same length. Note that RMII REF_CLK needs to be generated externally to ADIN1200 either by an external 50 MHz oscillator or by ESP32. It is simpler to use ESP32 for our demonstration purposes so I used that solution, but keep in mind that the ESP32 WROOM module is required.\n╔════════════════════╦═════════════════╦═════════════╗ ║ RMII Interface Pin ║ EVAL-ADIN1200 ║ ESP32 WROOM ║ ╠════════════════════╬═════════════════╬═════════════╣ ║ TX_EN ║ R80 ║ GPIO21 ║ ║ TXD[0] ║ R90 ║ GPIO19 ║ ║ TXD[1] ║ R88 ║ GPIO22 ║ ║ RXD[0] ║ R99 ║ GPIO25 ║ ║ RXD[1] ║ R86 ║ GPIO26 ║ ║ CRS_DV ║ R81 ║ GPIO27 ║ ║ RESET ║ R213 ║ GPIO5 ║ ║ REF_CLK ║ C92 ║ GPIO17 ║ ║ MDIO ║ MDIO Test Point ║ GPIO18 ║ ║ MDC ║ MDC Test Point ║ GPIO23 ║ ╚════════════════════╩═════════════════╩═════════════╝ The result of EVAL-ADIN1200 modification is shown in the figure below.\nFrom software point of view, it’s even simpler.\nSteps to create the new Ethernet PHY driver:\nCreate a copy of esp_eth_phy_ip101.c or any other IEEE 802.3 compatible PHY chip source file from the ESP-IDF /components/esp_eth/src/ folder to a new folder.\nRename all occurrences of “ip101” to “adin1200”.\nUpdate the “Vendor Specific Registers” code section with ADIN1200 registers you are planning to use. I’ve only updated the “PHY Status 1 Register” since I’m not planning to use any of the advanced features yet.\n/***************Vendor Specific Register***************/ /** * @brief PHY Status 1 Register * */ typedef union { struct { uint32_t lp_apause_adv : 1; /* The link partner has advertised asymmetric pause */ uint32_t lp_pause_adv : 1; /* The link partner has advertised pause */ uint32_t autoneg_sup : 1; /* Local and remote PHYs support autonegotiation */ uint32_t col_stat : 1; /* Indicates that collision is asserted */ uint32_t rx_dv_stat : 1; /* Indication that receive data valid (RX_DV) is asserted. */ uint32_t tx_en_stat : 1; /* Indication that transmit enable (TX_EN) is asserted */ uint32_t link_stat : 1; /* Link status */ uint32_t hcd_tech : 3; /* Indication of the resolved technology after the link is established */ uint32_t b_10_pol_inv : 1; /* polarity of the 10BASE-T signal inversion */ uint32_t pair_01_swap : 1; /* Pair 0 and Pair 1 swap */ uint32_t autoneg_stat : 1; /* Autonegotiation Status Bit */ uint32_t par_det_flt_stat: 1; /* Parallel Detection Fault Status Bit */ uint32_t reserverd : 1; /* Reserved */ uint32_t phy_in_stndby : 1; /* PHY is in standby state and does not attempt to bring up links */ }; uint32_t val; } ps1r_reg_t; #define ETH_PHY_PS1R_REG_ADDR (0x1A) Update expected oui and model in adin1200_init() function based on the content of “PHY Identifier 1/2 Register”* *defined in datasheet. /* Check PHY ID */ uint32_t oui; uint8_t model; ESP_GOTO_ON_ERROR(esp_eth_phy_802_3_read_oui(phy_802_3, \u0026amp;oui), err, TAG, \u0026#34;read OUI failed\u0026#34;); ESP_GOTO_ON_ERROR(esp_eth_phy_802_3_read_manufac_info(phy_802_3, \u0026amp;model, NULL), err, TAG, \u0026#34;read manufacturer\u0026#39;s info failed\u0026#34;); ESP_GOTO_ON_FALSE(oui == 0xa0ef \u0026amp;\u0026amp; model == 0x02, ESP_FAIL, err, TAG, \u0026#34;wrong chip ID (read oui=0x%\u0026#34; PRIx32 \u0026#34;, model=0x%\u0026#34; PRIx8 \u0026#34;)\u0026#34;, oui, model); Modify the update_link_duplex_speed() function to read the actual negotiation result. This information is not standardized under IEEE 802.3 hence all PHY chips differ at this point. ADIN1200 indicates this data in the “PHY Status 1 Register”. ... ESP_GOTO_ON_ERROR(eth-\u0026gt;phy_reg_read(eth, addr, ETH_PHY_ANLPAR_REG_ADDR, \u0026amp;(anlpar.val)), err, TAG, \u0026#34;read ANLPAR failed\u0026#34;); ESP_GOTO_ON_ERROR(eth-\u0026gt;phy_reg_read(eth, addr, ETH_PHY_BMSR_REG_ADDR, \u0026amp;(bmsr.val)), err, TAG, \u0026#34;read BMSR failed\u0026#34;); eth_link_t link = bmsr.link_status ? ETH_LINK_UP : ETH_LINK_DOWN; /* check if link status changed */ if (adin1200-\u0026gt;phy_802_3.link_status != link) { /* when link up, read negotiation result */ if (link == ETH_LINK_UP) { ps1r_reg_t ps1r; ESP_GOTO_ON_ERROR(eth-\u0026gt;phy_reg_read(eth, addr, ETH_PHY_PS1R_REG_ADDR, \u0026amp;(ps1r.val)), err, TAG, \u0026#34;read PS1R failed\u0026#34;); switch (ps1r.hcd_tech) { case 0: //10Base-T half-duplex speed = ETH_SPEED_10M; duplex = ETH_DUPLEX_HALF; break; case 1: //10Base-T full-duplex speed = ETH_SPEED_10M; duplex = ETH_DUPLEX_FULL; break; case 2: //100Base-TX half-duplex speed = ETH_SPEED_100M; duplex = ETH_DUPLEX_HALF; break; case 3: //100Base-TX full-duplex speed = ETH_SPEED_100M; duplex = ETH_DUPLEX_FULL; break; default: break; } ... Create a new header file with esp_eth_phy_new_adin1200() function. … and the new PHY driver is done and ready to be used!\nNow, we just create MAC and PHY objects as we are used to and initialize the ESP-IDF Ethernet driver in our application.\n#include \u0026#34;esp_eth_phy_adin1200.h\u0026#34; // Init common MAC and PHY configs to default eth_mac_config_t mac_config = ETH_MAC_DEFAULT_CONFIG(); eth_phy_config_t phy_config = ETH_PHY_DEFAULT_CONFIG(); // Update PHY config based on board specific configuration phy_config.phy_addr = CONFIG_EXAMPLE_ETH_PHY_ADDR; phy_config.reset_gpio_num = CONFIG_EXAMPLE_ETH_PHY_RST_GPIO; // Init vendor specific MAC config to default eth_esp32_emac_config_t esp32_emac_config = ETH_ESP32_EMAC_DEFAULT_CONFIG(); // Update vendor specific MAC config based on board configuration esp32_emac_config.smi_mdc_gpio_num = CONFIG_EXAMPLE_ETH_MDC_GPIO; esp32_emac_config.smi_mdio_gpio_num = CONFIG_EXAMPLE_ETH_MDIO_GPIO; // Create new ESP32 Ethernet MAC instance esp_eth_mac_t *mac = esp_eth_mac_new_esp32(\u0026amp;esp32_emac_config, \u0026amp;mac_config); // Create new PHY instance esp_eth_phy_t *phy = esp_eth_phy_new_adin1200(\u0026amp;phy_config); // Init Ethernet driver to default and install it esp_eth_handle_t eth_handle = NULL; esp_eth_config_t config = ETH_DEFAULT_CONFIG(mac, phy); ESP_GOTO_ON_FALSE(esp_eth_driver_install(\u0026amp;config, \u0026amp;eth_handle) == ESP_OK, NULL, err, TAG, \u0026#34;Ethernet driver install failed\u0026#34;); The full version of the ADIN1200 Ethernet PHY driver is available at ESP-IDF additional Ethernet drivers repository or via IDF Component Manager.\n","date":"27 November 2022","externalUrl":null,"permalink":"/blog/esp-idf-custom-ethernet-phy-driver-quick-guide/","section":"Blog","summary":"","title":"ESP-IDF Custom Ethernet PHY Driver Quick Guide","type":"blog"},{"content":"","date":"27 November 2022","externalUrl":null,"permalink":"/tags/ethernet/","section":"Tags","summary":"","title":"Ethernet","type":"tags"},{"content":"","date":"27 November 2022","externalUrl":null,"permalink":"/authors/ondrej-kosta/","section":"Developer Portal Authors","summary":"","title":"Ondrej Kosta","type":"authors"},{"content":"","date":"27 November 2022","externalUrl":null,"permalink":"/tags/programming/","section":"Tags","summary":"","title":"Programming","type":"tags"},{"content":"Recently, I’ve been sitting behind my computer, which is unluckily situated against a window. Sharp late-afternoon sunlight made me think about some intelligent system that recognizes this light and closes the curtains. As home automation has become more and more widespread in recent years, there are many options available on the market that solve most of the common problems we have daily. However, talking about intelligent curtains systems, most of the available solutions require replacing the whole curtains’ holders like rods or rails. I wanted to develop a system adaptable to curtains that are already in use.\nAfter several sketches, modeling attempts, and soldering experiments, this is what I came up with:\nAssembly # Stepper motor NEMA17 with driver TMC2209 to move the curtains BH1750 light sensor that provides information about light intensity thermistor to control the temperature of the motor to prevent overheating reed switch whose function is to initialize the curtains ESP32-DevKitC board controls the stepper motor and communicates with the server/Home Assistant DC/DC buck converter converts 12V powering the Stepper motor into 5V, which powers the ESP32-DevKitC All parts used in this project should be easy to buy in any hardware/electronics store. The only exception may be the TMC2209 driver. It was developed to control 3D printers, thus it will definitely be in a 3D printing store. For an easier understanding of how these components work, I have linked datasheets to them.\nSolution # A key feature to call this system automated is the reed switch. After plugging the system into electricity, it automatically starts moving the curtains. Neodymium magnets are placed on the belt, which are detected with the reed switch when the system is fully opened or closed. That’s how the system is initialized and ready to move to certain positions.\nI’ve created a custom PCB board to connect all these parts. The schematics diagram can be found in the GitHub repo. For better manipulation and modularity, all the peripherals are connected with JST XH connectors and pin sockets soldered to PCB.\nSoftware # I decided to implement three control modes. When one of these modes is active, the functionality is as follows:\nCommunication between the user and the system is ensured by Home Assistant. Home Assistant runs as a server on a local network to which the ESP32 connects and communicates using the MQTT protocol (MQTT Broker extension in Home Assistant).\nEvery transferred value has its MQTT topic, like: *light, temperature, position, etc. *Most of the messages are just Integers, which are easy to send. But timeTable sends more than just a number, so the message must be serialized. In my case, into JSON format.\nvoid Week::processRequrst(DynamicJsonDocument doc) { const char *action = doc[\u0026#34;action\u0026#34;]; const char *day = doc[\u0026#34;day\u0026#34;]; int hours = doc[\u0026#34;hour\u0026#34;]; int mins = doc[\u0026#34;min\u0026#34;]; int position = doc[\u0026#34;position\u0026#34;]; ... Home Assistant provides friendly GUI, where the user can change and set values of desired modes. When the whole system is fully initialized, there is an asynchronous function callback, that process an incoming message and based on the topic changes the relevant values. The program cycles in an infinite loop and processes the position of the curtains based on the active mode, sensor values and actual position. It also reads new sensor data every 15 seconds, which is sent to the server.\nMechanics # For easy adaptation to existing curtains, I designed 3D models of required holders that can be attached to the curtain rod. 3D models were made in Fusion 360 and can also be found in the repository.\nTesting # After assembling all parts into a prototype, came the moment of truth: How is it going to work altogether? After some debugging, the moving with all required modes works just fine. One of the problems is that I could not reach the required speed, probably caused by the stepper motor library I used.A future improvement could be motor overload detection. This function is called StallGuard and is supported by the TMC2209 driver. It can be used to detect a foreign object in the way of curtains to prevent the stepper motor from overloading.\nConclusion # This project was created as a Bachelor’s degree project at the Faculty of Information Technology, Brno University of Technology. I decided to implement the project in Arduino IDE, because of multiple choices of existing libraries to control time, motor, or WiFi connection. This was my first project using an embedded device and all its belongings like creating PCB, 3D modeling, soldering, etc…\nReference # Link to GitHub repo with all used libraries and models can be found here: Smart curtains system\n","date":"23 November 2022","externalUrl":null,"permalink":"/blog/smart-curtains-system/","section":"Blog","summary":"","title":"Building a Smart Curtains System with the ESP32","type":"blog"},{"content":"","date":"23 November 2022","externalUrl":null,"permalink":"/tags/home-automation/","section":"Tags","summary":"","title":"Home Automation","type":"tags"},{"content":"","date":"23 November 2022","externalUrl":null,"permalink":"/tags/smart-curtain/","section":"Tags","summary":"","title":"Smart Curtain","type":"tags"},{"content":"","date":"23 November 2022","externalUrl":null,"permalink":"/tags/smart-home/","section":"Tags","summary":"","title":"Smart Home","type":"tags"},{"content":" DevCon22 # If you missed the first DevCon edition, you can watch here!\nDay 1 # Day 2 # ","date":"20 October 2022","externalUrl":null,"permalink":"/events/devcon22/","section":"Events","summary":"","title":"Espressif DevCon22","type":"events"},{"content":"A few weeks ago in this article we have introduced SquareLine Studio and how it can be used to develop user interfaces. This feature was available only for Espressif’s boards. But what if we wanted to use this tool for our custom designed board based on an ESP chip with a custom LCD? Here is the solution!\nWhat is the best way to add a custom board into SquareLine Studio? Start with the custom_waveshare_7inch example on from esp-bsp repository on GitHub. This example is based on the same code as other Espressif’s examples for SquareLine Studio. However there is one big difference. There must be a custom component similar to Espressif’s BSP with main functions for handling the LCD screen and initialization of the LVGL graphic library.\nFor this example we have selected the following LCD display: WaveShare 7inch 800x480 with RA8875 graphical controller and GT911 touch screen controller.\n1. Making the custom BSP for your board # First step in preparing the package for the SquareLine Studio is to make a component similar to BSP. You can see implementation for the 7inch WaveShare LCD in our example on GitHub, where only important functions are implemented in ws_7inch.c file. For other screens, the following functions should be changed:\n/* LCD display initialization */ static lv_disp_t *lvgl_port_display_init(void) { ... }/* Touch initialization */ static esp_err_t lvgl_port_indev_init(void) { ... } If the communication with thetouch screen isn’t over I2C, there must be initialization of the SPI or some other communication interface instead of this:\nesp_err_t bsp_i2c_init(void) { ... } Second part of making a custom BSP is to edit the header file ws_7inch.h . This is where are all pin configurations, communication speed configuration and screen size for the board are defined.\nThe last thing you should do is to modify CMakeLists.txt and idf_component.yml , when any filename changes or when you need to use another component for the LCD screen or touch screen. You should modify idf_component.yml in the main project too when the component name is changed.\n2. The board description file and board image # After the custom BSP is done, we can move to update the board description file____ manifest.json :\n{ \u0026#34;name\u0026#34;:\u0026#34;Custom WaveShare 7inch\u0026#34;, \u0026#34;version\u0026#34;:\u0026#34;1.0.0\u0026#34;, \u0026#34;mcu\u0026#34;:\u0026#34;ESP32\u0026#34;, \u0026#34;screen_width\u0026#34;:\u0026#34;800\u0026#34;, \u0026#34;screen_height\u0026#34;:\u0026#34;480\u0026#34;, \u0026#34;screen_color_swap\u0026#34;:true, \u0026#34;short_description\u0026#34;:\u0026#34;WaveShare 7inch Display\u0026#34;, \u0026#34;long_description\u0026#34;:\u0026#34;Example of the custom BSP and custom LCD\u0026#34;, \u0026#34;placeholders\u0026#34;: { \u0026#34;__ESP_BOARD_INCLUDE__\u0026#34;: \u0026#34;bsp/ws_7inch.h\u0026#34;, \u0026#34;__ESP_BOARD_I2C_INIT__\u0026#34;: \u0026#34;/* Initialize I2C (for touch) */\\n bsp_i2c_init();\u0026#34; } } Values name , version, mcu, short_description and long_description are only for displaying your board right in the SquareLine Studio. There can be anything. More important are values screen_width , screen_height and screen_color_swap , which define physical values for your LCD display. The placeholders should be updated with the right values from your custom BSP. The header file path into ESP_BOARD_INCLUDE and touch screen initialization function into ESP_BOARD_I2C_INIT .\nSecond file for update is board image____ image.png . There must be a board image in size 380px x 300px .\n3. ESP-IDF and LVGL default configuration # If you have any specific changes in IDF configuration or LVGL configuration, you can put it into sdkconfig.defaults file. The configuration option CONFIG_LV_COLOR_16_SWAP must be same like value in screen_color_swap in manifest.json file.\n4. Generate and copy package for SquareLine Studio # After all changes are done in files, create the package by run generator in root SquareLine generator folder:\npython gen.py -b custom_waveshare_7inch -o output_folder The package will be generated into espressif folder in output_folder . The last step is to copy this generated package espressif/custom_waveshare_7inch into the boards folder in the SquareLine Studio installation folder.\n5. Launch the SquareLine Studio # After launching the SquareLine Studio, you should see your board in the Create tab and Espressif tab. There should be your board name, description and image.\nConclusion # Now, you can create your own project with the custom board. You can use a lot of widgets from LVGL. I can give the recommendation to you, don’t use zoom in image, if it is not necessary, resize image in another image editor and use in full size. The zoom function can be slower and the bigger image can take a lot of the size of the microcontroller flash memory.\nWhen your project is done, then export the template by selecting Export-\u0026gt;Create Template Project in the main menu and export UI files by Export-\u0026gt;Export UI Files in the main menu.\nThe last step is build and flash by command like this:\nidf.py -p COM34 flash monitor The second recommendation is, don’t forget to change the size of the factory partition in the partitions.csv file and change the flash size of your selected module in menuconfig, when you are using bigger images. Or you will see that the built application is too big and there is no space for downloading it.\n","date":"10 October 2022","externalUrl":null,"permalink":"/blog/developing-user-interfaces-for-custom-boards-with-esp-microcontrollers/","section":"Blog","summary":"","title":"Developing User Interfaces for Custom Boards with ESP microcontrollers","type":"blog"},{"content":"","date":"10 October 2022","externalUrl":null,"permalink":"/tags/lvgl/","section":"Tags","summary":"","title":"LVGL","type":"tags"},{"content":"","date":"10 October 2022","externalUrl":null,"permalink":"/tags/squareline/","section":"Tags","summary":"","title":"Squareline","type":"tags"},{"content":"","date":"11 September 2022","externalUrl":null,"permalink":"/tags/embedded/","section":"Tags","summary":"","title":"Embedded","type":"tags"},{"content":"If you tried to make some fancy UI without any graphic library, you know, how hard it is. Fortunately, there are lot of graphical libraries for making fancy UI on our screens. One of the often used is LVGL, which is supported on ESP microcontrollers. Usually, when we wanted to use graphical library like LVGL, we had to know API functions and how to combine it to reach fancy UI. It isn’t true anymore!\nThere is a tool called SquareLine Studio, which can help making better and fancy UI without any other knowledge of the LVGL API.\nSquareLine Studio # The SquareLine Studio is a visual multiplatform (Mac OS, Windows and Linux) tool for creating beautiful graphical user interface with LVGL graphical library. You can use drag-and-drop for adding and moving widgets on the screen. Working with images or fonts is very simple too.\nAfter launching the SquareLine Studio and creating a new project (or open example project), there is main editor view (Figure 1). In the middle of the screen is one or more screens in the size of the output LCD display. On the left side is a list of widgets added on the screen in well-arranged hierarchy . Under the hierarchy is list of available widgets but there aren’t all of widgets from LVGL, only most of them. On the right side are three tabs. The important is Inspector and very helpful can be Font manager too. Inspector is changing for each selected widget on the screen and allows make appearance changing of the widget. There is Events part too, where can be added an event for selected widget. There are lot of events for selection from click to gestures. Font manager can make LVGL font from any TTF font file and there can be selected only some characters for spare the memory. On the bottom of the application, there are two tabs, Assets for all media files in the project and Console , where is the whole history of info, warning and error messages.\nThe play button on top right corner on the main screen enables simulator - all widgets actions and animations. You can try there, how yours UI will be react.\nFor create the code files, there is Export in the top menu and Export UI Files .\nSquareLine studio version 1.1 introduce new feature — board templates . There are pre-prepared boards from some companies, so you can generate complete project with the UI code for selected hardware. This complete project can be created by Export-\u0026gt;Create Template Project and then Export-\u0026gt;Export UI Files (UI files must be exported again after any change).\nESP Boards in SquareLine Studio # Espressif has prepared two boards in SquareLine Studio for you: ESP-BOX and ESP-WROVER-KIT . You can select the board after launch the application in Create tab and then in Espressif tab (Figure 2). Each board has pre-filled size of screen, rotation and color depth, which is corresponding with ESP-BSP which is used in generated code.\nWhen you select the board, you can see empty screen on the main view of the application. This empty screen has same size like the display on the selected board. Now, you can drag-and-drop some widgets, put the texts and set events. For example something like in the figure 3.\nAfter creating the template files (Export-\u0026gt;Create Template Project) and exporting UI files (Export-\u0026gt;Export UI Files), you can compile and flash the project by following the same steps, as you are used to with another Espressif’s examples (if you are using ESP-IDF). On the ESP-BOX it will look like in the figure 4.\nIs SquareLine Studio for free? # This tool is free for personal use with some limitations . The free use is limited by 5 screens only and 50 widgets for one project. Other pricing plans can be found on SquareLine website.\nConclusion # In my opinion, that’s really helpful tool for making fancy user interfaces on your displays and after the board templates added, it is really easy to use. Sometimes, it can be helpful only for edit some UI or it helps with position of the new widgets. It is very fast for use and easy.\nUnfortunately, there is still missing some minor things, which can make this tool better. For example, I am missing some widgets like tabview or copy style to another widget. The compile and flash the Espressif’s microcontrollers would be nice too.\nIndeed it is a new tool and we can hope, that some of these things will be added in next updates.\n","date":"11 September 2022","externalUrl":null,"permalink":"/blog/making-the-fancy-user-interface-on-esp-has-never-been-easier/","section":"Blog","summary":"","title":"Making the Fancy User Interface on ESP Has Never Been Easier!","type":"blog"},{"content":"","date":"11 September 2022","externalUrl":null,"permalink":"/tags/user-interface/","section":"Tags","summary":"","title":"User Interface","type":"tags"},{"content":"Hi everyone,\nEspressif is taking part in the upcoming Maker Faire in Prague on 17–18 September____ 2022, and in Brno on 22–23 October. Maker Faire is a family-friendly showcase of inventions and creativity that gathers technology enthusiasts, crafters, and educators from the Czech Republic and abroad. Makers come to show their creations and visitors get the opportunity to try new gadgets firsthand. This technology festival is the perfect combination of sciences, traditional crafts, the latest technological trends and design.\nThe Maker Faire in Prague will be celebrating its fifth year in 2022, and will take place in the Prague Market Hall, a magnificent space where visitors will be able to find Espressif’s delegation among many others. The international programme of the Festival will take place both indoors and outdoors, where dozens of makers will showcase their projects. Visitors will have the opportunity to get involved in several workshops and installations.\nThe Maker Faire in Brno will be organised for the third consecutive year in 2022. It will take place at the weekend on 22–23 October in the perfectly fitting venue of Pavilion A1 in the Brno Exhibition Centre. Visitors will have the chance to familiarise with hundreds of makers and their projects. As ever, attendees will be able to participate in numerous workshops and installations. The program will take place indoors and partly outdoors.\nEspressif Systems’ participation in both cities of the Czech Maker Faire aims to introduce the latest ESP-based solutions to the general public, while getting to know local makers better.\nSo, those of you who happen to be in Prague and Brno, on 17–18 September and 22–23 October, respectively, do come and say “hi” to Espressif’s representatives! They will be more than happy to meet you and explain to you all about our innovative AIoT solutions.\nKeep reading this month’s newsletter, so you can also learn about:\nLight+Building Trade Fair Oct. ‘22 From From October 2 to 6, Espressif will participate in the 2022 Autumn Edition of the Light + Building Trade Fair in Frankfurt am Main, showcasing a wide range of smart-home and lighting solutions.\nPackage Delivery Detection with ESP-Based Computer Vision Identify when packages or boxes arrive on your doorstep with a computer-vision project that combines ESP-EYE, Espressif’s development board for image recognition and audio processing, as well as the Edge Impulse Studio.\nESP-Hosted Reduces Cost and Complexity of IoT Devices This article focuses on the many advantages of ESP-Hosted, our open-source solution which uses Espressif SoCs and modules as communication co-processors.\nESP Badge for the 2022 Fri3d Camp The 2022 Fri3d Camp took place last month. It was a family-friendly summer festival for hackers, where each participant received a cool-looking badge based on Espressif’s ESP32-WROVER module.\nRead More \u0026gt;\nHope you enjoy reading this month’s newsletter. Keep sending us your messages and requests on Facebook, Twitter, GitHub, Instagram, LinkedIn, and YouTube.\nYou can also contact us through our website or you can email us. We try to respond to all of your messages as quickly as possible!\nBest wishes,John LeeSenior Customer Support Officer.\n","date":"10 September 2022","externalUrl":null,"permalink":"/blog/aug-2022/","section":"Blog","summary":"","title":"Aug 2022","type":"blog"},{"content":"","date":"7 September 2022","externalUrl":null,"permalink":"/authors/adwait-patankar/","section":"Developer Portal Authors","summary":"","title":"Adwait Patankar","type":"authors"},{"content":"ESP Insights allows developers to view stack back-traces and register dumps for firmware running on devices.\nWith rich information about issues, developers have a much shorter turn-around time for fixing issues.\nQuick Links Here you can find the relevant links:\nESP Insights GitHub Dashboard Insights Related Articles Read more about the ESP Insights!\n","date":"7 September 2022","externalUrl":null,"permalink":"/tags/espinsights/","section":"Tags","summary":"","title":"ESP Insights","type":"tags"},{"content":"In today’s world which is completely engulfed in social media, the notion of tags is not new. Most of the media publicly shared on the social network is tagged (or to be more accurate, hash-tagged) with something or the other. With that familiarity in mind, we thought of introducing the concept of tagging to the ESP devices, that should help users categorise or search their devices faster on the ESP Insights Dashboard.\nWhat is tagging? # A tag is essentially a label, that makes the object or thing being tagged easier to find or categorise. In the social media world it is called as hashtag that is applied to a post, image, video or rather any media content based on the information it carries or sometimes based on specific theme. For e.g. #summervibes #sunnyday\nDevice Tagging # In IOT world too, how cool it would be to label your devices with such tags. The tag can be associated as a meta-data with the device and would certainly help in searching, categorising your devices in the field. We maintain tags as a combination of Name-Value pair to add a multi-dimensional categorization.\nFor e.g. If user wants to tag the devices based on their location viz. City:Boston or within a home automation project say Location:Kitchen for a smart bulb in the kitchen and so on so forth.\nIf the devices are to be categorised based on the firmware version viz. Version:v5.1 or based on their behaviour like infrequent crashing viz. Category:Crashing.\nThe image below showcases how the device level tags (if applied) are enlisted on the node reports page below the stats section.\nClick on any of the listed tags, user is taken to the Group Analytics page with an automatic search filter applied for the the clicked tag name. All the devices carrying the selected tag are displayed in the nodes listing.\nAs mentioned earlier, the users can also explicitly apply search filters based on node tags from the Group Analytics Dynamic Search Filters and list out device matching the search criteria. For e.g. Search all devices of type bulb.\nThe Property input box also supports auto-suggest based on the available tags as applied to the devices of the logged-in user. The Value input box also supports auto-suggest based on the values already present for the selected tag property.\nTag Management # Now that we know we know that the users can tag their own devices, let’s take a look at how to actually add tags to the devices from the ESP Insights Dashboard. At this moment, tags can only be applied one device (a.k.a node) at a time, by accessing the individual node details. User can reach to an individual node by selecting one of their nodes from the node list accessed either via “Nodes” option or a filtered node list from “Group Analytics” option.\nOn the selected node, now the users should see a new tab called “Tags ” along side the Node Report, Metrics and Variables tabs.\nThe Tags tab enlists all the existing tags. User is able to add or remove tags from this page. The tag is added or removed only for the selected node.\nUser has to enter a combination of Tag Name and Tag Value. Both of these are case-sensitive and each input field has a restriction of 15 characters.\nThere is a ‘Delete’ option available in front of the each listed tag. User can delete or disassociate one tag at a time.\nStay tuned to get more on what we can achieve with the tagging feature especially with the search and grouping of devices based on the tags.\nVisit https://dashboard.insights.espressif.com to play around with tags on your devices.\n","date":"7 September 2022","externalUrl":null,"permalink":"/blog/esp-insights-playing-with-device-tags/","section":"Blog","summary":"","title":"ESP Insights: Playing with Device Tags","type":"blog"},{"content":"","date":"7 September 2022","externalUrl":null,"permalink":"/tags/follow/","section":"Tags","summary":"","title":"Follow","type":"tags"},{"content":"","date":"7 September 2022","externalUrl":null,"permalink":"/tags/observability/","section":"Tags","summary":"","title":"Observability","type":"tags"},{"content":"","date":"7 September 2022","externalUrl":null,"permalink":"/tags/sign-in/","section":"Tags","summary":"","title":"Sign In","type":"tags"},{"content":"","date":"7 September 2022","externalUrl":null,"permalink":"/tags/sign-up/","section":"Tags","summary":"","title":"Sign Up","type":"tags"},{"content":"","date":"16 August 2022","externalUrl":null,"permalink":"/tags/custom-dashboard/","section":"Tags","summary":"","title":"Custom Dashboard","type":"tags"},{"content":"The core purpose of ESP Insights Dashboard has always been to help quickly identify a group of nodes which are showing similar behaviour patterns with the help of powerful search filters. Further it helps the user to reach to a particular node and help diagnose the reason behind the node showing a certain behaviour. The user can then check the event logs or point in time metrics and system variable values and correlate any diagnostic information at hand. More in detail about group analytics and search filters can be found here.\nThe need for custom dashboards # Each ESP Insights user may have a different perspective of looking at their device data. A user in developer role , may be using the dashboard more from diagnostics purposes and interested in understanding the crashing devices or the reboot pattern of devices. Whereas another user in product manager role might be using it from analytics insights purposes and interested in just looking at the spread of online devices of particular type(s) and at particular times in a day or a week or a month. In order to cater to individual perspectives, sticking to just one default view and asking the user to set the filters every single time was not scoring on the user experience. Thus came the improvement to make it easier for the end users to save their custom dashboard with their search filters applied and preserved. A user can save multiple dashboards as per their need and intention of use viz. Crashing Devices Dashboard or Led Light v5.0 Devices (light devices with firmware version 5.0) and so on so forth.\nManaging your dashboards # As can be seen in the above image, there are multiple dashboards created, each for a different purpose, and filtering devices accordingly. While the “Crashing Device Dashboard” lists devices reporting crashes in last 7 days, there is another dashboard named “LED Lights” which just lists devices with firmware project as “led_lights”.\nUsers can add specific search filters, apply specific date range; either absolute or relative like last 30 days or last 7 days etc. The device list is updated based on the search criteria.\nLet’s take a look at how the user can create and manage their dashboards.\nInitially there is only a default view, clean slate without any filters. The user can apply search filters, choose a date range and create a new dashboard. The users are prompted with a message if they want to save these filters as a separate dashboard. Click on the Save Dashboard should create a new Dashboard and should also get listed in the left side menu.\nBased on the selected time range the data is loaded in the dashboard. If the selected date range is absolute (for e.g 10 June 2022– 10 July 2022), then same data as received during that time range will be loaded every time that dashboard is selected. If the time range is relative (for e.g. last 30 days), then the data for relative time (say last 30 days) from the current day is fetched and displayed in the selected dashboard.\n2. Rename Dashboard\nOnce the dashboard is saved, the user has the ability to change the name of the dashboard to their liking. Click on the settings options in the top right corner of the dashboard and choose the option for Rename Dashboard\nThe name can be edited and the changes are saved. The same is reflected in the right side menu options as well as in the dashboard title.\n3. Save Dashboard\nMake any changes to the Dashboard filters or search criteria and the user has a provision to save the preferences. Once saved, these search criterion are persisted across the logins. Click on the settings options in the top right corner of the dashboard and choose the option for Save Dashboard\nA confirmation message should appear once the changes to the Dashboard are saved successfully.\n4. Save As New Dashboard\nThe user can create an altogether new dashboard from an existing dashboard as a template. Make changes to your existing dashboard, and user can save it as a new dashboard. The existing dashboard search filters are retained. Click on the settings options in the top right corner of the dashboard and choose the option for Save As New Dashboard.\nA new dashboard should get created and should be listed under the dashboards list on the left side menu.\n5. Set As Default Dashboard\nThe user can choose which dashboard should be the default landing page on login, sort of a favourite or the most frequently used one. Only one dashboard can be set as a default one. Click on the settings options in the top right corner of the dashboard and choose the option for Set As Default Dashboard.\n6. Delete Dashboard\nThe user can delete the dashboard which is no longer needed. Apart from the system default dashboard which sort of serves as the template, rest of the user created dashboards can be deleted one by one. Click on the settings options in the top right corner of the dashboard and choose the option for Delete Dashboard.\nTry out this new feature on the https://dashboard.insights.espressif.com\nWe are working on some more exciting features in the ESP Insights, stay tuned to hear more!\n","date":"16 August 2022","externalUrl":null,"permalink":"/blog/esp-insights-custom-dashboards/","section":"Blog","summary":"","title":"ESP Insights : Custom Dashboards","type":"blog"},{"content":"It’s been a few months, since we first introduced our Group Analytics feature in the ESP Insights. Group Analytics allows a wholistic view of your devices in the field, categorised or grouped either by their behavioural pattern viz. reporting certain type of crashes or reboots because of certain errors or even non-erroneous conditions. Devices could be even grouped at a very high level by their characteristics like the firmware application and the version they carry.\nThe first version of Group Analytics however provided a limited set of pre-defined grouping options. Refer to the blog for more details.\nDynamic Search Filters # With lot of device data intelligence available for perusal, having pre-defined search filters and grouping options gave limited capabilities to the end users.\nThe new release for ESP Insights Dashboard, Group Analytics provides ability to search and group the devices on varied parameters. User is given an option to apply grouping filters on pretty much anything that is indexed and searchable in the database. Based on the selected filter type, suggestions for the search filter values are also made available. User can even filter for crash by particular register addresses or even crash backtrace address or log tags etc.\nMultiple search filters can be applied in tandem as well to get more fine grained results. The most frequently used filters are listed at the beginning.\nThe filters types are available in a hierarchical fashion and are suggested as the user types in the input in the search filter text field.\nThe event timeline has options to change the frequency of plotting to daily, weekly, monthly or even hourly.\nCompact Event Stats # The event stats are displayed at one glance and are updated for the selected group search filter.\nVice versa, clicking on one of the items in the stats filter results in applying that particular event as search filter.\nEach individual widget section can be collapsed or opened to focus on particular sections.\nRich Date and Time Range Selector # New release of ESP Insights comes with a rich widget for Date and Time selector allowing user with a more fine grained control over time window to be used on this analytics page. The user is also provided with some default quick date filters like “Today”, “Yesterday”, “Last 24 hours”, “Last 7 days”, “Last 30 days” and “Last 3 months”. Custom date picker allows user to select time as well.\nNode listing and Node Report Correlation # Based on the search filters and grouping, the actual devices (nodes) are listed at the bottom. The listed nodes provide navigational links to move to individual node report for event logs, metrics and variable values for the selected node. The search filters like the event type and time window parameters are carried forward to the node report page automatically.\nTry out the new Group Analytics and advanced searching capabilities by accessing on ESP Insights Dashboard.\n","date":"8 August 2022","externalUrl":null,"permalink":"/blog/esp-insights-group-analytics-with-dynamic-search-filters/","section":"Blog","summary":"","title":"ESP Insights: Group Analytics with Dynamic Search Filters","type":"blog"},{"content":"Hi everyone,\nFrom 3 until 6 August 2022, Espressif is taking part in the Guangzhou International Lighting Exhibition (GILE), which is the most highly regarded platform for the LED and lighting industry, as it provides a unique chance for all industry players to communicate, cooperate and create valuable business opportunities. You can find Espressif’s delegation in Zone B, Hall 10.2, booth D48. Please scan the QR code in the picture below, to register and get your ticket.\nBy embracing the digital transformation, the lighting industry faces new opportunities in intelligent lighting controls, predictive management, space and occupancy analytics, beacon networking among many other applications that have created additional value to basic lighting fixtures. With this in mind, the theme chosen for the 27th edition of GILE is ‘New Era, New Opportunity’ along with the theme of the fringe programme ‘Turning Ideas Into Action’, which promises to share different ways of thinking about lighting in the new era, as well as how to put those ideas into practice.\nEspressif Systems’ participation in the Guangzhou International Lighting Exhibition aims to showcase two cost-effective, wireless-communication SoCs, ESP32-C2 and ESP32-C3, which are especially suitable for smart-lighting applications. Both of these SoCs combine 2.4 GHz Wi-Fi 4 and Bluetooth 5 (LE), while being built around RISC-V MCUs which provide stable and secure wireless connectivity.\nWe are also highlighting ESP RainMaker, our complete system for building Cloud-connected AIoT products, which is a private Cloud solution based on the AWS serverless architecture. Its many advantages include a pay-as-you-grow economic plan, easy adoption and deployment, best-in-class data security, voice-integration support, as well as full ownership and platform control. ESP RainMaker reduces the building time for your solutions to a single week, while it covers all Espressif chips and modules, device firmware, voice-assistant integrations, phone apps, and Cloud backend. This helps you minimize your R\u0026amp;D costs, gain independence, and focus on innovating your core-value offering.\nAdditionally, we are demonstrating Espressif’s one-stop Matter solution, which can simplify and accelerate the development of Matter devices significantly. This solution marks the culmination of our ongoing contribution to the Matter standard in various areas, including protocol formulation, core stack implementation and certification test events.\nFurthermore, we are exhibiting Espressif’s ESP32-C3-based smart switch, which upgrades traditional switches to smart switches, without rewiring, or configuring a gateway. It also combines low power-consumption with reliable and secure Wi-Fi connectivity. In our GILE booth visitors may also see ESP32-S3-BOX, Espressif’s AI voice-development kit, which provides a platform for developing the control of smart devices with offline and online voice assistants. ESP32-S3-BOX is ideal for developing not only smart speakers, but also IoT devices that achieve an excellent human-machine interaction. To this end, ESP32-S3-BOX integrates a touch screen controller, various sensors, an infrared controller and a smart gateway. Finally, we are demonstrating Espressif’s new human-detection solution, ESP-WIFI-CSI.\nSo, those of you who happen to be in Guangzhou from 3 to 6 August 2022 do come to Espressif’s stall and say “hi” to our representatives there. They will be more than happy to explain all about our innovative AIoT solutions.\nOther topics you can read about in this month’s newsletter include:\nLaunching ESP-RTC ESP-RTC achieves stable, smooth, ultra-low-latency voice-and-video transmission in real time, providing an ideal solution for users who want to build low-cost and low-power audio-and-video products.\nAnnouncing the Golioth ESP-IDF SDK Golioth has just released an open-source SDK for the Espressif ESP-IDF, making it easier for Espressif-based projects to securely connect to the Golioth Cloud.\nLaunching the ESP Privilege Separation ESP Privilege Separation is designed to prevent user-facing applications from interfering with protected applications and code.\nESP RainMaker: Accelerate Your AIoT Business with a Platform You Own Espressif’s ESP RainMaker® provides a complete, yet customizable, end-to-end solution to building AIoT products. With ESP RainMaker, it should take you only a week to fully build your own AIoT solution.\nRead More \u0026gt;\nHope you enjoy reading this month’s newsletter. Keep sending us your messages and requests on Facebook, Twitter, GitHub, Instagram, LinkedIn, and YouTube.\nYou can also contact us through our website or you can email us. We try to respond to all of your messages as quickly as possible!\nBest wishes,John LeeSenior Customer Support Officer.\n","date":"7 August 2022","externalUrl":null,"permalink":"/blog/july-2022/","section":"Blog","summary":"","title":"July 2022","type":"blog"},{"content":"Connecting your devices to the cloud is a topic which is actively discussed across multiple industries as it is not a hidden fact that there are numerous advantages to doing so. To name a few common advantages across various industries —\nAccessibility: With devices connected to the cloud, accessing them anywhere, anytime across the globe is possible with a click of a button or a fingertip. Back up your data : Most cloud services will provide facilities to back up your critical data collected through these connected devices. Over-The-Air (OTA) updates: One of the most important benefits is the capability of updating your devices\u0026rsquo; FW/SW remotely. This is critical to keep your devices secure and reduces maintenance costs significantly. Improved Productivity: With automation and increased collaboration between different devices (Machine-to-Machine), the time spent by valuable resources on getting things done is reduced drastically which results in much higher productivity. These well-known advantages are making the technology widely accepted across various industries so much so that “Over 60% of organisations currently use IoT, with only 9% of them currently having none at all.” (IoT Developer Survey, Eclipse Foundation[1])\nBut still, there are challenges for the adoption of the technology with I__ntegration with existing technology__ and cost of implementation remaining two of the biggest barriers as per the GSMA Intelligence Enterprise IoT Survey[2]\nEspressif’s ESP-Hosted is a solution to cater to the above two barriers and is aimed to ease the integration complexities by providing standard software interfaces which require no or minimal changes to the existing solutions, as well as, reduce the development timelines significantly by providing open source solution which works “off-the-shelf” thus lowering the development costs.\nThe latest ESP-Hosted NG solution from Espressif is targeted toward Linux or Android-based systems which want to add wireless and cloud connectivity to their existing products as well as for IoT Gateways. This is important as Linux is the number one operating system with a 43% market share amongst all connected devices as per the IoT Developer survey conducted by the Eclipse organisation[1].\nESP-Hosted # ESP-Hosted is an open source solution that provides a way to use Espressif SoCs and modules as a communication co-processor. This solution provides wireless connectivity (Wi-Fi and BT/BLE) to the host microprocessor(MPU) or microcontroller(MCU), allowing it to communicate with other devices. ESP-Hosted communicates with the host processor through commonly available UART, SPI or SDIO peripheral interface.\nThis architecture which separates the wireless connectivity module from the main host processing module is beneficial as it adds the wireless connectivity to existing MCU/MPU-based solutions providing the following advantages.\nFaster development cycles — The ESP-Hosted help the connectivity module to connect over the standard 802.11 interface (ESP-Hosted-NG) or an 802.3 interface (ESP-Hosted-FG) and thus acts as a“plug \u0026amp; play” device Reduce re-qualification/re-certification efforts — As the ESP-Hosted does not touch the user-space applications, adding the connectivity module will not require developers to re-qualify or re-certify the majority of their software. Power Saving — The main MPU/MCU can remain in low power mode without being interrupted to stay connected to the network. The main host needs to only get involved when there are actual tasks to perform offloading all the connectivity overheads to the connectivity module. Easier upgrades and Product variants — The architecture enables the developers to easily upgrade for better wireless connectivity or have multiple variants of the same product with different connectivity options. Such an example is shown below in which the developer can use the same Host applications and software but have a variety of options for wireless connectivity from Wi-Fi4 to Wi-Fi6 to Wi-Fi6 dual band. On top of the above-stated development advantages of the two chip architecture, by choosing the ESP-Hosted solution you also get Espressif’s easy availability of modules and a cost effective solution which has acceptable performance levels for a majority of the applications.\nESP-Hosted is open-source and Espressif makes the source code available for developers to take advantage of the rich features of the ESP32 family of SoCs. The developers can make use of the IO and HMI capabilities of the ESP32 and the ESP32-S3 or the advanced security features such as the Digital Signature Peripheral of the ESP32-C3 device. The possibilities are endless.\nVariants of ESP-Hosted # The ESP-Hosted solution is available in two variants as mentioned below. The differentiation factor here is the type of network interface presented to the host and the way Wi-Fi on ESP SoC/module is configured/controlled. Both the variants have their respective host and firmware software.\nESP-Hosted-FG # This is a first-generation ESP-Hosted solution. This variant provides a standard 802.3 (Ethernet) network interface to the host. In order to achieve this, the host is presented with the following:\nA simple 802.3 network interface which essentially is an Ethernet interface A lightweight control interface to configure Wi-Fi on the ESP SoC A standard HCI interface The use of the simple 802.3 interface for this solution makes it ideal to be used with MCU hosts. The MCU application can continue to take advantage of the standard TCP/IP stack and prevents significant changes to the host application for using the AT firmware-based approach or integrating the complex 802.11 interface.\nESP-Hosted-NG # This is the Next-Generation ESP-Hosted solution specifically designed for hosts that run Linux operating system. *This variant of the solution takes a standard approach while providing a network interface to the host. * This allows usage of standard Wi-Fi applications such as wpa_supplicant to be used with ESP SoCs/modules. This solution offers the following:\n802.11 network interface which is a standard Wi-Fi interface on a Linux host Configuration of Wi-Fi is supported through standard cfg80211 interface of Linux A standard HCI interface Our Recommendation # If you are using an MCU host , you have to use ESP-Hosted-FG. If you are using a Linux host , we recommend ESP-Hosted-NG since it takes a standard approach which makes it compatible with widely used user space applications/services such as wpa_supplicant, Network Manager etc. References - *1. *IoT Developer Survey, Eclipse Foundation*2. *GSMA Intelligence Enterprise IoT Survey\nThanks to Amey Inamdar for the review and feedback.\n","date":"31 July 2022","externalUrl":null,"permalink":"/blog/reducing-costs-and-complexity-for-deploying-connected-devices-with-esp-hosted/","section":"Blog","summary":"","title":"Reducing costs and complexity for deploying connected devices with ESP-Hosted","type":"blog"},{"content":"Hi everyone,\nLast month (21–23 June), Espressif Systems was delighted to participate in the 20th edition of embedded world. With over 3,900 online and onsite attendees embedded world proved that it is the leading trade fair of the international embedded community. More than 720 exhibitors from 39 countries presented their latest developments in embedded technologies, ranging from components, modules and complete development boards to operating systems and software tools, as well as services for embedded systems.\nIn this major event, Espressif unveiled ESP32-C5, the world’s first RISC-V SoC with a dual-band Wi-Fi 6 and Bluetooth 5 (LE) connectivity. We also presented the most recent achievements in our SoC portfolio. Here are some more details about them:\nESP32-C5: a RISC-V SoC with 2.4 \u0026amp; 5 GHz Wi-Fi 6 and Bluetooth 5 (LE), which is designed for IoT applications requiring high-efficiency wireless transmissions; ESP32-H2: a RiSC-V SoC that combines IEEE 802.15.4 (Thread and Zigbee) and Bluetooth 5 (LE) with support for the Matter protocol, which enables interconnectivity for home-automation projects from different providers; ESP32-C2 and ESP32-C3: RISC-V SoCs with 2.4 GHz Wi-Fi 4 and Bluetooth 5 (LE) connectivity, designed for a wide range of common IoT products; ESP32-S3: An AI SoC built specifically for the AIoT market. It combines 2.4 GHz Wi-Fi 4 and Bluetooth 5 (LE) with powerful AI acceleration and reliable security features for high-performance applications of voice and face recognition. Below you can watch the relevant video we presented at *embedded world *2022:\nIntroducing Espressif’s Latest SoCs and Solutions\nFurthermore, from 20 to 23 June 2022, the CSA Connectivity Standards Alliance held a members’ meeting in San Diego, USA, where professionals from across the globe came together to develop Alliance standards, through networking and collaboration across multiple working groups. Espressif, as an active member of the CSA Alliance and among the first contributors to the Matter project, was there showcasing its one-stop Matter solution. This is based on a whole range of Espressif SoC series, a production-ready ESP-Matter SDK, and ESP RainMaker’s Matter integration, which enables Cloud-based management for Matter devices. Please click here to get all the details on Espressif’s one-stop Matter solution.\nOther topics you can read about in this month’s newsletter include:\nIntroducing ESP32-C5 Espressif’s ESP32-C5 is the industry’s first RISC-V SoC solution that supports a 2.4 and 5 GHz dual-band Wi-Fi 6, along with Bluetooth LE, for high-efficiency wireless transmissions.\nEspressif’s One-Stop Matter Solution Espressif’s one-stop Matter solution can simplify and accelerate the development process of Matter products significantly.\nEspressif’s AWS IoT ExpressLink Module Espressif, in partnership with Amazon Web Services, is proud to announce the general availability of its new connectivity module with built-in support for the AWS IoT ExpressLink specification.\nEspressif Collaborates with PlatformIO Labs The two companies begin a wide-ranging partnership in providing a next-generation development ecosystem for IoT solutions.\nRead More \u0026gt;\nHope you enjoy reading this month’s newsletter. Keep sending us your messages and requests on Facebook, Twitter, GitHub, Instagram, LinkedIn, and YouTube.\nYou can also contact us through our website or you can email us. We try to respond to all of your messages as quickly as possible!\nBest wishes,John LeeSenior Customer Support Officer.\n","date":"10 July 2022","externalUrl":null,"permalink":"/blog/june-2022/","section":"Blog","summary":"","title":"June 2022","type":"blog"},{"content":"In the previous post, we introduced ESP Privilege Separation, a framework to achieve “user-kernel” separation and isolation on ESP32-C3 SoC. There are multiple ways of applying this framework to your project. This post presents a case study of integrating ESP-RainMaker, a real-world IoT application, with the ESP Privilege Separation framework.\nESP-RainMaker offers a complete ecosystem to build connected AIoT products. Please refer to this link for more details.\nIntegrating ESP-RainMaker with ESP Privilege Separation # rmaker_switch | — CMakeLists.txt | — partitions.csv | — protected_app/ | | — main/ | | — CMakeLists.txt | | — protected_main.c | — user_app/ | — main/ | | — CMakeLists.txt | | — user_code.c | — user_config.h | — CMakeLists.txt Please refer to the “Getting Started” documentation for a detailed explanation regarding the directory structure.\n2. Placement of the ESP-RainMaker agent Based on the system call implementation, we have the following options to place the ESP-RainMaker agent:\nOption1: ESP-RainMaker agent in the user application Option2: ESP-RainMaker agent in the protected application In this post, we will choose the second approach and we will also discuss certain implications in subsequent sections.\n3. Component split between protected and user apps\nThe above diagram shows the overview of component split between protected and user apps. All the libraries like ESP-RainMaker, TLS stack, etc. are placed in the protected app and hence it does the bulk of the heavy lifting. User app is a lightweight application consisting of business logic.\nThe build system generates app_libs_and_objs.json file in the build directory, which represents all the libraries, its memory footprint, and corresponding object files included in respective applications.\n4. System call implementation As we have decided to place the ESP-RainMaker agent in the protected app, we will have to implement system calls for all the public APIs provided by ESP-RainMaker. The ESP Privilege Separation’s easy extensibility features allow you to add application-specific custom system calls, which is documented here, and we shall use the same feature here.\nFor example, esp_rmaker_start()* *is one of the APIs exposed by ESP-RainMaker. After we move ESP-RainMaker in the protected app, all the calls to esp_rmaker_start() in the user app’s code will go through the system call interface. The following diagram shows the call trace when esp_rmaker_start() is called from the user app:\nWe can enable this by adding a custom system call as shown below:\nFirstly, we need to implement a system call wrapper in the user app. The name of this wrapper should have usr_ prefix prepended to the system call name. In this wrapper, we use EXECUTE_SYSCALL macro to generate a synchronous exception and land into protected space. __NR_esp_rmaker_start is the macro for a system call number that will be generated by the build system. esp_err_t usr_esp_rmaker_start(void) { return EXECUTE_SYSCALL(__NR_esp_rmaker_start); } NOTE: The build system maps esp_rmaker_start to usr_esp_rmaker_start . This mechanism enables user app to perform a system call by calling esp_rmaker_start.\nNow we need to implement the protected app system call handler. This handler is called after a synchronous exception is generated. Protected handler calls the actual API and returns error code to the user space. esp_err_t sys_esp_rmaker_start(void) { return esp_rmaker_start(); } To bind the user and protected system call implementation, we create a custom system call table in the example directory (examples/ rmaker_switch/components/rmaker_syscall/rmaker_syscall.tbl) . We need to define four attributes in the system call table:1. A unique system call number.2. A common/custom attribute indicator for a system call. Please refer to the documentation for more details.3. System call name.4. Protected system call handler name. 1289 common esp_rmaker_start sys_esp_rmaker_start This system call table file is processed by the build system to create the __NR_esp_rmaker_start macro that thus binds the user-app’s EXECUTE_SYSCALL call to the protected app’s sys_esp_rmaker_start.\nThe above example is just for demonstration purpose. Please refer to rmaker_syscall component for actual implementation.\n5. User app implementation After implementing these system calls, we can use almost all the public APIs provided by ESP-RainMaker in the user app. We have implemented an IoT switch application using the services added in the protected app. The code for user app is available on the GitHub repository.\nComparing ESP Privilege Separation application with a traditional application # From the above numbers, we can observe that the total binary size of the privilege separation application is the same as that of a traditional application.\nAt the expense of little static memory usage, this framework allows us to decouple the monolithic firmware into two separate and isolated applications.\nRunning the application on ESP32-C3 SoC # After the user app startup code registers heap and console, it hands over the control to user_main. user_main function initializes the ESP-RainMaker agent, creates a RainMaker device, and starts the ESP-RainMaker agent in the protected app through the system call interface. The protected app manages Wi-Fi connection and provides all the RainMaker services.\n2. ESP-RainMaker cloud connection: Once Wi-Fi is successfully provisioned and connected, the protected app establishes a TLS connection with the RainMaker cloud. Now our ESP32-C3 device is ready to receive events from the cloud. The protected app receives all the cloud events and triggers user space callbacks based on the configuration.\nFuture Scope # Summary # The ESP-RainMaker switch example is available in the ESP Privilege Separation Repository . Please give it a try and feel free to report any issues or feedback by raising an issue tracker on the GitHub repository.\n","date":"5 July 2022","externalUrl":null,"permalink":"/blog/esp-privilege-separation-a-case-study/","section":"Blog","summary":"","title":"ESP Privilege Separation — A Case Study","type":"blog"},{"content":"","date":"5 July 2022","externalUrl":null,"permalink":"/authors/shubham-kulkarni/","section":"Developer Portal Authors","summary":"","title":"Shubham Kulkarni","type":"authors"},{"content":"Typically, applications on microcontrollers (MCU) are developed as monolithic firmware. We have been discussing on achieving “user-kernel” separation with appropriate execution privileges, like general purpose OS, on MCUs.\nThe crux of this was to make the end application development easier without worrying about the underlying changes in the system, like how applications on desktop/mobile phones are developed: the underlying operating system handles the critical functionalities, and the end application can use the interface exposed by the operating system.\nWe started off with a PoC on ESP32 and realized that there were limitations in it, and we would require some robust hardware support that can enforce permissions at the hardware level to achieve isolation between the user and kernel application. This led us to design our own custom peripherals (described in more details in subsequent section) in ESP32-C3. With all the brainstorming and development done till now, we are excited to release a new framework called ESP Privilege Separation !\nIntroduction # Traditionally, any ESP-IDF application on an Espressif SoCs is built as a single monolithic firmware without any separation between the “core” components (Operating System, Networking, etc.) and the “application” or “business” logic. In the ESP Privilege Separation framework, we split the firmware image into two separate and independent binaries: protected and user application.\nHighlights of ESP Privilege Separation # Supports two isolated execution environments: Secure world and Non-secure world. Separation of monolithic firmware into two independent firmware: protected (secure) application and user (non-secure) application. Protected app is isolated from exceptions in the user app. Standard system call interface through which user application can request access to core services. Maintains consistency with ESP-IDF APIs. Configurable memory and peripheral access. Flexible memory split between protected and user application. Technical Details # 1. Application bootup # In ESP Privilege Separation, the bootup flow is like ESP-IDF application bootup flow, the Boot ROM (1st stage bootloader) verifies and loads the 2nd stage ESP-IDF bootloader from the flash. The 2nd stage bootloader then verifies and loads the protected application. Protected application checks for valid user application header in flash and if found, it sets appropriate permissions and tries to verify and load the user application.\n2. World controller and Permission control # The most important piece of this framework is achieving the separation of privileges and enforcing permissions. This is achieved using World controller and Permission Controller peripherals in ESP32-C3. Permission controller manages the permissions and World controller manages execution environment, where each World has its own permission configuration. Currently, we have 2 Worlds; World0 and World1.World0 is the secure (protected) environment and World1 is the non-secure (user) environment.\nThe above diagram shows that:\nSecure World (World0) has complete access to address range A. Non-secure World (World1) has read only access to address range A. If non-secure World tries to write to any address in range A, then a violation interrupt shall be raised. Secure World handles this violation interrupt and takes appropriate actions.\n3. Switching between Secure and Non-secure Worlds # Switching from Secure to Non-Secure World:CPU can be switched to non-secure world by configuring the address in World controller register. When CPU tries to execute the configured address, it will transparently switch and execute in the non-secure world. Switching from Non-secure to Secure World:CPU can only switch from non-secure to secure world via interrupts or exceptions. Any interrupt in the system will cause the CPU to switch to secure world. 4. Memory Layout # With the permissions enforced, the next step is to split the memory.\nInternal SRAM:\nThe following figure represents how the SRAM is split between protected and user application. SRAM is divided into IRAM and DRAM and this split is entirely configurable and dependent upon the usage of the application.\nThe DRAM region contains the .data and .bss section of the respective application and the remaining DRAM region is used as heap. In this framework, there is a dedicated heap allocator for each, protected and user application.\nThis SRAM memory layout helps maintain memory compatibility when upgrading protected application. If in case IRAM consumption of the protected app increases or decreases, we can move the main IRAM-DRAM split line such that the user boundary is not affected.\nExternal flash:\nThe following figure represents how the Flash virtual memory is split between protected and user application. Like internal memory split, flash MMU range is divided into .rodata and .text sections and is entirely configurable.\n5. System call interface # Protected application provides a standard “system call” interface through which user application can request access to core services. This uses a special CPU instruction that generates a synchronous exception that hands over the control to a protected application. The system call handler carefully checks the request and performs action accordingly. The following diagram gives an overview of how the system call interface is implemented:\n6. API consistency # We have maintained ESP-IDF API consistency, for most of the components, across protected and user app. Components which are exposed to user application through system call interface must use the system call implementation instead of the actual function implementation. We leverage the linker’s attributes to override the API’s definition with the system call definition.\nAPI consistency also ensures that ESP-IDF sample applications can easily (with minimal changes) be ported to this framework. Consistency with ESP-IDF API ensures the same program can be built either as a protected app or as a user app. 7. User space exception handling # With the permissions and the memory split in place, there can be scenarios where the user app, either intentionally or unintentionally, tries to access the forbidden region of protected environment. In this case, the permission controller raises a violation interrupt which can be handled in the protected application. The benefits of having the permissions enforced is that the protected space memory and hence the protected application is not hampered by any (mis)behavior of the user application. In the framework, we have provision for the protected application to register a handler for cases where any exception occurs in the user application. In this handler, we can gather some vital information and handle the exception accordingly.\n8. Device drivers # The user application might need access to peripherals (SPI, I2C, etc.) to communicate with external devices and sensors. In this framework, we have implemented device drivers in protected application and exposed it to user application through standard I/O system calls (open, read, write, etc.). This allows us to implement multiple device drivers through a common set of system calls.\nIt is also possible to provide a peripheral’s register access to the user application and let the user application write its own driver.\nAdvantages # With the ESP Privilege Separation framework, we envision various use cases and scenarios that usually cannot be achieved in the traditional monolithic approach; a few of which we have listed below:\nGetting Started # This project is still in beta phase and active development is being done. There are certain limitations and bottlenecks which are constantly being addressed. Please report any issues and bugs you may encounter.\nThe framework is entirely open-sourced and can be found in our ESP Privilege Separation repository . For detailed technical documentation and walkthroughs please refer here .\nPlease feel free to report any issues or feedback by raising an issue tracker on the GitHub repository. We also welcome contributions to this framework through PRs.\nWe hope this novel approach in application development will open various avenues for you. We are eager to hear your thoughts about this.\n","date":"19 June 2022","externalUrl":null,"permalink":"/blog/introducing-esp-privilege-separation/","section":"Blog","summary":"","title":"Introducing ESP Privilege Separation","type":"blog"},{"content":"","date":"13 June 2022","externalUrl":null,"permalink":"/blog/","section":"Blog","summary":"","title":"Blog","type":"blog"},{"content":"","date":"13 June 2022","externalUrl":null,"permalink":"/events/","section":"Events","summary":"","title":"Events","type":"events"},{"content":"Hi everyone,\nBy heavily investing in R\u0026amp;D, we have developed various series of robust, secure, wireless-communication MCUs which today power more than 700 million devices worldwide. Thus, we have established Espressif as a unique, one-stop, AIoT solution-provider of not just powerful hardware, but also of innovative SDKs, Firmware, Cloud backend, phone apps, and voice integrations.\nAs a valued AWS Technology Partner, Espressif has enhanced the advantages of its unique offerings even further by leveraging AWS’ expertise, global reach, and automatic scaling based on serverless technologies. Espressif’s ESP32, ESP32-C and ESP32-S series of SoCs and modules are qualified for FreeRTOS or AWS IoT, making it easy for customers to select the correct hardware. Additionally, Espressif’s AWS IoT ExpressLink module provides an easy way for customers to use it as an AWS IoT connectivity interface with other MCUs.\nAWS is the world’s most comprehensive and broadly-adopted Cloud platform. Its IaaS (Infrastructure as a Service) offering provides administrators with direct control over operating systems, while the AWS PaaS (Platform as a Service) offers users flexibility and ease of operation. Espressif’s close collaboration with AWS enables us to leverage the complete set of AWS’ Cloud computing services, including Cloud elasticity, storage resources, databases and applications. Having already built numerous AWS-based hardware and software solutions, Espressif has strengthened its portfolio of offerings, successfully meeting a varied range of customer demands, including innovation, security and cost-efficiency.\nEspressif’s ESP RainMaker® provides customers with a one-stop, development-free and maintenance-free AIoT solution for private Cloud deployment, reducing R\u0026amp;D costs and accelerating time-to-market. This service is entirely developed on the AWS Cloud. It provides a comprehensive solution that covers everything from the underlying chip to the device firmware, the third-party voice-assistant integration, mobile apps and the dashboard. The solution works on all Espressif SoCs and modules. This helps our customers accelerate their product launch, while also providing them with full control over their devices, the associated data, and Cloud management. Based on ESP RainMaker, customers will be able to build their own AIoT devices and ecosystem.\nESP RainMaker has adopted the AWS serverless architecture, and has chosen the AWS Lambda and Amazon DynamoDB services for building an elastically scalable resource configuration. Therefore, ESP RainMaker’s demand for AWS Cloud resources adapts to the actual circumstances automatically. This ensures both a low dev-ops overhead and reasonable expenses, since they are proportional to the actual usage of the service. With ESP RainMaker, customers can realize a series of product functions such as device provisioning, control, management, diagnostics and OTA upgrade, which further ensure a reliable operation and a better user experience. Powered by AWS, ESP RainMaker is available in any country and region that is also covered by the services and rapid-deployment features of AWS.\nWe look forward to welcoming more enterprises that will choose to take advantage of our AWS-powered AIoT Cloud solution. By enabling agile product development, reducing R\u0026amp;D costs, and driving greater profitability, ESP RainMaker enables our customers to truly focus on their core offerings. If you want to know more about Espressif’s cooperation with AWS, or if you wish to conduct business with us, please contact our customer support team.\nOther topics you can read about in this month’s newsletter include:\nAnnouncing an AWS IoT Reference Example for ESP32-C3 Espressif is pleased to announce the stable release of esp-aws-iot on GitHub and a reference example for the ESP32-C3, developed in collaboration with the AWS team. The combination of these repositories provides a production-ready starting point for making applications that connect to AWS IoT Core, using esp-aws-iot.\nUpdate on Espressif’s Support for Zephyr Since tracking the development of Espressif’s supportfor Zephyr through commits is somewhat painful, this article aims to provide a clear update on the features we have added recently, and clarify the direction of Espressif’s support for this project in the future.\nThe First Makerspace in Siem Riep! Independent maker, STEM educator and Espressif supporter, Tomoyuki Sakurai, has created the first makerspace in Siem Riep, Cambodia, called “Makers Siem Reap”. Its mission is to provide a place where people with shared interests in electronics and information technology can gather to work on various projects while sharing ideas, equipment, and knowledge.\nRead More \u0026gt;\nHope you enjoy reading this month’s newsletter. Keep sending us your messages and requests on Facebook, Twitter, GitHub, Instagram, LinkedIn, and YouTube.\nYou can also contact us through our website or you can email us. We try to respond to all of your messages as quickly as possible!\nBest wishes,John LeeSenior Customer Support Officer.\n","date":"30 May 2022","externalUrl":null,"permalink":"/blog/may-2022/","section":"Blog","summary":"","title":"May 2022","type":"blog"},{"content":"We had announced the availability of AWS IoT LTS libraries for ESP32 in beta in esp-aws-iot repository in August, 2021. Since then, many of our customers and independent developers have been using these libraries that we have ported and writing applications based on the examples.\nThis beta release of the AWS LTS libraries provided individual examples showcasing usage of a particular AWS IoT related service. It had the following structure:\nWe are pleased to announce the stable release of esp-aws-iot on GitHub and a reference example for the ESP32-C3 developed in collaboration with the AWS team. The combination of these repositories provides a production-ready starting point for making applications that connect to AWS IoT Core using esp-aws-iot.\nThe main features of this release are listed below:\n1. Closer to Production Example # While the standalone examples provided a clear path to use a particular LTS library, it was challenging to build a production application based only on the standalone examples. To address this, we have now made available a reference example for the ESP32-C3 that provides a better starting point. The reference example is built from the ground up to provide a reliable application that can handle and recover from real world cases like MQTT-level disconnections or Wi-Fi disconnections.\nIt also comes baked in with Espressif’s Unified Provisioning that allows you to use our phone apps (available in open source format for Android and iOS and on the Google Play Store and Apple App Store) for providing the Wi-Fi credentials to the device and can be easily extended to send additional information.\nA major goal while designing the reference example, was to allow extensibility and cover a vast majority of real-world scenarios and considerations.\n2. Security Best Practices # One of the important highlights of the reference example is that it is designed with security best practices in mind and provides a comprehensive guide for following them in production use-cases.\nIt makes use of the Digital Signature Peripheral on the ESP32-C3, which provides a hardware root-of-trust and secure storage for certificates. This ensures that the device identity remains protected using hardware security.\nAdditionally, the guide provides steps for production security considerations like enabling Flash Encryption and Secure Boot which are now de-facto features in any secure connected device.\n3. Combination of AWS Libraries and Features # Most of the real world scenarios use not one, but a combination of the AWS LTS libraries. To facilitate these use-cases, the reference example integrates various libraries, like coreMQTT, coreJSON and AWS OTA.\nThe reference example has three integrated functionalities:1. ota_over_mqtt_demo : This demo uses the AWS IoT OTA service for FreeRTOS to configure and create OTA updates.2. sub_pub_unsub_demo : The demo creates tasks which subscribe to a topic on AWS IoT Core, publish a constant string to the same topic, receive their publish, and then unsubscribes from the topic in a loop.3. temp_sub_pub_and_led_control_demo : This demo creates a task which subscribes to a topic on AWS IoT Core. This task then reads the temperature from the onboard temperature sensor, publishes this information in JSON format to the same topic, and then receives this publish in a loop. This demo also enables a user to send a JSON packet back to the device to turn an LED off or on.\nIt is simple to extend the reference example, by adding your own application logic or modifying one of the existing ones to suit your needs.\n4. Libraries as Individual IDF Components # As a side-effect of the restructuring of esp-aws-iot SDK in this context, we now provide ability to use each AWS LTS library as a standalone ESP-IDF component that can easily be added to any example. Each library comes with its own port layer and configuration that is easy to manage for the application.\nGetting Started # esp-aws-iot is currently supported to work on ESP-IDF v4.3 and v4.4 release branches, you can find the steps to install and setup ESP-IDF here.You can find the stable release of esp-aws-iot here and the Getting Started Guide for the reference example for the ESP32-C3 here.\nWe hope that the stable release of the esp-aws-iot repo together with the reference example simplifies and speeds up the development of your applications that connect to AWS IoT Core.\nWe will make the reference example available for other SoCs shortly.\nIf you run into any problems, you can file an issue on the respective repos.\n","date":"11 May 2022","externalUrl":null,"permalink":"/blog/announcing-aws-iot-reference-example-for-esp32-c3/","section":"Blog","summary":"","title":"Announcing AWS IoT Reference Example for ESP32-C3","type":"blog"},{"content":"","date":"11 May 2022","externalUrl":null,"permalink":"/authors/dhaval-gujar/","section":"Developer Portal Authors","summary":"","title":"Dhaval Gujar","type":"authors"},{"content":"Hi everyone,\nAs many of you may have already heard, Shanghai is currently undergoing a major lockdown due to COVID-19. In the midst of this lockdown, we received our production wafers of ESP32-C2, and proceeded with verification. Quarantine rules have caused us some logistics problems, but gradually we managed to find solutions and go ahead with ramping up the design and production of this chip. Also, thanks to Espressifers from Brazil, the Czech Republic, India and Singapore, the integration of ESP32-C2 into ESP-IDF and ESP-RainMaker continues at full speed.\nESP32-C2 is a combo Wi-Fi 4 + Bluetooth 5 ( LE) chip that was conceived during last year’s semiconductor supply shortages which -to a certain extent- persist even today. Hence, one of the most important goals for us in creating this chip was to reduce its silicon area and the flash size requirement. Thus, after almost a year of preparations, the resulting chip targets simple, high-volume, low-data-rate, IoT applications, such as smart plugs and light bulbs.\nESP32-C2 is a chip in a 4mm x 4mm package , with 272 kB of memory . It runs frameworks, such as ESP-Jumpstart and ESP RainMaker® , while it also runs ESP-IDF . ESP-IDF is Espressif’s open-source, real-time operating system for embedded IoT devices, which has been trusted by users across the whole wide world. It is supported by Espressif and the community for all ESP32 chips. The ROM code of ESP32-C2 is optimized, as it reduces the need for flash.\nThus, if you need a small, simple and cheap SoC that is able to provide your application with robust connectivity, ESP32-C2 is the way to go.Besides, ESP32-C2 also continues the tradition of Espressif’s excellent security, having such features as secure boot and flash encryption, while also providing hardware root-of-trust for any applications.\nOther topics you can read about in this month’s newsletter include:\nIntroducing the ESP USB Bridge The ESP USB Bridge is an ESP-IDF project utilizing ESP32-S2 or ESP32-S3 to create a link between a computer and a target microcontroller. It can serve as a replacement for USB-to-UART chips, e.g. CP210x.\nAnalogLamb’s Version of ESP32-S3 Offers a 2 MP Camera, a Mic, and Two LCDs AnalogLamb’s Maple Eye ESP32-S3 is a Wi-Fi-and-Bluetooth dev board based on Espressif’s ESP32-S3dual-core Xtensa LX7 microcontroller. Additionally, it is equipped with one 2MP camera, one microphone, and two LCDs placed on each side of the board.\nTracer: An ESP32-Powered Wearable for Things! Tracer is an open-source, ESP32-based, embedded project created by independent maker elektroThing. Tracer leverages the wide variety of software libraries written for ESP32, allowing tinkerers to gain insight into the necessary processing and algorithms required to develop their very own fitness tracker.\nRead More \u0026gt;\nHope you enjoy reading this month’s newsletter. Keep sending us your messages and requests on Facebook, Twitter, GitHub, Instagram, LinkedIn, and YouTube.\nYou can also contact us through our website or you can email us. We try to respond to all of your messages as quickly as possible!\nBest wishes,John LeeSenior Customer Support Officer.\n","date":"1 May 2022","externalUrl":null,"permalink":"/blog/april-2022/","section":"Blog","summary":"","title":"April 2022","type":"blog"},{"content":" In the earlier version of the ESP Insights Dashboard users could check and analyse device reported metrics, for only up to the past 3 hours.\nWe received developer feedback that they would like to look at the metrics within a particular time frame and most importantly in the time frame around an all important event being investigated viz. a crash or a reboot.\nIn the latest version of ESP Insights Dashboard, a user can play around the metrics data and analyse the issue in more depth using more granular date and time. Using the zoom in feature, zero-in to a very narrow window. Any impacting events that may have an effect on the metrics data are also highlighted viz. a reboot event or a crash.\nDate \u0026amp; Time Selector Widget # Users can now select a particular day with a date picker widget and using the slider select the time span for which metrics are to be investigated. Data correlation with the event logs and the associated device metrics at that given point of time can be achieved in a much better way now.\nEvent Metric Correlation # It is always better to check how a certain event occurrence impacts the metrics values reported by the device or vice-versa. For e.g. after an out of memory situation causing a crash or on reboot, the free heap size memory gets back to the expected baseline state\nAlso on clicking on the vertical event bar, the details of the event (viz. timestamp and the reason and where the crash occurred) are now displayed.\nZoom In # The plotted time series graph now also has the zoom-in capabilities to zero-in on the particular data points in the given time window.\nYou may also use the time range selector at the top to fine-tune the timeframe.\nTry out the new detailed metrics insights by accessing and analysing the device metrics data on the ESP Insights Dashboard.\n","date":"28 April 2022","externalUrl":null,"permalink":"/blog/esp-insights-in-depth-device-metrics/","section":"Blog","summary":"","title":"ESP Insights: In-depth device metrics","type":"blog"},{"content":"","date":"18 April 2022","externalUrl":null,"permalink":"/tags/ceo-blog/","section":"Tags","summary":"","title":"Ceo Blog","type":"tags"},{"content":" As many would have heard, Shanghai is now undergoing a major lockdown and quarantine due to COVID-19. In the midst of this lockdown, we received our production wafers of ESP32-C2, and proceeded with the verifications. Due to the quarantine, we have faced some logistics problems, but slowly, we have improvised, worked out solutions and continue to move ahead with the ramp up of this product. And thanks to Espressifers from Brazil, Czech Republic, India and Singapore, the integration of ESP32-C2 into ESP-IDF and ESP-RainMaker continues at full speed.\nESP32-C2 and Why It Matter-s # ESP32-C2 is a combo WiFi-BLE chip that was conceived middle of last year, at the start of the Great Semiconductor Supply Shortage, which to a certain extent, persists till today. Hence, one of the most important goals of the chip is to reduce its silicon area and the flash size requirement. In short, this chip targets simple high volume, low data rate IoT applications such as smart plugs and light bulbs.\nAfter almost a year, the result is a chip in a 4mm x 4mm package, supporting WiFi 4 + BLE 5.0 with 272 kB of memory and runs ESP-IDF and frameworks such as ESP-Jumpstart and ESP-RainMaker. The ROM code is optimized to reduce the need for flash. ESP-IDF is Espressif’s open-source real-time operating system for embedded IOT devices that now runs on more than 700 million devices. It is supported by Espressif and the community for all ESP32 chips.\nSo, if you need a small, simple, cheap, robust WiFi connection added to your application, ESP32-C2 is it. Besides, ESP32-C2 also continues to have the required security features such as secure boot and flash encryption, and provides hardware root-of-trust for the applications.\nRF Performance # One of the unintended side effects (positive) of this design is that the smaller package and chip enhance the RF performance due to reduced stray parasitics.\nESP32-C2 can transmit 802.11N MC7 packets (72.2 Mbps) with 18 dBm output power. It transmits at the full 20 dBm FCC limit for the lower data rates. The typical receiver sensitivity is between -97 to -100 dBm for 1 Mbps 802.11B packets. The receive current is 58 mA.\nRouters usually have better transmitters than the client devices (referring to the devices connecting to the routers). However, in the case of ESP32-C2, the client devices can transmit as much output power as the router. (We are not talking about the multi-antenna ones.) For most client devices, the output power of 20 dBm is only supported for the low data rate modes, but for ESP32-C2, it is supported for some of the high data rates, and hence reduces the transmission time and improves the overall connection quality in the situation when you have more devices.\nThe maximum distance is determined by the maximum power that the device can transmit, or is allowed to transmit, at the lowest data rate, i.e., 20 dBm at 802.11B 1 Mbps (usually 19.5 dBm or sometimes even lower to have some margins for FCC certification). If your application needs to maximize the physical distance, as with most applications, check out the receive sensitivity and transmit power at 802.11B 1 Mbps of the parts that you are using. ESP32-C2 is at the limits of what is allowed.\nBesides physical distance, larger bandwidths are helpful if you are targeting applications related to audio.\n(Incidentally, the improvements to the RF performance are also inherited by ESP32-C6, which is a WiFi-6 + BLE 5.2 IOT chip that is to be commercially available in late Q3/early Q4.)\nThe Matter Standard # The Matter standard is designed to run on any network stacks that support IP. In the soon-to-be-released Matter 1st release, it supports WiFi, Thread, and Ethernet protocols.\nThe following are the pros and cons of using Matter WiFi vs. Matter Thread:\nWiFi Pros\nLow latency, high throughput Most supported due to the high availability of WiFi routers WiFi Cons\nHigh power consumption, hard to support battery power Without additional mesh protocol, the network is limited in scale and to only one hop Thread Pros\nLow power, support battery power Supports mesh network (up to 250 devices) Thread Cons\nWe need a Thread border router to function. And we still need WiFi connectivity (or some other form of network connectivity). Low throughput, high latency Since WiFi is widely available in most places, the migration of existing WiFi-based devices to the Matter WiFi standard will most likely drive a large part of the early adoption of the Matter standard.\nFor this reason, ESP32-C2, which is a low-cost WiFi chip supporting the Matter standard, matters.\nHow Do I Get Started? # For ESP32-C2 samples, you can contact Espressif at sales@Espressif.com.\nFor other products, you can browse the list of available development kits and modules available from https://www.espressif.com/en/products/devkits and https://www.espressif.com/en/products/modules.\nFor information about ESP-IDF, do visit:\nEnglish : https://docs.espressif.com/projects/esp-idf/en/latest/esp32/get-started/index.html Chinese : https://docs.espressif.com/projects/esp-idf/zh_CN/latest/esp32/get-started/index.html Code : https://github.com/espressif/esp-idf ","date":"18 April 2022","externalUrl":null,"permalink":"/blog/esp32-c2-and-why-it-matter-s/","section":"Blog","summary":"","title":"ESP32-C2 and Why It Matter-s","type":"blog"},{"content":"","date":"18 April 2022","externalUrl":null,"permalink":"/authors/teo-swee-ann/","section":"Developer Portal Authors","summary":"","title":"Teo Swee Ann","type":"authors"},{"content":"","date":"13 April 2022","externalUrl":null,"permalink":"/tags/bridge/","section":"Tags","summary":"","title":"Bridge","type":"tags"},{"content":"The ESP USB Bridge is an ESP-IDF project utilizing an ESP32-S2 (or optionally, an ESP32-S3) chip to create a bridge between a computer and a target microcontroller. It can serve as a replacement for USB-to-UART chips (e.g. CP210x).\nESP USB Bridge creates a composite USB device accessible from the computer when they are connected through a USB cable. The main features are the following.\nSerial bridge: The developer can run esptool or connect a terminal program to the serial port provided by the USB CDC. The communication is transferred in both directions between the computer and the target microcontroller through the ESP USB bridge. JTAG bridge: openocd-esp32 can be run on the computer which will connect to the ESP USB Bridge. The ESP32-S2 acts again as a bridge between the computer and the target microcontroller, and transfers JTAG communication between them in both directions. Mass storage device: USB Mass storage device is created which can be accessed by a file explorer of the computer. Binaries in UF2 format can be copied to this disk and the ESP32-S2 will use them to flash the target microcontroller. Currently ESP USB Bridge is capable of flashing various Espressif microcontrollers. More information about the project can be found on Github. We hope it will be useful for the community. It is licensed under the Apache License Version 2.0. We welcome issue reports, feature requests and contributions on the project’s Github page.\n","date":"13 April 2022","externalUrl":null,"permalink":"/blog/esp-usb-bridge/","section":"Blog","summary":"","title":"ESP USB Bridge","type":"blog"},{"content":"","date":"13 April 2022","externalUrl":null,"permalink":"/authors/roland-dobai/","section":"Developer Portal Authors","summary":"","title":"Roland Dobai","type":"authors"},{"content":"Hi everyone,\nEspressif is taking part in the Smart Home Expo next month in Mumbai, India, which will take place at the Jio World Convention Centre, on 20–21 April 2022. The Smart Home Expo is India’s largest comprehensive trade show and conference that demonstrates the best smart-home technology from across the globe. With over 100+ brands, the exhibition is bound to be an action-packed event featuring the latest market trends, game-changing smart-home technology, live demos, new product launches, technical seminars, as well as exciting new opportunities. The Smart Home Expo in 2022 will also showcase automation technology for offices and hotels.\nEspressif Systems’ participation in the Smart Home Expo will showcase our brand as a one-stop, AIoT solution-provider of not just innovative hardware evidenced by our various series of SoCs, but also of SDKs, Firmware, Cloud backend, phone apps, and voice integrations. The main products we want to highlight in this exhibition are ESP32-C3 (our single-core Wi-Fi-and-Bluetooth 5 LE SoC based on the open-source RISC-V architecture), ESP32-S3 (our dual-core XTensa LX7 MCU with AI capabilities), and ESP RainMaker (our complete system for building AIoT products).\nMore specifically, through our participation in the Smart World Expo we want to address customers who are aware of our ESP32 series of SoCs but use third-party Cloud services. We want these people to know more about ESP RainMaker, our own Cloud offering, and its many advantages including the use of customers’ own private cloud with a pay-as-you-grow economic plan, with easy adoption and deployment, best-in-class data security, voice-integration support, as well as full ownership and platform control.\nSo, those of you who will be in Mumbai on 20–21 April 2022 do come to Espressif’s stall and say “hi” to our representatives there. They will be more than happy to explain all about our innovative AIoT solutions.\nOther topics you can read about in this month’s newsletter include:\nSmarten Up Your Life with ESP32-S3-BOX! To address our customers’ diverse needs, Espressif’s AI voice-development kit now comes in two versions: ESP32-S3-BOX and ESP32-S3-BOX-Lite, a rather simplified variant of the former, but with three additional customizable function buttons. Furthermore, the latest version of ESP-Skainet supports two new functions____ which can materialize a more efficient interactive experience tailored to users’ needs.\nFerrous Systems and Espressif’s Rust Training on ESP32 To consolidate the rising popularity of Rust, Espressif and Ferrous Systems are preparing a complete training program for developers using ESP32. This Rust training focuses on IoT applications in a way that is suitable for new and experienced embedded developers alike.\nRender HTML and CSS on ESP32 Directly Did you know you can easily develop user interfaces on ESP32 by directly rendering HTML and CSS on ESP32? Independent developer Andy Green has achieved just that!\nRead More \u0026gt;\nHope you enjoy reading this month’s newsletter. Keep sending us your messages and requests on Facebook, Twitter, GitHub, Instagram, LinkedIn, and YouTube.\nYou can also contact us through our website or you can email us. We try to respond to all of your messages as quickly as possible!\nBest wishes,John LeeSenior Customer Support Officer.\n","date":"3 April 2022","externalUrl":null,"permalink":"/blog/march-2022/","section":"Blog","summary":"","title":"March 2022","type":"blog"},{"content":"Espressif Matter Series #8\nAs Matter promised, Device Manufacturers (Vendors) don’t have to build their own Phone APP or Cloud service if they don’t want to. A Matter device will be able to work with all Matter enabled ecosystems seamlessly.\nBut how could the Matter device’s information be published, so that it can be retrieved by Matter ecosystems, in a secure manner? Today, we will talk about the Distributed Compliance Ledger (DCL) in Matter.\nWhat is DCL? # The Matter DCL is a cryptographically secure, distributed storage network based on blockchain technology. It allows Connectivity Standards Alliance (CSA) and authorized Vendors to publish information about their Matter devices. This information can then be retrieved using DCL clients.\nWhat kind of information will be stored in DCL?\nThe device information is divided into five databases (it’s called schemas in DCL):\nVendor Schema: Provide general information about a Vendor such as the Company legal name, Preferred brand name associated with the VendorID, the Landing page URL for the vendor, etc. DeviceModel Schema: Provide general information about a device, such as ProductName, Product ID, PartNumber, Commissioning info, etc. This information is shared across all software versions of the product. DeviceSoftwareVersionModel Scheme: Provide software version specific information. e.g Release Notes URL, FirmwareDigests, OTA Software Image URL, etc. Note: Only the URL is stored in DCL, so vendors need to store the OTA images in their own location and only publish the image URL to DCL.\nCompliance Test Result Schema: Provide compliance and test result data about the device. PAA Schema: Provide a list of Product Attestation Authorities Certificates for the approved PAAs (learn more from Matter security model). How will this information be used by Matter ecosystems?\nWith all this device information stored in DCL, Matter ecosystems may consult the DCL for:\nchecking device certification compliance status verifying Device Attestation Certificate (DAC) (by tracing back to it’s PAA) getting commissioning instructions, links to manuals, and product information checking OTA status and upgrade the device to latest firmware …… How DCL Works? # The DCL is a network of independent servers, which are owned and hosted by CSA and its members. Each server holds a copy of the database containing the information about Matter devices, and they communicate with each other using cryptographically secure protocol.\nDoes every Vendor have to setup its own DCL server? No.\nCSA provides DCL server setup, which allows public access to DCL information using DCL client, it also allows members with write access to publish their Matter devices’ information to DCL.\nVendors could also setup dedicated DCL server. The Vendor’s setup will be available to this Vendor’s clients only. A Vendor MAY choose to grant its DCL server access to others.\nWrite access to DCL is restricted\nVendors can add new device models that belong to the VendorID that is associated with the public key of that vendor (either via CSA’s DCL server or its own DCL server). VendorID is associated to the vendor public key during vendor account creation process. Vendors can update a subset of existing device model information, such as product name, product description, firmware and hardware info. Updates are only allowed if the device is associated with the same vendor account. CSA Certification Center can write or revoke the Compliance status of a device model to the Ledger. Read access from DCL is public\nRead DeviceModel info, including firmware and hardware versions from the DCL. Read the Device compliance state from the DCL. Read the Product Attestation Authorities certificates. Typical Workflow # Let’s go through an example, say there are following roles:\nConnectivity Standards Alliance (CSA) Vendor A Bulb B (made by A) Test House T Ecosystem G Ecosystem H Consumer C The typical workflow looks like:\nVendor A is a CSA member and has enrolled its public key to write to DCL. A makes a Matter Bulb B, and uses CSA’s DCL server to add B’s information to DCL. Vendor A sends some Bulbs to Test House T, T performs the Matter certification tests on B, and sends the test results to CSA. CSA checks the test results, if pass, CSA adds the compliance status for Bulb B in DCL. Consumer C buys a Bulb B from the market, C commissions the Bulb B using the commissioner from Ecosystem G, so B joins G’s Matter fabric, and works together with other devices in the same fabric. The commissioner consults the DCL for certification status of Bulb B during commissioning. Someday, A implements a cool feature for Bulb B, A adds the new software version information in DCL. G has Matter OTA provider support in their device, so it can assist B to finish the OTA process. Someday, C is interested in some services provided by Ecosystem H, C commissions the Bulb B to H’s fabric. Then Bulb B can work together with both Ecosystem G and H natively. Consumer C enjoys all these seamlessly.\n","date":"24 March 2022","externalUrl":null,"permalink":"/blog/matter-distributed-compliance-ledger-dcl/","section":"Blog","summary":"","title":"Matter: Distributed Compliance Ledger (DCL)","type":"blog"},{"content":"Espressif IDE is an Integrated Development Environment(IDE) based on Eclipse CDT for developing IoT Applications from end to end using the ESP-IDF(IoT Development Framework). It’s a standalone, customized IDE built specifically for ESP-IDF. Espressif IDE comes with the latest IDF Eclipse plugins, essential Eclipse CDT plugins, OpenOCD Plugins, and other third-party plugins from the Eclipse platform to support building ESP-IDF applications.\nKey features of Espressif IDE # Easy-to-use IDE built on Eclipse CDT environment Specifically built for ESP-IDF application development Integrated esp toolchain configuration for build Offers auto-configuration of the build environment variables Offers new project wizard and getting started ESP-IDF templates Advanced editing, compiling, and editing with syntax coloring features Pre-built function header and function definition navigation Offers to install a new ESP-IDF or configure an existing one ESP-IDF Tools installation and configuration directly from IDE SDK Configuration editor for project-specific settings Integrated CMake Editor for editing CMake files such as CMakeLists.txt CMake based build support Support for UART and JTAG flashing Customized ESP-IDF OpenOCD Debugging with pre-built configuration and settings GDB Hardware debugging support Integrated ESP-IDF serial monitor for viewing program serial output ESP-IDF Terminal with the pre-configured build environment variables Application size analysis editor for analyzing static memory footprint of your application Supports Heap profiling for memory analysis and finding memory leaks Supports GDB Stub debugging on panic mode Provides Application level tracing for analyzing program behavior using start and stop commands Supports ESP32, ESP32-S2, ESP32-S3 and ESP32-C3 chips English and Chinese language support for IDE Extensible IDE for other third-party plugins from Eclipse eco-system Host operating systems supported: Windows, macOS, and Linux What’s new with the v2.4.0 release? # With our recent release of v2.4.0/2.4.1, we have released a bunch of new features, enhancements, and notable bug fixes which greatly improve the quality of the plugin also improve user productivity!\nSource code navigation and linking esp-idf components # IDE offers integrated esp-idf components as part of the projects. When an IDF project is built all the dependent esp-idf components (based on the compile_commands.json) will be linked to the project with folder name esp_idf_components.\nThis will help in two ways. First, the user should be able to browse through the esp-idf source code directly under the eclipse project explorer. Second, It allows navigating to the function definitions by pressing F3 or ctrl+ click(in macOS command+click) on the function name.\nIndexer Improvements # One of the challenging issue with the IDE was unresolved headers and indexer problems. Though the project was able to build successfully the eclipse plugin was used to show errors in the source code editors. With the v2.4.0 release, we have optimized the indexer to find the headers based on the compile_commands.json defined components and resolve the functions.\nAs soon as the build finishes, the plugin will trigger linking esp-idf components and indexing all the files listed in it. This might take a couple of seconds based on the host system. These files located in the *esp_idf_components *folder are linked virtually to the esp-idf components folder and this list is refreshed every time after the build.\nApplication level tracing # ESP-IDF provides a useful feature for program behavior analysis called Application Level Tracing. IDE has UI, that allows using start, stop tracing commands and process received data. To familiarize yourself with this library, you can use the app_trace_to_host project.\nBefore you start using application-level tracing, it is important to create a debug configuration for the project where you must select the board you are using in order to successfully start the OpenOCD server.\nAfter debug configuration is created, right-click on the project in the project explorer and click on ESP-IDF: Application Level Tracing\nIt can take a while to open the application level tracing dialog because the OpenOCD server starts first, so you don’t need to start it externally. At the very top of the application-level trace dialog, there are auto-configured fields that you can change for the trace start command.\nTrace Processing Script and Start Parsing Command are used to parse the output file. The first one is used to provide the path to the parsing script, by default it is logtrace_proc.py from esp-idf. In the second field, you can check the resulting parsing command and edit it if it’s necessary. By default, this field is automatically configured to match $IDF_PATH/tools/esp_app_trace/logtrace_proc.py/path/to/trace/file/path/to/program/elf/file.\nThe Start parse button is disabled until a dump file is available. To generate it, click the Start button at the bottom of the dialog box. After you click, the button changes to Stop so that you can stop tracking.\nWhen the output file is generated, you can click on the Start parse button and you will see parse script output in the eclipse console.\nAdditional information can be found here.\nApplication memory usage in the build console # Keeping track of memory usage is an important aspect of IoT applications. Now after the build, you should be able to see the application RAM and flash usage information.\nESP-IDF Components Registry # IDE offers to browse and install esp-idf components from the IDF registry and allows you to integrate them into your existing ESP-IDF project.\nRight-click on the project from project explorer in which you want to add the component to and Select Install ESP-IDF Components, this will show up all the available components in the UI.\nFrom the window, you can click on the Install button to add that component to the project. To get to the readme file for that component you can click on More Info which will open the browser link to the readme file of that component.\nGDBStub Debugging # IDE offers to diagnose and debug esp-idf applications using GDBStub debugging on-chip when it’s in panic mode.\nTo enable GDBStub debugging for a project you need to enable it first in the sdkconfig. Launch the sdkconfig in project root by double-clicking on it which will open the configuration editor. Expand the Component Config section and select ESP System Settings. From the settings on the right for Panic Handler behavior select the GDBStub on Panic option from the list\nNow you will be taken to the GDBStub debugger automatically when you connect the serial monitor and there is a panic for this example create a template hello_world project and add the following lines in the main c file.\nThis is a global variable* COREDUMP_DRAM_ATTR uint8_t global_var;*\nNow add these two lines just above esp_restart() function global_var = 25; assert(0);\nThe final file should be something like this.\nBuild and flash the project and launch the serial monitor. On line number 45 we are signaling for a failing assert which will put the chip in panic mode and when that line reaches you will be prompted to switch the perspective to debug mode and the chip will be halted, remember that this is a panic mode and you cannot continue the execution from here you will have to stop and restart the chip through IDF commands or simply restart the serial monitor.\nYou can view the registers stack trace and even view the value of variables in the stack frame. To exit the debug session simply press the stop button.\nEspressif Menu # All the plugin contributed menu items are moved into the Espressif Menu and this will improve the user experience and easy accessibility!\nEclipse 2021–12 Support # IDF Eclipse plugin supports the latest version of Eclipse 2021–12(4.22) along with the Eclipse 2021–09 and Eclipse 2021–06.\nThere are many other improvements and bug fixes that are part of the v2.4.0 release. Please check our v2.4.0 and v2.4.1 release pages for more details.\n","date":"1 March 2022","externalUrl":null,"permalink":"/blog/espressif-ide-and-whats-new-in-v2-4-0-part-1/","section":"Blog","summary":"","title":"Espressif IDE and What’s new in v2.4.0 — Part 1","type":"blog"},{"content":"This section will talk about Espressif IDE installation options that are available and platforms supported.\nEspressif IDE supports Windows, macOS, and Linux platforms. Please find the download links below to get started.\nEspressif-IDE-2.4.1-win32.win32.x86_64.zip\nEspressif-IDE-2.4.1-macosx.cocoa.x86_64.tar.gz\nEspressif-IDE-2.4.1-linux.gtk.x86_64.tar.gz\nmacOS security notice # On macOS, if you download the Espressif-IDE archive with the browser, the strict security checks on recent macOS will prevent it to run, and complain that the program is damaged. That’s obviously not true, and the fix is simple, you need to remove the com.apple.quarantine extended attribute.\n*$ xattr -d com.apple.quarantine ~/Downloads/Espressif-IDE-2.4.1-macosx.cocoa.x86_64.tar.gz* After un-archiving, if the application still complains, check/remove the attribute from the Espressif-IDE.app folder too:\n*$ xattr -dr com.apple.quarantine ~/Downloads/Espressif-IDE.app* Espressif-IDE v2.4.0 Installer (All-in-one package) for Windows OS # Espressif-IDE Installer is an offline installer and it comes with all the required components to work with the ESP-IDF Application development.\nThe installer deploys the following components:\nESP-IDF v4.4 Espressif-IDE (based on Eclipse 2021–12) Amazon Corretto OpenJDK 11.0.14 Drivers — FTDI chip, WinUSB support for JTAG Embedded Python Cross-compilers OpenOCD CMake and Ninja build tools As Installer bundles, all the required components and tools including stable esp-idf so people behind corporate firewalls can use the whole solution out-of-box. This also configures all the required build environment variables and tool paths as you launch the IDE. All you could do is to get started with your project directly without manually configuring anything. This will give you a big boost to your productivity!\nThe All-in-one installer option is a recommended approach if someone trying for the first time in Windows OS or has challenges in installing tools.\nEspressif-IDE Installer for Windows OS is available here for download. The latest version of Espressif-IDE is v2.4.1 but you get as part of the installer is v2.4.0 so one has to update to the latest using the update site\nInstallation instructions are similar to what is described here for the ESP-IDF Tools installer. Always prefer *Full Installation *during the setup.\nOnce the installation completes you could launch the Espressif-IDE from the desktop shortcut and this will pre-configure everything required to build the ESP-IDF project.\nWhen you launch the IDE for the first time it will pop up with the Welcome page!\nTo verify Installed tools version and product information in general, you could navigate to the *Espressif *menu and click on the *Product Information *option.\nOnce you’re able to see all the tools, IDF_PATH, IDF_PYTHON_PATH, PATH, and other environment information correctly in the console, you are set to get started with the HelloWorld project!\nCheck our IDE documentation page for more information!\nHappy coding!\n","date":"1 March 2022","externalUrl":null,"permalink":"/blog/espressif-ide-and-whats-new-in-v2-4-0-part-2/","section":"Blog","summary":"","title":"Espressif IDE and What’s new in v2.4.0 — Part 2","type":"blog"},{"content":"","date":"1 March 2022","externalUrl":null,"permalink":"/tags/idf-eclipse-plugin/","section":"Tags","summary":"","title":"Idf Eclipse Plugin","type":"tags"},{"content":"","date":"1 March 2022","externalUrl":null,"permalink":"/tags/v2.4.0/","section":"Tags","summary":"","title":"V2.4.0","type":"tags"},{"content":"","date":"1 March 2022","externalUrl":null,"permalink":"/tags/v2.4.1/","section":"Tags","summary":"","title":"V2.4.1","type":"tags"},{"content":"Hi everyone,\nVersion 4.4 of Espressif’s IoT Development Framework (ESP-IDF v4.4) has recently been released, adding full support for the ESP32-S3 SoC and preliminary support for the ESP32-H2 SoC.\nThe purpose of ESP-IDF has always been to create a simple, easy-to-use, open-source development environment which helps users take full advantage of the powerful hardware and software solutions that Espressif offers. Thus, ESP-IDF integrates real-time operating systems, peripheral drivers, network protocol stacks, such as Wi-Fi and Bluetooth, program libraries, and development tools, while being accompanied by copious documentation, examples of use cases, and other relevant resources. As a result, there are already millions of Espressif IoT devices in use across the whole wide world.\nEspressif is committed to constantly enhancing the capabilities of its software and hardware solutions. On this note, Teo Swee Ann, Founder and CEO of Espressif Systems, said: “Although innovation often begins with bursts of creativity and inspiration, it eventually comes to fruition after sustained hard work, perseverance and well-coordinated team work. This is the kind of work that our R\u0026amp;D team performs, always aiming at constant improvement. We attach great importance to user experience and, therefore, we continuously collect developer feedback, we evaluate it, and we optimize our products, solutions and services accordingly”. ESP-IDF is now a mature platform, with a rigorous release process and a strong support strategy, which ensures software stability and hassle-free mass production. If you have any suggestions for ESP-IDF, please give us your feedback via the ESP32 forum or the ESP-IDF GitHub repository.\nOther topics you can read about in this month’s newsletter include:\nNew Features of the ESP-IDF-VS Code Extension The ESP-IDF extension of Visual Studio Code aims at helping developers write code based on ESP-IDF and Espressif SoCs. In the following article, you can find the latest features we have added.\nESP32-C3-based M5Stamp C3U Released The ESP32-C3-based M5Stamp C3U has just been released. With a 32-bit RISC-V microcontroller, a 400 KB internal RAM, and a 4 MB Flash, it operates at a maximum clock frequency of 160 MHz, facilitating a variety of use cases.\nAirTag-like Device Based on ESP32 Get to know how independent maker, Eric Nam, created the ESP32Tag, which works similarly to Apple’s AirTag!\nE SP32-Powered DIY Smartwatch An independent maker known as “rahmanshaber” recently presented an ESP32-WROOM-powered, open-source smartwatch, called MutantW.\nRead More \u0026gt;\nHope you enjoy reading this month’s newsletter. Keep sending us your messages and requests on Facebook, Twitter, GitHub, Instagram, LinkedIn, and YouTube.\nYou can also contact us through our website or you can email us. We try to respond to all of your messages as quickly as possible!\nBest wishes,John LeeSenior Customer Support Officer.\n","date":"28 February 2022","externalUrl":null,"permalink":"/blog/feb-2022/","section":"Blog","summary":"","title":"Feb 2022","type":"blog"},{"content":"","date":"28 February 2022","externalUrl":null,"permalink":"/tags/version-4.4/","section":"Tags","summary":"","title":"Version 4.4","type":"tags"},{"content":"","date":"24 February 2022","externalUrl":null,"permalink":"/authors/guo-jiacheng/","section":"Developer Portal Authors","summary":"","title":"Guo Jiacheng","type":"authors"},{"content":"Espressif Matter Series #7\nMatter is a protocol designed with security and privacy in mind. Cryptography is widely adopted in Matter to ensure:\nTrusted devices Trusted controllers Private communication In this post we will go through the Matter security model and investigate how these targets are accomplished in Matter.\nIntroduction to Public Key Infrastructure # The Matter security model is based on Public Key Infrastructure(PKI), a cryptographic mechanism widely adopted in the Internet. When you visit a website via https, the connection is secured by the site’s certificate.\nHere is the certificate chain of www.espressif.com:\nThe certificate chain is hierarchical structure. Each certificate in the chain is signed by its issuer, tracing back to the root certificate. A site will be trusted if its certificate can trace back to one of the trusted root certificates stored in the browser.\nThe PKI works together with session establishment protocols to achieve some key cryptograpic goals:\nIdentification : The peer’s identification will be verified by the signature of its issuer. Data privacy \u0026amp; integrity : All communication will be encrypted by a unique key independently negotiated for each session. In the following part of the aritcle, we’ll see how Matter facilites the PKI to achieve different security goals and how certificates are distributed among your apps and devices.\nCertificates in Matter # Device Attestation Certificate: Is the device what it claims to be? # All matter devices will be shipped with a unique Device Attestation Certificate (DAC). This certificate guards you against fakes: You can say with confidence the device comes from the brand on its box. This device identity authentication comes from the certificate chain of the DAC.\nThe DAC is signed by the Product Attestation Intermediate (PAI) certificate. This certificate will be typically held by the device manufacturers. The PAI certificate in turn is signed by the Product Attestation Authority (PAA) certificate. This PAA certificate acts as the root CA and provides root of trust. The list of trusted PAA certificates are stored in the Distributed Compliance Ledger (DCL), a distributed storage provided by the Connectivity Standard Alliance. We’ll have an in-depth article about DCL in the following posts.\nThe DAC and the PAI is burnt to the persistent storage of the device during manufacturing. During the commissioning process, the controller will retrieve them and verify the certificates as well as the Vendor/Product information shipped with the certification. Such verification step guarantees that all commissioned Matter devices are trusted.\nNode Operational Credentials: Who do I talk to? # Public key certificates are also used to authenticate the peer and ensure data privacy and integrity in the Matter protocol. The key used in this scenario is the Node Operational Crendential (NOC).\nThe NOC can be signed by an Intermediate Certificate Authority (ICA) or be directly signed by the Root Certificate Authority (RCA). The RCA is typically generated by the commissioner. During the commissioning process, the NOC and the RCA are installed to the device.\nWhen the app or another device connects to the device, the certificate information will be exchanged. The devices will trust each other if they share the same root certificate. Devices with same root certficate thus form a Matter fabric . After the certificate information exchange, an encrypted session will be established between the peers.\nBringing it all together: Commissioning # The device commissioning process configures an out-of-box device. It authenticates the device, sets up the network and installs the NOC to the device storage.\nOnce the device is powered, it will advertise itself via BLE advertisement or DNS-sd service advertisement. When the controller receives the advertisement, it will try to establish an encrypted session with the device based on the pairing code. This process is called Password Authenticated Session Establishment (PASE) in Matter. Typically the app will scan a QR code to retrieve the unique pairing code of the device, in the PASE process.\nAfter setting up the PASE session, the controller will check the DAC of the device. Once the device attestation certificate is authenticated, a new NOC will be signed and installed to the device. The controller will also tell the device about the Wi-Fi or the Thread network to join. Once the device has been correctly configured, the PASE session will be closed. All the following communications will be based on the certificate. The new session is called Certificate Authenticated Session Establishment (CASE) in Matter.\nIn a CASE session, the peers exchange their certificate information with salts to authenticate each other and negotiate a credential for symmetric encryption. All the control commands are protocted with this negotiated key.\nThe following diagram contains a typical flow for pairing a Matter device out-of-the-box.\nThat summarises how PKI forms an integral part of the Matter specification.\nThis article is a part of a series of articles Espressif Matter Series.\n","date":"24 February 2022","externalUrl":null,"permalink":"/blog/matter-security-model/","section":"Blog","summary":"","title":"Matter Security Model","type":"blog"},{"content":"","date":"30 January 2022","externalUrl":null,"permalink":"/tags/theia/","section":"Tags","summary":"","title":"Theia","type":"tags"},{"content":"Co-authored with Kondal Kolipaka\nThe ESP-IDF extension for Visual Studio Code aims to help users to write code with Espressif chips using ESP-IDF and other frameworks. We constantly try to improve the extension usability and add features to enhance the user developing experience.\nThe latest features we have added are:\nESP-IDF QEMU integration\nQEMU is an open-source machine emulator commonly used to emulate operating systems and many hardware devices. Espressif has a QEMU fork with ESP32 as a possible target which can be used to emulate in software the behavior of a real ESP32 device.\nWe added this QEMU fork in a Dockerfile used with the project template file .devcontainer (You can add these files to an existing project with the ESP-IDF: Add docker container configuration command) so the user can open a project in a container using the Remote-Containers: Open Folder in container… command____ from the Remote Containers extension.\nThe ESP-IDF: QEMU Manager command____ will____ run the current project application binary in an emulated ESP32. If you execute the ESP-IDF: Monitor QEMU device it will open____ a monitor session to observe the application output. You can also use ESP-IDF: Launch QEMU debug session command to start a debug session as shown below.\nFind more information on this feature in here.\nPartition Table Editor\nNow you should be able to get partition table information for the device connected and be allowed to select any .bin file to flash to a given partition.\nTo see the partitions of the current serial port, execute the ESP-IDF: Refresh partition table and use the sdkconfig partition offset or a custom partition offset to see the current partitions of your device in the ESP-IDF Explorer tab.\nWhen you can click on any partition, either you can flash a .bin file to this partition or launch the ESP-IDF: Partition Table Editor UI to edit the partition table. You could also right-click on the .bin file to flash it to one of the partitions in the Device partition explorer.\nImporting an existing ESP-IDF Project\nAdded the Import ESP-IDF Project command to the extension. This command will copy an existing ESP-IDF project and add .vscode configuration and .devcontainer files into a new project to be saved in a given location and project name.\nIntegrated ESP-IDF Component registry\nIDF Component registry is integrated into the extension and this allows users to add a component to your project. Run the ESP-IDF: Show Component registry command____ to launch components page.\nIDF Component Registry running in Visual Studio Code\nWelcome Page\nAdded a new welcome page with documentation links and buttons for basic features of the extension. You can run the ESP-IDF: Welcome command to launch it.\nOther notable improvements and features\nUse gdb commands directly for Heap tracing. Before we were using openOCD TCL commands to start and stop the heap tracing but now we are using gdb commands with a gdb file instead. To learn more about heap tracing please review the ESP-IDF documentation and the heap tracing extension tutorial. Added idf-size.py output after build task. This is done after executing the ESP-IDF: Build your project or__ESP-IDF: Build, flash and start a monitor__ command. This will help users to understand the amount of memory used in their applications and reduce the binary size. Added JTAG flashing type in the Build, flash and monitor command. Before it was only using UART flashing, but now it will use the flash type defined in the idf.flashType configuration setting. Added the Configure project for coverage command to set the required values in your project’s sdkconfig file to enable code coverage for your project. This is necessary if you want to enable the code coverage feature in the extension as shown in the code coverage tutorial. Using portable git and python in the extension setup workflow for Windows users. Now Windows users don’t need to install any prerequisites when configuring the extension using the ESP-IDF: Configure ESP-IDF extension setup wizard. Enable and disable CMakeLists.txt SRCS field update whenever .c files are created or deleted. Use the i__df.enableUpdateSrcsToCMakeListsFile__ configuration setting to enable and disable it. Use Espressif download mirrors for the extension setup wizard. Now if downloading from Github is slow in your location you can choose the download server in the ESP-IDF: Configure ESP-IDF extension setup wizard. Added serial port and IDF target in the VSCode status bar and add the commands to change them on click. Now users are allowed to configure pre-build, post-build, pre-flash, post flash, and custom tasks (with status bar icon for the custom task) with added configuration settings. You can use the idf.preBuildTask to define a task before the build task, the idf.postBuildTask after the build task, the idf.preFlashTask before the flash task and the__idf.postFlashTask__ after the flash task. There is also an idf.customTask which can be used with the ESP-IDF: Execute custom task (which has a status bar icon). Now you should be able to control the settings to enable/disable notifications for extension commands completion and show the task output when hidden. Using the idf.notificationSilentMode configuration setting to true will hide VSCode notifications from this extension such as Build Successful and flash done and show the task output directly. ESP-IDF cloud IDE based on Eclipse Theia # We are fascinated to build robust tools and IDEs to improve the productivity of esp-idf developers by leveraging the latest cloud technologies.\nEclipse Theia is an extensible framework to develop full-fledged multi-language Cloud \u0026amp; Desktop IDE-like products with state-of-the-art web technologies. It offers to install our existing IDF VSCode extension and work seamlessly.\nWe have been working on this for quite some time and we have shown this work-in-progress model during EclispeCon 2021 conference. It’s an internal project for now! Please take a look to see what it means to be working on Eclipse Theia cloud IDE and what it offers.\nWhat’s next? # The extension is far from complete. We are continuously improving existing and adding new and interesting features for you! Some of the things we are looking into are:\nExtend QEMU and features related to emulated devices. Improve the heap tracing UI and functionality Extend debugging experience adding registers and memory view, disassemble view, and data watchpoints. Integration with new frameworks such as NuttX and Matter Many more! Related links # Make a feature request or report an issue with the extension Extension tutorials ESP32 IDE Forum Espressif also offers an esp-idf plugin for eclipse enthusiasts, please check this out here!\n","date":"30 January 2022","externalUrl":null,"permalink":"/blog/whats-new-in-the-esp-idf-extension-for-vscode/","section":"Blog","summary":"","title":"What’s new in the ESP-IDF extension for VSCode","type":"blog"},{"content":" ESP Insights was released in its Beta in July 2021 and is being actively used by the ESP developer community. You can read more about it in the blog post Introducing ESP Insights. With this new version of the ESP Insights service, we introduce following new features, plus a few UI enhancements and stability fixes.\nSupport for HTTPs/REST API based device communication Group Analytics Let’s look at these new features in more detail.\nHTTPS Transport # When we launched ESP Insights, we borrowed some concepts from ESP RainMaker, especially the concept of “Claiming” and used MQTT as the transport so that we could leverage a single connection for RainMaker and Insights. However, for applications that only want to use ESP Insights without ESP RainMaker, the claiming concept is an unnecessary step.\nWe now support HTTPs/REST API based Insights communication as well. Instead of using unique X.509 key-certificate pairs, a single HTTP API key can now be used by multiple nodes , thereby simplifying the setup and management of devices.\n(Note that given the always-on connectivity of MQTT, some of the features that we introduce in the future may be more optimised for MQTT based transport)\nEnabling Insights with HTTPS # Enabling ESP Insights in your firmware is now as easy as adding the following lines of code in your application:\nThis code should get your started, and your application can start reporting ESP Insights data to the Insights cloud. As you may have noticed, all you will need is the unique ESP_INSIGHTS_AUTH_KEY to be embedded in your firmware. Here is how you can obtain the ESP Insights Auth Key:\nSign up or Sign in on ESP Insights Dashboard Visit Manage Auth Keys and generate an Auth Key Copy the Auth Key to your firmware Once device boots up look for following logs that contains the Node ID. You may use this node id for monitoring node logs, crashes, reboots, metrics, and variables through the ESP Insights Dashboard.\nI (4161) esp_insights: ========================================= I (4171) esp_insights: Insights enabled for Node ID 246F2880371C I (4181) esp_insights: ========================================= For more details please check our getting started guide.\nGroup Analytics # So far ESP Insights supported diagnostics at a node level, reporting any abnormal events as well as metrics and point in time variable values for individual nodes.\nThe latest version of ESP Insights introduces group analytics, that provides insights into how groups of your devices are performing. You may group devices based on the Project, Project Versions or Event categories.\nCompare the firmware insights across different versions of a project A very high-level insights starting at a project level and can be drilled down to an event category A few examples of group based data that you can observe:\nCounts grouped by events (for e.g., Errors) for a particular project and version, in a selected time interval. You can change the interval to hour or aggregate to week or a month interval Distribution of event counts (for e.g., crash counts) for a group in a selected time interval. Distribution of event (for e.g. Reboot reason) counts for a group in a selected time interval. You can drill down further on the reboot reason and get to the nodes which are reporting the particular event. Count of unique nodes which are reporting certain events (reboots / errors / warnings) in a selected time interval List of top nodes having the most number of events and can be drilled down to category level We are working on some more exciting features on top of ESP Insights, stay tuned to hear more!\n","date":"26 January 2022","externalUrl":null,"permalink":"/blog/esp-insights-whats-new/","section":"Blog","summary":"","title":"ESP Insights — What’s new","type":"blog"},{"content":"Espressif Matter Series* #6*\n[This is article #6 in the Espressif Matter Series of articles. You may read the first part here.]\nIn the previous articles we talked about Matter devices communicating with each other by themselves, or Matter devices participating in multiple ecosystems simultaneously.\nAs you can see in the image here, this lightbulb is part of 2 distinct ecosystems, green and red. Each of these ecosystems don’t know about the other, and they are powered by 2 separate organisations (Org1 and Org2).\nThis feature, called multi-admin, is a much desirable feature of the smart-home. This is particularly desirable because people in the same family/home may be comfortable with their own ecosystems of choice, and would love the same device be part of all of these.\nThe question is how do these devices identify and authenticate themselves to each other, and who controls this configuration? This is the topic of today’s article.\nOperational Credentials # Matter uses PKI to facilitate identity.\nEvery node in a Matter network has a Node Operational Certificate (NOC) . This X.509 certificate encodes a unique identifier (Node Operational Identifier) that is used to identify this node on the network.\nWhen a Matter node is part of multiple ecosystems, it has multiple of these Node Operational Certificates (one for each ecosystem it supports). As you may notice in the diagram below, the lightbulb, has two NOCs and hence has 2 Node Identifiers, xyz for the green ecosystem and PQR for the red ecosystem.\nThe NOC and the node identifier are valid within the scope of that particular ecosystem which it is a part of. In Matter terminology, this is called a Matter Fabric . Thus in the above diagram the lightbulb is part of 2 Matter fabrics, and it has a node id *xyz *in Matter fabric green, and node id *PQR *in Matter fabric red.\nA Matter node’s resources (CPU/RAM) may decide how many simultaneous Fabrics can it support.\nEvery Fabric will also have a Root CA Certificate associated with it. This CA certificate is used to validate the identities of other nodes (validate other’s NOCs) in the Fabric. For example, the green Fabric’s Root CA Certificate is what the lightbulb will use to validate that a request is really coming from the node id *abc *on the green fabric.\nCommissioning # Now who does the configuration of the Fabric, the NOC and the Root CA Certificates on a Matter node?\nEvery Matter node begins its participation in a Matter network after it is commissioned (the initial configuration of the device) by a commissioner (say a phone app that configures the device).\nDuring the process of commissioning, the commissioner will provide the node with the Node Operational Certificate (NOC) and the Trusted Root CA Certificate. This is when we say that the bulb has joined the Matter Fabric green (technically Matter Fabrics have a 64-bit identifier, we are just using green for convenience here).\nThe Second Matter Fabric # How does the device then join the second Matter Fabric?\nIf you are the admin of a Matter device, you could ask the device to open up its commissioning window again, after it has been commissioned. This allows other ecosystems to commission the Matter node and make it part of their own Matter Fabric.\nAccess Control List # Once any node can verify identities on the network, the other step is Access Control. Every Matter node has an Access Control List which specifies who (which NOC) can do what (read/write/invoke on endpoint x, cluster y) on this Matter node.\nWhen a Matter phone app controls a Matter lightbulb,\nthe lightbulb will have a set of permissions defined through ACLs when an action is executed on the lightbulb, the lightbulb will first verify the identity of the phone app using the phone app’s NOC and the Trusted Root CA that was installed on the bulb the lightbulb will then check the ACLs to ensure that this Node Identifier (the phone app) is allowed to perform the specific action Matter Ecosystems # As highlighted above, Matter ecosystems allow you to create and distribute Node Operational Certificates to devices and thus build a Matter Fabric of participating devices. You may build additional innovative features on top of these.\nThese features could be allowing remote control of these devices, controlling these devices through your own display controller, or say, a voice controller.\nEspressif is working on creating a solution for Matter ecosystems that you can deploy as your own Matter ecosystem. This solution will incorporate all the building blocks that will be required to build such an ecosystem, with hooks provided to extend it further to add any innovative features that you have in mind. Please reach out through our sales channels for more information on the same.\n","date":"18 January 2022","externalUrl":null,"permalink":"/blog/matter-multi-admin-identifiers-and-fabrics/","section":"Blog","summary":"","title":"Matter: Multi-Admin, Identifiers, and Fabrics","type":"blog"},{"content":" [If you have been following the Espressif blogs and announcements, you must already be aware of ESP RainMaker and its various features. If not, please check out the info here so that you get an idea about what ESP RainMaker is before you proceed further.]\nOne important aspect of RainMaker is that the cloud is very thin and acts as a tunnel between the ESP nodes and clients like mobile phones, Alexa, GVA, etc. This makes it very flexible and extensible allowing users to create any type of device with any kind of functionality and access it from the phone apps. There are some defaults that we have defined, but they are not mandatory to use and you can create your own device/param types.\nThe functionality that a RainMaker node supports is communicated by the node using something called as the node configuration. This, broadly has 2 parts.\nMost RainMaker users are now well versed with the concept of devices since they are very much visible in the examples. However, the concept of “services” may not be clear because it is hidden under the APIs like esp_rmaker_system_service_enable(), esp_rmaker_schedule_enable() or esp_rmaker_timezone_service_enable() and used internally by the phone apps.\nStructurally, a service is very similar to a device. It has a “name” and “type” and a set of parameters. That’s one reason why all device specific APIs are applicable even to services. This applies not just to the firmware APIs, but even to the cloud APIs. The same GET /user/nodes?node_details=true, GET /user/nodes/config and GET/PUT /user/nodes/params APIs that are used for devices are applicable for services.\nYou can find some standard services here, but the purpose of this post is to help understand how to add your own custom service.\nDefining the Use Case # Naturally, before you even write a service, you need to define your use case, which will then help you define the parameters of the service. Let’s consider a use case of “Diagnostics” wherein you want the users to trigger some diagnostics on the node and get the diagnostic data in the phone app.\nCreating the service # The code snippet below is the minimal code required to create a service. It basically has 4 components\nIf the overall number of values in diagnostic data is small, it would be ok to define separate integer/bool/float/string parameters for each (“Timestamp” in above example). But if the data is going to be large, it is recommended to use an “object” type (“Data” in above example) and then pass whatever JSON object you want.\nCreating the service. Registering a callback. Creating and adding parameters as applicable. Adding it to the node. /* Create the service using esp_rmaker_service_create(). However, note that a service uses esp_rmaker_device_t * as the data type, since it is structurally same as a device. */ esp_rmaker_device_t *diag_service = esp_rmaker_service_create(\u0026#34;Diagnostics\u0026#34;,\u0026#34;my.service.diag\u0026#34;, NULL); /* Register the write callback. Read callback would normally be NULL */ esp_rmaker_device_add_cb(diag_service, diag_write_cb, NULL); /* Create and add paramaters of various types as applicable. * Parameter types (like my.param.diag-trigger) are not mandatory, but useful to have. */ esp_rmaker_device_add_param(diag_service, esp_rmaker_param_create(\u0026#34;Trigger\u0026#34;, \u0026#34;my.param.diag-trigger\u0026#34;, esp_rmaker_bool(false), PROP_FLAG_WRITE)); esp_rmaker_device_add_param(diag_service, esp_rmaker_param_create(\u0026#34;Timestamp\u0026#34;, \u0026#34;my.param.diag-timestamp\u0026#34;, esp_rmaker_int(0), PROP_FLAG_READ)); esp_rmaker_device_add_param(diag_service, esp_rmaker_param_create(\u0026#34;Data\u0026#34;, \u0026#34;my.param.diag-data\u0026#34;, esp_rmaker_obj(\u0026#34;{}\u0026#34;), PROP_FLAG_READ)); /* Add the service to the node */ esp_rmaker_node_add_device(node, diag_service); Note that none of these parameters are mandatory and are shown just for reference.\nThe above service will show up in the node configuration as this object under the services array:\nSimilarly, the following will show up in the node parameters object\nHandling Service callbacks # As you can see in the code snippet above, we have registered diag_write_cb as the service write callback. Let us see a sample implementation of this.\n#include \u0026lt;json_generator.h\u0026gt; static esp_err_t diag_write_cb(const esp_rmaker_device_t *device, const esp_rmaker_param_t *param, const esp_rmaker_param_val_t val, void *priv_data, esp_rmaker_write_ctx_t *ctx) { /* This ctx check is just to find if the request was received via Cloud, Local network or Schedule. * Having this is not required, but there could be some cases wherein specific operations may be allowed * only via specific channels (like only Local network), where this would be useful. */ if (ctx) { ESP_LOGI(TAG, \u0026#34;Received write request via : %s\u0026#34;, esp_rmaker_device_cb_src_to_str(ctx-\u0026gt;src)); } /* Check if the write is on the \u0026#34;Trigger\u0026#34; parameter. We aren\u0026#39;t really checking true/false as that * is not much of a concern in this context. But you can add checks on the values too. */ if (strcmp(esp_rmaker_param_get_name(param), \u0026#34;Trigger\u0026#34;) == 0) { /* Here we start some dummy diagnostics and populate the appropriate values to be passed * to \u0026#34;Timestamp\u0026#34; and \u0026#34;Data\u0026#34;. */ ESP_LOGI(TAG, \u0026#34;Starting Diagnostics\u0026#34;); time_t current_timestamp = 0; time(\u0026amp;current_timestamp); char buf[100] = {0}; json_gen_str_t jstr; json_gen_str_start(\u0026amp;jstr, buf, sizeof(buf), NULL, NULL); json_gen_start_object(\u0026amp;jstr); json_gen_obj_set_bool(\u0026amp;jstr, \u0026#34;diag1\u0026#34;, true); json_gen_obj_set_int(\u0026amp;jstr, \u0026#34;diag2\u0026#34;, 30); json_gen_obj_set_float(\u0026amp;jstr, \u0026#34;diag3\u0026#34;, 54.1643); json_gen_obj_set_string(\u0026amp;jstr, \u0026#34;diag4\u0026#34;, \u0026#34;diag\u0026#34;); json_gen_end_object(\u0026amp;jstr); json_gen_str_end(\u0026amp;jstr); /* The values are reported by updating appropriate parameters */ esp_rmaker_param_update_and_report(esp_rmaker_device_get_param_by_name(device, \u0026#34;Data\u0026#34;), esp_rmaker_obj(buf)); esp_rmaker_param_update_and_report(esp_rmaker_device_get_param_by_name(device, \u0026#34;Timestamp\u0026#34;), esp_rmaker_int((int)current_timestamp)); } return ESP_OK; } The above code snippet should be self explanatory because of the comments.\nAs you can see, 4 different values of 4 different types could be reported via a single parameter, which is better than having 4 different parameters, which would bloat up the node configuration. Note that the JSON Generator library usage is shown just for reference as it is used at most places in ESP RainMaker. You can choose any other libraries or functions to create the object.\nTesting the Service # Before you add some logic in your phone apps to use the service, it would be better to test it first from the RainMaker CLI. Once you have the CLI set-up, you can use a command like this to start the diagnostics:\n$ ./rainmaker.py setparams --data \u0026#39;{\u0026#34;Diagnostics\u0026#34;:{\u0026#34;Trigger\u0026#34;:true}}\u0026#39; \u0026lt;node_id\u0026gt; Once the device gets this command, the device serial console will show up such prints\nI (74726) esp_rmaker_param: Received params: {\u0026#34;Diagnostics\u0026#34;: {\u0026#34;Trigger\u0026#34;: true}} I (74726) app_main: Received write request via : Cloud I (74726) app_main: Starting Diagnostics I (74736) esp_rmaker_param: Reporting params: {\u0026#34;Diagnostics\u0026#34;:{\u0026#34;Data\u0026#34;:{\u0026#34;diag1\u0026#34;:true,\u0026#34;diag2\u0026#34;:30,\u0026#34;diag3\u0026#34;:54.16430,\u0026#34;diag4\u0026#34;:\u0026#34;diag\u0026#34;}}} I (74746) esp_rmaker_param: Reporting params: {\u0026#34;Diagnostics\u0026#34;:{\u0026#34;Timestamp\u0026#34;:1639738352}} You can then query the node parameters to see the results using:\n$ ./rainmaker.py getparams \\\u0026lt;node_id\\\u0026gt; It will show up this object:\nAs you can see here, we could add a new custom functionality in RainMaker without changing/configuring anything in the cloud backend. That’s how the “tunnelling” concept of RainMaker works, making it very extensible.\nA few samples for RainMaker services can be found here:\nOTA Using Params System Service Time Service Schedules ","date":"12 January 2022","externalUrl":null,"permalink":"/blog/extending-esp-rainmaker-with-services/","section":"Blog","summary":"","title":"Extending ESP RainMaker with “Services”","type":"blog"},{"content":"Espressif Matter Series* #5*\nIn the Previous Articles, we talked about Matter from several aspects. Today, let’s start with a foundational concept of Matter: IP-based .\nMatter defines a common application layer, using Internet Protocol (IP) , that delivers interoperability among devices regardless of the underlying network protocol. At launch, Matter will run on Ethernet, Wi-Fi and Thread.\nEthernet and Wi-Fi are all well known networking protocols, while Thread may be new to some people.\nIn a nutshell, Thread is an IPv6-based , low-power, mesh networking protocol for Internet of things (IoT) products. It is built on IEEE-802.15.4 technology, so the Thread devices cannot communicate with the Wi-Fi or Ethernet devices directly. In the Matter topology, a special device is required to connect the sub-networks, the device is called the Thread Border Router (Thread BR will be used for short).\nBelow is a typical Matter topology:\nThe Device-to-Device Automations within local network is a key feature of Matter, it works across Ethernet, Wi-Fi and Thread devices. For instance, a Thread Matter switch can directly control a Wi-Fi Matter bulb, or the other way around, without any phone-apps/cloud in the middle.\nNow, let’s take a look at the Thread BR that connects Wi-Fi and Thread as an example, and investigate how it supports the (a) bi-directional connectivity and (b) service discovery used in Matter.\nBidirectional Connectivity\nThread BR is responsible for forwarding IP frames between Wi-Fi and Thread networks. Different from the Gateway/Bridge devices which need to handle the application-level interaction, Thread BR only focuses on the IP layer routing, regardless of the application payload.\nThere are three scopes in a Thread network for unicast addressing:\nLink-Local: used only for one-hop communication Mesh-Local: used for communication within the local Thread Network Global: used for communication with the hosts outside the local Thread Network Thread BR configures its Thread partition with an Off-Mesh Routable (OMR) prefix, each Thread device adds an OMR address as the Global unicast address. Thread BR announces reachability of this OMR Prefix to Wi-Fi network by sending Router Advertisement (RA) which contains an IPv6 Route Information Option (RIO).\nVice versa, Thread BR should also inform Thread devices about the routing to Wi-Fi network. Rather than using the IPv6 Neighbor Discovery protocol, prefixes are advertised via Thread Network Data as external route entries.\nThen both devices in Thread and Wi-Fi networks know about the particular IPv6 prefixes reachable via the Thread BR.\nService Discovery\nIn Matter, the Standard DNS-Based Service Discovery (DNS-SD) is used for Service Advertising and Discovery. On Wi-Fi and Ethernet networks, the DNS-SD uses Multicast DNS for zero-configuration operation.\nBut multicast and broadcast are inefficient on wireless mesh networks like Thread. Service Registry Protocol (SRP) is introduced in Thread for service discovery over unicast packets.\nNormally, Thread BR acts as the SRP server and the Advertising Proxy: Thread devices register their services to Thread BR, and the BR will advertise all the services via Multicast DNS to Wi-Fi network.\nThe Thread Border Router also implements DNS-SD Discovery Proxy, to enable clients on the Thread network to discover services from Wi-Fi network.\nEspressif Thread Border Router Solution\nEspressif, as an active member that supports Matter from the beginning, we can offer the full spectrum of Matter protocol solutions for end-products with Wi-Fi or Thread connectivity, as well as for Thread Border Router and Bridge solutions using a combination of SoCs.\nThe Thread Border Router SDK is now available from the link: Thread Border Router Example and SDK. It uses two SoCs (Wi-Fi + 802.15.4) connected via a serial interface like UART or SPI.\nIf you are interested in our Thread Border Router solution, please contact our customer support team.\n","date":"4 January 2022","externalUrl":null,"permalink":"/blog/matter-thread-border-router-in-matter/","section":"Blog","summary":"","title":"Matter: Thread Border Router in Matter","type":"blog"},{"content":"Espressif Matter Series* #4*\nSeveral big IoT ecosystems have announced integrated support for Matter, e.g., Amazon, Apple, Google and Samsung. It’s exciting to expect that more and more devices from multiple brands work natively together, under a bigger Matter ecosystem.\nMeanwhile, people may have a question: There are many IoT products in the consumers’ home already, these can be the devices based on Zigbee, Z-Wave, BLE Mesh and others. Could these non-Matter devices work together with Matter ecosystem? The answer is YES.\nToday, let’s talk about the Bridge feature in Matter.\nMatter Bridge Introduction # A Bridge serves to allow the use of non-Matter IoT devices in a Matter ecosystem (Matter Fabric). It enables the consumer to keep using these non-Matter devices together with their Matter devices.\nThe non-Matter devices are exposed as Bridged Devices to Nodes in the Matter ecosystem. The Bridge device performs the translation between Matter and other protocols so that the Matter nodes can communicate with the Bridged Devices.\nBelow is an example of Matter-Zigbee Bridge, it bridges two Zigbee lights to Matter ecosystem:\nBridge Data Model # In the previous article Matter: Clusters, Attributes, Commands, we talked about the Matter Data Model, below is a Data Model example of a Matter Bridge device.\nOn Endpoint 0, the device type is defined as Bridge. The PartsList field lists all endpoints for bridged devices, each endpoint represents one device at the non-Matter side of the bridge. The Descriptor cluster on each endpoint provides information about the particular Bridged Device. A Bridge may also contain native Matter functionality, for example, it may itself be a smart Thermostat having both Wi-Fi and Zigbee connection. The Thermostat is native Matter functionality, it is capable of sending heating and/or cooling requirement notifications to a heating/cooling unit. While the other endpoints represent the Bridged Devices.\nNow, let’s look into the Matter-Zigbee Bridge example we mentioned in previous section.\nHere is the workflow to control a Zigbee device on the phone with Matter protocol:\nStep-1. The Bridge, a device type defined in Matter, should follow the standard Matter commissioning process to join the Matter fabric.\nStep-2. The Matter-Zigbee Bridge Device should also join the Zigbee network. A bit different from Matter, the Zigbee specification does not mandate any standard commissioning process, it’s left to the device vendors to decide the workflow for distributing the link keys. The Install Code is the most common method since Zigbee 3.0.\nStep-3. Once the Bridge Device joins the Zigbee network, it will discover the supported devices in the Zigbee network by broadcasting the Match Descriptor Request command. The command includes desired Profile, In-Clusters and Out-Clusters. In this example, it will ask something like “Who has an On/Off Light with OnOff Cluster? ”. The corresponding Zigbee devices will reply the Match Descriptor Response with its network address included. For each matched Zigbee Light, the Bridge will add a dynamic endpoint, in Matter, which stands for the Bridged Zigbee Device.\nStep-4. The Bridge exposes all the Bridged Devices to the Matter fabric, which follows the Operational Discovery method as defined by Matter specification (stay tuned for the coming series talking about Discovery in Matter).\nStep-5. Now the Controllers in the Matter fabric can control the lights in the Zigbee network with the help of Bridge.\nSome Notes:\nNote 1: The interaction method in Step-2 and Step-3 is defined by device vendors and the protocol itself, which is out of Matter scope. Note 2: The Bridged Devices can be dynamic added or removed according to the keep alive mechanism in the non-Matter side network. This was a typical workflow for bridging to a Zigbee network. The similar concepts will be applicable to other networks that we would be bridging to.\nEspressif Matter Bridge Solutions # Espressif, as an active member that supports Matter from the beginning, can offer the full spectrum of Matter protocol solutions for end-products with Wi-Fi or Thread connectivity, as well as for Thread Border Router and Bridge solutions using a combination of SoCs.\nWe offer both Matter-Zigbee and Matter-BLE Mesh bridge solutions with full functional software SDK support. A Matter-Zigbee Bridge uses two SoCs (Wi-Fi + 802.15.4), they are connected via a serial interface like UART or SPI, while a Matter-BLE Mesh Bridge can be done on single SoC with both Wi-Fi and BLE interfaces.\nIf you are interested in our Matter Bridge solutions, please contact our customer support team.\n","date":"14 December 2021","externalUrl":null,"permalink":"/blog/matter-bridge-for-non-matter-devices/","section":"Blog","summary":"","title":"Matter: Bridge for Non-Matter Devices","type":"blog"},{"content":"","date":"7 December 2021","externalUrl":null,"permalink":"/authors/hrishikesh-dhayagude/","section":"Developer Portal Authors","summary":"","title":"Hrishikesh Dhayagude","type":"authors"},{"content":"Espressif Matter Series* #3*\n[This is article #3 in the Espressif Matter Series of articles. You may read the second part here.]\nIn the previous article we looked at the data model of Matter. Today, let us talk about how Matter devices within a network can interact with each other leading to useful automations. For instance, you may want a light switch at your home to control one or more light bulbs. Or even a thermostat to turn on or off based on reports from the occupancy sensor.\nThis is a very interesting usecase that is not easily possible through the existing ecosystem protocols. Matter easily enables this. This doesn’t require intermediation from any cloud or phone apps to make it happen. Instead, it is all facilitated directly over the local network.\nAs mentioned in the data model article, every Matter cluster has a cluster server, and a cluster client counterpart. The communication happens between the client and server of the same cluster. As can be seen above, the OnOff cluster client on the switch can talk with the OnOff cluster server on the light to turn it on or off. And the end-user can configure which device can talk to which device(s) in their home.\nFor this interaction to happen, the switch should know the details about the light. This is achieved through device binding . A binding represents a persistent relationship that informs a client endpoint of one or more target endpoints for a potential interaction. A user (through the Matter phone app) can establish binding between devices, regardless of the vendors they are from.\nThere are two ways through which device-to-device interaction can be accomplished:\n1. Synchronous Control # Let’s go back to our example of the switch controlling the light that is shown above. For this, the switch additionally needs to have a Binding cluster server that offers the binding service. After a user binds the light to the switch, an action (on or off) on the switch results into corresponding action on the light. This scenario is illustrated below:\nSimilarly, a Dimmer Switch needs to have an OnOff client, a Level Control client and a Binding server to control a dimmable light.\n2. Asynchronous Notification (Subscribe-Report) # This method facilitates receiving data reports from a publisher to a subscriber. The subscriber can subscribe to attributes and/or events on the publisher.\nThe thermostat and occupancy sensor usecase mentioned above can be realised after the thermostat subscribes to attributes of the sensor. First the user binds the thermostat to the occupancy sensor. Once done, the thermostat can subscribe to the sensor attributes and receive data periodically as well as when there is an activity (change in sensor attributes). This scenario is illustrated below:\nThis was an example of subscribing to attributes. Devices could also subscribe to events . In the data model article, we talked about clusters having attributes and commands. Here, we introduce events which are also a part of clusters. Events capture every single change and convey it to the subscribed entity. A few examples of events include switch pressed, long press, and door opened.\nThis sums up the introduction to device-to-device communication in Matter along with the different ways in which it can be implemented.\nThis article is a part of a series of articles Espressif Matter Series. You may read the next article that talks about Matter: Bridge to non-Matter Devices.\n","date":"7 December 2021","externalUrl":null,"permalink":"/blog/matter-device-to-device-automations/","section":"Blog","summary":"","title":"Matter: Device-to-Device Automations","type":"blog"},{"content":" Matter is an initiative of the Connectivity Standards Alliance, and developed through collaboration amongst all the leaders of the IoT industry.\nArticles # The following articles talk about Matter\nAnnouncing Matter Espressif Matter Series #1: What does Matter mean to you? Espressif Matter Series #2: Matter: Clusters, Attributes, Commands Espressif Matter Series #3: Matter: Device-to-Device Automations Espressif Matter Series #4: Matter: Bridge for non-Matter Devices Espressif Matter Series #5: Matter: Thread Border Router Espressif Matter Series #6: Matter: Multi-Admin, Identifiers, and Fabrics Espressif Matter Series #7: Matter Security Model Espressif Matter Series #8: Matter: Distributed Compliance Ledger Espressif Matter Series #9: Accelerating Matter Device Manufacturing Espressif Matter Series #10: Matter and Certificate Revocation Espressif’s Matter Demos # The following is a demonstration of the various Matter device classes that are supported by Espressif. This also demonstrates the device binding features of Matter.\nEspressif’s Matter Solutions # Look at the various ways Espressif helps you build and deploy Matter devices.\n","date":"30 November 2021","externalUrl":null,"permalink":"/blog/matter/","section":"Blog","summary":"","title":"Matter","type":"blog"},{"content":"Espressif Matter Series* #2*\n[This is article #2 in the Espressif Matter Series of articles. You may read the first part here.]\nIn the previous article we looked at what does Matter mean to you. Today, let’s talk about an important part of Matter, its data model. The data model of Matter defines the typical elements that go into making of a typical Matter node. As a device developer, you would typically express the capabilities of your device through this data model.\nFor better understanding, let’s consider we are building a luminaire that has 2 lights: one dimmable, one simple on/off.\nElements of Matter # The following diagram shows a simplistic view of how this can be represented in the Matter’s data model.\nNode: In our case, the luminaire is a node. This is a uniquely network addressable entity that exposes some functionality. This is typically a physical device that a user can recognise as a whole device.\nEndpoint: Each node has a number of endpoints. An endpoint could be thought of like a virtual device that provides services that could be logically grouped together. In our example above, our luminaire has 2 separate lights, one dimmable, one on-off. Each of these will have an endpoint of their own.\nNotice that endpoint 0 is reserved. This contains certain services that are applicable to the entire node. We will look at what this contains later in the section.\nThe Matter specification defines certain common Device Types . For example, the On/Off Light and Dimmable Light, that you see within endpoints 1 and 2 are standard device-types defined by Matter. A device type is used to indicate a set of commonly available functionality.\nClusters: A cluster groups together commonly used functionality in a reusable building block.\nIn our diagram, our first light (endpoint 1), is shown with 2 standard clusters, On/Off cluster, and Level Control cluster. The On/Off cluster provides a service to switch on or off certain things. The Level Control cluster provides a service that enables configuring levels of certain things. In our case, the On/Off cluster helps switch on or off the light and the Level Control cluster helps configure the brightness of our light.\nIf our light had supported controlling the colour, it would have another standard cluster called the Color Control cluster.\nOur second light (endpoint 2), is just an on/off light, hence it only includes the On/Off cluster.\nAs you may notice from the diagram, clusters contain attributes and commands.\nAttributes: Attributes indicate something that can be read or written to. In our example, the OnOff cluster has an OnOff attribute that maps to the actual state of the device. Similarly, in the Level Control cluster there is a Current Level attribute that maps to the current level that is set.\nAttributes may be persistent or volatile (lost across reboots), and also read-only or read-write.\nThe Matter specification includes a list of data types that may be possible for attributes. These include the typical, boolean, integers (signed/unsigned), floats, enumerations, strings, or even collections (lists or structures).\nCommands: A cluster command provides an ability to invoke a specific behaviour on the cluster. A command may have parameters that are associated with it. In our diagram above, the On/Off cluster has a Toggle command that toggles the current On/Off attribute of the cluster. The Level Control cluster has commands like MoveToLevel, Move, Step, that move the current level of the cluster in specified ways.\nThese are the typical elements of the Matter data model. The Matter specification provides a list of standard clusters and their attributes and commands. You may peruse this to check how it aligns with the capabilities of your device.\nNow that we’ve looked at the common elements in Matter’s data model, let’s understand another concept Cluster servers and clients.\nCluster Servers and Clients # Every Matter cluster has a Cluster Server, and a Cluster Client counterpart. In the diagram above, our device included Cluster Servers, as they provide the service. Interaction with these is done through Cluster Clients.\nThe following diagram demonstrates this well:\nHere a Matter Dimmer Switch implements OnOff and Level Control Cluster clients . These clients talk to the corresponding servers on the light, to control them. We also have a Matter Simple Switch, that only implements an OnOff Cluster client. Finally, a phone app that controls the same Light will also implement the relevant cluster clients to control the light. Note here that the Dimmer Switch, Simple Switch, Light as well as the phone-app, are all Matter nodes. Let’s look at some other examples that drive the point home.\nThe Endpoint 0 # Finally, earlier we talked about the endpoint 0, this is an endpoint with a “Root Node” device type. This is a special endpoint that has clusters that are specific to this entire Matter node. Some of the typical clusters that are part of this endpoint include:\nBasic Information Cluster Server : Provides basic information about the node, like firmware version, manufacturer etc ACL Cluster Server : Allows configuration of the Access Control Lists for this node. Network Commissioning Cluster Server : Allows configuration of a network (Wi-Fi, Ethernet, Thread) on the node. [Note that the Matter specification defines certain mandatory clusters that should be part of any endpoint. Similarly, every cluster may have certain mandatory attributes and commands as defined in the specification. For the sake of brevity, we have omitted listing all of them here.]\nThis was a short overview of the commonly used elements of the Matter Data Model. Hope it helps you to envision how your device’s capabilities aligns with the Matter Data Model.\nThis article is a part of a series of articles Espressif Matter Series. You may read the next article that talks about Matter: Device-to-Device Automations.\n","date":"30 November 2021","externalUrl":null,"permalink":"/blog/matter-clusters-attributes-commands/","section":"Blog","summary":"","title":"Matter: Clusters, Attributes, Commands","type":"blog"},{"content":"Hi everyone,\nEspressif is proud to announce the availability of new Wi-Fi modules implementing the AWS IoT ExpressLink specification.\nEspressif’s AWS IoT ExpressLink modules, ESP32-C3-MINI-1-N4-A, are based on the ESP32-C3 SoC and offer Wi-Fi + Bluetooth LE 5.0 connectivity, thus providing any host MCUs with out-of-the-box, seamless, AWS cloud connectivity. Espressif’s AWS IoT ExpressLink modules offer a simple serial interface which the host MCU uses to get connected to AWS IoT services, and transform any offline product into a cloud-connected product. Espressif’s AWS IoT ExpressLink Module handles complex, yet undifferentiated, workload, such as authentication, device management, connectivity, messaging and OTA. Thus, it relieves developers from developing and maintaining complex firmware, while it provides end-to-end security and fleet management at scale. Espressif’s AWS IoT ExpressLink module comes pre-programmed with qualified firmware, and pre-provisioned with unique device certificates that remove security concerns from the manufacturing process, which is, therefore, significantly simplified.\nEspressif’s AWS IoT ExpressLink module, ESP32-C3-MINI-1-N4-A, has the ESP32-C3 SoC at its core, which provides a cost-effective connectivity solution with 2.4 GHz Wi-Fi and Bluetooth LE 5.0 support. This Espressif SoC ensures connection security with such features as secure boot, flash encryption and an integrated digital signature peripheral. Espressif’s AWS IoT ExpressLink module comes in a small form-factor of just 13.2mm x 16.6 mm, and offers the option of either a PCB antenna or an external antenna connector. The module comes with regulatory certifications for most of the world’s regions.\nOther topics you can read about in this month’s newsletter include:\nAnnouncing the Availability of Pre-provisioned ESP32-C3, ESP32-S2 and ESP32-S3 Modules Espressif’s pre-provisioning service greatly simplifies manufacturing complexity and security management.\nLimited Sale: Launching ESP32-S3-BOX, a Versatile AI Voice Development Kit for the Smart Speaker Market ESP32-S3-BOX is based on the ESP32-S3 SoC but has an additional 16MB QSPI flash and an 8MB Octal PSRAM.\nIntroducing the ESP32-C3-based Smart Switch This solution upgrades traditional switches to smart switches, without rewiring, or configuring a gateway. It also combines low power-consumption with reliable and secure Wi-Fi connectivity.\nESP32-Powered Electrical Impedance Tomography Toolkit by MIT MIT’s EIT-kit supports users in creating a variety of EIT-sensing devices, and visualizing the resulting data. The EIT-kit comprises a 3D editor plugin, a sensing motherboard based on ESP32, a microcontroller library, and an image reconstruction API.\nHope you enjoy reading this month’s newsletter. Keep sending us your messages and requests on Facebook, Twitter, GitHub, Instagram, LinkedIn, and YouTube.\nYou can also contact us through our website or you can email us. We try to respond to all of your messages as quickly as possible!\nBest wishes,John LeeSenior Customer Support Officer.\n","date":"30 November 2021","externalUrl":null,"permalink":"/blog/november-2021/","section":"Blog","summary":"","title":"November 2021","type":"blog"},{"content":"Espressif Matter Series* #1*\nYou may have recently read about the newly introduced standard, Matter. Matter is an initiative of the Connectivity Standards Alliance, and developed through collaboration amongst all the leaders of the IoT industry.\nThere is a high level of excitement about Matter and what it aims to achieve. We often hear questions from device-makers and end-users as to how they can benefit from the Matter standard. In this article, let’s look at what does Matter mean to you as an end-user and as a device-maker.\nFor End Users # If you are an end-user, Matter will make smart-home much more natural and intuitive for you.\nNo More Silos:\nGone would be the days where one vendor’s app only worked with its own smart home devices. A Matter enabled app, will work with any Matter enabled device.\nSo also no more of: “Oh this is an iOS ecosystem device, so my wife on Android can’t use it that well”.\nAmazon, Apple, Google and Samsung all have announced integrated support for Matter in their latest announcements. So the typical devices that let us interact with smart devices: phones (iOS as well as Android) and voice assistants/smart speakers will support Matter based devices out of the box. You might not even require a separate phone app to use devices that run Matter.\nMore automation: Matter allows effective device-to-device communication without any other intermediary involved. A Matter smart switch or sensor can directly switch on/off a Matter lightbulb (or a group of bulbs), without having to go through any app, cloud or a skill. Once devices are setup, the control happens completely locally over the local network.\nNo more transport silos: Matter works with devices that support Wi-Fi, as well as Thread/802.15.4. Your phone app will be able to control devices using any of these transports equally well.\nYou could also setup automations that allow an 802.15.4-based sensor to directly switch-on a Wi-Fi based light-bulb without an app or a cloud into the picture. Yes, you read that right. A device called a border router (that includes both Wi-Fi and 802.15.4 transports) helps bridge these two networks, allowing direct addressability from one to another.\nAdditionally, all the communication happens over the local Wi-Fi/802.15.4 network. So smart control continues to work within devices in the local network even across Internet outages.\nFor existing products that use ZigBee or BLE Mesh, Matter bridges can help you make these devices reachable through the Matter ecosystems.\nMore ecosytems: Solution providers may offer higher level ecosystems based on Matter, that provide additional features to end users. The Matter specification makes it easier for devices to work with multiple ecosystems. So the same device could, simultaneously, work with multiple heterogenous ecosystems. What’s more, device vendors themselves can create their own ecosystems (not just restricted to phone OSes or voice assistants) and provide innovative features as part of these ecosystems. Please watch out for a follow-on blog post for more details about Matter Ecosystems.\nBetter security: The Matter specification has baked in secure features, agreed and reviewed by the best in the tech industry. This guarantees that devices that pass Matter certification rely on well reviewed and strong industry standards.\nAll in all, Matter should help accelerate pervasive intelligence in the smart home by delivering seamless integrations and new possibilities.\nFor Device Makers # If you are a device maker, firstly your customers will benefit from all the advantages of Matter described above. Secondly, Matter will help you build and scale smart devices much faster, with no encumbrances.\nEase of Development: Device makers no more have to spend engineering effort in painstakingly supporting and, importantly, certifying multiple ecosystems. This is often an engineering/cost overhead, but also a launch timeline overhead. Matter makes building devices much easier and faster.\nPower of Open: The Matter implementation is built openly and for a wide variety of vendors. This makes evaluation and development faster.\nYou can try out a Matter-enabled device even today, just head over to the Git repository.\nDevice — Device Automations: The device-to-device automations make it easier to introduce intelligence in a smart-home: a sensor coupled with light-bulb, that work by themselves. Your bulb or sensor, could work with any other Matter vendor’s devices.\nIf you are a device maker that builds devices like sensors or switches that always works in conjunction with other devices, this is great news for you. This means you could build smart devices, leaving up to the customer’s imagination what they tie the output of your device to (a bulb or a fan or anything else, from any vendor).\nMatter Ecosystems: Matter ecosystems is a way to implement an ecosystem of smart devices that may talk to each other and build compelling multi-device scenarios. The Matter specification allows vendors to create such an ecosystem so that these features can be layered on top.\nManufacturer-specific Innovations: The Matter specification has an evolving list of device-types, the typical attributes they will have, and the commands they will obey. If your device has certain innovative features that cannot be expressed through these, you could define your own attributes that allow you to make the best use of these.\nEspressif and Matter # Espressif has been actively working with Matter since its inception. Support for Espressif SoCs is already available upstream in the Matter repositories. You may take it for a spin on an ESP32 or ESP32-C3 by following the instructions in this article.\nWe are currently working on building tools and documentation, to assist our customers in every step of the product development process, right from solution architecture, to certification, manufacturing and diagnostics.\nWe are excited about this journey, and look forward to hearing how you envision building with Matter.\nThis article is a part of a series of articles Espressif Matter Series. You may read the next article that talks about Matter’s Data Model.\n","date":"23 November 2021","externalUrl":null,"permalink":"/blog/what-does-matter-mean-to-you/","section":"Blog","summary":"","title":"What does Matter mean to you?","type":"blog"},{"content":"","date":"22 November 2021","externalUrl":null,"permalink":"/tags/ai-voice-assistant/","section":"Tags","summary":"","title":"Ai Voice Assistant","type":"tags"},{"content":" Espressif Systems has recently released an AI voice development kit dubbed ESP32-S3-BOX, based on ESP32-S3 Wi-Fi + Bluetooth 5 (LE) SoC. It provides a platform for developing the control of smart devices with offline and online voice assistants. ESP32-S3-BOX is ideal for developing AIoT applications with reconfigurable AI voice functions, such as smart speakers, and IoT devices that achieve human-computer voice interaction directly. Not only does ESP32-S3-BOX address connectivity use cases, but it also targets various machine-learning (AI on the edge) and HMI application scenarios. ESP32-S3-BOX comes in an attractive form-factor that differentiates it from regular PCB development boards, since users can quickly build with it applications that are fairly close to actual end products. Furthermore, ESP32-S3-BOX functions as a versatile and extensible development kit that facilitates a multitude of interesting use-cases, the most characteristic of which we will examine in this blogpost.\nFirst, let’s take a look at the ESP32-S3-BOX specifications. In general, ESP32-S3-BOX is a compact, extensible kit with many features of a finished product. It is equipped with a 2.4-inch display (with a 320 x 240 resolution) integrated with a capacitive touch panel, a Type-C USB interface that supports 5 V of power input and serial/JTAG debugging, and two Pmod™-compatible headers for connecting peripheral modules that expand the functionality of the original board. The two Pmod™ headers offer 16 programmable GPIOs that are able to provide 3.3 V of power supply to peripherals.\nAt the core of ESP32-S3-BOX is ESP32-S3, a Wi-Fi (802.11b/g/n) + Bluetooth 5 (LE) SoC which has a 240 MHz Xtensa® 32-bit LX7 dual-core processor with powerful AI instruction extensions that enable neural network acceleration, and efficient audio processing. Moreover, ESP32-S3-BOX has 16MB of flash and 8MB of PSRAM, in addition to the internal SRAM of ESP32-S3.\nNow, let’s look at some of the most important use cases that are readily supported by ESP32-S3-BOX.\nOnline and Offline Voice Assistant # ESP32-S3-BOX features an online and offline voice assistant which can be used as either a stand-alone voice assistant, or a voice-enablement module that can be integrated into other devices.\nFor every high-quality voice assistant, a high-performance audio front-end and a wake-word engine are essential. Indeed, ESP32-S3-BOX supports Espressif’s Audio Front-End (AFE) algorithms that take advantage of the AI accelerator available in the ESP32-S3 SoC. Hence, ESP32-S3-BOX achieves a great performance, without requiring an external DSP co-processor. The combination of the AI accelerator and Espressif’s AFE algorithms achieves a 360-degree and far-field 5 m pickup with only two microphones, while ensuring high-quality, stable audio data; it also improves the quality of the target audio source in high-SNR scenarios, thus achieving an excellent performance in voice interaction. On this note, Espressif’s AFE algorithms have been qualified by Amazon as a “Software Audio Front-End” solution for Alexa built-in devices.\nEspressif’s ESP-Skainet SDK provides a reliable offline voice assistant that enables developers to configure up to 200 commands. Espressif’s Alexa for IoT SDK provides an easy way to integrate the Alexa functionality into IoT devices. Both of these assistants are available on ESP32-S3-BOX, thus addressing any developer requirements for offline and online voice assistants. Practical examples of these will be made available shortly.\nHMI Touch Screen # ESP32-S3-BOX has a 320x240 capacitive touch screen that can be used for HMI applications, such as control panels. ESP32-S3 SoC’s improved PSRAM interface and computing power support a touch screen with a high refresh rate. Espressif has integrated LVGL into its SDK, as a component, thus making it easy for developers to evaluate and port LVGL into their product designs. LVGL is a free and open-source graphics library, providing users with everything they need for creating an embedded GUI in ESP32-S3-BOX, with easy-to-use graphical elements and advanced visual effects, including animations and anti-aliasing.\nSmart Gateways # ESP32-S3-BOX can support several Espressif chip series through its Pmod™ headers, so that developers can easily build a smart gateway and integrate into it various communication protocols. This ensures connectivity for a variety of devices in a seamless way.\nFor instance, we can combine ESP32-S3-BOX with the ESP32-H2 module, which supports 802.15.4 (Thread 1.x/ZigBee 3.x) and Bluetooth 5 (LE), to build a Thread Border Router that connects a low-power Thread network to a Wi-Fi network. The router can also work as a Zigbee gateway, allowing users to control Zigbee devices through Matter, a connectivity protocol for smart home.\nESP32-S3-BOX can also work as a Wi-Fi/Bluetooth gateway. After it connects to the Internet via a router, it can share its connection with neighbouring devices via hotspots . By connecting to a mobile network module (e.g. LTE, 5G, NB-IoT) through the Pmod™ headers, ESP32-S3-BOX can also be used as a portable Wi-Fi hotspot that provides neighbouring devices with internet access.\nIn addition, ESP32-S3-BOX also supports multiple third-party cloud platforms to ensure device interoperability in different ecosystems. With the help of Espressif’s one-stop AIoT could platform, ESP RainMaker®, developers can use phone apps to communicate with ESP32-S3-BOX, configure GPIO pins at will, customize voice commands, and upgrade firmware via OTA. With ESP RainMaker and ESP-S3-BOX, you can convert any offline product into a connected product, just by using the Pmod™ interface. Bridge support in the ESP RainMaker integration also extends ESP-S3-BOX’s capability to control devices easily, with BLE or 802.15.4 radio, via the cloud.\nExtensible Pmod™ Interface # ESP32-S3-BOX also provides two Pmod™-compatible headers (with 16 programmable GPIOs) that support interfacing with various peripherals for flexibly expanding the functions of the board. Here are a few examples of how to use ESP32-S3-BOX in this way:\nConnect to a Micro SD card to make ESP32-S3-BOX work as a multimedia player that can store images and audio files. Connect to an infrared sensor to make ESP32-S3-BOX simulate a voice-enabled, infrared, remote control for an air conditioner, TV set, projector or other equipment, with offline voice commands. Connect to a temperature and humidity sensor or PM2.5 sensor to make ESP32-S3-BOX work as an air-quality detector that supports voice control, and displays sensor data on a screen. Connect to an RGB LED module to build with ESP32-S3-BOX a smart-lighting solution that supports offline voice control. Connect to a USB OTG module to achieve various USB applications involving a camera, 4G networking, a Wi-Fi USB disk, a USB touchpad, etc. Connect to a camera module to make ESP32-S3-BOX support face detection and recognition Additional Resources # Espressif provides developers with full access to its open-source technical resources, i.e. the ESP32-S3-BOX hardware reference design and user guide, LVGL guide, ESP-SR speech-recognition model library (including the wake-work detection model, speech-command recognition model, and acoustic algorithms), as well as ESP-DL deep-learning library that provides APIs for Neural Network (NN) Inference, Image Processing, Math Operations and some Deep Learning Models. Furthermore, Espressif’s IoT Development Framework (ESP-IDF) simplifies secondary development around ESP32-S3-BOX, and supports high-performance AI applications to run on the board, thus speeding up time-to-market for the end product. Please, keep watching this space, because we shall update specific example pointers shortly.\nEspressif will continue offering its customers innovative technologies and high-performance products. We look forward to collaborating with our partners to develop more state-of-the-art applications for the AIoT industry. If you are interested in ordering ESP32-S3-BOX, please go to AliExpress, Adafruit or Amazon. If you want to know more about the product, please contact our customer support team, who will try and assist you as soon as possible.\n","date":"22 November 2021","externalUrl":null,"permalink":"/blog/presenting-the-advantages-of-esp32-s3-box-espressifs-ai-voice-development-kit/","section":"Blog","summary":"","title":"Presenting the Advantages of ESP32-S3-BOX, Espressif’s AI Voice Development Kit","type":"blog"},{"content":"Hi everyone,\nLast week Amazon announced Alexa Connect Kit SDK (ACK SDK) , a software package that enables Original Design Manufacturers (ODMs) and System Integrators (SIs) to build their own ACK-based modules and differentiated, Alexa-compatible, smart-device solutions without having to worry about managing cloud services, building an app, or writing an Alexa skill.\nODMs and SI solution providers, such as Leedarson, Tonly, Innotech, and Linkplay, are already developing solutions with ACK SDK on Espressif hardware . With the new ACK SDK, developers can build their own Alexa-compatible solutions with the same benefits as ACK, and with more control over costs and features.\nOn this occasion, Espressif’s Director of Technical Marketing, Mr. Amey Inamdar said: “We are pleased to be part of the ACK SDK program, and excited to partner with Amazon to announce our first ACK SDK-compatible development kit. Espressif’s ACK SDK-compatible development kit is going to make it even easier for solution providers and device makers to use our products to build innovative, connected-devices using the best-in-class ACK SDK”.\nHere, you can read more about how the new ACK SDK works, and how you can start building with it today.\n*Picture courtesy of Amazon’s *Device Makers Blog\nOther topics you can read about in this month’s newsletter include:\nESP32-H2 Officially Recognised as a “Thread-Certified Component” and a “Zigbee-Compliant Platform” ESP32-H2 has been granted the official “Thread Interoperability Certificate”, while it has also been certified as a “Zigbee-Compliant Platform”, according to the relevant certification issued by the Connectivity Standards Alliance (CSA).\nGolioth Qualified on Espressif’s ESP32 Golioth has been qualified on Espressif Systems’ ESP32, which it naturally recommends as the easiest way to get started with Golioth’s own Cloud-connected IoT platform.\nSupport for New Operating Systems in the ESP32 Series of SoCs NuttX and Zephyr are now supported on the ESP32 series of SoCs. Check out how it all happened!\nVoltLog’s ESP32-Based Tasmota Floor Heating Valve Controller Independent maker, Florin “VoltLog” C., has just released an ESP32-based, open-hardware design for building a Tasmota-compatible, ten-channel valve actuator for an in-floor heating system.\nRead More \u0026gt;\nHope you enjoy reading this month’s newsletter. Keep sending us your messages and requests on Facebook, Twitter, GitHub, Instagram, LinkedIn, and YouTube.\nYou can also contact us through our website or you can email us. We try to respond to all of your messages as quickly as possible!\nBest wishes,John LeeSenior Customer Support Officer.\n","date":"7 November 2021","externalUrl":null,"permalink":"/blog/october-2021/","section":"Blog","summary":"","title":"October 2021","type":"blog"},{"content":"Hi everyone,\nA few weeks ago, the Bluetooth SIG Blog interviewed Teo Swee Ann, Espressif Systems’ founder and CEO, who shared his insight into the current and future use cases of Espressif’s open-source Bluetooth mesh protocol stack. ESP-BLE-MESH is widely used across smart-home, smart-lighting, and smart-industry environments.\n“The most common use case for our Bluetooth® mesh solution in the smart lighting market is connecting the lighting equipment using the Bluetooth mesh topology. This can be implemented effectively in home, enterprise, industrial, or public environments”, said Teo Swee Ann. Regarding the role of Bluetooth mesh in the future of smart lighting, he added: “Based on current market data, we anticipate an increase in the penetration of Bluetooth® mesh in the smart lighting market. For example, combining Bluetooth AoA/AoD technology with Bluetooth mesh will enable indoor positioning through lighting networks that will facilitate various consumer and business-oriented use cases, such as asset tracking. With the ability of Bluetooth mesh to provide device-to-device communication and connect to the internet via a gateway, more smart-lighting systems will be developed.”\nTeo Swee Ann, then, went on to talk about potential future applications of the Bluetooth mesh technology: “Through the combination of Bluetooth mesh, voice-and-image recognition, smart home sensors, and machine learning, technology will adapt to human needs even better, improving the quality of everyday life even further.” To read the whole of Teo Swee Ann’s interview, click on the picture below.\nOther topics you can read about in this month’s newsletter include:\nToit’s Cloud-managed Containers on ESP32 Secure your code on ESP32 with lightweight containers, and orchestrate them through Toit’s cloud API.\nESP-USB: Espressif’s Wireless Communication Solution A USB interface is integrated into Espressif’s ESP32-S series of SoCs, enabling video streaming over Wi-Fi, accessing the Internet through a 4G hotspot, connecting to a wireless USB disk, and many other applications.\nAdding Vision to ESP32 with Edge Impulse You only need a few lines of additional code to run powerful machine-learning algorithms on ESP32, especially if you also use the Arduino framework and Edge Impulse.\nUDOO KEY Combines RP2040 and ESP32 in a New AI Dev Board UDOO KEY is a fully programmable board combining RP2040 and ESP32 into a single solution. It allows you to use either RP2040, or ESP32, or even both, so that you can build any AI project on your terms.\nRead More \u0026gt;\nHope you enjoy reading this month’s newsletter. Keep sending us your messages and requests on Facebook, Twitter, GitHub, Instagram, LinkedIn, and YouTube.\nYou can also contact us through our website or you can email us. We try to respond to all of your messages as quickly as possible!\nBest wishes,John LeeSenior Customer Support Officer.\n","date":"7 November 2021","externalUrl":null,"permalink":"/blog/september-2021/","section":"Blog","summary":"","title":"September 2021","type":"blog"},{"content":"This article was written by Scott Mabin and originally posted on his blog.\nNow I am working at Espressif I plan on publishing updates roughly every quarter just to keep the community in the loop around the esp rust effort.\nDocumentation \u0026amp; Planning # One of the hardest parts in any community project is onboarding new developers, especially in the early stages of a project where API’s, processes and tooling is changing rapidly; it can be frustrating to work on something one week, and in the next you’re fighting to get it compiling again. We began work on a book in which we will try to keep as a source of truth for the Rust esp effort. This will include install instructions, tooling guides, ecosystem overviews and much more.\nWe have also put together a road map project on github, with the aim of managing the project from Espressif’s point of view, but also to allow new contributors to pick up backlog items. Simply comment in the issue if there is something you’d like to take a stab at, we’re more than happy to assist and review. We also host bi-weekly meetings which anyone is welcome to attend, just drop a comment in the latest discussion thread.\nUsing the Rust standard library on Espressif chips # In the last post, I mentioned that was possible to use the Rust standard library thanks to @ivmarkov’s hard work; well, he’s been at it again! He pushed forward and managed to upstream the standard library changes required to build std on top of esp-idf. From Rust 1.56 it the changes will be stable, meaning it\u0026rsquo;s possible to use the upstream Rust toolchain to build the std platform for any RISC-V Espressif chip! Currently, that only includes the esp32c3 but there are more to come. This change also applies to Xtensa chips, however they still require a custom toolchain due to the lack of a backend for Xtensa in upstream LLVM. For more info in the std effort, please see the book. I\u0026rsquo;d also like to take this time to thank the upstream Rust developers for the prompt and helpful reviews, in particular @Amanieu for helping us push this over the finish line.\nCompiler # The custom toolchain is a hindrance to developer onboarding, especially if developers have to build it themselves. We now offer a prebuilt toolchains for all common OS’s under the esp-rs/rust-build repository. A few days after a new Rust release we typically have the new compiler ready, unless we run into any issues; speaking of, we now test the compiler with a few projects in CI so hopefully we don’t ship a broken compiler. Note that this extra compiler step is only required when targeting Espressif’s Xtensa based chips.\nThere have been a couple of improvements to the compiler fork since the last post, for one the patch set we have to manage has reduced in size thanks to the std library changes being upstreamed. There is now asm! support for the Xtensa architecture, which also means we have removed the old llvm_asm! macros from the xtensa crates and ported them to the new syntax.\nTooling # SVDs # SVDs have been coming along very nicely, we now have official SVDs for the esp32c3, esp32s2 and the esp32. If you have been following this effort for a while, you may be thinking we already had an esp32 SVD, well you would be correct! However, it was very hacky, missed a lot of peripherals and was all around horrible to work with. The new SVD aims to be more complete and importantly more consistent. One thing that has been missing from the official SVDs is interrupt information, however this has recently changed and interrupt information for each peripheral is now available. Overall the SVDs available now are in a great spot to feed into svd2rust and other tooling, ready for HAL creation.\nespflash # espflash is a rewrite of Espressif\u0026rsquo;s esptool.py, but also has cargo integration. It\u0026rsquo;s been under heavy development and now has a 1.0 release! Including:\nSupport for flashing: esp32 esp32c3 esp32s2 esp8266 Compression for faster flashing. Support for the esp-idf partition table format. Support for flashing a stock esp-idf bootloader. Removed support xargo \u0026amp; cargo xbuild, now focusing support on build-std. Reading back flash info. Reading some EFUSE values. elf2image functionality, for writing the formatted image to a file. Beautiful \u0026amp; helpful error messages with miette. Big thanks to all the contributors in this release, especially @icewind1991.\nprobe-rs # We have also started adding support for flashing and debugging Espressif chips with probe-rs. As the RISC-V architecture is already supported in probe-rs, we set out to add support for the esp32c3 initially. We are happy to report that probe-rs master now has a flash algorithm capable of flashing the esp32c3! The esp-flash-loader repository contains the code for the esp32c3 flash loader, but thanks for Espressif\u0026rsquo;s ROM API it should be very easy to port the algorithm to the other chips. Xtensa support for probe-rs is planned eventually, but will take some time to implement. A big thank you to the probe-rs folks, in particular @Yatekii, @Tiwalun and @Dirbaio for the reviews and assistance.\nHaving probe-rs support gives us easy access to RTT for fast, low overhead logging. We have the esp32c3 using RTT with probe-rs locally, however a few patches are required due to the esp32c3\u0026rsquo;s lack of atomics. Whilst we have contributed to crates such as atomic-polyfill these crates are quite intrusive and require other ecosystem crates to depend on them instead of core::sync::atomic. To combat this, we are in the process of writing an atomic emulation trap handler. This works by treating the esp32c3 like it has atomic support (build as riscv32imac-unknown-none-elf), and when we trap on the atomic instructions, we decode them and emulate them in software transparently. There is a performance penalty that it is roughly 2-4x slower than native instructions based on our testing, but having an atomic story is important in the embedded Rust ecosystem.\nWhat’s next? # Continue to improve the tooling around Rust with Espressif chips, until we have out of the box solutions for most stories. Continue to build and polish standard library use with Espressif chips, as well as the #![no_std] story. We would also like to explore using rustc_codegen_gcc to try and target Espressif\u0026rsquo;s Xtensa chips. The end goal will still be to upstream the Xtensa backend to LLVM, but rustc_codegen_gcc may allow targeting Xtensa chips faster as GCC already has a stable Xtensa backend.\nExpect another update early next year!\n","date":"17 October 2021","externalUrl":null,"permalink":"/blog/rust-on-espressif-chips-10-01-2022/","section":"Blog","summary":"","title":"Rust on Espressif chips — 18-10-2021","type":"blog"},{"content":"","date":"31 August 2021","externalUrl":null,"permalink":"/tags/2.0.0/","section":"Tags","summary":"","title":"2.0.0","type":"tags"},{"content":"Arduino is definitely one of the most popular embedded development frameworks, and this popularity is mostly due to its simplicity and huge community.\nThis popularity is also shared with the ESP32. When the first support was introduced for the ESP8266, Espressif saw the full potential about using Arduino on the SoCs, and all the possibilities for creating IoT products as easier as before.\nAfter all the incredible success on the ESP8266, Espressif has started the ESP32 support for Arduino. This support is based on the ESP-IDF, the official IoT Development Framework. Prior to version 2.0.0, it was based on the IDF v3.3, only supporting ESP32.\nEspressif is continuously expanding the ESP32 family, first introducing the ESP32-S2, the first SoC with embedded USB and Wi-Fi only and secondly the ESP32-C3, the first SoC with RISC-V architecture.\nTo see all ESP products, visit our product page here.\nIntroducing Arduino ESP32 2.0.0 # As the ESP32 family increases, it’s time to move forward and give Arduino ESP32 support for the recently introduced SoC’s.\nThe new version, the 2.0.0 (this is the Arduino ESP32 support version, and it’s not related to the Arduino IDE version 2.0.0) is based on the latest ESP-IDF development version and includes all new features and bugfix since the ESP-IDF v3.3. This is the major difference from the v1.0.6 and it’s also the reason for upgrading.\nWith this major update, can now support the ESP32-S2 and ESP32-C3 and in the future the ESP32-S3.\nESP32-S2 # ESP32-S2 is a highly integrated, low-power, single-core Wi-Fi Microcontroller SoC, designed to be secure and cost-effective, with a high performance and a rich set of IO capabilities.\nMore about ESP32-S2.\nESP32-C3 # ESP32-C3 is a single-core Wi-Fi and Bluetooth 5 (LE) microcontroller SoC, based on the open-source RISC-V architecture. It strikes the right balance of power, I/O capabilities and security, thus offering the optimal cost-effective solution for connected devices. The availability of Wi-Fi and Bluetooth 5 (LE) connectivity not only makes the device’s configuration easy, but it also facilitates a variety of use-cases based on dual connectivity.\nMore about ESP32-C3.\nMajor Changes and New Features Added # This version introduces major changes since the 2.0.0-alpha1.\nSome of the most important ones are:\nSupport for ESP32-S2. Support for ESP32-C3. Upload over CDC. Support for the KSZ8081 (Ethernet PHY). LittleFS update for partition label and multiple partitions. Added support for RainMaker. BLE5 features for ESP32-C3 (ESP32-S3 ready). ESPTOOL update. Added FTM support. Online Documentation added. See here. USB MSC and HID support (ESP32-S2 only). UART refactoring (SerialHardware). New examples. Boards added. Bugs fixed. See the complete list here.\nHow to Upgrade to v2.0.0 # To install or to upgrade to version 2.0.0, see this detailed process on our online documentation.\nYou can also install directly from the Arduino IDE, PlatformIO (supported on Windows, Linux and macOS).\n","date":"31 August 2021","externalUrl":null,"permalink":"/blog/2021/08/arduino-esp32-support-version-2-0-0-is-out/","section":"Blog","summary":"Announcement of Arduino 2.0.0 release.","title":"Arduino ESP32 support version 2.0.0 is out!","type":"blog"},{"content":"","date":"31 August 2021","externalUrl":null,"permalink":"/tags/version-2.0.0/","section":"Tags","summary":"","title":"Version 2.0.0","type":"tags"},{"content":"Hi everyone,\nEarlier this month, a workshop focusing on ESP32 applications took place in the Milwaukee School of Engineering, a non-profit university in Winsconsin, USA. The workshop was run by Peter Haydock, founding director of Gearbox Labs, which produce project-based STEM and STEAM resources. The workshop was part of Building2Learn, which is an innovative program connecting engineering, construction and manufacturing industries to Milwaukee’s next generation of talent.\nThrough this workshop, students had the opportunity to develop academic proficiency, life skills, and career plans as they learned how to use new technologies in real work environments. Peter Haydock said after the workshop: “Seeing so many motivated future coders and engineers working on our IoT projects inspires us. We were honored to work with students on setting up their internet-connected smart-home prototypes. The Espressif SystemsESP32 was perfect for their projects!”\nGearbox Labs’ Workshop at MSOE, focused on ESP32! [Photo courtesy of Gearbox Labs’ Facebook profile.]\nOther topics you can read about in this month’s newsletter include:\nImprovements to the ESP-IDF Installation Process and Tooling Over the past few years, we have received requests from our customers to simplify the ESP-IDF installation process and usage. This article describes some of the recent improvements in this area.\nReleasing LTS of AWS IoT Device SDK for Embedded C on ESP32 Since 2017, Espressif SoCs have been capable of connecting to the AWS IoT Core and related services. There are two ways to connect Espressif Wi-Fi SoCs to the AWS IoT Core. Click here to see how.\nCheck out ESP-DL! ESP-DL is a library for high-performance deep learning resources dedicated to Espressif SoCs. ESP-DL provides APIs for Neural Network (NN) Inference, Image Processing, Math Operations and Deep Learning Models.\nMagicbit: An ESP32-Driven Dev Board on Kickstarter Magicbit adds a bit of …magic to the projects of IoT beginners and seasoned professionals alike! This new ESP32-powered, Arduino-compatible dev board got fully funded on Kickstarter in just four hours!\nMeet the ESP-EYE-Powered Doc InSight Created by American engineer Nick Bild, Doc InSight provides an augmented reality heads-up display driven by ESP-EYE and built into a pair of glasses. It is designed specifically for healthcare professionals, and aims to help them treat their patients more efficiently.\nRead More \u0026gt;\nHope you enjoy reading this month’s newsletter. Keep sending us your messages and requests on Facebook, Twitter, GitHub, Instagram, LinkedIn, and YouTube.\nYou can also contact us through our website or you can email us. We try to respond to all of your messages as quickly as possible!\nBest wishes,John LeeSenior Customer Support Officer.\n","date":"27 August 2021","externalUrl":null,"permalink":"/blog/august-2021/","section":"Blog","summary":"","title":"August 2021","type":"blog"},{"content":"","date":"25 August 2021","externalUrl":null,"permalink":"/tags/aws-iot/","section":"Tags","summary":"","title":"Aws Iot","type":"tags"},{"content":"","date":"25 August 2021","externalUrl":null,"permalink":"/tags/aws-iot-core/","section":"Tags","summary":"","title":"Aws Iot Core","type":"tags"},{"content":" Since 2017, Espressif SoCs have been capable of connecting to the AWS IoT Core and related services. There are two ways to connect Espressif Wi-Fi SoCs to the AWS IoT Core.\nThe first one is by using Amazon provided FreeRTOS distribution. The FreeRTOS distribution is an all-inclusive solution, providing the kernel, the connectivity libraries, and its own build system. This offers a seamless way of connecting qualified SoCs to AWS IoT and related services. Yet, there are certain limitations on using this FreeRTOS distribution with Espressif SoCs. The SMP support to utilise multiple cores of SoCs like ESP32, as well as support for newer SoCs like ESP32-C3 are not yet available through the FreeRTOS distribution.\nThe second way of connecting an Espressif Wi-Fi SoC to the AWS IoT Core, is by using the IoT Device SDK for Embedded C which is a stand-alone library, that includes support for MQTT and Device Shadow. However, support for other AWS services like OTA and Device Defender, was not available in this agent until recently.\n202009.00 and newer releases of the IoT Device SDK for Embedded C include a larger set of libraries for connecting to various AWS services (AWS IoT MQTT Broker, Device Shadow, AWS IoT Jobs, AWS IoT Device Defender, AWS IoT Over-the-air Update Library etc.). Additionally, the above-mentioned newer releases provide maximum flexibility by allowing the LTS releases of the AWS libraries to be used separately. This option gives developers the freedom to choose from different Espressif SoCs and versions of ESP-IDF, which allows for effective integration.\nOn that account, we have just launched support for the 202103.00 release of the SDK in beta, for Espressif boards: https://github.com/espressif/esp-aws-iot/tree/release/beta\nAt the time of writing this article, the beta release supports the following AWS Standard LTS libraries :\ncoreHTTP coreJSON coreMQTT corePKCS11 and the following AWS LTS libraries :\nAWS IoT Device Shadow AWS IoT Jobs AWS IoT OTA To simplify the use of these libraries, we have made the following examples available:\ncoreMQTT with TLS Mutual Authentication Device Shadow Example Jobs Example OTA over MQTT coreHTTP with TLS Mutual Authentication OTA over HTTP Let us take take a look at the Device Shadow library and the corresponding example to see how we can use it easily:\nNote: The following section assumes that the reader is familiar with using AWS IoT from the Web console, and has ESP-IDF setup on their computer.If have not setup the AWS IoT Core, follow steps given here.If you have not installed ESP-IDF, follow steps given here.\nBegin by cloning the repository, checking out the release/beta branch and updating the submodule.Then, navigate to the Device Shadow example and set the AWS IoT endpoint, identifier and port.\nNote: The example has been tested with ports 8883 and 443. In general, port 8883 is for secured MQTT connections. Port 443 requires the use of the ALPN TLS extension with the ALPN protocol name, which is not required when using port 8883.More on this here: https://aws.amazon.com/blogs/iot/mqtt-with-tls-client-authentication-on-port-443-why-it-is-useful-and-how-it-works/\nOpen menuconfig and set the required values.Add the device certificates, as shown here.Finally, build and flash the example onto your Espressif SoC.\ngit clone --recursive https://github.com/espressif/esp-aws-iot cd esp-aws-iot git checkout release/beta git submodule update --init --recursive cd examples/thing_shadow idf.py menuconfig # Set example and connection configuration here. idf.py build flash monitor –p \u0026lt;UART port\u0026gt; You should now start seeing logs on your console every few seconds, describing the current status.The README within the example contains more detailed steps and troubleshooting instructions, should you run into any issues.\nWhile the port of these libraries to the ESP32 platform is in beta, they are ready to be used for development. We will continue to work on adding more examples and porting other available LTS libraries.They will be out of beta once the qualification is complete.\nIf you have any questions or face any problems, you can file an issue on our repository.\nThanks Amey Inamdar\n","date":"25 August 2021","externalUrl":null,"permalink":"/blog/support-for-lts-release-of-aws-iot-device-sdk-for-embedded-c-on-esp3/","section":"Blog","summary":"","title":"Releasing LTS of AWS IoT Device SDK for Embedded C on ESP32","type":"blog"},{"content":" Hi everyone,\nAn exciting IoT contest has just been launched by Amazon Web Services (AWS) on hackster.io. It is entitled “Reinventing Health Spaces” and the challenge for developers across the world is to build an open-source, healthy-spaces solution using M5Stack Core2 for the AWS IoT EduKit reference hardware, AWS IoT Core, and at least one other cloud service. We, at Espressif, are particularly happy about this event, because the AWS IoT EduKit is based on ESP32. AWS IoT EduKit also works seamlessly with ESP RainMaker, as is mentioned in the EduKit’s Getting-Started guide.\nAs the contest organizers have put it: “The COVID-19 pandemic has placed a spotlight on the importance of public health and safety. […] As cities begin to open back up and people can gather once again in homes, businesses, and public spaces, it’s more important than ever to have strong safety protocols and continue innovating new solutions that keep us safe. These may include temperature screenings, physical distancing guidelines, face-covering requirements, occupancy limits, and enhanced cleaning and air flow. Technology can clearly play a role in reinventing how we keep people healthy by making it easier to follow safety protocols and best practices”.\nSo, we can’t wait to see what the community will invent!\nAll submissions must include an article on the Hackster website about your entry for the competition, open-source code, and either images or a short video demonstrating your solution. The deadline for submitting it to the contest is August 15, 2021, at 8:00pm Pacific Time. Winners will be announced on August 31, 2021. To get all the details about the “Reinventing Healthy Spaces” contest, you can check out the relevant article on hackster.io.\nOther topics you can read about in this month’s newsletter include:\nNew ESP RainMaker Features The latest additions to ESP RainMaker’s feature set include node sharing, timezone setting, Arduino support, and node grouping.\nESP-HMI: Smart Interaction — Boundless Communication ESP-HMI is Espressif’s high-performance and low-cost solution for enabling smart interaction between people and AIoT devices.\nESPGateway: A Powerful ESP32-based Device by ThingPulse Connecting two ESP32 SoCs via a serial connection, attaching an external (Wi-Fi) antenna to each of them, and tucking them away in a pretty enclosure opens up a number of interesting opportunities.\n","date":"21 July 2021","externalUrl":null,"permalink":"/blog/june-2021/","section":"Blog","summary":"","title":"June 2021","type":"blog"},{"content":" Today we are announcing ESP Insights.\nESP Insights is a device observability framework that allows developers to remotely peek into their firmware to get rich information about the firmware execution; and analyse this to pin-point issues and bottlenecks. This observability should help organisations save valuable engineering resources, allowing them to speed up firmware development and fix issues within a shorter turn-around time.\nIn the preview release that we launched today:\nYou can observe the critical logs , or errors that the firmware has generated during its execution. If the firmware crashed, you can observe the register dump and the backtrace , to help you understand what may have been going on with the device. You can look at a device timeline that shows the events of interest. You can add your custom events to show up on this timeline. You can observe firmware metrics like the amount of free heap over a timeline. You can view the current values of certain variables of interest. The Insights agent in the firmware leverages the Wi-Fi connectivity, and allows devices to post this information to the Insights cloud. The Insights cloud collects this information, from all the deployed devices, and compiles them into meaningful representations. Firmware developers can view this information through a web-based dashboard, the Insights dashboard.\nWhy ESP Insights? # In multiple discussions with our customers, we noticed a pattern. As software development progresses and gets closer to the initial alpha, or beta runs, the observability into the firmware diminishes. What was easily visible as console logs and through CLIs to the developer, is now hidden when the firmware is packaged into the final ID. The trial or beta runs, indicate there may be issues, but there is no faster way to recreate them in a dev/QA environment.\n1. Launch Products Faster # Beta test runs expose the product to a real-life uncontrolled environment: the development board is packaged into an industrial design and actually deployed in user’s home. The idea of these runs is to get information to your engineering team about firmware stability and issues as might be observed with the user’s environments. ESP Insights allows developers, sitting on their desks, to view stack back-traces and register dumps for firmware running on devices in these runs. Turn-around time for fixing issues is much shorter for developers that have rich information about issues. Most teams spend enormous amounts of time recreating issues based on the scanty user-visible symptoms reported to them. ESP Insights captures and reports details about errors or warnings as observed on the device firmware. Of particular interest are events generated just before a crash. ESP Insights preserves these events across a device reset, so that it is reported to the cloud once the device is back up again. 2. Fix Issues Before they Snowball # Monitoring Device Health by tracking key metrics such as available free memory, or largest free block, allow developers to understand the kind of stress the device gets under and plan for these better in their upcoming firmware versions. Detailed Crash Backtraces on the ESP Insights console allow developers to start working on issues even before customers may notice them. Integration with ESP RainMaker # Today, the preview release for ESP Insights works with ESP RainMaker. What this implies is that we leverage the ESP RainMaker platform for device-authentication and device-cloud transport.\nWe will soon follow-up with another release for customers who wish to use ESP Insights by itself.\nGetting Started # Please refer to the Getting Started section for steps on setting up esp-insights for your ESP32.\nWe are excited to start this journey with ESP Insights. Our release today is but a small step towards, what we believe, will be a rich platform that assists developers in novel ways, to building more robust software faster.\nTitle image picture credits: pixabay\n","date":"5 July 2021","externalUrl":null,"permalink":"/blog/introducing-esp-insights/","section":"Blog","summary":"","title":"Introducing ESP Insights","type":"blog"},{"content":"ESP RainMaker has been around for more than a year now and we have been adding quite some features to it every few months. Here we are now, with some more new features.\nNode Sharing # ESP RainMaker allows a user to control a node remotely over the Internet. However, there is often a need to allow others to use the same node. It could be something like giving control of lightbulbs to members of your family, or temporarily giving access to a door lock to your tenant or a maid, or something like a shared hardware resource being accessed remotely by multiple employees. To serve such use cases, ESP RainMaker offers an ability of sharing a node with others.\nTo share a node, go to the parameters control page by tapping the device tile on the home page, click on the (i) on top right and then scroll own to the bottom where you can find an option to Add a new member. Note that you can add only those users who have already signed up for RainMaker. The user who shares the node is called the primary user for the node, whereas all the other users added are called secondary users.\nThe secondary user with whom the node was shared can open the phone app, and under the User profile page, go to “Sharing Requests”. It will show all the sharing requests received, which can then be accepted or declined. Soon, we will provide push notifications to alert users that someone has shared RainMaker nodes with them.\nOnce the sharing is accepted, the secondary user can control and monitor the node, in the same way as the primary user. However, he/she cannot share it further. For more information, check out the ESP RainMaker docs.\nTimezone Setting # ESP RainMaker already had support for Timezones on the device side. The various ways in which this could be used can be found ESP RainMaker docs. However, the support on phone app side was missing, making it a bit hard to set timezone on the devices at run time. The latest phone apps now have an option to set this on the Node details page. Moreover, to prevent cases wherein people may forget to set the timezone explicitly from the Node details page, we have also added this in the “Adding device” workflow. So, after provisioning and user-node association is done, the phone app automatically sets the device timezone to match the phone’s timezone.\nArduino Support # Even though we have taken quite some efforts to make developer on-boarding easy, by ways of the ESP IDF Windows Installer and the Eclipse and VSCode plug-ins, we do understand that a lot of makers/hobbyists would still prefer Arduino due to its simplicity and cross platform support. That’s why we have now added the ESP RainMaker support in Arduino. Check out ESP RainMaker now in Arduino post for more information.\nNode Grouping # As people start using more and more Smart devices, it often gets hard to view and manage them from the phone apps. To make that simpler, we have added a concept of Node grouping. You can create logical or abstract groups of your nodes using the RainMaker app. For some users, the groups can be based on rooms; for others, they could be based on device types. The choice is yours. Group management is available directly on the homepage as you can see in this screenshot.\nEven though the phone apps have only single level groups, the RainMaker backend supports even sub groups. You can check out the Grouping APIs at Swagger if you are interested.\nApart from these features, we have made quite some visual and convenience related improvements. Download our latest apps from RainMake docs and check these out for yourself. You can give your feedback either on GitHub or the forums.\n","date":"25 June 2021","externalUrl":null,"permalink":"/blog/new-features-in-esp-rainmaker/","section":"Blog","summary":"","title":"New Features in ESP RainMaker","type":"blog"},{"content":" Since its launch in April 2020, we have been making quite some improvements to ESP RainMaker, mostly around the feature set. Along with that, we have also been making efforts to make developer on-boarding easier. The ESP IDF Windows Installer and the Eclipse and VSCode integrations especially have been useful for a lot of developers. One common request we still kept getting was support for Arduino, since getting started with it is much more convenient for many developers and it is also easier to migrate from other chips/platforms since the IDE and code structure is familiar.\nSo, here it is. The support for ESP RainMaker in Arduino is now live.\nOverview # A sample sketch for a switch has been included. Let’s quickly look at the code that enables this.\n//GPIO for switch relay static int gpio_switch = 16; // The framework provides some standard device types like switch, lightbulb, // fan, temperature-sensor. You may add your own as well. static Switch my_switch(\u0026#34;Switch\u0026#34;, \u0026amp;gpio_switch); void setup() { // Create a RainMaker Node Node my_node = RMaker.initNode(\u0026#34;ESP RainMaker Node\u0026#34;); //Add the switch device to the node my_node.addDevice(my_switch); // Add processing callback to the switch (This is what will get called when // the state of the switch is updated using the phone-app or voice-assistants my_switch.addCb(write_callback); // Enable RainMaker features to be supported (we enable Schedules and OTA here) RMaker.enableOTA(OTA_USING_PARAMS); RMaker.enableTZService(); RMaker.enableSchedule(); RMaker.start(); // Hand-over the control for Wi-Fi Provisioning. If a Wi-Fi network is not yet configured, // this will start the provisioning process, else it will connect to the Wi-Fi network WiFiProv.beginProvision(WIFI_PROV_SCHEME_BLE, WIFI_PROV_SCHEME_HANDLER_FREE_BTDM, WIFI_PROV_SECURITY_1, pop, service_name); } With the above few lines of simple code, our fully functional smart switch is ready. The switch can be controlled with the Android and iOS applications, as well as Alexa and Google Voice Assistant skills.\nWhen we execute this code:\nThe device will first check if a Wi-Fi network is configured. If the network is not configured, it will launch the provisioning process. The device can then be configured using the phone apps mentioned above. If Wi-Fi configuration is found, it will connect to the configured network. Once connected, it will connect to the RainMaker cloud, looking for commands to modify its parameter (switch state in this case). The device will also look for commands on the local Wi-Fi network. When somebody changes the switch state using phone apps or voice integrations, the write_callback() gets called. This is then implemented as: void write_callback(Device *device, Param *param, const param_val_t val, void *priv_data, write_ctx_t *ctx) { const char *param_name = param-\u0026gt;getParamName(); if(strcmp(param_name, \u0026#34;Power\u0026#34;) == 0) { switch_state = val.val.b; (switch_state == false) ? digitalWrite(gpio_switch, LOW) : digitalWrite(gpio_switch, HIGH); param-\u0026gt;updateAndReport(val); } } The function takes the new switch output value and\nupdates in our internal state, calls the driver to update its GPIO state reports back to the cloud the new state There, that’s a fully functional Smart Switch in action. A few common device types are already supported in the data model (bulb, fan, switch), but you can add yours too.\nGetting Started # Before you even get started, a few points to note\nFor using RainMaker, you first have to get started with the ESP32 support in Arduino. RainMaker support is not yet part of a stable esp32-arduino release. So we will use the master branch of the ESP32 Arduino repository. We will update here and elsewhere once this support is available in a stable release. Currently, only ESP32 is supported. Support for ESP32-S and ESP32-C series is coming soon. Once your Arduino is set-up with the ESP32 support, follow these steps\nBoard: “ESP32 Dev Module” Flash Size: “4MB” Partition Scheme: “RainMaker” Core Debug Level: “Info” Port: Choose the appropriate ESP32 port as per your Host platform from the list. By connecting/disconnecting your ESP32 board, you can find out the port number. This is the complete list for reference:\nNow, go to File -\u0026gt; Examples -\u0026gt; Examples for ESP32 Dev Module -\u0026gt; ESP RainMaker -\u0026gt; RMakerSwitch\nUpload the Sketch onto your ESP32 board by clicking on the Upload button in the IDE, or going to Sketch -\u0026gt; Upload\nGo to Tools -\u0026gt; Serial Monitor. Choose 115200 as Baud. If you do not see anything in the monitor window, reset your board (using the RST button).\nDownload the ESP RainMaker phone app, sign-up or sign-in and you are ready to go.\nFollow the instructions in the Serial Monitor to add the switch from the RainMaker app. (If you do not see the instructions, double check the “Core Debug Level: Info” option under Tools)\nAny control from the phone app should now reflect on the device and any change on the device (by pressing the BOOT button) should reflect in the phone app.\nYou can press and hold the BOOT button for more than 3 seconds and then release for Resetting Wi-Fi, and for more than 10 seconds to Reset to Factory defaults.\nPlease check out here to understand more about ESP RainMaker. Even though all the RainMaker APIs are expected to work seamlessly with Arduino, we have provided some simplified APIs to suit typical Arduino codes, as you can see here.\nJohn Macrae is active in our ESP32 maker community and he had created this video when Arduino support was launched. His newer video demonstrates the improvements introduced recently and also shows how to build a custom device.\nHope you enjoy RainMaker, have fun hacking!\n","date":"14 June 2021","externalUrl":null,"permalink":"/blog/esp-rainmaker-now-in-arduino/","section":"Blog","summary":"","title":"ESP RainMaker now in Arduino","type":"blog"},{"content":" This tutorial was created based on the Arduino for ESP32 version 2.0.0-alpha1 (preview version) on April 30th, 2021.\nIf you were waiting for the ESP32-S2 and ESP32-C3 support for Arduino, you will soon have it!\nFew days ago, we released the preview support for the S2 and C3. This is still a work in progress, but we will let you have some early access to both chips.\nThe ESP32-S2 was released in the end of 2019 and it’s the first ESP32 with USB support. To see more details about the S2, see this datasheet.\nAt end of 2020, ESP32-C3 was announced to be Espressif’s first RISC-V SoC and soon will be ready for shipment to developers, customers and distributors all over the world.\nThis means that most of you will receive the new ESP32-C3 and it will be already supported in the Arduino framework!\nThe Arduino core for the ESP32 version 2.0.0 is a huge milestone for the community, not only for the new chip support but also due to the upgrade in the ESP-IDF (running under the hood of the Arduino framework). This adds new functionalities that can be added to the Arduino framework as well as a possibility to get future support to the ESP32-S3 faster than the ESP32-S2.\nFor now, we are offering the preview version. Some work is still in progress to fully support these new chips. We will get everything working smoothly in the near future with the help of our community!\nYou can track all work in progress by following our GitHub repository. If you find any issue or missing functionality, don’t hesitate to create a new issue!\nespressif/arduino-esp32If you want to test ESP32-S2 and/or ESP32-C3 through the board manager, please use the development release link…github.com\nSee “how to contribute” for more details on how to help us to improve.\nNew Supported SoC # ESP32-S2 # ESP32-S2 is a highly integrated, low-power, single-core Wi-Fi Microcontroller SoC, designed to be secure and cost-effective, with a high performance and a rich set of IO capabilities.\nTo learn more about the ESP32-S2, click here!\nESP32-C3 # ESP32-C3 is a single-core Wi-Fi and Bluetooth 5 (LE) microcontroller SoC, based on the open-source RISC-V architecture. It strikes the right balance of power, I/O capabilities and security, thus offering the optimal cost-effective solution for connected devices. The availability of Wi-Fi and Bluetooth 5 (LE) connectivity not only makes the device’s configuration easy, but it also facilitates a variety of use-cases based on dual connectivity.\nTo learn more about the ESP32-C3, click here!\nHow to Get Started? # If you want to try this new version, you just need to update your ESP32-Arduino install by following these steps.\nFirst, go to our GitHub repository: arduino-esp32\nFor Arduino IDE \u0026lt; 2.0\nIf you are using the Arduino IDE \u0026lt; 2.0, you can install or update using these steps:\nFile → Preferences\nAdd the “https://raw.githubusercontent.com/espressif/arduino-esp32/gh-pages/package_esp32_dev_index.json ”to Additional Boards Manager URLs and click OK.\nTo install it, go to Tools → Boards → Boards Manager and you will find the “esp32” by Espressif Systems in the list.\nBe sure to select the version 2.0.0-alpha1.\nIf the version 2.0.0 isn’t in the list, update the JSON link in the “Additional Boards Manager URLs” and restart the Arduino IDE.\nFor the Arduino IDE 2.0:\nThe process for the Arduino IDE 2.0 is very similar to the early version.\nFile → Preferences\nAdd the “https://raw.githubusercontent.com/espressif/arduino-esp32/gh-pages/package_esp32_dev_index.json ” to Additional Boards Manager URLs and click OK.\nTo install it, go to Tools → Boards → Boards Manager and you will find the “esp32” by Espressif Systems in the list.\nYou can finally start using the ESP32-S2 and ESP32-C3 SoC with Arduino!\nConclusion\nWe are all excited with this preview version release to give you the chance to try our new chips using Arduino.\nAdditionally, your feedback is very important! We are looking forward to hearing from you. Let us know how we can improve the development experience.\n","date":"8 June 2021","externalUrl":null,"permalink":"/blog/2021/06/arduino-for-esp32-s2-and-esp32-c3-is-coming/","section":"Blog","summary":"Announcing support for new devices to the Arduino Core for Espressif. How to enable them in the 2.0.0rc1 release.","title":"Arduino for ESP32-S2 and ESP32-C3 is coming!","type":"blog"},{"content":" If you are starting on ESP32 development, you will see that the ESP-IDF is the official development framework and Espressif actively maintains it with constant updates.\nThe ESP-IDF is a collection of different things. We have the development framework which provides a comprehensive Software Development Kit, and it also includes the toolchain (the compilers are installed separate from the ESP-IDF folder), documentation, example codes, and a set of tools.\nThese tools are particularly important and commonly used in many different scenarios in the development process.\nThis guide will introduce some tools that are not commonly used and could help you on specific tasks or to be used for automation process for example.\nTo access the documentation reference about the complete Build System, including the idf.py, see: Build System on our official documentation.\nESP-IDF Introduction # Before starting on the tools themselves, it is important to explain the basic structure of the ESP-IDF. This part will be very introductory and more informative. We will explore it more in detail in future articles.\nThe ESP-IDF means Espressif IoT Development Framework and was created to provide the full development environment for IoT applications, including the SDK, installation scripts, components, documentation, examples, build system, compilers, and tools. It is required to develop the application on the ESP32 (not compatible with ESP8266).\nThe ESP-IDF is compatible with all ESP32 SoC series, including the Xtensa and RISC-V cores.\nCurrently, the ESP-IDF is available on our GitHub.\nespressif/esp-idfESP-IDF is the official development framework for the and ESP32-S Series SoCs provided for Windows, Linux and macOS…github.com\nContributions from the community are very welcome! To know how to contribute, please see: How to Contribute.\nThe ESP-IDF is composed of various parts, detailed below:\nComponents # The components are where the SDK is located. It contains several components used for the bootloader, FreeRTOS, drivers, stacks and libraries.\nDocumentation # The ESP-IDF includes the documentation needed for developers to create and use all the features available. This documentation is also available online.\nFor ESP32, ESP32-S2 or ESP32-C3.\nOr: Getting Started with ESP-IDF.\nExamples # We provide a set of examples on each peripheral and functionality, so you can start your project using one of those examples. Most of the examples were written in C and a few in C++.\nYou can find examples from blinking a LED, to connect to Wi-Fi, Bluetooth, protocols, storage, systems functions, and many others. This section is continuously updated to provide new examples for each new release.\nTo see more: ESP-IDF Examples.\nTools # The tools referred in this article are the specific ESP-IDF tools. They are not the tools installed in the Operating System, like CMake, git, dfu-utils, and many others required tools.\nThe ESP-IDF tools are a set of scripts, most created in Python, to help with various tasks, from configuring the SDK to programming the ESP32. All the tools are available directly from the virtual environment terminal.\nThe following is the list of the tools available on the ESP-IDF v4.3:\nidf.py – It is a command-line tool and provides a front-end for managing your project builds. esptool.py – This tool is a ROM bootloader utility used to perform memory-related, like read, write, erase, dump, etc. otatool.py – It is a set of commands to deal with the OTA partitions and configuration. parttool.py – This tool is similar to the otatool.py but more generic. You can use this to read, write, erase and get partitions information. espefuse.py – The espefuse manages the efuses and gets states from them. This tool must be used very carefully since some operations are irreversible. espsecure.py - It is the Secure Boot \u0026amp; Flash Encryption tool, used for secure operations. Installing ESP-IDF for Windows, Linux and macOS: To install the ESP-IDF in your system, you can follow the Getting Started guide in the documentation.See the Getting Started page to start using ESP-IDF.We also have some tutorials on the Espressif Official YouTube channel.\nESP-IDF Tools # To start using the tools, we need to open a terminal window and set the virtual environment variables. This can be done by running the export script, included on the ESP-IDF.\nWindows Command Prompt:\n%userprofile%\\esp\\esp-idf\\export.bat or for PowerShell:\n.$HOME/esp/esp-idf/export.ps1 Linux/macOS:\n. $HOME/esp/esp-idf/export.sh In this guide, the idf.py and esptool.py will be addressed first. The other tools will be covered in the other guides.\nIDF Tool # The idf.py is the main command tool and it is widely used.\nThe main feature of this tool is to serve as a front-end. It invokes the build system, currently supporting CMake, creates new project, components, prepares the DFU binary, configures the SDK, program the firmware to the device, etc. Other features are included on the idf.py and the commands will be described below:\nTo see the full list of commands supported, type in the terminal:\nidf.py \u0026ndash;help\nNote: Some commands are target-dependent and may not be available on other targets. To see all the commands supported by the target, run the set-target command before.\nidf.py set-target [TARGET]\nTo see all the targets supported:\nidf.py set-target \u0026ndash;help\nThe command syntax may vary from command to command, but the basic structure is:\nUsage: idf.py [OPTIONS] COMMAND1 [ARGS]\u0026hellip; [COMMAND2 [ARGS]\u0026hellip;]\u0026hellip;\nHere is the list of the most used commands as well as some that are helpful. Not all commands will be covered in this guide, so specific guides will be created to cover them.\nFor the commands that requires serial connection to the device, the COM port, we can use the the option \u0026ndash;port or -p and the port.\nFor example:\nLinux: -p /dev/ttyUSB0\nor\nWindows: -p COM1\nThe COM port name and number may vary from system to system and from different Serial-to-USB converters.\nCommands: # all — Build the project. This command is used to build the full project, including the bootloader and all other required partitions. You can use build instead of all as a alias. Syntax: idf.py all or idf.py build\napp — Build the app only. This command is used if you want to build only the application and keep the other binaries (bootloader, partitions, etc) out from the build. Syntax: idf.py app\napp-flash — Flash the application only. Using this command to flash the application, all the other partitions will be kept unchanged. Syntax: idf.py p [PORT] app-flash\nbootloader — Build the bootloader only. This is similar to the app command. Syntax: idf.py bootloader\nbootloader-flash — Flash the bootloader only. This is like the app-flash but for the bootloader. Syntax: idf.py p [PORT] bootloader-flash\nclean — Cleans all the build output files from the build directory. This command is used to delete the last build file in order to re-build if needed.See also: fullclean. Syntax: idf.py clean\ncreate-component — Create a new component. This command creates a new component and all necessary files into your project. To use this command, first, you need to create a folder in your project called “components” and under the folder, you can run the following command and the new component name as an argument.\nSyntax: idf.py create-component [COMPONENT-NAME]\nAlternatively, you can use the -C option and point the path to the components folder. If the components folder does not exist, the folder will be created.\nSyntax: idf.py -C [PATH]/components create-component [COMPONENT-NAME]\nAfter that, you can simply add the new component header file to your project.\ncreate-project — Create a new project. This command is extremely helpful for creating new projects, including all necessary files to build. To create a new project using this tool, you need to go to the destination folder and use the following command.\nSyntax: idf.py create-project [PROJECT-NAME]\nIf you want to define the path to the project destination folder, you can use the -C option.\nSyntax: idf.py -C [PATH] create-project [PROJECT-NAME]\ndfu — Build the DFU binary. To create the DFU binary, use the dfu option before downloading it to the device. This option is only available if the SoC supports DFU and may not be visible before setting the target to the supported SoC.\nSyntax: idf.py dfu\ndfu-flash — Flash the DFU binary. This option is used to download the DFU binary to the device. Syntax: idf.py dfu-flash\nTo see the DFU in detail, please check the ESP32-S2 DFU API guide documentation.\nerase-flash — Erase the entire flash chip. This option is used to wipe the flash memory. Syntax: idf.py -p [PORT] erase-flash\nflash — Flash the project. This option will download the firmware binaries to the device. If the project has not been built yet, this command will trigger the build before flashing it to the device. Syntax: idf.py -p [PORT] flash\nfullclean — Delete the entire build directory contents. This option removes all files from the build folder. This command does not remove the build folder. Syntax: idf.py fullclean\nmenuconfig — Run “menuconfig” project configuration tool. This command opens the configuration menu to adjust the SDK options to your needs. Syntax: idf.py menuconfig\nmonitor — Display serial output. One of the most used option is the monitor. This option allows you to start the monitoring tool and to display all the output from the device. Syntax: idf.py -p [PORT] monitor\nTo see more details about the monitor tool, see: Monitor on our docs.\nreconfigure — Re-run CMake. This option can reconfigure your project CMake. Syntax: idf.py reconfigure\nIf you are adding a new component to your project, this function should be used to update the CMake for your new project structure.\nset-target — Set the chip target to build. This option is often used to change the target device in the current project. It’s important to mention that every time you change the target, the project creates a new SDK configuration, and all changes will be settled as the default target configuration. You will need to rebuild the project after setting the new target.\nSyntax: idf.py set-target [TARGET]\nTo see all the available targets on the current ESP-IDF version, you can use:\nSyntax: idf.py set-target\nsize — Print basic size information about the app. This allows you to check the RAM usage and the total image size. Syntax: idf.py size\nESPTOOL # The ROM Bootloader Utility, also known as esptool, is the tool used to write the firmware to the device and also for other memory and binary operations.\nBelow you will see the full list of functionalities on the esptool.py:\nesptool.py \u0026ndash;help\nThe idf.py uses the esptool.py in several commands, including flash and erase. You might need to use the esptool for some other specific reasons.\nThe esptool.py command syntax is defined below:\nUsage: esptool.py [OPTIONS] COMMAND1 [ARGS]\u0026hellip; [COMMAND2 [ARGS]\u0026hellip;]\u0026hellip;\nHere are some commands: # write_flash — Write a binary blob to the device flash. Syntax:\nesptool.py -p [PORT] write_flash [ADDRESS1] [PATH_TO_BINARY1]… [ADDRESS2] [PATH_TO_BINARY2] The write_flash command supports multiple binaries in the same command.\nThis command also allows some before-and-after commands:\n\u0026ndash;before : What to do before connecting to the chip.\ndefault_reset no_reset no_reset_no_sync This option usually is used with default_reset by the idf.py when flashing the device. For some special demands, you can change this behavior.\n\u0026ndash; after : What to do after esptool.py is finished.\nhard_reset soft_reset no_reset For this option, the idf.py default option is the hard_reset. It means that the device will be hard reset after flashing is done.\nIf you need to keep the device into download state, you can use the “no_reset” argument for this option.\nSyntax:\nesptool.py -p [PORT] --before [ARG_BEFORE] --after [ARG_AFTER] write_flash [ADDRESS] [PATH_TO_BINARY] verify_flash — Verify a binary blob against flash. This option is used to verify the integrity of the compiled version to the flashed into the device. This kind of verification is often used to check or verify possible errors after flashing the device.\nSyntax: esptool.py -p [PORT] verify_flash [ADDRESS] [PATH_TO_BINARY]\nimage_info — Dump headers from an application image. Syntax: esptool.py \u0026ndash;chip [CHIP] image_info [PATH_TO_BINARY]\nread_mac — Read MAC address from OTP ROM. Syntax: esptool.py -p [PORT] read_mac\nerase_flash — Perform Chip Erase on SPI flash. Same as idf.py erase_flash. It wipes the whole flash memory and could take some time depending on the flash size.\nSyntax: esptool.py -p [PORT] erase_flash\nerase_region — Erase a region of the flash. This partially wipes the flash memory. This can be used to erase a specific partition or some other area specified by the addresses.\nSyntax: esptool.py -p [PORT] erase_region [START_ADDRESS] [END_ADDRESS]\nNote: The parttool.py use this option on esptool.py to erase the selected partition.\nchip_id — Read Chip ID from OTP ROM, if available. Syntax: esptool.py -p [PORT] chip_id\nflash_id — Read SPI flash manufacturer and device ID. You can use this option to detect the flash information, like size and manufacturer. You can also use this to get the chip details such as:\nChip type and revision Crystal frequency MAC Address Syntax: esptool.py -p [PORT] flash_id\nmerge_bin — Merge multiple raw binary files into a single file for later flashing. This option is useful when distributing the full image. You can merge all binaries files generated by the build, including bootloader, app, partitions, ota, etc.\nMerge Command Syntax:\nesptool.py merge_bin [OUT] [OPTIONS] [ADDRESS1] [PATH_TO_BINARY1]...[ADDRESS2] [PATH_TO_BINARY2] Merge Advanced Options:\n• __--flash_freq__ : Defines the flash SPI speed (in MHz) ◦ keep ◦ 40m ◦ 26m ◦ 20m ◦ 80m• __--flash_mode__ : Defines the SPI flash memory connection mode. ◦ keep ◦ qio ◦ qout ◦ dio ◦ dout• __--flash_size [FLASH_SIZE]__ : Defines the flash memory size.• __--spi-connection [SPI_CONNECTION]:__ Defines the flash pinout configuration. If not defined, the default will be used from efuse.• __--target-offset [TARGET_OFFSET]:__ This option define the memory ofsset that the binary will be flashed. The default option is 0x0.• __--fill-flash-size [FILL_FLASH_SIZE]:__ Use this option to fill the binary with 0xff padding. This option will increase the binary size up to the defined flash size. Here is an example to merge three binaries into one for an ESP32 with 4MB of flash in DIO mode:\nesptool.py --chip esp32 merge_bin -o my_app_merged.bin --flash_mode dio --flash_size 4MB 0x1000 build/bootloader/bootloader.bin 0x8000 build/partition_table/partition-table.bin 0x10000 build/my_app.bin Note that the addresses may vary from one application to another. A good way to check this is through the partitions CSV file or the output from the command idf.py build.\nThen, the output file can be flashed at the offset 0x0.\nesptool.py write_flash 0x0 my_app_merged.bin Optional arguments # The esptool.py has some optional arguments that help the commands to be more specific or to change some default options. Here are the arguments:\nIf not set, the default will be used.\n• __--help__ : Shows the help information.• __--chip__ : Set the target chip type. Can be used to avoid mistakes such as sending a command to the wrong chip type.• __--port__ : Set the serial port device.• __--baud__ : Set the serial port device speed.• __--before__ : What to do before connecting to the chip.• __--after__ : What to do after running esptool.py.• -__-no-stub__ : Disable launching the flasher stub, only talk to ROM bootloader.• __--trace__ : Enable trace-level output of esptool.py interactions.• __--override-vddsdio__ : Override ESP32 VDDSDIO internal voltage regulator (use with care).• __--connect-attempts__ : Number of attempts to connect, negative or 0 for infinite. Default: 7. Conclusion # The get the full potential of the ESP-IDF, you must also know how to use the set of tools available. Using these tools’ functionalities, you can build automation for your project or manufacturing process, creating scripts that perform specific functions.\nMastering the ESP-IDF tools could save time and get your development process even easier on the daily tasks!\n","date":"8 June 2021","externalUrl":null,"permalink":"/blog/esp-idf-development-tools-guide-part-i/","section":"Blog","summary":"","title":"ESP-IDF Development Tools Guide — Part I","type":"blog"},{"content":"Hi everyone,\nAt the beginning of the month, Espressif’s Founder and CEO, Mr Teo Swee-Ann, gave an interview to the Electronic Engineering Times (EETimes), a leading news and analysis magazine about the latest technologies and business developments in the global electronics industry. In this interview, readers had the opportunity to learn more about Teo Swee-Ann, who holds 40 patents in circuit design and AIoT technology, is an avid Go player, a classical guitarist, a husband, and a father of four wonderful children.\nTeo Swee-Ann explained that he does not directly talk about technology with his children, but he does have conversations with them about the implications of today’s technological innovations. “I just want to make sure that they have some thoughts about these questions and their ethical consequences. […] technology should be developed and used in such a way that results in meaningful progress and a better outcome for the future generations”.\nTalking about his leadership style, Teo Swee-Ann characterized it as “variable and pragmatic”. […] “As CEO, I focus on creating value for our customers and the long-term growth of the company… [But] we are an amalgamation of 500 engineers and staff from about 30 different countries connected via face-to-face interactions, emails, messaging apps, MatterMost, Git repositories, shared docs, Zoom meetings, and our core values. We have a rather flat organization […] making decisions and [developing] strategies collectively”.\nYou can read Teo Swee-Ann’s entire interview here.\nTeo Swee-Ann: Espressif’s Founder and CEO\nOther topics you can read about in this month’s newsletter include:\nLaunching ESP32-WROOM-DA With two complementary PCB antennas, ESP32-WROOM-DA is Espressif’s new module for high-quality, long-range communication, while being pin-to-pin compatible with ESP32-WROOM-32E.\nHow to Use ‘Matter’ on ESP32 Matter is an industry-unifying standard, guided by the Connectivity Standards Alliance, for devices that have to be connected reliably, securely and seamlessly. Espressif has been part of the Matter initiative since its early days. In the following article we discuss the ways in which you can easily build your first Matter app on an ESP32.\n‘IoT Cricket’: An ESP8266-based Wi-Fi Module by ‘Things On Edge’ IoT Cricket is an ESP8266-based, easy-to-use Wi-Fi module created by the UK-based company ‘Things On Edge’. This module enables users to build various IoT devices within minutes, and power them directly on batteries, with literally no code and programming.\nE3K: An ESP32-powered Bio-sensing Platform by WallySci E3K is an ESP32-powered device that is especially designed for students and researchers. It aims at providing an affordable, fully open-source, wireless framework for an intuitive understanding of bio-signals originated from the human heart, muscles, and brain.\nRead More \u0026gt;\nHope you enjoy reading this month’s newsletter. Keep sending us your messages and requests on Facebook, Twitter, GitHub, Instagram, LinkedIn, and YouTube.\nYou can also contact us through our website or you can email us. We try to respond to all of your messages as quickly as possible!\nBest wishes,John LeeSenior Customer Support Officer.\n","date":"27 May 2021","externalUrl":null,"permalink":"/blog/may-2021/","section":"Blog","summary":"","title":"May 2021","type":"blog"},{"content":" Introduction # Matter, previously project CHIP, is the new foundation for connected things. Guided by the Connectivity Standards Alliance, and developed through collaboration amongst all the leaders of the IoT industry, Matter focuses on building connected devices that are secure, reliable, and importantly, seamless to use.\nEspressif has been a part of the Matter initiative since early days, and we have been focusing on making it easy to develop and use Matter with Espressif’s line of SoCs. In this article, we will discuss the steps to get your first Matter application up and running on an ESP32. In upcoming articles, we will discuss various technical details of Matter and explore ways to quickly build Matter certified devices on Espressif platforms.\nArchitecture # As illustrated above, Matter defines the application layer that will be deployed on devices and controllers as well as supported IPv6-based networks to help achieve the interoperability goals. Matter will initially support Wi-Fi and Thread for core communications and Bluetooth Low Energy (BLE) to simplify device commissioning and setup.\nMatter on ESP32 # Matter SDK # The Matter SDK is an open source repository for the implementation of the specification and continues to be under active development. ESP32 has been a supported platform in the Matter SDK since the very beginning. At present, it is the only platform that offers support of both Wi-Fi as well as BLE. ESP32 supports commissioning (initial device configuration) over BLE as well as Wi-Fi SoftAP; and supports operational communication over Wi-Fi.\nSample Examples # You could try either of the following examples:\nEither of these examples can be tested against a Matter controller. The Matter SDK provides reference implementation of controllers:\nGetting Started # Let’s look at the steps to try the above examples on ESP32.\nWe use Espressif IoT Development Framework (ESP-IDF) release v4.3 to try this out.\nBuild the Python Controller # $ cd /path/to/connectedhomeip$ ./scripts/build_python.sh -m platform Execute the controller and establish a secure session over BLE. BLE is the default mode in the application and is configurable through menuconfig. $ source ./out/python_env/bin/activate$ chip-device-ctrlchip-device-ctrl \u0026gt; ble-scanchip-device-ctrl \u0026gt; connect -ble 3840 20202021 135246 Parameters:\nAdd credentials of the Wi-Fi network you want the ESP32 to connect to, using the AddWiFiNetwork command and then enable the ESP32 to connect to it using EnableWiFiNetwork command. In this example, we have used TESTSSID and TESTPASSWD as the SSID and passphrase respectively. chip-device-ctrl \u0026gt; zcl NetworkCommissioning __AddWiFiNetwork__ 135246 0 0 ssid=str:__TESTSSID__ credentials=str:__TESTPASSWD__ breadcrumb=0 timeoutMs=1000chip-device-ctrl \u0026gt; zcl NetworkCommissioning __EnableNetwork__ 135246 0 0 networkID=str:__TESTSSID__ breadcrumb=0 timeoutMs=1000 Close the BLE connection to ESP32, as it is not required hereafter. chip-device-ctrl \u0026gt; close-ble Resolve DNS-SD name and update address of the node in the device controller. chip-device-ctrl \u0026gt; resolve 135246 Use the OnOff cluster command to control the OnOff attribute. This allows you to toggle a parameter implemented by the device to be On or Off. chip-device-ctrl \u0026gt; zcl OnOff Off 135246 1 0 Note: All the above commands have help associated with them that can assist with the parameters.\nThe above commands help you try the common functionality that is exposed by Matter on the ESP32.\nESP32-C3 Support # ESP32-C3 support is integrated in Matter. Please follow the READMEs to run the examples on ESP32-C3\nStay tuned for more updates on Matter and ESP32. Happy hacking!\n","date":"25 May 2021","externalUrl":null,"permalink":"/blog/announcing-matter-previously-chip-on-esp32/","section":"Blog","summary":"","title":"Announcing Matter (previously ‘CHIP’) on ESP32","type":"blog"},{"content":"","date":"25 May 2021","externalUrl":null,"permalink":"/tags/release-v4.3/","section":"Tags","summary":"","title":"Release V4.3","type":"tags"},{"content":"Hi everyone,\nRISC-V Days Tokyo is Japan’s largest live online RISC-V event, featuring presentations, virtual demo booths, and an online press conference. RISC-V Days Tokyo aims to bring together leading RISC-V technologies and products, key persons and engineers, while providing business opportunities for product recognition, collaboration among companies, and exchange of information among industry experts. Last year’s event attracted a total of 1,053 participants from 11 countries.\nThis year’s event took place on 22–23 April and, of course, Espressif was there. On 22 April 2021, Espressif’s Senior Software and Technical Marketing Manager, Jeroen Domburg, made a presentation of ESP32-C3, which is Espressif’s recently released, RISC-V-based Wi-Fi+Bluetooth LE SoC. With more than twenty years of experience in embedded systems, Jeroen is involved with both the software and the hardware design process of Espressif’s microcontroller units. Thus, Jeroen discussed the technical specifications of ESP32-C3, which is a SoC intended for IoT connectivity with WiFi and Bluetooth LE. The launch of this chip has also marked Espressif’s first SoC with a RISC-V processor at its core and, therefore, Jeroen talked about our experience of changing over to a RISC-V-based solution.\nJeroen Domburg: Espressif’s Senior Software \u0026amp; Technical Marketing Manager\nOther topics you can read about in this month’s newsletter include:\nAnnouncing ESP32-C6: a Wi-Fi 6 + Bluetooth 5 (LE) SoC ESP32-C6 is Espressif’s first low-power and cost-effective Wi-Fi 6 + Bluetooth 5 (LE) SoC, with a 32-bit RISC-V core, for securely connected devices. ESP32-C6 is already certified by Wi-Fi Alliance.\nESP32-C3 Is Now Wi-Fi CERTIFIED™ ESP32-C3 has passed the Wi-Fi Alliance certificationfor providing industry-leading, Wi-Fi connectivity, and high-standard data security to private users and enterprises alike.\nESP32-S2-HMI-DevKit-1 for Human-Machine Interaction Espressif recently launched ESP32-S2-HMI-DevKit-1, which is specifically designed for human-machine interfaces in smart-home automation controllers, smart speakers with a display, smart alarm clocks, etc. It comes with a 4.3-inch color LCD and a touch panel.\n“App Fairy” for ThingPulse ESP-based Devices Released ThingPulse has recently developed the App Fairy, in order to make their ESP-based devices more accessible and user-friendly. The App Fairy is a self-contained app store for your computer. It allows you to install and configure applications for ThingPulse devices, without editing any source code.\nESP32-based Autonomous Sensors by VZ VocalZoom (VZ), a provider of laser sensors for industry 4.0, has just launched its ESP32-basedAutonomous Sensors for the Industrial Internet of Things (IIoT).\n","date":"30 April 2021","externalUrl":null,"permalink":"/blog/apr-2021/","section":"Blog","summary":"","title":"Apr 2021","type":"blog"},{"content":"","date":"25 April 2021","externalUrl":null,"permalink":"/tags/esp32-programming/","section":"Tags","summary":"","title":"Esp32 Programming","type":"tags"},{"content":"Espressif launched ESP32-C3 at the end of 2020. It’s very well received and now it’s already in the mass production state. ESP32-C3 provides Wi-Fi and Bluetooth LE connectivity for applications in the most cost-effective way. For the users of ESP32 who use it for Wi-Fi and/or BLE connectivity, ESP32-C3 is a possible upgrade option provided other requirements match. So let’s first take a look at the comparison of ESP32 and ESP32-C3 from that perspective.\nThe users who have used ESP32 have a common question about how does 400 KB SRAM compare against 520 KB SRAM of ESP32 as many of the times memory availability is a critical factor for embedded applications. In this article, I provide overview of enhancements done related to memory management in ESP32-C3 and show how ESP32-C3 can provide better or the same memory headroom in comparison with ESP32 for various application use-cases.\nMemory Subsystem Improvements and Optimisations # Dynamic IRAM-DRAM Split # The above two diagrams show memory maps of ESP32 and ESP32-C3 respectively. As you can see, ESP32 has static IRAM-DRAM partitioning where 192KB SRAM is used as IRAM and then remaining 328KB SRAM is used as DRAM. Part of IRAM (32 or 64KB) is used as flash cache. Then linker script is used to fill IRAM with the code that can’t be in the flash memory due to functional or performance reasons. The unused IRAM beyond this, remains unused* by the application.\nIn case of ESP32-C3, there is no static partitioning of IRAM and DRAM. ESP32-C3 has 16KB flash cache at the beginning of SRAM. IRAM and DRAM addresses increment in the same direction unlike ESP32. Based on the application, the linker script allocates IRAM as required for the application. The DRAM begins right where IRAM ends. Hence the memory is used more efficiently in case of ESP32-C3 than ESP32.\nReduced IRAM Utilisation # ESP32-C3 has reduced IRAM utilisation than ESP32. This is result of the following two efforts\nImproved Bluetooth Memory Management # ESP32’s Bluetooth subsystem requires a contiguous memory (56KB for dual-mode and 38KB for BLE) at a fixed location in the DRAM. This is a considerable disadvantage if the application requires to use Bluetooth functionality but not continuously. In such case this memory remains occupied even when not used.\nESP32-C3 doesn’t require Bluetooth memory to be contiguous and at fixed location. ESP32-C3 Bluetooth subsystem allocates memory using standard system heap and hence Bluetooth can be enabled and disabled by the application as and when required. All this needs is sufficient memory to be available in the heap.\nMemory Consumption for Common Use-cases # With the above mentioned 3 reasons, ESP32-C3 can provide more effective memory usability for the applications. Let’s consider some common application use-cases and let’s see how much memory these use-cases consume of ESP32 and ESP32-C3 SoCs and what headroom is available for the application.\nI have ensured that the configuration is same between ESP32 and ESP32-C3 as far as possible. Also the same SDK version (IDF version 4.3-beta3) has been used to run the applications on these SoCs.\nLooking at the above table, it is clear that:\nSo as we discussed, ESP32-C3 provides equal or more headroom for applications than ESP32. However when you are considering choosing the SoC or migration option, please ensure that you also consider other important features such as PSRAM availability, IO availability and CPU performance.\n","date":"25 April 2021","externalUrl":null,"permalink":"/blog/memory-availability-comparison-between-esp32-and-esp32-c3/","section":"Blog","summary":"","title":"Memory Availability Comparison between ESP32 and ESP32-C3","type":"blog"},{"content":"Hi everyone,\nHave you noticed the newest addition to our services? We are very excited about enriching our set of customer services with free-of-charge reviewing services for circuit diagrams and PCB designs of products powered by Espressif’s chips and modules. We have added this to our existing customer services, in order to ensure the technical accuracy of Espressif-powered products and their conformity to our high-quality standards.\nSo, if you would like us to make sure that your self-designed, Espressif-based product achieves optimal performance, please provide us with its circuit schematic and PCB design for a technical review. Together with this, you should also fill in and submit the relevant online form. Then, our experienced team of engineers will carry out this review. Rest assured they will come up with suggestions specifically tailored to your product, while also paying particular attention to the confidentiality that this process entails.\nOther topics you can read about in this month’s newsletter include:\nESP32-C3-DevKitM-1 Available Soon ESP32-C3-DevKitM-1 is an entry-level development board based on ESP32-C3-MINI-1, a module named like this because of its small size. This board provides a full range of Wi-Fi and Bluetooth LE functions. It is expected to hit the stores in the second half of April 2021.\nNebuLink NLC1242: An ESP32-Powered Data Acquisition System by SLS NLC1242 is an ESP32-based advanced data acquisition system designed to bridge the gap between end-user applications and sensors. Functioning both wirelessly and seamlessly, NLC1242 drives the exchange of data between sensors and the cloud.\nESP32-Powered Heart Rate and Pulse Oximetry Monitoring with MAX30102 Francesco Azzola, from a blog entitled \u0026ldquo;Surviving with Android\u0026rdquo;, has just posted a really interesting tutorial which demonstrates the way in which we can use ESP32 to monitor someone’s heart rate and pulse oximetry.\nFibonacci256: A Mesmerizing ESP8266-based Piece of Art Jason Coon from the Evil Genius Labs LLC has created several LED art pieces in a Fibonacci pattern. Jason’s latest work, Fibonacci256, is an ESP8266-powered, 166mm disc, with 256 RGB LEDs that are surface-mounted in a flower-like Fibonacci layout.\nRead More \u0026gt;\nHope you enjoy reading this month’s newsletter. Keep sending us your messages and requests on Facebook, Twitter, GitHub, Instagram, LinkedIn, and YouTube.\nYou can also contact us through our website or you can email us! We try to respond to all of your messages as quickly as possible!\nBest wishes,John Lee.Senior Customer Support Officer\n","date":"6 April 2021","externalUrl":null,"permalink":"/blog/march-2021/","section":"Blog","summary":"","title":"March 2021","type":"blog"},{"content":"","date":"23 March 2021","externalUrl":null,"permalink":"/tags/dfu/","section":"Tags","summary":"","title":"Dfu","type":"tags"},{"content":" Since the ESP32-S2 was released, a notable new functionality got everyone’s attention: the USB host and device capabilities. This new functionality adds a new world in terms of possibilities and cool stuff that could be made using USB and it’s a game changer in many projects.\nBut one of the uses for this peripheral is to upload the firmware without any external IC or programmer. This can be done directly by using the USB DFU mechanism.\nThe DFU (Device Firmware Upgrade) makes it possible and easy to update the device firmware as well as monitor the device.\nUsually, to flash a new firmware to the ESP32 flash memory, you have two possibilities:\nNow, the DFU works very similarly to the UART method, but it has some differences when building the firmware that will be uploaded using DFU.\nTo work with DFU, you don’t need to install any new software, just the ESP-IDF toolchain.\nIf you want to go deeply in the DFU mechanism, see this official specification from USB.org.\nUsing DFU for the first time # To start using the DFU, we first need to check if your IDF version supports the functionality.\nThe ESP32-S2 support starts from the IDF v4.2. To check your IDF version, you can use the following command on the terminal/shell/command prompt:\n*idf.py --version* To install the ESP-IDF, you can follow the Getting Started guide from our official documentation.\nIf you’re not using this version or above, please consider updating your environment in order to get this feature working on the ESP32-S2.\nElectrical connection # For this example, we will use the ESP32-Saola-1 v1.2 development board.\nAs you can see, the Saola board doesn’t have the connector for the native USB, only for the external USB-to-UART. To use the native interface, you need to connect a breakout USB cable as follows:\nUSB D- to GPIO19 USB D+ to GPIO20 You can use an old USB to do this by striping the wires and soldering to the pin header or using a breadboard to make it easier. In most of the cables, the D+ is the green and the D- is the white wire.\nBe careful if you are going to use the USB 5V to power the board. Make sure that you’re connecting the 5V on the pin marked as 5V in the ESP32-Saola dev kit.\nAfter connecting and powering the board, we are able to enter in DFU mode by holding BOOT and pressing and releasing the RST (reset) button.\nBuilding the DFU firmware # To build the firmware and upload it over the DFU, the process is a little bit different from a regular firmware, but it is very easy to do it.\nTo build and flash a regular firmware, we use the following command:\nidf.py build flash Note: We can use only “flash” instead of “build flash”, since the toolchain will build the firmware before flashing anyway.\nTo build the firmware for DFU, we need to change to:\nidf.py dfu dfu-flash Before executing the command, be sure to be in DFU mode.\nIf you need to monitor the log output in the terminal, you must change the log output configuration before building. This configuration changes the log output from UART to USB CDC, in order to see all the console prints over the USB.\nYou can do this by following these steps:\nGo to Component config menu.\nSelect ESP System Settings or Common ESP-related (if ESP-IDF is the v4.2).\nChange the Channel for console output to USB CDC.\nSave and exit the configuration menu build and flash the firmware.\nExample Video # This is the example video on how to configure and use the DFU on the ESP32-S2 to flash and monitor the ESP32-Saola development kit.\nConclusion # Taking advantage from the embedded USB peripheral on the ESP32-S2 could save time and money by reducing build of material and space in your project. Embedding the program interface into your project could save time and it’s much more convenient than using an external one with some wires.\nAlso, you can use USB peripheral for many other solutions, not only for programming your board!\n","date":"23 March 2021","externalUrl":null,"permalink":"/blog/dfu-using-the-native-usb-on-esp32-s2-for-flashing-the-firmware/","section":"Blog","summary":"","title":"DFU — Using the native USB on ESP32-S2 for flashing the firmware","type":"blog"},{"content":" General Information # This is a Quick Start based on several guidelines. There are many tutorials listed in this page, all of them very important for a sucessful start. It is common to overstep and miss important details. Be attentive. Before Starting # Zephyr is an RTOS maintained by the Linux Foundation and ported to several architectures. More about Zephyr. Espressif officially supports Zephyr RTOS on its devices. Visit the Product page. Check if your device is supported. Users can track the development status of Zephyr on Espressif devices by following the Support Status Page. Installation # Follow the Official Getting Started Guide Make sure your system is updated. Follow the instructions with attention to every step. Extra precautions are needed with Windows: Paths on environment variables may have problems with mixing \u0026lsquo;\\\u0026rsquo; and \u0026lsquo;/\u0026rsquo;. You must to use Chocolatey, otherwise installation is complex. If Chocolatey is blocked, refer this article, as this step is mandatory. First Build # The application west is the meta tool of Zephyr. After following the Getting Started Guide, only west will be needed. Simpleboot is the name used for the absence of a second stage bootloader. It is the old school firmware build. Find your board. Boards search page. Vendor refers to the board manufacturer. Many different vendors, including Espressif itself, use Espressif chips. Boards Folder in Github. If your board is not listed or if you are using a custom board, try using a regular DevkitC for the Espressif device you have. It won\u0026rsquo;t change outcome for now. Read the Board documentation, and stop after fetching the binary blobs. There are important information and commands that cannot be missed. Jump to Manual Build and execute all the steps. If all went well, you should have seen the hello world message. Use Ctrl + ] to exit the console application. You can study the Monitor manual here. All Espressif boards will require to fetch binary blobs. Some devkits have 2 options for console output:\nUART0 (usually with on-board Serial-USB converter), as default. USB, using the On-Chip USB-Serial converter. If you see some messages but not the hello world message, for now, try connecting to the other port.\nBuild with Zephyr Port of MCUboot # If you saw the hello world, everything is good so far. If OTA or any form of firmware ugrade is necessary, MCUboot will be mandatory, so we test it. The same applies to Security. More about MCUboot. There are 2 options for MCUboot: Zephyr port or Espressif port. Zephyr port: software security only. Espressif Port: hardware backed security. Let\u0026rsquo;s go with the Zephyr Port for now. First, enable MCUboot. Instructions here. Further explanation: Zephyr project configuration is based on Kconfigs. More about it here. You can search for Kconfigs. All project configurations go to a file named proj.conf. On the instructions above, you will have to edit the file zephyr/samples/hello_world/proj.conf. It is time to build the MCUboot and Zephyr. Instructions here. The --sysbuild option commands west to build the Zephyr, but also to build the MCUboot Second Stage Bootloader. The building process results in 2 binaries, but you don\u0026rsquo;t have to worry, west takes care of flashing both correctly. Remember to flash the device and start the monitor, just like the manual build. You should see, during the boot message, that MCUboot was executed. You should also see the hello world message. Building the Espressif Port of MCUboot # If all went fine so far, it is time to build the Espressif Port of MCUboot. This allows for features like Flash Encryption and Secure Boot, although we won\u0026rsquo;t be enabling them now. Clone the MCUboot repository on a different folder than Zephyr. git clone https://github.com/mcu-tools/mcuboot.git Follow the MCUboot instructions and make sure you don\u0026rsquo;t skip any step. If using Windows, make sure all paths are correct. Make sure NINJA is working properly. Having errors of any kind is a bad sign. Stop at the ninja flashing command. Now, the Zephyr image needs to be rebuilt to work with MCUboot - Espressif Port. This is not automatic. The Kconfig option enabling MCUboot must be kept, so Zephyr is built accordingly. There is no need to build MCUboot, as it as already done with the steps above and flashed to the device. Only Zephyr needs to be built. This is done by building it without using the --sysbuild option, similar to the Manual build. west build -b \u0026lt;board\u0026gt; samples/hello_world -p The -p option commands west to do a pristine build, which is a build after a clean-up. It is recomended when there are big config changes. Flash it and make it run. Usual commands: west flash west espressif monitor If you saw the bootloader running MCUboot and the hello world message, everything went fine. There is no noticeable difference from the Zephyr port of MCUboot. Next Steps # The steps above are valid for all examples. But be careful, some samples may not work directly out of the box. From this point and forward, you will face more Zephyr Problems than Espressif Problems. Run the Blinking example. It will not work directly on DevkitC, because it has no LED. You will need to learn about OVERLAYS, and have a breadboard to add LED circuitry, if not is present. Test Wi-Fi examples (if present). It\u0026rsquo;s recommeded to use Wi-Fi Shell at first. Test BlueTooth Examples (if present) Test 15.4 (if present) Test OTA with MCUboot Selected Tutorials # In case you need more information or detailed explanations, there are lots of sources to look for. These 2 below are very friendly for beginners:\nShawn Hymel and Digikey have a very nice series about Zephyr. Introduction to Zephyr The Pull-Up Resistor Channel also has good tutorials. ESP32 on Zephyr OS Make sure to see all the videos on those series. There may be changes regarding commands due to Zephyr evolution. If any command is not working, check the official documentation or ask Discord.\nThe original article was published on Medium, at the ESP Journal. It was rewritten for the current format.\n","date":"24 February 2021","externalUrl":null,"permalink":"/blog/2021/02/zephyr-rtos-on-esp32-first-steps/","section":"Blog","summary":"First Steps with Zephyr on ESP32, a collection of all needed tutorials.","title":"Zephyr RTOS on ESP32 — First Steps","type":"blog"},{"content":" Introduction # When we create a new project using ESP32 , sometimes we need to store data in the flash to persist even after a restart or power down. In the past, the most common way to do that was by using EEPROM, with just a few bytes of storage ability which limited it for larger amount of data.\nOn the other hand, the ESP32 uses a flash memory to store the firmware, including the bootloader and other relevant data. The flash memory size may vary from version to version, but it’s enough for most of the application code and you still can manage to have some spare storage area.\nBut not only the firmware, (your application) is stored in the flash memory. There is some other important data to keep in the flash, including the partitions map, RF calibration data, WiFi data, Bluetooth pairing information, Over-the-air updates and many other data important enough to be kept in the flash.\nTo see all ESP32 family variants, see this ordering information link .\nImportant note: This article uses the ESP-IDF v4.2 and all references use this version.\nUnderstanding partition tables # The partition tables on the ESP32 works very similarly to our computer. Just imagine that you can logically separate data according to the usage by telling the system where certain type of data will be stored on the memory, the type of this partition and, of course, the size.\nUsing the partition tables, you can have your application stored in one partition and your data, like the configuration or any other data, could be stored in a different partition. This allows you to keep your app and data in a separate memory area, making it possible, for example, to update only the application with a latest version and keep all your data intact.\nThe default partition scheme is defined by two different major partitions:\nnvs # The default NVS partition is used to store the unique device PHY calibration, WiFi data, Bluetooth pairing information, and any other value to be stored as NVS format. The default size is 24kB (0x6000 bytes).\nfactory # The factory partition stores the application firmware itself. The bootloader uses this partition as the starting point to initialize the application. When using OTA , this partition is used only if all OTA partitions are empty, otherwise the actual OTA partition will be used, and the factory partition will be no longer used.\nAnother usage for this partition is to keep the default application and use the OTA API to change the boot partition in case of factory reset (after updating the device to some OTA partition) or some failure during OTA updates.\nUse case # The most common usage for a custom partition table is when the firmware needs to be updated remotely by using the Over-The-Air update. This feature requires, at least three additional partitions to store the OTA data (ota) and two application (ota_0 and ota_1).\nAnother usage for this feature to add another storage area for saving files, logging data, device configuration, GPIO status or many other kinds of data.\nYou can also use the extended storage area to store the cloud certificates, therefore avoiding the need to keep hardcoded in your application (not recommended at all).\nThe flash memory on the ESP32 and ESP32-S2 is limited to up to 16MB. This way, if you need a more than 16MB of flash memory for data storage, you can add a second flash memory or an SDCard to your board.\nCreating custom partition tables # To start creating new partitions, we need to first understand the partitions’ file structure. The custom partition tables are defined by a CSV file with the following structure:\n__# ESP-IDF Partition Table # Name, Type, SubType, Offset, Size, Flags__ The CSV file contains 6 columns, defined in the second line in the CSV file.\nName # The first column is the partition name, and it defines the label of the partition.\nThe name field doesn’t have special meaning (except to the default NVS partition) but must be meaningful according to the partition usage and the name size should at maximum of 16 chars (larger names will be truncated).\nType # The second column is the partition type. Currently there are two types: data and app.\nThe data (0x01) type can be used to define the partition that stores general data, not the application.\nThe app (0x00) type is used to define the partition that will store the application.\nNote: The type is defined by the esp_partition_type_t enumeration.\nSubType # The third column is the partition sub type and defines the usage of the app and data partitions.\nSubType for data partitions:\nFor the data type, the subtype can be specified as:\nNote: The subtype is defined on the esp_partition_subtype_t enumeration .\nota (0x00): The ota subtype is used to store the OTA information. This partition is used only when the OTA is used to select the initialization partition, otherwise no need to add it to your custom partition table.The size of this partition should be a fixed size of 8kB (0x2000 bytes). nvs (0x02): The nvs partition subtype is used to define the partition to store general data, like the WiFi data, device PHY calibration data and any other data to be stored on the non-volatile memory.This kind of partition is suitable for small custom configuration data, cloud certificates, etc. Another usage for the NVS is to store sensitive data, since the NVS supports encryption.It is highly recommended to add at least one nvs partition, labeled with the name nvs, in your custom partition tables with size of at least 12kB (0x3000 bytes). If needed, you can increase the size of the nvs partition.The recommended size for this partition is from 12kb to 64kb. Although larger NVS partitions can be defined, we recommend using FAT or SPIFFS filesystem for storage of larger amounts of data. coredump (0x03): The coredump partition subtype is used to store the core dump on the flash. The core dump is used to analyze critical errors like crash and panic.This function must be enabled in the project configuration menu and set the data destination to flash.The recommended size for this partition is 64kB (0x10000). nvs_keys (0x04): The nvs_keys partition subtype is used to store the keys when the NVS encryption is used.The size for this partition is 4kB (0x1000). fat (0x81): The fat partition subtype defines the FAT filesystem usage, and it is suitable for larger data and if this data is often updated and changed. The FAT FS can be used with wear leveling feature to increase the erase/modification cycles per memory sector and encryption for sensitive data storage, like cloud certificates or any other data that may be protected.To use FAT FS with wear leveling see the example. spiffs (0x82): The spiffs partition subtype defines the SPI flash filesystem usage, and it is also suitable for larger files and it also performs the wear leveling and file system consistency check.The SPIFFS do not support flash encryption. SubType for app partitions:\nFor the app type it can be specified as:\nfactory (0x00): The factory partition subtype is the default application. The bootloader will set this partition as the default application initialization if no OTA partition is found, or the OTA partitions are empty.If the OTA partition is used, the ota_0 can be used as the default application and the factory can be removed from the partition table to save memory space. ota_0 to ota_15 (0x10–0x19): The ota_x partition subtype is used for the Over-the air update. The OTA feature requires at least two ota_x partition (usually ota_0 and ota_1) and it also requires the ota partition to keep the OTA information data.Up to 16 OTA partitions can be defined but only two are needed for basic OTA feature. test (0x20): The test partition subtype is used for factory test procedures . Offset # The fourth column is the memory offset and it defines the partition start address. The offset is defined by the sum of the offset and the size of the earlier partition.\nNote that the first partition (nvs in our case) must start at offset 0x9000. This is mandatory due the bootloader (offset 0x1000 and size of 0x7000) and the partition table section offset (offset 0x8000 and size of 0x1000) as well. Those partitions are not listed in the CSV file.\nIf the size of the bootloader needs to be increased, due any customization on it for example, you need to increase the offset in the project configuration menu (Partition Table → Offset of partition table) and you need to add the new offset on the first partition.\nOffset must be multiple of 4kB (0x1000) and for app partitions it must be aligned by 64kB (0x10000).\nIf left blank, the offset will be automatically calculated based on the end of the previous partition, including any necessary alignment.\nSize # The fifth column is size and defines the amount of memory to be allocated on the partition. The size can be formatted as decimal, hex numbers (0x prefix), or using unit prefix K (kilo) or M (mega) i.e: 4096 = 4K = 0x1000.\nThe size is defined in number of bytes and the minimum size is 4kB. The size for larger partitions must be multiple of 4kB. The maximum size is limited by the flash memory size, including all partitions.\nFlags # The last column in the CSV file is the flags and it is currently used to define if the partition will be encrypted by the flash encryption feature.\nAfter creating the CSV file, we need to change the project configuration to load the new partition tables’ file.\nIt is important to mention that for any changes on the partition tables structure, we need to erase the flash memory and reprogram the device including the new partitions binary file.\nThere is a tool to create the partition table in binary format manually from the CSV file. This conversion is done automatically during the build process.\nDemo # To show the usage of custom partition tables, we will create a quite simple demo with an extended NVS partition and one partition for SPIFFS alongside the default partitions and OTA.\nThe code will be based on the partition_find example, using the ESP-IDF v4.2.\nThe extended NVS will be used to store the device configuration and any other small relevant data besides the other NVS partition.\nNOTE: We highly recommend the use of NVS to store small amount of data. For larger data storage, you should move to FAT file system or SPIFFS.\nAnother partition that we will create is to store files and any other large data. For that partition, we will use the SPIFFS format.\nIn this demo, our development board is based on ESP32 and equipped with a 8MB flash memory.\nThe custom partition table will be the following:\n__*# ESP-IDF Partition Table # Name, Type, SubType, Offset, Size, Flags*__ * nvs,* *data, nvs, 0x9000,* *0x6000, otadata,* *data, ota, 0xf000, 0x2000, ota_0,* *app, ota_0, 0x20000, 0x200000, ota_1,* *app, ota_1, 0x220000, 0x200000, storage,* *data, spiffs, 0x420000, 0x200000, nvs_ext,* *data, nvs, 0x620000, 0x10000,* The graphical representation of the partition table is the following:\nThe storage will be used with SPIFFS and the nvs_ext for extra NVS data storage.\nIt’s important to mention that the both OTA partitions should have the same size and be sure to keep in mind to allocate enough space for additional features in the future.\nIf not using OTA, you don’t need to set the size of 2MB on the factory partition, if your firmware size is less than 1MB.\nNow we need to add the new CVS file, named as partitions_example.csv and change the example to find the partition scheme:\n# ESP-IDF Partition Table # Name, Type, SubType, Offset, Size, Flags nvs, data, nvs, 0x9000, 0x6000, otadata, data, ota, 0xf000, 0x2000, ota_0, app, ota_0, 0x20000, 0x200000, ota_1, app, ota_1, 0x220000, 0x200000, storage, data, spiffs, 0x420000, 0x200000, nvs_ext, data, nvs, 0x620000, 0x10000, After flashing and running the example, the output will show all detected partitions, according to our partition table layout.\nidf.py -p \u0026lt;COM_PORT\u0026gt; flash monitor Log output on terminal:\n# ESP-IDF Partition Table # Name, Type, SubType, Offset, Size, Flags nvs, data, nvs, 0x9000, 0x6000, otadata, data, ota, 0xf000, 0x2000, ota_0, app, ota_0, 0x20000, 0x200000, ota_1, app, ota_1, 0x220000, 0x200000, storage, data, spiffs, 0x420000, 0x200000, nvs_ext, data, nvs, 0x620000, 0x10000, I (380) example: ----------------Find partitions--------------- I (390) example: Find partition with type ESP_PARTITION_TYPE_DATA, subtype ESP_PARTITION_SUBTYPE_DATA_NVS, label NULL (unspecified)... I (400) example: found partition \u0026#39;nvs\u0026#39; at offset 0x9000 with size 0x6000 I (410) example: Find partition with type ESP_PARTITION_TYPE_DATA, subtype ESP_PARTITION_SUBTYPE_DATA_PHY, label NULL (unspecified)... E (420) example: partition not found! I (430) example: Find partition with type ESP_PARTITION_TYPE_APP, subtype ESP_PARTITION_SUBTYPE_APP_FACTORY, label NULL (unspecified)... E (440) example: partition not found! I (450) example: Find partition with type ESP_PARTITION_TYPE_DATA, subtype ESP_PARTITION_SUBTYPE_DATA_FAT, label NULL (unspecified)... E (460) example: partition not found! I (460) example: Find partition with type ESP_PARTITION_TYPE_DATA, subtype UNKNOWN_PARTITION_SUBTYPE, label NULL (unspecified)... I (480) example: found partition \u0026#39;storage\u0026#39; at offset 0x420000 with size 0x200000 I (480) example: Find partition with type ESP_PARTITION_TYPE_DATA, subtype ESP_PARTITION_SUBTYPE_APP_FACTORY, label NULL (unspecified)... I (500) example: found partition \u0026#39;otadata\u0026#39; at offset 0xf000 with size 0x2000 I (500) example: Find partition with type ESP_PARTITION_TYPE_DATA, subtype UNKNOWN_PARTITION_SUBTYPE, label NULL (unspecified)... E (520) example: partition not found! I (520) example: Find partition with type ESP_PARTITION_TYPE_DATA, subtype UNKNOWN_PARTITION_SUBTYPE, label NULL (unspecified)... E (530) example: partition not found! I (540) example: Find second FAT partition by specifying the label I (540) example: Find partition with type ESP_PARTITION_TYPE_DATA, subtype ESP_PARTITION_SUBTYPE_DATA_NVS, label nvs_ext... I (560) example: found partition \u0026#39;nvs_ext\u0026#39; at offset 0x620000 with size 0x10000 I (560) example: ----------------Iterate through partitions--------------- I (570) example: Iterating through app partitions... I (580) example: found partition \u0026#39;ota_0\u0026#39; at offset 0x20000 with size 0x200000 I (590) example: found partition \u0026#39;ota_1\u0026#39; at offset 0x220000 with size 0x200000 I (590) example: Iterating through data partitions... I (600) example: found partition \u0026#39;nvs\u0026#39; at offset 0x9000 with size 0x6000 I (610) example: found partition \u0026#39;otadata\u0026#39; at offset 0xf000 with size 0x2000 I (610) example: found partition \u0026#39;storage\u0026#39; at offset 0x420000 with size 0x200000 I (620) example: found partition \u0026#39;nvs_ext\u0026#39; at offset 0x620000 with size 0x10000 I (630) example: Example end To use the extended NVS partition (nvs_ext), you need to change the NVS initialization by using* *nvs_flash_init_partition_ptr by passing the NVS partition name.\nUsing ESP-IDF VS Code Extension # There is another way to work with the partition table CSV file, instead of editing in text mode. The ESP-IDF VS Code Extension allows you to install ESP-IDF, manage and create projects directly on the Microsoft Visual Studio Code IDE.\nESP-IDF VS Code Extension embeds various tools to aid in development. One of those tools is used to create the partition table using a GUI tool, called the ESP-IDF Partition Table Editor.\nTo start the Partition Table Editor, first open the Command Palette and type *Partition Table Editor UI *to open the editor interface (to open the command menu press F1).\nNow you can start creating your Partition Table structure by filling the same fields described in the last section.\nAfter creating the partition table structure, you can save the CSV file to your project, build the binary and flash it to your board.\nIf you are interested, watch the get started with the ESP-IDF VS Code Extension video-tutorial:\nCommon issues (Troubleshooting) # Some of the most common issues when dealing with partitions are about the alignment and overlapping.\nFirst, you need to flash erase if any modification on the partitions structure is done. This ensures that all new binary files will be flashed.\nTo erase flash, use the following command:\nidf.py -p \u0026lt;COM_PORT\u0026gt; erase_flash Failed to find X partition… # This issue means that the partition is not found or missing in your partition tables. This could be due to some wrong value on the CSV file, like the wrong type or subtype.\nPartition overlapping issue # If your partition offset points into an area that belongs to another partition, you will see an error like the following:\nCSV Error: Partitions overlap. Partition at line 6 sets offset 0x210000 . Previous partition ends 0x220000\nIt means that your partition at line 6 on the CSV should start at 0x220000 and not at 0x210000 . To solve this issue, change the value on the CSV file.\nMemory size issue # The most common issue about the partition size stands for the size alignment.\nFor the partitions type app , the size must be aligned by 64kB (0x10000) and must be multiple of the same value. This means that the size and offset must be aligned by 64kB for any app partition.\nIf you have a partition like this:\nota_0, app, ota_0, 0x12000, 0x200000, Then the error should be something like this:\nPartition ota_0 invalid: Offset 0x12000 is not aligned to 0x10000\nTo solve this issue, change the offset to 0x20000 and remember to recalculate the next offset.\nA smart solution for any alignment issue is to keep the offset blank and let the magic happen. By keeping the offset blank, the offset will be calculated automagically.\nFor example, if you create a partition table that uses 8MB flash, be sure to change in the project configuration the right amount on the menu ‘Serial flasher config — → Flash size’.\nConclusion # Creating custom partition tables in your project can be advantageous as you reuse available flash memory for extended data storage by customizing the partitions. This technique can avoid usage of external SDCard for extra data storage.\nWhen defining a custom partition table, make sure to use the right amount of data and alignment for each partition. Have in mind to allocate some free space in the application partition, especially when OTA is used, avoiding any problem if the size of the application increases and doesn\u0026rsquo;t fits in the partition anymore.\nThat way, you can maximize the flash usage you will not be wasting resources!\nReference for Partition Table # Docs: API Guide — Partition Tables\n","date":"12 February 2021","externalUrl":null,"permalink":"/blog/how-to-use-custom-partition-tables-on-esp32/","section":"Blog","summary":"","title":"How to use custom partition tables on ESP32","type":"blog"},{"content":" The Transport Layer Security(TLS) is an integral part of the IoT world. It facilitates a secure way of communication between the IoT device and the cloud service. The TLS uses asymmetric key cryptography for security that consists of a private key and corresponding public key (certificate). As the name suggests public key is shared with everyone and the private key is kept secured on the IoT device. It is pivotal to keep the private key secure in order to protect the identity of the IoT device. This article explains how to keep the device private key secure with the Digital Signature peripheral present in Espressif’s SoCs.\nThe Digital Signature (DS) peripheral is a new security feature introduced in the Espressif’s ESP32-S2 SoC. This peripheral is also available in ESP32-C3 and ESP32-S3 SoCs. It produces hardware accelerated RSA digital signatures, without the RSA private key being accessible by software. This allows the private key to be kept secured on the device without anyone other than the device hardware being able to access it.\nHow does the DS peripheral keep the private key secure ? # The DS peripheral makes use of the eFuse Controller available on the ESP32-S2 chip. For technical details about the eFuse Controller please refer to the *eFuse Controller * section of the ESP32-S2 Technical Reference Manual.\nThe ESP32-S2 has a total of 11 eFuse blocks each of the size of 256 bits. The eFuse block no.4 to block no.9 out of the total 11 blocks are available as key blocks and can be used to program a 256 bit key. All the blocks in the eFuse are one time programmable. Also, once a key is programmed in one of these key blocks, the software read operation on that block can be disabled. Thus making the key accessible only to the hardware of the ESP32-S2 chip.\nThe eFuse key blocks shown above can be used for multiple purposes e.g. Digital Signature, Flash Encryption, Secure Boot etc.\nAs you might have noticed, only a 256 bit key can be stored in a key block of the eFuse Controller. A typical RSA key has recommended minimum length of 1024 bits. Then how can we secure the RSA private key which has a considerably larger length?\nUsing the DS peripheral to secure the RSA private key # The process to secure RSA private key involves multiple steps. Note that all the technical steps are not mentioned here for simplicity. Please refer to the DS documentation in the ESP-IDF programming guide for more details. The following diagram explains the process in a simple manner.\nAs the above diagram shows, the process to secure the RSA private key and use the DS peripheral follows these steps -\nSetup Mode — One-Time Device Configuration # RSA Sign/Verify mode — Regular RSA key usage # The DS peripheral will use the DS key from the eFuse to internally decrypt the cipher-text to obtain the RSA private key. Then this RSA private key can be used to perform the operations such as sign/verify. This way the encrypted RSA private key can be used to perform a TLS connection.\nOnly the DS peripheral (hardware) now has the access of the DS key. This way the RSA private key is kept secure on the device with help of the DS peripheral.\nCan we generate the RSA private key on the device? # This article talks about a workflow where the RSA private key is generated and encrypted on the host machine (e.g. PC) and then stored in the flash of the device. This has been done for simplifying the workflow. But it is very well possible to generate the RSA private key on the device itself during manufacturing. Along with the RSA key, the other parameters e.g. IV, DS key can also be randomly generated on the device. Thus, the RSA key can be encrypted on the device using parameters which are completely randomly generated on the device itself. This way the RSA private key never leaves the device. The cipher-text (encrypted RSA private key) generated on the device can then be backed up safely if required.\nWhat does a developer have to do to use the DS peripheral in their product ? # The Espressif’s ESP-IDF provides all the necessary support for using the DS peripheral on the ESP32-S2 SoC. This support is added through the ESP-TLS component. A developer needs to perform the following steps in order to use the DS peripheral in their project for a TLS connection.\nTL;DR: # One-Time Device Configuration: # Step 1: First step is to configure the DS peripheral on the ESP32-S2 Soc. It can be done with the configure_ds.py script. To use the script we will have to set the appropriate idf_target (chip) in the project. The idf_target can be set to esp32s2 with following command:\n$ idf.py set-target esp32s2 The command to configure the DS peripheral for development purpose is as follows:\n$ python configure_ds.py --port /* USB COM port */ --private-key /* RSA priv key */ The script documentation can be found here. The private key in above command indicates the device RSA private key.\nThe script performs step i) to step iii) as mentioned above. It also creates an NVS partition containing the encrypted private key parameters to be stored onto the flash. This data is required by the DS peripheral and is called as the DS context.\nThe content of the NVS partition generated will be as follows:\nStep 2: In order to use the NVS partition generated in the previous step. We will have to create a custom partition table in our example project which lists the required partition. The following custom partition table can be used for that purpose.\nThe pre_prov * *partition in the above partition table represents the entry for NVS partition containing the DS context. The example project can be made to use the custom partition in the configuration menu (*idf.py menuconfig -\u0026gt; Partition Table). *Now the partition can be flashed onto the device with help of the parttool.py script. The commands will be as follows:\n$ idf.py partition_table partition_table-flash $ parttool.py --port /* Serial port */--partition-table-offset 0x8000 write_partition --partition-name=\u0026#34;pre_prov\u0026#34; --input /* Path to NVS partition */ Regular RSA key usage: # Step 3: The support of DS peripheral is added through the ESP-TLS and is enabled by default. To use the peripheral for a TLS connection, the application will have to pass the DS context to the ESP-TLS along with the device certificate (public key).\nThe contents of the NVS partition generated by the configure_ds.py script are listed in step 1. The application will have to read the contents by using respective NVS read/write API functions in order to create a DS context. The DS context and the client (device) certificate can be passed to an ESP-TLS connection as follows:\nThis way the ESP-TLS will use the DS peripheral for that particular TLS connection.\nThe DS peripheral uses the hardware RSA accelerator. Hence, the RSA sign/verify operation using the DS peripheral will be faster as compared to software RSA sign/verify operation. Refer the ESP32-S2 TRM for more technical details.\nReadily available example for the DS peripheral # The ESP-IDF provides the example mqtt/ssl_ds to showcase the use of the DS peripheral . The example connects to the broker test.mosquitto.org using ssl transport with client certificate(RSA) and as a demonstration subscribes/unsubscribes, sends a message on certain topic. The RSA signature operation required in the ssl connection is performed with help of the Digital Signature (DS) peripheral.\nThe example follows all of the above mentioned steps. A detailed explanation of the steps to perform the example is also provided in the example README.\nIf you would like to know more about TLS security then please see the article TLS and IOT\nIf you would like to know more about the other security features in the ESP32 series then you can see this article Understanding ESP32’s Security Features\n","date":"3 February 2021","externalUrl":null,"permalink":"/blog/esp32-s2-digital-signature-peripheral/","section":"Blog","summary":"","title":"ESP32-S2: Digital Signature Peripheral","type":"blog"},{"content":"Hi everyone,\nEspressif’s Founder and CEO, Teo Swee Ann, recently gave an interview to EEWeb, the go-to website for users of electronic design tools. Discussing Espressif’s plans for Artificial Intelligence, Teo Swee Ann said: “We will be introducing our low-cost AI-enabled line of products early in 2021, based on the ESP32-S series of chips, starting with ESP32-S3. For AI chips, it is not enough to build the hardware; the algorithm is equally important because we do not expect average Makers to collect enough training samples and roll their own AI networks now. So, we will be populating our GitHub repositories with more AI code. We have been internally testing ESP32-S3 and we are able to achieve state-of-the-art performance for tasks such as beam forming, wake-word recognition and offline command recognition.”\nEspressif’s official announcement about ESP32-S3 has already made the rounds on the internet. ESP32 has become a mainstream IoT microcontroller since its release in 2016, so it is only natural that a new member in this series of MCUs causes sensation. Espressif is always committed to innovating its AIoT solutions; hence, ESP32-S3 is the result of an overall optimization in terms of connectivity, AI computing power, security, IO availability, and peripheral interfaces.\nFurthermore, Teo Swee Ann announced in his EEWeb interview that “ESP32-S3 has also been tested on some image-related applications, but a more powerful version will come with ESP32-S4”. So, fans of the ESP32-S series should be waiting for more from Espressif in the near future!\nOther topics you can read about in this month’s newsletter include:\nESP32-Powered PDP-11 Minicomputer Espressif’s Software and Technical Marketing Manager, Jeroen Domburg, otherwise known as Sprite_tm, has just built an ESP32-powered, ultra-compact replica of a Digital DEC VT-102 terminal emulating a PDP-11 running 2.11BSD.\nLine-us: An ESP8266-Based Drawing Robot Line-us is a small, portable, ESP8266-based robot which draws using a real pen on paper. The free app that goes with Line-us lets you draw, send messages, share sketchbooks or collect artworks from others!\nAgromon: Smart Agriculture Using ESP32-WROOM-32U Agromon is a wireless transmitter based on ESP32-WROOM-32U and designed for agricultural IoT applications. As a plug-and-play device, Agromon can be easily installed and used. By simply plugging in the sensors included in the package, the device is ready for use.\nMorphESP 240: A New ESP32-S2 Board by Morpheans Morpheans, a French startup, are introducing MorphESP 240, an easy-to-use dev board that is compatible with Arduino and CircuitPython. MorphESP 240 is based on ESP32-S2 and comes with a built-in, high-resolution, IPS-color display.\nHope you enjoy reading this month’s newsletter. Keep sending us your messages and requests on Facebook, Twitter, GitHub, Instagram, LinkedIn, and YouTube.\nYou can also contact us through our website or you can email us! We try to respond to all of your messages as quickly as possible!\nBest wishes,John Lee.Senior Customer Support Officer\n","date":"26 January 2021","externalUrl":null,"permalink":"/blog/jan-2021/","section":"Blog","summary":"","title":"Jan 2021","type":"blog"},{"content":"Hi everyone,\nWe hope you are enjoying this year’s holiday season. All of us at Espressif would like to send you our positive energy, along with our warmest wishes for health and happiness in 2021! As ever, we shall continue working hard, trying to give you the best in the field of AIoT.\nWe are bidding farewell to 2020 with some really exciting news. Espressif’s Founder and CEO, Teo Swee Ann, was recently appointed as a member of the International Advisory Council at the Singapore Management University (SMU). The SMU International Advisory Council comprises experts from China, Indonesia, Malaysia, Myanmar, the Philippines, Thailand, and Vietnam. The Council’s mission is to develop the SMU’s international collaboration with governments, business leaders and academics both in Asia and globally. Teo Swee Ann’s contribution to the SMU International Advisory Council will stem from his expertise in the wireless chip industry, which spans more than two decades.\nOther topics you can read about in this month’s newsletter include:\nAWS Launched an ESP32-Powered IoT Educational Kit Amazon Web Services introduced the ESP32-powered AWS IoT EduKit — an easy way to learn how to build IoT applications, with ESP RainMaker and ESP Alexa SDKs.\nESP32 at the Heart of Nuvia’s Energy Management Platform Nuvia’s ESP32-powered, smart thermostats have taken the Turkish market by storm.\nFlowcode v9.0 Supports ESP32 In the latest version of Flowcode v9.0, there is full support for Espressif’s ESP32 MCUs. At the same time, ESP32 is completely free within the Flowcode ecosystem.\nMaypole: ESP32-Based Open-Source Hardware for Wireless Collaboration The ESP32-based Maypole looks like a USB stick. However, when it is configured appropriately, it turns any USB port into a hub for wireless collaboration.\nESP-WIFI-MESH-Powered, Self-Service, Smart-Laundry Facility The fruit of Espressif and Ujing’s recent collaboration is an ESP-WIFI-MESH-powered, self-service, smart-laundry facility. It was recently launched on campus at Jiangnan University.\nHope you enjoy reading this month’s newsletter. Keep sending us your messages and requests on Facebook, Twitter, GitHub, Instagram, LinkedIn, and YouTube.\nYou can also contact us through our website or you can email us! We try to respond to all of your messages as quickly as possible!\nBest wishes,John Lee.Senior Customer Support Officer\n","date":"11 January 2021","externalUrl":null,"permalink":"/blog/december-2020/","section":"Blog","summary":"","title":"December 2020","type":"blog"},{"content":"","date":"22 December 2020","externalUrl":null,"permalink":"/tags/firmware/","section":"Tags","summary":"","title":"Firmware","type":"tags"},{"content":"In this post we will discuss the design and internal workings of Over-The-Air (OTA) Updates framework in ESP-IDF.\nWe shall also cover some of the features from OTA updates, focused around reliability and security that can help to build better IoT products with ESP32.\nBackground Information # Lets cover some basic information essential for understanding the overall OTA update procedure.\nPartition Table \u0026amp; Flash Layout # The Partition table defines the flash layout on ESP32. Applications can specify its desired flash layout using simple CSV files. A template looks like below:\n# Name, Type, SubType, Offset, Size, Flags # Note: if you have increased the bootloader size, make sure to update the offsets to avoid overlap nvs, data, nvs, , 0x4000, otadata, data, ota, , 0x2000, phy_init, data, phy, , 0x1000, ota_0, app, ota_0, , 1M, ota_1, app, ota_1, , 1M, Important points to note:\nA binary partition table image is generated using the above CSV file. This occupies 4KiB (single flash sector) and is located at offset 0x9000 in default configuration. First 8 sectors (32KiB), before this, are reserved for the bootloader image. If more space is desired for bootloader, then the partition table offset can be adjusted using configuration option CONFIG_PARTITION_TABLE_OFFSET. Partitions ota_0 and ota_1 denote active and passive versions for application firmware. Identical copies ensure power safety during OTA updates. Application image partitions (ota_0/ota_1) are always adjusted to align on 64 KiB boundary, as that is the page size for flash cache mapping. Even though factory partition is supported, we will not be considering it, as that partition is not supported in anti-rollback scheme. If required, that logic can be coupled in primary firmware itself. For simplicity we will also not consider multiple firmware partitions (total 16) even though they are supported in ESP-IDF. Visual representation of above configuration for 4MiB flash part is shown below:\nApplication Image Format # A detailed documentation can be found here , whereas, here we will only consider interesting bits that are applicable for this discussion.\nFollowing is the application image descriptor (present at offset 0x20 in application image):\ntypedef struct { uint32_t magic_word; /*!\u0026lt; Magic word ESP_APP_DESC_MAGIC_WORD */ uint32_t secure_version; /*!\u0026lt; Secure version */ uint32_t reserv1[2]; /*!\u0026lt; reserv1 */ char version[32]; /*!\u0026lt; Application version */ char project_name[32]; /*!\u0026lt; Project name */ char time[16]; /*!\u0026lt; Compile time */ char date[16]; /*!\u0026lt; Compile date*/ char idf_ver[32]; /*!\u0026lt; Version IDF */ uint8_t app_elf_sha256[32]; /*!\u0026lt; sha256 of elf file */ uint32_t reserv2[20]; /*!\u0026lt; reserv2 */ } esp_app_desc_t; Few important fields to note:\nversion: Firmware version embedded in image. This can be embedded in firmware image using multiple methods including configuration option or version file. By default its retrieved using command git describe \u0026ndash;always \u0026ndash;tags command if application is hosted in a git repository. secure_version : Security version embedded in image. This can be embedded using configuration option only. This is desired as it groups firmware images based on fixes against security vulnerabilities (e.g. revoked CA certificate) and thus ensuring security. More on this in followup section on anti-rollback feature. Software Architecture # Above is simplified diagram that highlights some key components in an application from ESP-IDF that deals with OTA updates. In most cases, application needs to interact with public interface of esp_https_ota and app_update ____ components only.\nESP_HTTPS_OTA : This software component provides simplified API for updating device securely over TLS channel. API accepts two mandatory parameters, HTTPS URL where firmware image is hosted and server certificate to validate server’s identity. APP_Update : This software component abstracts out the complexity of dealing with partition and flash layer operations. It exposes simplified API that can be directly used by an application for programming firmware to device flash. Additionally it also provides some convenience APIs for dealing with rollback and anti-rollback use-cases that we shall cover in the later part of this article. HTTPS OTA API # API for secure OTA update is kept very simple and requires 2 mandatory parameters:\nServer (Firmware) URL Server Certificate Code snippet is as shown below, assuming firmware image is hosted on github.com server:\nesp_http_client_config_t config = { .url = \u0026#34;https://raw.githubusercontent.com/path/to/firmware\u0026#34;, .cert_pem = (char *) github_server_start_pem, };esp_err_t ret = esp_https_ota(\u0026amp;config); if (ret == ESP_OK) { esp_restart(); } There is also support for advanced APIs which provide more granular control to the application in terms of validation of firmware version, monitoring OTA update progress etc.Detailed documentation for this can be found here.\nOTA Update Workflow # Simplified workflow for OTA update looks like below:\nServer authentication ensures that firmware is downloaded from trusted entity. Based on version information in downloaded image header, device can decide to perform upgrade. Validation on device side includes header and integrity (SHA256 checksum) related checks. This happens after entire firmware image is written to flash partition. If hardware secure boot is enabled then firmware image has signature appended to it. For flash encryption cases, it is entirely handled on device level during flash write stage. More on this in later section. Boot-loader \u0026amp; Application Flowchart # Two entities play an important role in OTA update process, the boot-loader and the application.\nThe boot-loader and application both rely on the partition table to extract information on various partitions and their offsets in flash. Partition otadata is responsible for selection of active firmware (latest updated) based on sequence numbers stored within it. otadata partition is allocated with 2 flash sectors (similar to active/passive firmware, 8KiB size) and thus allows for power safety while updating sequence numbers and other parameters during OTA update. Following is a simplified flowchart for decision making involved during OTA update in an application. Also it shows how boot-loader picks up newly updated firmware after OTA update.\nFlash Layout Transition # For normal OTA update scenario, flash layout transition is rather simple. It goes through following stages:\nStage 1 # Newly shipped smart light bulb would have functional ota_0 partition and empty ota_1 partition. Boot-loader will always give control to firmware in ota_0 partition.\nStage 2 # Application after performing OTA update will make ota_1 partition as active by updating its sequence number in otadata partition. Thus from subsequent RESET, boot-loader will always give control to firmware in ota_1 partition (till next OTA update).\nLimitations # In the above scenario, if there is some issue (e.g. early firmware bootup crash) in the newly updated firmware from partition ota_1, there is no way the device can fallback to previous known working firmware.\nConsideration I — Rollback # Typically OTA updates are staged and well tested in actual deployment scenarios, e.g. friend-family devices, beta-users and then finally to larger device groups. However this still can not ensure 100% recovery if OTA update goes wrong due to many parameters like variation in hardware attributes of device, or some rare firmware crashes.\nThe firmware rollback feature provides an ability to rollback to the previous known working firmware.\nBoot-loader \u0026amp; Application Flowchart # Unlike normal OTA update workflow, rollback case involves few intermittent states before marking firmware as valid. Transition from new firmware to valid or invalid is handled by both application and boot-loader. Flash Layout Transition # For rollback enabled OTA update scenario, flash layout transition goes through following stages:\nStage 1 # Newly shipped smart light bulb would have functional ota_0 partition and empty ota_1 partition. Boot-loader will always give control to firmware in ota_0 partition.\nStage 2 # First OTA update writes new firmware image in passive partition (ota_1) and marks its state as ESP_OTA_IMG_NEW . The state is stored in otadata partition along with its sequence number.\nStage 3 # After RESET, boot-loader sees a new firmware with state__ESP_OTA_IMG_NEW__ and turns its state to ESP_IMAGE_PENDING_VERIFY ,____ as its functionality is yet to be validated.\nStage 4/4' # Once new firmware starts execution, it can set its state to either ESP_OTA_IMG_VALID or ESP_OTA_IMG_INVALID based on application logic (will come to that in next section). If it fails to update the state of new and first time executing firmware then on subsequent RESET, boot-loader updates its state to ESP_OTA_IMG_ABORTED and thus falls back to previous firmware. Following APIs are provided for state transitions:\n// Mark firmware as valid and cancel rollback process esp_ota_mark_app_valid_cancel_rollback();// Mark firmware as invalid and rollback to previous firmware esp_ota_mark_app_invalid_rollback_and_reboot(); Firmware Functionality # Lets discuss more on transition to “Stage 4 ” from above.\nFirmware functionality can be decided based on various checkpoints within it.\nSuccessful initialisation Connection to WiFi network Connection to OTA server Connection to OTA server being the best possible option, as it ensures possibility of next OTA update. However this may need some changes on cloud agent side as well, which can acknowledge communication from device firmware. Once firmware reaches to desired checkpoint successfully, it can invoke earlier mentioned API to cancel rollback process and continue further execution.\nNote: Rollback feature can be enabled through config option, which is discussed in more detail in followup section through working example code.\nConsideration II — Anti-Rollback # Rollback offers an ability to go back to previous working firmware but sometimes this may not be a desired operation. Many times, a device firmware update can also modify some secure credentials (e.g. server’s certificate) embedded within it. This implies that all older firmware images are pretty much obsolete and if executed may posses security risks. “Firmware Anti-rollback ” feature can help to mitigate such issues.\nAnti-rollback is a feature that allows to execute firmware only-if the____ security version embedded within it is greater than the one programmed in the device’s EFuse (one-time-programmable memory). Certain bits (up-to 32) can be reserved to store the security version in EFuse. It is ensured that this is kept in sync with the one embedded in the firmware image by both the application and boot-loader during startup.\nAbove image illustrates idea of grouping firmware based on their security versions.\nEach group (G1/G2/G3) has 3 firmware images with different firmware version but same security version. If device anti-rollback reserved EFuse has 2 bits set (which means security version 2) then only firmware from G2 and G3 groups will be allowed to execute on device. Firmware images from group G1 having lesser security version will not be allowed to boot. Anti-rollback is tightly coupled with rollback, as in version in EFuse is only updated after functionality of new firmware image is confirmed. This can be seen in “Simplified rollback OTA update flowchart” shown earlier. Working Example in ESP-IDF # Working example which implements rollback and anti-rollback features can be found here . This is slightly modified version of advanced_https_ota example from ESP-IDF.\nConfiguration Changes # Updated sdkconfig.defaults file looks like below:\n# Use custom partition table without factory partition CONFIG_PARTITION_TABLE_CUSTOM=y CONFIG_PARTITION_TABLE_CUSTOM_FILENAME=\u0026#34;partitions_example.csv\u0026#34;# Enable firmware versioning from config option CONFIG_APP_PROJECT_VER_FROM_CONFIG=y CONFIG_APP_PROJECT_VER=\u0026#34;1\u0026#34;# Enable firmware rollback and anti-rollback features CONFIG_BOOTLOADER_APP_ROLLBACK_ENABLE=y CONFIG_BOOTLOADER_APP_ANTI_ROLLBACK=y# Set initial secure version to 0 CONFIG_BOOTLOADER_APP_SECURE_VERSION=0# Set secure version eFuse field size CONFIG_BOOTLOADER_APP_SEC_VER_SIZE_EFUSE_FIELD=32# Emulate secure version through flash partition for testing CONFIG_BOOTLOADER_EFUSE_SECURE_VERSION_EMULATE=y Both version and secure_version fields in the firmware image are set through config options itself. For testing purpose, we have enabled an option to emulate anti-rollback EFuses through flash partition. For actual product deployment scenario this option should be disabled. Code Changes # We have used information from API esp_https_ota_get_img_desc() to decide if OTA update is really required or not. This API retrieves image descriptor part thus its useful to get metadata that involves firmware version and security version. This also prevent further image download from remote server and unnecessary flash program cycles. Important point to note is that we are considering successful Wi-Fi connection as a checkpoint within firmware to cancel rollback process and mark image as valid. Same API (esp_ota_mark_app_valid_cancel_rollback) is also responsible for updating security version in EFuse matching with current firmware header. Consideration III — Secure Boot \u0026amp; Flash Encryption # In this section we will see how OTA updates can be coupled with platform security features (more information covered here) in ESP32.\nSecure boot allows only trusted firmware to execute by verifying its signature with public key on device. During an OTA update, the firmware image hosted on the server should be signed with ECDSA NIST256p (secure boot v1 scheme) or RSA-3072 (secure boot v2 scheme) based private key. Signature is calculated on SHA256 checksum of firmware image, offering constant time verification, and then it is appended to it. As mentioned earlier in the flowchart diagram, the OTA workflow on application side includes image validation stage. For non secure boot enabled cases, validation includes only integrity checks in the form of image header magic bytes and plain SHA256 checksum. For secure boot enabled cases, it involves verification of signature using public key stored in device. After the secure boot verification stage, the firmware is marked as valid (non-rollback case) or new (rollback case). If signature is found to be invalid, its marked as invalid right away aborting the OTA update procedure. For flash encryption case there are no additional steps are required on server or device side. Firmware image hosted on the server is still in plain text format with (optional) secure boot signature appended to it. During flash write stage on the device, if flash encryption is enabled then firmware gets written in encrypted manner using hardware AES engine and key from EFuse. Important Notes # Above discussed features like “rollback” and “anti-rollback” must be enabled before device ships out of factory. Since these features enable certain code path in bootloader, which in itself can not be updated on-field. It is recommended that any sort of power save modes (e.g. WiFi modem sleep) should be disabled during OTA update. This allows optimal throughput for data transfer. ESP-IDF provided examples take explicit care for this. During OTA update flash goes through programming operations (erase/write) and hence flash cache stays disabled. If there are any interrupts that are required to kept enabled, then they should be registered with their handler in internal code memory (IRAM). More information on this can be found here. Getting robust OTA update for IoT product is very essential and some of the considerations mentioned above can be helpful in making right design decisions!\n","date":"22 December 2020","externalUrl":null,"permalink":"/blog/ota-updates-framework/","section":"Blog","summary":"","title":"OTA Updates Framework","type":"blog"},{"content":" ESP RainMaker is a collection of device-agent SDK, a transparent cloud application and iOS/Android phone apps. This lets developers write the firmware and instantaneously interact with it through the phone-apps, or through voice assistants, without writing a single line of code in the cloud or the phone-applications.\nThe various articles for RainMaker are available here:\nIntroducing ESP RainMaker RainMaker Projects: Firmware Considerations OTA Firmware Upgrades with ESP RainMaker ESP RainMaker and Serverless 3rd Party Integrations in ESP RainMaker ESP RainMaker now in Arduino New Features in ESP RainMaker ","date":"6 December 2020","externalUrl":null,"permalink":"/blog/esp-rainmaker/","section":"Blog","summary":"","title":"ESP RainMaker","type":"blog"},{"content":"\nThis article is under review and may contain outdated information. Introduction # This article is part of the “First Steps with ESP32 and NuttX” series. A series whose objective is to present an overview of the NuttX Operating System and to provide instructions for using NuttX on ESP32.\nThe first part of the series showed how to prepare the environment, compile and build the Operating System (NuttX) until uploading the firmware to the SoC (ESP32).\nThis is the second part and will demonstrate how to run the famous “Hello World” from the Embedded Systems world, i.e., an application that blinks a LED. The evaluation board used here is a DevKit v1 and the built-in LED will be used for convenience. If your DevKit does not come with a built-in LED, just connect an LED to pin 2 in series with a resistor as it will be briefly discussed in the execution section.\nIncluding LED # From the nuttx directory, clean your current configuration and pre-existing binaries, load the configuration for ESP32 DevKit board with nsh (NuttX shell) and finally enter the configuration menu using the following commands:\ncd ~/nuttxspace/nuttx make distclean ./tools/configure.sh esp32-devkitc:nsh make menuconfig To add the driver for the LED, navigate to* Device Drivers-\u0026gt; LED Support and select LED Driver and Generic Lower Half LED Driver* (Click y). In this step you are adding the driver for the LED.\nReturn to the home menu via ‘Exit’. Just use the side arrows and ‘Enter’. Finally, to add the example, navigate to Application Configuration-\u0026gt; Examples and select Led Driver Example.\nExit the menu via “Exit” and save the configuration.\n✓As a shortcut, you may load the leds config instead of nsh. If you do so, you don’t need to enter the configuration menu. This config has everything included for you. It’s nice to try both to realize how configs may be used to try functionalities faster but it’s also nice to get familiar with the menuconfig options.\nBuilding and Flashing # If you did not add the paths for the cross compiler binaries and for the esptool to PATH permanently as suggested in the Getting Started, run the following commands to load these paths.\nexport PATH=$PATH:/opt/xtensa/xtensa-esp32-elf/bin export PATH=$PATH:/home/\u0026lt;user\u0026gt;/.local/bin NOTE: Replace with your user name.\nFinally, clean up any previously generated binaries, connect your DevKit to your computer and perform the build process and flash using the following commands:\nmake clean make download ESPTOOL_PORT=/dev/ttyUSB0 NOTE: adjust the USB port according to your configuration. In case this is the first time you are downloading the binaries to ESP32, pass the bootloader and the partition table directory as an argument in the second comand as instructed in the previous article from this series.\nExample Execution # Access the serial terminal and execute the command leds. This command will run the selected example!\nsudo picocom /dev/ttyUSB0 -b 115200 Congratulations! From now on you should be seeing the LED blinking! If you want to return to the terminal, reset the ESP32 by pressing the DevKit EN button. If you do not have a built-in led, connect an LED to pin 2 and associate a resistor in series (between 100 Ω to 1 k Ω).\nTip:\nRun “help” or “?” to check the built-in apps like exposed in Figure 3.\nCurrent Support Status # At the moment this article is written the following peripherals/features are supported:\nSymmetric Multi-Processing (SMP) It’s already possible to use the 2 ESP32 cores. The default configuration only uses 1 core. If you want to use both cores, access the following path in menuconfig:\n-\u0026gt; RTOS Features -\u0026gt; Tasks and Scheduling\nand enable the SMP option.\nSPI I2C SPI Flash Ethernet WiFi PSRAM 4 Generic Timers Watchdog Timers Hardware Random Number Generator (RNG) Low Power support (PM) You can keep yourself updated through the following link:\nhttps://github.com/apache/nuttx/tree/master/boards/xtensa/esp32/esp32-devkitc\nCurrently, the support for debugging with OpenOCD and eFUSE are in development! Sooner, they will also be available!\nSo, stay tuned!\nWhere to find support? # To participate in the Nuttx mail list, you can send an email to dev-subscribe@nuttx.apache.org.\nFor help, doubts, bugs reports, and discussion regarding NuttX, you can send an email to dev@nuttx.apache.org.\nThe original article was published on Medium, on the ESP Journal. It has since been updated.\n","date":"1 December 2020","externalUrl":null,"permalink":"/blog/2020/12/blink-led-on-esp32-with-rtos-nuttx/","section":"Blog","summary":"This is a tutorial on how to blink an LED with NuttX after getting started.","title":"Blink LED on ESP32 with RTOS NuttX","type":"blog"},{"content":"","date":"1 December 2020","externalUrl":null,"permalink":"/authors/sara-monteiro/","section":"Developer Portal Authors","summary":"","title":"Sara Monteiro","type":"authors"},{"content":" Introduction to Apache NuttX RTOS # In this tutorial, we will do a quick overview of NuttX and its compatibility with Espressfi SoCs. After that, we will build and flash NuttX onto the ESP32-DevKitC board and connect to a Wi-Fi network. Along the way, we will also install the required dependencies for NuttX, set up the toolchains to build applications for Espressif SoCs, get NuttX\u0026rsquo;s source code, and configure the project before building.\nAccording to the Apache NuttX website: NuttX is a real-time operating system (RTOS) with an emphasis on standards compliance and small footprint. Scalable from 8-bit to 64-bit microcontroller environments, the primary governing standards in NuttX are Posix and ANSI standards. NuttX is the 2nd most popular community-based RTOS (along with Zephyr in the 1st position):\nOperating system First commit Governance License Contributors Pulse (jun10/2024) Zephyr 2014 community Apache 2.0 100+ 942 NuttX 2007 community Apache 2.0 100+ 135 RT-Thread 2009 community Apache 2.0 100+ 67 RIOT 2010 community LGPL2.1 100+ 71 Tyzen RT 2015 Samsung Apache 2.0 100+ 36 myNewt 2015 Community Apache 2.0 100+ 25 mbed OS 2013 ARM Apache 2.0 or BSD-3 Clause 100+ 7 FreeRTOS 2004 Richard Barry MIT 100+ 6 Contiki-NG 2016 community BSD-3 Clause 100+ 4 CMSIS-5 2016 ARM Apache 2.0 100+ 0 Azure-RTOS 2020 Microsoft Microsoft Software License 10+ archived — Table by Alin Jerpelea, presented on NuttX Workshop 2024\nIts standards conformance (POSIX and ANSI, mostly) allows software developed under other OSes (under the same standards, such as software developed for Linux) to be easily ported to NuttX, enabling embedded applications to reuse tested applications. In such a sense, NuttX can be seen as the closest alternative to Linux for embedded software, providing interfaces similar to the ones used by Embedded Linux applications to SoCs that do not require running Linux directly.\nNuttX supports more than 300 boards from different architectures and its active community keeps providing support for newer devices and boards.Espressif SoCs are supported on NuttX!\nNuttX Documentation # The primary source of information for NuttX is its documentation, which is accessible at https://nuttx.apache.org/docs/.\nSupported Espressif SoCs in NuttX # NuttX currently supports Espressif\u0026rsquo;s ESP32, ESP32-C and ESP32-S series. Peripheral support is increasing constantly. Those include but are not limited to GPIO, DAC, DMA, SPI, I2C, I2S, Wi-Fi, Bluetooth and many more.\nCurrently, Espressif SoCs supported on NuttX are divided into two different architectures: RISC-V and Xtensa.\nRISC-V # ESP32-C3 ESP32-C6 ESP32-H2 Xtensa # ESP32 ESP32-S2 ESP32-S3 Getting started with NuttX and ESP32 # The following steps use Ubuntu 22.04 as an example. Please check the official documentation for other Operating Systems. Installing System Dependencies # Install the system dependencies required to build NuttX:\nsudo apt install \\ automake binutils-dev bison build-essential flex g++-multilib gcc-multilib \\ genromfs gettext git gperf kconfig-frontends libelf-dev libexpat-dev \\ libgmp-dev libisl-dev libmpc-dev libmpfr-dev libncurses5-dev libncursesw5-dev xxd \\ libtool picocom pkg-config python3-pip texinfo u-boot-tools util-linux Also, please install some python packages:\npip install kconfiglib Espressif Tools and Toolchains # Once the NuttX dependencies are available, it’s time to install the compilation tools for Espressif SoCs.\nInstall esptool:\npip install esptool Finally, install the toolchains to build the Espressif SoCs. It can be installed depending on the SoC being used, but it is highly recommended to keep all of them installed.\nRISC-V SoCs (ESP32-C3, ESP32-C6, ESP32-H2) # All RISC-V SoCs use the same toolchain. Currently (Jun 2024), NuttX uses the xPack’s prebuilt toolchain based on GCC 13.2.0-2 for RISC-V devices. Please, visit the ESP32-C3\u0026rsquo;s Toolchain section in the NuttX documentation to check for the newest recommended RISC-V toolchain.\nCreate a directory to install the toolchain. It can be on your home directory:\nmkdir -p ~/riscv-none-elf-gcc Download and extract the toolchain on the new directory:\ncd ~/riscv-none-elf-gcc wget https://github.com/xpack-dev-tools/riscv-none-elf-gcc-xpack/releases/download/v13.2.0-2/xpack-riscv-none-elf-gcc-13.2.0-2-linux-x64.tar.gz tar -zxf xpack-riscv-none-elf-gcc-13.2.0-2-linux-x64.tar.gz Once extracted, add the location of the binaries to the user’s PATH and reload the terminal:\necho \u0026#34;export PATH=$HOME/riscv-none-elf-gcc/xpack-riscv-none-elf-gcc-13.2.0-2/bin:\\$PATH\u0026#34; \u0026gt;\u0026gt; ~/.bashrc This last step is optional and applicable only if you want to make the toolchain available automatically, even after a restart. On the other hand, exporting it to the PATH variable before using it is sufficient. Please also note that the ~/.bashrc is automatically sourced after a logout/login or after restarting the machine.\nMake sure to either\n1) export the PATH with the toolchain or\n2) source the ~.bashrc or\n3) logout and login or\n4) restart the machine.\nXtensa SoCs (ESP32, ESP32-S2, ESP32-S3) # Each Xtensa-based device has its own toolchain. However, they can be downloaded and configured in a bundle.\nIn a similar approach to RISC-V toolchain, visit the ESP32-S3\u0026rsquo;s Toolchain section in the NuttX documentation to check for the newest recommended Xtensa toolchain.\nCreate a directory to install the toolchain. It can be on your home directory:\nmkdir -p ~/xtensa-esp-elf Download and extract the toolchain on the new directory:\ncd ~/xtensa-esp-elf wget https://github.com/espressif/crosstool-NG/releases/download/esp-14.2.0_20241119/xtensa-esp-elf-14.2.0_20241119-x86_64-linux-gnu.tar.xz tar -xf xtensa-esp-elf-14.2.0_20241119-x86_64-linux-gnu.tar.xz Once extracted, add the location of the binaries to the user’s PATH and reload the terminal:\necho \u0026#34;export PATH=$HOME/xtensa-esp-elf/xtensa-esp-elf/bin:\\$PATH\u0026#34; \u0026gt;\u0026gt; ~/.bashrc To check if the toolchain is properly installed:\nxtensa-esp32-elf-gcc --version xtensa-esp32s2-elf-gcc --version xtensa-esp32s3-elf-gcc --version Getting NuttX # Clone the NuttX repository and the NuttX Apps repository in a directory called nuttxspace. The Apps repository is optional, as it contains mostly example applications.\nmkdir nuttxspace cd nuttxspace git clone https://github.com/apache/nuttx.git nuttx git clone https://github.com/apache/nuttx-apps apps Building an App to Connect to a Wi-Fi network # NuttX provides ready-to-use board default configurations that enable the required config (from Kconfig) for a use scenario, such as Wi-Fi or I2C. To enter NuttX directory and list all available configurations for the ESP32 DevKitC V4 board you can use the following command:\ncd nuttx ./tools/configure.sh -L | grep esp32-devkitc This command lists all available configurations for the ESP32-DevKitC board. These pre-defined configurations can be modified before building to better suit your application.\nMore information about this board can be found here. It embeds a USB-to-UART bridge chip to enable accessing the device\u0026rsquo;s UART0 through a micro-USB port. The board is also powered up through the USB.\nConnect the board to your computer and check if the associated USB port is available. In Linux:\nls /dev/tty* The currently logged user should have read and write access to the serial port over USB. This is done by adding the user to dialout group with the following command:\nsudo usermod -a -G dialout $USER Connecting to a Wi-Fi Access Point # As an example, let\u0026rsquo;s use the Wi-Fi configuration for the ESP32 DevKitC board with the following command:\n./tools/configure.sh esp32-devkitc:wifi To change some configuration in the default configuration that was just loaded, use menuconfig:\nmake menuconfig The menuconfig utility allows you, for instance, to enable peripherals, modify the NuttX kernel settings, enable support for device drivers, configure the NuttShell and the file system, enable example programs and set up the Wi-Fi credentials.\nTo quickly connect to a known Wi-Fi network, navigate to Application Configuration -\u0026gt; Network Utilities -\u0026gt; Network Initialization -\u0026gt; WAPI Configuration and set the SSID (the name of the Wi-Fi Access Point) and the passphrase to connect to it.\nIt is also necessary to set how to get a valid IP address after connecting to the Wi-Fi network. In this example, DHCP will be used to receive it from the network automatically. In Application Configuration -\u0026gt; Network Utilities -\u0026gt; Network Initialization -\u0026gt; IP Address Configuration, select Use DHCP to get IP address.\nNavigate to the Exit and, when prompted, save the current settings.\nBefore building and flashing the firmware, it is necessary to build the bootloader to boot NuttX:\nmake bootloader To build and flash the ESP32 board, use the following command (modifying the USB port accordingly):\nmake flash ESPTOOL_PORT=/dev/ttyUSB0 ESPTOOL_BINDIR=./ When flashing is complete, you can use picocom to open a serial console by running:\npicocom -b115200 /dev/ttyUSB0 Please check the following example that shows the device connecting to the Wi-Fi network and other commands that can be used in the NuttShell, like ifconfig:\nIt\u0026rsquo;s worth noting that there is no need to pre-define the SSID/passphrase of the Wi-Fi network in menuconfig. NuttX provides the wapi application that manages the Wi-Fi subsystem. More information about wapi can be found in NuttX documentation. Experiment with wapi for scanning available access points, for instance:\nwapi scan wlan0 Conclusion # NuttX is one of the most preferred RTOS for developers familiar with Linux interfaces (including the so-called \u0026ldquo;Embedded Linux\u0026rdquo;) because of its POSIX-compliant interface. Most of the features covered by this introductory article rely on usual applications, like the NuttShell (or NSH: the shell system used in NuttX, similar to bash) and usual built-in commands, like ping. Stay tuned for more articles about NuttX (in special, for the question \u0026ldquo;Why using NuttX\u0026rdquo;?).\nUseful Links # NuttX Documentation NuttX GitHub NuttX channel on Youtube Developer Mailing List The original article was published on Medium, on the ESP Journal. It has since been updated.\n","date":"30 November 2020","externalUrl":null,"permalink":"/blog/2020/11/nuttx-getting-started/","section":"Blog","summary":"This article provides a tutorial to get started with NuttX.","title":"Getting Started with NuttX and ESP32","type":"blog"},{"content":"Hi everyone,\nEarlier this week, the news about the upcoming release of ESP32-C3, Espressif’s single-core, RISC-V-based, Wi-Fi and Bluetooth LE 5.0 MCU, took the online maker community by storm. We’re delighted to know that so many people are eager to find out more about Espressif’s new products! That’s why we’re including in this month’s newsletter a comprehensive article about ESP32-C3 along with the relevant datasheet.\nESP32-C3 is, of course, part of our MINI series of modules, which we announced back in August 2020, as you might remember. So, here’s some more news about the MINI series: the engineering samples of ESP32-S2-MINI-1/1U, ESP32-MINI-1 and ESP32-PICO-MINI-02 are now available on Espressif’s official sample provider webpage. Make sure you order your samples today, so you can start working on your new ESP projects as quickly as possible!\nAlso, if you’re getting into a Christmassy mood already, you can order a couple of more samples and give them to your maker friends as a gift. We can guarantee they will love them! Espressif’s MINI series of modules are an ideal choice for a wide variety of application scenarios relating to the Internet of Things, wearable electronics and smart home .\nOn a different note, IOT2TANGLE’s hackathon that Espressif System sponsored along with other IoT companies was calling for the best IoT/IOTA integrations until November 25th at 11:59 PM CET.\nWe’re really excited that dozens of registered projects have been submitted by contestants from all around the world , e.g. from Argentina, Brazil, Canada, Denmark, Germany, India, Indonesia, Italy, Peru, Switzerland, the United States, and many other countries. This hackathon, entitled “Integrate Everything with IOTA”, aims to generate quality open-source integrations that will be valuable stepping-stones for subsequent development projects that connect IoT devices with Distributed Ledger Technologies.\nGood luck to all the participants!\nOther topics you can read about in this month’s newsletter include:\nIntroducing ESP32-C3 ESP32-C3 is a single-core Wi-Fi and Bluetooth LE 5.0 microcontroller unit, based on the open-source RISC-V architecture. It strikes the right balance of power, I/O capabilities and security, thus offering the optimal cost-effective solution for connected devices. The availability of Wi-Fi and Bluetooth LE 5.0 connectivity makes the device configuration easy, while also enabling a variety of dual connectivity use-cases.\nESP Product Selector Launched Our new ESP Product Selector is an online tool designed to increase development efficiency and reduce the time for business communication. To use it, customers do not need to register with us or download the tool. All they need to do is click on the link and use it, taking advantage of its simple function and multiple benefits.\nAimagin’s ESP32-powered Waijung 2 Released Waijung 2 is Aimagin’s next generation model-based development platform for embedded systems, which automatically generates C code from Simulink model files, compiles it, and downloads .bin to ESP32 MCUs. Waijung 2 speeds up complex stand-alone and IoT device development, since there is no need for writing a single line of C or HTML code.\nESP32-powered BBC Doctor Who HiFive Inventor Coding Kit Industry leading partners, Tynker and BBC Learning, have taken coding to the next level with the revolutionary new ESP32-powered BBC Doctor Who HiFive Inventor Coding Kit. It comes with a Wi-Fi \u0026amp; Bluetooth combo MCU board, along with guided lessons aimed at teaching children how to use Block Coding and MicroPython for IoT applications.\nHope you enjoy reading this month’s newsletter. Keep sending us your messages and requests on Facebook, Twitter, GitHub, Instagram, LinkedIn, and YouTube.\nYou can also contact us through our website or you can email us! We try to respond to all of your messages as quickly as possible!\nBest wishes,John Lee.Senior Customer Support Officer\n","date":"30 November 2020","externalUrl":null,"permalink":"/blog/november-2020/","section":"Blog","summary":"","title":"November 2020","type":"blog"},{"content":"Hi everyone,\nWe are really happy about the successful outcome of the webinar we jointly organised with Amazon Web Services this month. It was an online event which took place on Tuesday, 27 October 2020. The main objective of this webinar was to demonstrate how to build voice-interactive products with AVS Integration for AWS IoT Core, using Espressif’s ESP32-Vaquita-DSPG development kit.\nAs we all know, Alexa-based voice-interactive solutions have become a mainstream way for controlling IoT devices. With the advent of Alexa Voice Service (AVS) Integration for AWS IoT Core, low-power, low-cost microcontrollers have started playing a significant role in creating connected devices with Alexa built-in capabilities. So, in our webinar we showed participants how a solution based on Espressif’s ESP32-Vaquita-DSPG development kit, in conjunction with the rich set of Amazon Web Services, can be used to simplify building Alexa-based voice-interactive devices.\nMore specifically, we talked about AVS Integration for the AWS IoT Core protocol, the hardware and software system architecture that is based on ESP32-Vaquita-DSPG, the engineering efforts required to build voice-controlled devices, the ways in which users can accelerate development and manage deployment nowadays, and finally the manufacturing and certification issues that should always be taken into consideration.\nOur webinar was addressed to Technical Decision Makers in Engineering, Solution Architects, Product Managers of voice-enabled products, Engineers of Embedded Hardware/Software, and Cloud Engineers. Indeed, the audience we attracted on the day was truly diverse, enthusiastic and keen on learning more about the technological solutions we presented. We were delighted to welcome all of them to an event that was both fun and useful, while we also look forward to continuing our collaboration with AWS on all fronts.\nOther topics you can read about in this month’s newsletter include:\nESP HomeKit SDK Opened Up on GitHub # ESP HomeKit SDK, which is Espressif’s own implementation of the Apple HomeKit, has become available on GitHub and supports ESP32, ESP32-S2 and ESP8266. So, developers can now create smarter and safer home devices with the ESP HomeKit SDK, taking advantage of Espressif’s full support for all the stages of development, certification and manufacturing.\nNew ESP RainMaker Features # One of the most recent new features we have added to ESP RainMaker is the ESP RainMaker Scheduling. You can now schedule certain actions that will be triggered on your devices at any given time on any specified day or days of the week.\nESP32-S2-based FeatherS2 Released # Unexpected Maker, who is also known as Seon Rozenblum, has officially released FeatherS2. This is a Feather-compatible development board that has been built around Espressif Systems’ latest ESP32-S2 microcontroller.\nSwarmDrive: NickStick’s ESP32-Powered Dev Board for Experimentation and Learning # NickStick’s SwarmDrive has an ESP32-powered board and strong educational documentation. As such, it helps professionals and students alike learn about different commutation algorithms and all the other aspects of electric (BLDC) motors.\nRosie: The Robot Maid Using ESP8266 # Rosie is created by DJ Harrigan, who was inspired by a character from the famous cartoon entitled “The Jetsons”. This open-source robot maid uses Arduino and ESP8266, is easy-to-build and is intended to be the first step towards DIY robots.\nHope you enjoy reading this month’s newsletter. Keep sending us your messages and requests on Facebook, Twitter, GitHub, Instagram, LinkedIn, and YouTube.\nYou can also contact us through our website or you can email us! We try to respond to all of your messages as quickly as possible!\nBest wishes,John Lee.Senior Customer Support Officer\n","date":"17 November 2020","externalUrl":null,"permalink":"/blog/october-2020/","section":"Blog","summary":"","title":"October 2020","type":"blog"},{"content":"","date":"27 July 2020","externalUrl":null,"permalink":"/tags/embedded-club/","section":"Tags","summary":"","title":"Embedded Club","type":"tags"},{"content":"Hi everyone,\nYou might remember that a rather short while ago we launched ESP RainMaker, Espressif’s end-to-end platform which enables makers to realize their IoT ideas faster and without the hassle of managing the infrastructure involved in this process. Today, we are pleased to announce that we have recently added a number of features to this platform. So, ESP RainMaker now supports ESP32 too, on top of ESP32-S2, with which our end-to-end platform was initially launched. It also supports BLE-based Wi-Fi provisioning for ESP32. Another new feature is the recently-released, third-party voice integrations with Alexa and Google Voice Assistant skills, which enable your ESP RainMaker-based devices to be controlled with voice commands.\nFurthermore, the newly-introduced support for OTA firmware upgrades will allow you to remotely upgrade the firmware of your devices by using the ESP RainMaker command line interface. We have also released resources for Android and iOS smartphone applications, so that you can customize your projects as per your requirements. Finally, a VSCode extension with which you can control ESP RainMaker-based devices is also available now. Stay tuned for more ESP RainMaker features that are coming up shortly!\nAnother piece of news I would like to highlight is Espressif’s first quarterly donation to The IUCN Red List of Threatened Species™. This year we started a wildlife protection program, in an effort to raise public awareness of the current climate crisis and the natural habitat’s encroachment by humans in recent decades. In July 2020, we donated to The IUCN Red List of Threatened Species™ the proceeds from the three development boards included in this initiative so far:\nESP32-Vaquita-DSPG, ESP32-S2-Saola-1, and ESP32-S2-Kaluga-1.\nSo, we would like to extend a heartfelt “thank you” to all the developers who have purchased the above-mentioned products and made our first donation possible. We greatly appreciate your contribution to our wildlife protection program and we look forward to welcoming more and more supporters in the future!\nOther topics you can read about in this month’s newsletter include:\nESP32-PICO-V3-ZERO, also known as the “Alexa Connect Kit (ACK) module with Espressif”, which provides an easy way for customers to build Alexa-compatible devices; TDK SmartBug™ (MD-42688-P), which is a multi-sensor wireless module that leverages Espressif’s powerful ESP32 SoC, as well as TDK’s MEMS sensors and algorithms for a wide range of IoT applications; WT-32-SC01, which is an ESP32-based development board with a colour display that has recently been launched by Wireless-Tag Technology Co. Ltd; A fantastic offer by the ESP32-powered obniz platform, which gives the relevant operating system for free to one device per obniz account. Hope you enjoy reading this month’s newsletter. Keep sending us your messages and requests on Facebook, Twitter, LinkedIn, Instagram and YouTube. We try to respond to all of your messages as quickly as possible!\nBest wishes,John Lee.Senior Customer Support Officer\nAlexa Connect Kit Module with Espressif Released # ESP32-PICO-V3-ZERO, which is also known as the “Alexa Connect Kit (ACK) module with Espressif”, provides an easy way for developers to build Alexa-compatible devices, without worrying about managing cloud services, writing an Alexa Skill, phone applications or complex device firmware. It provides Alexa connectivity and supports features like Frustration-Free Setup and Amazon Dash Replenishment.\nKeep Reading\nSmartBug: ESP32-based All-in-One Wireless Sensor Module # TDK SmartBug™ (MD-42688-P) is a module that leverages the power of Espressif’s flagship SoC, ESP32, while also combining six sensors, a powerful wireless (BLE) MCU, seven algorithm-driven features and a rechargeable battery, all in a small enclosure. Furthermore, SmartBug comes with the option of an Add-On board that includes a Wi-Fi module, an SD card slot and an ultrasonic sensor from TDK.\nKeep Reading\nNew Color Display for ESP32 by Wireless-Tag Technology Co. Ltd # WT-32-SC01 is an ESP32-based development board with a touch screen, which has recently been launched by Wireless-Tag Technology Co. Ltd. Leveraging the power of ESP32, the WT-32-SC01 development board is capable of processing full-colour high-resolution images and JPEG decoding.\nKeep Reading\nFantastic Offer by ESP32-based Platform Obniz # Nearly a year ago, Japanese IoT company Cambrian Robotics Inc. released the obniz development board, operating system and cloud services, all of which are based on Espressif’s ESP32-WROOM-32. ObnizOS is the specific software that runs on the obniz development board, enabling its operation via APIs over the obniz cloud. ObnizOS is now available to one device per account for free!\nKeep Reading\nOriginally published at https://mailchi.mp.\n","date":"27 July 2020","externalUrl":null,"permalink":"/blog/july-2020/","section":"Blog","summary":"","title":"July 2020","type":"blog"},{"content":"Hi everyone,\nWe’ve got some exciting news for you this month! In response to our customers’ requests, we have just launched ESP-Hosted. This is a project which addresses our customers’ requirement to use ESP32 as a connectivity module with Linux-based host controllers.\nMore specifically, the ESP-Hosted project offers a way of using ESP32 as a communication processor that provides Wi-Fi and Bluetooth/BLE connectivity to the host MCU. In this context, ESP32 provides a standard network-interface implementation for the host to receive and transmit 802.3 frames. The host can use its own TCP/IP and TLS stack above the network interface that the application uses. For Bluetooth connectivity, ESP32 provides a standard host controller interface (HCI), on which the host can run a Bluetooth host stack. Although this project does not provide a standard 802.11 interface to the host, it does provide the control path with a custom command implementation, based on Protobufs, both on the host-side and the ESP32-side.\nOn our GitHub webpage, you can get all the information about ESP-Hosted, along with the relevant diagrams and getting-started instructions. Other topics you can read about in this month’s newsletter include:\nATOM Echo, an ESP32-based miniature programmable smart speaker by M5Stack. With ATOM Echo, you and your friends can now enjoy your favorite music everywhere! An ESP32-based Wi-Fi-connected espresso machine, with which you can make the most elaborate tasting coffee in the “Blynk” of an eye! A cool project by the Embedded Club founder, Ashok, who used ESP8266 for hacking the IR remote control of his air cooler. This project shows that you can hack pretty much any infrared remote control in the same way! Hope you enjoy reading this month’s newsletter. Keep sending us your messages and requests on Facebook, Twitter, LinkedIn, Instagram and YouTube. We try to respond to all of your messages as quickly as possible!\nBest wishes,John Lee.Senior Customer Support Officer\nATOM Echo: ESP32-based Miniature Programmable Smart Speaker by M5Stack # M5Stack’s ATOM Echo is a tiny programmable smart speaker. It makes full use of ESP32’s IoT power, while the design of ATOM Echo is based on the M5ATOM series of products. Its slim design measures only 24x24x17mm, so the gadget itself can be easily carried anywhere. At the same time, its premium finish gives it a sleek appearance.\nKeep Reading\nESP32-based Wi-Fi-connected Espresso Machine # Fracino, an award-winning UK manufacturer of cappuccino and espresso machines, chose an ESP32-powered mobile app for building an efficient and aesthetically pleasing solution for their client, Londinium espresso. The ESP32-based app, which was created by Blynk IoT, controls all the main parameters of the espresso machine effortlessly.\nKeep Reading\nAlexa-controlled Air Cooler with ESP8266 # Ashok, the founder of Embedded Club, a community of makers in India, focused on embedded programming / design, STEM trainings, application development and 2D/3D animations, has come up with really cool project. He hacked the remote control of an air cooler, using ESP8266. More importantly, though, this project demonstrates that any infrared remote control can be hacked in the same way!\nKeep Reading\nOriginally published at https://mailchi.mp.\n","date":"27 July 2020","externalUrl":null,"permalink":"/blog/june-2020/","section":"Blog","summary":"","title":"June 2020","type":"blog"},{"content":"Internal memory of the MCU is probably the most precious resource as it occupies maximum area in the chip. The newer application use-cases have ever increasing memory requirement. For making the most of the hardware, understanding of the memory architecture and optimising of the memory for application’s use-case becomes important. Especially with the ESP32 SoC architecture that includes communication subsystems (Wi-Fi and BT/BLE) that requires certain memory to operate, it becomes necessary for the application to understand the requirements and tune their memory.\nWe often get questions about available memory headroom for the application; and there is no easy answer to that question unless we go into the details of the use-case. But when developers understand the details about memory layout, system requirements and the common methods to optimise, we have seen that ESP32 can accommodate quite a variety of interesting application use-cases.\nThis blog is intended to provide an overview of ESP32 SoC’s memory layout for application developers, explain different memory regions and their characteristics and discusses the memory allocation for a typical ESP32 firmware.\nPlease note that all the specific details mentioned here are with respect to ESP-IDF release version 4.0 which is the latest stable release at the time of writing of this blog.\nInternal RAM Layout # The above diagram shows the ESP32 internal memory (SRAM) layout. The SRAM is divided into 3 memory blocks SRAM0, SRAM1 and SRAM2 (and two small blocks of RTC fast and slow memory which we’ll consider separately later).\nThe SRAM is used in two ways — one for instruction memory — IRAM(used for code execution — text data) and data memory — DRAM (used for BSS, data, heap). SRAM0 and SRAM1 can be used as a contiguous IRAM whereas SRAM1 and SRAM2 can be used as a contiguous DRAM address space.\nWhile SRAM1 can be used as a IRAM and DRAM both, for practical purposes, ESP-IDF uses SRAM1 as DRAM, as it’s generally the data memory that applications fall short of. The above diagram shows the memory map for programmers to consider for their application development where they get 192KB IRAM and 328KB DRAM. While it does not matter much for the application as there is no overlap, please note that the direction of the address range is opposite for IRAM and DRAM address spaces.\nIRAM Organisation # Lets now zoom into the IRAM section.\nThe 192 KB of available IRAM in ESP32 is used for code execution, as well as part of it is used as a cache memory for flash (and PSRAM) access.\nFirst 32KB IRAM is used as a CPU0 cache and next 32KB is used as CPU1 cache memory. This is statically configured in the hardware and can’t be changed. After the first 64KB, the linker script starts placing the text region in IRAM. It first places all the interrupt vectors and then all the text in the compiled application that is marked to be placed in IRAM. While in common case, majority of the application is executed out of the flash (XiP), there are some portions of the applications which are time critical, or that operate on flash itself. They need to be placed in IRAM and that is achieved using a special attribute to these functions or files and linker script doing a job of placing them in IRAM. The symbols _iram_text_start and _iram_text_end are placed by the linker script at the two boundaries of this text section. The IRAM after the text section remains unused and is added to the heap. _iram_text_start and _iram_text_end symbols are placed by the linker script at the two boundaries of this text section. The IRAM after the text section remains unused and is added to the heap.\nAlso, when the application is configured in a single-core mode, the CPU1 is not functional and CPU1 cache is unused. In that case, CPU1 cache memory (0x40078000–0x4007FFFF ) is added to the heap.\nThe unused IRAM, that is placed in the heap, can be accessed through dynamic allocations.\nIt can be used to place any code in IRAM if the application has such a requirement. However this is quite uncommon.\nThe IRAM can also be used for data, but with two important limitations.\nIf the application has such data that can obey these two rules of accesses, it can make use of IRAM memory for that data.\nThere is also a way to access IRAM without this limitations; but as a slower memory. This is discussed in a later section.\nDRAM Organisation # The above diagram shows a typical (simplified) DRAM layout for an application. As the DRAM addresses start at the end of SRAM2, increasing in backward direction, the link time segments allocation happens starting at the end of SRAM2.\nThe first 8KB (0x3FFA_E000–0x3FFA_FFFF) are used as a data memory for some of the ROM functions. The linker then places initialised data segment after this first 8KB memory. Zero initialised BSS segment comes next. The memory remaining after allocating data and BSS segments, is configured to be used as a heap. This is where typical dynamic memory allocations go. Please note that the size of data and BSS segments depend on the application. So each application, based on the components that it uses and APIs it calls has a different available heap size to begin with.\nThere are two regions within the heap (0x3FFE_0000–0x3FFE_0440 — 1088 bytes) and (0x3FFE_3F20–0x3FFE_4350–1072 bytes) that are used by ROM code for its data. These regions are marked reserved and the heap allocator does not allocate memory from these regions.\nDRAM Organisation with BT Enabled # When BT functionality is enabled, the BT controller (software and hardware) needs to use a dedicated data memory. This memory is used as data/BSS for the controller as well as for transfer memory for BT packets between the software and hardware. So the linker script reserves 54KB of memory in addition to the default DRAM allocations between 0x3FFB_0000–0x3FFB_DB5C. The application’s data and BSS segment allocations continues after this region.\nWhen only BLE functionality is used by the application, a part of the BT controller memory can be relinquished back to the heap. The amount of memory that is released and added to the heap is ~19KB.\nDRAM Organisation with Trace Memory # When the application level tracing is enabled, it reserves a fixed 32 KB memory at the end of DRAM. Note that the above diagram shows the layout with BT disabled. But possibly application can use tracing with BT enabled too and in that case BT controller memory will be reserved as well by the linker script.\nExternal SPIRAM # ESP32 provides an ability to interface optional Pseudo-Static RAM (PSRAM a.k.a SPIRAM) on the same QSPI bus used for the flash using a different chip-select. This memory is directly addressable and just like flash, the accesses to this memory go through cache that is part of IRAM. ESP32 can map maximum 4MB SPIRAM at a time in its address space in the range 0x3F80_0000 to 0x3FBF_FFFF. There are three ways for the application to make use of the SPIRAM\nWhile this allows application to use additional memory, there are certain restrictions on the use of SPIRAM\nThese ways of using SPIRAM and restrictions on using it are documented in detail here.\nHeap Allocator # From the above diagrams for IRAM and DRAM memory layout you can see that DRAM area _bss_end to 0x3FFF_FFFF (or _heap_end in case of trace memory enabled) and IRAM area _iram_text_end to 0x4009_FFFF are unused memory segment. If SPIRAM is available in the system, that too has unused memory. The application and SDK components always need to allocate and free the memory on demand. So a general purpose memory allocator — a.k.a. Heap Allocator operates on the available free memory and provides memory allocation and freeing APIs for them.\nAs you see, the memory regions under the heap allocator’s control have different capabilities and access properties. Hence ESP-IDF implements a capability based heap allocator where the caller can specify the purpose of allocation along with the size of allocation. For example, an application may ask for memory specifically that is capable of DMA for using it with some peripheral or it may as memory explicitly from external SPIRAM for audio buffers for which allocating from internal DRAM is not preferred.\nESP-IDF also performs generic malloc and free APIs above the heap allocator’s capability based allocation APIs to make the application porting easy from POSIX type systems. The application configuration can have governing rules to prefer the use of certain memory segment for malloc API based on allocation size.\nUsing IRAM for Data # Starting with ESP-IDF release 4.2, we have added an ability to use IRAM for data. As mentioned above, IRAM has access limitations in terms of alignment of address and size. If an unaligned access is made, it results into an exception. The ESP-IDF, after release 4.2, handles these exceptions transparently to provide load/store as desired by the caller. As these unaligned accesses result in exception, the access is slower than the DRAM access. Typically each exception handling requires approximately 167 CPU cycles (i.e. 0.7 usec per access at 240 MHz or 1 usec per access at 160 MHz). The application or SDK components can use the IRAM for data either for BSS at link time or through heap allocator at run time. There are two limitations in using IRAM for data:\nESP-IDF 4.2 provides some ready-made configurations to make effective use of unused IRAM for data such as TLS transmit and receive fragments in single-core mode.\nPlease checkout this blog for a case-study for memory analysis of an AWS-IoT client application and some common optimisation techniques.\nIn the next blog, we’ll see more details about how Wi-Fi subsystem and BT subsystem use the memory so that memory availability for the application can be determined. We’ll also see various common use-cases and their memory consumption and possible optimisations for these use-cases. Please stay tuned.\n","date":"2 July 2020","externalUrl":null,"permalink":"/blog/esp32-programmers-memory-model/","section":"Blog","summary":"","title":"ESP32 Programmers’ Memory Model","type":"blog"},{"content":" IoT, in general, has come a long away. During the very early stage, there was browser based control and monitoring, which, though more convenient than non-IoT devices, had a very narrow market. With the advent of Smartphones, IoT devices became much more easier to use and mass adoption became a possibility. However, the real push was given by the advent of various eco-systems and Voice assistants like Siri, Alexa and Google Assistant. Controlling by just asking verbally is much more natural than opening some app in a smartphone and tapping buttons.\nWith this in mind, we now have added 3rd party integrations, particularly Alexa and Google Voice Assistant (GVA) support in ESP RainMaker!\nHow does this work? # If you are already familiar with ESP RainMaker, you may know that it has the concepts of devices and parameters. The devices and parameters have an optional “type” field. We have defined our own standard types for some common smart home devices like switches, lightbulbs, fans, etc. You can find information about the standard types here. We have now created a layer which maps these parameters to formats that are understood by Alexa and GVA. So a device type in RainMaker (like light, switch, etc.) maps to a similar device type there, and their parameters like power, brightness, hue, saturation, intensity. etc. get mapped to the corresponding capabilities/traits. If you have just the power and brightness params, you get a simple brightness controllable light. If you include hue, saturation and intensity, you get a color light in Alexa and GVA.\nUsage # The code required to implement the standard devices is very simple. Let us look at a colour light example (led_light) which is already available on GitHub. The relevant code snippet below is self explanatory.\n/* Create a standard lightbulb (internally adds name and power as mandatory parameters */ esp_rmaker_create_lightbulb_device(\u0026#34;Light\u0026#34;, common_callback, NULL, DEFAULT_POWER); /* Add the standard brightness parameter */ esp_rmaker_device_add_brightness_param(\u0026#34;Light\u0026#34;, \u0026#34;brightness\u0026#34;, DEFAULT_BRIGHTNESS); /* Add the standard hue parameter */ esp_rmaker_device_add_hue_param(\u0026#34;Light\u0026#34;, \u0026#34;hue\u0026#34;, DEFAULT_HUE); /* Add the standard saturation parameter */ esp_rmaker_device_add_saturation_param(\u0026#34;Light\u0026#34;, \u0026#34;saturation\u0026#34;, DEFAULT_SATURATION); The switch example on GitHub is also ready out of the box for Alexa/GVA.\nOnce you build and flash the Lightbulb/Switch example, provision your board and link to your account using the ESP RainMaker Phone apps. Give the device some friendly name so that it is easy to identify.\nEnabling Alexa # Open the Alexa app on your phone, go to Skills and Games in the menu and search for ESP RainMaker. Select the skill, tap on “Enable to Use” and provide your RainMaker credentials. Once the account linking is successful, allow Alexa to discover your devices. Once the devices are successfully discovered, the setup is complete and you can start controlling them using Alexa. Enabling Google Voice Assistant (GVA) # Open the Google Home app on your phone. Tap on “+” -\u0026gt; Set up Device. Select the “Works with Google” option meant for devices already set up. Search for ESP RainMaker and sign in using your RainMaker credentials. Once the Account linking is successful, your RainMaker devices will show up and you can start using them. Some users may not see the list like above, but the devices should show up in the device list in the Google Home app. So, go ahead and start linking your RainMaker devices to your favourite voice assistants. Currently, only switch and light are supported. Let us know what you would like us to add next by dropping a message either on the forum or GitHub.\n","date":"30 June 2020","externalUrl":null,"permalink":"/blog/3rd-party-integrations-in-esp-rainmaker/","section":"Blog","summary":"","title":"3rd Party Integrations in ESP RainMaker","type":"blog"},{"content":"","date":"30 June 2020","externalUrl":null,"permalink":"/tags/alexa/","section":"Tags","summary":"","title":"Alexa","type":"tags"},{"content":"","date":"30 June 2020","externalUrl":null,"permalink":"/tags/google-home/","section":"Tags","summary":"","title":"Google Home","type":"tags"},{"content":"","date":"24 June 2020","externalUrl":null,"permalink":"/tags/debugger/","section":"Tags","summary":"","title":"Debugger","type":"tags"},{"content":"This article outlines a quick and easy way to start a debugger from the command line. More specifically, it discusses the debugging targets of idf.py, which have been added to ESP-IDF from v4.2. At the time of writing, IDF v4.2 is not released yet, but you can try out this feature on the master branch.\nWhy Do We (Not) Debug # Debugging is an essential development technique, no less so for embedded platform engineers. However, getting the debugging tools to work on embedded platforms is often more complex. Also, asking an ESP32 developer how they debug suggests that the ESP platform may be just as complex, because the more common answers seem to favor printf()s or GPIO toggling as a debugging technique.\nCheck It Out # Many developers who work with ESP-IDF rely on the command line tools for configuring, building, and debugging their applications. Although IDE plugins are also available (Espressif IDF Eclipse Plugins, ESP-IDF Visual Studio Code Extension), they are not the subject of this article. idf.py is the main command tool in ESP-IDF CMake based build system. It is most often known for the idf.py menuconfig and idf.py flash monitor commands.\nDebugging commands are available, as well, to make the JTAG configuration easier to use. To explore this option, let’s just connect an ESP32 WROVER-KIT, and start building a project by typing:\nidf.py flash monitor openocd gdbgui This command does several things:- flashes the application to the development board- opens IDF Monitor to observe serial output- starts OpenOCD debugger and a gdbgui debug server- opens a web browser, where gdbgui interface is displayed.\nOverview of the New Debugging Targets # idf.py now implements the actions described below. For instructions on setting up JTAG debugger with an ESP32, see the JTAG debugging section in IDF programming guide. Please note that a board with JTAG interface must be connected to use any of these debugging targets.\nidf.py openocd # Runs OpenOCD in a console with configuration defined in the environment or via command line.\nBy default, it is assumed that ESP32 WROVER-KIT board with 3.3V flash is used. This configuration also works with an ESP32 Ethernet Kit and many other boards. To override the default, set OPENOCD_COMMANDS environment variable or pass an \u0026ndash;openocd-commands argument.\nidf.py gdb # Starts the gdb in the current active console with the project’s elf file.\nidf.py gdbtui # Starts the gdb the same way as above, but with the \u0026ndash;tui argument allowing very simple source code view in a textual user interface mode.\nidf.py gdbgui # Starts gdbgui debugger frontend enabling out-of-the-box debugging in a browser window.\nPutting More Actions Together # It is possible to combine multiple debugging actions on a single command line, thus allowing a convenient setup of blocking and non-blocking actions in one step.* * idf.pyimplements a simple logic to move the background actions (such as OpenOCD) to the beginning, and the interactive ones (such as gdb or monitor ) to the end of the action list.\nAn example of a very useful combination is shown below with the corresponding screenshot.\nidf.py gdbgui monitor openocd This command starts OpenOCD in the background, while it opens gdbgui in a browser and the IDF-monitor in the active console window, allowing the user to observe serial output and debug it at the same time. When the monitor exits with Ctrl + ], all debugging actions are terminated and cleaned up.\nExplore JTAG # If you are a “command-line person” or a dedicated IDE user, please step into these new debugging functions and give them a try to explore the ESP chips from the JTAG perspective!\nFor More Information # Official documentation of JTAG Debugging with idf.py idf.py help or a contextual help related to the specific targets below: idf.py openocd --help idf.py gdb --help idf.py gdbtui --help idf.py gdbgui --help ","date":"24 June 2020","externalUrl":null,"permalink":"/blog/debugging-targets-of-idf.py/","section":"Blog","summary":"","title":"Debugging Targets of idf.py","type":"blog"},{"content":"","date":"24 June 2020","externalUrl":null,"permalink":"/tags/jtag/","section":"Tags","summary":"","title":"JTAG","type":"tags"},{"content":"Memory has significant impact on silicon cost as well as die size, hence from hardware perspective having optimal size is important and from software perspective being able to utilise it to fullest is crucial.\nIn this post we will discuss some upcoming features and commonly available configuration options (knobs) in ESP-IDF to allow end application to utilise various internal memory regions in most optimal way.\nImportant Notes # We will focus on single core mode of ESP32 here, as that is where more number of memory optimisation features are applicable. We will be considering typical IoT use-cases here where gaining memory at the cost of performance is acceptable criteria. We will take typical cloud application as case study which requires TLS connection with mutual authentication support. ESP-IDF feature branch used here can be found at, https://github.com/mahavirj/esp-idf/tree/feature/memory_optimizations ESP32: Internal Memory Breakup # As can be seen from above memory layout, there are various memory regions internal to silicon and of different clock speed. For single core use-cases, we get additional 32K of instruction memory, which otherwise would have acted as cache for APP CPU core. Instruction RAM access should always be 32-bit address and size aligned. For end application business logic, it is always desirable to have more DRAM, which is fastest memory without any access restrictions. Case Study — AWS IoT Sample Application # We will be taking subscribe_publish example from ESP-AWS-IoT here as case study to analyse memory utilisation. ESP-IDF provides an API to get minimum free heap or dynamic memory available in system using heap_caps_get_minimum_free_size(). Our aim would be to maximise this number (for relative analysis) and thus increase the amount of memory available for end application specific business logic (DRAM region to be specific). Default Memory Utilisation # We will be using following patch on top of subscribe_publish example to log dynamic memory statistics.\nFirst we will be logging system level minimum free heap numbers for DRAM and IRAM regions respectively as mentioned earlier. Second we will be using heap task tracking feature which provides information on dynamic memory usage on per task basis. This feature is modified to also log peak usage numbers for DRAM and IRAM regions on per task basis. We will be logging this information for aws_iot_task , tiT (tcpip) and wifi tasks respectively (as these tasks define data transfer path from application layer to physical layer and vice-versa). It is also to be noted that there will some variation in peak memory usage of networking tasks based on environmental (like WiFi connection, network latency) factors. Note: Change in core-id during task creation (from below patch) is for single core configuration that we are using for this particular example.\nWith default configuration (and heap task tracking feature enabled) we get following heap utilisation statistics (all values in bytes):\nTask Heap Utilisation Stats: || Task | Peak DRAM | Peak IRAM || || aws_iot_task | 63124 | 0 || || tiT | 3840 | 0 || || wifi | 31064 | 0 ||System Heap Utilisation Stats: || Minimum Free DRAM | Minimum Free IRAM || || 152976 | 40276 || Single Core Config # As mentioned earlier we will be using single core configuration for all our experiments. Please note that even in single core mode there is enough processing power available in ESP32 (close to 300 DMIPS), more than sufficient for typical IoT use-cases.\nCorresponding configuration to be enabled in application:\nCONFIG_FREERTOS_UNICORE=y Updated heap utilisation statistics from application re-run as following:\nTask Heap Utilisation Stats: || Task | Peak DRAM | Peak IRAM || || aws_iot_task | 63124 | 0 || || tiT | 3892 | 0 || || wifi | 31192 | 0 ||System Heap Utilisation Stats: || Minimum Free DRAM | Minimum Free IRAM || || 162980 | 76136 || As can be seen from above, we have gained ~10KB memory in DRAM, since some of services (e.g. idle, esp_timer tasks etc.) for second CPU core are not required anymore. In addition IPC service for inter processor communication is also no more required, so we gain from stacks and dynamic memory of that service. Increase in IRAM is due to the freeing up of 32KB cache memory of second CPU core and some of code savings due to disablement of above mentioned services.\nTLS Specific # Asymmetric TLS Content Length # This feature has been part of ESP-IDF from v4.0 onwards. This feature allows to enable asymmetric content length for TLS IN/OUT buffers. Thus application has an ability to reduce TLS OUT buffer from its default value of 16KB (maximum TLS fragment length per specification) to as small as say 2KB, and thus allowing 14KB of dynamic memory saving .\nPlease note that, it is not possible to reduce TLS IN buffer length from its default 16KB, unless you have direct control over server configuration or sure about server behaviour that it will never send inbound data (during handshake or actual data-transfer phase) over certain threshold.\nCorresponding configuration to be enabled in application:\n# Enable TLS asymmetric in/out content length CONFIG_MBEDTLS_ASYMMETRIC_CONTENT_LEN=y CONFIG_MBEDTLS_SSL_OUT_CONTENT_LEN=2048 Updated heap utilisation statistics from application re-run as following:\nTask Heap Utilisation Stats: || Task | Peak DRAM | Peak IRAM || || aws_iot_task | 48784 | 0 || || tiT | 3892 | 0 || || wifi | 30724 | 0 ||System Heap Utilisation Stats: || Minimum Free DRAM | Minimum Free IRAM || || 177972 | 76136 || As can be seen from above, we have gained ~14KB memory from aws_iot_task and thus minimum free DRAM number has increased accordingly.\nDynamic Buffer Allocation Feature # During TLS connection, mbedTLS stack keeps dynamic allocations active during entire session starting from initial handshake phase. These allocations includes, TLS IN/OUT buffers, peer certificate, client certificate, private keys etc. In this feature (soon to be part of ESP-IDF), mbedTLS internal APIs have been glued (using SHIM layer) and thus it is ensured that whenever resource usage (including data buffers) is complete relevant dynamic memory is immediately freed up.\nThis greatly helps to reduce peak heap utilisation for TLS connection. This will have small performance impact due to frequent dynamic memory operations (on-demand resource usage strategy). Moreover since memory related to authentication credentials (certificate, keys etc.) has been freed up, during TLS reconnect attempt (if required), application needs to ensure that mbedTLS SSL context is populated again.\nCorresponding configuration to be enabled in application:\n# Allow to use dynamic buffer strategy for mbedTLS CONFIG_MBEDTLS_DYNAMIC_BUFFER=y CONFIG_MBEDTLS_DYNAMIC_FREE_PEER_CERT=y CONFIG_MBEDTLS_DYNAMIC_FREE_CONFIG_DATA=y Updated heap utilisation statistics from application re-run as following:\nTask Heap Utilization Stats: || Task | Peak DRAM | Peak IRAM || || aws_iot_task | 26268 | 0 || || tiT | 3648 | 0 || || wifi | 30724 | 0 ||System Heap Utilization Stats: || Minumum Free DRAM | Minimum Free IRAM || || 203648 | 76136 || As can be seen from above, we have gained ~22KB memory from aws_iot_task and thus minimum free DRAM number has increased accordingly.\nNetworking Specific # WiFi/LwIP Configuration # We can further optimise the WiFi and LwIP configuration to reduce memory usage, at the cost of giving away some performance. Primarily we will reduce WiFi TX and RX buffers and try to balance it out by moving some critical code path from networking subsystem to instruction memory (IRAM).\nTo give some ballpark on performance aspect, with default networking configuration average TCP throughput is close to ~20Mbps, but with below configuration it will be close to ~4.5Mbps, which is still sufficient to cover typical IoT use-cases.\nCorresponding configuration to be enabled in application:\n# Minimal WiFi/lwIP configuration CONFIG_ESP32_WIFI_STATIC_RX_BUFFER_NUM=4 CONFIG_ESP32_WIFI_DYNAMIC_TX_BUFFER_NUM=16 CONFIG_ESP32_WIFI_DYNAMIC_RX_BUFFER_NUM=8 CONFIG_ESP32_WIFI_AMPDU_RX_ENABLED= CONFIG_LWIP_TCPIP_RECVMBOX_SIZE=16 CONFIG_LWIP_TCP_SND_BUF_DEFAULT=6144 CONFIG_LWIP_TCP_WND_DEFAULT=6144 CONFIG_LWIP_TCP_RECVMBOX_SIZE=8 CONFIG_LWIP_UDP_RECVMBOX_SIZE=8 CONFIG_ESP32_WIFI_IRAM_OPT=y CONFIG_ESP32_WIFI_RX_IRAM_OPT=y CONFIG_LWIP_IRAM_OPTIMIZATION=y Updated heap utilisation statistics from application re-run as following:\nTask Heap Utilization Stats: || Task | Peak DRAM | Peak IRAM || || aws_iot_task | 26272 | 0 || || tiT | 4108 | 0 || || wifi | 19816 | 0 ||System Heap Utilization Stats: || Minumum Free DRAM | Minimum Free IRAM || || 213712 | 62920 || As can be seen from above log, we have gained roughly ~9KB of additional DRAM for application usage. Impact (reduction) in total IRAM comes because we moved critical code path from networking subsystem to this region.\nSystem Specific # Utilising RTC (Fast) Memory (single-core only) # As can be seen from earlier memory breakup there is one useful 8KB RTC Fast memory (and reasonably fast) which has been sitting idle and not fully utilised. ESP-IDF will soon have feature to enable RTC Fast memory for dynamic allocation purpose. This option exists in single core configuration, as the RTC Fast memory is accessible to PRO CPU only.\nIt has been ensured that RTC Fast memory region will be utilised as first dynamic memory range, and most of startup, pre-scheduler code/services will occupy this range. This will allow to not have any performance impact in application code due to clock speed (slightly on slower side) of this memory.\nSince there are no access restrictions to this region, capability wise we will call it as DRAM henceforth.\nLet’s re-run our application with this feature and gather memory numbers.\nCorresponding configuration to be enabled in application:\n# Add RTC memory to system heap CONFIG_ESP32_ALLOW_RTC_FAST_MEM_AS_HEAP=y Updated heap utilisation statistics from application re-run as following:\nTask Heap Utilization Stats: || Task | Peak DRAM | Peak IRAM || || aws_iot_task | 26272 | 0 || || tiT | 4096 | 0 || || wifi | 19536 | 0 ||System Heap Utilization Stats: || Minumum Free DRAM | Minimum Free IRAM || || 221792 | 62892 || As can be seen from above log, we have gained 8KB of additional DRAM for application usage.\nUtilising Instruction Memory (IRAM, single-core only) # So far we have seen different configuration options to allow end application to have more memory from DRAM (data memory) region. To continue along similar lines, it should be noted that there is still sufficient IRAM (instruction memory) left but it can not be used as generic purpose due to 32-bit address and size alignment restrictions.\nIf access (load or store) is from IRAM region and size is not word-aligned, then processor will generate LoadStoreError(3) exception If access (load or store) is from IRAM region and address is not word-aligned then processor will generate LoadStoreAlignmentError(9) exception In this particular feature from ESP-IDF, above mentioned unaligned accesses have been fixed through corresponding exception handlers and thus resulting in correct program execution. However, these exception handlers can take up-to 167 CPU cycles for each (restricted) load or store operation. So there could be significant performance penalty (as compared with DRAM access) while using this feature.\nThis memory region can be used in following ways:\nFirst through heap allocator APIs using special capability field known as MALLOC_CAP_IRAM_8BIT Second by redirecting DATA/BSS to this region using provided linker attributes, IRAM_DATA_ATTR and IRAM_BSS_ATTR Limitations wise:\nThis memory region can be not be used for DMA purpose This memory region can not be used for allocating task stacks While discussing usage of this memory region with understood performance penalty, TLS IN/OUT (per our configuration value of buffer 16KB/2KB) buffers were found to be one of the potential candidate to allocate from this region. In one of the experiments, for transfer of 1MB file over TLS connection, time increased from ~3 seconds to ~5.2 seconds with TLS IN/OUT buffers moved to IRAM.\nIt is also possible to redirect all TLS allocations to IRAM region but that may have larger performance impact and hence this feature redirects only buffers whose size is greater or equal than minimum of TLS IN or OUT buffer (in our case threshold would be 2KB).\nLet’s re-run our application with this feature and gather memory numbers.\nCorresponding configuration to be enabled in application:\n# Allow usage of IRAM as 8bit accessible region CONFIG_ESP32_IRAM_AS_8BIT_ACCESSIBLE_MEMORY=y CONFIG_MBEDTLS_IRAM_8BIT_MEM_ALLOC=y Updated heap utilisation statistics from application re-run as following:\nTask Heap Utilization Stats: || Task | Peak DRAM | Peak IRAM || || aws_iot_task | 17960 | 21216 || || tiT | 3640 | 0 || || wifi | 19536 | 0 ||System Heap Utilization Stats: || Minumum Free DRAM | Minimum Free IRAM || || 228252 | 40432 || As can be seen from above log, we have gained another ~7KB of additional DRAM for application usage. Please note that, even though we have redirected all allocations above 2KB threshold to IRAM, there are still many smaller (and simultaneous) allocations happening from DRAM region (another local maxima) and hence effective gain is lower than what actually should have been. If additional performance impact is acceptable then it is possible to redirect all TLS allocation to IRAM and gain further at-least ~10–12KB memory from DRAM region.\nSummary # Having complete application control over selection of various features through configuration options is one of the important features in ESP-IDF. Through above exercise we have systematically evaluated various features and configuration options within ESP-IDF to increase DRAM (fastest memory) budget for end application by 63KB (minimum free DRAM size increased from ~160KB to ~223KB). Some of these configuration options are available for single-core configuration only (have been marked as such in title itself) but even in dual-core configuration memory savings are possible with rest of the options. It is further possible to utilise instruction memory (IRAM) as 8-bit accessible region for non-performance critical modules like logging and diagnostics by end application. It is recommended to disable some of the debugging features that we used in above exercise like heap task tracking to reduce metadata overhead (and further increase memory budget) once required system characterisation is achieved. References # Modified subscribe_publish example along with final sdkconfig.defaults file can be found here . This application should be built against ESP-IDF fork and feature branch from here . ","date":"1 June 2020","externalUrl":null,"permalink":"/blog/esp32-memory-analysis-case-study/","section":"Blog","summary":"","title":"ESP32 Memory Analysis — Case Study","type":"blog"},{"content":"","date":"1 June 2020","externalUrl":null,"permalink":"/tags/memory-optimization/","section":"Tags","summary":"","title":"Memory Optimization","type":"tags"},{"content":"Hi everyone,\nMay has been a busy and exciting month for all of us at Espressif! Our 2020 online and offline courses, based on ESP-Jumpstart, have just been released. These courses are part of our outreach program for Chinese graduates and final-year College students who are interested in pursuing an engineering career. We want to introduce them to the world of engineering through ESP32, while showing them the diverse career opportunities the Espressif is able to offer. In response to our uncertain times, the online part of our program has been especially designed as an all-inclusive learning opportunity for Chinese graduates either within the country or abroad, since their physical presence is not required for the completion of the course.\nWe believe that ESP-Jumpstart is the ideal platform for our outreach program, because it simplifies the process of building ESP32-based products. ESP-Jumpstart provides the optimal solution to getting started with product development. It is a comprehensive guide for developers, which helps them quickly achieve the conversion of their ideas into products. ESP-Jumpstart is based on Espressif’s IoT Development Framework, ESP-IDF, and discusses all the necessary steps and best practices for product development in a simple, well-structured and user-friendly way.\nOn a similar note, our German-speaking friends and supporters will be pleased to know that the Franzis\nMaker Kit for ESP32 has just been released. This maker kit contains everything you need to get started with microcontroller technology using our flagship SoC, ESP32. An ESP32 development board along with all the necessary components are included in this kit, so you can start implementing your own applications right away!\nOther topics you can read about in this month’s newsletter include:\nThe launching of ESP Apple HomeKit ADK, with which makers can now prototype non-commercial smart-home accessories with the open-source ESP Apple HomeKit Accessory Development Kit (ADK). The release of ESP Module, a powerful all-in-one device for microcontroller-based projects, which has been made by the US American start-up, Edge Devices. ESP_8_BIT, a new gadget with which you can enjoy Atari 8-bit computers, NES and SMS game consoles on your TV, with only an ESP32 and a sense of nostalgia. Hope you enjoy reading this month’s newsletter. Keep sending us your messages and requests on Facebook, Twitter, LinkedIn, Instagram and YouTube. We try to respond to all of your messages as quickly as possible!\nBest wishes,John Lee.Senior Customer Support Officer\nESP Apple HomeKit ADK Launched # HomeKit is a framework developed by Apple for controlling and communicating with connected accessories in a userʼs smart home, where iOS devices are being operated. The ESP Apple HomeKit ADK is a port of Apple’s open-source HomeKit ADK, which can be used on ESP32 and ESP32-S2 for a number of AIoT projects.\nKeep Reading\nPowerful ESP Module by Edge Devices # The US American start-up, Edge Devices, has chosen Espressif’s ESP32-DevKitC-D32 for its new “ESP Module”, an all-in-one device for microcontroller-based projects. ESP32-DevKitC-D32 is actually based on the ESP32-WROOM-32D module. This way, makers who prefer a lightweight architecture can enjoy all the benefits of the ESP32 technology, which lies at the heart of the ESP Module.\nKeep Reading\nESP_8_BIT: Serving Some ESP32-based Nostalgia # When all you need is a little escape from today’s disconcerting reality, ESP_8_BIT is the gadget you should turn to! With Rossum’s new creation, you can enjoy Atari 8-bit computers, Nintendo Entertainment System (NES) and Sega Master System (SMS) game consoles on your television with nothing more than an ESP32 and a sense of nostalgia.\nKeep Reading\nOriginally published at https://mailchi.mp.\n","date":"28 May 2020","externalUrl":null,"permalink":"/blog/may-2020/","section":"Blog","summary":"","title":"May 2020","type":"blog"},{"content":"","date":"26 May 2020","externalUrl":null,"permalink":"/tags/cloud-architecture/","section":"Tags","summary":"","title":"Cloud Architecture","type":"tags"},{"content":" Recently, we launched ESP RainMaker, that provides a way for developers to build devices with readymade cloud, phone apps and voice assistant support. In this context, designing and implementing an IoT cloud service was a significant part of the efforts and we wanted to ensure that it met some of the key criteria that we had laid out.\nSecurity — We gave utmost importance to security to ensure that device and the user data is secure, and unintentional access to the data is prevented. The authentication, authorization and access control were to be supported using standard security protocols.\nTime-to-market — It was important for us to spend time wisely on innovating on the features that we like to be part of our solution. So we were ready to use a suitable platform instead of reinventing the wheel.\nScalability — Scalability was an important consideration for us to ensure that the platform was well suited for large number of devices and varied workloads from different device classes that developers will build.\nCost — Given that the number of devices and their workload is varied, the choice of our architecture and our implementation will provide the service at an optimised cost structure.\nIn addition to these measurable key criteria, we wanted to follow an important design principle for ESP RainMaker — to be independent of the application protocol between the devices and other services by supporting Runtime Reconfiguration Pattern . We wanted to ensure that the cloud architecture that we select can provide good framework for this type of design.\nRuntime Reconfiguration Pattern — A static device configuration in the cloud has up till now been the norm for most applications. With ESP RainMaker, devices could be dynamically updated with the latest firmware and their cloud bindings could be reconfigured. This opens the possibility to continue to evolve (a) the devices, to provide new services after they are deployed and, (b) other services, to consume the device data and interact with the devices.\nDefining these criteria helped us to evaluate available architectures or paradigms and select the one that is a closest-fit for our criteria.\nThe first three architectures required not only building the application, but also to maintain the infrastructure at various level. While elastic containers provide some level of scalability, it too required building and maintaining a distributed system with its own nuances. That’s where the Serverless deployment stood out and it was certainly worth a consideration.\nWhat is Serverless? # Serverless does not mean that there is no server. It hides the management of the hardware and software infrastructure and provides usable services for the application. The application is also designed to not run on a specific server instance, but is event driven and can make use of the available services.\nFaaS — Function As A Service # In addition to managed services, the Serverless architecture offers “FaaS (Function-as-a-Service)” runtime that allows developers to write code snippets that can work on the data and interact with available services. Developers can use their familiar programming languages (such as Python, node.js and Go) with SDKs to interact with services. FaaS is also charged based on number of executions and time and memory consumption of the runtime.\nThe cloud infrastructure provides a “Rule Engine” that facilitates the orchestration of the data flow through services. The FaaS runtime can be set to trigger based on various conditions in the system. Together Rule Engine and FaaS runtime can be used to build the business logic of the application.\nThe typical available Serverless services that are meaningful in the context of device connectivity include an MQTT broker, SQL and no-SQL database services, a binary blob/object storage, user management service, web API gateway service, message queuing service and stream analytics service amongst the few other Serverless services.\nWhile ESP RainMaker is based on AWS Serverless platform, most of the other leading cloud service providers including Google Cloud Platform, Microsoft Azure Cloud, Tencent Cloud and Alibaba Cloud provide Serverless platform offering that is more or less similar. ESP-RainMaker could also be deployed on these platforms.\nESP RainMaker and Serverless — Our Experience # Let’s first evaluate how Serverless fares for the parameters that we have considered to be important.\nSecurity — The Serverless architecture provides unified user management and RBAC (role-based access control) through security policies across the services. These roles and policies can be associated with multiple services at a very fine granularity. This is very useful as when the device data enters the system, when a user operation is performed, the context flows along with data across the services ensuring appropriate permission control at each stage. Devices get to choose a strong authentication with the IoT cloud service (e.g. TLS based mutual authentication). There are also some security specific services available for common requirements such as a web API gateway firewall that would protect from typical DoS attacks. With this infrastructure, security becomes an integral part of the design of the application and not an afterthought.\nTime-to-Market — This is where Serverless provides a very strong advantage. The services’ availability, scalability and reliability is guaranteed and constraints are documented clearly. This provides a distributed platform to the application where the complexity of the distributed system is abstracted from the application. The Serverless application design pattern is however non-orthodox where the application is broken into individual segments responding to various system events and inter-service orchestration is a part of the application. However this, in-fact, leads to an easier to develop and maintain architecture compared to the monolithic architecture. There is no traditional dev-ops involved. This all greatly reduces time-to-market and makes the maintenance of the system easier.\nScalability — With the distributed nature of the services abstracted out and the availability of configuration to improve service response, the application achieves inherent scalability upto a large extent. However it’s also worthwhile to emphasise here that use of the Serverless architecture does not by default guarantee scalability. The data and workflows have to be defined considering the known limitations of individual services.\nCost — While the cost of services vary from cloud vendor to cloud vendor, the basic device connectivity, messaging service pricing is quite low in general. However here too, choice of the architecture and the services used, can impact the actual cost of cloud usage under the same workload. It requires a continuous analysis and optimisation as a part of development process. With ESP RainMaker running on AWS Serverless infrastructure, we can maintain the cost of an always-connected device with a few messages per day to be within a few cents per device per year. While there are greater savings for indirect cost (such as engineering and maintenance), even direct cost is quite attractive and linear scaling as expected beating our initial apprehension.\nRuntime Reconfiguration Pattern — The Serverless framework with its availability of messaging, compute and storage services provided a good platform to design ESP RainMaker to meet its Runtime Reconfiguration requirement. In the Runtime Reconfiguration requirement, the devices and other services can use the cloud as a conduit: the devices can dynamically self describe their characteristics and the services can render themselves with the available data in an efficient way.\nServerless has proven to be a great platform for us for ESP RainMaker to deliver a feature-rich yet cost-effective (just like our hardware :-) ) device cloud platform. This gives us an ample opportunity to innovate further in terms of features that will make developers’ life easy for building and maintaining connected devices.\nHowever this is also an important learning that Serverless is not a silver bullet. The application needs to be designed carefully, security configuration needs to be well thought through and service features need to be chosen to ensure low cost of operation. Also, application development and debugging is quite different than traditional model. But still the advantages greatly outweigh the efforts.\nESP-Rainmaker is designed for Makers to reduce the complexity of connecting their devices to the web and to provide a ready-to-use phone apps, so that Makers can focus on building their devices instead of reinventing the wheel. We would love to see your devices connecting to ESP RainMaker.\nLet’s Make the world better!\n","date":"26 May 2020","externalUrl":null,"permalink":"/blog/esp-rainmaker-and-serverless/","section":"Blog","summary":"","title":"ESP RainMaker and Serverless","type":"blog"},{"content":"","date":"26 May 2020","externalUrl":null,"permalink":"/tags/serverless/","section":"Tags","summary":"","title":"Serverless","type":"tags"},{"content":" Any Internet of Things (IoT) system is incomplete if it does not have a facility of upgrading the firmware remotely (also called Over The Air firmware upgrades). The ESP IDF offers a very simple interface for OTA upgrade using a secure HTTP connection. However, the following things still remain unaddressed, as they are out of scope of the firmware development framework and require some infrastructural support:\nSetting up the infrastructure could be a challenge, especially for Makers. The recently launched ESP RainMaker just added a facility to address all these concerns.\nIntroducing Services # Similar to the concept of “devices”, a new concept of “services” has been introduced. They are very similar to devices but are meant for features like OTA, diagnostics, system information, etc. which do not really fall in the category of any device.\nThe OTA Service # The OTA Service is the first standard service added. It has 3 string parameters: URL, Status and Info, which are accessible in the same way as any other device parameters. Applications can send the firmware upgrade url by writing to the URL parameter and then monitor the status by reading the Status and Info. The firmware side code has been abstracted out completely and applications need to call this single API:\nCheck the ESP RainMaker Switch example for sample usage .\nThis takes care of points 2 and 3 above, but point 1 could still be a pain point. To make it even easier, ESP RainMaker now also offers an image hosting service which makers can use for temporary storage of their firmware images. This facility is exposed via the ESP RainMaker CLI.\nUsing OTA Upgrades with RainMaker CLI # To use it, set up the CLI as per the instructions here. Once done, ensure that your node is linked to your account and is also online. Then, follow these steps:\n$ cd /path/to/esp-rainmaker/cli $ ./rainmaker.py login # Use the same credentials used in phone app for setting up the node $ ./rainmaker.py getnodes # Just to verify that you see the node that you want to upgrade $ ./rainmaker.py otaupgrade \u0026lt;node_id\u0026gt; \u0026lt;path_to_ota_fw_image\u0026gt; The otaupgrade command uploads the firmware image to the RainMaker server and gets back a temporary URL in return. It then sends this URL to the node using the OTA URL parameter mentioned above and then checks for the status using the Status and Info parameters. It will print the progress as below:\n$ ./rainmaker.py otaupgrade 7CDFA1XXXXXX ../examples/switch/switch-2.0.bin Uploading OTA Firmware Image... Checking esp.service.ota in node config... Setting the OTA URL parameter... OTA Upgrade Started. This may take time. Getting OTA Status... [19:49:50] in-progress : Downloading Firmware Image [19:49:58] in-progress : Downloading Firmware Image [19:50:07] in-progress : Downloading Firmware Image [19:50:16] in-progress : Downloading Firmware Image [19:50:25] in-progress : Downloading Firmware Image [19:50:34] in-progress : Downloading Firmware Image [19:50:43] success : OTA Upgrade finished successfully Once the OTA Upgrade is successful, the node reboots into the new firmware and you are done. Additional configuration and technical details can be found here.\nSo, get going with ESP RainMaker. Let your devices be anywhere, in the garage, in the water tank, out on the lawn, in the home or the office; you can continue playing around with the firmware by using this new OTA service.\n","date":"24 May 2020","externalUrl":null,"permalink":"/blog/ota-firmware-upgrades-with-esp-rainmaker/","section":"Blog","summary":"","title":"OTA Firmware Upgrades with ESP RainMaker","type":"blog"},{"content":"Hi everyone,\nEspressif is known for its keen sense of corporate social responsibility. We have long supported low-power, green technologies, while we have also based our entire business model on the idea of democratizing technology with open-source software .\nAt present, we are deeply concerned about climate change, which has been the result of human actions in recent decades. Hoping to create more public awareness of this crisis, we are launching a wildlife protection program which draws on the environmental insight brought about by The IUCN Red List of Threatened Species™. This is considered the most authoritative guide for evaluating biodiversity and the extinction risk of thousands of species.\nFrom now on, some of Espressif’s new development boards will be named after endangered animals. Some revenue from these development boards will be donated to the IUCN. We hope that our contribution will help the IUCN people to protect a greater number of threatened species. So far we have launched:\nESP32-Vaquita-DSPG, an Alexa built-in solution named after Vaquita, the world’s rarest marine mammal on the verge of extinction. ESP32-S2-Saola-1, a general-purpose development board named after Saola, the so-called Asian unicorn, which is a critically endangered mammal. ESP32-S2-Kaluga-1, a new multimedia development board, named after Kaluga, which is a critically endangered sturgeon inhabiting the Amur River in the Russian Far East. Other topics you can read about in this month’s newsletter include:\nESP RainMaker, Espressif’s end-to-end platform which enables makers realize their IoT ideas faster, with Espressif’s ESP32-S2 SoC, and without the hassle of managing the infrastructure involved. ESP32-Korvo, Espressif’s new AI development board, which features a multi-microphone array that enables it to achieve high performance, spoken-command recognition and far-field voice wake-up. The release of Espressif’s ESP8266 NonOS SDK, v3.0.3, which contains the latest bug fixes and updates. M5Stack ATOM, the smallest ESP32-based development board on the market, which is mainly designed for portable embedded systems and IoT development projects. Hope you enjoy reading this month’s newsletter. Keep sending us your messages and requests on Facebook, Twitter, LinkedIn, Instagram and YouTube. We try to respond to all of your messages as quickly as possible!\nBest wishes,John Lee.Senior Customer Support Officer\nESP RainMaker Released # Last week, Espressif announced the release of ESP RainMaker, which has been designed to empower firmware developers with more freedom, creativity and potential than ever before. You can now build connected devices really quickly. With ESP32-S2 and our ESP-IDF open-source SDK you can avoid all the hassle of managing the infrastructure involved in building connected devices.\nKeep Reading\nESP32-Korvo Launched # ESP32-Korvo is an artificial-intelligence development board based on ESP32 and ESP-Skainet, Espressif’s speech recognition SDK. ESP32-Korvo features two boards connected with an FPC cable, as well as a multi-microphone array which is suitable for far-field speech recognition applications with a low-power consumption.\nKeep Reading\nESP8266 NonOS SDK V3.0.3 Released # Espressif continuously optimizes and updates its SDKs to meet its customers’ needs. That’s why Espressif has just released ESP8266 NonOS SDK v3.0.3 . Customers using the ESP8266 NonOS SDK are advised to update their systems to the latest version, v3.0.3.\nKeep Reading\nM5Stack ATOM: An ESP32-based Portable Development Toolkit # The ESP32-based M5Stack ATOM is the smallest development board on the market, measuring only 24×24mm. Designed for portable embedded systems and IoT development projects, M5Stack ATOM is truly cost-effective not just because of its small size, but also because it has no integrated battery.\nKeep Reading\n","date":"4 May 2020","externalUrl":null,"permalink":"/blog/april-2020/","section":"Blog","summary":"","title":"April 2020","type":"blog"},{"content":"Recently we released ESP RainMaker that easily allows makers to build connected devices. Beyond the part of connecting with the phone applications, the way the applications are structured makes it much easier to build an easy to distribute firmware. Many of these features are the guidelines that are part of the ESP-Jumpstart framework. Let’s look at some of these features.\nWi-Fi Network Configuration # In many projects, the Wi-Fi network’s credentials (SSID/Password) are embedded within the code itself. This makes it harder to make the project easily usable by others.\nRainMaker applications utilise the Wi-Fi Provisioning firmware component, that lets users configure the Wi-Fi SSID/passphrase into the device securely over the SoftAP/BLE interface. This configuration can easily be done by users with iOS/Android phone apps. The phone applications for both, iOS and Android, with full source-code, are available for easy customisation and integration.\nQR Code — Security with Proof of Possession # The Wi-Fi provisioning IDF component includes an optional field called pop (proof of possession). The proof-of-possession field is a per-device unique secret, that only a person with physical possession of the device has access to. The Wi-Fi provisioning step validates that the user has access to this secret before initiating the provisioning. This ensures that when the device is being provisioned, your neighbour can’t just configure it to connect to their own Wi-Fi network (since they don’t have access to the proof of possession).\nMany makers hesitated from using this, since it increases a step in the end-user’s device provisioning user-experience: the users had to look-up and enter this proof of possession secret into the phone-apps.\nThe RainMaker agent makes it much easier to include the proof of possession handling by embedding it in the QR code. Each device has a unique QR code, which is displayed on the device console, or can be easily printed on a sheet of paper.\nReset to Factory # This is a common feature requirement, so users can erase the earlier configuration and re-configure the device with updated settings. In RainMaker applications, all the configuration information, like the Wi-Fi credentials, is stored in an NVS partition.\nImplemented like this, the reset-to-factory is nothing but a simple nvs-erase operation.\nManufacturing Partition # Many devices want to have some per-device unique information that should be configured at the time of building the device. This may include the unique key that the device’s use to authenticate with the RainMaker service, or any other information like UUID, and other secrets. We don’t want this information to be erased with a *Reset to Factory *action.\nThe RainMaker infrastructure uses a “manufacturing” partition for storing such unique information. This ensures that,\nthis unique information isn’t erased across a reset-to-factory event the device firmware is common across all devices, since all unique information is partitioned out IDF already contains the mass_mfg utility that lets you build these mfg partition easily and in large numbers Over the Air Firmware Upgrades # The default partitioning mechanism for RainMaker applications includes the active-passive firmware partition support from IDF. So currently, you can easily create a RainMaker parameter (of type string) that accepts a URL as the value. And then once you get data on this parameter, you can initiate upgrade from that link using the esp_https_ota component.\nRemote Sync # The RainMaker agent internally synchronises the state of the device with the RainMaker service over MQTT/TLS.\nThe agent manages the initial communication required to associate the end-user and the device. The other part of this implementation is implemented in the phone applications.\nAdditionally the agent syncs the device state. A concept of “device parameters” is used to identify the parameters of the device (power, brightness, speed etc.). Any local changes to these parameters are published to the RainMaker service, while any remote updates are delivered to the application using a callback.\nThose were some of the highlights of the considerations that have been taken on the RainMaker applications so far. If you have a request to add as a feature, or believe we missed any other considerations, please let us know in the comments below.\n","date":"1 May 2020","externalUrl":null,"permalink":"/blog/rainmaker-projects-firmware-considerations/","section":"Blog","summary":"","title":"RainMaker Projects: Firmware Considerations","type":"blog"},{"content":" ESP-IDF Eclipse Plugin brings developers an easy-to-use Eclipse-based development environment for developing ESP32 based IoT applications.\nIt provides better tooling capabilities, which simplifies and enhances standard Eclipse CDT for developing and debugging ESP32 IoT applications. It offers advanced editing, compiling, flashing and debugging features with the addition of Installing the tools, SDK configuration and CMake editors. The plug-in runs on Windows, macOS and GNU/Linux.\nIt supports ESP-IDF CMake based projects (4.x and above)\nCurrent Status # We have recently released 1.0.1 to the public. Check here\nGetting Started # The IDF Eclipse Plugin is available from the Eclipse Marketplace. To get started, users need to download the Eclipse CDT from the Eclipse downloads page. The Eclipse CDT can be installed with the new Eclipse installer, or the CDT package can be downloaded directly. Once that’s set up, the Marketplace client can be used to search for and install the ESP-IDF Eclipse Plugin.\nYou can also install the IDF Eclipse Plugin into the existing Eclipse CDT using the plugin update site URL https://dl.espressif.com/dl/idf-eclipse-plugin/updates/latest/\nYou can find the detailed instructions here\nEspressif believes in the open-source approach and we have made code open for the plugin as well https://github.com/espressif/idf-eclipse-plugin. We really welcome any kind of contribution that one can provide.\nKey Features # Eclipse CDT with IDF Eclipse Plugin supports end-to-end workflow to develop ESP32 IoT applications. Here are some of the features.\nIDF Tools installation: It installs xtensa-esp32-elf, xtensa-esp32s2-elf, esp32ulp-elf, esp32s2ulp-elf, openocd-esp32, CMake and Ninja build tools Auto-configuration of Eclipse CDT build environment variables such as PATH, IDF_PATH, OPENOCD_SCRIPTS and IDF_PYTHON_ENV_PATH Auto-configuration of Core build toolchains and CMake toolchain which is used in resolved headers and indexing New ESP-IDF project wizard and templates to get started Compiling and Flashing an application to the board Viewing Serial monitor output JTAG GDB Hardware debugging OpenOCD debugging using Eclipse GNU MCU Plugin Predefined debug launch configuration files to quickly get started with debugging Importing an existing IDF project and converting to the Eclipse-based CMake project CMake Editor Plug-in is integrated with IDF plugins for editing CMake files such as CMakeLists.txt Easy to use Eclipse-based GUI for SDK Configuration Editor which will simulate the behaviour of idf.py menuconfig Customized flash target — supports esp32 and esp32s2 chips Eclipse CDT Workbench with IDF Eclipse Plugin # Components Based Design # Demo # Please check our demo presented in EclipseCon 2019. This will also give an overview of ESP-IDF, build system and a quick demo on the plugin.\nResources # ESP-IDF Eclipse Plugin https://github.com/espressif/idf-eclipse-plugin\nESP-IDF https://github.com/espressif/esp-idf/\nESP-IDF documentation https://docs.espressif.com/projects/esp-idf/en/latest/\nESP32 Forum for IDE’s https://www.esp32.com/viewforum.php?f=40\n","date":"17 April 2020","externalUrl":null,"permalink":"/blog/eclipse-plugin-for-esp-idf/","section":"Blog","summary":"","title":"Eclipse Plugin for ESP-IDF","type":"blog"},{"content":"","date":"17 April 2020","externalUrl":null,"permalink":"/tags/plugins/","section":"Tags","summary":"","title":"Plugins","type":"tags"},{"content":"","date":"15 April 2020","externalUrl":null,"permalink":"/tags/announcements/","section":"Tags","summary":"","title":"Announcements","type":"tags"},{"content":" Today we announced ESP RainMaker. This is another step forward for Espressif to enable makers to build connected devices and access them through phone apps, 3rd party services or voice assistants, quickly, without having to manage the infrastructure.\nThe ESP RainMaker is a collection of device-agent SDK, a transparent cloud application and iOS/Android phone apps. This lets developers write the firmware and instantaneously interact with it through the phone-apps, or through other services.\nDeveloper Workflow # We are excited about this launch as it gives more power to firmware developers. And I want to talk about this a bit.\nAs a firmware developer working with RainMaker this is how the workflow looks like:\nYou build applications using the goodness of Espressif’s ESP-IDF open-source SDK and the RainMaker Agent. You choose to expose any parameters of your device in the application’s firmware that you wish to control externally. The RainMaker agent syncs these attributes with the RainMaker cloud. The RainMaker cloud transparently makes the device parameters available to the phone applications and other services. This does not require you to write any code in the cloud. The cloud application is built with AWS Serverless services. The RainMaker phone applications then redraw themselves to present the parameters of the devices to the user. Reading or changing these attributes is as easy as toggling a button on the phone. The availability of a Python client library lets you access the same parameters through a command-line or through python programs, that you could then link with any other services. And all of this, without any configuration of the cloud interfaces, or phone apps. All you can continue to focus on is the device firmware.\nExamples # Let’s quickly look at some examples that will make things clearer.\nGPIO # The simplest example is GPIOs. Let’s say you wish to expose some GPIO controls from your device. Your RainMaker code for this will look like:\n/* Create a device and add the relevant parameters to it */ esp_rmaker_create_device(\u0026#34;ESP32-S2-Saola-1\u0026#34;, NULL, gpio_callback, NULL); esp_rmaker_device_add_param(\u0026#34;ESP32-S2-Saola-1\u0026#34;, \u0026#34;Red\u0026#34;, esp_rmaker_bool(false), PROP_FLAG_READ | PROP_FLAG_WRITE); esp_rmaker_param_add_ui_type(\u0026#34;ESP32-S2-Saola-1\u0026#34;, \u0026#34;Red\u0026#34;, ESP_RMAKER_UI_TOGGLE); esp_rmaker_device_add_param(\u0026#34;ESP32-S2-Saola-1\u0026#34;, \u0026#34;Green\u0026#34;, esp_rmaker_bool(false), PROP_FLAG_READ | PROP_FLAG_WRITE); esp_rmaker_param_add_ui_type(\u0026#34;ESP32-S2-Saola-1\u0026#34;, \u0026#34;Green\u0026#34;, ESP_RMAKER_UI_TOGGLE); esp_rmaker_device_add_param(\u0026#34;ESP32-S2-Saola-1\u0026#34;, \u0026#34;Blue\u0026#34;, esp_rmaker_bool(false), PROP_FLAG_READ | PROP_FLAG_WRITE); esp_rmaker_param_add_ui_type(\u0026#34;ESP32-S2-Saola-1\u0026#34;, \u0026#34;Blue\u0026#34;, ESP_RMAKER_UI_TOGGLE); Basically,\nesp_rmaker_create_device: You define a name for a device and a callback (in this case* gpio_callback*) that will handle the requests when the parameter is modified externally. esp_rmaker_device_add_param: You add parameters (or attributes) of the device that you wish to expose. Here we add 3 GPIOs (Red, Green, Blue). We mention that this parameter is of type bool. We can create parameters of other data types as well. esp_rmaker_param_add_ui_type: Each parameter also includes a UI type that the phone application should use for displaying that parameter. In this case we mention that a UI type “toggle” element should be used. Correspondingly the phone apps will show the following while accessing the device:\nLight # You can also use other parameter types, for example let’s look at the light example.\n/* Create a device and add the relevant parameters to it */ esp_rmaker_create_lightbulb_device(\u0026#34;Light\u0026#34;, common_callback, NULL, DEFAULT_POWER); esp_rmaker_device_add_brightness_param(\u0026#34;Light\u0026#34;, \u0026#34;brightness\u0026#34;, DEFAULT_BRIGHTNESS); esp_rmaker_device_add_hue_param(\u0026#34;Light\u0026#34;, \u0026#34;hue\u0026#34;, DEFAULT_HUE); esp_rmaker_device_add_saturation_param(\u0026#34;Light\u0026#34;, \u0026#34;saturation\u0026#34;, DEFAULT_SATURATION); In the GPIOs example earlier, we had used a “raw” datatype as bool. The RainMaker agent also provides some pre-defined higher level datatypes (standard types). This example uses these higher level APIs for creating the parameters. Note that we could also have written this code using the raw datatype instead, but this is a short-hand utility API.\nA list of these standard types is available here: https://rainmaker.espressif.com/docs/standard-types.html. It also has the corresponding Standard Types C API that is used in the code above. We will continue to update this list of standard types as we go along.\nThe phone apps then redraw themselves to match what is written in the firmware:\nBridges # You can also easily export multiple “logical devices” within the same ESP32 node. This makes it convenient in cases where your ESP32 acts as a bridge and allows the RainMaker phone apps to interact with these bridged devices.\nMore Examples # You can find many other samples in the esp-rainmaker/examples/ directory of the ESP RainMaker project.\nSpecifications # While we make this infrastructure available, we want to be as transparent as possible about the architecture and the data exchange that flows through the ESP RainMaker infrastructure.\nThe ESP32-S2/ESP32 to RainMaker cloud communication details are captured here: https://rainmaker.espressif.com/docs/node-cloud-comm.html The RainMaker agent that implements (in the C language) the above protocol is available at: https://github.com/espressif/esp-rainmaker The REST APIs exposed by the RainMaker cloud are captured in this swagger documentation: https://swaggerapis.rainmaker.espressif.com. These APIs are used by the phone apps and the Python library to interact with the RainMaker cloud. The Python CLI that uses these APIs is available here: https://github.com/espressif/esp-rainmaker-cli Feel free to reach out to us if you have any feedback, requests or suggestions for ESP RainMaker.\nGet started using the ESP RainMaker # Support for ESP-RainMaker is currently enabled for ESP32-S2 SoCs. If you have an ESP32-S2 based development board with you, you can get started with using ESP RainMaker from here: https://rainmaker.espressif.com/docs/get-started.html\nYou can also head over to the ESP RainMaker GitHub repository.\nWe are excited about releasing this, and we hope you find it helpful. We really look forward to what you will do!\n","date":"15 April 2020","externalUrl":null,"permalink":"/blog/introducing-esp-rainmaker/","section":"Blog","summary":"","title":"Introducing ESP RainMaker","type":"blog"},{"content":"Hi everyone,\nAs the COVID-19 crisis spreads rapidly all around the world our thoughts are with those who keep fighting the global pandemic. Now that the epicenter of infections has moved westward, we want to send a message of hope from China to all our partners, our customers and our international community of supporters. Things will get better!\nIn China, life is gradually getting back to normal. Further to what Espressif’s CEO and Founder, Teo Swee Ann , said in a recent blog post, we are now happy to confirm that Espressif in China functions normally and at full capacity. But we have more reasons to be excited about. As we mentioned last month, ESP32-S2 is in mass production now . We have been working for this moment for many years, as we wanted to offer a Wi-Fi-enabled MCU targeting connected, low-cost, low-power, interactive sensors with numerous advantageous features.\nAdditionally, we are particularly moved to witness members of the international maker community using their creativity and technical skills to respond to the COVID-19 crisis . Many of the solutions they suggest are based on our SoCs and this makes us even happier! Hence, we decided to dedicate most of this month’s newsletter to presenting their solutions.\nSo, the topics you can read about in this month’s newsletter include:\nEspressif’s new ESP32-Vaquita-DSPG development kit and its accompanying SDK, both of which support AVS integration with the AWS IoT Core; An ESP8266-based, low-cost, contactless, do-it-yourself, infrared thermometer which can contribute to the fight against the spread of the novel coronavirus; An ESP8266-based, distance monitor that can help you properly maintain the official guidelines for social distancing during the COVID-19 crisis; ESP8266-based gadgets that can track the development of COVID-19 in different countries; In Italy, Gabriele Merlonghi, a maker and Espressif supporter, turned to the power of ESP8266, in order to fuel his creativity and uplift his young son’s spirits during the global pandemic. Hope you enjoy reading this month’s newsletter. Keep sending us your messages and requests on Facebook, Twitter, LinkedIn, Instagram and YouTube. We try to respond to all of your messages as quickly as possible!\nBest wishes,John Lee.Senior Customer Support Officer\nESP32-Vaquita-DSPG Development Kit and SDK Support AVS Integration with AWS IoT Core # Espressif announces the availability of ESP32-Vaquita-DSPG and its accompanying SDK, both of which support AVS integration with the AWS IoT Core. Espressif’s new ESP32-Vaquita-DSPG development kit provides a turnkey solution for easily creating Alexa built-in connected devices that provide voice enablement and AWS-IoT cloud connectivity out of the box.\nKeep Reading\nESP8266-based Contactless Thermometer # An ESP8266-based, low-cost, contactless, do-it-yourself, infrared thermometer contributes to the fight against the spread of the novel coronavirus that has been haunting the world for the past three months. An Indian engineer, Abhijit Mukherjee, has come up with this gadget.\nKeep Reading\nESP8266-based Wearable Corona Distance Monitor # Indian engineer Sahil Rastogi and his Delhi-based team, who call themselves Random Stuff We Make!, have responded to the COVID-19 pandemic by creating a wearable distance-monitoring gadget that is based on Espressif’s ESP8266.\nKeep Reading\nPandemic Development Monitors Based on ESP8266 # The rapid development of COVID-19 into a full-blown global pandemic has generated the need for regular updates regarding the status of this crisis. People want to be regularly informed about the number of infections, deaths and recoveries in their countries. The maker community has responded to this need by creating a number of monitors for this purpose. Here are a few based on ESP8266.\nKeep Reading\nESPminecraft Lamp # In Italy, Gabriele Merlonghi, a maker and Espressif supporter, turned to the power of ESP8266 in order to fuel his creativity and uplift his young son’s spirits during the global pandemic! Here’s how he did this:\nKeep Reading\nOriginally published at https://mailchi.mp.\n","date":"6 April 2020","externalUrl":null,"permalink":"/blog/march-2020/","section":"Blog","summary":"","title":"March 2020","type":"blog"},{"content":" Why Is ESP32-S2 Significant? # We launched the ESP32-S2 chip and we are excited to announce that it is in mass production now. Personally, I think it’s a big thing; it’s something we have been working for, for many years: a Wi-Fi enabled MCU targeting connected low-cost low-power interactive sensors with these features:\nAll these features add up to be a self-contained small form factor connected interactive secure computing and sensor device with a small LCD, such as a thermostat or a smart light switch.\nRadio # Transmit power on the client device is central to the quality of the wireless connection. Most routers have large linear amplifiers, while IOT client devices have more limitations on output power range.\nESP32-S2 transmits at the maximum output power level while meeting the stringent spectral mask requirements.\nESP32-S2 also has leading receiver sensitivity of -97 dBm. With the combination receive sensitivity and output power, the customer is guaranteed the best possible user experience for Wi-Fi connectivity.\nImportantly ESP32-S2 maintains this performance from -40°C to 105°C facilitating the applications such as light bulbs and industrial sensors.\nGPIOs (Lots Of It) # ESP32-S2 has 43 programmable GPIOs with all the standard peripheral support including USB-OTG. These standard peripheral enable different sensors and actuators interfacing. 14 IO pins can be configured for capacitive touch sense. This paired with available LCD interface can enable HMI interface for your devices. Availability of audio interfaces and sufficient compute power and memory expandability allows building streaming media solutions.\nTouch Sensors and HMI # Based on ESP32-S2, the highly-integrated kit provides an easy-to-use platform to develop HMI solutions with touch screen displays for use across a wide range of industrial and building automation, simplistic designs with touch pad and basic LED indicator screens or a more complex HMI systems with touchscreen and other features. ESP32-S2 touch sensors are able to withstand harsh environments and are resistant to dust, water, moisture. We can envision these type of devices used to improve the communication among various types of equipment throughout the facility benefiting in operation, safety and productivity.\nSecurity # With tiny MCU based devices becoming frontline soldiers of the IOT revolution, their security becomes an important aspect. The target attack surface is wide given the fact that these devices become first class citizens of the internet using standard communication protocols. ESP32-S2 supports secure boot and flash encryption with standard cryptographic protocols. RSA based secure boot ensures that only trusted software executes on the chip. AES-XTS based flash encryption ensures that the sensitive configuration data and application remain encrypted on the flash. In addition the cryptographic accelerators provide TLS connectivity with cloud servers with strongest cipher suites without any performance impact. It also comes with a high tolerance to physical fault injection attacks. You can find more information about these security features here.\nESP-IDF SDK # ESP-IDF is Espressif’s open source RTOS based SDK that is already being used in millions of deployed products. The same SDK continues to supports ESP32-S2. Availability of commonly required software components and rich tooling makes it easy to develop and maintain your application firmware. It implements easy to use Wi-Fi network provisioning protocols, cloud support and over the air (OTA) software upgrades. ESP-Jumpstart running on ESP32-S2 offers a step-by-step production quality application reference for the developers. ESP-Rainmaker provides a quick way to realise production quality cloud connected devices.\nCamera Support # ESP32-S2 provides an 8/16 bit DVP camera interface that supports a maximum clock frequency of 40 MHz. Also, the DMA bandwidth is optimized for transferring high resolution images.\nWe imagine that ESP32-S2 can be widely used in various IoT applications. It is suitable for variety of smart-home devices, industrial wireless control, wireless monitoring, wireless QR code scanners, wireless positioning systems and many other IoT applications. As always, we remain open to your valuable feedback.\nAvailable Documentation # ESP32-S2 Datasheet ESP32-S2 Technical Reference Manual ","date":"10 March 2020","externalUrl":null,"permalink":"/blog/esp32-s2-is-here/","section":"Blog","summary":"","title":"ESP32-S2 Is Here!","type":"blog"},{"content":"The COVID-19 situation is developing rapidly, and the CEO of Espressif, Teo Swee Ann, gives a short update of the situation and some considerations of the future.\nThe COVID-19 situation continues to unfold fast and globally. It has reached Europe, Japan, South Korea, and the United States, and on the minds of many is whether COVID-19’s advance will be arrested by warmer weather or if a cure or vaccine will be found.\nUpdate # In Espressif, the COVID-19 situation has imposed upon us many changes, such as how we conduct meetings and interact. But we have otherwise been operating normally for close to three weeks, since the Chinese New Year break.\nHere are some of the statistics: 97% of our staff in China are now back to work, of which about 23% are working from home. 2.5% are at home under quarantine, most of whom will return this coming week.\nMaking Chips # Two weeks ago, we had a test chip back from fabrication, and our engineers have, since then, been busy with the measurements.This chip is one of those “high risk test chips” where we put in our latest ideas and see what works and what doesn’t. As usual, the initial results are a mixed bag: some things work and that’s great; some things don’t work and that’s even better — it tells us that there is perhaps a lesson to be learnt here.\nIn the last couple of days, the measurement results of the chip have given us more hope as we gradually figure out how we need to adjust our settings in order to coax the best performance from it. The result is a net improvement in performance and lowered power consumption under limited conditions.\nMoving Forward One Step At A Time # Limited conditions? Yes, it’s about first getting to the higher ground so that we could build upon it and generalize and build a platform. I am glad that I still feel the joy of achieving the gain in performance in the chip, because I have had been distracted by the COVID-19 issues. I still have a daily update from my staff about the figures from various countries, the latest news about the virus and spend time reading the statistics.\nWhile it is possible that the virus will be with us for a relatively long period of time on the order of a couple of year or more, the best outcome would be a winding down of infections starting from April, as the weather gets warmer. But in the short term, given that it’s another 30 days to get to warmer weathers, COVID-19 is highly infectious and many parts of the world are not taking drastic measures, if COVID-19 spreads to 5% of the world’s population outside of China with a mortality rate of 1%, then we are talking about ~2.5 million deaths over the next 1–2 months.\nStaying on Course # Despite this, we do not see the direct impact of the virus extending beyond 2020, because there is a very high probability of a vaccine or effective medication to be found within this time frame. With researchers all around the world working round the clock to solve the COVID-19 crisis, and the recent advances in microbiology and science, it is probable that new effective solutions will be implemented by the end of the year.\nFor the rest of us, we need to focus on some of the bigger issues on the horizon, and in particular, the global environmental crisis.\nIOT # IOT can be an important technology to combat against the global environmental crisis: global warming, rising sea levels, species extinction, resource depletion, plastics, etc. Espressif continues to contribute to useful knowledge of the world, through our open source projects related to IOT and artificial intelligence. In the process of this, we hope to build collaborations and consensus.\nEspressif remains on our course to better serve our customers and Makers through the democratization of technology, to use open source IOT technology to build cost effective, smart, secure, connected devices, and in the process of it, solve some real world problems.\nThis is my last update on COVID-19. So Long, and Thanks for All the Fish!\nTeo Swee Ann, CEO Espressif Systems\n7 March 2020\n","date":"7 March 2020","externalUrl":null,"permalink":"/blog/a-ceos-experience-during-the-covid-19-crisis-part-iii-looking-ahead/","section":"Blog","summary":"","title":"A CEO’s Experience During the COVID-19 Crisis — Part III : Looking Ahead","type":"blog"},{"content":"","date":"7 March 2020","externalUrl":null,"permalink":"/tags/covid-19/","section":"Tags","summary":"","title":"Covid-19","type":"tags"},{"content":" Hi everyone,\nWe expect that all of you will have heard by now the news about the novel coronavirus epidemic in China and beyond. These are tough times indeed, but luckily, at the time of the outbreak, Espressif had already structured its IT system in such a way that has enabled the vast majority of staff members to work from home. As Espressif’s Founder and CEO, Teo Swee Ann, mentioned in a recent message he posted on our website: “the disruption to our operations will be minimal. Our teams in Europe, India and China continue our work to best serve our customers. ”\nIndeed, everyone at Espressif remains committed to working hard not just to overcome the current crisis, but also to honour our partnerships in China and abroad, and accomplish our goals for the first quarter of 2020, as well as for the rest of the year.\nOn this note, Teo Swee Ann, also mentioned in his recent message: “In 2020, we will be launching four new chips, covering different segments of the market, price points and performance. Our latest chips feature our new radio architecture that has lower power consumption, while maintaining the same -40°C to +125°C performance. The peripherals have been upgraded with highly sensitive capacitive touch IOs. Capacitive touch controls are now a staple of user interfaces, because they are cost efficient; certain functions such as slider controls are better supported with capacitive touch than with analog implementations.”\nTeo Swee Ann also pointed out: “As you can see, we are not just about creating the best Wi-Fi chips, but also about providing our customers with complete and fully customizable solutions that work right out of the box. We also understand that connected product development and maintenance needs to be simplified, without compromising its flexibility. Try our latest ESP32-S2-based ESP-RAINMAKER development boards that enable you to build the a complete cloud-connected product within a couple of hours.”\nYou can read Teo Swee Ann’s entire message here. Other topics you can read about in this month’s newsletter include:\nEspressif’s ESP32 SoC providing a qualified platform for Amazon Common Software for devices; ESP32-S2 SoCs, modules and development boards going into mass production from February 2020 onwards; Espressif’s partnership with Gigabits, a real-world IoT Sandbox for enterprises, developers, and makers looking to explore various IoT use cases and application spaces. Hope you enjoy reading this month’s newsletter. Keep sending us your messages and requests on Facebook, Twitter, LinkedIn, Instagram and YouTube. We try to respond to all of your messages as quickly as possible!\nBest wishes,John Lee.Senior Customer Support Officer\nEspressif’s ESP32 SoC Provides a Qualified Platform for Amazon Common Software for Devices # Espressif’s ESP32 is among the first Systems-on-Chip to support the newly announced Amazon Common Software for Devices (ACS). The combination of ESP32 hardware with ACS provides accelerated, yet flexible, development for connected devices with a seamless integration of Amazon Device SDKs.\nKeep Reading\nESP32-S2 SoC, Modules and Dev Boards Go Into Mass Production # With the ESP32-S2 chips, modules and development boards going into into mass production from February 2020 onwards, the functional advantages of all these products will become readily available to the entire IoT market. In the course of 2020, Espressif will launch more chips in the ESP32-S series and, at the same time, its simplified version, the ESP32-C series, will also be launched.\nKeep Reading\nEspressif Partners with Gigabits # Espressif has just launched a collaboration with Gigabits, a real-world IoT Sandbox for enterprises, developers, and makers looking to explore various IoT use cases. Gigabits is where the physical world meets the digital world. So, combining the Gigabits IoT platform with the power of ESP32 will enable users to rapidly deploy test environments, explore application spaces, and develop use cases for their business or IoT project.\nKeep Reading\nOriginally published at https://mailchi.mp.\n","date":"27 February 2020","externalUrl":null,"permalink":"/blog/february-2020/","section":"Blog","summary":"","title":"February 2020","type":"blog"},{"content":"As Espressif is a company with their main offices in China, the recent coronavirus outbreak has affected us as well. CEO Teo Swee Ann gives an update of the situation in Shanghai.\nAfter I landed in Shanghai from Singapore on 10 Feb, the first thing I did was to get to the company. Thirty of our staff are reporting for work today. Along the way, I noticed that the traffic has been greatly reduced. It is understandable that with the COVID-19 crisis unfolding, most trips to Shanghai have been cancelled.\nThere is a sense of surreality because when you pass by all the familiar places, most of them are empty, though the lights are still on. I quickly got back to reality, once I entered the office; I had a long meeting with the company secretary on various matters regarding regulations, finances and status of our colleagues, now scattered in various cities, and evaluated the situation and our options. The discussion centered on things that are in general so detailed and convoluted that they would warrant a face-to-face meeting.\nEvaluation of The Ground # On 11 Feb, I decided to buy food for myself and experience the situation. I hailed a cab on my phone using Didi (the Chinese equivalent of Uber), and went to a nearby open mall.\nDespite being devoid of visitors, shops are still making business via online platforms and food deliveries. This is one major differences between a megacity like Shanghai and any other megacities in the world: one can do practically everything via phone Apps such as WeChat, Alipay, Meituan, Starbucks, etc, without having to handle any paper currency or credit cards or even leaving your home.\nLogistically, there would be no issues if one wishes to quarantine himself indefinitely. One of our colleagues joked that if we could get the entire world to do this once a year and we could eradicate chicken pox, influenza, measles, etc. Based on the latest statistics, it appears possible that China could stem new infections over the next couple of months. But, what about the rest of the world?\nLife Goes On — Sort Of # Yesterday, I was told that I would not be allowed into the company, as I had embarked from Singapore, which had cases of the virus. Hence, I was advised to stay away from work for another 12 days. (It is a rule of the business complex.) A staff asked if we should fudge the rules for me. I declined and cited Kant’s Deontological Ethics — it is something that we often talked about within the company.\nSo since yesterday, I have had been working from home, going out only to have my meals.\nBesides the option of ordering food using online platforms, many restaurants are open in the normal sense of the word, albeit with some rules. For instance, I have had my lunch at an Italian eatery today (picture above) while working on my circuits and running simulations via remote access. I was however, the only person at the restaurant (I sat in the open) for that two hours, except for food delivery guys who dropped by every so often to pick up their orders. I finally left because it was too windy for me to have my WeChat teleconference.\nDespite the strict quarantine measures and disruptions, Shanghai city hums along with quiet resolve and expansive tenacity, rapidly adjusting herself to the new circumstances — there have had been no disruption to water, electricity and food, and streets continue to be maintained. Somehow, even the cats in the vicinity of our workplace get fed too.\nRestoring Functions # Our engineers and partners have made significant progress over the past two days to address our concerns regarding logistics and the supply chain. I was informed today that our manufacturing partners resumed operations yesterday and are producing our Espressif modules. A couple of new module designs were also being sent to our partners.\nI don’t remember if I have had ever been so happy about such routine matters—they now rank high on The Checklist.\nThe Virus # In the cities other than Hubei, new infections are decreasing. In Shanghai, for instance, there were only 7 new cases detected today. In Hubei, there was a sharp rise in the number of infections (increase of more than 15,000) reported, and which was attributed to the change in the diagnostic criteria. The Hubei governor was also replaced by the central government today.\nIt’s not a perfect day, but things are moving in the correct direction.\nTeo Swee Ann, CEO Espressif Systems\n13 Feb 2020\n","date":"12 February 2020","externalUrl":null,"permalink":"/blog/a-ceos-experience-during-the-ncov-crisis-part-ii-on-the-ground/","section":"Blog","summary":"","title":"A CEO’s Experience During the nCoV Crisis — Part II : On the Ground","type":"blog"},{"content":"","date":"12 February 2020","externalUrl":null,"permalink":"/tags/ceo/","section":"Tags","summary":"","title":"CEO","type":"tags"},{"content":"","date":"12 February 2020","externalUrl":null,"permalink":"/tags/coronavirus/","section":"Tags","summary":"","title":"Coronavirus","type":"tags"},{"content":"","date":"12 February 2020","externalUrl":null,"permalink":"/tags/covid/","section":"Tags","summary":"","title":"Covid","type":"tags"},{"content":"As Espressif is a company with their main offices in China, the recent coronavirus outbreak has affected us as well. Even though there is an obvious impact on the way we work, the blow is cushioned because we have offices outside of China. Additionally, the way our IT is structured allows most of our staff to work from home, and even for the jobs that do need people to be at the office, there are ways to work around the current issues. CEO Teo Swee Ann gives some insight the thought process behind the decisions made.\nIt was approaching Chinese New Year. I had just left for Okinawa on 24th Jan 2020, from Shanghai with my family — a planned vacation during the Chinese New Year celebration that we were looking forward to. In fact, it had been more than 2 years, since I last had a holiday together with my family.\nHowever, it was to be a holiday that wasn’t meant to be. The coronavirus outbreak situation in China was developing rapidly: just a day ago, Wuhan was locked down and the news reported that there is human-human transmission of the coronavirus. Still at that point of time, most people thought that it was going to blow over soon, and it wasn’t not that bad. It was said to be no more dangerous than a common flu and to only affect the elderly, albeit highly contagious.\nMany things went through my mind on the plane en route to Okinawa. As I watch the clouds floating by, from my window seat, I wondered how the virus will spread in in China, when it would be over, would it affect our colleagues in China, how many days of delay would this be? I had optimistically thought that it would blow over within a month.\nSafety First # As with all new problems, we need to first establish the facts and consider what our alternatives are. Once I landed in Okinawa and checked into the hotel, I immediately called for an online meeting with our China management team to discuss and gather what we know. First, we knew that it was infectious. Second, the mortality rate wasn’t too high. Third, the virus was only fatal to people who were aged or had pre-existing conditions. Of concern, we have some staff who fall within the susceptible age group.\nBased on these information, we formulated our base case and decided to push back the start date of the company to the 3rd of Feb instead of the 30th of Jan (which was later pushed back to the 17th). With this established, we then considered the extreme case: what if nCoV-2019 is the biological equivalent of a nuclear holocaust; with a couple of mutations, it acquires a mortality rate like that of MERS (70%) and is highly infectious?\nCould we move our staff out of harm’s way?\nThe discussion was long and no one was sure how serious it is. Should we wait for the government to make an announcement? Should we panic? We finally decided that we should err on the side of caution, and pro-actively mitigate our risks. For the case of our expat staff, working in Shanghai, we would move them overseas, because many of the group do not speak Chinese and are relatively older. In the case of an emergency, the language barrier may severely disadvantage them.\nWe also knew that when we move our colleagues from Shanghai to another country, we could possibly exacerbate the situation, by spreading it to other countries. How do we square this risk with the considerations about the safety of our colleagues? I made the decision that we should look at the facts as they were: was Shanghai being quarantined? No. Do I think that our staff were infected or exposed? I don’t know everything but I think no — our colleagues were not in Wuhan, or had contact with people from Wuhan. Do I think we should move as many people as we could as long as the laws do not bar us from doing so, our staff are symptoms free and do not have exposure to Wuhan? Yes.\nOn the 27th, we had most of our expat staff leave Shanghai for their home countries with instructions to self-quarantine themselves for at least 10 days thereafter. One of our directors stayed put in Shanghai because his child has flu-like symptoms.\nHow about our local staff in China? First of all, everyone has families in China and naturally everyone wants to be with their family. We briefly considered moving our staff to a warmer climate (within China), such as balmy Hainan (an island in southern China) — it was theorized in the previous SARS outbreak that hot climate and high humidity may have helped stemmed the outbreaks in some regions. After a long exchange, we came to a conclusion that the best course of action was to stay put. Most Chinese cities such as Shanghai, Suzhou and Wuxi, where most of our staff are located, have good medical resource; the Chinese government was also taking a vigorous response to the crisis — the plan to impose strict quarantine on entire major cities and making use of the Chinese New Year to isolate every household is unprecedented in scope and audacity.\nThe early intervention and coordination of the Chinese central government have played a huge role in reining in the spread of the virus to the other Chinese cities and countries, giving everyone precious time to prepare for this contagion. While there have had been criticism of the initial handling of the Chinese government of this crisis, I am of the opinion that the Chinese central government has responded decisively and swiftly once they had gathered the information.\nSituational Analysis # Chip Production # Based on the feedback from our supply chain and logistics partners, our chip supply functions are unaffected. On the silicon wafer side, our associate foundries are located in Taiwan and unaffected. Our partner module factories in China will be resume operations on the 10th of February.\nOur current considerations are how we could without endangering our colleagues and our partners, fulfill the needs of our customers. We note that our manufacturing partners have automated processes that require very little physical workforce. However, we will have another review of our manufacturing processes and supply chain over the next 1 week as we obtain new data from and continue to build new contingencies.\nNew Product and Customer Support # After we moved some of our colleagues out of China, we would regroup everyone in our Czech and Indian offices to proceed with the launch of our new product, ESP32-S2. The R\u0026amp;D of ESP-IDF, solutions frameworks and customer support from these sites are not affected.\nChip R\u0026amp;D # About 40% of our staff in China are issued with laptops and can work from home without any issues.\nThe majority of the chip design is done in our China offices and this year, we have completed and verified major pieces of our core IPs (some of which are used in ESP32-S2) and we are just finishing up on our integration for ESP32-S3 and ESP32-C2. While there is some impact on chip R\u0026amp;D due to the need to access simulation servers, this can be mitigated by enabling remote access.\nBased on our current estimates, more than 90% of our staff will be back and ready to get back to work within 14 days from now, either physically or via remote access. We are also preparing to have all our staff work online, in the event that the situation turns for the worse.\nContingencies and Questions # Over the past two weeks, our global management team has formed the business contingencies, created a new emergency response team (ERT) and carefully evaluated all of the functions of our groups. When formulating the contingencies, we have to make sure that they are real contingencies for the worst case scenarios, including what if I and the management team were infected and down. Although the chances of this happening is extremely small, but we still have to consider these scenarios — things can be unpredictable.\nWhile our aims are to restore the full function of the company as soon as possible, we have to put the safety of our staff at first place. There are certain functions of the company which will require the physical presence of our staff. How do we evaluate the risk?\nFirst, the risk of spreading an infection is described by the following equation:\nprobability[spread at least 1 new infection] = 1 — (1 — 𝜹) ^ ( N[interactions] ⨉ N[infected] )\nwhere 𝜹 is the probability of spreading the virus with each interaction, N[interaction] is the number of direct interactions each infected person has with other non-infected people in one epoch (we define as 5 days), and N[infected] is the number of infected people in the group. (95% of the population develop symptoms when infected, within 5 days.)\nIf any of the values: 𝜹, N[interactions] or N[infected] is equal to zero, there would be no chance of spreading the infection. Hence, to minimize the risks of spreading any infection within the company, we then have to do these 3 groups of actions:\nMore on Reducing Infectivity (or 𝜹) # Here’s our list of recommendations:\nPractical Questions # The Situation in Wuhan # As we have learnt, the situation in Wuhan is critical. Medical staff are getting infected and falling sick. The frontline medical workers are putting their lives at stake to battle the disease. There are even some who have died not of the disease but of exhaustion. The central government is sending thousands of medical workers to Wuhan to relieve the crisis. As of today (10 Feb 2020), the number of new infections in Wuhan are on a downward trend.\nWhat Next # In this epidemic, we are currently in unknown territory; we do not know how the situation will develop or the outcome. Experts have commented that with a R0 that is greater than 2.5, it would probably become a pandemic. But these may not be taking into account the drastic quarantine measures in China. These quarantine measures could also possibly keep the infection rates low enough to buy some time, till warmer weather eliminates the virus.\nBased on the current statistics, the mortality rates outside of Wuhan is 0.2%. This could be no worse than a bad influenza, which has a mortality rate of 0.1%?\nWe have taken measures to keep Espressif going and to keep everyone within Espressif healthy to fight another day. Espressif Czech and Espressif India are unaffected and continue to support our customers directly and develop our latest solutions. In case the situation deteriorates, we will have our entire China workforce to work from home.\nWe are also ready to contribute to the fight against the virus with IOT technology, such with our low cost AI enabled voice recognition (hands free) solution ESP-SKAÏNET and soon to be announced ESP-RAINMAKER. @Makers, please share your ideas! We will help support any IOT solutions that help control the epidemic.\nTeo Swee Ann, CEO Espressif Systems\n10 Feb 2020\n","date":"9 February 2020","externalUrl":null,"permalink":"/blog/a-ceos-experience-during-the-ncov-crisis-part-i-safety-first/","section":"Blog","summary":"","title":"A CEO’s Experience During the nCoV Crisis — Part I: Safety First","type":"blog"},{"content":"","date":"9 February 2020","externalUrl":null,"permalink":"/tags/coronaviruses/","section":"Tags","summary":"","title":"Coronaviruses","type":"tags"},{"content":"Dear all,\n2019 has been an eventful year for Espressif; we went IPO and we launched the new ESP32-S series of chips that enable making secure, connected devices with high performance at affordable cost.\nWe also worked on improving the security of our existing systems. ESP32v3 (aka ESP32 ECO3, the updated version of ESP32) patched the hardware vulnerabilities that were uncovered by the works of our security consultants and later independently by “LimitedResults” (aka “LR”). We thank them for the work on ESP32; Espressif has been and will always be transparent about any security issues. The security of our systems is also constantly reviewed by the best security professionals of our industry, and we spare no effort to fix any issues that comes up. To our customers, we reaffirm our commitment to provide the best support for both our old and new products alike.\nEspressif is about building the best user experience. For this, we have built the most comprehensive ecosystem for IoT developers, including our flagship ESP-IDF SDK, application frameworks: ESP-JUMPSTART and ESP-RAINMAKER, ESP-SKAINET for AI enabled offline voice commands engines, ESP-WHO for AI enabled face recognition solutions, development boards, and modules.\nAs you can see, we are not just about creating the best Wi-Fi chips, but also about providing to our customers complete and fully customizable solutions that work right out of the box. We also understand that connected product development and maintenance needs to be simplified without compromising flexibility. Try our latest ESP32-S2 based ESP-RAINMAKER development boards that enable you to build the a complete cloud connected product within a couple of hours.\nIn 2020, we will be launching 4 new chips, covering different segments of the market, price points and performance. Our latest chips feature our new radio architecture that has lower power consumption while maintaining the same -40°C~125°C performance. The peripherals have been upgraded with highly sensitive capacitive touch IO’s. Capacitive touch controls are now a staple of user interfaces because they are cost efficient; certain functions such as slider controls are better supported with capacitive touch than with analog implementations.\nRecently there has been an unfortunate coronavirus epidemic in China. We have taken measures to work around the restrictions caused by the situation and as a result, based on our current assessment of the situation, the disruption to our operations will be minimal. We and our suppliers are expected to resume operations on the 10th of February. Our teams in Europe, India and China continue in our work to best serve our customers. Should you have any questions or requests, please do write to our business team at sales@espressif.com.\nLastly, we thank our supporters, commercial customers and makers. IoT is a powerful technology that can be used to create solutions that could solve the pressing issues of our time and we continue to believe in our open source approach, robust and low cost solutions that can help everyone develop applications seamlessly.\nHappy coding!\nBest regards,\nTeo Swee Ann\nCEO, Espressif Systems\n2nd February 2020\n","date":"8 February 2020","externalUrl":null,"permalink":"/blog/ceo-letter-feb-2020/","section":"Blog","summary":"","title":"CEO Letter: Feb 2020","type":"blog"},{"content":" Happy New Year to all!\nEveryone here at Espressif would like to wish you health, happiness and creativity for 2020! As ever, we shall continue working hard in trying to give you the best in the field of AIoT. The outgoing year has been an incredible one for our company. In 2019 we released ESP-WHO, our AI development framework, along with its accompanying development board, ESP-EYE. We also launched the ESP-Jumpstart framework to help developers convert their ideas into actual products as quickly as possible. And we also put ESP-Skainet, Espressif’s voice assistant, on the market. At the same time, we consolidated our collaboration with the Google Cloud IoT platform, Tencent Cloud IoT platform and Microsoft Azure IoT solutions.\nFurthermore, we made an impressive debut in a field of 25 companies that launched their initial public offering on the Sci-Tech Innovation Board (STAR) of Shanghai’s Stock Exchange in July 2019. Last, but not least, ESP-BLE-MESH, our implementation of the SIG Bluetooth Mesh got fully certified by Bluetooth-SIG and at the same time other Espressif chips advanced their certification credentials, as shown below:\nESP-WROOM-02D: ANATEL / IFETEL ESP32-S2-WROVER: SRRC / CE / FCC ESP32-WROVER-B: Wi-Fi Alliance These are only a few of our achievements in 2019, but they are the basis of why we look into 2020 with a sense of hope and optimism. Our positivity is based on our work ethos, our passion for innovation and our openness to sharing our technological know-how with the rest of the world. In 2020 we shall continue working hard to take Espressif’s AIoT solutions to the next level. Our intention is to remain at the forefront of technological evolution.\nOther topics you can read in this month’s newsletter include:\nan impact analysis of a recent fault injection attack on ESP32 and the immediate action Espressif took to secure its SoCs even further; the recent Bluetooth LE 5.0 certification of ESP32, which has given our chip greater stability and compatibility; the recent qualification of ESP-EYE, ESP32-WROOM-32S and ESP32-SOLO-1 for Amazon:FreeRTOS. Hope you enjoy reading this month’s newsletter. Keep sending us your messages and requests on Facebook, Twitter, LinkedIn, Instagram and YouTube. We try to respond to all of your messages as quickly as possible!\nBest wishes,John Lee.Senior Customer Support Officer\nESP32 Fault Injection Vulnerability — Impact Analysis # Security researchers have recently described a fault injection attack on ESP32, which may result in some security compromise and unintended disclosure of information. However, ESP32’s security design remains safe for the vast majority of our products. Click on the link below to learn how.\nKeep Reading\nESP32 Is Now Bluetooth LE 5.0-Certified # Espressif’s flagship chip, ESP32, has recently passed the SIG Bluetooth LE 5.0 certification. This affirms that the protocol version supported by the ESP32 microcontroller has been upgraded from Bluetooth LE 4.2 to Bluetooth LE 5.0, which has higher stability and compatibility.\nKeep Reading\nMore Espressif Products Get Qualified for Amazon:FreeRTOS # An increasing number of Espressif products are being qualified for Amazon:FreeRTOS. It was only yesterday (30th Dec.) that our AI dev board, ESP-EYE, as well as our ESP32-WROOM-32SEmodule got qualified, while last month our ESP32-SOLO-1 module got qualified as well.\nKeep Reading\nOriginally published at https://us15.campaign-archive.com.\n","date":"23 January 2020","externalUrl":null,"permalink":"/blog/january-2020/","section":"Blog","summary":"","title":"January 2020","type":"blog"},{"content":"Espressif recently announced ESP32-S2 — a new Wi-Fi SoC with additional security features and improvements over some of the ESP32 security features. Given the current state of the security of the connected devices, these are quite meaningful features. This article discusses these changes and what do they mean from security perspective.\nMy colleague wrote about ESP32 security features here. We continue to carry forward Secure Boot and Flash Encryption features. ESP32-S2 improves these features further and also adds more security features.\nDetailed ESP32-S2 datasheet and technical reference manual are available now.\nSecure Boot # Secure Boot allows the ESP32-S2 to boot only trusted code. The BootROM (which can’t be modified and is trusted) verifies the software bootloader and software bootloader then verifies the application firmware to be trusted (authenticated) one. This is transitive trust model to ensure that the application is fully trusted.\nESP32 BootROM uses a digest programmed in the eFUSE for validating the software bootloader. This digest based authentication uses AES symmetric encryption and SHA secure digest algorithm internally.\nESP32-S2 implements a public key cryptography based signature verification mechanism in BootROM. The algorithm is RSA-PSS with 3072-bit keys. The device maker generates the RSA3072 public-private key pair. The private key remains with the device maker and the public key is programmed in the eFUSE of the device at the time of manufacturing. The software bootloader image carries the signature of the image signed using the private key corresponding to the public key in eFUSE. The BootROM verifies the authenticity of the software bootloader by verifying the signature of the software bootloader (the signature in fact contains a cryptographic hash of the software bootloader that is checked against the software bootloader image).\nThe application firmware verification can happen using the same algorithm and same public-private key pair.\nESP32-S2 has an improved hardware RSA accelerator and BootROM’s secure boot algorithm makes use of this to provide sub-100ms signature verification time. This results into significantly reduced boot up time of the device with secure boot enabled. This is a big improvement especially for those devices which can’t afford longer boot-up time — imagine a light bulb that needs to switch on immediately upon powering-on.\nFlash Encryption # Flash encryption allows the contents of the flash to remain encrypted for the data and code at rest. This is useful in two ways\nESP32 uses AES256 cryptographic algorithm with key tweaking based on the flash offset. The flash encryption key stays in eFUSE and only the hardware has access to this key. While the key tweaking based on the flash offset adds to the security of AES256 protocol, it’s still a customised cryptographic implementation over which a standard implementation is preferred.\nESP32-S2 has an improved scheme where it uses AES256-XTS based encryption scheme that is standard for the storage encryption where the random access needs to be supported. ESP32-S2 continues to use the eFUSE for the storage and access protection of the AES-XTS keys.\nDigital Signature Peripheral # This is a new hardware block added to ESP32-S2. This block is capable of allowing application to perform RSA digital signature operations without letting the application access the private key. Let’s first discuss the need for it.\nOne compelling requirement for the Digital Signature Peripheral is considering the current device-cloud authentication. Most of the common device cloud implementations (AWS-IoT, Azure IoT, Google-IoT-Core to name a few) use (or support) X.509 certificate based mutual authentication. The cloud and device both have a private key and certificate with only certificate shared with the each other. With this, the cloud and device can both authenticate each other and if required cloud can revoke the service access to a specific device. So essentially the device private key is the device identity that needs to be protected. Any application vulnerability that gives the malicious user access to the device private key can compromise the device identity. The devices which require protection against such compromise typically use a separate hardware (HSM, smart-card, PIV dongles etc.) that secures the private key with itself and provides signing procedures with the stored device private key. However this adds to the cost of the device.\nESP32-S2’s Digital Signature Peripheral allows the manufacturer to generate the symmetric encryption key that can be unique to each device and then encrypt the device private key with the same encryption key. At runtime, the Digital Signature Peripheral allows application to perform signing operation with this encrypted device private key without software being able to access the plaintext private key. The per-device unique encryption key also stops malicious user from recovering plaintext private keys or cloning them on other devices.\nEspressif also provides a pre-provisioned modules service where customers can order the modules that have the device certificates pre-generated in a secure fashion in Espressif factory. This when combined with the ESP32-S2’s Digital Signature Peripheral, greatly simplifies manufacturing of devices for device makers.\nMore eFUSE Memory # ESP32 has 1024 bits of eFUSE memory out of which 256 bits are useable by the application.\nESP32-S2 increases the eFUSE memory to 4096 bits with 2048 bits available for application’s use. This is useful when applications want to generate and use per-device unique identifiers for its own use.\nPerformance Improved Cryptographic Accelerators # ESP32-S2 has improved performance of the RSA, ECC and AES hardware accelerators. The mbedTLS stack will continue to facilitate the use of hardware accelerators making the system performance better for the TLS communication over internet and local network. Of course these peripherals can be used directly as well based on the application’s requirement.\nResilience to Physical Fault Injection # When malicious user has physical possession of the device, a glitching based fault injection can be used to make device behave in unintended way or to give undesired information out. There has been fault injection attack for ESP32 V1 SoC that allowed user to compromise security by reading encryption key or bypassing secure boot. ESP32-S2 has additional hardware and software checks in the bootROM that prevent physical voltage glitching. This hardening against physical fault injection attacks may be useful for certain product use-cases.\nESP32-S2 has some additional security features. I’ll write about them adding them to the same blog in the near future. Please stay tuned!\n","date":"9 December 2019","externalUrl":null,"permalink":"/blog/esp32-s2-security-features/","section":"Blog","summary":"","title":"ESP32-S2 — Security Features","type":"blog"},{"content":" Hi everyone,\nAt the beginning of November, a fun project posted on hackster.io put us in the mood to take Halloween seriously! “Doris, the Evil Bowler Hat with ESP32 Matrix Voice” was created by Samreen Islam, Alfred Gonzalez and Carlos Chacin. They used an Open embeddeD Audition System (ODAS) and customized code to move a servo motor in the direction of the most concentrated incoming sound around a 180-degree radius.\nThis enabled the hat to face anyone who would be speaking to the person wearing it! Then, an ESP32on the MATRIX Voice was used for controlling an 8x8 LED MATRIX via SPI with eye animations, which created a fun and spooky effect. Finally, 3D-printed spidery legs completed the look of the evil bowler hat! You can find all the details about this project by clicking here.\nCongratulations to all three members of the team who created this project. Here, at Espressif we value good team work and believe it is the essence of any kind of success.\nOther topics you can read in this month’s newsletter include:\nESP32-VoIP is Espressif’s newly released Internet-Phone solution, which also functions as an example of how to operate voice-controlled devices. The ESP8266 series of modules is now available on China Mobile’s And-link platform, enabling users to develop smart-home solutions with the power of ESP8266. The ESP8266 series of modules also supports China Telecom’s Zhijia platform, where programmers can develop and test smart-home devices. The ESP32-CAM project is Rui Santos’s latest super cool project, showing how the ESP32-CAM board can take a photo and display it in a web server! Hope you enjoy reading this month’s newsletter. Keep sending us your messages and requests on Facebook, Twitter, LinkedIn, Instagram and YouTube. We try to respond to all of your messages as quickly as possible!\nBest wishes,John Lee.Senior Customer Support Officer\nEspressif’s ESP32-based Internet Phone Solution # Espressif has just released an Internet Phone solution, which is based on ESP32 and the Voice over Internet Protocol (VoIP), but also functions as an example of how to operate voice-controlled devices. This application is really cost-effective, with a great performance, supporting voice wake-up, voice interaction, voicemail service, music on demand, etc.\nKeep Reading\nESP8266 Now Supporting China Mobile’s And-link Platform # China Mobile is one of the biggest Chinese telecommunications corporations and also one of the world’s largest mobile network operators with about 100 million subscribers. The ESP8266 series of modules is now available on China Mobile’s And-link platform, which enables users to develop smart-home solutions with the power of ESP8266.\nKeep Reading\nESP8266 Now Supporting China Telecom’s IoT Platform # China Telecom, one of the biggest Chinese telecommunications corporations, is at the forefront of IoT technology and drives the digital transformation of industries in China and beyond. Espressif has now partnered with China Telecom, as the powerful ESP8266 WROOM series of modules is at the epicenter of Zhijia platform’s operation. China Telecom’s Zhijia platform enables programmers to develop and test smart-home devices.\nKeep Reading\nESP32-CAM and Other Cool Projects on RNT # Rui Santos from Random Nerd Tutorials recently posted a very interesting entry on his blog. It shows how to build a web server with the ESP32-CAM board that allows you to send a command to take a photo and visualize the latest captured photo in your browser, having saved it first in SPIFFS.\nKeep Reading\nOriginally published at https://mailchi.mp.\n","date":"22 November 2019","externalUrl":null,"permalink":"/blog/november-2019/","section":"Blog","summary":"","title":"November 2019","type":"blog"},{"content":" Hi everyone,\nOur friends at ThingPulse, Daniel Eichhorn and Marcel Stör, are preparing a treat for the European fans of Espressif boards. They are holding three IoT workshops in beautiful Zürich, in November 2019 and January 2020, which will be about introducing the Internet of Things to children and adults in an interactive setup with many hands-on exercises on Espressif boards . Anyone from 12 years up, including grandparents with kids, are welcome! Prior programming skills may prove to be helpful but are not required.\nThe ThingPulse IoT workshops will cover topics such as:\nWi-Fi Weather Station with ESP8266 and Arduino IDE (November 16th, 2019) This session is aimed at Arduino and ESP8266 beginners with affinity for technology and computer science. Build and Program a Color Weather Station with ESP8266 and Arduino IDE (November 30th, 2019) Participants will be shown how to solder and then program a weather station with a fancy color touch display. “You’ve got Mail” — Advanced IoT with ESP32 and Platform IO (January 15th, 2020) Attendees will learn about ESP32 features and quirks, as well as how to build a mailbox-to-push-notification sensing device. So, do you -or someone you know- want to learn more about IoT, but don’t know where to start from? Then, the ThingPulse IoT workshops are for you, because they are all about learning, sharing and a having a good time! Places are limited and filling up quickly. So, hurry up!\nOther topics you can read in this month’s newsletter include:\nESP-BLE-MESH, which is now fully certified by Bluetooth SIG; ESP32 being launched into space, which happened through a research project at the German Aerospace Center; ESP8266, which is now listed on the Tencent Cloud, supporting the quick connection of ESP8266 to IoT Explorer, Tencent’s Cloud IoT platform; ESP32-based smart devices winning innovation-of-the-year awards in India. Hope you enjoy reading this month’s newsletter. Keep sending us your messages and requests on Facebook, Twitter, LinkedIn, Instagram and YouTube. We try to respond to all of your messages as quickly as possible!\nBest wishes,John Lee.Senior Customer Support Officer\nESP-BLE-MESH Is Now Fully Certified by Bluetooth-SIG # Espressif is pleased to announce that ESP-BLE-MESH has been fully certified by the Bluetooth Special Interest Group (SIG) as of September 2019. This officially ensures that our embedded software solution meets the Bluetooth SIG standards for global product interoperability, and complies with the organization’s License Agreement.\nKeep Reading\nESP32 Launched Into Space # Nico Maas, an IT Engineer and Ground Controller from the Microgravity User Support Center (MUSC) at the German Aerospace Center (DLR), worked with a team of other researchers on developing a new commercial off-the-shelf on-board computer platform for sounding rockets. This experiment was based on ESP32 and resulted in Espressif’s flagship chip being launched into space!\nKeep Reading\nESP8266 Listed on Tencent Cloud # Tencent is a Chinese multinational conglomerate specializing in various Internet-related services and products, entertainment, Artificial Intelligence and the Internet of Things, both in China and abroad. Espressif’s Cloud IoT AT firmware now supports the quick connection of the powerful ESP8266 module to IoT Explorer, which is Tencent’s Cloud IoT platform.\nKeep Reading\nESP32-based Smart Devices Win Innovation-of-the-Year Award in India # Sirena Technologies Private Limited, a partner company of Espressif’s, won the “Alexa Voice Service — Innovation of the Year” award at last month’s Alexa Vox Conference in New Delhi, India. The Alexa Adaptor and Smart Speaker are two award-winning smart voice products, both of whom use Espressif’s ESP32 chip.\nKeep Reading\nOriginally published at https://mailchi.mp.\n","date":"7 November 2019","externalUrl":null,"permalink":"/blog/october-2019/","section":"Blog","summary":"","title":"October 2019","type":"blog"},{"content":"","date":"11 October 2019","externalUrl":null,"permalink":"/tags/api/","section":"Tags","summary":"","title":"API","type":"tags"},{"content":"One of the common requirements I have seen is, during the initial device provisioning, configuring some device specific custom data on the device. This could be something as easy as assigning a user-friendly name to the device, or something like initialising the Alexa credentials on the device.\nThe unified provisioning infrastructure within the ESP-IDF/ESP-Jumpstart allows for this mechanism with ease.\nConceptual Overview # The communication mechanism for the unified provisioning is depicted in the following block diagram:\nThis is the protocol stack that is used during the initial provisioning of the device. From the bottom to the top:\nTransport: The client (typically a phone app) will use either of the two available transport mechanism, HTTP (generally over softAP) or BLE, to establish a connection with the device. Protocomm: The protocomm layer provides a secure abstraction for the higher level APIs. The protocomm layer takes care of registering the API as a HTTPd service API, or a GATT-level API. Additionally, the protocomm layer ensures that data exchange that happens over the API happens over a secure channel. API implementation: At the highest level, the Wi-Fi Provisioning module implements its own APIs: Scan(), SetConfig(), ApplyConfig() and GetStatus(). These are the APIs that the phone application will call while performing the initial device provisioning. The Protocomm layer allows you to install your own custom API. This API can handle the additional configuration such as the user-friendly device name, or the Alexa credentials, that we discussed in the beginning.\nThe provisioning implementation uses Protocol Buffers to exchange data over its API. Your API implementation is free to choose any data representation for exchanging data.\nSample Code # Let’s say you have to create your own custom API, MyCustomAPI() that allows the phone application to configure a user-friendly device name into the device.\nWe can take the example of ESP-Jumpstart application for this discussion. In the ESP-Jumpstart application, in any application after the 4_network_config/ application, go to the line that makes the call to wifi_prov_mgr_start_provisioning().\nYou can modify this call to look like the following:\nwifi_prov_mgr_endpoint_create(\u0026#34;my-custom-api\u0026#34;); wifi_prov_mgr_start_provisioning(security, pop, service_name, service_key));wifi_prov_mgr_endpoint_register(\u0026#34;my-custom-api\u0026#34;, custom_prov_config_data_handler, NULL); So we use the wifi_prov_mgr_endpoint_create() to create a new endpoint, and then setup a callback handler that needs to be invoked using the wifi_prov_mgr_endpoint_register(). And now you can implement the function *custom_prov_config_data_handler(). *This callback handler will get called whenever the client makes a call to the my-custom-api endpoint.\nesp_err_t custom_prov_config_data_handler(uint32_t session_id, const uint8_t *inbuf, ssize_t inlen, uint8_t **outbuf, ssize_t *outlen, void *priv_data) {/* The \u0026#39;inbuf\u0026#39; contains the input data to this API. The function * should allocated and populate the \u0026#39;outbuf\u0026#39; that should contain * the response. */ if (inbuf) { ESP_LOGI(TAG, \u0026#34;Received data: %.*s\u0026#34;, inlen, (char *)inbuf); } char response[] = \u0026#34;SUCCESS\u0026#34;; *outbuf = (uint8_t *)strdup(response); if (*outbuf == NULL) { ESP_LOGE(TAG, \u0026#34;System out of memory\u0026#34;); return ESP_ERR_NO_MEM; } /* +1 for NULL terminating byte */ *outlen = strlen(response) + 1; return ESP_OK;} Phone Application # This API can now be called from any client like a phone application. The client will make calls to this API, just like it makes to the other APIs of the network configuration infrastructure.\nThe source code for the provisioning phone applications is available for iOS and Android.\nThe phone application can be modified to make the call to the my-custom-api that we defined in the firmware above. Please note any calls to custom APIs should be made before the phone application executes the *ApplyConfig *API. The *ApplyConfig *call indicates to the firmware that the provisioning is now complete.\nAnd that way, we have easily added a custom configuration API to our device’s initial provisioning workflow.\n","date":"11 October 2019","externalUrl":null,"permalink":"/blog/esp32-device-provisioning-configuring-custom-data/","section":"Blog","summary":"","title":"ESP32 Device Provisioning: Configuring Custom Data","type":"blog"},{"content":"","date":"11 October 2019","externalUrl":null,"permalink":"/tags/jumpstart/","section":"Tags","summary":"","title":"Jumpstart","type":"tags"},{"content":" Hi everyone,\nApologies for the typo in our latest newsletter, at the beginning of which ESP32-S3 was mentioned, instead of the correct ESP32-S2 . So, it is the ESP32-S2 datasheet that has been released. You can now find it online in the documentation section of our website.\nESP32-S2 is a low-power 2.4 GHz Wi-Fi System-on-Chip (SoC) solution. With its state-of-the-art power and RF performance, this SoC is an ideal choice for a wide variety of application scenarios relating to the Internet of Things (IoT), wearable electronics and Smart Home. ESP32-S2 includes a Wi-Fi subsystem that integrates a Wi-Fi MAC, Wi-Fi radio and baseband, RF switch, RF balun, power amplifier, low noise amplifier (LNA), etc. Espressif’s new SoC is fully compliant with the IEEE 802.11b/g/n protocol and offers a complete Wi-Fi solution. At the core of this SoC is an Xtensa® 32-bit LX7 CPU that operates at a maximum of 240 MHz. The SoC supports application development, without the need for a host MCU.\nThe on-chip memory includes 320 KB SRAM and 128 KB ROM. It also supports a number of external SPI/QSPI/OSPI flash and SRAM chips for more memory space. With its multiple low-power modes, ESP32-S2 is designed for ultra-low-power performance. Its fine-grained clock gating, dynamic voltage and frequency scaling, as well as the adjustable output of its power amplifier contribute to an optimal trade-off between communication range, data rate and power consumption.\nThe device provides a rich set of peripheral interfaces, including SPI, I2S, UART, I2C, LED PWM, LCD, camera, ADC, DAC, touch sensor, temperature sensor, as well as 43 GPIOs.\nIt also includes a full-speed USB On-The-Go (OTG) interface which enables USB communication at all times.\nESP32-S2 has several dedicated hardware security features. Cryptographic accelerators are integrated, thus providing AES, SHA and RSA algorithms. Additional hardware security features are provided by the RNG, HMAC and Digital Signature modules, as well as flash encryption and secure boot signature verification. These characteristics allow the device to meet stringent security requirements.\nOther news you can read in this month’s newsletter include:\nEspressif’s new Smart Voice Assistant, which supports voice wake-up and multiple offline speech-recognition commands; Cesanta’s support for ESP32 and ESP8266 on the mDash Cloud platform, which generally aims to accelerate the Web for the Internet of Things; Espressif’s new partnership with Temboo, which is meant to give IoT developers the opportunity to research, design and build the next generation of connected products with access to sensor data; Ryan Bates’s animated pixel art with ESP8266. Hope you enjoy reading this month’s newsletter. Keep sending us your messages and requests on Facebook, Twitter, LinkedIn, Instagram and YouTube. We respond to all of your messages as quickly as possible!\nBest wishes,John Lee.\nSenior Customer Support Officer\nEspressif’s New Smart Voice Assistant, ESP-Skainet, Released # ESP-Skainet is a new voice-interaction development framework based on Espressif’s flagship chip, ESP32. The new development framework supports voice wake-up and multiple offline speech-recognition commands. With ESP-Skainet, users can easily build applications based on wake-word detection and speech-recognition commands.\nKeep Reading\nESP32 and ESP8266 Supported by Cesanta’s mDash Cloud Platform # Cesanta, an IoT company based in Dublin, Ireland, has recently launched mDash, which is an IoT Cloud platform for the administration of various IoT modules. This platform now supports Espressif’s SoCs, ESP32 and ESP8266, among other chips, offering a number of features that significantly facilitate building IoT applications\nKeep Reading\nEspressif and Temboo Partner to Empower Everyone to Benefit from the Internet of Things # The new partnership between Espressif Systems and Temboo is meant to give IoT developers the opportunity to research, design and build the next generation of connected products with access to sensor data. This will further bridge the gap between the physical and the digital world by using the Internet of Things more effectively.\nKeep Reading\nAnimated Pixel Art with ESP8266 # If you are a maker and also into pixel-art renditions of iconic video-game characters, then this article is for you! It’s time to unleash your creativity by making your own animated pixel-frame depicting your favorite character. All you need is an ESP8266 and Ryan Bates’s tutorial.\nKeep Reading\nOriginally published at https://mailchi.mp.\n","date":"9 October 2019","externalUrl":null,"permalink":"/blog/august-2019/","section":"Blog","summary":"","title":"August 2019","type":"blog"},{"content":"Hi everyone,\nSummer is getting hotter by the day here in Shanghai, but it seems that the only effect it is having is our steaming ahead with a new series of chips based on ESP8285 . The already existing version of ESP8285 features complete and self-contained Wi-Fi networking capabilities, fast switching between sleep and wakeup modes, adaptive radio biasing, advance signal processing, spur cancelation and RF co-existence, to mention only a few of its sophisticated characteristics.\nIn addition to these, the two new variants in the ESP8285 series will have different memory capacities and operating temperatures, in order to cater for as many application scenarios as possible. The first variant to be released in late August 2019 is ESP8285H16 , with a 2 MB memory and an operating temperature that ranges from -40°C to +105°C . The other variant is ESP8285H08 , with a 1 MB memory, operating from -40°C to +105°C . Stay tuned to get all the details about our new ESP8285 variants in August!\nOn a different note, as many of you probably know already, ESP-Jumpstart is Espressif’s reference guide that is based on the IoT Development Framework, ESP-IDF. The aim of this guide is to help developers convert their ideas into actual products as quickly as possible. The guide itself was released in April 2019, but last month the first ESP-Jumpstart training____ for University students took place in Espressif’s headquarters in Shanghai, at Zhangjiang Hi-Tech Park.\nThis training was part of Espressif’s outreach program which aims to disseminate knowledge of AIoT technologies to top University students from across China. Led by Espressif engineers, this 16-hour training was offered to 9 students from Shanghai JiaoTong University, Shanghai University, East China Normal University and ESIGELEC ROUEN University .\nThe participants used ESP32-DevKitC to build their own IoT demos and WeChat mini-programs for controlling smart devices. After due deliberation the Espressif engineers who led this training program awarded the best student of the cohort a prize which consisted of a CNY 5,000 stipend and an internship at Espressif Systems . That said, the benefits of this program were not restricted only to the prize winner. The knowledge that all participants acquired and the skills they honed during this training has helped them to significantly improve their graduation projects. Other news you can read in this month’s newsletter include:\nEspressif’s impressive debut on the Sci-Tech Innovation Board of Shanghai’s Stock Exchange, on July 22nd, which was celebrated with a glorious gala later on the same day; Espressif’s new Module Pre-provisioning Services (MPS), which will enable customers to reduce manufacturing complexities and time to market; Espressif’s partner, DFRobot, which -offering several products based on ESP32 and ESP8266- has become a world-leading provider of robotics and open-source hardware; ESPcopter, which is a unique ESP8266-based, small-sized drone that is wirelessly networkable, interactive and programmable. Hope you enjoy reading this month’s newsletter. Keep sending us your messages and requests on Facebook, Twitter, LinkedIn, Instagram and YouTube. We respond to all of your messages as quickly as possible!\nBest wishes,John Lee.Senior Customer Support Officer\nEspressif Celebrates Its IPO and Presents a New Series of Chips # Espressif was one of the 25 companies that traded on the day when Shanghai Stock Exchange’s (SSE) STAR Market, the NASDAQ-style technology board, made its debut. Hence, July 22 has been a day of historical significance for the development of Espressif. We celebrated our successful Initial Public Offering in a glorious event at Kerry Hotel, in Pudong, Shanghai, where we also officially presented a new series of chips, ESP32-S2, which will be released shortly.\nKeep Reading\nEspressif Now Offers Module Pre-Provisioning Services # Espressif customers can now take advantage of a new service that will enable them to reduce manufacturing complexities and time to market. Espressif modules are adequately prepared and equipped with Public Key Infrastructure (PKI) at the manufacturing level, so they can provide out-of-the-box secure communication with IoT cloud services. Espressif’s pre-provisioned modules enable users to connect their products to their cloud of choice quickly, easily and securely.\nKeep Reading\nDFRobot’s Espressif-based Products Foster IoT Learning Community # DFRobot is an Espressif partner that specializes in robotics and open-source hardware. They have a product catalog that includes more than a thousand components and widgets, such as sensors, robotic platforms, communication modules, and 3D printers. They have modeled several of their products around ESP8266 and ESP32, fostering a strong community of IoT learning.\nESPcopter: An ESP8266-based Programmable Mini Drone # Are you interested in learning programming, but have no such background and are skeptical about taking the plunge? Are you a programmer already, wishing to specialize in IoT applications? Do you want to learn how to fly a drone? If you’ve given at least one “yes” to the above-mentioned questions, then you have to check out ESPcopter, an ESP8266-based programmable mini drone like no other!\nKeep Reading\nAs imported on 26 July 2019 from here.\n","date":"28 July 2019","externalUrl":null,"permalink":"/blog/july-2019/","section":"Blog","summary":"","title":"July 2019","type":"blog"},{"content":"","date":"11 June 2019","externalUrl":null,"permalink":"/tags/internet-of-things/","section":"Tags","summary":"","title":"Internet of Things","type":"tags"},{"content":"Hi everyone,\nCelebrating the Dragon Boat Festival on 7–9 June is not the only reason we feel energetic and refreshed this week. More importantly, our new chip, ESP32-S2, will soon come out, as we have recently announced.\nESP32-S2 is a highly integrated, low-power microcontroller supporting 2.4 GHz Wi-Fi HT40 and having 43 GPIOs. Our new chip is based on an Xtensa single-core 32-bit LX7 processor that can be clocked up to 240MHz. With state-of-the-art power management, RF performance, IO capabilities and security features, ESP32-S2 is an ideal choice for smart-home applications, wearables and a wide variety of other IoT applications. In fact, the 240 MHz Xtensa core makes ESP32-S2 an optimal solution for building the most demanding IoT projects without requiring external MCUs.\nBy leveraging Espressif’s mature and production-ready IoT development framework (ESP-IDF), ESP32-S2 achieves excellent value for money, thus bringing faster and more secure IoT solutions to the market.\nEngineering samples of the beta version of ESP32-S2 will become available towards the end of June 2019. For more information, please contact Espressif’s Business Support Department.\nOther news you can read in this month’s newsletter include:\nthe official inclusion of our ESP32-Azure IoT Kit in Microsoft’s Plug-and-Play program, which aims to bring extra ease to connecting IoT devices. a great event that AWS and Espressif put together on 4 June for the IoT community in the USA, which was about the development of IoT solutions. Espressif’s sponsorship of Pycom’s #GOINVENT worldwide series of workshops. a really cool project posted on hackster.io, which shows how you can create 8-bit tunes, using an ESP8266 development board. Hope you enjoy reading this month’s newsletter. Keep sending us your messages and requests on Facebook, Twitter, LinkedIn, Instagram and YouTube. We respond to all of your messages as quickly as possible!\nBest wishes,John Lee.Senior Customer Support Officer\nMicrosoft’s Plug-and-Play with the ESP32-Azure IoT Kit # Espressif’s ESP32-Azure IoT Kit has been granted a certification that makes it an integral part of Microsoft’s Plug-and-Play program, which has been designed to bring the ease of “Plug and Play” to IoT devices. With Microsoft’s Plug and Play, developers can plug virtually any peripheral into a Windows PC without having to worry about drivers.\nKeep Reading\nAWS and Espressif’s Workshop in the USA # On 4 June, Espressif and AWS co-hosted a hands-on workshop focused on developing IoT solutions using Amazon FreeRTOS and ESP32 development boards, such as ESP32-DevKitC and ESP-WROVER-KIT-VB. Embedded developers learned about the AWS IoT suite of services and built firmware for the management of typical IoT appliances.\nKeep Reading\nEspressif Sponsors Pycom’s #GOINVENT World Series of Workshops # Pycom has been an Espressif partner since 2017. They provide IoT platforms with end-to-end solutions that can fit any project. Pycom has recently started a series of workshops aiming to engage with the worldwide community of IoT makers. Espressif could not but support them in this fantastic initiative.\nKeep Reading\nCreate 8-bit Tunes with ESP8266! # Chiptune, also known as chip music or 8-bit music, is a style of synthesized electronic music made using the programmable sound generator (PSG) sound chips in vintage arcade machines, computers and video game consoles. However, you can now create cool 8-bit tunes, using an ESP8266 dev board.\nKeep Reading\n","date":"11 June 2019","externalUrl":null,"permalink":"/blog/june-2019/","section":"Blog","summary":"","title":"June 2019","type":"blog"},{"content":"Hi everyone,\nThe beginning of May found us celebrating not only this year’s Labor Day Festival, which was a four-day public holiday in China, but also the new phase of Espressif’s collaborations with Google and Microsoft. Our popular ESP32-DevKitC now enables an easy evaluation and development for ESP32-based products connected to the Google Cloud IoT Core. Similarly, our ESP32-Azure IoT Kit is dedicated to supporting Microsoft’s Azure IoT cloud services. We have recently added “Joint Development” to our dropdown menu under the “Products” tab on the landing page of our website, in order to offer our customers a detailed presentation of the two development kits mentioned above. You can also find a short description below.\nESP32-DevKitC-GoogleCloud-IoT is built around ESP32-WROOM-32Dand provides out-of-the-box Google Cloud IoT connectivity. This unbeatable dev kit enables rapid prototyping by being breadboard-friendly and feature-rich. We’re equally proud of our ESP32-Azure IoT Kit, which is a development kit designed with powerful functions, such as sensor data acquisition and cloud platform access, as well as a wide range of applications.\nOther news you can read in this month’s newsletter include:\nESP-IDF v3.2, the latest version of Espressif’s IoT Development framework, which has just been released; The ekey UNO finger scanner, an innovative security system, which has been based on Espressif’s ESP32-WROVER module and made in Austria; LyraT-Mini, a new development board that is small in size, yet highly versatile and powerful, which will soon be added to Espressif’s Lyra series; and last, but not least, The Complete ESP32 Projects Guide, Prof. Dragan Ibrahim’s new book about ESP32, which has just been published by Elektor. Hope you enjoy reading this month’s newsletter. Keep sending us your messages and requests on Facebook, Twitter, LinkedIn, Instagram and YouTube. We respond to all of your messages as quickly as possible!\nBest wishes,John Lee.Senior Customer Support Officer\nESP-IDF v3.2 Released # The latest version of Espressif’s IoT Development Framework, ESP-IDF v3.2, has just been released. This is part of our commitment to improve our IoT solutions, based on the results of our quality assurance procedures and the feedback we receive from the community of developers who use our chips.\nKeep Reading\nekey UNO: No More Keys with ESP32-WROVER # The ekey UNO finger scanner is an innovative security system that has been based on Espressif’s ESP32-WROVER module. This biometric security solution has been developed in Austria by ekey, a top European company that creates high-tech access solutions. Since 2002, ekey has been entrusted by private households, leading companies and public organizations providing fire and rescue services.\nKeep reading\nNew “LyraT-Mini” To Be Launched Soon # Espressif has developed an ESP32-based audio development board which will be part of the Lyra series. The distinctive characteristics of the new board are its mini size (hence the name “LyraT-Mini”) and its single-mic wake-up interrupt. Moreover, it has a simple hardware architecture, a very competitive price and an excellent keyword recognition rate.\nKeep Reading\nThe Complete ESP32 Projects Guide # Prof. Dogan is a seasoned electrical engineer and an IET Fellow. He has recently written a book about ESP32, which has been published by Elektor. The book’s title is The Complete ESP32 Projects Guide and it contains 59 projects based on Espressif’s popular ESP32-DevKitC development board.\n","date":"26 May 2019","externalUrl":null,"permalink":"/blog/may-2019/","section":"Blog","summary":"","title":"May 2019","type":"blog"},{"content":"ESP-Jumpstart (GitHub repository) is a production-ready, easy-to-customise firmware template that you can use to jumpstart your product development with ESP32 / ESP8266. ESP-Jumpstart builds a fully functional, ready to deploy “Smart Power Outlet” in a sequence of incremental tutorial steps.\nAlong with the ESP32 / ESP8266 firmware, ESP-Jumpstart includes phone applications(iOS/Android) for network configuration, and integrated with cloud agents (currently AWS IoT) to synchronise device state with the cloud.\nESP-Jumpstart implements a power outlet with the following functionality:\nAllows and end-user to configure their home Wi-Fi network through phone applications (iOS/Android) Switch on or off the GPIO output Use a push-button to physically toggle this output Allow remote control of this output through a cloud Implement over-the-air (OTA) firmware upgrade Perform Reset to Factory settings on long-press of the push-button You can easily customise ESP-Jumpstart to convert it into your particular product by only writing your device drivers, and adapting the cloud agent accordingly. Everything else is already included.\nHead over to the ESP-Jumpstart documentation and get started.\n","date":"12 May 2019","externalUrl":null,"permalink":"/blog/jumpstart-iot-product-development-on-esp32/","section":"Blog","summary":"","title":"ESP-Jumpstart","type":"blog"},{"content":"","date":"12 May 2019","externalUrl":null,"permalink":"/tags/product-development/","section":"Tags","summary":"","title":"Product Development","type":"tags"},{"content":"Welcome to our April Newsletter\nHi everyone,\nWe’re really excited this month because Espressif has just started the process of offering its shares to the public for the first time (IPO), through the Shanghai Stock Exchange. We are hopeful that this process will come to fruition by the end of the year and that Espressif will be listed on the new Science and Technology Innovation Board of the Shanghai Stock Exchange. The Science and Technology Innovation Board, which aspires to become the Chinese version of Nasdaq, is designed to help technology-oriented enterprises grow their finances and drive innovation.\nEspressif has gone from strength to strength over the last few years. Our achievements include prestigious collaborations, awards and investments, while also providing evidence that our business cycle has significantly expanded both in China and abroad. Submitting, then, our IPO application to the Shanghai Stock Exchange was the next step in our path to driving technological innovation in China and beyond.\nOther news you can read in this month’s newsletter include:\nJumpstart, Espressif’s new reference guide which aims to help developers convert their ideas into actual products in the least possible amount of time; Embedding voice into ESP32 devices using Google’s Dialogflow, which provides developers with a hassle-free way of building their own conversational platforms for their own products; ESP-EYE being featured on WeChat, which is China’s biggest social media platform, with more than a billion monthly active users; and last, but not least, “Kevin”, who is your new ESP32-based virtual housemate. Built by Mitipi, a Swiss startup, Kevin seems “determined” to deter any burglars from breaking into your house. Hope you enjoy reading this month’s newsletter. Keep sending us your messages and requests on Facebook, Twitter, LinkedIn, Instagram and YouTube. We respond to all of your messages as quickly as possible!\nBest wishes, John Lee. Senior Customer Support Officer\nESP-Jumpstart: Building ESP32 Products Fast # Espressif has once again responded to the need of IoT makers for quick product development. ESP-Jumpstart is Espressif’s new reference guide which aims to help developers convert their ideas into actual products in the least possible amount of time. It provides users with a complete guide for product development.\nKeep Reading\nGoogle Dialogflow: Embedding Voice into Devices with ESP32 # Dialogflow is a Google service that runs on the Google Cloud Platform, allowing users to build engaging AI-powered conversational interfaces on their products. ESP32 now supports Dialogflow with Espressif’s Voice-Assistant SDK, enabling IoT developers to embed natural-language processing in their devices.\nKeep reading\nESP EYE on WeChat # To people living outside China, Tencent’s ubiquitous messaging application, WeChat, might be relatively unknown. But to everyone in China, WeChat is much more than just a smartphone app. With more than a billion monthly active users, WeChat is also a powerful marketing tool. Espressif, as a top social-media influencer in the Chinese AIoT industry, has developed its own WeChat mini program (an app within WeChat) that will enhance the use of ESP-EYE, Espressif’s brand new AI development board.\nKeep Reading\nESP32-based Protection Against Burglars # Everyone can agree that even the idea of getting back home and finding it robbed can give you the shivers. Mitipi is a Swiss company that has built “Kevin”, an ESP32-based virtual housemate who will deter any burglars from breaking into your house. Kevin will make any burglars lurking around your neighborhood think that you are still at home when you are actually away.\nKeep Reading\nOriginally published at mailchi.mp.\n","date":"4 April 2019","externalUrl":null,"permalink":"/blog/april-2019/","section":"Blog","summary":"","title":"April 2019","type":"blog"},{"content":"ESP-IDF now supports Apache Mynewt NimBLE host stack which is ported for the ESP32 platform and FreeRTOS. NimBLE is an open-source Bluetooth Low Energy (BLE) or Bluetooth Smart stack (both host and controller) fully compliant with Bluetooth 5 specifications and with support for BLE Mesh. More details can be found here: https://mynewt.apache.org/. NimBLE, being BLE only, is a footprint optimised stack and can be used in a variety of applications involving BLE.\nThe NimBLE preview release is made available on ESP-IDF Github: https://github.com/espressif/esp-idf/\nA few examples, ported from the NimBLE repository, can be found here: examples/bluetooth/nimble\nThe porting layer is kept cleaner by maintaining all the existing APIs of NimBLE along with a single ESP-NimBLE API for initialisation, making it simpler for the application developers. The documentation of NimBLE APIs can be found at: https://mynewt.apache.org/\n","date":"19 March 2019","externalUrl":null,"permalink":"/blog/preview-release-nimble-support-in-esp-idf/","section":"Blog","summary":"","title":"Preview Release: NimBLE support in ESP-IDF","type":"blog"},{"content":"Welcome to our March Newsletter\nOur News. Our World Join Us!\nHi everyone,\nAt the end of last month Google announced its partnership with Espressif Systems in a blogpost introducing the Google Cloud IoT Device SDK. This consists of libraries written in Embedded C that enable developers to securely connect, provision, and manage all of their devices with the Google Cloud IoT Core. On this occasion, Teo Swee Ann, the founder and CEO of Espressif Systems, said: “Our collaboration allows for the easy integration of two of our most widely-used products, ESP32 and ESP8266. We are committed to working with Google Cloud, supporting updates to the SDK and enabling our customers to easily make use of current and future designs with Cloud IoT Core.”\nFrom a value perspective, the Google Cloud IoT Device SDK allows embedded engineers to rapidly prototype, profile, and test in a standard desktop environment before porting to an embedded target, which allows for shorter time to market. So, Espressif is excited to be an integral part of this ecosystem.\nEspressif’s increasing market penetration is further evidenced by the growing number of companies that are looking for ESP32 specialists. After searching a number of overseas recruitment websites (e.g. Guru, Freelancer, Upwork, Monster, CareerBuilder, SimpleHired, LinkedIn, etc.), we found that ESP32 developers are now widely sought after! The latest example is derived from a London-based company with the evocative\nname, “Tech Will Save Us”. They are looking for engineers with proven experience in embedded development with ESP32 / ESP-IDF. Compensation would depend on the successful candidate’s actual knowledge, but could range up to £500/day.\nOther topics you can find in this month’s newsletter include:\n“Empathy Swarm”, an Espressif-sponsored project which examines how non-anthropomorphic robots can learn, but also instigate, feelings of empathy and compassion; Espressif’s energy-saving smart-lighting solution that is based on ESP-MESH; MoonBot, a do-it-yourself kit for tinkering with modern robotics and artificial intelligence projects, which has been based on Espressif’s ESP32-WROOM-32 module; An ESP32-based remote-controlled car, which enables video-streaming over Wi-Fi, while running on a small LiPo battery and being controlled accurately from any web browser. Hope you enjoy reading this month’s newsletter. Keep sending us your messages and requests on Facebook, Twitter, LinkedIn, Instagram and YouTube. We respond to all of your messages as quickly as possible!\nBest wishes, John Lee. Senior Customer Support Officer\n“Empathy Swarm”: An Art-and-Science Project Sponsored by Espressif # Espressif has sponsored a project that is on the verge between arts and sciences. It is named “Empathy Swarm” and it examines the ways in which non-anthropomorphic robots can learn, but also instigate, feelings of empathy and compassion. The people behind the project are Katrin Hochschuh and Adam Donovan. Espressif’s contribution has taken the form of a hardware sponsorship based on the ESP32-WROVER-B (IPEX) and the ESP32-PICO-D4 modules.\nKeep Reading\nEnergy-Efficient Lighting Solution with ESP Mesh # Have you ever wondered how wasteful it is to leave the office without turning the lights off or have only few employees working during the night and yet keep the lights on across the entire company? Likewise, is it not very inefficient to use big meeting rooms day and night without a system adjusting the lights to users’ actual needs? Automation is the key concept here and ESP Mesh is Espressif’s technology for energy-efficient lighting systems that respond automatically to users’ needs.\nKeep reading\n“MoonBot Kit” Based on ESP32-WROOM-32 # MoonBot is a do-it-yourself kit for tinkering with modern robotics and artificial intelligence projects. Its vision processor is Espressif’s ESP32-WROOM-32 module. Whether you are just getting started, or have worked with robots in the past, the MoonBot kit will help you create professional-looking robots with advanced autonomy.\nKeep Reading\nESP32-Powered FPV Car # “Simplicity is the key to brilliance”, some people say, and it seems that the remote-controlled car made by the German engineer Maximilian Kern (also known as Max.K) is a concrete example of this principle. Despite the current trends of producing fairly complicated high-tech gadgets, there is plenty to to be said about simple ones, too, such as Maximilian’s adorable ESP32-driven bot.\nKeep Reading\nOriginally published at mailchi.mp.\n","date":"11 March 2019","externalUrl":null,"permalink":"/blog/march-2019/","section":"Blog","summary":"","title":"March 2019","type":"blog"},{"content":"","date":"10 March 2019","externalUrl":null,"permalink":"/tags/dialogflow/","section":"Tags","summary":"","title":"Dialogflow","type":"tags"},{"content":"ESP32 already supported being a fully functional Alexa client, a voice assistant.\nESP32 now also supports Dialogflow, a voice-enabled conversational interface from Google. It enables IoT users to include a natural language user interface in their devices.\nThe differences of Dialogflow w.r.t. voice assistants are\na reduced complexity, pay as you go pricing, custom wake words, instead of having to use ‘Okay Google’ or ‘Alexa’ and no certification hassles, because hey, you aren’t integrating with Alexa or Google Assistant; you are building one of your own Unlike voice-assistants, Dialogflow let’s you configure every step of the conversation, and it won’t answer other trivia/questions like voice-assistants typically do. For example, a Dialogflow agent for a Laundry project will provide information only about the configurable parameters of the laundry (like state, temperature, wash cycle etc.)\nThis is now a part of Espressif’s Voice Assistant SDK and is available on github here: https://github.com/espressif/esp-va-sdk. To get started, see this.\nThe underlying technologies used by the Dialogflow implementation for VA SDK includes:\ngRPC Google Protobufs HTTP 2.0 You can see a demo video of Dialogflow on ESP32 LyraT below:\nNote that the current Dialogflow SDK does not yet include support for creating custom wake words. Conversations initiated with a tap-to-talk button are supported.\n","date":"10 March 2019","externalUrl":null,"permalink":"/blog/embedding-voice-into-devices-with-esp32/","section":"Blog","summary":"","title":"Embedding Voice into Devices with ESP32","type":"blog"},{"content":"IoT is not one thing, it means different things to different people. So also, there are so many ways of building connected products. And that means there are so many questions for every aspect of your connected product:\nWhat communication protocols do we use? Which network configuration mechanism should we use? What do we use for remote communication? What’s the most secure method for doing this? Do we offer low-latency control options through local network access? How do we expose this in the app so that it offers the smoothest user experience? How do we participate in the broader smart-home ecosystem? Every question is additional time spent researching about a topic and identifying the best (and secure) solution for the problem.\nWhen the Apple HomeKit ecosystem came along, it came with a set of defined solutions for most of these questions, such that they are secure, easy to use and part of a larger ecosystem.\nIn the same spirit, we decided to build a HomeKit SDK that is extremely easy and intuitive to build with. And at the same time make it quite extensible, for developers that want to do off-beat things with it.\nSo far, we have a large number of customers developing with our HomeKit SDK (HomeKit requires developers to have Apple’s MFi license), and given the feedback that I have seen, the SDK has helped them shave off significant development time, reaching to production faster. The SDK has been a significant product management win. Let’s look at some key highlights.\nAPI # Let’s say, I have been a manufacturer of electric switches. I think this consumer interest in the smart-home is exciting and I want to build a smart electric switch. What I really want to do is enable the on/off toggle of this switch through a phone or tablet. All I want is a way to say that these are the attributes I have (in this case: the power state), and this is what happens when I read the attributes or update them (in this case: assert/deassert a GPIO that controls a relay). All these questions above, about network configuration, discovery, cloud servers and interoperability are a needless hindrance. Should I really have to answer all these questions, and if so who do I seek out for a more informed decision?\nFor the HomeKit SDK, we have spent a significant amount of time on the API design, keeping this in mind. We have structured the API in such a way that for all the common scenarios, customers only have to do the bare minimal things. They declare what the device attributes are (heating/cooling state and temperature for the thermostat), and how to read/update them (perform a SPI transaction that sets the temperature). Everything else about connectivity, comformance, state management, is handled by the SDK.\nAnd by creating the right layers of advanced APIs underneath these simplified APIs, we can also accommodate the diverging use cases that don’t necessarily fit in this simplified model. This allows us to support a wide range of end-product scenarios.\nEnd-Product Features # We keep putting ourselves into our customers’ shoes, trying to understand the typical additional features that developers would want to have in their product. And try to provide better support for these up-front.\nFor example, developers building HomeKit-enabled products, may also want to have support for Android-initiated configuration or Android/Cloud initiated access. The SDK includes software components that let you do this without affecting the HomeKit workflows. And it is structured so that it is an optional component, (a) you could use it in your product, (b) you could completely not have it, or (c) use a completely different method for supporting Android access.\nSimilar is the case for supporting common features such as over-the-air (OTA) firmware upgrades, using secure storage, or handling per-device unique manufacturing data. Appropriate abstractions ensure that these common tasks are made as smooth as possible, at the same time, provide flexibility to diverge.\nDeveloper Workflows # For an SDK, optimising for developer workflows directly implies getting faster to that production-ready firmware. As developers start using the HomeKit SDK, they are at various stages of HomeKit expertise. Some have done it before, some are just starting anew. Some may have all the hardware components required for building HomeKit products, while others may have to wait for the hardware lead time before they get started.\nThe SDK provides multiple start points such that evaluation or development doesn’t have to block on one particular aspect. As you progress through the stages of evaluation to manufacturing, you can incrementally move components into the final production-ready state.\nFix-only-once # Our mantra for support is Fix only once. What that means is that once a customer issue is reported, it should either lead to a documentation update, or a code commit. This ensures that that issue, or those class of issues, should never be reported again by any customer.\nOur SDK continues to evolve with every new customer that uses the SDK, and every new feature that they implement. We are excited about this journey and continue to look forward to making it even easier to build connected devices.\nReferences # Register for HomeKit SDK access (MFi Account Number Mandatory): https://www.espressif.com/en/company/contact/pre-sale-questions-crm?js-from=homekit Mass Manufacturing Utility: https://docs.espressif.com/projects/esp-idf/en/latest/api-reference/storage/mass_mfg.html Manufacturing Data Partitions: https://medium.com/the-esp-journal/building-products-creating-unique-factory-data-images-3f642832a7a3 All product names, trademarks and registered trademarks are property of their respective owners.\n","date":"10 February 2019","externalUrl":null,"permalink":"/blog/homekit-on-espressifs-esp32/","section":"Blog","summary":"","title":"HomeKit on Espressif’s ESP32","type":"blog"},{"content":"Welcome to our February Newsletter\nOur News. Our World Join Us!\nHi everyone,\nToday is New Year’s Day, according to the lunar calendar, which we follow here in China. The lunar year from 5 February 2019 until 24 January 2020 is considered to be the year of the pig, which is the twelfth animal in the Chinese horoscope and is regarded as a symbol of wealth and good fortune. On this note, then, we would like to wish you all “新年快乐”, which is transliterated as “xīnnián kuàilè” and translated as Happy New Year!\nIn mid-January, between the Chinese and Western New Year’s Day we spent a weekend in Chongming Island, where we held our annual gathering as a company. On this picturesque island at the mouth of Yangtze River in Eastern China, Espressifers from all our offices across China, Europe and India gathered to contemplate the company’s course in 2018 and discuss its goals for 2019. We spoke about our mission to build bridges between the wider public and technology, particularly in the domains of Artificial Intelligence and the Internet of Things. As a company driving today’s AI and IoT revolution, Espressif Systems will continue supporting research in these fields through investments and partnerships with scholars and institutions whose mission is to promote STEM education in China and beyond.\nOther topics you can find in this month’s newsletter include:\nESP-EYE, Espressif’s newly-released development board for applications relating to Artificial Intelligence and the Internet of Things (AIoT); an announcement of the recent Bluetooth SIG certification for our ESP BLE Mesh SDK which will be released very soon; the new “washMaster”, a cutting-edge laundry machine based on Espressif’s powerful ESP32, which has been developed by Schulthess Maschinen AG in Switzerland; and, last but not least, the exciting one-day event, dedicated to ESP32, which took place in Bangkok last weekend, attracting a large number of makers from all around the country, and highlighting the huge popularity of ESP32 in Thailand. Hope you enjoy reading this month’s newsletter. Keep sending us your messages and requests on Facebook, Twitter, LinkedIn, Instagram and YouTube. We respond to all of your messages as quickly as possible!\nBest wishes, John Lee. Senior Customer Support Officer\nNew AIoT Solution Released # Espressif’s new development board for applications relating to Artificial Intelligence and the Internet of Things has just been released, together with its accompanying SDK, ESP-WHO. Its commercial name is ESP-EYE. This board is based on ESP32, which also integrates a digital microphone, 8 MB of PSRAM and 4 MB of flash. Additionally, it provides an external 2-megapixel camera, which makes the board ideal for face detection, face recognition and speech recognition.\nKeep Reading\nEspressif’s BLE Mesh SDK Is Now Bluetooth-SIG-certified # Espressif is pleased to announce that the ESP BLE-Mesh SDK has been Bluetooth-SIG-certified as of January 2019, having received what was previously known as the BQB certification. This officially ensures that Espressif’s above-mentioned SDK meets the Bluetooth organization’s standards for global product interoperability and complies with the Bluetooth License Agreement.\nKeep reading\n“washMaster”: A Swiss ESP32-based Laundry Machine # Schulthess Maschinen AG is a Swiss company that has produced washing machines and dryers for families, hotels and other commercial enterprises for over 170 years. Their latest pioneering product, “The New washMaster”, is an ESP32-based laundry machine which provides a state-of-the-art solution to cashless payment systems for laundry rooms in big blocks of flats.\nKeep Reading\nPacked Out One-Day ESP32 Event in Thailand # An exciting one-day event took place in Bangkok, Thailand, last Sunday on 3 February. It was dedicated to Espressif’s flagship chip ESP32 and the multiple ways in which it can be used in IoT and AI applications. The event featured prominent speakers from the Thai maker community, attracting scores of attendees.\nKeep Reading\nOriginally published at mailchi.mp.\n","date":"4 February 2019","externalUrl":null,"permalink":"/blog/february-2019/","section":"Blog","summary":"","title":"February 2019","type":"blog"},{"content":"Welcome to our January Newsletter__Our News. Our World__\nHappy New Year everyone!\nWarmest wishes from all of us here at Espressif. May the new year bring you health, happiness and creativity! In 2019 Espressif will continue its expansion in the field of Artificial Intelligence, while also taking its IoT solutions to the next level. Our intention is to continue working hard and remain at the forefront of technological evolution.\nWe said goodbye to 2018 in the best possible way, having received a technological-breakthrough award in December, as a top-10 startup company in Shanghai. The award ceremony took place during a conference about technological achievements in 2018, which was organized by the Shanghai Science \u0026amp; Technology Innovation Center with the support of the local government.\nSo, we’re welcoming 2019 full of energy and hope, as we’re heading to Las Vegas for this year’s Consumer Electronics Show (CES), the world’s biggest event for companies conducting business in the consumer technologies sector. At the 2019 CES we’ll showcase, among others, the Amazon FreeRTOS-qualified ESP32, the Espressif HomeKit SDK, ESP-Mesh, ESP-ADF, Conversational User Interfaces and Alexa on ESP32. At the same time, we’ll be holding several business meetings with clients and potential partners, aiming to familiarize them with our latest solutions in the fields of Artificial Intelligence and the Internet of Things.\nOther news you can read about in\nthis month’s newsletter include:\nWe hope these topics can convey a sense of the variety of products and services that Espressif intends to deliver during 2019. Our company aims to expand the range of its products even further, reach new and bigger markets, and deliver innovative solutions to more people across the world. At the core of these strategic goals are always our customers, our partners and our supporters.\nNothing would be possible without your continuing support.\nSeason’s greetings,\nJohn Lee. Senior Customer Support Officer\nESP-ADF v1.0 Released # Espressif is resolutely expanding in the field of AI solutions, introducing ESP-ADF v1.0 (Espressif’s Audio Development Framework). ESP-ADF is an open-source platform that can be used for developing a variety of audio applications, ranging from connected speakers to story-telling toys. ESP-ADF works on top of ESP-IDF, the commonly-used base SDK for ESP32. ESP-ADF provides flexible and reusable components that allow users to build their own audio-enabled products of varying complexity levels.\nKeep Reading\nESP32 Modules Support LittlevGL and μGFX # ESP32 modules of the WROOM and WROVER series have incorporated two new libraries, LittlevGL and μGFX. LittlevGL is an open-source graphics library providing various features for creating an embedded Graphical User Interface (GUI), with beautiful visual effects and a low memory footprint. μGFX is a lightweight embedded library for displays and touchscreens, providing everything required to build a fully-featured embedded GUI.\nKeep reading\nESP32 Internet Radio Player # Believe it or not, you can now build an Internet radio player in less than ten minutes and with approximately $30! Nick Koumaris and his popular educational platform, educ8s, have come up with this cool project which is based on ESP32. Educ8s consists of a website and a YouTube channel which is dedicated to developing high-quality videos about DIY hardware and software projects.\nKeep Reading\n“U Cup”: The ESP32-Based Smart Water Bottle # Most people think that water contain-ers provide only a good way of keep-ing people hydrated when they are not close to a source of drinking wa-ter. But “Leiyue”, a Shanghai-based startup, has taken water bottles to a whole other level. They have just launched an ESP32-based gadget that combines water bottles with artificial intelligence.\nKeep Reading\nOriginally published at us15.campaign-archive.com.\n","date":"4 February 2019","externalUrl":null,"permalink":"/blog/january-2019/","section":"Blog","summary":"","title":"January 2019","type":"blog"},{"content":"Welcome to our December Newsletter\nHi everyone,\nAs original equipment manufacturers work to squeeze more functionality onto cheaper and smaller IoT devices, they face a series of challenges in development and operations. This whole process results in security vulnerabilities, inefficient code, compatibility issues and unclear licensing. One of the sessions at the recent AWS re:Invent 2018 revolved around the ways in which Amazon FreeRTOS makes building, deploying and updating connected microcontroller-based devices easier, quicker and more economical, while retaining confidence that these devices are secure.\nEspressif’s Director of Technical Marketing, Amey Inamdar, was at AWS re:Invent 2018 and spoke about an IoT solution developed with the help of Amazon FreeRTOS and Pentair, a leading water treatment company. Moreover, the session introduced the OTA and BLE support that has been recently added to Amazon:FreeRTOS. Amey talked about three particular aspects (Security, OTA and Openness) for building connectable products, and how the ESP32 port of Amazon FreeRTOS helps in this regard.\nIn fact, this month’s newsletter explores a bit further, in a separate article, how Espressif’s ESP32-based development boards support BLE in a:FreeRTOS, thus making Espressif one the first platform providers to do so.\nOther news you can read in our December newsletter include: an article about the Paris-based software vendor, MicroEJ, which utilizes ESP32 dev boards to provide a secure platform for designing compact-sized and low-power IoT products with a rich set of features and an improved user experience; Espressif’s presence in Macnica’s booth at the 2018 “electronica”, the biggest international trade fair and conference for electronics, which took place in Munich a couple of weeks ago; and, last but not least, the ultimate Christmas gift, the ESPaper Calendar, based on ESP8266 and developed by ThingPulse!\nNovember was a productive month for Espressif, leading to exciting IoT solutions, collaborations and events. We hope that you can feel our inexhaustible enthusiasm about IoT and AI technology, as it is manifested through our work and the news we are delivering about it in our December newsletter. The calendar year is drawing to a close and we cannot help but reflect on our accomplishments in 2018, thinking that this year has marked one of the most fulfilling, challenging and successful chapters in Espressif’s ten-year history. So, we’ll leave you with an optimistic mood about the future, sending season’s greetings and wishes for a merry Christmas to those of you who celebrate it.\nBest wishes, John Lee.\nSenior Customer Support Officer\nESP32 Supports BLE in Amazon FreeRTOS # At the end of last month, Amazon Web Services (AWS) announced the beta version of Amazon FreeRTOS BLE, a feature that makes it possible for embedded developers to securely connect ESP32 dev boards, or other a:FreeRTOS devices that use Bluetooth Low Energy, to AWS IoT through Android or iOS devices. ESP32 provides one of the first few platforms supporting the BLE feature in a:FreeRTOS.\nKeep Reading\nMicroEJ Now Supports ESP32 Chipsets # MicroEJ is a Paris-based software vendor of cost-effective solutions for embedded IoT devices. It seems that Espressif’s collaboration with MicroEJ was only a matter of time, since both companies are committed to providing secure products in markets where software applications require high performance, compact size, energy efficiency and cost-effective development.\nKeep reading\nEspressif Products at electronica 2018 # The 2018 “electronica”, an international trade fair and conference for electronics, took place in Munich last month and Espressif’s latest series of products were presented by Macnica, Espressif’s distributor in Europe. This was one of the most important events in the electronics industry, as more than 3,100 exhibitors from over 50 countries provided an insight into the electronics of the future with their solutions and products. It was the biggest gathering in the history of this event which is held in Munich every two years since 1964.\nKeep Reading\nThe ESPaper Calendar App # Christmas is fast approaching and we couldn’t think of a better gift than the ESPaper Calendar App from ThingPulse. Recently, Marcel and Dani have been hard at work to deliver a new application for their 2.9\u0026quot; ESPaper Plus Kit, the ESPaper Calendar. It lets you manage shared resources such as meeting rooms and shared desks by connecting it to a cloud calendar.\nKeep Reading\nOriginally published at mailchi.mp.\n","date":"4 December 2018","externalUrl":null,"permalink":"/blog/december-2018/","section":"Blog","summary":"","title":"December 2018","type":"blog"},{"content":"Welcome to our November Newsletter\nHi everyone,\nNovember has already started, but we’re still in a Halloween mood. Luckily it’s not just us! Tricksters and treaters were not simply carving pumpkins and wearing spooky outfits on October 31st. They were also using ESP32 to make their Halloween costumes even more horrifying!\nWhat’s scarier than a pair of Uncanny Eyes ? Well, the obvious answer is five pairs of Uncanny Eyes mounted on skulls and controlled in a way that makes everyone scream. Laurent did exactly that and posted the project on hackster.io. Powered by ESP32-DevKitC, Uncanny Eyes achieve maximum effect when they are attached to the bust of a Halloween skull costume. The wearer of the costume seamlessly controls the uncanny eyes, as they transition from random motion to coordinated movements via a hidden device with an analog joystick and buttons.\nApart from Halloween, what kept us excited last month was the release of ESP-WHO , which is Espressif’s face detection and recognition platform based on ESP32. You will find ESP-WHO to be most helpful if, for example, you want to build a\ncoffee machine which will be able to recognize your face when using it, so that it gives you the kind of coffee that matches your taste; or when you want to control a home appliance that will shut down automatically upon recognizing that unsupervised children are in the vicinity. If you want to learn more about ESP-WHO, click on here.\nOther news you can find in this month’s newsletter includes Espressif’s representation at the IoT/M2M Expo in Japan, which took place on October 24–26; “Bob” , a French mini dishwasher powered by ESP32; the Hackaday Super-conference which takes place in Pasadena on November 2–4, featuring Espressif’s Software and Technical Marketing Manager, Jeroen Domburg , as an invited speaker; and, finally, the continuing ESP32 Bug Bounty Program .\nHope you enjoy reading the November edition of our newsletter. Keep sending us your comments and requests on Facebook, Twitter and Instagram. We respond to all of your messages as quickly as possible!\nasdf\nBest wishes, John Lee.\nSenior Customer Support Officer\nESP Solutions at Japan’s 4th IoT/M2M Expo # Espressif’s distributor in Japan, Midoriya Electric, participated in the 4th IoT/M2M Expo, in Makuhari Messe, which took place on October 24–26. This was part of Japan’s IT Week, which is a world-leading IT show that has become the most comprehensive business-to-business IT exhibition in Japan. This year the show was the biggest one in its history, in terms of the number of exhibitors and professional visitors from the industry. asdf\nKeep Reading\nMini Dishwasher Powered by ESP32 # “Throw in the sponge. Adopt Bob!” This is the motto of Daan.Tech, a French start-up whose goal is to usher in a new era of smart home appliances. Bob is a newly-designed ultra-compact dishwasher which offers the ultimate solution for people with space-constrained kitchens and an irreversible aversion to washing dishes by hand. Needless to say, of course, that “Bob” is built around Espressif’s powerful ESP32-WROOM-32 module, which can bring to life a variety of projects, ranging from low-power sensor networks to the most demanding tasks.\nKeep reading\nEspressif at the Hackaday Supercon 2018 # Every year, the Hackaday Super-conference attracts huge numbers of hardware hackers, makers, engineers and enthusiasts from around the world. Hundreds of people gather for the organized talks and workshops, as well as the unplanned challenges, conversations and discoveries that make Supercon the ultimate hardware conference.\nKeep Reading\nThe ESP32 Security Bug Bounty Is Still On! # Do you like searching for security bugs? Do you want to earn some extra cash? Are you a fan of Espressif Systems and ESP32? If the answer to all these questions is positive, then you should definitely consider participating in our bug-reporting program, the ESP32 Security Bug Bounty! We had a similar program about ESP8266, which lasted from March 2015 until July 2018. Our ESP32 Bug Bounty started in March 2017 and is still on!\nKeep Reading\nOriginally published at mailchi.mp.\n","date":"11 November 2018","externalUrl":null,"permalink":"/blog/november-2018/","section":"Blog","summary":"","title":"November 2018","type":"blog"},{"content":" Note (as of Sep 2025):\nThis project is no longer actively maintained. The information in this article is provided for archival and reference purposes only, and developers are encouraged to explore Espressif’s latest solutions for voice-enabled applications. Espressif’s Alexa SDK makes building Alexa-powered devices a breeze. These devices have microphones and speaker embedded within the device to provide the full Alexa experience. Alexa features like Conversation, Music Services, Alerts and Reminders are all supported within the SDK. The SDK also provides references phone apps that let you configure the device for the first time.\nWe support two types of Alexa built-in device SDKs:\nUsing Espressif’s Alexa Voice Services SDK : Ideal for building Alexa-enabled speakers with support for Bluetooth A2DP Sink, A2DP Source, DLNA among other features. Amazon-certified speakers using this SDK are already launched in the market. Using Espressif’s SDK for AVS for AWS IoT : Ideal for smart-devices with Alexa built-in capability. This SDK implements Amazon’s AVS integration for AWS-IoT. The same AWS-IoT connection is shared for voice exchange, as well as the smart device’s data exchange. This is fully Amazon-qualified and listed on their dev-kits page here: https://developer.amazon.com/en-US/alexa/alexa-voice-service/dev-kits#smart-home-dev-kits. We have certified solutions with DSP-G’s DBMD5P SoC and Synaptics CNX20921 SoC. These DSPs run the Wake-word engine that captures the local “Alexa” utterance.\nThe SDK is available at: https://github.com/espressif/esp-va-sdk\nSome relevant articles:\nAnatomy of a Voice-Integrated Device Espressif’s AVS SDK Release Announcement Espressif’s SDK for AVS integration for AWS IoT ","date":"24 October 2018","externalUrl":null,"permalink":"/blog/alexa/","section":"Blog","summary":"","title":"Alexa","type":"blog"},{"content":" Amazon FreeRTOS is an operating system for microcontrollers that extends the FreeRTOS kernel with libraries that make it easy to connect devices to AWS services like AWS IoT Core and AWS GreenGrass. ESP32 is a certified and fully supported platform for Amazon FreeRTOS.\nSome relevant articles:\nAmazon FreeRTOS and ESP32 Managing OTA Firmware Upgrades ","date":"24 October 2018","externalUrl":null,"permalink":"/blog/amazon-freertos/","section":"Blog","summary":"","title":"Amazon FreeRTOS","type":"blog"},{"content":" Espressif’s HomeKit SDK is a fully certified SDK that conforms to the latest HomeKit specification. The SDK is engineered to expose an easy to use API, while also being flexible enough to create a variety of accessories and bridges. Espressif supports the entire workflow from development to certification and manufacturing. This way you can focus on your product, and let the SDK manage HomeKit conformance.\nThe SDK is available at:\nApple’s HomeKit ADK: https://github.com/espressif/esp-apple-homekit-adk Espressif’s HomeKit SDK: https://github.com/espressif/esp-homekit-sdk More Details:\nHomeKit On Espressif’s ESP32 ","date":"24 October 2018","externalUrl":null,"permalink":"/blog/apple-homekit/","section":"Blog","summary":"","title":"Apple HomeKit","type":"blog"},{"content":" If you wish to define your own conversation with your product, this solution is for you. Integrations with Amazon Lex and Google DialogFlow helps you create intuitive conversations between your device and its user.\nBuilding Audio Conversations with ESP32: https://medium.com/the-esp-journal/embedding-voice-into-devices-with-esp32-107d9211633c Please reach out to sales@espressif.com for more details.\n","date":"24 October 2018","externalUrl":null,"permalink":"/blog/conversational-interfaces/","section":"Blog","summary":"","title":"Conversational Interfaces","type":"blog"},{"content":" Use Espressif’s IoT Development Framework to build a complete product. Right from network configuration, to local or remote access, OTA firmware upgrades, certification and manufacturing, we have got you covered. You may refer to ESP-Jumpstart for more details.\nSome other relevant articles:\nDevelopment:\nEclipse Plugin for ESP-IDF Features:\nLocal Network Access Footprint Analysis Security:\nESP32 and Security TLS (Transport Layer Security) Certification:\nUnderstanding Wi-Fi Certification Manufacturing:\nCreating Unique Factory Data Images ","date":"24 October 2018","externalUrl":null,"permalink":"/blog/esp-idf/","section":"Blog","summary":"","title":"ESP-IDF","type":"blog"},{"content":" TLS is the security component in the familiar *https protocol, *that we rely on for security on the Internet. A TLS connection between a device and the server ensures that the data exchange between them is secured from the multiple threats possible over an untrusted medium. The TLS connection typically includes mutual authentication of the communicating parties, secure key exchange, symmetric encryption and message integrity checks.\nAs a recommendation, all the communication between a device and a remote server (cloud) must use TLS. Although the TLS layer will take care of all the components involved in the secure communication, as a device maker, you have to be aware of a few things while you are using the TLS session. Let’s quickly look at these:\nCA Certificates (Server Validation) # The TLS layer uses a CA certificate to validate that the server is really who it claims to be. Say your device needs to talk to aws.amazon.com. The CA certificate ensures that you are really talking to aws.amazon.com and not somebody who is impersonating (DNS Spoofing) them.\nDuring a TLS session establishment, the server presents a certificate to the device. One of the pieces of information encoded in this certificate is the server’s domain name (aws.amazon.com). This server’s certificate is signed by a CA (Certifying Authority). A CA certificate (different from the server’s certificate) present on the device helps validate this signature. If the signature is valid, then the server’s certificate is valid, and hence the domain name encoded in the certificate is valid. The TLS layer then ensures that this domain name in the certificate matches the domain name that we have connected to.\nA TLS connection typically expects a CA certificate to be passed to it as a session establishment parameter. For example in the ESP-IDF, this is the cacert_pem_buf parameter in the *esp_tls_cfg_t *structure.\nesp_tls_cfg_t cfg = { .cacert_pem_buf = server_root_cert_pem_start, .cacert_pem_bytes = server_root_cert_pem_end - server_root_cert_pem_start, };struct esp_tls *tls= esp_tls_conn_http_new(\u0026#34;https://aws.amazon.com\u0026#34;, \u0026amp;cfg); In the code above, the server_root_cert_pem_start points to the start of the CA certificate that is embedded in the device’s firmware.\nNot specifying the certificate here implies that the server certificate validation check will be skipped.\nObtaining a CA Certificate # If your server is hosted on a cloud infrastructure, your https endpoint will likely already have a certificate signed by some CA. In this case, you could fetch the CA certificate for your server’s endpoint using the following command:\n$ openssl s_client -showcerts -connect hostname:443 \u0026lt; /dev/null This prints out a list of certificates. The last certificate is the CA certificate that can be embedded in the device’s firmware.\nSelf-Signed Certificates # Typically server certificates are signed by a CA like Verisign. But you also have the option of using your own key-certificate pair to sign the server’s certificate. This is the self-signed certificate.\nYou may have your reasons to do this (your cloud provider charges you for certificates with your own domain name, you want to have more control your infrastructure etc). The following two things need to be noted in this context:\nThe onus of protecting the private key is now on you Self-signed certificates work as long as the client (in this case your device) is under control and you have a means of installing your certificate as a CA certificate on the client. For example, most web browsers will flag a server with self-signed certificate as a security-risk, since the browsers don’t have your certificate installed as a trusted CA certificate. Updating Certificates on your Device # Once you have the CA certificate embedded in your firmware, you have to make sure you update it when required. Typically, you may have to update the CA certificate\nif you happen to change cloud service providers or your domain names or if your cloud service provider migrates to another CA or if the CA certificate’s time validity is going to expire If your CA certificate is embedded in the device firmware, you can update the CA certificates by doing an OTA firmware upgrade. The new firmware can contain the updated CA certificate to be used.\nSince devices in the field may come and go online based on their usage, it may not be guaranteed that all devices see the firmware upgrade just in time for you to make the switch. It is usually helpful to maintain a period of transition where devices can continue to support multiple CA certificates the old and the new.\nIn the ESP-TLS API above, the *cacert_pem_buf *can point to a buffer that contains multiple CA certificates one after the other. The TLS module will then try to validate the server’s certificate using any of the trusted CA certificates in that buffer.\nDebugging TLS Problems # 1. Memory Requirement # The TLS session takes quite a bit of memory. You should have enough free heap memory while running TLS. Typically one TLS session requires about 5–6KB of additional stack and about 33–35KB of additional heap memory. Please make sure you have enough room in your heap while running the TLS session.\n2. Cipher Suites # During the TLS session establishment the client and server negotiate the best possible cipher suite to be used for the session. Most of the typical cipher-suites supported by the servers these days are already enabled in IDF. But it may happen that some servers use a different combination of ciphers.\nIf your TLS connection fails because of mismatched ciphers you may have to select those specific ciphers in the SDK configuration. This can be done by:\nmake menuconfig --\u0026gt; Component configuration --\u0026gt; mbedTLS --\u0026gt; And then selecting the appropriate ciphers that are missing Note that enabling/disabling cipher suites from the SDK configuration will have a static and dynamic memory footprint impact.\n3. Identifying Certificate Validation Issues # It is likely that once you deploy a CA certificate for verification, the TLS handshake may fail. This typically implies that there is some problem in certificate validation. Usually this may happen if you select the wrong CA certificate for validation. Additional information about the exact reason for failure can be known by using the following calls:\nint flags = mbedtls_ssl_get_verify_result(\u0026amp;tls-\u0026gt;ssl);char buf[100] = { 0, }; mbedtls_x509_crt_verify_info(buf, sizeof(buf), \u0026#34; ! \u0026#34;, flags); printf(\u0026#34;Certificate Verification Failure Reason: %s\\n\u0026#34;, buf); ","date":"24 October 2018","externalUrl":null,"permalink":"/blog/esp32-tls-transport-layer-security-and-iot-devices/","section":"Blog","summary":"","title":"ESP32: TLS (Transport Layer Security) And IoT Devices","type":"blog"},{"content":"","date":"24 October 2018","externalUrl":null,"permalink":"/tags/homekit/","section":"Tags","summary":"","title":"Homekit","type":"tags"},{"content":"","date":"24 October 2018","externalUrl":null,"permalink":"/tags/voices/","section":"Tags","summary":"","title":"Voices","type":"tags"},{"content":"","date":"13 October 2018","externalUrl":null,"permalink":"/tags/building-products/","section":"Tags","summary":"","title":"Building Products","type":"tags"},{"content":"So you have your smart device on your end-user’s home network. Now you would want your user to access your device over the local network. That’s what we will look at in this post.\nLet’s say you are building a smart plug, and you want to toggle the power on or off on your plug. We will create a HTTP URI */power *on your device.\nAn HTTP GET on this URI will give us the current state of the output of the plug. An HTTP POST on this URI will update the output state of the plug. We will create this URI with the following code:\nhttpd_uri_t power_get = { .uri = \u0026#34;/power\u0026#34;, .method = HTTP_GET, .handler = power_get_handler };httpd_uri_t power_post = { .uri = \u0026#34;/power\u0026#34;, .method = HTTP_POST, .handler = power_post_handler }; The *power_get_handler() *and the power_post_handler() are the functions that will get called respectively, whenever an HTTP GET or HTTP POST will happen on the /power URI on the device.\nThen in our application, we can start the web server and register these URIs with the web server as:\nhttpd_handle_t server = NULL; httpd_config_t config = HTTPD_DEFAULT_CONFIG(); // Start the httpd server ESP_LOGI(TAG, \u0026#34;Starting server on port: \u0026#39;%d\u0026#39;\u0026#34;, config.server_port); if (httpd_start(\u0026amp;server, \u0026amp;config) == ESP_OK) { // Set URI handlers httpd_register_uri_handler(server, \u0026amp;power_get); httpd_register_uri_handler(server, \u0026amp;power_post); } Now the power_get_handler() and the power_post_handler() functions could be implemented as:\nesp_err_t power_get_handler(httpd_req_t *req) { char resp_str[100]; snprintf(resp_str, sizeof(resp_str), \u0026#34;{\\\u0026#34;state\\\u0026#34;: %s}\u0026#34;, driver_get_output_state() ? \u0026#34;true\u0026#34; : \u0026#34;false\u0026#34;); httpd_resp_send(req, resp_str, strlen(resp_str)); return ESP_OK; } #define RESP_SUCCESS \u0026#34;{\\\u0026#34;status\\\u0026#34;: \\\u0026#34;success\\\u0026#34;}\u0026#34; #define RESP_FAIL \u0026#34;{\\\u0026#34;status\\\u0026#34;: \\\u0026#34;fail\\\u0026#34;}\u0026#34; esp_err_t power_post_handler(httpd_req_t *req) { char buffer[100]; char *resp_str = RESP_SUCCESS; int remaining = req-\u0026gt;content_len; while (remaining \u0026gt; 0) { /* Read the data for the request */ if ((ret = httpd_req_recv(req, buffer, MIN(remaining, sizeof(buffer)))) \u0026lt; 0) { return ESP_FAIL; } remaining -= ret; } /* Parse input */ target_state = my_parse_user_request(buffer); if (target_state \u0026lt; 0) { resp_str = RESP_FAIL; } else { /* Change the output */ driver_set_output_state(target_state); } /* Send back status */ httpd_resp_send(req, resp_str, strlen(resp_str)); return ESP_OK; } In the *power_get_handler() *routine above, we just fetch the current output state from the driver, and return it in the HTTP GET response.\nIn the power_post_handler() routine above, we fetch the user’s request, and modify the driver’s state as the user requested it.\nUsing the API # For my testing purposes, I could use the following Curl commands to test this implementation:\n$ curl http://192.168.1.113/power {\u0026#34;state\u0026#34;: true} $ curl -d \u0026#39;{\u0026#34;state\u0026#34;: false}\u0026#39; http://192.168.1.113/power {\u0026#34;status\u0026#34;: \u0026#34;success\u0026#34;} For my production scenario, my phone app will make these API calls to query/modify the state of my device.\nSecurity # Using the API as defined above, relies on the Wi-Fi network’s security to secure the data exchange between your phone and the device. So as long as the user has a secured Wi-Fi network, these exchanges will not be visible to entities outside of the user’s network.\nIn case of Wi-Fi networks with Open security, the data will be exchanged in plain-text. You could also use a security layer for exchanging these commands. That is a topic for another article.\n","date":"13 October 2018","externalUrl":null,"permalink":"/blog/local-network-access-via-http-server/","section":"Blog","summary":"","title":"Local Network Access via HTTP Server","type":"blog"},{"content":"Welcome to our October Newsletter\nHi everyone,\nThe beginning of autumn has been marked by a bunch of exciting Espressif-related news. First and foremost, we released the latest version of ESP-IDF v3.1 with improvements on previous features regarding its Wi-Fi and Bluetooth connectivity, as well as its Security Manager Protocol (SMP). At the same time, certain companies in Espressif’s ecosystem introduced new ESP-related features, services and products, including Olimex’s ESP32 DevKit LiPo; Atmosphere’s platform update with Wi-Fi support for ESP32; the Sensything ESP32 board with multi-sensor data acquisition, Wi-Fi and Bluetooth; Zerynth’s combination of IoT and Blockchain, using simple Python on the ESP32-DevKitC; and, last but not least, we also got a sneak peek of the upcoming ESP32-powered watch by Squarofumi on Twitter!\nAdditionally, among the most recent independent ESP8266-based projects that we distinguished were the Pluto Quadcopter by the Indian startup Drona Aviation; a Code-Review Lamp, notifying developer teams of pending code reviews (this one is for the fellow programmers out there!); the Amazon Echo (IR) TV Remote; a Bitcoin-activated power outlet; and an IoT Pool Monitor,\nmeasuring the pH, Oxidation-Reduction Potential (ORP) and temperature of the water. The global community of developers never ceases to impress us with their new and inventive uses of Espressif products!\nOther news you can find in the October edition of our newsletter include the two-day courses on building end-products with ESP-IDF, which we are jointly hosting with Grid Connect in Chicago and San Francisco this month; the release of Espressif’s Alexa SDK, which provides an implementation of Amazon’s Alexa Voice Service for the ESP32 microcontroller; an interview with the best-selling writer and maker, Erik Bartmann, about his latest book on ESP32, *Das ESP32 Praxisbuch *(The ESP32 Practice Book); and an ESP32-powered badge, Ph0xx, which can be easily turned into a bipedal mini robot!\nHope you enjoy this month’s newsletter, and keep sending us your messages and requests on Facebook, Twitter, and Instagram. We respond to all of your messages as quickly as possible!\nBest wishes,\nJohn Lee.\nSenior Customer Support Officer\nESP32 Developer Trainings in the USA # Espressif is partnering with Grid Connect for the first time to host developer trainings on ESP32 in Chicago and San Francisco. These hands-on, in-depth trainings will focus on building end-products using Espressif’s IoT Development Framework (ESP-IDF). These 2-day trainings will cover the latest version of the ESP-IDF (v3.1) and will be given by Espressif engineers.\nAlexa on ESP32 # Espressif’s Alexa SDK has just been released, providing an implementation of Amazon’s Alexa Voice Service for the ESP32 microcontroller. This is meant to facilitate developers to evaluate ESP32-based devices integrating Alexa, such as speakers and IoT devices.\nKeep reading\nNew Book on ESP32 by Best-Selling Author Erik Bartmann # Erik Bartmann is an experienced maker and writer with several bestselling books about programming and electronics under his belt. After the success of *Das ESP8266 Praxisbuch (The ESP8266 Practice Book) *in 2016, Erik gave us its sequel, *Das ESP32 Praxisbuch *(The ESP32 Practice Book), in July 2018. In his usual reader-friendly way, Erik illustrates step by step the great variety of projects that anyone can create with ESP32.\nPh0xx: ESP32 Badge Turned Into Robot # Have you been to a hackathon or a high-tech event lately? Did they give you a digital badge that was interactive, hackable and reusable? Pretty cool, huh? Well, did you actually do something with your badge after the event, or did you put it in a dark desk drawer? If the latter is the case, the ESP32 Badge which can be turned into a bipedal robot might give you some inspiration as to what to do with your own badge.\nKeep Reading\nOriginally published at mailchi.mp.\n","date":"2 October 2018","externalUrl":null,"permalink":"/blog/october-2018/","section":"Blog","summary":"","title":"October 2018","type":"blog"},{"content":"ESP32 now supports secure Over-the-Air firmware updates with Amazon FreeRTOS. This enables users of ESP32 with Amazon FreeRTOS to:\nDeploy new firmware on ESP32 in secure manner (single or group of devices, along with dynamic addition of new/re-provisioned device) Verify authenticity and integrity of new firmware after its deployed Extend OTA update security scheme to take leverage of hardware security features in ESP32 Working # At a high level,\nThe firmware image (or any other partition’s content: filesystem, configuration data), is initially uploaded to an S3 bucket on AWS. An AWS OTA Job with the required certificates (for demo purpose can be self-signed) and code-signing profile (security scheme for ESP32 is ECDSA + SHA256) is setup. On the device side, the OTA agent from Amazon FreeRTOS needs to be enabled in the firmware, along with the certificate that is responsible for verifying the firmware update image (essentially ECDSA public key). The AWS OTA Job then takes the firmware image from the S3 bucket, signs it, and sends it over MQTT+TLS channel in small chunks to the OTA agent on the device. The OTA agent on the device then writes the newly received firmware to its storage and manages the state. At the end, firmware signature gets validated on the device and it gets approved for boot-up. Post boot-up, the OTA agent again interacts with AWS OTA Job for verifying sanity of firmware, and finally the firmware image gets marked as legitimate one, notifying the boot-loader to erase all older firmware instances from the device storage (for not allowing forced rollback). Procedure # Lets quickly walk over the steps for getting the OTA update demo functional on ESP32:\nPlease follow the Getting Started Guide for some of the prerequisites as documented at, https://docs.aws.amazon.com/freertos/latest/userguide/ota-prereqs.html Refer to https://docs.aws.amazon.com/freertos/latest/userguide/ota-code-sign-cert-esp.html for creating code signing profile for the ESP32 platform For downloading firmware to ESP32, refer to https://docs.aws.amazon.com/freertos/latest/userguide/ota-download-freertos.html Once the device boots up, the log should look like the one mentioned at, https://docs.aws.amazon.com/freertos/latest/userguide/burn-initial-firmware-esp.html Create an Amazon FreeRTOS OTA Job (by navigating to IoT Core -\u0026gt; Manage -\u0026gt; Jobs -\u0026gt; Create), Select “Sign a new firmware image for me” option, Create code signing profile, please select ESP32 platform here and provide certificates created earlier, Enabling Hardware Security # The ESP32 port is so structured that the same secure firmware verification mechanism can be used by the ESP32 chipset for enabling secure boot .\nESP32’s secure boot scheme uses the same ECDSA + SHA256 algorithm. Hence the same public key that is used for the OTA firmware image verification can also be used by the bootloader to validate the firmware image on boot-up.\nIt is highly recommended that you use secure boot in conjunction with the OTA firmware updates in your products.\n","date":"30 September 2018","externalUrl":null,"permalink":"/blog/esp32-ota-updates-amazon-freertos/","section":"Blog","summary":"","title":"ESP32 OTA Updates — Amazon FreeRTOS","type":"blog"},{"content":"","date":"30 September 2018","externalUrl":null,"permalink":"/tags/framework/","section":"Tags","summary":"","title":"Framework","type":"tags"},{"content":"The Espressif’s Alexa SDK v1.0b1 is now available on github here: https://github.com/espressif/esp-avs-sdk\nThis is a low-footprint C-based SDK that includes support for all of the following features:\nConversations (Calendar, Shopping, News, Todo, Info, Movies, Sports) Music/Audio Services : Amazon Prime Music, Audible, Kindle, TuneIn and iHeartRadio Alerts : Alarms, Timers, Reminders and Notifications Supported Hardware # By default, the SDK supports ESP32-LyraT development boards.\nThe SDK is so structured that it should be easily possible to support other hardware configurations.\nGetting Started # Instructions for building, flashing and using the firmware are available here.\nHands-Free Mode/Wake-Word Engine # The SDK also supports hands-free mode of operation. The example lyrat_alexa_sr/ is provided that demonstrates the use in a hands-free mode (activity triggered based on saying ‘Alexa’ instead of pushing a button).\nAs discussed in a previous article, Anatomy of a Voice-Integrated Device, multiple configurations are possible given the micro-controller, DSP and the wake-word engine. The example lyrat_alexa_sr/ demonstrates the scenario where the Alexa client as well as the WWE is running on ESP32.\nPhone Apps # The SDK release also includes a phone app for Android for performing (a) network configuration of the development board and (b) Authentication with Amazon. The source code for this app is also available here: https://github.com/espressif/esp-idf-provisioning-android/tree/versions/avs. It can be easily modified to add your Alexa project’s ID and credentials. It can also be easily customized to the branding and look-and-feel of your products.\nProduction Ready # We offer a complete production-ready solution that includes all Alexa features, reference phone app implementations and hardware reference designs. If you are interested in building commercial products with this, please reach out to us.\n","date":"24 September 2018","externalUrl":null,"permalink":"/blog/espressifs-alexa-sdk-v1/","section":"Blog","summary":"","title":"Espressif’s Alexa SDK v1.0b1!","type":"blog"},{"content":"","date":"6 September 2018","externalUrl":null,"permalink":"/tags/esp8266/","section":"Tags","summary":"","title":"Esp8266","type":"tags"},{"content":"","date":"6 September 2018","externalUrl":null,"permalink":"/tags/here/","section":"Tags","summary":"","title":"Here","type":"tags"},{"content":" Hi everyone,\nIt seems that the scorching heat of summer in Shanghai has only fueled our fervor for improving our IoT solutions! We have been hard at work releasing ESP-IDF v3.0.3. This bugfix update is compatible with all apps written for ESP-IDF v.3.0.x. The changes are related to Bluetooth, LWIP, Wi-Fi, System, and Driver. You can check the entire list of changes here, while you can have a look at the ESP-IDF Programming Guide for all the installation instructions.\nAdditionally, we have recently released ESP Mesh, our latest solution to achieving stable and secure Wi-Fi coverage across big spaces. With ESP Mesh, a Wi-Fi hotspot expands to a whole network with many more nodes than in traditional networks. Furthermore, ESP Mesh is a “self-healing” and automatically formed network, which makes it significantly more stable.\nAt the same time, Microsoft announced that its Azure IoT Workbench has started supporting Arduino development on ESP32. This is integrated into Microsoft Visual Studio, while also supporting OTA updates from, and data-processing in, the Microsoft Azure cloud. For more information, you can see Microsoft’s announcement here.\nOn a different note, the 2018 IoT Bootcamp by iBHubs in India, which was partially sponsored by Espressif, came to a grand closure last month. This event comprised ten comprehensive bootcamps on IoT, which received a huge response from 110 institutions\nEspressif Sponsored the IoT Mini-Conf atPyCon AU 2018 # Espressif always tries and supports important events in the international maker community. One of them is PyCon AU, Australia’s national conference for the Python Programming Community. This year it took place in Sydney on August 24th — 28th. Espressif was delighted to be part of this event by sponsoring the one-day mini-conference that was dedicated to the Internet of Things. This eventincluded presentations and demonstrations of how Python powers IoT devices, applications and services.\nKeep Reading\nZerynth Tutorials on ESP32-based Devices # Zerynth is a middleware for IoT and Industry 4.0 solutions. It speeds up IoT development and enables Python for microcontrollers. In recent weeks, Zerynth has been publishing some really interesting articles focused on ESP32-based devices. For instance, their CW02 development board is based on Espressif’s ESP32-WROOM-32 module.\nKeep reading\nWiFiBoy32 # WiFiBoy32 is a portable game console and IoT DevKit based on Espressif’s ESP32-WROOM-32module. The platform also features a pair of 8-pin GPIOs, along with SPI, DAC, I2S, ADC, and VP/VN connections. It also sports six large gaming/multi-purpose buttons, select and start buttons, as well as Program/Reset buttons, a micro USB, and a 2.4-inch (240 x 320) color SPI TFT LCD display.\nKeep Reading\nESP32 WiPhone # A new project presented onhackaday.io has piqued our interest. It is an open-source phone which has been made for placing and transmitting telephone calls over the Internet. It is based on an ESP32microprocessor and runs a type of software that is compatible with Arduino. The ESP32-WiPhone measures approximately 120mm x 65mm x 12mm and has a 2.4” LCD screen.\nKeep Reading\nOriginally published at mailchi.mp.\n","date":"6 September 2018","externalUrl":null,"permalink":"/blog/september-2018/","section":"Blog","summary":"","title":"September 2018","type":"blog"},{"content":"Hi everyone,\nThe ESP32-Azure IoT Kit has been granted a Microsoft certification which makes it integral to Microsoft’s Plug-and-Play program. This has been designed to bring the ease of “Plug and Play” to IoT devices. So, developers can plug virtually any peripheral into a Windows PC without having to worry about drivers. As a result, not only has Espressif been featured as an official partner of Microsoft’s IoT Plug and Play program, but also the ESP32-Azure IoT Kit is now featured on the product list of Microsoft’s Azure IoT solutions.\nAnother exciting piece of news that came in this month was that Norvi, a Sri Lankan IoT company, rolled out its industrial IoT controller (IIOT), which is based on Espressif Systems’ microcontrollers. To provide a value-adding device to a growing market, Norvi designed the Espressif-based IIOT, which ensures high-quality connectivity for industrial IoT applications. Moreover, it comes with the option of either an ESP32-WROOM-32 module or an ESP8266 microcontroller.\nNorvi’s IIOT offers a dual-core 32-bit CPU that achieves a total of 160 MHz. Moreover, this is combined with a 520KB SRAM and a 4MB Flash. Using such a powerful processor ensures that IIOT also conforms to stringent industrial standards.\nOther news you can read in this month’s newsletter include:\nObniz, an all-inclusive IoT platform for ESP32, created by the Japanese company Cambrian Robotics Inc. The obniz solution comprises a dev board, an operating system and cloud services. Measuring particulate pollution with ESP32, which may offer a much-needed solution to a growing number of cities across the globe, where CO2 emissions are, sadly, still on the increase. IoT-based heart monitoring (ECG) with an AD8232 ECG Sensor and ESP32. This is a solution that may prove valuable to thousands of people facing heart problems. Obniz: A New ESP32-based Dev Board, OS and Cloud # Obniz is an ESP32-based development board for IoT applications, functioning over Wi-Fi and Bluetooth (Classic and BLE). The obniz dev board can be connected to the obniz cloud, while it can be controlled in various programming languages and environments. The unique hardware of the obniz dev board is based on the powerful ESP32-WROOM-32, Espressif’s Wi-Fi+BT/BLE module that targets a wide variety of applications.\nESP32-based Measurement of Particulate Pollution # A network engineer from Israel, Nir Huri, has created a project that measures particulate pollution — a cause of concern for many people in the present-day climate crisis. Nir Huri’s gadget measures particulate matter with an SDS011 sensor, while ESP32 functions as the brain of the operation, due to its onboard net-working capabilities.\nIoT-based Heart Monitoring with ESP32 # A useful tutorial which is on the cusp between technology and healthcare has been recently posted by Alex Newton on how2electronics.com. This post is about IoT-based electrocardiographic (ECG) monitoring with an AD8232 ECG Sensor and ESP32, using the online IoT platform Ubidots. It is important to highlight that the ECG signal from a patient’s heart can be checked online from any part of the world.\n","date":"6 September 2018","externalUrl":null,"permalink":"/blog/september-2019/","section":"Blog","summary":"","title":"September 2018","type":"blog"},{"content":"Recently I have seen significant interest from OEMs in embedding voice assistants, like Alexa, directly into their products. Not just linking with a voice-assistant using a cloud to cloud integration, but by having the product itself be voice-enabled (with microphones and speakers).\nFor example, a washing machine with a voice interface for starting it, or a smart switch with “Echo” embedded into it.\nLet us have a quick look at the internal components of a typical Voice-Integrated device. We will take Alexa as an example for this post.\nThe Record Path # When we typically say “Alexa , what is the time”, the word “Alexa” is detected locally, while the rest of the sentence “what is the time” is detected in the cloud (in this case by the Alexa Voice Service). The keyword Alexa in this case is called a Wake-Word .\nThe typical journey of the record path is as shown below:\nThe sounds that the device hears using the microphone are typically processed to perform noise and echo cancellation first.\nThen a wake-word engine processes the sound to detect if a wake-word was spoken. The wake-word engine is typically trained with a sample-set of data with the particular accents that the end-users will utter. When the wake-word engine detects the wake-word it notifies the Alexa client to start processing.\nThe Alexa client now knows that the user has uttered the wake-word, and may be now asking a query. The client then starts capturing the audio stream and sends it up to the cloud.\nThe cloud interprets the user’s command and then instructs the device to stop recording and take the action that the user requested.\nMapping to Hardware # So how do the above components map to typical hardware components? Let’s quickly check below:\nA combination of connectivity processors and digital signal processors can be used to achieve this.\nAs in the diagram above the simplest case is all the components are running on the same host that offers connectivity too. For example, ESP32 can be used to run the algorithms for noise cancellation, the wake-word engine and also the Alexa client to transmit data over Wi-Fi. Since it is a single chip solution this will be the lowest cost solution for the job at hand.\nThen there are options of offloading the echo cancellation/beam-forming or wake-word engine to a dedicated DSP. This combination can be used to optimise for use cases where far-field interactions need to be supported, or where a wake-word needs to be detected while also playing music (barge-in). A DSP could also offer the capacity to load a wake-word engine with a much larger wake-word sample set.\nDepending upon the use-case at hand, the appropriate selection can be made for supporting it in the most effective manner.\nThe Playback Path # In most cases, the playback path is fairly simple.\nIn its simplest form, the playback path consists of the ESP32, acting as a client, fetching the encoded audio data (MP3, AAC etc), decoding it and forwarding the samples to a DAC which then drives a speaker.\nIn case hardware options with DSP are used, the playback stream may also have to be provided to the DSP for performing acoustic echo cancellation. Depending upon the DSP, it can drive the DAC by itself, or the data needs to be duplicated (in hardware or software) for the DSP.\nWe are looking at voice-controlled devices in 2 major ways: a) those with voice assistants (like Alexa) that are running on the ESP32, and b) those with conversational interfaces (like Amazon-Lex or Google DialogFlow). Stay tuned for an upcoming post on these approaches.\nIf you are intereted in building Voice-Controlled Devices with ESP32, we would love to hear about it. Please reach out to sales@espressif.com with the subject line “Voice-Controlled Devices”.\n","date":"12 August 2018","externalUrl":null,"permalink":"/blog/anatomy-of-a-voice-integrated-device/","section":"Blog","summary":"","title":"Anatomy of a Voice-Integrated Device","type":"blog"},{"content":"A fair number of questions come up regarding Wi-Fi certification for Wi-Fi enabled IoT products. Here is an attempt to answer some of the relevant ones.\nWi-Fi certification is a program by Wi-Fi Alliance that ensures that products that pass certification adhere to the interoperability and security requirements as laid out in the standard. It tests for protocol compliance.\nThis is different from regulatory certification (like FCC in the US) which is mandatory since it tests that the electromagnetic emissions from a product are under safe limits.\nIs Wi-Fi certification mandatory for all? # Wi-Fi certification is mandatory if your product will use ‘Wi-Fi certified’ or the ‘Wi-Fi logo’ on the product branding or marketing campaigns. Certain ecosystem programs, like Apple HomeKit, also have Wi-Fi certification as a mandatory requirement. Your organisation must be a member of the Wi-Fi Alliance to have your product tested for Wi-Fi certification.\nDerivative Certification using ESP32 # If you have identified that you require Wi-Fi certification, the quickest path is to use the derivative certification . This certification is applicable if you are using an already certified Wi-Fi module into your product, without any modifications. In such a case, the certification of that Wi-Fi module (called the source), can be directly applied to your product.\nThe benefit of derivative certification is that you won’t have to perform all the Wi-Fi certification tests on your product. You just carry forward the results from the source Wi-Fi module to your product. This saves money and importantly, time, for getting the product certified.\nFor additional details about the derivative certification please refer to the Certifications Overview - Derivative Certificate document on the Wi-Fi Alliance website.\nThe modules ESP32-WROVER and ESP32-WROOM-32D are already certified with Wi-Fi Alliance. If you are using these modules in your product you can use derivative certification for certifying your products. If you are using an ESP32 module from another vendor, please check with them for that module’s Wi-Fi Alliance certification status.\nSteps for Derivative Certification # For any certification, you have to first be a member of Wi-Fi Alliance. Details about membership levels, cost and benefits is available here. Once you are a member, login to the certification system and click on New Derivative Product Certification. Choose the Source Company as Espressif Inc (If you are using Espressif’s WFA certified modules). Choose your organisation’s name as the Target Company. Choose the* Product* that you are deriving from. If you are using Espressif’s WFA certified module, you may use WFA77915 for ESP32-WROVER , or WFA77387 for ESP32-WROOM . Go to the next page:Product Information Mention any changes you may have done to the subsystems as indicated in the page. Go to the next page: Product Designators Fill in the appropriate designators for your product. Select the closest matching Primary Product Category. For example, if your product is a refrigerator, select Refrigerator from the list. If applicable, also select the Secondary Product Category. Go to the next page: Review Application Make sure everything is in order, make the payment and submit the application. The WFA staff will review the submission and if everything is in order, will grant you the Wi-Fi certification. Full Wi-Fi Certification # If you cannot use the derivative certification as mentioned above, you will have to perform the full Wi-Fi certification.\nSteps for Wi-Fi Certification # ","date":"11 August 2018","externalUrl":null,"permalink":"/blog/wi-fi-certification-with-esp32/","section":"Blog","summary":"","title":"Wi-Fi Certification with ESP32","type":"blog"},{"content":" Fake News About Espressif Systems…Again! # Espressif Systems’ PR and Media Department emphatically states that the rumor about our company’s acquisition by the Alibaba Group is entirely fake. Unfortunately, the same rumor surfaced on Chinese social media earlier this year, on April 20th. This piece of fake news was repeated by toutiao.com on August 6th.\nNew Espressif Module ESP32-WROVER-B # We are delighted to announce that a new module from Espressif Systems, ESP32-WROVER-B, has just been released. With 8MB of PSRAM, the ESP32-WROVER-B module marks a big improvement over ESP32-WROVER and ESP32-WROVER-I. This is part of Espressif’s strategic plan to continue developing new capabilities for its IoT solutions. Our goal is to stay competitive and attractive within the growing IoT ecosystem, while keeping our prices as low as possible, so that the Internet of Things becomes accessible to everyone.\nKidBright32: An ESP32-based Dev Board for Thai Schoolchildern # Thailand’s Ministry of Education has recently launched an initiative to boost the country’s electronics education, creating a development board which is based on Espressif Systems’ ESP32-WROOM-32 WiFi-and-Bluetooth module. This follows the example of other similar initiatives, such as the ESP8266-based Kniwwelino in Luxembourg and the BBC Micro:Bit in the UK.\nZerynth and XinaBox’s Innovative IoT Toolkit Built Around ESP32-WROOM-32 # A new IoT development kit that is programmable with Zerynth, the XK12 IoT Starter Kit, is designed to simplify building electronic devices. By combining the XinaBox modular electronics with an ecosystem of software tools in Python, development time, speed to market and costs are expected to be significantly reduced. The XK12 IoT Starter Kit has been built around Espressif’s ESP32-WROOM-32 module. Powered by Espressif’s flagship SoC, ESP32-WROOM-32 features high performance, a wide range of peripherals, as well as Wi-Fi and Bluetooth connectivity. It is a complete solution tailored to advanced IoT applications\nESP32-based Cereal Distribution Machine # Cereal lovers, rejoice! This article is for you. Kevin Obermann and Adrian Bernhart have put their engineering skills to good service, ultimately taking their love for cereals to a whole different level. They created a carousel of cereals, which mixes and matches customized breakfast blends.\nGreenhouse Alarm System with ESP8266 \u0026amp; Ubidots # Is your lifestyle too busy to allow you to have the kitchen garden you always wanted? A young maker, Valerie Odioh, has combined the technology offered by ESP8266 and Ubidots, ultimately creating a green IoT solution that you cannot but find useful!\n“Nero”: An ESP8266-powered Smart Glove That Controls Remote Devices # Varun Sharman, Jival Jenson and Shijith Mathew are a team of young engineers who have created a smart glove that can control devices from a distance. This project is based on the power of ESP8266, which is a highly-integrated Wi-Fi solution that is capable of functioning consistently even in industrial environments with extreme temperatures.\n","date":"6 August 2018","externalUrl":null,"permalink":"/blog/august-2018/","section":"Blog","summary":"","title":"August 2018","type":"blog"},{"content":" Espressif Mentioned in Gartner’s Report for the Third Consecutive Year # It was with great delight that we received the news about Espressif being mentioned in Gartner’s 2018 IoT “Thingification” report, authored by analysts Amy Teng, Bill Ray, George Brocklehurst and Jon Erensen. Gartner’s expert-led, practitioner-sourced and data-driven research is trusted as an objective resource in the IoT industry and beyond. Gartner awarded Espressif the “Cool Vendor” title in 2016 and for each of the subsequent two years our company has been included in the follow-up report “Where Are They Now?”\nNew Espressif Module ESP32-SOLO-1 # We are delighted to announce that a new module from Espressif Systems, ESP32-SOLO-1, is now at the stage of mass production. Releasing this module is part of Espressif’s strategic plan to continue developing new capabilities for its IoT solutions. Our goal is to stay competitive and attractive within the growing IoT ecosystem, while keeping our prices as low as possible, so that the Internet of Things becomes accessible to everyone.\nGreat Success for the AWS Workshop with ESP Dev Boards # At the end of last month, Amazon Web Services (AWS) partnered with Espressif to host a one-day IoT Workshop in San Francisco. The event was focused on using Amazon FreeRTOS with Espressif’s ESP32-DevKitC. The event attracted the interest of many embedded engineers who managed to successfully complete hands-on activities, such as running the a:FreeRTOS Sample Code, using the AWS IoT Core and Device Shadows, as well as interacting with devices through a web interface.\nEspressif Sponsors Prizes for iBHub’s IoT Bootcamps in India # Espressif Systems is renowned not only for its fast, secure and green IoT solutions. Our technology-oriented development strategy is coupled with out commitment to young people’s electronics education. We also sponsor hackathons, workshops and bootcamps through which we are reaching out to graduates and young makers in China and beyond. A recent example is our product sponsorship of India’s iBHub, which organizes IoT bootcamps and other events aiming to develop a culture of innovation and entrepreneurship across India.\nESP8266-Spotify Remote Control # In the European Union’s 2018 Innovation Scoreboard, Luxembourg ranked among the “Innovation Leaders” for the first time, along with such countries as Sweden, the Netherlands and the United Kingdom. One recent example of Luxembourg’s research innovation is “Kniwwelino”, an ESP8266-based development kit for young children.\nOriginally published at mailchi.mp.\n","date":"4 July 2018","externalUrl":null,"permalink":"/blog/july-2018/","section":"Blog","summary":"","title":"July 2018","type":"blog"},{"content":" Preface # Amazon FreeRTOS is the latest offering (after acquisition of FreeRTOS) from Amazon that tries to simplify cloud connectivity with Amazon services (e.g. Shadow, Green-grass etc.) It has support for multiple micro-controller platforms from different vendors. Our ESP32 is now officially supported in Amazon FreeRTOS.\nIn this article we will discuss about —\nESP32 integration in Amazon FreeRTOS (using existing ESP-IDF ) Getting Started with ESP32 using Amazon FreeRTOS Architecture # Let us dig deeper in architecture of this offering in the context of ESP32 -\nUpstream or vanilla FreeRTOS had no support for theESP32 architecture (Xtensa LX6 dual core CPU). Support for this architecture is now available in the FreeRTOS V10 kernel . As of now it only supports single core mode of operation. A slightly modified version of the ESP-IDF is part of the Amazon FreeRTOS SDK itself. This IDF has all the required components including, hardware abstraction layer, Wi-Fi driver and other components that do not conflict with the ones already available in Amazon FreeRTOS SDK (e.g. Networking Stack, TLS stack etc.). Such a self contained package allows easier certification process as well. The WiFi portability layer acts as an abstraction, providing consistent application interface between different vendor platforms. Mostly the API for this layer helps in Wi-Fi interface/state management (Station and SoftAP) and power management. Another abstration layer is the secure socket layer shown above. It provides consistent application interface between different vendor’s network platforms (some of the vendors use custom Networking Stack) and interfacing with the mbedTLS stack. Qualification # The Amazon FreeRTOS Qualification Program (Amazon FQP) is for microcontroller (MCU) vendors for qualifying platforms (not SoC itself), and both ESP32-DevKitC and ESP-WROVER-KIT are certified in the latest release.\nFor more information please refer to, https://aws.amazon.com/freertos/partners/\nGetting Started # Please refer to the official Getting Started Guide on the AWS website for latest instructions on working with Amazon FreeRTOS: https://docs.aws.amazon.com/freertos/latest/userguide/getting_started_espressif.html\nExamples # Please refer to https://docs.aws.amazon.com/freertos/latest/userguide/freertos-mds-projects-struct.html for navigating to examples, primarily includes:\nMQTT — Client that both subscribes to and publishes to the same MQTT topic, as a result of which each time the MQTT client publishes a message to the remote MQTT broker, the broker sends the same message back to the client Shadow — Simple lightbulb example to illustrate how client application and things communicate with the Shadow service Greengrass — Simple example that performs discovery of AWS greengrass core device Future Road-map (Near Term) # Support for secure OTA updates using AWS is in Beta phase, please refer to, https://docs.aws.amazon.com/freertos/latest/userguide/freertos-ota-dev.html\nThis is certainly very important feature and as it evolves, all qualified vendors will support this, including Espressif.\nThis is still at early stage, please stay tuned as expecting some exciting road-map (with potential of use-cases it can cover) here!\n","date":"19 June 2018","externalUrl":null,"permalink":"/blog/amazon-freertos-esp32-support/","section":"Blog","summary":"","title":"Amazon FreeRTOS — ESP32 Support","type":"blog"},{"content":" Welcome to our June Newsletter!\nHi everyone,\nOur campus recruitment program for 2019 has already started, while we also accept university graduates and experienced professionals during summer 2018. We are delighted to be able to offer several job opportunities to applicants interested in working for our Research and Development, Engineering, Information Technology, Marketing, Business Operation, Documentation, and Human Resources Departments in our Chinese offices and abroad (Pune and Brno branches).\nSuccessful candidates will join teams of specialists in chip design, software/ firmware development, business development and marketing. At Espressif Systems we are passionate about creating state-of-the-art chipsets and enabling our customers to deliver innovative products. Espressif Systems is a multi-national IoT company with a growing business cycle both in China and abroad. This allows us to offer competitive salaries, annual bonuses, comprehensive medical care and health insurance packages, continuing professional development\nprograms and many more benefits. All this happens in a positive work environment that encourages collaboration, communication and technological innovation.\nFurthermore, Espressif Systems is an equal opportunities employer and considers all applicants on the basis of individual merit, regardless of their race, national and ethnic origin, color, religion, age, disability, marital and pregnancy status, gender identity, sexual orientation and any other legally-protected status.\nBased on our recent funding from Intel Capital and the Beijing Singularity Power Investment Fund L.P. (SPC), our aim for 2018 is to expand the range of our products, reach new and bigger markets, and deliver our innovative IoT solutions to more people across the world. Our customers, our partners and our supporters are always at the core of our strategic goals. Nothing would be possible without them.\nBest wishes, John Lee\nSenior Customer Support Officer\nIoT Seminars by Espressif India in Pune # The Indian branch of Espressif Systems is only a few months old, but it is already highly active, organizing IoT seminars for the local community of developers in Pune. The last session was held at the end of May and it focused on FreeRTOS. Due to popular demand, there will be a complementary session on Saturday , June 9th , from 10:00am to 1:00pm , which aims to cover the wide range of questions that could not be tackled during the first two-hour session. Places are limited, so register now to make sure you can attend this seminar.\nESP8266-based DIY Model Airplane # Imagine you are an aviation enthusiast and you have less than 15 US dollars to spend on your hobby. What can you do? Well, an ESP8266-based IoT solution might be just right for you! Ravi Butani, an electronics engineer from India, has devised a remote-controlled light-weight DIY aircraft, combining his passion about electronics and aviation. What’s more, his project relies on the power of ESP8266.\n“La Cool Co.” Wins 2nd Prize at VivaTech 2018 # There is considerable media hype surrounding cryptocurrencies nowadays, not least due to the volatility of their value. Those who have invested in them need to instantly get the latest updates on their value, so that they can plan their next moves accordingly. In response to this reality, Igor Fonseca Albuquerque has created a highly versatile gadget that is based on ESP32.\nESP32-based Smart Wallet # There is considerable media hype surrounding cryptocurrencies nowadays, not least due to the volatility of their value. Those who have invested in them need to instantly get the latest updates on their value, so that they can plan their next moves accordingly. In response to this reality, Igor Fonseca Albuquerque has created a highly versatile gadget that is based onESP32.\nOriginally published at mailchi.mp.\n","date":"5 June 2018","externalUrl":null,"permalink":"/blog/june-2018/","section":"Blog","summary":"","title":"June 2018","type":"blog"},{"content":"[This document discusses security features for ESP32v3. If you are looking for the security features of the latest ESP32-S2 SoC, that article is available here.]\nThe ESP32v3 has two interesting features, secure boot and flash encryption. Let’s have a quick overview of these features.\nTypically when a device is shipped, any firmware or data is stored in the SPI flash connected to the ESP32v3. Since typically flashes are external to the SoC, a sufficiently inclined person could read the contents of this flash if she so desires for their benefit. What’s more, the contents could also be modified or tampered with to affect the flow of execution.\nThe flash encryption and secure boot features protect from the side-effects of these types of unwanted accesses to the flash.\nThe eFUSE: One Time Programmable # The eFUSE plays an important role in the functioning of these security features. So let’s quickly look into the eFUSE before we get into the security features.\nThe ESP32 has a 1024-bit eFUSE, which is a one-time programmable memory. This eFUSE is divided into 4 blocks of 256-bits each.\nOf primary interest to us right now are blocks 1 and 2. These blocks store keys for flash encryption and secure boot respectively. Also, once the keys are stored in the eFUSE, it can be configured such that any software running on ESP32 cannot read (or update) these keys (disable software readout ). Once enabled, only the ESP32 hardware can read and use these keys for ensuring secure boot and flash encryption.\nSecure Boot # The secure boot support ensures that when the ESP32 executes any software from flash, that software is trusted and signed by a known entity. If even a single bit in the software bootloader and application firmware is modified, the firmware is not trusted, and the device will refuse to execute this untrusted code.\nThis is achieved by building a chain of trust from the hardware, to the software bootloader to the application firmware.\nValidating the Software Bootloader # The Bootloader image, as stored in flash, contains the following logical parts:\nBootloader Image: This is the bootloader executable that contains the bootloader RSA Signature: This is the RSA3072 based signature of the bootloader image. RSA 3072 Public Key: The public key that can be used to validate the signature. The validation progresses as follows:\nThis way, it is validated that the bootloader is trusted. The RSA private key that was used to generate the signature is kept safely with the manufacturer.\nValidating the Application Firmware # In the previous step, the Bootloader is confirmed to be trusted. Once trust is established, the BootROM transfers execution control to the Bootloader.\nThe Bootloader will now, in turn, validate the Application Firmware. The validation of application firmware is exactly similar to that of the bootloader as shown below.\nAnd that’s how secure boot on ESP32 works.\nFlash Encryption # The flash encryption support ensures that any application firmware, that is stored in the flash of the ESP32, stays encrypted. This allows manufacturers to ship encrypted firmware in their devices.\nWhen flash encryption is enabled, all memory-mapped read accesses to flash are transparently, and at-runtime, decrypted. The flash controller uses the AES key stored in the eFUSE to perform the AES decryption. Similarly, any memory-mapped write operation causes the corresponding data to be transparently encrypted before being written to flash.\nBecause the key is locked into the eFUSE, only the hardware can use it to decrypt the contents of the flash.\nDisabling JTAG/UART Boot # The eFuse has one-time programmable bit fields that allow you to disable support for JTAG debugging, as well as the support for UART Boot. Once disabled, these features cannot be re-enabled on the device under consideration.\nPrevious versions of ESP32\nThe previous versions of ESP32 (prior to ESP32v3), did not support RSA. This is called Secure Boot v1 (as opposed to Secure Boot v2 supported in ESP32v3 onwards).\nIf you are looking for network security using TLS (Transport Layer Security), please go to this article: TLS and IoT.\nIf you are looking for more information or would like to try it out, please head over to the step-by-step documentation for Secure Boot and Flash Encryption.\n","date":"31 May 2018","externalUrl":null,"permalink":"/blog/understanding-esp32s-security-features/","section":"Blog","summary":"","title":"Understanding ESP32’s Security Features","type":"blog"},{"content":"Back in late 2017, when Amazon launched their C++ SDK for Alexa, we thought it would be fun to port the SDK on ESP32. It not only will showcase the powerful development tools and execution environment that ESP32 currently has, but it will also be a great way to run Alexa on ESP32.\nWe recently launched a beta preview of this Alexa on ESP32 on github.\nThe Alexa C++ SDK is targetted for micro-processores, and is quite heavy to be run on micro-controllers. We wanted to see what kind of a load would it generate on ESP32. Thankfully, the hardware (ESP WROVER module) and the software development framework (IDF) were very robust to support such performance intensive use case. Here are some details:\nThreads # In a normal Wi-Fi connected state, the ESP32 typically forks about 13 threads for its operation. These include threads for Wi-Fi, the network stack, application threads among other things.\nIn the normal Alexa operation, the SDK forks a whopping 47 threads (inclusive of the 13 threads above) to get the job done. All these threads merrily co-ordinate with each other on the ESP32’s two cores performing audio record, transmit, receive, decode and playback operation.\nMemory # All these threads need to have their stacks in memory. Additionally, we need significantly large ring buffers for audio record and playback. And then there’s 2 TLS connections (one for HTTP2 for the primary Alexa communication, and the other for HTTP1.1 managing OAuth).\nThe SPIRAM (external SPI memory) is heavily used for many of these buffers and thread stacks. Although being accessed over SPI (and hence relatively slower than the main memory), the caches on the ESP32 ensured that we did not see an end-user visible degradation.\nIn terms of memory, we try to keep around 15–20KB of free main memory, and the SPIRAM is about half-way (2MB) full.\nFootprint # Given the footprint constraints of the platform, and the size of the Alexa CPP SDK, we had to make sure we know what component added how much to the static memory footprint . And then optimize components that added too much. The idf_size.py utility in IDF was a very important tool to identify and check which libraries are adding to the static footprint, and what can be optimized out.\nA bountiful path # Additionally, we made a few minor modifications to better support some of the usecases. Listing them down here, if you find them useful.\nAlexa requires an HTTP/2 connection with their cloud. So we started with the HTTP/2 client (nghttp2) that is part of IDF. The nghttp2 library is very flexible with its multitude of callbacks. Because of the flexibility though, as you start using it, it is easy to miss the forest for the trees. So we created a tiny layer on top of that called sh2lib (simple-http2 library). As with any simplifying layer, it does offer simplicity at the cost of flexibility. But by using this simplification we could keep the code more organised, as in this example. Maybe that simplicity-flexibility tradeoff is not for everyone, so it’s kept into the IDF’s *examples/ *section for now.\nThe next stop was TLS . We created a layer esp-tls on top of mbedTLS. This layer encoded the common tasks of setting up a TLS session and performing data exchange on this session. Apart from simplicity the layer should try to ensure that it chooses the default secure configurations with minimal scope of error. This was to avoid situations like, *Oh I forgot to perform server certificate validation, *or Oh I didn’t setup CN verification. This layer is also now a part of IDF.\nIDF already includes C++ development support. The Alexa CPP SDK extensively uses features (C++11 included) like threads, shared-locks, smart-pointers, futures and lambda expressions from IDF.\nAll in all, the hardware and software platforms have been robust and comprehensive to meet these demands thrown at it. We will continue to improve it even further. It’s been an exciting project to work on.\n","date":"18 May 2018","externalUrl":null,"permalink":"/blog/running-alexa-cpp-sdk-on-esp32/","section":"Blog","summary":"","title":"Running Alexa CPP SDK on ESP32","type":"blog"},{"content":"The ESP32 is equipped with a 512KB of SRAM. While this may seem quite small, it can pack a lot of punch in this compact form if used well.\nAs we use the various components and its features in our application firmware, the linker pulls in different functions and variables from these components. The linker will typically optimise out entities that aren’t being used (or referenced) from the current application firmware. So, depending upon what you do in your application, the contribution from various components to your footprint changes.\nThe IDF provides a utility, idf_size.py, that lets you peek into the footprint utilisation so you could identify and optimise the relevant bits. The utility is also linked with the build scripts so you could directly run make targets to look at the footprint without having to remember a number of commands.\nLet’s look at some quick ways how this can be used to look at the effective static footprint.\nPer-Component Size # One way to look at the static footprint is to look at what impact every component has on your final firmware image. This can be done using the size-components target of the build system. Executing this target after building the examples/wifi/power_save application shows me the following output:\n$ __make IDF_PATH=~/work/idf size-components__ Total sizes: DRAM .data size: 14200 bytes DRAM .bss size: 23224 bytes Used static DRAM: 37424 bytes ( 143312 available, 20.7% used) Used static IRAM: 62344 bytes ( 68728 available, 47.6% used) Flash code: 368546 bytes Flash rodata: 65916 bytes Total image size:~ 511006 bytes (.bin may be padded larger) Per-archive contributions to ELF file: __Archive File DRAM .data \u0026amp; .bss IRAM Flash code \u0026amp; rodata Total__ libnet80211.a 1976 8891 3358 92337 10206 116768 liblwip.a 19 3865 0 72280 14962 91126 libpp.a 855 6339 13035 40707 7311 68247 libc.a 0 0 0 55343 3889 59232 libphy.a 1334 869 4584 29104 0 35891 libesp32.a 2685 436 8067 10719 7388 29295 libwpa.a 0 682 0 20314 2320 23316 libfreertos.a 4148 776 12215 0 1595 18734 libnvs_flash.a 0 32 0 9497 2705 12234 libgcc.a 4 20 104 9899 848 10875 ...upplicant.a 0 0 0 9492 4 9496 ...spi_flash.a 36 323 6465 912 1724 9460 libheap.a 876 4 3390 1123 996 6389 libdriver.a 24 4 0 883 4990 5901 libsoc.a 669 8 3841 0 1239 5757 libcoexist.a 1277 94 3344 0 137 4852 libstdc++.a 8 20 0 2613 1253 3894 libmbedtls.a 0 0 0 3109 320 3429 ...p_adapter.a 0 124 0 2578 316 3018 libvfs.a 40 63 0 2212 417 2732 libnewlib.a 152 252 750 463 95 1712 libpthread.a 16 12 178 770 655 1631 liblog.a 8 268 438 396 166 1276 libmain.a 0 0 0 574 643 1217 libcore.a 0 5 0 709 402 1116 librtc.a 0 4 1090 0 0 1094 ...pp_update.a 0 0 0 123 725 848 libhal.a 0 0 515 0 32 547 libm.a 0 0 92 0 0 92 libcxx.a 0 0 0 11 0 11 libwps.a 0 1 0 0 0 1 libwpa2.a 0 1 0 0 0 1 libethernet.a 0 0 0 0 0 0 ..._support.a 0 0 0 0 0 0 As you can see from the output above, it will display footprint information that is contributed by all the components towards the firmware. The information is additionally displayed in multiple columns:\nDRAM .data : This is the size of the .data section of the component. This includes any pre-initialized data that can be read or written at runtime DRAM .bss : This is the size of the .bss section of the component. This includes any global or statically defined variables and objects that are zero-initialised on boot-up. IRAM : This is the size of the code (.text) section that needs to be loaded into IRAM. Note that most code can directly be executed from flash (XIP), without having to load it into IRAM. Typically code that is executed in interrupt context or accesses flash for read/write directly goes in here. Flash Code : This is the size of the code (.text) section that is in the flash and is directly executed from there. Most of your code section will end up in this column. Flash rodata : Any read-only data that is used by your firmware (strings, statically initialized and unmodifiable arrays) all go into this section. Since the flash can directly be accessed during execution, this need not be loaded into memory. Total: The total contribution of this component. As you might have guessed the size contributions to the IRAM and DRAM section here are critical. Since SRAM is limiting factor (512KB) relative to flash (about 2–8 MB).\nPer-Symbol Size # Now Let’s say you found out that one of the components that you have written consumes much more memory that it should have. You can dig deeper by trying to check which symbols within this component contribute the most to the footprint. This can be done using the size-symbols target to the build system. For example,\n$ __make IDF_PATH=~/work/idf size-symbols COMPONENT=soc__ Total sizes: DRAM .data size: 14200 bytes DRAM .bss size: 23224 bytes Used static DRAM: 37424 bytes ( 143312 available, 20.7% used) Used static IRAM: 62344 bytes ( 68728 available, 47.6% used) Flash code: 368546 bytes Flash rodata: 65916 bytes Total image size:~ 511006 bytes (.bin may be padded larger) Symbols within the archive: libsoc.a (Not all symbols may be reported)__Symbols from section: .dram0.data__ str1.4(605) __func__$3446(23) __func__$3425(21) rtc_clk_cpu_freq_value(20) Section total: 669__Symbols from section: .dram0.bss__ s_cur_pll(4) s_cur_freq(4) Section total: 8__Symbols from section: .iram0.text__ rtc_init(1020) rtc_clk_cpu_freq_set(472) rtc_clk_bbpll_set(380) rtc_clk_cal_internal(369) .iram1(282) rtc_clk_cpu_freq_get(172) rtc_clk_32k_bootstrap(170) rtc_clk_32k_enable_internal(149) rtc_clk_wait_for_slow_cycle(129) rtc_time_get(96) rtc_clk_cpu_freq_value(96) rtc_clk_cal(78) rtc_clk_xtal_freq_get(68) rtc_clk_slow_freq_get_hz(51) rtc_clk_apb_freq_get(50) rtc_clk_32k_enable(49) rtc_clk_fast_freq_set(46) rtc_clk_slow_freq_set(43) clk_val_is_valid(32) .iram1.literal(28) rtc_clk_apb_freq_update(23) rtc_clk_slow_freq_get(16) clk_val_to_reg_val(14) reg_val_to_clk_val(8) Section total: 3841Symbols from section: .iram0.vectorsSection total: 0Symbols from section: .flash.textSection total: 0__Symbols from section: .flash.rodata__ soc_memory_regions(704) soc_memory_types(320) str1.4(159) soc_reserved_regions(48) soc_reserved_region_count(4) soc_memory_region_count(4) Section total: 1239 Notice that we pass an additional parameter COMPONENT=\u0026lt;component_name\u0026gt; in the make command line to get per symbol information of this component. In the example above, we requested information for the component ‘soc’.\nThis caused the tool to display how much every symbol (function or variable/object) from this component contributed to the firmware’s footprint. Notice how information about how much size every function contributed to .iram0.text is shown in the output above. Also, because the arrays soc_memory_types and soc_memory_regions (defined in soc_memory_layout.c) are defined as ‘const’ are put into the flash since it is read-only data.\nThis information can be effectively used to identify exactly what parts of your components are contributing to the firmware footprint and then help you focus on optimizing these parts effectively.\n","date":"13 May 2018","externalUrl":null,"permalink":"/blog/analysing-static-footprint/","section":"Blog","summary":"","title":"Analysing Static Footprint","type":"blog"},{"content":"Espressif Systems (or “Espressif”), a leading global IoT semiconductor company, announced today that it has received investment co-led by Intel Capital and Beijing Singularity Power Investment Fund L.P. (SPC).\nEspressif Systems’ Founder and CEO Swee Ann Teo (1st from left) and the CEOs of other invested companies\nEspressif helps power the devices that are key to the Internet-of-Things (IoT) industry. The company’s IoT chipsets provide dual-mode connectivity (Wi-Fi \u0026amp; BT/BLE), powered by a 32-bit, single- or dual-core processor in all-in-one SoCs with excellent price performance. Gartner profiled Espressif in the category of “Cool Vendors in ‘IoT Thingification’ 2016,” and Techno Systems Research Co. Ltd, a Japan market research company, ranked Espressif first in the MCU Embedded WiFi sector in 2017. With highly integrated MCU embedded Wi-Fi solutions, such as the popular ESP32 and ESP8266, Espressif achieved sales of one hundred million IoT chipsets by the end of 2017. This new round of investment is another milestone in Espressif’s development and will strengthen the company’s R\u0026amp;D capabilities and help increase its market influence.\nEspressif Systems’ Founder and CEO Swee Ann Teo at the Intel Capital Global Summit\nEspressif Founder and CEO Swee Ann Teo said: “We are honored to receive investment from Intel Capital and SPC. This new funding will assist our expansion in the field of Artificial Intelligence, take our IoT solutions to the next level and allow us to remain at the forefront of today’s technological innovation.”\nAnthony Lin, Intel Capital Vice President and Managing Director of Greater Asia and Europe, commented: “Intel Capital is committed to propelling data-driven technological innovation and promoting the transformation of smart technology industries. Espressif has demonstrated its ability to create innovative IoT solutions with a competitive edge. We look forward to working with the company to help unlock the potential for data in a new era of smart and connected devices.”\nWang Jiaheng, Managing Director of SPC, stated: “Espressif Systems is a leading company in the IoT industry and has gained a competitive advantage in the field of embedded Wi-Fi solutions by building a reputation for delivering innovative products. The company has a track record of responding to customer needs and constantly improving user experience with cost-effective and easy-to-use IoT solutions. With this investment deal, SPC offers Espressif the opportunity to seize momentum in China’s rapidly developing semiconductor industry by further optimizing its own strategic and operational capabilities, while also contributing to the rapid growth of the IoT industry.”\nAbout Espressif Systems\nEspressif Systems (Shanghai, China) is a multinational, fabless, semiconductor company that creates low-cost and high-performance solutions for the Internet-of-Things industry. The company’s all-in-one system-on-chips (SoCs), such as the popular ESP8266 and ESP32, provide dual-mode connectivity (Wi-Fi+BT/BLE) to a wide range of IoT products, including tablets, cameras, smart-home devices and wearable electronics. For more information on the products and services that Espressif offers, visit www.espressif.com.\nAbout Intel Capital\nIntel Capital invests in innovative startups targeting artificial intelligence, autonomous driving, workload accelerators, 5G connectivity, virtual reality and a wide range of other disruptive technologies. Since 1991, Intel Capital has invested US $12.3 billion in over 1,530 companies worldwide, and more than 660 portfolio companies have gone public or been acquired. For more information on what makes Intel Capital one of the world’s most powerful venture capital firms, visit www.intelcapital.com or follow @Intelcapital.\nAbout Beijing Singularity Power Investment Fund L.P. (SPC)\nBeijing Singularity Power Investment Fund L.P. (SPC) was initiated and established in 2015 by the BOE Technology Group, National IC Industry Investment Fund, Yizhuang SDIC, and industry leaders. SPC is headquartered in Yizhuang, Beijing, and has research centers in such areas such as Zhongguancun in Beijing and Silicon Valley in the USA. The initial investable funds of SPC totaled RMB 4bn (USD 600m). SPC mainly focuses on integrated-circuit design, human-computer interaction, the Internet of Things and Artificial Intelligence.\nMedia Contact:\nEspressif Systems\nEmail: pr@espressif.com\nOgilvy PR\nJoyce Li, Director\nTel: +86 10 8520 3305\nEmail: joycey.li@ogilvy.com\n","date":"8 May 2018","externalUrl":null,"permalink":"/blog/espressif-receives-investment-from-intel-capital-and-beijing-singularity-power-investment-fund/","section":"Blog","summary":"","title":"Espressif Receives Investment from Intel Capital and Beijing Singularity Power Investment Fund","type":"blog"},{"content":" Hi everyone, The month of April is an exciting one for Espressif, since it is our birthday month. This year, in particular, we are celebrating the tenth birthday of our company on 29 April, and we plan our celebrations to extend even in May! Many things have coincided with this occasion, making our tenth anniversary even more special.\nOur brand new audio development boards, ESP32-LyraTD-MSC and ESP32-LyraT, have been officially released and our customers can order them or make enquiries about them through our CRM system. Also, ESP32-WROOM-32D is now available to the Japanese market through www.switch-science.com. ESP32-WROOM-32D is a powerful Wi-Fi+BT/BLE module that targets a wide variety of applications, ranging from low-power sensor networks to the most demanding tasks, such as voice encoding, music streaming and MP3 decoding.\nAdditionally, our presence in Europe is becoming stronger by the day. Our branch in the Czech Republic is developing quickly, while also our distribution partners in France, Astone Technology, brought Espressif to the spotlight in the latest exhibition in Paris about embedded systems and machine-to-machine (M2M) communications at the Expo Porte de Versailles on 21 and 22 March 2018.\nMost importantly, however, the latest report by Techno Systems Research regarding the 2017 market shares in the semiconductorindustry was released last month, showing that Espressif Systems ranked first in the MCU Embedded Wi-Fi market with a share of about 30%, which was well over that of our competitors. As our company continues to develop, it is important to us to be not only a mainstream IoT company, but an integral part of the innovation that drives the semiconductor industry forward. We will continue creating IoT solutions that deliver exactly this. Furthermore, we will remain loyal to our motto about the democratization of technology, maintaining our competitive prices which allow everyone’s access to the alluring world of IoT.\nIn the April edition of our newsletter you will also find out more about Talent Land 2018, the biggest gathering of hi-tech people in Latin America, and the ESP8266-powered electronic badge that they offer as a limited-edition souvenir; a very interesting tutorial about how to use ESP8266 and/or ESP32 to achieve voice-controlled relay; a home-made Arduino robot based on ESP8266, which everyone can recreate in order to control their home appliances over the internet; and an ESP8266-enabled smart-parking app to assist you in finding and reserving an available parking spot, so that others cannot beat you to it.\nEnjoy reading our newsletter and do not forget to like us on Facebook and follow us on Twitter.\nBest wishes,John LeeSenior Customer Support Officer\nMexico’s “Talent Land 2018” with an ESP8266 Badge # On 2 April Talent Land 2018 started. This is the largest innovation and entrepreneurship event that takes place in Mexico every year. It is a five-day event addressed to the maker community in Latin America, attracting talented young developers, investors, institutions and recruiters who meet up, share knowledge and strengthen the community’s development. What’s more, this year there is a limited-edition badge designed specifically for Talent Land 2018, which is based on our very own ESP8266.\nVoice-Controlled Relay with ESP32 and ESP8266 # Rui Santos has just published on his very interesting RNT blog a tutorialthrough which readers can learn how to control ESP8266 or ESP32 with voice commands, using Amazon’s Alexa. The RNT blog helps makers, hobbyists and engineers build projects about electronics. In this particular tutorial, Rui uses the example of controlling two 12V lamps, with a relay. He also shows how to physically control these lamps, using a wireless 433 MHz switch on a wall.\nESP8266-based GO-4 Smart-Home Arduino Bot # Ahmed Azouz, an Egyptian software engineer, has developed an application that uses the ESP8266 IoT technology to control home appliances remotely over the internet. Ahmed said on hackster.io, where his project is published in full: “There is a small technological marvel called ESP8266 and it is a great tool for enabling your project’s access to the internet. You can plug it into an Arduino easily and control it over the internet from anywhere in the world via its unique IP address!”\nESP8266-Controlled Smart-Parking # “Astro” is a smart-parking system created by Priyanka Joshi, a graduate student at the University of Texas at Dallas majoring in Computer Science with specialization in Intelligent Systems, and Shubham Pradeep Kothari. Astro was created to save drivers’ time and fuel wastage, while looking for parking space, which can be quite an arduous task in densely populated urban areas. Of course, the whole project has been based on our powerful ESP8266.\nOriginally published at mailchi.mp.\n","date":"7 May 2018","externalUrl":null,"permalink":"/blog/april-2018/","section":"Blog","summary":"","title":"April 2018","type":"blog"},{"content":"","date":"7 May 2018","externalUrl":null,"permalink":"/tags/esp-idf-v3.0/","section":"Tags","summary":"","title":"ESP-IDF V3.0","type":"tags"},{"content":" Hi everyone,\nWe said goodbye to April with a glorious party celebrating Espressif’s 10th birthday! Espressif was created on April 29th, 2008. Back then our company was a small Chinese startup fueled with the vision of its CEO and founder, Teo Swee Ann. It soon became apparent that Espressif’s field of specialization would be the Internet of Things. Our company evolved significantly in this area, leaving its indelible mark with such popular IoT solutions as ESP8266and ESP32. During the last decade, Espressif has changed from being a Chinese technology startup to being a multinational company providing fast, secure and green IoT solutions that can be available to all.\nTo celebrate our tenth anniversary we launched Espressif’s brand new Instagram account, which you can follow by clicking here. They say that a picture is worth a thousand words. Since Instagram is based on broadcasting pictures mainly, we want to use the power of image in order to communicate our brand, our values and our technologies to the worldwide community of IoT developers. We really hope that you join us in this new journey through social media, which is meant to complement our presence on Twitter, Facebook and WeChat.\nOne day prior to Espressif’s birthday, our Indian branch in Pune hosted an IoT meetup. These meetups are monthly events scheduled for the\nlast Saturday of every month. Every session includes one or two technical presentations, followed by demonstrations of exciting projects from the IoT community in Pune. The last meetup on April 28th, examined how MQTT started and evolved as a dominant protocol for TCP/IP communications. The specific topics included an explanation of MQTT 3.1, the new aspects of MQTT 5, and a presentation of AWS IoT as an MQTT broker. The session was very successful attracting numerous attendees who left their positive remarks on the event’s webpage. In the May edition of our newsletter you will also find out more about the results of the ESP32 Design Contest 2018, which we organized and delivered together with Elektor International Media; the release of the much anticipated ESP-IDF v3.0; Espressif’s official mesh development framework, ESP-MDF, which supports mesh applications for the ESP32 chip in the most comprehensive way; and “Atmosphere IoT”, the innovative cloud platform which has just started providing support for our ESP32 chipsets.\nWe hope that you enjoy reading the May edition of our newsletter and that you continue following us on Instagram, Facebook , Twitter and WeChat.\nBest wishes, John Lee\nSenior Customer Support Officer\nBig Success for the ESP32 Design Contest 2018 # Remember last January when we announced that we would organize a contest about ESP32 Design together with Elektor International Media? After receiving a great number of remarkable entries, our judging panel, which consisted of engineers from Espressif and Elektor, announced the winners at the end of last month. Our judges noted that the programming level of all participating entries was considerably high, which made their task more challenging, but also more intellectually stimulating and exciting.\nESP-IDF v3.0 Released # The latest version of Espressif’s IoT Development Framework, ESP-IDF v3.0, has just been released. This is part of our commitment to improve our IoT solutions, based on the results of our quality assurance procedures and the feedback we receive from the community of developers who use our chips.\nESP-MESH Development Framework Released # Further to ESP8266’s Wi-Fi mesh networking, Espressif is pleased to announce that this local network topology is now officially supported on ESP32, as well. ESP-MDF is the official mesh development framework for ESP32, supporting mesh applications for our flagship chip in the most comprehensive way.\nAtmospher IoT Starts Supporting ESP32 # Atmosphere IoT has just started supporting Espressif Systems’ ESP32, with the aim of delivering better, faster and more secure IoT solutions for everyone. First released in January 2015, the innovative cloud platform of Atmosphere IoT has already been used by thousands of developers and OEMs. Adding to this the power of Espressif’s ESP32 will enable developers to build and deploy cloud-enabled embedded applications with optimized cost performance and reduced time-to-market.\nOriginally published at mailchi.mp.\n","date":"7 May 2018","externalUrl":null,"permalink":"/blog/may-2018/","section":"Blog","summary":"","title":"May 2018","type":"blog"},{"content":"A common requirement while building a device is to have some unique information programmed into the device at the time of manufacturing. This information could be a unique serial number, or a unique MAC address ; or it could be a unique secret like the default password, or the HomeKit pairing pin.\nWe have seen quite a number of ways that customers have achieved this.\nSome use a few NVS keys to store this information at the factory. Since the NVS also stores user configuration, this method makes it harder to implement reset-to-factory, where the user’s settings must be erased. Some write a script that modifies known locations of a firmware image to add unique values in the firmware. This makes firmware upgrades harder because the unique information is now part of the application firmware itself. In the recent ESP IDF master, we have introduced a few changes that should make implementing this behaviour easier.\nMultiple NVS Partitions # IDF now supports simultaneously having multiple NVS partitions.\nOne of the NVS partitions can be used to store user configuration. This partition only stores user’s configuration, and thus can be freely erased at a reset-to-factory event. The other NVS partition can be used to store per-device unique information. Thousands of unique NVS partition images/binaries could be created and then be programmed per-device into this partition at the factory. Creating the partitions file # The IDF uses a default partition layout that works for most cases. A number of such layouts are available in the components/partition_table/ directory within the IDF. We now need to create a partition file that has 2 NVS partitions instead of the typical one.\nA sample updated partition file is shown below:\n# Name, Type, SubType, Offset, Size, Flags # Note: if you change the phy_init or app partition offset, make sure to change the offset in Kconfig.projbuild nvs, data, nvs, 0x9000, 0x6000, phy_init, data, phy, 0xf000, 0x1000, __fctry, data, nvs, 0x10000, 0x6000,__ factory, app, factory, 0x20000, 1M, Notice the line fctry that indicates the additional NVS partition. This partitions stores the per-device unique keys programmed into the factory. The first NVS partition continues to be used as the partition for storing user configuration like Wi-Fi network name, passphrase etc.\nUsing the partitions file # Save the above partition file at some location. Now update your SDK configuration to pick up this partitions file as:\nmenuconfig → Partition Table → Custom partition table CSV menuconfig → Partition Table → Custom partition CSV file menuconfig → Partition Table → Factory app partition offset The custom partition CSV file should match the name of your partitions file.\nThe factory app partition offset should match the offset at which the ‘factory’ firmware is stored in your partitions file.\nAccessing the factory data # The factory partition can then be accessed as shown below:\n/* Error checks removed for brevity */ nvs_handle fctry_handle;nvs_flash_init___partition__ (MFG_PARTITION_NAME); nvs_open___from_partition__ (MFG_PARTITION_NAME, “fctryNamespace”, NVS_READWRITE, \u0026amp;fctry_handle);nvs_get_str(fctry_handle, “serial_number”, buf, \u0026amp;buflen); The above code initializes and opens the factory NVS partition. Note how we use nvs_flash_init_partition() over nvs_flash_init() and nvs_open_from_partition() over nvs_open() The rest of the code for reading the variables uses the standard nvs_get_() function. Generating the factory data # A utility nvs_flash/nvs_partition_generator/nvs_partition_gen.py is now available to make it easy to generate these unique factory partitions. This utility can generate an NVS partition from a CSV file. The following is an example of the CSV file:\n$ __cat device-164589345735.csv__ key,type,encoding,value fctryNamespace,namespace,, serial_number,data,string,164589345735 mac_addr,data,string,0A:0B:0C:0D:0E:0F So the CSV file has 4 lines. Each line should have 4 entries separated by commas.\nThe first entry is the key. The second entry is the type. This indicates how should the ‘value’ be interpreted. The supported types are (a) file: the ‘value’ is a filename that actually contains the value for this key, (b) data: the ‘value’ contains the final data, (c) namespace: this key is really a namespace not a key-value pair The third entry is the encoding, which specifies how the value should be encoded into the generated partition. Supported values include standard data types like u8, i8, u16, u32, i32, string. And also hex2bin: which will apply a hex2bin conversion to the data before putting it into the NVS partition. The fourth entry is the value that we talked about above. Now that we have this information, let’s see what the CSV shown above would do:\nThe first line is just a heading of the columns, this line should be exactly as shown above The second line defines the NVS namespace in which the variables will be defined. In this case, the ‘device_data’ is the namespace that these variables will be defined in The third line defines an NVS key serial_no, with the value 164589345735 The fourth line defines an NVS key mac_addr, with the value 0A:0B:0C:0D:0E:0F The NVS partition can then be generated as:\n$ python nvs_partition_gen.py device-164589345735.csv device-164589345735.bin The device-164589345735.bin file is the NVS partition data that can now be programmed into the device. Assuming you have the partition table as shown above, the following command should do the job for you:\n$ /path/to/idf/components/esptool_py/esptool/esptool.py — port /dev/cu.SLAB_USBtoUART write_flash 0x10000 device-164589345735.bin This allows you to create as many unique images as you want, using a script, and then flash them on the respective hardware boards.\nPlease refer to the NVS partition generator documentation for more details.\nCurrent Limitations # Currently the NVS object value can only be 1968 bytes in size. ","date":"1 May 2018","externalUrl":null,"permalink":"/blog/creating-unique-factory-data-images/","section":"Blog","summary":"","title":"Creating Unique Factory Data Images","type":"blog"},{"content":"","externalUrl":null,"permalink":"/pages/about/","section":"","summary":"","title":"About","type":"pages"},{"content":"","externalUrl":null,"permalink":"/categories/","section":"Categories","summary":"","title":"Categories","type":"categories"},{"content":" ","externalUrl":null,"permalink":"/pages/esp-idf-survey/","section":"","summary":"","title":"ESP-IDF Survey","type":"pages"},{"content":"Explore additional resources for your project and accelerate product development with Espressif solutions.\nThis page provides a comprehensive collection of resources to help you build and scale your ESP32 projects:\nDocumentation \u0026amp; Frameworks - Access the Centralized Documentation Platform (CDP) and explore the ESP-IDF ecosystem, including specialized libraries for AI, connectivity, audio/video, HMI, Matter, and cloud integration Development Environments - Find resources for developing with Arduino, NuttX, Rust, and Zephyr on ESP32 platforms Whether you\u0026rsquo;re looking for community support, technical documentation, or exploring different development frameworks, this page serves as your gateway to all essential Espressif resources.\nEspressif IoT Development Framework espressif/esp-idf Espressif IoT Development Framework. Official development framework for Espressif SoCs. C 17733 8184 CDP \u0026#8599; \u0026#8598; Espressif Access comprehensive technical documentation for all Espressif products, SDKs, and development frameworks in one place. ESP32 Forum \u0026#8599; \u0026#8598; Espressif Join the ESP32 community forum to ask questions and share projects. Registry ESP Component Registry \u0026#8599; \u0026#8598; Espressif Discover and share reusable ESP-IDF components. Browse thousands of community and official libraries to accelerate your development. AI espressif/esp-dl Espressif deep-learning library for AIoT applications Assembly 966 194 espressif/esp-nn Optimised Neural Network functions for Espressif chipsets Assembly 212 33 Connectivity esp-thread-br \u0026#8599; \u0026#8598; GitHub Open-source Thread Border Router stack and tools for Espressif platforms. espressif/esp-thread-br Espressif Thread Border Router SDK C 215 47 Audio, video and HMI espressif/esp-adf Espressif Advanced Development Framework for Multimedia Applications C 2207 846 espressif/esp-sr Speech recognition C 1324 186 espressif/esp-gmf Espressif General Multimedia Framework (ESP-GMF) C 91 23 espressif/esp-brookesia ESP-Brookesia is a human-machine interaction development framework designed for AIoT devices. C 634 155 Matter espressif/esp-matter Espressif\u0026rsquo;s SDK for Matter C\u0026#43;\u0026#43; 984 225 Cloud ESP RainMaker \u0026#8599; \u0026#8598; Espressif Build connected IoT products with Espressif\u0026rsquo;s cloud platform. Includes device provisioning, remote control, OTA updates, and mobile apps. ESP Insights \u0026#8599; \u0026#8598; Espressif Monitor and debug your deployed IoT devices remotely. Track crashes, errors, metrics, and diagnostics data in real-time. ESP ZeroCode \u0026#8599; \u0026#8598; Espressif Deploy Matter-certified devices without writing code. Pre-built firmware modules for quick Matter device development and deployment. Community Arduino for ESP32 \u0026#8599; \u0026#8598; Community Arduino core for the ESP32 family of SoCs. Provides a comprehensive set of Arduino libraries and tools supporting ESP32, ESP32-S2, ESP32-S3, ESP32-C3, ESP32-C6, ESP32-H2, and ESP32-P4. Apache NuttX \u0026#8599; \u0026#8598; Community Apache NuttX is a real-time operating system (RTOS) with an emphasis on standards compliance and small footprint. Scalable from 8-bit to 64-bit microcontroller environments, the primary governing standards are POSIX and ANSI standards. Rust \u0026#8599; \u0026#8598; Community Libraries, crates, and examples for using the Rust programming language on various SoCs and modules produced by Espressif Systems, with both no_std and std support. Zephyr \u0026#8599; \u0026#8598; Community The Zephyr Project is a scalable real-time operating system (RTOS) supporting multiple hardware architectures, optimized for resource-constrained devices, and built with security in mind. Downloads Espressif SoC Portfolio 2026 \u0026#8599; \u0026#8598; Espressif Espressif Brochure Embedded World 2026 \u0026#8599; \u0026#8598; Espressif Espressif EW26 ESP IDF Flyer \u0026#8599; \u0026#8598; Espressif Espressif EW26 Arduino Flyer \u0026#8599; \u0026#8598; Espressif Espressif EW26 NuttX Flyer \u0026#8599; \u0026#8598; Espressif Espressif EW26 Rust Flyer \u0026#8599; \u0026#8598; Espressif Espressif EW26 Zephyr Flyer \u0026#8599; \u0026#8598; Espressif ","externalUrl":null,"permalink":"/pages/resources/","section":"","summary":"","title":"Explore ESP32 Related Resources","type":"pages"},{"content":"","externalUrl":null,"permalink":"/authors/glauber-ferreira/","section":"Developer Portal Authors","summary":"","title":"Glauber Ferreira","type":"authors"},{"content":"","externalUrl":null,"permalink":"/authors/he-xinlin/","section":"Developer Portal Authors","summary":"","title":"He Xinlin","type":"authors"},{"content":"","externalUrl":null,"permalink":"/authors/espressif/","section":"Developer Portal Authors","summary":"","title":"John Lee","type":"authors"},{"content":"","externalUrl":null,"permalink":"/authors/ma-jingjing/","section":"Developer Portal Authors","summary":"","title":"Ma Jingjing","type":"authors"},{"content":"","externalUrl":null,"permalink":"/platforms/","section":"Platforms","summary":"","title":"Platforms","type":"platforms"},{"content":"","externalUrl":null,"permalink":"/socs/","section":"Socs","summary":"","title":"Socs","type":"socs"},{"content":"","externalUrl":null,"permalink":"/authors/wangyuxin/","section":"Developer Portal Authors","summary":"","title":"Wang Yuxin","type":"authors"}]