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
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
|
# FSDIO 驱动程序
## 1. 概述
SD/SDIO/eMMC控制器,主要支持SD卡,eMMC介质的访问能力,同时支持连接SDIO接口设备,目前 FSDIO 驱动已经支持 SD 卡的访问
## 2. 功能
FSDIO 驱动提供了SD/MMC卡的控制访问方法,
- 初始化SD/MMC控制器
- 以轮询方式发送/接收数据和命令
访问SD/MMC卡需要兼容一系列协议命令,这一部分驱动不提供,可以通过第三方框架sdmmc使用
驱动相关的源文件包括,
```
fsdio
├── fsdio.c
├── fsdio.h
├── fsdio_cmd.c
├── fsdio_dma.c
├── fsdio_g.c
├── fsdio_hw.h
├── fsdio_intr.c
├── fsdio_pio.c
├── fsdio_selftest.
```
## 3. 配置方法
以下部分将指导您完成 FSDIO 驱动的软件配置:
- 初始化 FSDIO 控制器
- 通过协议命令完成 SD/MMC 卡初始化
- 通过协议命令读写 SD/MMC 卡数据
## 4 应用示例
### [通过协议命令读写SD卡](../../../baremetal/example/storage/sdio_cmds)
## 5. API参考
### 5.1. 用户数据结构
#### FSdio
- SDIO intance
```c
typedef struct _FSdio
{
FSdioConfig config; /* Current active configs */
u32 is_ready; /* Device is initialized and ready */
FSdioIDmaDescList desc_list; /* DMA descriptor list, valid in DMA trans mode */
FSdioEvtHandler evt_handlers[FSDIO_NUM_OF_EVT]; /* call-backs for interrupt event */
void *evt_args[FSDIO_NUM_OF_EVT]; /* arguments for event call-backs */
FSdioRelaxHandler relax_handler;
u32 prev_cmd; /* record previous command code */
} FSdio; /* SDIO intance */
```
#### FSdioConfig
- SDIO intance configuration
```c
typedef struct
{
u32 instance_id; /* Device instance id */
uintptr base_addr; /* Device base address */
u32 irq_num; /* Interrupt num */
FSdioTransMode trans_mode; /* Trans mode, PIO/DMA */
FSdioSpeedType speed; /* Trans speed type */
FSdioVoltageType voltage; /* Card voltage type */
boolean non_removable; /* No removeable media, e.g eMMC */
boolean filp_resp_byte_order; /* Some SD protocol implmentation may not do byte-order filp */
} FSdioConfig; /* SDIO intance configuration */
```
#### FSdioCmdData
- SDIO trans command and data
```c
typedef struct
{
u32 cmdidx; /* command index */
u32 cmdarg; /* command argument */
u32 response[4]; /* command response buffer */
u32 flag; /* command flags */
#define FSDIO_CMD_FLAG_NEED_INIT BIT(1) /* need initialization */
#define FSDIO_CMD_FLAG_EXP_RESP BIT(2) /* need reply */
#define FSDIO_CMD_FLAG_EXP_LONG_RESP BIT(3) /* need 136 bits long reply */
#define FSDIO_CMD_FLAG_NEED_RESP_CRC BIT(4) /* need CRC */
#define FSDIO_CMD_FLAG_EXP_DATA BIT(5) /* need trans data */
#define FSDIO_CMD_FLAG_WRITE_DATA BIT(6) /* need trans data to write card */
#define FSDIO_CMD_FLAG_READ_DATA BIT(7) /* need trans data to read card */
#define FSDIO_CMD_FLAG_NEED_AUTO_STOP BIT(8) /* need auto stop after command */
#define FSDIO_CMD_FLAG_ADTC BIT(9) /* need ADTC */
#define FSDIO_CMD_FLAG_SWITCH_VOLTAGE BIT(10) /* need switch voltage */
FSdioData *data_p; /* SDIO trans data */
} FSdioCmdData; /* SDIO trans command and data */
```
#### FSdioIDmaDesc
- SDIO DMA descriptor
```c
typedef struct
{
u32 attribute; /* ds0 */
#define FSDIO_IDMAC_DES0_DIC BIT(1)/* 内部描述表不触发TI/RI中断 */
#define FSDIO_IDMAC_DES0_LD BIT(2)/* 数据的最后一个描述符 */
#define FSDIO_IDMAC_DES0_FD BIT(3)/* 数据的第一个描述符 */
#define FSDIO_IDMAC_DES0_CH BIT(4)/* 链接下一个描述符地址 */
#define FSDIO_IDMAC_DES0_ER BIT(5)/* 链表已经到达最后一个链表 */
#define FSDIO_IDMAC_DES0_CES BIT(30)/* RINTSTS寄存器错误汇总 */
#define FSDIO_IDMAC_DES0_OWN BIT(31)/* 描述符关联DMA,完成传输后该位置置0 */
u32 non1; /* ds1 --> unused */
u32 len; /* ds2 bit[25:13] buffer2 size,bit[12:0] buffer1 size*/
#define FSDIO_IDMAC_DES2_BUF1_MASK GENMASK(12, 0)
#define FSDIO_IDMAC_DES2_BUF1_SIZE(x) (FSDIO_IDMAC_DES2_BUF1_MASK & (x))
#define FSDIO_IDMAC_DES2_BUF2_MASK GENMASK(25, 13)
#define FSDIO_IDMAC_DES2_BUF2_SIZE(x) (FSDIO_IDMAC_DES2_BUF2_MASK & (x << 13))
u32 non2; /* ds3 --> unused */
u32 addr_lo; /* ds4 Lower 32-bits of Buffer Address Pointer 1 --> buffer 1 */
u32 addr_hi; /* ds5 Upper 32-bits of Buffer Address Pointer 1 */
u32 desc_lo; /* ds6 Lower 32-bits of Next Descriptor Address --> buffer 2 */
u32 desc_hi; /* ds7 Upper 32-bits of Next Descriptor Address */
} __attribute__ ((packed)) __attribute((aligned(4))) FSdioIDmaDesc; /* SDIO DMA descriptor */
```
### 5.2 错误码定义
- FSDIO_SUCCESS : 操作成功
- FSDIO_ERR_TIMEOUT :操作超时失败
- FSDIO_ERR_NOT_INIT :控制器未初始化
- FSDIO_ERR_SHORT_BUF :缓冲区大小不足
- FSDIO_ERR_NOT_SUPPORT :操作不支持
- FSDIO_ERR_INVALID_STATE :控制器的状态不合法
- FSDIO_ERR_TRANS_TIMEOUT :传输数据超时失败
- FSDIO_ERR_CMD_TIMEOUT :传输命令超时失败
- FSDIO_ERR_NO_CARD :卡不在位
- FSDIO_ERR_BUSY : 卡处于繁忙状态
### 5.3. 用户API接口
#### FSdioLookupConfig
```c
const FSdioConfig *FSdioLookupConfig(u32 instance_id)
```
Note:
- Get the device instance default configure
Input:
- {u32} instance_id
Return:
- {const FSdioConfig *} default configure
#### FSdioCfgInitialize
```c
FError FSdioCfgInitialize(FSdio *const instance_p, const FSdioConfig *input_config_p)
```
Note:
- initialization SDIO controller instance
- get into card-detect mode after initialization, bus width = 1, card freq = 400kHz
Input:
- {FSdio} *instance_p, SDIO controller instance
- {FSdioConfig} *input_config_p, SDIO controller configure
Return:
- {FError} FSDIO_SUCCESS if initialization success, otherwise failed
#### FSdioDeInitialize
```c
void FSdioDeInitialize(FSdio *const instance_p)
```
Note:
- deinitialization SDIO controller instance
Input:
- {FSdio} *instance_p, SDIO controller instance
Return:
- {NONE}
#### FSdioSetIDMAList
```c
FError FSdioSetIDMAList(FSdio *const instance_p, volatile FSdioIDmaDesc *desc, u32 desc_num)
```
Note:
- Setup DMA descriptor for SDIO controller instance
Input:
- {FSdio} *instance_p, SDIO controller instance
- {volatile FSdioIDmaDesc} *desc, first item in DMA descriptor lists
- {u32} desc_num, number of items in DMA descriptor lists
Return:
- {FError} FSDIO_SUCCESS if setup done, otherwise failed
#### FSdioSetClkFreq
```c
void FSdioSetClkFreq(FSdio *const instance_p, u32 input_clk_hz)
```
Note:
- Set the Card clock freqency
Input:
- {FSdio} *instance_p, SDIO controller instance
- {u32} input_clk_hz, Card clock freqency in Hz
Return:
- {None}
#### FSdioGetClkFreq
```c
u32 FSdioGetClkFreq(FSdio *const instance_p)
```
Note:
- Get the Card clock freqency
Input:
- {FSdio} *instance_p, SDIO controller instance
Return:
- {u32} real clock in Hz
#### FSdioDMATransfer
```c
FError FSdioDMATransfer(FSdio *const instance_p, FSdioCmdData *const cmd_data_p)
```
Note:
- Start command and data transfer in DMA mode
Input:
- {FSdio} *instance_p, SDIO controller instance
- {FSdioCmdData} *cmd_data_p, contents of transfer command and data
Return:
- {FError} FSDIO_SUCCESS if transfer success, otherwise failed
#### FSdioPollWaitDMAEnd
```c
FError FSdioPollWaitDMAEnd(FSdio *const instance_p, FSdioCmdData *const cmd_data_p)
```
Note:
- Wait DMA transfer finished by poll
Input:
- {FSdio} *instance_p, SDIO controller instance
- {FSdioCmdData} *cmd_data_p, contents of transfer command and data
Return:
- {FError} FSDIO_SUCCESS if wait success, otherwise wait failed
#### FSdioGetInterruptMask
```c
u32 FSdioGetInterruptMask(FSdio *const instance_p, FSdioIntrType type)
```
Note:
- Get SDIO controller interrupt mask
Input:
- {FSdio} *instance_p, SDIO controller instance
- {FSdioIntrType} type, Type of interrupt, controller/DMA interrupt
Return:
- {u32} interrupt mask bits
#### FSdioSetInterruptMask
```c
void FSdioSetInterruptMask(FSdio *const instance_p, FSdioIntrType type, u32 set_mask, boolean enable)
```
Note:
- Enable/Disable SDIO controller interrupt
Input:
- {FSdio} *instance_p, SDIO controller instance
- {FSdioIntrType} type, Type of interrupt, controller/DMA interrupt
- {u32} set_mask, interrupt mask bits
- {boolean} enable, TRUE: enable interrupt mask bits
Return:
- {NONE}
#### FSdioInterruptHandler
```c
void FSdioInterruptHandler(s32 vector, void *param)
```
Note:
- Interrupt handler for SDIO instance
Input:
- {s32} vector, Interrupt id
- {void} *param, Interrupt params, is SDIO instance
Return:
- {NONE}
#### FSdioRegisterEvtHandler
```c
void FSdioRegisterEvtHandler(FSdio *const instance_p, FSdioEvtType evt, FSdioEvtHandler handler, void *handler_arg)
```
Note:
- Register event call-back function as handler for interrupt events
Input:
- {FSdio} *instance_p, SDIO controller instance
- {FSdioEvtType} evt, interrupt event
- {FSdioEvtHandler} handler, event call-back function
- {void} *handler_arg, argument of event call-back function
Return:
- {NONE}
#### FSdioPIOTransfer
```c
FError FSdioPIOTransfer(FSdio *const instance_p, FSdioCmdData *const cmd_data_p)
```
Note:
- Start command and data transfer in PIO mode
Input:
- {FSdio} *instance_p, SDIO controller instance
- {FSdioCmdData} *cmd_data_p, contents of transfer command and data
Return:
- {FError} FSDIO_SUCCESS if transfer success, otherwise failed
#### FSdioPollWaitPIOEnd
```c
FError FSdioPollWaitPIOEnd(FSdio *const instance_p, FSdioCmdData *const cmd_data_p);
```
Note:
- Wait PIO transfer finished by poll
Input:
- {FSdio} *instance_p, SDIO controller instance
- {FSdioCmdData} *cmd_data_p, contents of transfer command and data
Return:
- {FError} FSDIO_SUCCESS if wait success, otherwise wait failed
#### FSdioGetCmdResponse
```c
FError FSdioGetCmdResponse(FSdio *const instance_p, FSdioCmdData *const cmd_data_p)
```
Note:
- Get cmd response and received data after wait poll status or interrupt signal
Input:
- {FSdio} *instance_p, SDIO controller instance
- {FSdioCmdData} *cmd_data_p, contents of transfer command and data
Return:
- {FError} FSDIO_SUCCESS if get success
#### FSdioRestart
```c
FError FSdioRestart(FSdio *const instance_p)
```
Note:
- reset controller from error state
Input:
- {FSdio} *instance_p, instance of controller
Return:
- {FError} FSDIO_SUCCESS if restart success
|