class SDCard -- SD / MMC 卡驱动

SDCard 用于驱动配备 SD / MMC 卡槽的 OpenMV 摄像头上的卡槽。该驱动实现了 vfs.AbstractBlockDev 接口,因此可以直接传递给 vfs.mount():

import machine
import vfs

sd = machine.SDCard()
vfs.mount(sd, "/sd")

备注

OpenMV 固件会在启动时自动挂载 SD 卡,因此大多数脚本从不直接构造 SDCard —— 它们只是通过自动挂载的路径进行读写。仅当你需要非默认的挂载点,或需要通过 readblocks() / writeblocks() / ioctl() 进行原始块级访问时,才手动构造一个。

在 OpenMV Cam M7 / H7 / H7 Plus / Pure Thermal / N6 上,卡槽由 STM32 的片上 SDMMC 控制器以 4 位 SD 模式驱动。在 OpenMV Cam RT1062 上,卡槽由 i.MX RT 的 USDHC 控制器驱动,同样为 4 位 SD 模式。在当前的任何 OpenMV 开发板上都不需要引脚复用参数 —— 驱动已知晓开发板的接线方式。

在 OpenMV Cam AE3(alif port)上未公开。

构造函数

class machine.SDCard(id: int = 1) SDCard

返回由 id 标识的 SD 卡槽的 SDCard 单例。id 是为了跨端口兼容而被接受的,但 OpenMV 支持的端口只公开一个卡槽;请传入 1 或省略它。

在 STM32 上,构造函数完全不接受任何参数;在 mimxrt 上,id 参数会被接受,但只有 1 是有效的。

方法

present() bool

如果当前在卡槽中检测到卡,返回 True,否则返回 False

在接有插卡检测信号线的开发板上,该方法实时反映该信号,因此可以在 SDCard 对象构造完成后轮询它,以响应热插入 / 移除。在没有插卡检测信号的开发板上,该值在构造时被锁存 —— 它报告的是驱动在对象创建时进行的初始 CMD0 探测的结果,之后热插入的卡在重新构造对象(或在 mimxrt 上调用 init())之前将不可见。

info() tuple[int, int, int]

返回一个描述当前已插入卡的 3 元组:

  • [0] num_blocks —— 以 512 字节块为单位的总容量。乘以 512 可得到原始字节容量。

  • [1] block_size —— 对于 SD 卡始终为 512。包含该值是为了让调用者能够可移植地执行 num_blocks * block_size

  • [2] card_type —— SD 总线在 CMD8 / OCR 初始化握手期间报告的卡类型。典型值为 0(SDSC —— 标准容量)、0x40(SDHC / SDXC —— 高 / 扩展容量)和 0x80(MMC)。

可用于检查卡是否被正确识别,或用于显示相对于总容量的可用空间数值。

power(state: bool, /) None

打开或关闭卡槽的电源轨。STM32 固件公开了该方法,但当前没有任何 OpenMV Cam 对 SD 电源供应进行门控,因此该调用实际上是空操作。保留它是为了兼容最初为上游 MicroPython STM32 参考板编写的代码。仅限 STM32 端口。

read(block_num: int, /) bytes

从卡中读取单个 512 字节块,并将其作为新分配的 bytes 对象返回。

这是 STM32 端口提供的旧式单块读取方法。新代码应改用 readblocks() —— 该方法适用于每个 OpenMV 端口,可在一次传输中读取任意数量的连续块,并通过写入调用者提供的缓冲区来避免每次调用的内存分配。仅限 STM32 端口。

write(block_num: int, data: bytes, /) None

向卡写入单个 512 字节块。data 的长度必须恰好为 512 字节。

这是 STM32 端口提供的旧式单块写入方法;新代码应改用 writeblocks(),该方法适用于每个 OpenMV 端口,并可在每次调用中写入任意数量的连续块。仅限 STM32 端口。

readblocks(block_num: int, buf: bytearray) None
readblocks(block_num: int, buf: bytearray, offset: int) None

从卡中读取原始的块对齐数据到 buf 中。这是文件系统层使用的标准 vfs.AbstractBlockDev 块设备入口点。

简单形式readblocks(block_num, buf)):从块索引 block_num 开始读取整块。len(buf) 必须是 SD 块大小(512 字节)的整数倍。

扩展形式readblocks(block_num, buf, offset)):从块 block_num 内的字节 offset 开始读取 len(buf) 个字节 —— 不一定是整数个块。供 littlefs 和其他按字节寻址的文件系统使用。

writeblocks(block_num: int, buf: bytes | bytearray) None
writeblocks(block_num: int, buf: bytes | bytearray, offset: int) None

buf 中的原始块对齐数据写入卡中。这是文件系统层使用的标准 vfs.AbstractBlockDev 块设备入口点。

简单形式writeblocks(block_num, buf)):从块索引 block_num 开始写入整块。len(buf) 必须是 SD 块大小(512 字节)的整数倍。每个受影响的块都会被完整覆盖。

扩展形式writeblocks(block_num, buf, offset)):从块 block_num 内的字节 offset 开始写入 len(buf) 个字节 —— 不一定是整数个块。供 littlefs 和其他按字节寻址的文件系统使用。

ioctl(cmd: int, arg: int) int | None

标准的 vfs.AbstractBlockDev 控制入口点。由文件系统层在挂载/卸载时以及每次同步时调用。可识别的 cmd 值为:

  • 1 —— 初始化。成功时返回 0

  • 2 —— 反初始化。成功时返回 0

  • 3 —— 同步所有待处理的写入。返回 0(SDMMC 驱动同步写入,无需刷新)。

  • 4 —— 返回设备上的块数。

  • 5 —— 返回单个块的大小(始终为 512)。

  • 6 —— 擦除一个块(在 SD 上为空操作,保留是为了遵循 vfs.AbstractBlockDev 约定)。

  • 7 —— 返回设备是否支持块擦除(在 SD 上为 0)。

直接调用者通常不使用此方法 —— 一旦 SDCard 被挂载,文件系统驱动会自动分派所有标准代码。

init(*args, **kwargs) None

从头重新初始化 SD 接口。接受与构造函数相同的参数。对于在没有插卡检测信号的开发板上重新检测热插入的卡很有用,因为 present() 在其他情况下会在构造时被锁存。仅限 mimxrt 端口。

deinit() None

反初始化 SD 接口,释放 SDMMC/USDHC 控制器及其占用的 IO 引脚。在再次调用 init() 之前,SDCard 对象将不可用。在从另一个接口重新刷写卡之前使用它,或在电池供电的应用中切断卡槽电源时使用它。仅限 mimxrt 端口。