ESP-IDF spi_flash no_flash_delay 构建验证:最小测试工程与擦除让出机制(SPI_FLASH_YIELD_DURING_ERASE)深度解析

发布时间:2026/9/14 2:36:22
ESP-IDF spi_flash no_flash_delay 构建验证:最小测试工程与擦除让出机制(SPI_FLASH_YIELD_DURING_ERASE)深度解析 ESP-IDF spi_flash no_flash_delay 构建验证最小测试工程与擦除让出机制SPI_FLASH_YIELD_DURING_ERASE深度解析【免费下载链接】esp-idfEspressif IoT Development Framework. Official development framework for Espressif SoCs.项目地址: https://gitcode.com/GitHub_Trending/es/esp-idf本文聚焦 ESP-IDF 中 spi_flash 组件下的 no_flash_delay 测试工程讲清楚它如何在仅支持 ESP32-C3 的最小化构建下验证 no_flash_delay即关闭CONFIG_SPI_FLASH_YIELD_DURING_ERASE配置的可构建性。读完本文你将理解该测试工程的结构与用途、SPI_FLASH_YIELD_DURING_ERASE及其两个关联参数在 Kconfig 中的定义与默认值以及从源码层面看擦除期间让出 CPU这一机制是如何在on_spi_check_yield()中实现的、关闭它后对擦除路径的编译级影响并能独立完成该工程的构建与配置验证。测试工程 no_flash_delay目标、用途与文件结构根据 README.md 的说明Supported Targets: ESP32-C3 This project tests building with the no_flash_delay configuration. This project uses MINIMAL_BUILDy to reduce build time and dependencies.即该工程唯一的目标芯片是 ESP32-C3用途是验证在 no_flash_delay 配置下工程能够成功构建并通过MINIMAL_BUILDy缩短构建时间、减少依赖组件。它是一个纯粹的构建验证工程而非功能测试工程——这一点从它的全部源码内容可以得到直接印证。整个工程只有 4 个文件结构非常精简文件作用README.md声明支持目标与工程用途CMakeLists.txt开启MINIMAL_BUILD声明工程main/test_main.c空app_main()仅提供可链接的入口sdkconfig.ci.defaultCI 基线配置唯一一行即关闭擦除让出其中 main/test_main.c 的全部内容就是一个空的app_main(void)函数体main/CMakeLists.txt 也只用idf_component_register(SRCS test_main.c ...)注册了这个源文件。工程不包含任何测试断言、外设操作或运行时检查验证点完全落在能否编译、链接、生成固件上。开启 no_flash_delayCONFIG_SPI_FLASH_YIELD_DURING_ERASEn该工程实现 no_flash_delay 配置的核心只有一行位于 sdkconfig.ci.defaultCONFIG_SPI_FLASH_YIELD_DURING_ERASEnsdkconfig.ci.default是 ESP-IDF CI 体系中的基线配置文件CI 构建时以此为基础展开完整 sdkconfig。这里没有配置其他任何项意味着工程其余全部采用该芯片的默认配置只有擦除期间是否让出 CPU这一项被显式关闭——这也正是 README 中 no_flash_delay configuration 的具体所指。该选项在 components/spi_flash/Kconfig 中的完整定义如下config SPI_FLASH_YIELD_DURING_ERASE bool Enables yield operation during flash erase default y help This allows to yield the CPUs between erase commands. Prevents starvation of other tasks. Please use this configuration together with SPI_FLASH_ERASE_YIELD_DURATION_MS and SPI_FLASH_ERASE_YIELD_TICKS after carefully checking flash datasheet to avoid a watchdog timeout.关键信息可以归纳为默认值为y开启flash 擦除在多条 erase 命令之间会让出 CPU防止其他任务因长时间得不到运行时间而被饿死starvation。no_flash_delay 即把默认值反转为n擦除过程不再让出 CPU擦除命令连续执行期间不插入任务切换。官方 help 中特别提示若保留让出机制应结合SPI_FLASH_ERASE_YIELD_DURATION_MS和SPI_FLASH_ERASE_YIELD_TICKS两个参数并仔细核对 flash 数据手册以看门狗超时的风险。这两个联动参数同样定义在同一 Kconfig 中且都depends on SPI_FLASH_YIELD_DURING_ERASE即当 no_flash_delay 生效选项为n时它们在菜单中根本不可见配置项含义默认值SPI_FLASH_ERASE_YIELD_DURATION_MS单次擦除持续该时长ms后让出 CPU20SPI_FLASH_ERASE_YIELD_TICKS让出 CPU 后继续等待多少个 tick 再恢复擦除1从参数依赖关系可以推断关闭SPI_FLASH_YIELD_DURING_ERASE后整套按时间窗让出的策略被整体停用擦除路径退化为不被任务调度打断的连续执行。这类配置通常服务于对擦除时序确定性有要求的场景例如单核平台上不希望擦除期间引入不可预期的调度延迟但代价是擦除窗口内其他任务将得不到运行机会——这一点与 Kconfig help 中让出机制防止其他任务被饿死的设计初衷正好互为镜像。源码视角让出检查如何被编译级移除理解 no_flash_delay 的实际效果最直接的方式是查看主 flash 的操作系统适配层实现 spi_flash_os_func_app.c。该文件中定义了擦除过程插入有效任务执行区间的核心逻辑// The goal of this part is to manually insert one valid task execution interval, if the time since // last valid interval exceed the limitation (CONFIG_SPI_FLASH_ERASE_YIELD_DURATION_MS). // // Valid task execution interval: continuous time with the cache enabled, which is longer than // CONFIG_SPI_FLASH_ERASE_YIELD_TICKS. Yield time shorter than CONFIG_SPI_FLASH_ERASE_YIELD_TICKS is // not treated as valid interval. static inline IRAM_ATTR bool on_spi_check_yield(app_func_arg_t* ctx) { #ifdef CONFIG_SPI_FLASH_YIELD_DURING_ERASE uint32_t time esp_system_get_time(); if ((time - ctx-released_since_us) CONFIG_SPI_FLASH_ERASE_YIELD_TICKS * portTICK_PERIOD_MS * 1000) { // Reset the acquired time as if the yield has just happened. ctx-acquired_since_us time; } else if ((time - ctx-acquired_since_us) CONFIG_SPI_FLASH_ERASE_YIELD_DURATION_MS * 1000) { return true; } #endif return false; }这段实现与 Kconfig 定义完全对应可以读出三个层次判定规则on_spi_check_yield()在持有 SPI 总线期间被周期性调用。若距上次获取总线以来的持续占用时间达到SPI_FLASH_ERASE_YIELD_DURATION_MS默认 20 ms则返回true触发一次让出同时若上次释放与本次获取之间的空闲时间已超过SPI_FLASH_ERASE_YIELD_TICKS默认 1 tick则直接重置占用计时视同刚刚完成过让出——源码注释解释了这样做是为了省掉一次esp_system_get_time()调用。配套的时间戳维护配套的 on_spi_released() 在释放总线时记录released_since_uson_spi_yielded() 在真正让出后刷新acquired_since_us共同构成持续占用计时—超限判定—让出—重置的闭环。no_flash_delay 的编译级效果整个让出判定与时间戳维护都被包裹在#ifdef CONFIG_SPI_FLASH_YIELD_DURING_ERASE之内。当配置为nno_flash_delay时on_spi_check_yield()函数体被裁空恒返回false擦除流程中不存在任何让出分支。也就是说该配置的影响不是在运行时少做一点事而是把让出路径从固件中彻底移除——这与build test验证配置组合可构建的测试定位一致CI 需要确认这一编译裁剪路径函数体为空、相关字段不再参与判定不会引入编译错误、链接错误或结构体不一致问题。从源码结构看on_spi_acquired()同样保留了空实现与注释说明见 第 590-596 行它假设释放到再次获取之间的间隙已在on_spi_check_yield()中处理进一步说明这些回调是为让出机制可选而设计的钩子集合——关闭该机制后钩子仍然存在但逻辑为空工程仍可正常构建这正是 no_flash_delay 测试工程要覆盖的组合。MINIMAL_BUILD为什么测试工程要做裁剪构建工程根 CMakeLists.txt 展示了第二个关键配置cmake_minimum_required(VERSION 3.22) include($ENV{IDF_PATH}/tools/cmake/project.cmake) # Trim the build. Include the minimal set of components, main, and anything it depends on. idf_build_set_property(MINIMAL_BUILD ON) project(test_build)idf_build_set_property(MINIMAL_BUILD ON)即 README 所称的 MINIMAL_BUILDy注释直接说明了语义裁剪构建只包含最小的一组组件、main以及main所依赖的传递闭包。对 no_flash_delay 这样的构建验证工程而言这带来两方面收益缩短 CI 构建时间不需要编译完整 IDF 组件树只编译与最小工程相关的部分降低依赖面避免无关组件的 Kconfig 组合引入干扰让关闭擦除让出这一单一变量成为构建结果的决定因素。配合空的app_main()与单条 CI 配置整个工程构成一个干净的验证闭环目标芯片 ESP32-C3 最小组件集 CONFIG_SPI_FLASH_YIELD_DURING_ERASEn只要能出固件即视为通过。如何复现该构建验证在本地仓库中复现该测试工程的构建步骤如下进入工程目录components/spi_flash/test_apps/no_flash_delay设置目标为 ESP32-C3README 声明的唯一支持目标idf.py set-target esp32c3通过idf.py menuconfig进入SPI Flash配置组将Enables yield operation during flash eraseCONFIG_SPI_FLASH_YIELD_DURING_ERASE设为nCI 场景下则直接由 sdkconfig.ci.default 注入该值执行idf.py build验证可构建性。适用前提与限制该工程只声明支持 ESP32-C3其他芯片不在 README 的测试范围内由于MINIMAL_BUILD裁剪了组件集构建产物仅用于验证构建链路不宜作为功能样机使用若改为默认配置让出开启则SPI_FLASH_ERASE_YIELD_DURATION_MS与SPI_FLASH_ERASE_YIELD_TICKS才会在菜单中出现调整前应按 Kconfig help 的提示核对 flash 数据手册避免看门狗超时。小结no_flash_delay 测试工程用最小成本回答了 spi_flash 组件的一个具体构建问题关闭SPI_FLASH_YIELD_DURING_ERASE后擦除期间不再让出 CPUSPI_FLASH_ERASE_YIELD_DURATION_MS/SPI_FLASH_ERASE_YIELD_TICKS两个联动参数随之不可见整个让出路径在 spi_flash_os_func_app.c 中被编译级裁空工程仍应在 ESP32-C3 MINIMAL_BUILD下顺利产出固件。该工程的价值正在于把这一编译裁剪 最小组件集的组合固化进了 CI 可复现的验证流程为后续修改擦除让出机制提供了回归基准。【免费下载链接】esp-idfEspressif IoT Development Framework. Official development framework for Espressif SoCs.项目地址: https://gitcode.com/GitHub_Trending/es/esp-idf创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考