1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
|
# FSDMMC 驱动程序
## 1. 概述
SD/MMC控制器主要提供对固态非易失性存储的内存卡的访问能力,包括多媒体存储卡(MMC,MultiMedia Card)和安全和数据保护卡(SD,Secure Digital Card)。
## 2. 功能
SD/MMC控制器驱动提供了SD/MMC卡的控制访问方法,
- 初始化SD/MMC控制器
- 以轮询方式发送/接收数据和命令
- 以中断方式发送/接收数据和命令
- 设置SD/MMC控制器的中断工作模式和中断响应函数
访问SD/MMC卡需要兼容一系列协议命令,这一部分驱动不提供,可以通过第三方框架sdmmc使用
驱动相关的源文件包括,
```
fsdmmc
├── fsdmmc.c
├── fsdmmc.h
├── fsdmmc_dma.c
├── fsdmmc_dma.h
├── fsdmmc_g.c
├── fsdmmc_hw.c
├── fsdmmc_hw.h
├── fsdmmc_intr.c
└── fsdmmc_sinit.c
```
## 3. 配置方法
以下部分将指导您完成 FSDMMC 驱动的软件配置:
- 初始化FSDMMC控制器
- 通过协议命令完成SD/MMC卡初始化
- 通过协议命令读写SD/MMC卡数据
## 4 应用示例
### [检测SD卡](../../../baremetal/example/peripheral/mmc/fsdmmc_probe)
### [SD/MMC卡协议实现](../../../third-party/sdmmc)
### [通过协议命令读写SD卡](../../../baremetal/example/storage/sdmmc_cmds)
### [通过文件系统使用SD卡](../../../baremetal/example/storage/sdmmc_fatfs)
## 5. API参考
### 5.1. 用户数据结构
- FSDMMC控制数据
```c
typedef struct
{
FSdmmcConfig config; /* Current active configs */
u32 is_ready; /* Device is initialized and ready */
FSdmmcEventHandler evt_handler[FSDMMC_EVT_NUM];
} FSdmmc; /* Device instance */
```
- FSDMMC配置数据
```c
typedef struct
{
u32 instance_id; /* Device instance id */
uintptr base_addr; /* Device base address */
u32 irq_num[FSDMMC_INTR_NUM];
} FSdmmcConfig;
```
- FSDMMC命令结构
```c
typedef struct
{
u32 cmdidx;
u32 cmdarg;
u32 resptype;
u32 response[4];
u32 flag;
#define FSDMMC_CMD_FLAG_NEED_STOP BIT(0)
#define FSDMMC_CMD_FLAG_NEED_INIT BIT(1)
#define FSDMMC_CMD_FLAG_EXP_RESP BIT(2)
#define FSDMMC_CMD_FLAG_EXP_LONG_RESP BIT(3)
#define FSDMMC_CMD_FLAG_NEED_RESP_CRC BIT(4)
#define FSDMMC_CMD_FLAG_EXP_DATA BIT(5)
#define FSDMMC_CMD_FLAG_WRITE_DATA BIT(6)
#define FSDMMC_CMD_FLAG_READ_DATA BIT(7)
#define FSDMMC_CMD_FLAG_NEED_AUTO_STOP BIT(8)
#define FSDMMC_CMD_FLAG_ADTC BIT(9)
FSdmmcData *data_p;
} FSdmmcCmd;
```
- FSDMMC数据结构
```c
typedef struct
{
u8 *buf;
u32 blksz;
u32 blkcnt;
u32 datalen;
} FSdmmcData;
```
- FSDMMC中断类型和中断事件
```c
enum
{
FSDMMC_DMA_BD_INTR = 0,
FSDMMC_CMD_INTR,
FSDMMC_ERROR_INTR,
FSDMMC_INTR_NUM
}; /* 中断类型 */
enum
{
FSDMMC_EVT_CARD_REMOVED = 0,
FSDMMC_EVT_CMD_DONE,
FSDMMC_EVT_CMD_ERROR,
FSDMMC_EVT_CMD_RESP_ERROR,
FSDMMC_EVT_DATA_ERROR,
FSDMMC_EVT_DATA_READ_DONE,
FSDMMC_EVT_DATA_WRITE_DONE,
FSDMMC_EVT_NUM
}; /* 事件类型 */
```
### 5.2 错误码定义
- [0x0] FSDMMC_SUCCESS : success
- [0x10c0001] FSDMMC_ERR_NOT_READY : FSDMMC控制器未初始化
- [0x10c0001] FSDMMC_ERR_TIMEOUT : 数据或者命令传输等待超时
- [0x10c0001] FSDMMC_ERR_CMD_FAILED : 命令传输失败
- [0x10c0001] FSDMMC_ERR_DATA_FAILED : 数据传输失败
- [0x10c0001] FSDMMC_ERR_CARD_NO_FOUND : 卡未检测到
- [0x10c0001] FSDMMC_ERR_INVALID_BUF : 数据缓冲区不合法
### 5.3. 用户API接口
#### FSdmmcLookupConfig
- 获取FSDMMC控制器默认配置
```c
const FSdmmcConfig *FSdmmcLookupConfig(u32 instance_id);
```
Note:
- instance_id从0开始,取决于FSDMMC控制器的个数
Input:
- {u32} instance_id 驱动控制器ID
Return:
- {const FSdmmcConfig *} FSDMMC默认配置,返回NULL如果找不到默认配置
#### FSdmmcCfgInitialize
- 初始化FSDMMC控制器, 使之可以使用
```c
FError FSdmmcCfgInitialize(FSdmmc *instance_p, const FSdmmcConfig *input_config_p);
```
Note:
- 输入配置通过FSdmmcLookupConfig获取,用户按照需要修改后传入此函数
Input:
- {FSdmmc} *instance_p FSDMMC驱动控制数据
- {FSdmmcConfig} *input_config_p FSDMMC用户输入配置
Return:
- {FError} 驱动初始化的错误码信息,FSDMMC_SUCCESS 表示初始化成功,其它返回值表示初始化失败
#### FSdmmcDeInitialize
- 去使能FSDMMC控制器, 清零实例数据
```c
void FSdmmcDeInitialize(FSdmmc *instance_p);
```
Note:
- 无
Input:
- {FSdmmc} *instance_p FSDMMC驱动控制数据
Return:
- 无
#### FSdmmcPollTransfer
- 通过FSDMMC轮询方式发送/接收数据和命令
```c
FError FSdmmcPollTransfer(FSdmmc *instance_p, FSdmmcCmd *cmd_data_p);
```
Note:
- FSDMMC控制器初始化后才能调用此函数
Input:
- {FSdmmc} *instance_p FSDMMC驱动控制数据
- {FSdmmcCmd} *cmd_data_p FSDMMC数据和命令
Return:
- {FError} 驱动初始化的错误码信息,FSDMMC_SUCCESS 表示发送/接收成功,其它返回值表示发送/接收失败
#### FSdmmcInterruptTransfer
- 通过FSDMMC中断方式发送/接收数据和命令
```c
FError FSdmmcInterruptTransfer(FSdmmc *instance_p, FSdmmcCmd *cmd_data_p);
```
Note:
- FSDMMC控制器初始化后才能调用此函数,使用前需要确保FSDMMC中断设置完成
Input:
- {FSdmmc} *instance_p FSDMMC驱动控制数据
- {FSdmmcCmd} *cmd_data_p FSDMMC数据和命令
Return:
- {FError} 驱动初始化的错误码信息,FSDMMC_SUCCESS 表示发送/接收成功,其它返回值表示发送/接收失败
#### FSdmmcGetInterruptMask
- 获取FSDMMC的中断掩码
```c
u32 FSdmmcGetInterruptMask(uintptr base_addr, u32 intr_type);
```
Note:
- FSDMMC控制器初始化后才能调用此函数
Input:
- {uintptr} base_addr FSDMMC控制器基地址
- {u32} intr_type FSDMMC中断类型, 参考FSDMMC_INTR_NUM
Return:
- {u32} 中断掩码
#### FSdmmcSetInterruptMask
- 设置FSDMMC的中断掩码
```c
void FSdmmcSetInterruptMask(uintptr base_addr, u32 intr_type, u32 mask, boolean enable);
```
Note:
- FSDMMC控制器初始化后才能调用此函数
Input:
- {uintptr} base_addr FSDMMC控制器基地址
- {u32} intr_type FSDMMC中断类型, 参考FSDMMC_INTR_NUM
- {u32} mask 中断掩码
- {boolean} enable TRUE:打开中断, FALSE:关闭中断
Return:
- 无
#### FSdmmcCmdInterrupHandler
- 命令中断响应函数
```c
void FSdmmcCmdInterrupHandler(s32 vector, void *param);
```
Note:
- 此函数用于设置FSDMMC中断时注册,用户可以自定义一个中断响应函数替换此函数
Input:
- vector 中断向量号
- {void} *param 中断响应输入参数
Return:
- 无
#### FSdmmcDmaInterrupHandler
- DMA中断响应函数
```c
void FSdmmcDmaInterrupHandler(s32 vector, void *param);
```
Note:
- 此函数用于设置FSDMMC中断时注册,用户可以自定义一个中断响应函数替换此函数
Input:
- {s32} vector 中断向量号
- {void} *param 中断响应输入参数
Return:
- 无
#### FSdmmcErrInterrupHandler
- 错误中断响应函数
```c
void FSdmmcErrInterrupHandler(s32 vector, void *param);
```
Note:
- 此函数用于设置FSDMMC中断时注册,用户可以自定义一个中断响应函数替换此函数
Input:
- {s32} vector 中断向量号
- {void} *param 中断响应输入参数
Return:
- 无
#### FSdmmcRegisterInterruptHandler
- 注册中断事件响应函数
```c
void FSdmmcRegisterInterruptHandler(FSdmmc *instance_p, u32 event, FSdmmcEventHandler handler);
```
Note:
- 此函数用于设置FSDMMC中断时注册,被注册的函数被FSdmmcCmdInterrupHandler、FSdmmcErrInterrupHandler
* 和FSdmmcDmaInterrupHandler调用
Input:
- {FSdmmc} *instance_p FSDMMC驱动控制数据
- {u32} event FSDMMC中断事件类型,参考FSDMMC_EVT_NUM
- {FSdmmcEventHandler} handler, FSDMMC中断事件响应函数
Return:
- 无
|