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
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
|
/*
ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
/**
* @file hal_mmcsd.h
* @brief MMC/SD cards common header.
* @details This header defines an abstract interface useful to access MMC/SD
* I/O block devices in a standardized way.
*
* @addtogroup MMCSD
* @{
*/
#ifndef HAL_MMCSD_H
#define HAL_MMCSD_H
#if (HAL_USE_MMC_SPI == TRUE) || (HAL_USE_SDC == TRUE) || defined(__DOXYGEN__)
/*===========================================================================*/
/* Driver constants. */
/*===========================================================================*/
/**
* @brief Fixed block size for MMC/SD block devices.
*/
#define MMCSD_BLOCK_SIZE 512U
/**
* @brief Mask of error bits in R1 responses.
*/
#define MMCSD_R1_ERROR_MASK 0xFDFFE008U
/**
* @brief Fixed pattern for CMD8.
*/
#define MMCSD_CMD8_PATTERN 0x000001AAU
/**
* @name SD/MMC status conditions
* @{
*/
#define MMCSD_STS_IDLE 0U
#define MMCSD_STS_READY 1U
#define MMCSD_STS_IDENT 2U
#define MMCSD_STS_STBY 3U
#define MMCSD_STS_TRAN 4U
#define MMCSD_STS_DATA 5U
#define MMCSD_STS_RCV 6U
#define MMCSD_STS_PRG 7U
#define MMCSD_STS_DIS 8U
/** @} */
/**
* @name SD/MMC commands
* @{
*/
#define MMCSD_CMD_GO_IDLE_STATE 0U
#define MMCSD_CMD_INIT 1U
#define MMCSD_CMD_ALL_SEND_CID 2U
#define MMCSD_CMD_SEND_RELATIVE_ADDR 3U
#define MMCSD_CMD_SET_BUS_WIDTH 6U
#define MMCSD_CMD_SWITCH MMCSD_CMD_SET_BUS_WIDTH
#define MMCSD_CMD_SEL_DESEL_CARD 7U
#define MMCSD_CMD_SEND_IF_COND 8U
#define MMCSD_CMD_SEND_EXT_CSD MMCSD_CMD_SEND_IF_COND
#define MMCSD_CMD_SEND_CSD 9U
#define MMCSD_CMD_SEND_CID 10U
#define MMCSD_CMD_STOP_TRANSMISSION 12U
#define MMCSD_CMD_SEND_STATUS 13U
#define MMCSD_CMD_SET_BLOCKLEN 16U
#define MMCSD_CMD_READ_SINGLE_BLOCK 17U
#define MMCSD_CMD_READ_MULTIPLE_BLOCK 18U
#define MMCSD_CMD_SET_BLOCK_COUNT 23U
#define MMCSD_CMD_WRITE_BLOCK 24U
#define MMCSD_CMD_WRITE_MULTIPLE_BLOCK 25U
#define MMCSD_CMD_ERASE_RW_BLK_START 32U
#define MMCSD_CMD_ERASE_RW_BLK_END 33U
#define MMCSD_CMD_ERASE 38U
#define MMCSD_CMD_APP_OP_COND 41U
#define MMCSD_CMD_LOCK_UNLOCK 42U
#define MMCSD_CMD_APP_CMD 55U
#define MMCSD_CMD_READ_OCR 58U
/** @} */
/**
* @name CSD record offsets
*/
/**
* @brief Slice position of values in CSD register.
*/
/* CSD for MMC */
#define MMCSD_CSD_MMC_CSD_STRUCTURE_SLICE 127U,126U
#define MMCSD_CSD_MMC_SPEC_VERS_SLICE 125U,122U
#define MMCSD_CSD_MMC_TAAC_SLICE 119U,112U
#define MMCSD_CSD_MMC_NSAC_SLICE 111U,104U
#define MMCSD_CSD_MMC_TRAN_SPEED_SLICE 103U,96U
#define MMCSD_CSD_MMC_CCC_SLICE 95U,84U
#define MMCSD_CSD_MMC_READ_BL_LEN_SLICE 83U,80U
#define MMCSD_CSD_MMC_READ_BL_PARTIAL_SLICE 79U,79U
#define MMCSD_CSD_MMC_WRITE_BLK_MISALIGN_SLICE 78U,78U
#define MMCSD_CSD_MMC_READ_BLK_MISALIGN_SLICE 77U,77U
#define MMCSD_CSD_MMC_DSR_IMP_SLICE 76U,76U
#define MMCSD_CSD_MMC_C_SIZE_SLICE 73U,62U
#define MMCSD_CSD_MMC_VDD_R_CURR_MIN_SLICE 61U,59U
#define MMCSD_CSD_MMC_VDD_R_CURR_MAX_SLICE 58U,56U
#define MMCSD_CSD_MMC_VDD_W_CURR_MIN_SLICE 55U,53U
#define MMCSD_CSD_MMC_VDD_W_CURR_MAX_SLICE 52U,50U
#define MMCSD_CSD_MMC_C_SIZE_MULT_SLICE 49U,47U
#define MMCSD_CSD_MMC_ERASE_GRP_SIZE_SLICE 46U,42U
#define MMCSD_CSD_MMC_ERASE_GRP_MULT_SLICE 41U,37U
#define MMCSD_CSD_MMC_WP_GRP_SIZE_SLICE 36U,32U
#define MMCSD_CSD_MMC_WP_GRP_ENABLE_SLICE 31U,31U
#define MMCSD_CSD_MMC_DEFAULT_ECC_SLICE 30U,29U
#define MMCSD_CSD_MMC_R2W_FACTOR_SLICE 28U,26U
#define MMCSD_CSD_MMC_WRITE_BL_LEN_SLICE 25U,22U
#define MMCSD_CSD_MMC_WRITE_BL_PARTIAL_SLICE 21U,21U
#define MMCSD_CSD_MMC_CONTENT_PROT_APP_SLICE 16U,16U
#define MMCSD_CSD_MMC_FILE_FORMAT_GRP_SLICE 15U,15U
#define MMCSD_CSD_MMC_COPY_SLICE 14U,14U
#define MMCSD_CSD_MMC_PERM_WRITE_PROTECT_SLICE 13U,13U
#define MMCSD_CSD_MMC_TMP_WRITE_PROTECT_SLICE 12U,12U
#define MMCSD_CSD_MMC_FILE_FORMAT_SLICE 11U,10U
#define MMCSD_CSD_MMC_ECC_SLICE 9U,8U
#define MMCSD_CSD_MMC_CRC_SLICE 7U,1U
/* CSD version 2.0 */
#define MMCSD_CSD_20_CRC_SLICE 7U,1U
#define MMCSD_CSD_20_FILE_FORMAT_SLICE 11U,10U
#define MMCSD_CSD_20_TMP_WRITE_PROTECT_SLICE 12U,12U
#define MMCSD_CSD_20_PERM_WRITE_PROTECT_SLICE 13U,13U
#define MMCSD_CSD_20_COPY_SLICE 14U,14U
#define MMCSD_CSD_20_FILE_FORMAT_GRP_SLICE 15U,15U
#define MMCSD_CSD_20_WRITE_BL_PARTIAL_SLICE 21U,21U
#define MMCSD_CSD_20_WRITE_BL_LEN_SLICE 25U,12U
#define MMCSD_CSD_20_R2W_FACTOR_SLICE 28U,26U
#define MMCSD_CSD_20_WP_GRP_ENABLE_SLICE 31U,31U
#define MMCSD_CSD_20_WP_GRP_SIZE_SLICE 38U,32U
#define MMCSD_CSD_20_ERASE_SECTOR_SIZE_SLICE 45U,39U
#define MMCSD_CSD_20_ERASE_BLK_EN_SLICE 46U,46U
#define MMCSD_CSD_20_C_SIZE_SLICE 69U,48U
#define MMCSD_CSD_20_DSR_IMP_SLICE 76U,76U
#define MMCSD_CSD_20_READ_BLK_MISALIGN_SLICE 77U,77U
#define MMCSD_CSD_20_WRITE_BLK_MISALIGN_SLICE 78U,78U
#define MMCSD_CSD_20_READ_BL_PARTIAL_SLICE 79U,79U
#define MMCSD_CSD_20_READ_BL_LEN_SLICE 83U,80U
#define MMCSD_CSD_20_CCC_SLICE 95U,84U
#define MMCSD_CSD_20_TRANS_SPEED_SLICE 103U,96U
#define MMCSD_CSD_20_NSAC_SLICE 111U,104U
#define MMCSD_CSD_20_TAAC_SLICE 119U,112U
#define MMCSD_CSD_20_CSD_STRUCTURE_SLICE 127U,126U
/* CSD version 1.0 */
#define MMCSD_CSD_10_CRC_SLICE MMCSD_CSD_20_CRC_SLICE
#define MMCSD_CSD_10_FILE_FORMAT_SLICE MMCSD_CSD_20_FILE_FORMAT_SLICE
#define MMCSD_CSD_10_TMP_WRITE_PROTECT_SLICE MMCSD_CSD_20_TMP_WRITE_PROTECT_SLICE
#define MMCSD_CSD_10_PERM_WRITE_PROTECT_SLICE MMCSD_CSD_20_PERM_WRITE_PROTECT_SLICE
#define MMCSD_CSD_10_COPY_SLICE MMCSD_CSD_20_COPY_SLICE
#define MMCSD_CSD_10_FILE_FORMAT_GRP_SLICE MMCSD_CSD_20_FILE_FORMAT_GRP_SLICE
#define MMCSD_CSD_10_WRITE_BL_PARTIAL_SLICE MMCSD_CSD_20_WRITE_BL_PARTIAL_SLICE
#define MMCSD_CSD_10_WRITE_BL_LEN_SLICE MMCSD_CSD_20_WRITE_BL_LEN_SLICE
#define MMCSD_CSD_10_R2W_FACTOR_SLICE MMCSD_CSD_20_R2W_FACTOR_SLICE
#define MMCSD_CSD_10_WP_GRP_ENABLE_SLICE MMCSD_CSD_20_WP_GRP_ENABLE_SLICE
#define MMCSD_CSD_10_WP_GRP_SIZE_SLICE MMCSD_CSD_20_WP_GRP_SIZE_SLICE
#define MMCSD_CSD_10_ERASE_SECTOR_SIZE_SLICE MMCSD_CSD_20_ERASE_SECTOR_SIZE_SLICE
#define MMCSD_CSD_10_ERASE_BLK_EN_SLICE MMCSD_CSD_20_ERASE_BLK_EN_SLICE
#define MMCSD_CSD_10_C_SIZE_MULT_SLICE 49U,47U
#define MMCSD_CSD_10_VDD_W_CURR_MAX_SLICE 52U,50U
#define MMCSD_CSD_10_VDD_W_CURR_MIN_SLICE 55U,53U
#define MMCSD_CSD_10_VDD_R_CURR_MAX_SLICE 58U,56U
#define MMCSD_CSD_10_VDD_R_CURR_MIX_SLICE 61U,59U
#define MMCSD_CSD_10_C_SIZE_SLICE 73U,62U
#define MMCSD_CSD_10_DSR_IMP_SLICE MMCSD_CSD_20_DSR_IMP_SLICE
#define MMCSD_CSD_10_READ_BLK_MISALIGN_SLICE MMCSD_CSD_20_READ_BLK_MISALIGN_SLICE
#define MMCSD_CSD_10_WRITE_BLK_MISALIGN_SLICE MMCSD_CSD_20_WRITE_BLK_MISALIGN_SLICE
#define MMCSD_CSD_10_READ_BL_PARTIAL_SLICE MMCSD_CSD_20_READ_BL_PARTIAL_SLICE
#define MMCSD_CSD_10_READ_BL_LEN_SLICE 83U,80U
#define MMCSD_CSD_10_CCC_SLICE MMCSD_CSD_20_CCC_SLICE
#define MMCSD_CSD_10_TRANS_SPEED_SLICE MMCSD_CSD_20_TRANS_SPEED_SLICE
#define MMCSD_CSD_10_NSAC_SLICE MMCSD_CSD_20_NSAC_SLICE
#define MMCSD_CSD_10_TAAC_SLICE MMCSD_CSD_20_TAAC_SLICE
#define MMCSD_CSD_10_CSD_STRUCTURE_SLICE MMCSD_CSD_20_CSD_STRUCTURE_SLICE
/** @} */
/**
* @name CID record offsets
*/
/**
* @brief Slice position of values in CID register.
*/
/* CID for SDC */
#define MMCSD_CID_SDC_CRC_SLICE 7U,1U
#define MMCSD_CID_SDC_MDT_M_SLICE 11U,8U
#define MMCSD_CID_SDC_MDT_Y_SLICE 19U,12U
#define MMCSD_CID_SDC_PSN_SLICE 55U,24U
#define MMCSD_CID_SDC_PRV_M_SLICE 59U,56U
#define MMCSD_CID_SDC_PRV_N_SLICE 63U,60U
#define MMCSD_CID_SDC_PNM0_SLICE 71U,64U
#define MMCSD_CID_SDC_PNM1_SLICE 79U,72U
#define MMCSD_CID_SDC_PNM2_SLICE 87U,80U
#define MMCSD_CID_SDC_PNM3_SLICE 95U,88U
#define MMCSD_CID_SDC_PNM4_SLICE 103U,96U
#define MMCSD_CID_SDC_OID_SLICE 119U,104U
#define MMCSD_CID_SDC_MID_SLICE 127U,120U
/* CID for MMC */
#define MMCSD_CID_MMC_CRC_SLICE 7U,1U
#define MMCSD_CID_MMC_MDT_Y_SLICE 11U,8U
#define MMCSD_CID_MMC_MDT_M_SLICE 15U,12U
#define MMCSD_CID_MMC_PSN_SLICE 47U,16U
#define MMCSD_CID_MMC_PRV_M_SLICE 51U,48U
#define MMCSD_CID_MMC_PRV_N_SLICE 55U,52U
#define MMCSD_CID_MMC_PNM0_SLICE 63U,56U
#define MMCSD_CID_MMC_PNM1_SLICE 71U,64U
#define MMCSD_CID_MMC_PNM2_SLICE 79U,72U
#define MMCSD_CID_MMC_PNM3_SLICE 87U,80U
#define MMCSD_CID_MMC_PNM4_SLICE 95U,88U
#define MMCSD_CID_MMC_PNM5_SLICE 103U,96U
#define MMCSD_CID_MMC_OID_SLICE 119U,104U
#define MMCSD_CID_MMC_MID_SLICE 127U,120U
/** @} */
/*===========================================================================*/
/* Driver pre-compile time settings. */
/*===========================================================================*/
/*===========================================================================*/
/* Derived constants and error checks. */
/*===========================================================================*/
/*===========================================================================*/
/* Driver data structures and types. */
/*===========================================================================*/
/**
* @brief @p MMCSDBlockDevice specific methods.
*/
#define _mmcsd_block_device_methods \
_base_block_device_methods
/**
* @brief @p MMCSDBlockDevice specific data.
* @note It is empty because @p MMCSDBlockDevice is only an interface
* without implementation.
*/
#define _mmcsd_block_device_data \
_base_block_device_data \
/* Card CID.*/ \
uint32_t cid[4]; \
/* Card CSD.*/ \
uint32_t csd[4]; \
/* Total number of blocks in card.*/ \
uint32_t capacity;
/**
* @extends BaseBlockDeviceVMT
*
* @brief @p MMCSDBlockDevice virtual methods table.
*/
struct MMCSDBlockDeviceVMT {
_base_block_device_methods
};
/**
* @extends BaseBlockDevice
*
* @brief MCC/SD block device class.
* @details This class represents a, block-accessible, MMC/SD device.
*/
typedef struct {
/** @brief Virtual Methods Table.*/
const struct MMCSDBlockDeviceVMT *vmt;
_mmcsd_block_device_data
} MMCSDBlockDevice;
/**
* @brief Unpacked CID register from SDC.
*/
typedef struct {
uint8_t mid;
uint16_t oid;
char pnm[5];
uint8_t prv_n;
uint8_t prv_m;
uint32_t psn;
uint8_t mdt_m;
uint16_t mdt_y;
uint8_t crc;
} unpacked_sdc_cid_t;
/**
* @brief Unpacked CID register from MMC.
*/
typedef struct {
uint8_t mid;
uint16_t oid;
char pnm[6];
uint8_t prv_n;
uint8_t prv_m;
uint32_t psn;
uint8_t mdt_m;
uint16_t mdt_y;
uint8_t crc;
} unpacked_mmc_cid_t;
/**
* @brief Unpacked CSD v1.0 register from SDC.
*/
typedef struct {
uint8_t csd_structure;
uint8_t taac;
uint8_t nsac;
uint8_t tran_speed;
uint16_t ccc;
uint8_t read_bl_len;
uint8_t read_bl_partial;
uint8_t write_blk_misalign;
uint8_t read_blk_misalign;
uint8_t dsr_imp;
uint16_t c_size;
uint8_t vdd_r_curr_min;
uint8_t vdd_r_curr_max;
uint8_t vdd_w_curr_min;
uint8_t vdd_w_curr_max;
uint8_t c_size_mult;
uint8_t erase_blk_en;
uint8_t erase_sector_size;
uint8_t wp_grp_size;
uint8_t wp_grp_enable;
uint8_t r2w_factor;
uint8_t write_bl_len;
uint8_t write_bl_partial;
uint8_t file_format_grp;
uint8_t copy;
uint8_t perm_write_protect;
uint8_t tmp_write_protect;
uint8_t file_format;
uint8_t crc;
} unpacked_sdc_csd_10_t;
/**
* @brief Unpacked CSD v2.0 register from SDC.
*/
typedef struct {
uint8_t csd_structure;
uint8_t taac;
uint8_t nsac;
uint8_t tran_speed;
uint16_t ccc;
uint8_t read_bl_len;
uint8_t read_bl_partial;
uint8_t write_blk_misalign;
uint8_t read_blk_misalign;
uint8_t dsr_imp;
uint32_t c_size;
uint8_t erase_blk_en;
uint8_t erase_sector_size;
uint8_t wp_grp_size;
uint8_t wp_grp_enable;
uint8_t r2w_factor;
uint8_t write_bl_len;
uint8_t write_bl_partial;
uint8_t file_format_grp;
uint8_t copy;
uint8_t perm_write_protect;
uint8_t tmp_write_protect;
uint8_t file_format;
uint8_t crc;
} unpacked_sdc_csd_20_t;
/**
* @brief Unpacked CSD register from MMC.
*/
typedef struct {
uint8_t csd_structure;
uint8_t spec_vers;
uint8_t taac;
uint8_t nsac;
uint8_t tran_speed;
uint16_t ccc;
uint8_t read_bl_len;
uint8_t read_bl_partial;
uint8_t write_blk_misalign;
uint8_t read_blk_misalign;
uint8_t dsr_imp;
uint16_t c_size;
uint8_t vdd_r_curr_min;
uint8_t vdd_r_curr_max;
uint8_t vdd_w_curr_min;
uint8_t vdd_w_curr_max;
uint8_t c_size_mult;
uint8_t erase_grp_size;
uint8_t erase_grp_mult;
uint8_t wp_grp_size;
uint8_t wp_grp_enable;
uint8_t default_ecc;
uint8_t r2w_factor;
uint8_t write_bl_len;
uint8_t write_bl_partial;
uint8_t content_prot_app;
uint8_t file_format_grp;
uint8_t copy;
uint8_t perm_write_protect;
uint8_t tmp_write_protect;
uint8_t file_format;
uint8_t ecc;
uint8_t crc;
} unpacked_mmc_csd_t;
/*===========================================================================*/
/* Driver macros. */
/*===========================================================================*/
/**
* @name R1 response utilities
* @{
*/
/**
* @brief Evaluates to @p true if the R1 response contains error flags.
*
* @param[in] r1 the r1 response
*/
#define MMCSD_R1_ERROR(r1) (((r1) & MMCSD_R1_ERROR_MASK) != 0U)
/**
* @brief Returns the status field of an R1 response.
*
* @param[in] r1 the r1 response
*/
#define MMCSD_R1_STS(r1) (((r1) >> 9U) & 15U)
/**
* @brief Evaluates to @p true if the R1 response indicates a locked card.
*
* @param[in] r1 the r1 response
*/
#define MMCSD_R1_IS_CARD_LOCKED(r1) ((((r1) >> 21U) & 1U) != 0U)
/** @} */
/**
* @name Macro Functions
* @{
*/
/**
* @brief Returns the card capacity in blocks.
*
* @param[in] ip pointer to a @p MMCSDBlockDevice or derived class
*
* @return The card capacity.
*
* @api
*/
#define mmcsdGetCardCapacity(ip) ((ip)->capacity)
/** @} */
/*===========================================================================*/
/* External declarations. */
/*===========================================================================*/
#ifdef __cplusplus
extern "C" {
#endif
uint32_t _mmcsd_get_slice(const uint32_t *data,
uint32_t end,
uint32_t start);
uint32_t _mmcsd_get_capacity(const uint32_t *csd);
uint32_t _mmcsd_get_capacity_ext(const uint8_t *ext_csd);
void _mmcsd_unpack_sdc_cid(const MMCSDBlockDevice *sdcp,
unpacked_sdc_cid_t *cidsdc);
void _mmcsd_unpack_mmc_cid(const MMCSDBlockDevice *sdcp,
unpacked_mmc_cid_t *cidmmc);
void _mmcsd_unpack_csd_mmc(const MMCSDBlockDevice *sdcp,
unpacked_mmc_csd_t *csdmmc);
void _mmcsd_unpack_csd_v10(const MMCSDBlockDevice *sdcp,
unpacked_sdc_csd_10_t *csd10);
void _mmcsd_unpack_csd_v20(const MMCSDBlockDevice *sdcp,
unpacked_sdc_csd_20_t *csd20);
#ifdef __cplusplus
}
#endif
#endif /* HAL_USE_MMC_SPI == TRUE || HAL_USE_MMC_SDC == TRUE */
#endif /* HAL_MMCSD_H */
/** @} */
|