git-svn-id: svn://svn.code.sf.net/p/chibios/svn/trunk@4349 35acf78f-673a-0410-8e92-d51de3d6d3f4

master
gdisirio 2012-06-26 18:18:14 +00:00
parent 853b0fd51c
commit 9492ff4976
5 changed files with 92 additions and 119 deletions

View File

@ -34,8 +34,8 @@
/* Card insertion monitor. */
/*===========================================================================*/
#define SDC_POLLING_INTERVAL 10
#define SDC_POLLING_DELAY 10
#define POLLING_INTERVAL 10
#define POLLING_DELAY 10
/**
* @brief Card monitor timer.
@ -55,47 +55,55 @@ static EventSource inserted_event, removed_event;
/**
* @brief Insertion monitor timer callback function.
*
* @param[in] p pointer to the @p SDCDriver object
* @param[in] p pointer to the @p BaseBlockDevice object
*
* @notapi
*/
static void tmrfunc(void *p) {
SDCDriver *sdcp = 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);
chSysLockFromIsr();
if ((state != BLK_READING) && (state != BLK_WRITING)) {
/* Safe to perform the check.*/
if (cnt > 0) {
if (sdcIsCardInserted(sdcp)) {
if (blkIsInserted(bbdp)) {
if (--cnt == 0) {
chEvtBroadcastI(&inserted_event);
}
}
else
cnt = SDC_POLLING_INTERVAL;
cnt = POLLING_INTERVAL;
}
else {
if (!sdcIsCardInserted(sdcp)) {
cnt = SDC_POLLING_INTERVAL;
if (!blkIsInserted(bbdp)) {
cnt = POLLING_INTERVAL;
chEvtBroadcastI(&removed_event);
}
}
chVTSetI(&tmr, MS2ST(SDC_POLLING_DELAY), tmrfunc, sdcp);
}
chVTSetI(&tmr, MS2ST(POLLING_DELAY), tmrfunc, bbdp);
chSysUnlockFromIsr();
}
/**
* @brief Polling monitor start.
*
* @param[in] sdcp pointer to the @p SDCDriver object
* @param[in] p pointer to an object implementing @p BaseBlockDevice
*
* @notapi
*/
static void tmr_init(SDCDriver *sdcp) {
static void tmr_init(void *p) {
chEvtInit(&inserted_event);
chEvtInit(&removed_event);
chSysLock();
cnt = SDC_POLLING_INTERVAL;
chVTSetI(&tmr, MS2ST(SDC_POLLING_DELAY), tmrfunc, sdcp);
cnt = POLLING_INTERVAL;
chVTSetI(&tmr, MS2ST(POLLING_DELAY), tmrfunc, p);
chSysUnlock();
}
@ -276,8 +284,6 @@ static void InsertHandler(eventid_t id) {
static void RemoveHandler(eventid_t id) {
(void)id;
if (sdcGetDriverState(&SDCD1) == SDC_ACTIVE)
sdcDisconnect(&SDCD1);
fs_ready = FALSE;
}

View File

@ -106,20 +106,6 @@
/* Driver data structures and types. */
/*===========================================================================*/
/**
* @brief Driver state machine possible states.
*/
typedef enum {
SDC_UNINIT = 0, /**< Not initialized. */
SDC_STOP = 1, /**< Stopped. */
SDC_READY = 2, /**< Ready. */
SDC_CONNECTING = 3, /**< Card connection in progress. */
SDC_DISCONNECTING = 4, /**< Card disconnection in progress. */
SDC_ACTIVE = 5, /**< Cart initialized. */
SDC_READING = 6, /**< Read operation in progress. */
SDC_WRITING = 7, /**< Write operation in progress. */
} sdcstate_t;
#include "sdc_lld.h"
/*===========================================================================*/
@ -130,16 +116,6 @@ typedef enum {
* @name Macro Functions
* @{
*/
/**
* @brief Returns the driver state.
*
* @param[in] sdcp pointer to the @p SDCDriver object
* @return The driver state.
*
* @api
*/
#define sdcGetDriverState(sdcp) ((sdcp)->state)
/**
* @brief Returns the card insertion status.
* @note This macro wraps a low level function named
@ -171,16 +147,6 @@ typedef enum {
* @api
*/
#define sdcIsWriteProtected(sdcp) (sdc_lld_is_write_protected(sdcp))
/**
* @brief Returns the card capacity in blocks.
*
* @param[in] sdcp pointer to the @p SDCDriver object
* @return The card capacity.
*
* @api
*/
#define sdcGetCardCapacity(sdcp) ((sdcp)->capacity)
/** @} */
/*===========================================================================*/

View File

@ -346,7 +346,7 @@ void sdc_lld_start(SDCDriver *sdcp) {
STM32_DMA_CR_MBURST_INCR4;
#endif
if (sdcp->state == SDC_STOP) {
if (sdcp->state == BLK_STOP) {
/* Note, the DMA must be enabled before the IRQs.*/
bool_t b;
b = dmaStreamAllocate(sdcp->dma, STM32_SDC_SDIO_IRQ_PRIORITY, NULL, NULL);
@ -376,7 +376,9 @@ void sdc_lld_start(SDCDriver *sdcp) {
*/
void sdc_lld_stop(SDCDriver *sdcp) {
if ((sdcp->state == SDC_READY) || (sdcp->state == SDC_ACTIVE)) {
if (sdcp->state != BLK_STOP) {
/* SDIO deactivation.*/
SDIO->POWER = 0;
SDIO->CLKCR = 0;
SDIO->DCTRL = 0;

View File

@ -229,10 +229,6 @@ struct SDCDriver {
*/
const struct SDCDriverVMT *vmt;
_mmcsd_block_device_data
/**
* @brief Driver state.
*/
sdcstate_t state;
/**
* @brief Current configuration data.
*/

View File

@ -126,7 +126,7 @@ void sdcInit(void) {
void sdcObjectInit(SDCDriver *sdcp) {
sdcp->vmt = &sdc_vmt;
sdcp->state = SDC_STOP;
sdcp->state = BLK_STOP;
sdcp->errors = SDC_NO_ERROR;
sdcp->config = NULL;
sdcp->capacity = 0;
@ -147,11 +147,11 @@ void sdcStart(SDCDriver *sdcp, const SDCConfig *config) {
chDbgCheck(sdcp != NULL, "sdcStart");
chSysLock();
chDbgAssert((sdcp->state == SDC_STOP) || (sdcp->state == SDC_READY),
chDbgAssert((sdcp->state == BLK_STOP) || (sdcp->state == BLK_ACTIVE),
"sdcStart(), #1", "invalid state");
sdcp->config = config;
sdc_lld_start(sdcp);
sdcp->state = SDC_READY;
sdcp->state = BLK_ACTIVE;
chSysUnlock();
}
@ -167,17 +167,17 @@ void sdcStop(SDCDriver *sdcp) {
chDbgCheck(sdcp != NULL, "sdcStop");
chSysLock();
chDbgAssert((sdcp->state == SDC_STOP) || (sdcp->state == SDC_READY),
chDbgAssert((sdcp->state == BLK_STOP) || (sdcp->state == BLK_ACTIVE),
"sdcStop(), #1", "invalid state");
sdc_lld_stop(sdcp);
sdcp->state = SDC_STOP;
sdcp->state = BLK_STOP;
chSysUnlock();
}
/**
* @brief Performs the initialization procedure on the inserted card.
* @details This function should be invoked when a card is inserted and
* brings the driver in the @p SDC_ACTIVE state where it is possible
* brings the driver in the @p BLK_READY state where it is possible
* to perform read and write operations.
*
* @param[in] sdcp pointer to the @p SDCDriver object
@ -192,12 +192,11 @@ bool_t sdcConnect(SDCDriver *sdcp) {
uint32_t resp[1];
chDbgCheck(sdcp != NULL, "sdcConnect");
chSysLock();
chDbgAssert((sdcp->state == SDC_READY) || (sdcp->state == SDC_ACTIVE),
chDbgAssert((sdcp->state == BLK_ACTIVE) || (sdcp->state == BLK_READY),
"mmcConnect(), #1", "invalid state");
sdcp->state = SDC_CONNECTING;
chSysUnlock();
/* Connection procedure in progress.*/
sdcp->state = BLK_CONNECTING;
/* Card clock initialization.*/
sdc_lld_start_clk(sdcp);
@ -311,13 +310,13 @@ bool_t sdcConnect(SDCDriver *sdcp) {
goto failed;
/* Initialization complete.*/
sdcp->state = SDC_ACTIVE;
sdcp->state = BLK_READY;
return CH_SUCCESS;
/* Initialization failed.*/
/* Connection failed, state reset to BLK_ACTIVE.*/
failed:
sdc_lld_stop_clk(sdcp);
sdcp->state = SDC_READY;
sdcp->state = BLK_ACTIVE;
return CH_FAILED;
}
@ -337,29 +336,31 @@ bool_t sdcDisconnect(SDCDriver *sdcp) {
chDbgCheck(sdcp != NULL, "sdcDisconnect");
chSysLock();
chDbgAssert((sdcp->state == SDC_READY) || (sdcp->state == SDC_ACTIVE),
chDbgAssert((sdcp->state == BLK_ACTIVE) || (sdcp->state == BLK_READY),
"sdcDisconnect(), #1", "invalid state");
if (sdcp->state == SDC_READY) {
if (sdcp->state == BLK_ACTIVE) {
chSysUnlock();
return CH_SUCCESS;
}
sdcp->state = SDC_DISCONNECTING;
sdcp->state = BLK_DISCONNECTING;
chSysUnlock();
/* Waits for eventual pending operations completion.*/
if (_sdc_wait_for_transfer_state(sdcp))
if (_sdc_wait_for_transfer_state(sdcp)) {
sdc_lld_stop_clk(sdcp);
sdcp->state = BLK_ACTIVE;
return CH_FAILED;
}
/* Card clock stopped.*/
sdc_lld_stop_clk(sdcp);
sdcp->state = SDC_READY;
sdcp->state = BLK_ACTIVE;
return CH_SUCCESS;
}
/**
* @brief Reads one or more blocks.
* @pre The driver must be in the @p SDC_ACTIVE state after a successful
* @pre The driver must be in the @p BLK_READY state after a successful
* sdcConnect() invocation.
*
* @param[in] sdcp pointer to the @p SDCDriver object
@ -378,25 +379,26 @@ bool_t sdcRead(SDCDriver *sdcp, uint32_t startblk,
bool_t status;
chDbgCheck((sdcp != NULL) && (buf != NULL) && (n > 0), "sdcRead");
chDbgAssert(sdcp->state == BLK_READY, "sdcRead(), #1", "invalid state");
if ((startblk + n - 1) > sdcp->capacity){
sdcp->errors |= SDC_OVERFLOW_ERROR;
return CH_FAILED;
}
chSysLock();
chDbgAssert(sdcp->state == SDC_ACTIVE, "sdcRead(), #1", "invalid state");
sdcp->state = SDC_READING;
chSysUnlock();
/* Read operation in progress.*/
sdcp->state = BLK_READING;
status = sdc_lld_read(sdcp, startblk, buf, n);
sdcp->state = SDC_ACTIVE;
/* Read operation finished.*/
sdcp->state = BLK_READY;
return status;
}
/**
* @brief Writes one or more blocks.
* @pre The driver must be in the @p SDC_ACTIVE state after a successful
* @pre The driver must be in the @p BLK_READY state after a successful
* sdcConnect() invocation.
*
* @param[in] sdcp pointer to the @p SDCDriver object
@ -415,19 +417,20 @@ bool_t sdcWrite(SDCDriver *sdcp, uint32_t startblk,
bool_t status;
chDbgCheck((sdcp != NULL) && (buf != NULL) && (n > 0), "sdcWrite");
chDbgAssert(sdcp->state == BLK_READY, "sdcWrite(), #1", "invalid state");
if ((startblk + n - 1) > sdcp->capacity){
sdcp->errors |= SDC_OVERFLOW_ERROR;
return CH_FAILED;
}
chSysLock();
chDbgAssert(sdcp->state == SDC_ACTIVE, "sdcWrite(), #1", "invalid state");
sdcp->state = SDC_WRITING;
chSysUnlock();
/* Write operation in progress.*/
sdcp->state = BLK_WRITING;
status = sdc_lld_write(sdcp, startblk, buf, n);
sdcp->state = SDC_ACTIVE;
/* Write operation finished.*/
sdcp->state = BLK_READY;
return status;
}
@ -442,6 +445,8 @@ bool_t sdcWrite(SDCDriver *sdcp, uint32_t startblk,
sdcflags_t sdcGetAndClearErrors(SDCDriver *sdcp) {
chDbgCheck(sdcp != NULL, "sdcGetAndClearErrors");
chDbgAssert(sdcp->state == BLK_READY,
"sdcGetAndClearErrors(), #1", "invalid state");
chSysLock();
sdcflags_t flags = sdcp->errors;
@ -465,12 +470,8 @@ bool_t sdcSync(SDCDriver *sdcp) {
chDbgCheck(sdcp != NULL, "sdcSync");
chSysLock();
if (sdcp->state != SDC_READY) {
chSysUnlock();
if (sdcp->state != BLK_READY)
return CH_FAILED;
}
chSysUnlock();
return sdc_lld_sync(sdcp);
}
@ -489,15 +490,10 @@ bool_t sdcSync(SDCDriver *sdcp) {
*/
bool_t sdcGetInfo(SDCDriver *sdcp, BlockDeviceInfo *bdip) {
chDbgCheck((sdcp != NULL) && (bdip != NULL), "sdcGetInfo");
chSysLock();
if (sdcp->state != SDC_READY) {
chSysUnlock();
if (sdcp->state != BLK_READY)
return CH_FAILED;
}
chSysUnlock();
bdip->blk_num = sdcp->capacity;
bdip->blk_size = MMCSD_BLOCK_SIZE;
@ -523,29 +519,36 @@ bool_t sdcErase(SDCDriver *sdcp, uint32_t startblk, uint32_t endblk) {
uint32_t resp[1];
chDbgCheck((sdcp != NULL), "sdcErase");
chDbgAssert(sdcp->state == BLK_READY, "sdcErase(), #1", "invalid state");
/* 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.*/
/* Handling command differences between HC and normal cards.*/
if (!(sdcp->cardmode & SDC_MODE_HIGH_CAPACITY)) {
startblk *= MMCSD_BLOCK_SIZE;
endblk *= MMCSD_BLOCK_SIZE;
}
_sdc_wait_for_transfer_state( sdcp );
_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]))
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]))
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]))
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 */
/* TODO: ??????????????????????????? */
/* Wait for it to return to transfer state to indicate it has finished erasing */
_sdc_wait_for_transfer_state( sdcp );
_sdc_wait_for_transfer_state(sdcp);
return CH_SUCCESS;
}