存储设备驱动
AD16N SDK 中的存储设备驱动层为 NOR Flash、SD 卡(含 CD-ROM 模拟与加密分区)、U 盘(USB 大容量存储)等存储介质提供统一抽象,通过 dev_node/device 注册表与 struct device_operations 操作集向上层文件系统与业务逻辑暴露标准化的打开、读写、控制接口。
Purpose and Scope
本页面向存储设备驱动子系统,覆盖以下内容:
- 设备抽象层:
dev_node、device、device_operations的定义与注册机制(.device段)。 - 设备管理 API:
dev_open、dev_ioctl、dev_close、dev_byte_read/write、dev_bulk_read/write等。 - 设备类型、状态与错误码枚举(
dev_type、dev_sta、dev_err)。 - NOR Flash 驱动(
sfc/ext_flsh):命令集、互斥锁与擦除类型。 - SD 卡驱动(
sd0/sd_cdrom/sd_enc):sdx_dev_*系列接口。
以下相关主题属于兄弟页面,不在本页展开:上层文件系统与分区表(见文件系统相关页面)、USB 协议栈与 OTG 控制器(见 USB 相关页面)、设备管理中间件(dev_mg)的调度细节。
Overview
存储设备驱动是连接物理存储介质与上层文件系统/业务应用的桥梁。AD16N 是一颗 MCU SoC,其存储形态包括:
- 片内/片外 SPI NOR Flash(设备名
sfc、ext_flsh),承载固件、配置与用户数据; - SD/TF 卡(
sd0),支持普通文件系统、CD-ROM 模拟(sd_cdrom)与加密分区(sd_enc); - USB U 盘(
udisk0),通过 USB Host 栈挂载的大容量存储。
驱动的设计目标:
- 统一抽象:所有存储介质都注册为
struct dev_node,实现同一套struct device_operations函数指针,上层代码无需关心介质差异。 - 引用计数管理:
struct device内含atomic_t ref,支持多任务共享打开的设备句柄。 - 扇区级批量接口:
dev_bulk_read/write以扇区为单位,面向文件系统;dev_byte_read/write以字节为单位,面向配置读写等小数据场景。
Architecture
flowchart TD
subgraph sg_App["应用/文件系统层"]
FS["文件系统 / 业务逻辑"]
end
subgraph sg_DevMg["设备管理层 dev_mg"]
REG["dev_node 注册表<br/>(.device 段)"]
OPS["struct device_operations<br/>online/init/open/read/write<br/>bulk_read/bulk_write/ioctl/close"]
DEV["struct device<br/>(atomic ref + ops)"]
end
subgraph sg_Drivers["存储设备驱动"]
SFC["sfc / ext_flsh 驱动<br/>NOR Flash (SPI)"]
SD0["sd0 驱动<br/>SD/TF 卡"]
SDCD["sd_cdrom 驱动<br/>CD-ROM 模拟"]
SDENC["sd_enc 驱动<br/>加密分区"]
UDISK["udisk0 驱动<br/>USB 大容量存储"]
end
subgraph sg_Media["物理介质"]
FLASH[(SPI NOR Flash)]
SDCARD[(SD/TF Card)]
USBDEV[(USB U-Disk)]
end
FS -->|"dev_open / dev_ioctl / dev_bulk_read"| DEV
DEV --> OPS
OPS --> REG
REG --> SFC
REG --> SD0
REG --> SDCD
REG --> SDENC
REG --> UDISK
SFC --> FLASH
SD0 --> SDCARD
SDCD --> SDCARD
SDENC --> SDCARD
UDISK --> USBDEV
架构说明:上层只与 struct device 交互,通过 dev_open(name) 按名字查找 dev_node,获得绑定驱动操作集的 device 句柄。每个驱动(如 sfc_dev_ops)在链接期通过 REGISTER_DEVICE 宏放入 .device 段,devices_init() 在启动时遍历该段完成初始化。这样新增一种存储介质只需实现一套 device_operations 并注册,无需改动上层代码——这是典型的驱动-设备分离设计。
设备抽象层与注册机制
核心数据结构
存储驱动的三大核心结构定义在 sdk/apps/include_lib/dev_mg/device.h:
struct device_operations {
bool (*online)(const struct dev_node *node);
int (*init)(const struct dev_node *node, void *);
int (*open)(const char *name, struct device **device, void *arg);
int (*read)(struct device *device, void *buf, u32 len, u32);
int (*write)(struct device *device, void *buf, u32 len, u32);
int (*bulk_read)(struct device *device, void *buf, u32 len, u32);
int (*bulk_write)(struct device *device, void *buf, u32 len, u32);
int (*seek)(struct device *device, u32 offset, int orig);
int (*ioctl)(struct device *device, u32 cmd, u32 arg);
int (*close)(struct device *device);
};
struct dev_node {
const char *name;
const struct device_operations *ops;
void *priv_data;
};
struct device {
atomic_t ref;
void *private_data;
const struct device_operations *ops;
void *platform_data;
void *driver_data;
};
Source: device.h
设计要点:
struct device_operations是纯函数指针集合,一个驱动(如sfc_dev_ops)就是一张该结构的静态表。read/write与bulk_read/bulk_write并存:前者用于字节寻址(如配置区),后者用于扇区寻址(如文件系统簇读写)。struct dev_node是注册条目:名字 + 操作集 + 私有数据,作为驱动实例存在于.device链接段。struct device是打开后的句柄:atomic_t ref做引用计数,private_data/driver_data供驱动保存介质上下文(如 SPI 句柄、卡状态)。
注册宏与链接段
驱动通过宏将节点放入 .device 段,链接脚本负责把段内所有节点排布在 device_node_begin 与 device_node_end 之间:
#define REGISTER_DEVICE(node) \
const struct dev_node node sec_used(.device)
#define REGISTER_DEVICES(node) \
const struct dev_node node[] sec_used(.device)
extern const struct dev_node device_node_begin[];
extern const struct dev_node device_node_end[];
Source: device.h
REGISTER_DEVICES 支持一次注册数组形式的多个节点(例如同一驱动管理多个 SD 卡槽)。devices_init() 遍历 [device_node_begin, device_node_end) 区间,对每个节点调用其 ops->init;该函数注释明确说明它只能由 devices_init_api() 调用,不可单独使用,避免重复初始化。
设备命名约定
系统预定义了以下存储设备名(device.h 顶部宏):
| 宏 | 设备名 | 介质 |
|---|---|---|
__SFC_NANE | "sfc" | 片内 SPI NOR Flash |
__SD0_NANE | "sd0" | SD/TF 卡 0 |
__SD_CDROM | "sd_cdrom" | SD 卡 CD-ROM 模拟 |
__SD_ENC | "sd_enc" | SD 卡加密分区 |
__EXT_FLASH_NANE | "ext_flsh" | 外部扩展 NOR Flash |
__UDISK | "udisk0" | USB U 盘 |
__OTG | "otg" | USB OTG 控制器 |
Source: device.h
设备类型、状态与错误码
device_drive.h 定义了驱动层的设备类型枚举 dev_type,将物理设备与逻辑设备统一编号:
typedef enum _dev_type {
DEV_SDCRAD_0 = 0X10,
DEV_SDCRAD_1,
DEV_SDCRAD_2,
DEV_UDISK_H0,
DEV_UDISK_H1,
DEV_UDISK_F0,
DEV_NOR_FLASH,
DEV_NAND_FLASH,
DEV_STORAGE = 0x100,
DEV_LOGIC_DISK = 0x101,
DEV_USB_SLAVE,
DEV_USB_HOST,
DEV_HID = 0x200,
DEV_NET,
DEV_AUDIO,
DEV_ISP,
} dev_type;
Source: device_drive.h
SD 卡与 U 盘占用 0x10~0x15,NOR/NAND Flash 紧随其后;0x100 起为逻辑层类型(存储设备、逻辑盘、USB 主从),0x200 起为其他外设(HID、网络、音频、ISP)。该枚举与 dev_io_t 结构配套,dev_io_t 是驱动提供给文件系统层的另一套接口(mount/unmount/read/write/ioctrl/power/detect),与 device_operations 互补:前者面向块设备挂载,后者面向句柄式读写。
状态枚举 dev_sta 定义了设备热插拔与电源状态:
typedef enum dev_sta {
DEV_OFFLINE = 0, // 设备从在线切换到离线
DEV_ONLINE = 1, // 设备从离线切换到在线
DEV_HOLD = 2, // 设备状态未改变
DEV_POWER_ON = 0x10,// 开机
DEV_POWER_OFF, // 关机
DEV_POWER_STANDBY, // 待机
DEV_POWER_WAKEUP, // 唤醒
} DEV_STA;
Source: device_drive.h
错误码枚举 dev_err 从 DEV_ERR_NONE 起按类别排列:挂载/容量类(NOT_MOUNT、OVER_CAPACITY)、就绪类(NOT_READY)、超时类(TIMEOUT、CMD_TIMEOUT、READ_TIMEOUT、WRITE_TIMEOUT)、离线类(OFFLINE)、CRC 类(CRC、CMD_CRC、READ_CRC、WRITE_CRC)、USB 控制传输类(CONTROL_STALL、RXSTALL、TXSTALL)以及存储路径类(NOT_STORAGE、INVALID_PATH 等)。这些错误码为上层文件系统与用户层提供了统一的错误语义,避免各驱动各自为政。
NOR Flash 驱动(sfc / ext_flsh)
驱动开关与无 OS 模式
NOR Flash 驱动由 TFG_EXT_FLASH_EN 编译开关控制:启用后定义 TCFG_NORFLASH_DEV_ENABLE 以启动 NOR Flash 驱动。
#if defined(TFG_EXT_FLASH_EN) && TFG_EXT_FLASH_EN
#define TCFG_NORFLASH_DEV_ENABLE //启动 nor flash
#endif
#define NORFLASH_NO_SYS 1 //0:使用操作系统,1:不使用操作系统
Source: norflash.h
NORFLASH_NO_SYS 决定互斥实现方式。MCU 裸机场景(NORFLASH_NO_SYS=1)下,驱动使用自旋式的 flash_mutex(本质是一个 volatile u8 信号量)保证对 SPI Flash 的独占访问;flash_mutex_pend 支持超时(timeout=0 表示死等),并在等待期间调用 wdt_clear() 喂狗,防止长时间占用 Flash 时看门狗复位:
static inline s8 flash_mutex_pend(flash_mutex *sem, u32 timeout)// 当为timeout=0时,死等
{
u32 _jiffies = maskrom_get_jiffies();
u32 _timeout = timeout + _jiffies;
extern void wdt_clear();
while (1) {
if (*sem) {
(*sem) = 0;
break;
}
if ((timeout != 0) && (_timeout < _jiffies)) {
return -1;
}
wdt_clear();
}
return 0;
}
Source: norflash.h
设计意图:Flash 擦写属于长耗时操作(扇区擦除可达数十毫秒),若多任务/中断同时访问 SPI 总线会产生竞态;而裸机下没有 RTOS 互斥量可用,故用轻量自旋锁 + 超时 + 喂狗组合,既保证互斥又防止系统因长时间关中断或忙等而复位。同时提供 query_flash_mutex_pend 非阻塞查询变体,供中断上下文探测锁状态。
Flash 命令集
驱动内置 WinBond W25X 系列命令集,覆盖完整的读写擦生命周期:
#define WINBOND_WRITE_ENABLE 0x06
#define WINBOND_READ_SR1 0x05
#define WINBOND_READ_SR2 0x35
#define WINBOND_WRITE_SR1 0x01
#define WINBOND_WRITE_SR2 0x31
#define WINBOND_READ_DATA 0x03
#define WINBOND_FAST_READ_DATA 0x0b
#define WINBOND_FAST_READ_DUAL_OUTPUT 0x3b
#define WINBOND_PAGE_PROGRAM 0x02
#define WINBOND_PAGE_ERASE 0x81
#define WINBOND_SECTOR_ERASE 0x20
#define WINBOND_BLOCK_ERASE 0xD8
#define WINBOND_CHIP_ERASE 0xC7
#define WINBOND_JEDEC_ID 0x9F
#define WINBOND_POWER_DOWN 0xB9
#define WINBOND_RELEASE_POWER_DOWN 0xAB
Source: norflash.h
命令设计遵循 NOR Flash 规范:写操作前必须先 WRITE_ENABLE (0x06);状态寄存器读取(READ_SR1)用于轮询写/擦完成位(WIP);提供四级擦除粒度——页擦除(0x81)、扇区擦除(0x20,4KB)、块擦除(0xD8,64KB)、整片擦除(0xC7),上层根据数据量选择最小合适的擦除粒度以平衡速度与磨损。JEDEC_ID (0x9F) 用于上电识别 Flash 厂商与型号,POWER_DOWN/RELEASE_POWER_DOWN 用于低功耗管理。
擦除类型枚举
enum {
FLASH_PAGE_ERASER,
FLASH_SECTOR_ERASER,
...
};
Source: norflash.h
该枚举供 ioctl 命令(如 IOCTL_FLASH_ERASE_SECTOR 等,定义于 ioctl_cmds.h)选择擦除粒度,驱动据此分发到对应的擦除命令。
SD 卡驱动(sd0 / sd_cdrom / sd_enc)
SD 卡接口族
SD 卡驱动以 sdx_dev_* 为前缀,在 sdk/apps/include_lib/device/sdmmc/sd.h 中声明,覆盖从初始化到关闭的完整生命周期:
extern int sdx_dev_init(const struct dev_node *node, void *arg);
extern bool sdx_dev_online(const struct dev_node *node);
extern int sdx_dev_open(const char *name, struct device **device, void *arg);
extern int sdx_dev_byte_read(struct device *device, void *buf, u32 len, u32 offset);
extern int sdx_dev_byte_write(struct device *device, void *buf, u32 len, u32 offset);
extern int sdx_dev_read(struct device *device, void *buf, u32 len, u32 offset);
extern int sdx_dev_write(struct device *device, void *buf, u32 len, u32 offset);
extern int sdx_dev_ioctl(struct device *device, u32 cmd, u32 arg);
extern int sdx_dev_close(struct device *device);
Source: sd.h
接口与 struct device_operations 一一对应,说明 sdx_* 函数族就是 sd0 设备节点的 ops 实现体。sdx_dev_online 用于热插拔检测(轮询卡检测引脚或命令响应),sdx_dev_ioctl 透传容量查询、只读状态、写保护等命令。
SD 卡功能变体
SD 卡驱动还派生出两个功能变体,同一物理介质、不同逻辑角色:
sd_cdrom(CD-ROM 模拟):sd_cdrom_dev_init/open/read/ioctl/close,将 SD 卡内容以只读光驱形式暴露,通常用于车机/音箱等场景的固件升级盘或媒体盘模拟。sd_enc(加密分区):sd_enc_dev_init/open/read/write/ioctl,在标准读写之外增加加密变换,用于保护版权内容或私有数据。
//*****************sd_cdrom区
int sd_cdrom_dev_init(const struct dev_node *node, void *arg);
bool sd_cdrom_dev_online(const struct dev_node *node);
int sd_cdrom_dev_open(const char *name, struct device **device, void *arg);
int sd_cdrom_dev_read(struct device *device, void *buf, u32 len, u32 offset);
int sd_cdrom_dev_ioctl(struct device *device, u32 cmd, u32 arg);
int sd_cdrom_dev_close(struct device *device);
//*****************sd_enc区
int sd_enc_dev_init(const struct dev_node *node, void *arg);
bool sd_enc_dev_online(const struct dev_node *node);
int sd_enc_dev_open(const char *name, struct device **device, void *arg);
int sd_enc_dev_read(struct device *device, void *buf, u32 len, u32 offset);
int sd_enc_dev_write(struct device *device, void *buf, u32 len, u32 offset);
int sd_enc_dev_ioctl(struct device *device, u32 cmd, u32 arg);
注意 sd_cdrom 没有 write 接口(只读光驱语义),而 sd_enc 提供完整的 read/write。三者可分别注册为独立 dev_node,由应用按需 dev_open,互不干扰。
Core Flow:设备打开与读写时序
一次典型的存储读写请求(如文件系统读一个扇区)按以下顺序穿过抽象层:
sequenceDiagram
participant FS as 文件系统/应用
participant MG as 设备管理 (dev_mg)
participant OP as device_operations 表
participant DRV as 驱动实现 (sdx_dev_*/sfc)
participant MED as 物理介质 (SD/Flash)
FS->>MG: dev_open("sd0", arg)
MG->>MG: 遍历 .device 段查找 dev_node
MG->>OP: ops->open(name, &device, arg)
OP->>DRV: sdx_dev_open(...)
DRV->>MED: 卡初始化/命令准备
DRV-->>OP: 返回 device 句柄
OP-->>MG: 填充 struct device (ref=1)
MG-->>FS: void* device
FS->>MG: dev_bulk_read(device, buf, sector, num)
MG->>OP: ops->bulk_read(device, buf, len, offset)
OP->>DRV: sdx_dev_read(...)
DRV->>MED: CMD17/CMD18 读块
MED-->>DRV: 数据块
DRV-->>FS: 拷贝到 buf
FS->>MG: dev_ioctl(device, cmd, arg)
MG->>OP: ops->ioctl(...)
OP-->>DRV: 容量/状态查询
FS->>MG: dev_close(device)
MG->>OP: ops->close(device)
OP->>DRV: sdx_dev_close(...) / ref--
流程要点:
- 打开阶段:
dev_open按名字在.device段注册表中定位dev_node,调用ops->open创建struct device,atomic_t ref初始化为 1,之后所有读写都通过该句柄进行。 - 读写阶段:上层调用
dev_bulk_read/write(扇区语义,offset为扇区号)或dev_byte_read/write(字节语义,offset为字节地址);设备管理函数将参数转发给对应ops函数指针,由具体驱动翻译成介质命令(SD 的 CMD17/CMD18、Flash 的 READ_DATA/PAGE_PROGRAM)。 - 控制阶段:
dev_ioctl是通用控制通道,承载容量查询、擦除命令、写保护等非读写操作。 - 关闭阶段:
dev_close递减引用计数并释放资源。
flowchart LR
A["dev_open(name)"] --> B{"节点存在?"}
B -->|"否"| E["返回 NULL"]
B -->|"是"| C{"ops->online?"}
C -->|"离线"| F["返回 NULL / 状态通知"]
C -->|"在线"| D["ops->open → struct device"]
D --> G["dev_bulk_read/write<br/>dev_ioctl<br/>dev_close"]
数据模型与关系
classDiagram
class dev_node {
+const char* name
+const device_operations* ops
+void* priv_data
}
class device {
+atomic_t ref
+void* private_data
+const device_operations* ops
+void* platform_data
+void* driver_data
}
class device_operations {
<<interface>>
+online(node) bool
+init(node, arg) int
+open(name, device**, arg) int
+read(device, buf, len, offset) int
+write(device, buf, len, offset) int
+bulk_read(device, buf, len, offset) int
+bulk_write(device, buf, len, offset) int
+seek(device, offset, orig) int
+ioctl(device, cmd, arg) int
+close(device) int
}
class dev_io_t {
+char name[8]
+mount(parm) s32
+unmount() s32
+read(buf, addr, len) s32
+write(buf, addr, len) s32
+ioctrl(parm, cmd) s32
+power(mod) s32
+detect() s32
+dev_type device_type
}
dev_node --> device_operations : 绑定 ops
device --> device_operations : 调用 ops
dev_node ..> dev_io_t : 驱动另提供块设备接口
两类接口的协作关系:device_operations 是"句柄式"接口(先 open 拿句柄,再按句柄读写),服务于设备管理中间件与文件系统;dev_io_t 是"注册式"块设备接口(mount/unmount/read/write/ioctrl/power/detect 直接按地址操作),服务于上层存储管理框架。两者通过 dev_node 的 priv_data 或 device->driver_data 关联到同一驱动实例,实现"同一介质、两套视图"。
API Reference
设备管理 API(device.h)
| 函数 | 签名 | 说明 |
|---|---|---|
devices_init | int devices_init(void) | 遍历 .device 段初始化所有驱动,仅由 devices_init_api() 调用 |
devices_init_api | int devices_init_api(void) | 对外提供的设备初始化入口 |
dev_online | bool dev_online(const char *name) | 查询设备是否在线(热插拔检测) |
dev_open | void *dev_open(const char *name, void *arg) | 打开设备,返回 struct device* 句柄(失败返回 NULL) |
dev_ioctl | int dev_ioctl(void *device, int cmd, u32 arg) | 向设备发送控制命令 |
dev_close | int dev_close(void *device) | 关闭设备句柄,递减引用计数 |
dev_byte_read | int dev_byte_read(void *device, void *buf, u32 offset, u32 len) | 字节寻址读 |
dev_byte_write | int dev_byte_write(void *device, void *buf, u32 offset, u32 len) | 字节寻址写 |
dev_bulk_read | int dev_bulk_read(void *device, void *buf, u32 sector, u32 sector_num) | 扇区批量读 |
dev_bulk_write | int dev_bulk_write(void *device, void *buf, u32 sector, u32 sector_num) | 扇区批量写 |
set_device_node | struct dev_node_mg *set_device_node(struct dev_node *start, struct dev_node *end) | 自定义设备节点区间(动态注册) |
device_status_emit | int device_status_emit(const char *device_name, const u8 status) | 上报设备在线/离线/电源状态事件 |
Source: device.h
参数约定:
dev_byte_read/write与dev_bulk_read/write的参数顺序不同:字节接口为(buf, offset, len),批量接口为(buf, sector, sector_num)。前者 offset 是字节地址,后者 sector 是扇区号——调用时务必区分,避免混淆。dev_open返回void*,实际类型为struct device*,上层通常直接透传给读写函数,无需解引用内部字段。
NOR Flash 驱动接口(norflash.h)
| 符号 | 类型 | 说明 |
|---|---|---|
flash_mutex_create(sem, count) | inline | 初始化 Flash 互斥信号量 |
flash_mutex_pend(sem, timeout) | inline s8 | 获取锁,timeout=0 死等,超时返回 -1 |
flash_mutex_post(sem) | inline | 释放锁 |
query_flash_mutex_pend(sem, timeout) | inline s8 | 非阻塞探测锁状态 |
flash_mutex_set(sem, count) | inline | 强制设置锁值 |
TCFG_NORFLASH_DEV_ENABLE | 宏 | 使能 NOR Flash 驱动(由 TFG_EXT_FLASH_EN 触发) |
SD 卡驱动接口(sd.h)
sd0 设备:sdx_dev_init/online/open/byte_read/byte_write/read/write/ioctl/close(见上文代码),直接实现 device_operations 全部条目。
Configuration Options
| 配置项 | 类型 | 默认值 | 说明 |
|---|---|---|---|
TFG_EXT_FLASH_EN | 编译宏 | 0 | 使能外部扩展 Flash,开启后自动定义 TCFG_NORFLASH_DEV_ENABLE |
NORFLASH_NO_SYS | 编译宏 | 1 | 1=不使用 OS,采用自旋锁式 flash_mutex;0=使用 OS 互斥量 |
flash_mutex_pend 的 timeout | 函数参数 | 0(死等) | 锁获取超时(jiffies),非 0 时超时返回 -1 |
设备名宏(__SFC_NANE 等) | 宏 | "sfc"/"sd0" 等 | 设备注册名,上层 dev_open 按此查找 |
Failure Modes、边界情况与并发
设备离线与热插拔
dev_online(name)与驱动ops->online构成热插拔检测链:上层轮询在线状态,离线时dev_open返回 NULL。dev_err中的DEV_ERR_OFFLINE、DEV_ERR_NOT_READY(在线但未初始化完成)区分了两种失败时机。- SD 卡在读写中途拔出时,驱动层返回超时/CRC 类错误(
DEV_ERR_READ_TIMEOUT、DEV_ERR_READ_CRC等),上层应据此触发卸载流程而非重试风暴。
并发与互斥
- 句柄引用计数:
struct device.ref为atomic_t,多任务可共享同一句柄;dev_close递减,最后一个关闭者释放资源。 - Flash 独占:裸机模式下
flash_mutex自旋锁保证 SPI Flash 访问串行化;等待期间wdt_clear()喂狗,避免长擦除导致看门狗复位。若flash_mutex_pend超时(返回 -1),调用方必须放弃操作,不可重入写。 - 中断上下文:
query_flash_mutex_pend为非阻塞变体,供中断/高优先级上下文探测锁状态,避免死等。
容量与寻址边界
DEV_ERR_OVER_CAPACITY表示读写越过介质容量;dev_bulk_*的 sector 语义下,len为扇区数,驱动需换算为字节偏移并做边界检查。- Flash 擦写粒度差异(页/扇区/块/整片)要求上层按对齐边界下发擦除命令,否则可能破坏相邻数据。
字节接口与批量接口的混用
同一设备上字节接口(配置区)与批量接口(文件系统)并存。若二者没有共享互斥(device_drive.h 的 dev_io_t.mutex 即为此设计),并发混用可能导致 Flash 写状态机冲突;SD 驱动内部应保证命令串行。
Extension Points
- 新增存储介质驱动:实现
struct device_operations(至少init/open/read/write/ioctl/close),用REGISTER_DEVICE(node)注册到.device段,系统启动时自动初始化。参考sfc_dev_ops(device.h末尾导出)与sdx_dev_*函数族。 - 动态注册:
set_device_node(start, end)可在运行时注册额外节点区间,适用于需要动态枚举设备(如多 U 盘)的场景。 - 设备事件上报:
device_status_emit(name, status)将dev_sta状态(在线/离线/电源切换)广播给上层,供 UI 或电源管理订阅。 - 功能变体:参照
sd_cdrom(只读)与sd_enc(加密)模式,可基于同一底层驱动派生新的逻辑设备,仅重写device_operations中差异化的函数指针。
Related Links
- 设备管理中间件(dev_mg) — 本页所述
dev_open/dev_ioctl等 API 的调度与注册表实现。 - 文件系统与分区 — 基于本页批量读写接口的挂载与分区表管理(若目录存在)。
- USB 协议栈与 OTG —
udisk0设备背后的 USB Host/SCSI 实现(若目录存在)。 - 源码入口:device.h、device_drive.h、norflash.h、sd.h