
嵌入式语言运行时编程语言解释器编译器物联网系统编程【免费下载链接】micropythonMicroPython - a lean and efficient Python implementation for microcontrollers and constrained systems项目地址https://gitcode.com/gh_mirrors/mi/micropython点击查看免费下载导读pyb.Flash是 MicroPython 在 STM32 系列Pyboard上提供的一个内建块设备block device类用于绕过文件系统直接读写 MCU 内部 Flash 或板载外部 SPI Flash。本指南将完整讲解它的两种构造函数、底层分区布局、readblocks/writeblocks/ioctl三件套的块协议实现并结合 storage.c 源码与 vfs.AbstractBlockDev 协议规范帮你掌握自定义文件系统分区、实现低层存储系统以及理解 MicroPython 启动挂载流程的完整技术细节。1. 为什么需要直接访问 Flash在 Pyboard 上存储持久化数据绝大多数场景推荐使用标准 Python 文件 API 配合文件系统FAT / littlefs例如with open(/flash/data.txt, w) as f: f.write(hello)但有些需求文件系统 API 无法直接满足此时需要pyb.Flash提供的原始块级访问能力定制文件系统配置调整分区布局、文件系统类型FAT 或 littlefs v1/v2或为应用实现自定义块设备实现低层存储系统例如自建日志型存储、磨损均衡、OTA 固件区读写等需要精确控制块边界的场景理解底层布局掌握固件、文件系统与虚拟分区表在 Flash 中的排布关系。注意pyb.Flash只在 STM32 裸机移植ports/stm32中提供运行操作系统的 Unix 移植由宿主 OS 提供文件系统不涉及该接口。2. 构造函数与 Flash 布局pyb.Flash提供两个构造函数签名对应两种不同的寻址视角。2.1Flash()整盘视图已弃用from pyb import Flash flash Flash() # 已弃用将在未来版本移除该形式返回的块设备代表呈现给 USB 大容量存储USB MSC接口的虚拟磁盘其特点包括起始处包含一个虚拟分区表virtual partition table真实 Flash 从块0x100开始只实现简单块协议不能用于 littlefs 等需要扩展接口的文件系统官方文档明确标注此构造形式已弃用新代码应改用带start参数的形式。2.2Flash(*, start-1, len-1)子区间视图推荐from pyb import Flash # 从 Flash 起始处开始长度默认为剩余全部空间 flash pyb.Flash(start0) # 指定字节偏移与字节长度 flash pyb.Flash(start0x20000, len0x10000)参数规则参数含义约束start起始偏移字节默认-1表示 0必须为块大小的整数倍且0 start 可用空间len长度字节默认-1表示剩余全部必须为块大小的整数倍且0 len 可用空间 - start块大小说明内部 Flash 的块大小通常为 512 字节FLASH_BLOCK_SIZE这是文档中typically 512的来源从 storage.h 可以看到STM32N6 系列的块大小为 4096 字节。若使用外部 SPI Flash扩展块大小由MICROPY_HW_BDEV_BLOCKSIZE_EXT决定见 storage.c。2.3 源码中的参数校验逻辑从源码看pyb_flash_new_obj()storage.c对参数做了严格校验uint32_t bl_len (storage_get_block_count() - FLASH_PART1_START_BLOCK) * FLASH_BLOCK_SIZE; if (start -1) { start 0; } else if (!(0 start start bl_len start % MICROPY_HW_BDEV_BLOCKSIZE_EXT 0)) { return mp_const_none; } if (len -1) { len bl_len - start; } else if (!(0 len start len bl_len len % MICROPY_HW_BDEV_BLOCKSIZE_EXT 0)) { return mp_const_none; }可以推断start/len的取值空间由块计数减去0x100分区起始块后的实际可用容量决定参数不合法时pyb_flash_make_new()会抛出ValueErrorstorage.c。2.4 虚拟分区表与0x100偏移FLASH_PART1_START_BLOCK定义为0x100即 256 块 × 512 字节 128 KiB这是 Pyboard 传统布局中文件系统分区起点。Flash()单例对象pyb_flash_obj用负的起始偏移实现整盘 分区表视图// storage.c:288-293 // This Flash object represents the entire available flash, with emulated partition table at start const pyb_flash_obj_t pyb_flash_obj { { pyb_flash_type }, -(FLASH_PART1_START_BLOCK * FLASH_BLOCK_SIZE), // to offset FLASH_PART1_START_BLOCK 0, // actual size handled in ioctl, MP_BLOCKDEV_IOCTL_BLOCK_COUNT case };pyb_flash_obj_t结构体storage.c保存start字节、len字节与use_native_block_size标志Flash()的len在ioctl(4, ...)时才查询真实大小。3. 块设备协议readblocks / writeblocks / ioctlpyb.Flash的三个方法实现的是vfs.AbstractBlockDev定义的块协议同时支持简单接口与扩展接口两种签名。3.1 简单接口Simple interfaceflash.readblocks(block_num, buf) # 整块对齐读取 flash.writeblocks(block_num, buf) # 整块对齐写入从block_num指定的块开始读取/写入buf长度的数据buf长度必须是块大小的整数倍读写的块必须对齐写入前设备自身负责擦除如需。在 storage.c 中简单形式的readblocks会做块号换算后交给底层存储层block_num FLASH_PART1_START_BLOCK (int32_t)self-start / FLASH_BLOCK_SIZE; ret storage_read_blocks(bufinfo.buf, block_num, bufinfo.len / FLASH_BLOCK_SIZE);即最终物理块号 分区起始块0x100 对象自身起始块偏移 传入块号。3.2 扩展接口Extended interfaceflash.readblocks(block_num, buf, offset) flash.writeblocks(block_num, buf, offset)允许在块内任意字节偏移处读写任意长度的数据buf长度无需对齐块大小扩展形式绝不能隐式擦除调用方必须先通过ioctl(6, ...)完成擦除见 vfs.rstlittlefs 类文件系统强制要求块设备支持扩展接口。源码中扩展分支storage.c会进行越界检查并调用MICROPY_HW_BDEV_READBLOCKS_EXT/WRITEBLOCKS_EXT宏且仅对非单例对象生效——Flash()单例因带有虚拟分区表不支持扩展块访问。3.3 ioctl 操作码ioctl(cmd, arg)用于控制设备与查询参数操作码与 vfs.rst 中AbstractBlockDev的定义一一对应操作码语义pyb.Flash的实际行为见 storage.c1初始化设备调用storage_init()若arg1将使用扩展协议单例对象返回-1子区间对象切换到use_native_block_sizetrue2关闭设备调用storage_flush()3同步设备调用storage_flush()4返回块数量单例返回真实块计数storage_get_block_count()子区间返回len / 块大小5返回块大小FLASH_BLOCK_SIZE512使用扩展协议时返回MICROPY_HW_BDEV_BLOCKSIZE_EXT6擦除一块仅在使用扩展协议native block size时执行调用MICROPY_HW_BDEV_ERASEBLOCKS_EXT其他-返回None可忽略关于返回值按协议约定ioctl(4)必须实现并返回整数块数ioctl(5)返回块大小或None默认 512其他操作成功返回 0、失败返回OSErrorerrno 对应的负整数readblocks/writeblocks成功返回None或 0失败返回负 errno如-MP_EIO、越界时的-MP_EFAULT。3.4 一个完整的自定义文件系统分区示例结合以上知识可以在应用里把 Flash 的一段区域格式化为独立文件系统并挂载import os import vfs from pyb import Flash # 1. 从 Flash 中划出一块 512 KiB 的区域start/len 必须为 512 的倍数 bdev Flash(start0x80000, len0x80000) # 2. 创建文件系统FAT若固件编译了 littlefs 也可用 VfsLfs2但需扩展接口 vfs.VfsFat.mkfs(bdev) # 3. 挂载到指定目录 vfs.mount(bdev, /data) # 4. 像普通文件系统一样使用 with open(/data/log.txt, w) as f: f.write(sensor data) print(os.listdir(/data))提示vfs.VfsFat.mkfs(bdev)会调用ioctl(4)与ioctl(5)查询几何参数若使用vfs.VfsLfs2.mkfs(bdev)块设备必须支持扩展接口带offset参数与ioctl(6)擦除操作。详见 filesystem.rst 中的完整块设备实现范例。4. 与文件系统的关系挂载流程与启动逻辑4.1 默认挂载点在 STM32 / Pyboard 上内部 Flash 默认挂载为/flashSD 卡如存在挂载为/sd见 filesystem.rst。4.2 启动时的自动检测与挂载main.c 展示了固件启动时如何利用pyb.Flash建立文件系统默认块设备设为pyb_flash_obj整盘 虚拟分区表若固件编译了 littlefs会读取前两个块检测 littlefs 超级块superblockLFS1 魔数位于偏移 40LFS2 魔数位于偏移 8检测成功后调用pyb_flash_new_obj(0, len)创建精确覆盖文件系统的块设备若长度非法超级块损坏回退为pyb_flash_new_obj(0, -1)以尝试整盘挂载尝试mp_vfs_mount_and_chdir_protected(bdev, mount_point)挂载到/flash并切换工作目录若未发现文件系统且尚未创建则调用factory_reset_create_filesystem()自动创建全新文件系统。这也是power-on 时若未发现文件系统则自动创建 FAT 文件系统行为filesystem.rst的源码实现。4.3 与 USB MSC 的关系pyb_flash_init_vfs()storage.c将块设备协议函数与 FAT VFS 绑定并标记MP_BLOCKDEV_FLAG_NATIVE使用原生storage_read_blocks/storage_write_blocks快速路径。这就是Flash()无参构造反映USB 大容量存储接口呈现的虚拟磁盘的原因——USB MSC 导出的正是这份带分区表的整盘视图。5. 硬件说明内部 Flash 与外部 SPI Flash硬件上的一个关键差异即文档中的 Hardware NotePyboard D 等带外部 SPI Flash 的板卡固件被配置为将外部 SPI Flash 作为主存储。这类板卡在mpconfigboard.h中定义MICROPY_HW_BDEV_SPIFLASH_EXTENDED此时扩展块协议的读写宏会落到spi_bdev_readblocks_raw/spi_bdev_writeblocks_raw并叠加MICROPY_HW_BDEV_SPIFLASH_OFFSET_BYTES偏移见 storage.c 与 PYBD_SF6/mpconfigboard.h其他板卡使用MCU 内部 Flash如 STM32F4/F7/H7 系列此时走flash_bdev_*系列函数littlefs 内部 Flash组合下扩展块协议同样使能#elif (MICROPY_VFS_LFS1 || MICROPY_VFS_LFS2) MICROPY_HW_ENABLE_INTERNAL_FLASH_STORAGE。因此同一份pyb.FlashPython 代码在不同板卡上实际操作的物理介质可能不同——这由编译期宏决定Python 层无需感知但需要知道主存储到底落在哪块芯片上。6. 使用建议与注意事项新代码一律使用Flash(start0)官方已明确Flash()无参构造弃用且它只支持简单块协议、无法配合 littlefs参数必须块对齐start/len不满足块大小整数倍会直接抛ValueError建议先用ioctl(5)查询实际块大小再计算偏移区分两种接口整块对齐访问用简单接口需要 sub-block 粒度littlefs时用扩展接口且扩展写入前必须自行ioctl(6)擦除不要破坏系统分区0x100之前是虚拟分区表区域无参构造的整盘视图包含它自定义分区时建议从start0或明确计算的偏移开始避免覆盖启动代码区域结合 VFS 文档阅读块设备的完整契约返回值、擦除语义、操作码含义见 vfs.rst文件系统定制教程见 filesystem.rst固件编译相关是否支持 littlefs、扩展接口、外部 SPI Flash 均由构建配置决定可在 py/mpconfig.h 与板级mpconfigboard.h中确认相应宏。7. 总结pyb.Flash是 Pyboard 上唯一面向主存储块设备的内建 Python 接口。通过本文可以看到它表面上只是三个方法readblocks/writeblocks/ioctl底层却串联了虚拟分区表布局FLASH_PART1_START_BLOCK 0x100、块地址换算分区起始块 对象偏移 传入块号、简单/扩展双协议、内部 Flash 与外部 SPI Flash 双后端以及固件启动时的文件系统自动检测挂载逻辑。掌握这些细节你就能在 MicroPython 中自信地实现自定义分区、低层存储系统或深入调试文件系统层面的问题。延伸阅读类参考原文docs/library/pyb.Flash.rst块设备实现源码ports/stm32/storage.c对象定义与协议实现、ports/stm32/storage.hFLASH_BLOCK_SIZE、FLASH_PART1_START_BLOCK与 BDEV ioctl 枚举启动挂载逻辑ports/stm32/main.c块设备协议规范docs/library/vfs.rst文件系统定制教程docs/reference/filesystem.rst赞分享嵌入式语言运行时编程语言解释器编译器物联网系统编程【免费下载链接】micropythonMicroPython - a lean and efficient Python implementation for microcontrollers and constrained systems项目地址https://gitcode.com/gh_mirrors/mi/micropython点击查看免费下载相关推荐MicroPython mimxrt 模块深入解析NXP i.MX RT 的 Flash 存储与块设备接口MicroPython mimxrt 模块深入解析NXP i.MX RT 的 Flash 存储与块设备接口 本篇技术指南以 MicroPython 官方文档嵌入式语言运行时编程语言解释器编译器物联网系统编程DeepSeek-V4-Flash-NVFP4多GPU部署方案张量并行与分布式推理实践DeepSeek V4 Flash NVFP4多GPU部署方案张量并行与分布式推理实践 DeepSeek V4 Flash NVFP4是一款高性能AI模型通pypdf 实战全攻略一篇讲透 Python PDF 处理pypdf 实战全攻略一篇讲透 Python PDF 处理 手头有 200 份合同要批量盖水印、一个月攒下来的散 PDF 想拼成一份别一个个手动点了写个脚后端上一篇Android开发者必学HotFix框架多版本适配实战指南下一篇技术工作与搬迁指南创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考