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-bit SD 模式驅動。在 OpenMV Cam RT1062 上,插槽由 i.MX RT 的 USDHC 控制器驅動,同樣採用 4-bit SD 模式。目前所有 OpenMV 開發板都不需要任何接腳多工(pin-mux)參數,因為驅動程式已知曉開發板的接線方式。

在 OpenMV Cam AE3(alif 移植版)上未提供此功能。

建構子

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

回傳由 id 所指定 SD 插槽的 SDCard 單例(singleton)。id 是為了跨移植版相容性而接受的參數,但 OpenMV 支援的移植版僅提供一個插槽;請傳入 1 或省略此參數。

在 STM32 上,建構子完全不接受任何參數;在 mimxrt 上,會接受 id 參數,但僅 1 為有效值。

方法

present() bool

若插槽中目前偵測到卡片則回傳 True,否則回傳 False

在配備卡片偵測(card-detect)訊號接線的開發板上,此方法會即時反映該訊號,因此在 SDCard 物件建構之後可輪詢此方法,以對熱插拔做出反應。在沒有卡片偵測訊號的開發板上,此值會在建構時鎖存(latch)——它回報的是驅動程式在建立物件時所執行的初始 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 供電,因此此呼叫實際上是無操作(no-op)。保留此方法是為了與最初為上游 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 移植版。