diff options
-rw-r--r-- | os/hal/include/mmc_spi.h | 9 | ||||
-rw-r--r-- | os/hal/include/mmcsd.h | 4 | ||||
-rw-r--r-- | os/hal/include/sdc.h | 1 | ||||
-rw-r--r-- | os/hal/src/mmc_spi.c | 44 | ||||
-rw-r--r-- | os/hal/src/sdc.c | 46 | ||||
-rw-r--r-- | os/various/fatfs_bindings/fatfs_diskio.c | 12 |
6 files changed, 109 insertions, 7 deletions
diff --git a/os/hal/include/mmc_spi.h b/os/hal/include/mmc_spi.h index a1a33c72d..307ffd3ca 100644 --- a/os/hal/include/mmc_spi.h +++ b/os/hal/include/mmc_spi.h @@ -158,6 +158,14 @@ typedef struct { */
bool_t block_addresses;
/**
+ * @brief Card CID.
+ */
+ uint32_t cid[4];
+ /**
+ * @brief Card CSD.
+ */
+ uint32_t csd[4];
+ /**
* @brief Total number of blocks in card.
*/
uint32_t capacity;
@@ -215,6 +223,7 @@ extern "C" { bool_t mmcStopSequentialWrite(MMCDriver *mmcp);
bool_t mmcSync(MMCDriver *mmcp);
bool_t mmcGetInfo(MMCDriver *mmcp, BlockDeviceInfo *bdip);
+ bool_t mmcErase(MMCDriver *mmcp, uint32_t startblk, uint32_t endblk);
bool_t mmc_lld_is_card_inserted(MMCDriver *mmcp);
bool_t mmc_lld_is_write_protected(MMCDriver *mmcp);
#ifdef __cplusplus
diff --git a/os/hal/include/mmcsd.h b/os/hal/include/mmcsd.h index b21c29442..7595e1202 100644 --- a/os/hal/include/mmcsd.h +++ b/os/hal/include/mmcsd.h @@ -77,6 +77,7 @@ #define MMCSD_CMD_SEL_DESEL_CARD 7
#define MMCSD_CMD_SEND_IF_COND 8
#define MMCSD_CMD_SEND_CSD 9
+#define MMCSD_CMD_SEND_CID 10
#define MMCSD_CMD_STOP_TRANSMISSION 12
#define MMCSD_CMD_SEND_STATUS 13
#define MMCSD_CMD_SET_BLOCKLEN 16
@@ -85,6 +86,9 @@ #define MMCSD_CMD_SET_BLOCK_COUNT 23
#define MMCSD_CMD_WRITE_BLOCK 24
#define MMCSD_CMD_WRITE_MULTIPLE_BLOCK 25
+#define MMCSD_CMD_ERASE_RW_BLK_START 32
+#define MMCSD_CMD_ERASE_RW_BLK_END 33
+#define MMCSD_CMD_ERASE 38
#define MMCSD_CMD_APP_OP_COND 41
#define MMCSD_CMD_LOCK_UNLOCK 42
#define MMCSD_CMD_APP_CMD 55
diff --git a/os/hal/include/sdc.h b/os/hal/include/sdc.h index f54007f44..d2624d306 100644 --- a/os/hal/include/sdc.h +++ b/os/hal/include/sdc.h @@ -203,6 +203,7 @@ extern "C" { sdcflags_t sdcGetAndClearErrors(SDCDriver *sdcp);
bool_t sdcSync(SDCDriver *sdcp);
bool_t sdcGetInfo(SDCDriver *sdcp, BlockDeviceInfo *bdip);
+ bool_t sdcErase(SDCDriver *mmcp, uint32_t startblk, uint32_t endblk);
bool_t _sdc_wait_for_transfer_state(SDCDriver *sdcp);
#ifdef __cplusplus
}
diff --git a/os/hal/src/mmc_spi.c b/os/hal/src/mmc_spi.c index a4ce608e3..a6dda0dc1 100644 --- a/os/hal/src/mmc_spi.c +++ b/os/hal/src/mmc_spi.c @@ -330,12 +330,12 @@ static uint8_t send_command_R3(MMCDriver *mmcp, uint8_t cmd, uint32_t arg, *
* @notapi
*/
-static bool_t read_CSD(MMCDriver *mmcp, uint32_t csd[4]) {
+static bool_t read_CxD(MMCDriver *mmcp, uint8_t cmd, uint32_t cxd[4]) {
unsigned i;
uint8_t *bp, buf[16];
spiSelect(mmcp->config->spip);
- send_hdr(mmcp, MMCSD_CMD_SEND_CSD, 0);
+ send_hdr(mmcp, cmd, 0);
if (recvr1(mmcp) != 0x00) {
spiUnselect(mmcp->config->spip);
return TRUE;
@@ -349,7 +349,7 @@ static bool_t read_CSD(MMCDriver *mmcp, uint32_t csd[4]) { spiReceive(mmcp->config->spip, 16, buf);
bp = buf;
- for (wp = &csd[3]; wp >= csd; wp--) {
+ for (wp = &cxd[3]; wp >= cxd; wp--) {
*wp = ((uint32_t)bp[0] << 24) | ((uint32_t)bp[1] << 16) |
((uint32_t)bp[2] << 8) | (uint32_t)bp[3];
bp += 4;
@@ -491,7 +491,6 @@ void mmcStop(MMCDriver *mmcp) { bool_t mmcConnect(MMCDriver *mmcp) {
unsigned i;
bool_t result;
- uint32_t csd[4];
chDbgCheck(mmcp != NULL, "mmcConnect");
@@ -564,12 +563,15 @@ bool_t mmcConnect(MMCDriver *mmcp) { return TRUE;
/* Determine capacity.*/
- if (read_CSD(mmcp, csd))
+ if (read_CxD(mmcp, MMCSD_CMD_SEND_CSD, mmcp->csd))
return TRUE;
- mmcp->capacity = mmcsdGetCapacity(csd);
+ mmcp->capacity = mmcsdGetCapacity(mmcp->csd);
if (mmcp->capacity == 0)
return TRUE;
+ if (read_CxD(mmcp, MMCSD_CMD_SEND_CID, mmcp->cid))
+ return TRUE;
+
/* Transition to MMC_READY state (if not extracted).*/
chSysLock();
if (mmcp->state == MMC_INSERTED) {
@@ -927,6 +929,36 @@ bool_t mmcGetInfo(MMCDriver *mmcp, BlockDeviceInfo *bdip) { return FALSE;
}
+/**
+ * @brief Erases blocks.
+ *
+ * @param[in] mmcp pointer to the @p MMCDriver object
+ * @param[in] startblk starting block number
+ * @param[in] endblk ending block number
+ *
+ * @return The operation status.
+ * @retval FALSE the operation succeeded.
+ * @retval TRUE the operation failed.
+ *
+ * @api
+ */
+bool_t mmcErase(MMCDriver *mmcp, uint32_t startblk, uint32_t endblk) {
+
+ chDbgCheck((mmcp != NULL), "mmcErase");
+
+ if (send_command_R1(mmcp, MMCSD_CMD_ERASE_RW_BLK_START, startblk))
+ return TRUE;
+
+ if (send_command_R1(mmcp, MMCSD_CMD_ERASE_RW_BLK_END, endblk))
+ return TRUE;
+
+ if (send_command_R1(mmcp, MMCSD_CMD_ERASE, 0))
+ return TRUE;
+
+ return FALSE;
+}
+
+
#endif /* HAL_USE_MMC_SPI */
/** @} */
diff --git a/os/hal/src/sdc.c b/os/hal/src/sdc.c index 653819bb3..ff90fdd62 100644 --- a/os/hal/src/sdc.c +++ b/os/hal/src/sdc.c @@ -505,6 +505,52 @@ bool_t sdcGetInfo(SDCDriver *sdcp, BlockDeviceInfo *bdip) { return CH_SUCCESS;
}
+
+/**
+ * @brief Erases the supplied blocks.
+ *
+ * @param[in] sdcp pointer to the @p SDCDriver object
+ * @param[in] startblk starting block number
+ * @param[in] endblk ending block number
+ *
+ * @return The operation status.
+ * @retval CH_SUCCESS the operation succeeded.
+ * @retval CH_FAILED the operation failed.
+ *
+ * @api
+ */
+bool_t sdcErase(SDCDriver *sdcp, uint32_t startblk, uint32_t endblk) {
+ uint32_t resp[1];
+
+ chDbgCheck((sdcp != NULL), "sdcErase");
+
+ /* Driver handles data in 512 bytes blocks (just like HC cards). But if we
+ have not HC card than we must convert address from blocks to bytes.*/
+ if (!(sdcp->cardmode & SDC_MODE_HIGH_CAPACITY)) {
+ startblk *= MMCSD_BLOCK_SIZE;
+ endblk *= MMCSD_BLOCK_SIZE;
+ }
+
+ _sdc_wait_for_transfer_state( sdcp );
+
+ if (sdc_lld_send_cmd_short_crc(sdcp, MMCSD_CMD_ERASE_RW_BLK_START, startblk, resp) != CH_SUCCESS || MMCSD_R1_ERROR(resp[0]))
+ return CH_FAILED;
+
+ if (sdc_lld_send_cmd_short_crc(sdcp, MMCSD_CMD_ERASE_RW_BLK_END, endblk, resp) != CH_SUCCESS || MMCSD_R1_ERROR(resp[0]))
+ return CH_FAILED;
+
+ if (sdc_lld_send_cmd_short_crc(sdcp, MMCSD_CMD_ERASE, 0, resp) != CH_SUCCESS || MMCSD_R1_ERROR(resp[0]))
+ return CH_FAILED;
+
+ /* Quick sleep to allow it to transition to programming or receiving state */
+ chThdSleepMilliseconds(2);
+
+ /* Wait for it to return to transfer state to indicate it has finished erasing */
+ _sdc_wait_for_transfer_state( sdcp );
+
+ return CH_SUCCESS;
+}
+
#endif /* HAL_USE_SDC */
/** @} */
diff --git a/os/various/fatfs_bindings/fatfs_diskio.c b/os/various/fatfs_bindings/fatfs_diskio.c index 06ee81acc..3a8b6866e 100644 --- a/os/various/fatfs_bindings/fatfs_diskio.c +++ b/os/various/fatfs_bindings/fatfs_diskio.c @@ -7,7 +7,7 @@ #include "ch.h"
#include "hal.h"
-
+#include "ffconf.h"
#include "diskio.h"
#if HAL_USE_MMC_SPI && HAL_USE_SDC
@@ -207,6 +207,11 @@ DRESULT disk_ioctl ( case GET_SECTOR_SIZE:
*((WORD *)buff) = MMC_SECTOR_SIZE;
return RES_OK;
+#if _USE_ERASE
+ case CTRL_ERASE_SECTOR:
+ mmcErase(&MMCD1, *((DWORD *)buff), *((DWORD *)buff + 1));
+ return RES_OK;
+#endif
default:
return RES_PARERR;
}
@@ -224,6 +229,11 @@ DRESULT disk_ioctl ( case GET_BLOCK_SIZE:
*((DWORD *)buff) = 256; /* 512b blocks in one erase block */
return RES_OK;
+#if _USE_ERASE
+ case CTRL_ERASE_SECTOR:
+ sdcErase(&SDCD1, *((DWORD *)buff), *((DWORD *)buff + 1));
+ return RES_OK;
+#endif
default:
return RES_PARERR;
}
|