aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--demos/ARMCM3-STM32F103-FATFS/main.c93
-rw-r--r--os/hal/include/io_block.h31
-rw-r--r--os/hal/include/mmc_spi.h28
-rw-r--r--os/hal/include/mmcsd.h16
-rw-r--r--os/hal/src/mmc_spi.c113
-rw-r--r--os/various/fatfs_bindings/fatfs_diskio.c16
6 files changed, 203 insertions, 94 deletions
diff --git a/demos/ARMCM3-STM32F103-FATFS/main.c b/demos/ARMCM3-STM32F103-FATFS/main.c
index 16d04dd49..d3e1e7e73 100644
--- a/demos/ARMCM3-STM32F103-FATFS/main.c
+++ b/demos/ARMCM3-STM32F103-FATFS/main.c
@@ -30,7 +30,85 @@
#include "ff.h"
/*===========================================================================*/
-/* MMC/SPI related. */
+/* Card insertion monitor. */
+/*===========================================================================*/
+
+#define POLLING_INTERVAL 10
+#define POLLING_DELAY 10
+
+/**
+ * @brief Card monitor timer.
+ */
+static VirtualTimer tmr;
+
+/**
+ * @brief Debounce counter.
+ */
+static unsigned cnt;
+
+/**
+ * @brief Card event sources.
+ */
+static EventSource inserted_event, removed_event;
+
+/**
+ * @brief Insertion monitor timer callback function.
+ *
+ * @param[in] p pointer to the @p BaseBlockDevice object
+ *
+ * @notapi
+ */
+static void tmrfunc(void *p) {
+ BaseBlockDevice *bbdp = p;
+
+ /* The presence check is performed only while the driver is not in a
+ transfer state because it is often performed by changing the mode of
+ the pin connected to the CS/D3 contact of the card, this could disturb
+ the transfer.*/
+ blkstate_t state = blkGetDriverState(bbdp);
+ if ((state == BLK_READING) || (state == BLK_WRITING))
+ return;
+
+ /* Safe to perform the check.*/
+ chSysLockFromIsr();
+ if (cnt > 0) {
+ if (blkIsInserted(bbdp)) {
+ if (--cnt == 0) {
+ chEvtBroadcastI(&inserted_event);
+ }
+ }
+ else
+ cnt = POLLING_INTERVAL;
+ }
+ else {
+ if (!blkIsInserted(bbdp)) {
+ cnt = POLLING_INTERVAL;
+ chEvtBroadcastI(&removed_event);
+ }
+ }
+ chVTSetI(&tmr, MS2ST(POLLING_DELAY), tmrfunc, bbdp);
+ chSysUnlockFromIsr();
+}
+
+/**
+ * @brief Polling monitor start.
+ *
+ * @param[in] p pointer to an object implementing @p BaseBlockDevice
+ *
+ * @notapi
+ */
+static void tmr_init(void *p) {
+
+ chEvtInit(&inserted_event);
+ chEvtInit(&removed_event);
+ chSysLock();
+ cnt = POLLING_INTERVAL;
+ chVTSetI(&tmr, MS2ST(POLLING_DELAY), tmrfunc, p);
+ chSysUnlock();
+}
+
+/*===========================================================================*/
+/* FatFs related. */
/*===========================================================================*/
/**
@@ -190,6 +268,10 @@ static const ShellConfig shell_cfg1 = {
commands
};
+/*===========================================================================*/
+/* Main and generic code. */
+/*===========================================================================*/
+
/*
* Red LEDs blinker thread, times are in milliseconds.
*/
@@ -278,6 +360,11 @@ int main(void) {
mmcStart(&MMCD1, &mmccfg);
/*
+ * Activates the card insertion monitor.
+ */
+ tmr_init(&MMCD1);
+
+ /*
* Creates the blinker thread.
*/
chThdCreateStatic(waThread1, sizeof(waThread1), NORMALPRIO, Thread1, NULL);
@@ -286,8 +373,8 @@ int main(void) {
* Normal main() thread activity, in this demo it does nothing except
* sleeping in a loop and listen for events.
*/
- chEvtRegister(&MMCD1.inserted_event, &el0, 0);
- chEvtRegister(&MMCD1.removed_event, &el1, 1);
+ chEvtRegister(&inserted_event, &el0, 0);
+ chEvtRegister(&removed_event, &el1, 1);
while (TRUE) {
if (!shelltp)
shelltp = shellCreate(&shell_cfg1, SHELL_WA_SIZE, NORMALPRIO);
diff --git a/os/hal/include/io_block.h b/os/hal/include/io_block.h
index 2e47eb10a..acd20ebca 100644
--- a/os/hal/include/io_block.h
+++ b/os/hal/include/io_block.h
@@ -39,6 +39,20 @@
#define _IO_BLOCK_H_
/**
+ * @brief Driver state machine possible states.
+ */
+typedef enum {
+ BLK_UNINIT = 0, /**< Not initialized. */
+ BLK_STOP = 1, /**< Stopped. */
+ BLK_ACTIVE = 2, /**< Interface active. */
+ BLK_CONNECTING = 3, /**< Connection in progress. */
+ BLK_DISCONNECTING = 4, /**< Disconnection in progress. */
+ BLK_READY = 5, /**< Device ready. */
+ BLK_READING = 6, /**< Read operation in progress. */
+ BLK_WRITING = 7, /**< Write operation in progress. */
+} blkstate_t;
+
+/**
* @brief Block device info.
*/
typedef struct {
@@ -71,10 +85,10 @@ typedef struct {
/**
* @brief @p BaseBlockDevice specific data.
- * @note It is empty because @p BaseBlockDevice is only an interface
- * without implementation.
*/
-#define _base_block_device_data
+#define _base_block_device_data \
+ /* Driver state.*/ \
+ blkstate_t state;
/**
* @brief @p BaseBlockDevice virtual methods table.
@@ -98,6 +112,17 @@ typedef struct {
* @{
*/
/**
+ * @brief Returns the driver state.
+ *
+ * @param[in] ip pointer to a @p BaseBlockDevice or derived class
+ *
+ * @return The driver state.
+ *
+ * @api
+ */
+#define blkGetDriverState(ip) ((ip)->state)
+
+/**
* @brief Returns the media insertion status.
*
* @param[in] ip pointer to a @p BaseBlockDevice or derived class
diff --git a/os/hal/include/mmc_spi.h b/os/hal/include/mmc_spi.h
index cff70876b..b03732992 100644
--- a/os/hal/include/mmc_spi.h
+++ b/os/hal/include/mmc_spi.h
@@ -74,20 +74,6 @@
/*===========================================================================*/
/**
- * @brief Driver state machine possible states.
- */
-typedef enum {
- MMC_UNINIT = 0, /**< Not initialized. */
- MMC_STOP = 1, /**< Stopped. */
- MMC_READY = 2, /**< Ready. */
- MMC_CONNECTING = 3, /**< Card connection in progress. */
- MMC_DISCONNECTING = 4, /**< Card disconnection in progress. */
- MMC_ACTIVE = 5, /**< Cart initialized. */
- MMC_READING = 6, /**< Read operation in progress. */
- MMC_WRITING = 7, /**< Write operation in progress. */
-} mmcstate_t;
-
-/**
* @brief MMC/SD over SPI driver configuration structure.
*/
typedef struct {
@@ -132,10 +118,6 @@ typedef struct {
const struct MMCDriverVMT *vmt;
_mmcsd_block_device_data
/**
- * @brief Driver state.
- */
- mmcstate_t state;
- /**
* @brief Current configuration data.
*/
const MMCConfig *config;
@@ -154,16 +136,6 @@ typedef struct {
* @{
*/
/**
- * @brief Returns the driver state.
- *
- * @param[in] mmcp pointer to the @p MMCDriver object
- * @return The driver state.
- *
- * @api
- */
-#define mmcGetDriverState(mmcp) ((mmcp)->state)
-
-/**
* @brief Returns the card insertion status.
* @note This macro wraps a low level function named
* @p sdc_lld_is_card_inserted(), this function must be
diff --git a/os/hal/include/mmcsd.h b/os/hal/include/mmcsd.h
index a05c2602f..8eaba8ed7 100644
--- a/os/hal/include/mmcsd.h
+++ b/os/hal/include/mmcsd.h
@@ -216,6 +216,22 @@ typedef struct {
/* Driver macros. */
/*===========================================================================*/
+/**
+ * @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. */
/*===========================================================================*/
diff --git a/os/hal/src/mmc_spi.c b/os/hal/src/mmc_spi.c
index 1b9271944..96167a950 100644
--- a/os/hal/src/mmc_spi.c
+++ b/os/hal/src/mmc_spi.c
@@ -380,7 +380,7 @@ void mmcInit(void) {
void mmcObjectInit(MMCDriver *mmcp) {
mmcp->vmt = &mmc_vmt;
- mmcp->state = MMC_STOP;
+ mmcp->state = BLK_STOP;
mmcp->config = NULL;
mmcp->block_addresses = FALSE;
}
@@ -396,13 +396,11 @@ void mmcObjectInit(MMCDriver *mmcp) {
void mmcStart(MMCDriver *mmcp, const MMCConfig *config) {
chDbgCheck((mmcp != NULL) && (config != NULL), "mmcStart");
-
- chSysLock();
- chDbgAssert((mmcp->state == MMC_STOP) || (mmcp->state == MMC_READY),
+ chDbgAssert((mmcp->state == BLK_STOP) || (mmcp->state == BLK_ACTIVE),
"mmcStart(), #1", "invalid state");
+
mmcp->config = config;
- mmcp->state = MMC_READY;
- chSysUnlock();
+ mmcp->state = BLK_ACTIVE;
}
/**
@@ -415,13 +413,11 @@ void mmcStart(MMCDriver *mmcp, const MMCConfig *config) {
void mmcStop(MMCDriver *mmcp) {
chDbgCheck(mmcp != NULL, "mmcStop");
-
- chSysLock();
- chDbgAssert((mmcp->state == MMC_STOP) || (mmcp->state == MMC_READY),
+ chDbgAssert((mmcp->state == BLK_STOP) || (mmcp->state == BLK_ACTIVE),
"mmcStop(), #1", "invalid state");
- mmcp->state = MMC_STOP;
- chSysUnlock();
+
spiStop(mmcp->config->spip);
+ mmcp->state = BLK_STOP;
}
/**
@@ -446,11 +442,11 @@ bool_t mmcConnect(MMCDriver *mmcp) {
chDbgCheck(mmcp != NULL, "mmcConnect");
- chSysLock();
- chDbgAssert((mmcp->state == MMC_READY) || (mmcp->state == MMC_ACTIVE),
+ chDbgAssert((mmcp->state == BLK_ACTIVE) || (mmcp->state == BLK_READY),
"mmcConnect(), #1", "invalid state");
- mmcp->state = MMC_CONNECTING;
- chSysUnlock();
+
+ /* Connection procedure in progress.*/
+ mmcp->state = BLK_CONNECTING;
/* Slow clock mode and 128 clock pulses.*/
spiStart(mmcp->config->spip, mmcp->config->lscfg);
@@ -491,7 +487,7 @@ bool_t mmcConnect(MMCDriver *mmcp) {
send_command_R3(mmcp, MMCSD_CMD_READ_OCR, 0, r3);
/* Check if CCS is set in response. Card operates in block mode if set.*/
- if(r3[0] & 0x40)
+ if (r3[0] & 0x40)
mmcp->block_addresses = TRUE;
}
@@ -526,10 +522,13 @@ bool_t mmcConnect(MMCDriver *mmcp) {
if (read_CxD(mmcp, MMCSD_CMD_SEND_CID, mmcp->cid))
goto failed;
- mmcp->state = MMC_READY;
+ mmcp->state = BLK_READY;
return CH_SUCCESS;
+
+ /* Connection failed, state reset to BLK_ACTIVE.*/
failed:
- mmcp->state = MMC_READY;
+ spiStop(mmcp->config->spip);
+ mmcp->state = BLK_ACTIVE;
return CH_FAILED;
}
@@ -550,20 +549,20 @@ bool_t mmcDisconnect(MMCDriver *mmcp) {
chDbgCheck(mmcp != NULL, "mmcDisconnect");
chSysLock();
- chDbgAssert((mmcp->state == MMC_READY) || (mmcp->state == MMC_ACTIVE),
+ chDbgAssert((mmcp->state == BLK_ACTIVE) || (mmcp->state == BLK_READY),
"mmcDisconnect(), #1", "invalid state");
- if (mmcp->state == MMC_READY) {
+ if (mmcp->state == BLK_ACTIVE) {
chSysUnlock();
return CH_SUCCESS;
}
- mmcp->state = MMC_DISCONNECTING;
+ mmcp->state = BLK_DISCONNECTING;
chSysUnlock();
/* Wait for the pending write operations to complete.*/
sync(mmcp);
- spiStop(mmcp->config->spip);
- mmcp->state = MMC_READY;
+ spiStop(mmcp->config->spip);
+ mmcp->state = BLK_ACTIVE;
return CH_SUCCESS;
}
@@ -582,25 +581,24 @@ bool_t mmcDisconnect(MMCDriver *mmcp) {
bool_t mmcStartSequentialRead(MMCDriver *mmcp, uint32_t startblk) {
chDbgCheck(mmcp != NULL, "mmcStartSequentialRead");
-
- chSysLock();
- chDbgAssert(mmcp->state == MMC_ACTIVE,
+ chDbgAssert(mmcp->state == BLK_READY,
"mmcStartSequentialRead(), #1", "invalid state");
- mmcp->state = MMC_READING;
- chSysUnlock();
+
+ /* Read operation in progress.*/
+ mmcp->state = BLK_READING;
/* (Re)starting the SPI in case it has been reprogrammed externally, it can
happen if the SPI bus is shared among multiple peripherals.*/
spiStart(mmcp->config->spip, mmcp->config->hscfg);
spiSelect(mmcp->config->spip);
- if(mmcp->block_addresses)
+ if (mmcp->block_addresses)
send_hdr(mmcp, MMCSD_CMD_READ_MULTIPLE_BLOCK, startblk);
else
send_hdr(mmcp, MMCSD_CMD_READ_MULTIPLE_BLOCK, startblk * MMCSD_BLOCK_SIZE);
if (recvr1(mmcp) != 0x00) {
- mmcp->state = MMC_READY;
+ spiStop(mmcp->config->spip);
return CH_FAILED;
}
return CH_SUCCESS;
@@ -623,7 +621,7 @@ bool_t mmcSequentialRead(MMCDriver *mmcp, uint8_t *buffer) {
chDbgCheck((mmcp != NULL) && (buffer != NULL), "mmcSequentialRead");
- if (mmcp->state != MMC_READING)
+ if (mmcp->state != BLK_READING)
return CH_FAILED;
for (i = 0; i < MMC_WAIT_DATA; i++) {
@@ -637,7 +635,7 @@ bool_t mmcSequentialRead(MMCDriver *mmcp, uint8_t *buffer) {
}
/* Timeout.*/
spiUnselect(mmcp->config->spip);
- mmcp->state = MMC_READY;
+ spiStop(mmcp->config->spip);
return CH_FAILED;
}
@@ -658,7 +656,7 @@ bool_t mmcStopSequentialRead(MMCDriver *mmcp) {
chDbgCheck(mmcp != NULL, "mmcStopSequentialRead");
- if (mmcp->state != MMC_READING)
+ if (mmcp->state != BLK_READING)
return CH_FAILED;
spiSend(mmcp->config->spip, sizeof(stopcmd), stopcmd);
@@ -666,8 +664,9 @@ bool_t mmcStopSequentialRead(MMCDriver *mmcp) {
/* Note, ignored r1 response, it can be not zero, unknown issue.*/
(void) recvr1(mmcp);
+ /* Read operation finished.*/
spiUnselect(mmcp->config->spip);
- mmcp->state = MMC_READY;
+ mmcp->state = BLK_READY;
return CH_SUCCESS;
}
@@ -686,23 +685,22 @@ bool_t mmcStopSequentialRead(MMCDriver *mmcp) {
bool_t mmcStartSequentialWrite(MMCDriver *mmcp, uint32_t startblk) {
chDbgCheck(mmcp != NULL, "mmcStartSequentialWrite");
-
- chSysLock();
- chDbgAssert(mmcp->state == MMC_ACTIVE,
+ chDbgAssert(mmcp->state == BLK_READY,
"mmcStartSequentialWrite(), #1", "invalid state");
- mmcp->state = MMC_WRITING;
- chSysUnlock();
+
+ /* Write operation in progress.*/
+ mmcp->state = BLK_WRITING;
spiStart(mmcp->config->spip, mmcp->config->hscfg);
spiSelect(mmcp->config->spip);
- if(mmcp->block_addresses)
+ if (mmcp->block_addresses)
send_hdr(mmcp, MMCSD_CMD_WRITE_MULTIPLE_BLOCK, startblk);
else
send_hdr(mmcp, MMCSD_CMD_WRITE_MULTIPLE_BLOCK,
startblk * MMCSD_BLOCK_SIZE);
if (recvr1(mmcp) != 0x00) {
- mmcp->state = MMC_READY;
+ spiStop(mmcp->config->spip);
return CH_FAILED;
}
return CH_SUCCESS;
@@ -726,7 +724,7 @@ bool_t mmcSequentialWrite(MMCDriver *mmcp, const uint8_t *buffer) {
chDbgCheck((mmcp != NULL) && (buffer != NULL), "mmcSequentialWrite");
- if (mmcp->state != MMC_WRITING)
+ if (mmcp->state != BLK_WRITING)
return CH_FAILED;
spiSend(mmcp->config->spip, sizeof(start), start); /* Data prologue. */
@@ -740,7 +738,7 @@ bool_t mmcSequentialWrite(MMCDriver *mmcp, const uint8_t *buffer) {
/* Error.*/
spiUnselect(mmcp->config->spip);
- mmcp->state = MMC_READY;
+ spiStop(mmcp->config->spip);
return CH_FAILED;
}
@@ -760,14 +758,14 @@ bool_t mmcStopSequentialWrite(MMCDriver *mmcp) {
chDbgCheck(mmcp != NULL, "mmcStopSequentialWrite");
- if (mmcp->state != MMC_WRITING)
+ if (mmcp->state != BLK_WRITING)
return CH_FAILED;
spiSend(mmcp->config->spip, sizeof(stop), stop);
spiUnselect(mmcp->config->spip);
- chSysLock();
- mmcp->state = MMC_READY;
+ /* Write operation finished.*/
+ mmcp->state = BLK_READY;
return CH_SUCCESS;
}
@@ -786,7 +784,7 @@ bool_t mmcSync(MMCDriver *mmcp) {
chDbgCheck(mmcp != NULL, "mmcSync");
- if (mmcp->state != MMC_READY)
+ if (mmcp->state != BLK_READY)
return CH_FAILED;
sync(mmcp);
@@ -809,11 +807,12 @@ bool_t mmcGetInfo(MMCDriver *mmcp, BlockDeviceInfo *bdip) {
chDbgCheck((mmcp != NULL) && (bdip != NULL), "mmcGetInfo");
- if (mmcp->state != MMC_READY)
+ if (mmcp->state != BLK_READY)
return CH_FAILED;
bdip->blk_num = mmcp->capacity;
bdip->blk_size = MMCSD_BLOCK_SIZE;
+
return CH_SUCCESS;
}
@@ -834,18 +833,28 @@ bool_t mmcErase(MMCDriver *mmcp, uint32_t startblk, uint32_t endblk) {
chDbgCheck((mmcp != NULL), "mmcErase");
+ /* Handling command differences between HC and normal cards.*/
+ if (!mmcp->block_addresses) {
+ startblk *= MMCSD_BLOCK_SIZE;
+ endblk *= MMCSD_BLOCK_SIZE;
+ }
+
if (send_command_R1(mmcp, MMCSD_CMD_ERASE_RW_BLK_START, startblk))
- return CH_FAILED;
+ goto failed;
if (send_command_R1(mmcp, MMCSD_CMD_ERASE_RW_BLK_END, endblk))
- return CH_FAILED;
+ goto failed;
if (send_command_R1(mmcp, MMCSD_CMD_ERASE, 0))
- return CH_FAILED;
+ goto failed;
return CH_SUCCESS;
-}
+ /* Command failed, state reset to BLK_ACTIVE.*/
+failed:
+ spiStop(mmcp->config->spip);
+ return CH_FAILED;
+}
#endif /* HAL_USE_MMC_SPI */
diff --git a/os/various/fatfs_bindings/fatfs_diskio.c b/os/various/fatfs_bindings/fatfs_diskio.c
index 3a8b6866e..40f3666a4 100644
--- a/os/various/fatfs_bindings/fatfs_diskio.c
+++ b/os/various/fatfs_bindings/fatfs_diskio.c
@@ -49,7 +49,7 @@ DSTATUS disk_initialize (
case MMC:
stat = 0;
/* It is initialized externally, just reads the status.*/
- if (mmcGetDriverState(&MMCD1) != MMC_READY)
+ if (blkGetDriverState(&MMCD1) != BLK_READY)
stat |= STA_NOINIT;
if (mmcIsWriteProtected(&MMCD1))
stat |= STA_PROTECT;
@@ -58,7 +58,7 @@ DSTATUS disk_initialize (
case SDC:
stat = 0;
/* It is initialized externally, just reads the status.*/
- if (sdcGetDriverState(&SDCD1) != SDC_ACTIVE)
+ if (blkGetDriverState(&SDCD1) != BLK_READY)
stat |= STA_NOINIT;
if (sdcIsWriteProtected(&SDCD1))
stat |= STA_PROTECT;
@@ -84,7 +84,7 @@ DSTATUS disk_status (
case MMC:
stat = 0;
/* It is initialized externally, just reads the status.*/
- if (mmcGetDriverState(&MMCD1) != MMC_READY)
+ if (blkGetDriverState(&MMCD1) != BLK_READY)
stat |= STA_NOINIT;
if (mmcIsWriteProtected(&MMCD1))
stat |= STA_PROTECT;
@@ -93,7 +93,7 @@ DSTATUS disk_status (
case SDC:
stat = 0;
/* It is initialized externally, just reads the status.*/
- if (sdcGetDriverState(&SDCD1) != SDC_ACTIVE)
+ if (blkGetDriverState(&SDCD1) != BLK_READY)
stat |= STA_NOINIT;
if (sdcIsWriteProtected(&SDCD1))
stat |= STA_PROTECT;
@@ -118,7 +118,7 @@ DRESULT disk_read (
switch (drv) {
#if HAL_USE_MMC_SPI
case MMC:
- if (mmcGetDriverState(&MMCD1) != MMC_READY)
+ if (blkGetDriverState(&MMCD1) != BLK_READY)
return RES_NOTRDY;
if (mmcStartSequentialRead(&MMCD1, sector))
return RES_ERROR;
@@ -133,7 +133,7 @@ DRESULT disk_read (
return RES_OK;
#else
case SDC:
- if (sdcGetDriverState(&SDCD1) != SDC_ACTIVE)
+ if (blkGetDriverState(&SDCD1) != BLK_READY)
return RES_NOTRDY;
if (sdcRead(&SDCD1, sector, buff, count))
return RES_ERROR;
@@ -159,7 +159,7 @@ DRESULT disk_write (
switch (drv) {
#if HAL_USE_MMC_SPI
case MMC:
- if (mmcGetDriverState(&MMCD1) != MMC_READY)
+ if (blkGetDriverState(&MMCD1) != BLK_READY)
return RES_NOTRDY;
if (mmcIsWriteProtected(&MMCD1))
return RES_WRPRT;
@@ -176,7 +176,7 @@ DRESULT disk_write (
return RES_OK;
#else
case SDC:
- if (sdcGetDriverState(&SDCD1) != SDC_ACTIVE)
+ if (blkGetDriverState(&SDCD1) != BLK_READY)
return RES_NOTRDY;
if (sdcWrite(&SDCD1, sector, buff, count))
return RES_ERROR;