32 #if (HAL_USE_MMC_SPI == TRUE) || defined(__DOXYGEN__) 47 static bool mmc_read(
void *instance, uint32_t startblk,
48 uint8_t *buffer, uint32_t n);
49 static bool mmc_write(
void *instance, uint32_t startblk,
50 const uint8_t *buffer, uint32_t n);
57 (
bool (*)(
void *))mmc_lld_is_card_inserted,
58 (bool (*)(
void *))mmc_lld_is_write_protected,
71 0x00, 0x09, 0x12, 0x1b, 0x24, 0x2d, 0x36, 0x3f, 0x48, 0x41, 0x5a, 0x53,
72 0x6c, 0x65, 0x7e, 0x77, 0x19, 0x10, 0x0b, 0x02, 0x3d, 0x34, 0x2f, 0x26,
73 0x51, 0x58, 0x43, 0x4a, 0x75, 0x7c, 0x67, 0x6e, 0x32, 0x3b, 0x20, 0x29,
74 0x16, 0x1f, 0x04, 0x0d, 0x7a, 0x73, 0x68, 0x61, 0x5e, 0x57, 0x4c, 0x45,
75 0x2b, 0x22, 0x39, 0x30, 0x0f, 0x06, 0x1d, 0x14, 0x63, 0x6a, 0x71, 0x78,
76 0x47, 0x4e, 0x55, 0x5c, 0x64, 0x6d, 0x76, 0x7f, 0x40, 0x49, 0x52, 0x5b,
77 0x2c, 0x25, 0x3e, 0x37, 0x08, 0x01, 0x1a, 0x13, 0x7d, 0x74, 0x6f, 0x66,
78 0x59, 0x50, 0x4b, 0x42, 0x35, 0x3c, 0x27, 0x2e, 0x11, 0x18, 0x03, 0x0a,
79 0x56, 0x5f, 0x44, 0x4d, 0x72, 0x7b, 0x60, 0x69, 0x1e, 0x17, 0x0c, 0x05,
80 0x3a, 0x33, 0x28, 0x21, 0x4f, 0x46, 0x5d, 0x54, 0x6b, 0x62, 0x79, 0x70,
81 0x07, 0x0e, 0x15, 0x1c, 0x23, 0x2a, 0x31, 0x38, 0x41, 0x48, 0x53, 0x5a,
82 0x65, 0x6c, 0x77, 0x7e, 0x09, 0x00, 0x1b, 0x12, 0x2d, 0x24, 0x3f, 0x36,
83 0x58, 0x51, 0x4a, 0x43, 0x7c, 0x75, 0x6e, 0x67, 0x10, 0x19, 0x02, 0x0b,
84 0x34, 0x3d, 0x26, 0x2f, 0x73, 0x7a, 0x61, 0x68, 0x57, 0x5e, 0x45, 0x4c,
85 0x3b, 0x32, 0x29, 0x20, 0x1f, 0x16, 0x0d, 0x04, 0x6a, 0x63, 0x78, 0x71,
86 0x4e, 0x47, 0x5c, 0x55, 0x22, 0x2b, 0x30, 0x39, 0x06, 0x0f, 0x14, 0x1d,
87 0x25, 0x2c, 0x37, 0x3e, 0x01, 0x08, 0x13, 0x1a, 0x6d, 0x64, 0x7f, 0x76,
88 0x49, 0x40, 0x5b, 0x52, 0x3c, 0x35, 0x2e, 0x27, 0x18, 0x11, 0x0a, 0x03,
89 0x74, 0x7d, 0x66, 0x6f, 0x50, 0x59, 0x42, 0x4b, 0x17, 0x1e, 0x05, 0x0c,
90 0x33, 0x3a, 0x21, 0x28, 0x5f, 0x56, 0x4d, 0x44, 0x7b, 0x72, 0x69, 0x60,
91 0x0e, 0x07, 0x1c, 0x15, 0x2a, 0x23, 0x38, 0x31, 0x46, 0x4f, 0x54, 0x5d,
92 0x62, 0x6b, 0x70, 0x79
99 static bool mmc_read(
void *instance, uint32_t startblk,
100 uint8_t *buffer, uint32_t n) {
120 static bool mmc_write(
void *instance, uint32_t startblk,
121 const uint8_t *buffer, uint32_t n) {
149 static uint8_t
crc7(uint8_t crc,
const uint8_t *buffer,
size_t len) {
169 for (i = 0; i < 16; i++) {
171 if (buf[0] == 0xFFU) {
178 if (buf[0] == 0xFFU) {
181 #if MMC_NICE_WAITING == TRUE 203 buf[0] = (uint8_t)0x40U | cmd;
204 buf[1] = (uint8_t)(arg >> 24U);
205 buf[2] = (uint8_t)(arg >> 16U);
206 buf[3] = (uint8_t)(arg >> 8U);
207 buf[4] = (uint8_t)arg;
209 buf[5] = ((
crc7(0, buf, 5U) & 0x7FU) << 1U) | 0x01U;
227 for (i = 0; i < 9; i++) {
229 if (r1[0] != 0xFFU) {
295 r1 =
recvr3(mmcp, response);
315 uint8_t *bp, buf[16];
319 if (
recvr1(mmcp) != 0x00U) {
325 for (i = 0U; i < MMC_WAIT_DATA; i++) {
327 if (buf[0] == 0xFEU) {
332 for (wp = &cxd[3]; wp >= cxd; wp--) {
333 *wp = ((uint32_t)bp[0] << 24U) | ((uint32_t)bp[1] << 16U) |
334 ((uint32_t)bp[2] << 8U) | (uint32_t)bp[3];
361 if (buf[0] == 0xFFU) {
364 #if MMC_NICE_WAITING == TRUE 399 mmcp->block_addresses =
false;
466 mmcp->block_addresses =
false;
478 if (++i >= MMC_CMD0_RETRY) {
496 (
send_command_R3(mmcp, MMCSD_CMD_APP_OP_COND, 0x400001AAU, r3) == 0x00U)) {
501 if (++i >= MMC_ACMD41_RETRY) {
511 if ((r3[0] & 0x40U) != 0U) {
512 mmcp->block_addresses =
true;
526 if (++i >= MMC_CMD1_RETRY) {
542 if (
read_CxD(mmcp, MMCSD_CMD_SEND_CSD, mmcp->csd)) {
547 if (mmcp->capacity == 0U) {
551 if (
read_CxD(mmcp, MMCSD_CMD_SEND_CID, mmcp->cid)) {
625 if (mmcp->block_addresses) {
626 send_hdr(mmcp, MMCSD_CMD_READ_MULTIPLE_BLOCK, startblk);
632 if (
recvr1(mmcp) != 0x00U) {
661 for (i = 0; i < MMC_WAIT_DATA; i++) {
663 if (buffer[0] == 0xFEU) {
689 static const uint8_t stopcmd[] = {
690 (uint8_t)(0x40U | MMCSD_CMD_STOP_TRANSMISSION), 0, 0, 0, 0, 1, 0xFF
732 if (mmcp->block_addresses) {
733 send_hdr(mmcp, MMCSD_CMD_WRITE_MULTIPLE_BLOCK, startblk);
736 send_hdr(mmcp, MMCSD_CMD_WRITE_MULTIPLE_BLOCK,
740 if (
recvr1(mmcp) != 0x00U) {
761 static const uint8_t start[] = {0xFF, 0xFC};
774 if ((b[0] & 0x1FU) == 0x05U) {
798 static const uint8_t stop[] = {0xFD, 0xFF};
864 bdip->
blk_num = mmcp->capacity;
891 if (!mmcp->block_addresses) {
896 if (
send_command_R1(mmcp, MMCSD_CMD_ERASE_RW_BLK_START, startblk) != 0x00U) {
900 if (
send_command_R1(mmcp, MMCSD_CMD_ERASE_RW_BLK_END, endblk) != 0x00U) {
Structure representing a MMC/SD over SPI driver.
bool mmcStartSequentialRead(MMCDriver *mmcp, uint32_t startblk)
Starts a sequential read.
void spiUnselect(SPIDriver *spip)
Deasserts the slave select signal.
static void send_hdr(MMCDriver *mmcp, uint8_t cmd, uint32_t arg)
Sends a command header.
void spiSelect(SPIDriver *spip)
Asserts the slave select signal and prepares for transfers.
void spiReceive(SPIDriver *spip, size_t n, void *rxbuf)
Receives data from the SPI bus.
bool mmcStopSequentialWrite(MMCDriver *mmcp)
Stops a sequential write gracefully.
void spiStart(SPIDriver *spip, const SPIConfig *config)
Configures and activates the SPI peripheral.
bool mmcConnect(MMCDriver *mmcp)
Performs the initialization procedure on the inserted card.
#define MMCSD_BLOCK_SIZE
Fixed block size for MMC/SD block devices.
void mmcStart(MMCDriver *mmcp, const MMCConfig *config)
Configures and activates the MMC peripheral.
MMC/SD over SPI driver configuration structure.
bool mmcStopSequentialRead(MMCDriver *mmcp)
Stops a sequential read gracefully.
static void osalSysUnlock(void)
Leaves a critical zone from thread context.
void mmcStop(MMCDriver *mmcp)
Disables the MMC peripheral.
const SPIConfig * lscfg
SPI low speed configuration used during initialization.
#define MMCSD_CMD8_PATTERN
Fixed pattern for CMD8.
static uint8_t crc7(uint8_t crc, const uint8_t *buffer, size_t len)
Calculate the MMC standard CRC-7 based on a lookup table.
bool mmcGetInfo(MMCDriver *mmcp, BlockDeviceInfo *bdip)
Returns the media info.
bool mmcErase(MMCDriver *mmcp, uint32_t startblk, uint32_t endblk)
Erases blocks.
static const struct MMCDriverVMT mmc_vmt
Virtual methods table.
bool mmcSync(MMCDriver *mmcp)
Waits for card idle condition.
#define osalThreadSleepMilliseconds(msecs)
Delays the invoking thread for the specified number of milliseconds.
static bool read_CxD(MMCDriver *mmcp, uint8_t cmd, uint32_t cxd[4])
Reads the CSD.
_mmcsd_block_device_data const MMCConfig * config
Current configuration data.
const struct MMCDriverVMT * vmt
Virtual Methods Table.
bool mmcStartSequentialWrite(MMCDriver *mmcp, uint32_t startblk)
Starts a sequential write.
uint32_t blk_num
Total number of blocks.
void mmcObjectInit(MMCDriver *mmcp)
Initializes an instance.
bool mmcSequentialWrite(MMCDriver *mmcp, const uint8_t *buffer)
Writes a block within a sequential write operation.
#define osalDbgCheck(c)
Function parameters check.
static void sync(MMCDriver *mmcp)
Waits that the card reaches an idle state.
SPIDriver * spip
SPI driver associated to this MMC driver.
static void wait(MMCDriver *mmcp)
Waits an idle condition.
MMCDriver virtual methods table.
void spiIgnore(SPIDriver *spip, size_t n)
Ignores data on the SPI bus.
void mmcInit(void)
MMC over SPI driver initialization.
static void osalSysLock(void)
Enters a critical zone from thread context.
static uint8_t recvr1(MMCDriver *mmcp)
Receives a single byte response.
static uint8_t send_command_R3(MMCDriver *mmcp, uint8_t cmd, uint32_t arg, uint8_t *response)
Sends a command which returns a five bytes response (R3).
void spiSend(SPIDriver *spip, size_t n, const void *txbuf)
Sends data over the SPI bus.
uint32_t blk_size
Block size in bytes.
#define osalDbgAssert(c, remark)
Condition assertion.
uint32_t _mmcsd_get_capacity(const uint32_t *csd)
Extract card capacity from a CSD.
static uint8_t recvr3(MMCDriver *mmcp, uint8_t *buffer)
Receives a three byte response.
bool mmcDisconnect(MMCDriver *mmcp)
Brings the driver in a state safe for card removal.
void spiStop(SPIDriver *spip)
Deactivates the SPI peripheral.
const SPIConfig * hscfg
SPI high speed configuration used during transfers.
static const uint8_t crc7_lookup_table[256]
Lookup table for CRC-7 ( based on polynomial x^7 + x^3 + 1).
static uint8_t send_command_R1(MMCDriver *mmcp, uint8_t cmd, uint32_t arg)
Sends a command an returns a single byte response.
bool mmcSequentialRead(MMCDriver *mmcp, uint8_t *buffer)
Reads a block within a sequential read operation.