git-svn-id: svn://svn.code.sf.net/p/chibios/svn/trunk@4349 35acf78f-673a-0410-8e92-d51de3d6d3f4
parent
853b0fd51c
commit
9492ff4976
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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)
|
||||
/** @} */
|
||||
|
||||
/*===========================================================================*/
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -229,10 +229,6 @@ struct SDCDriver {
|
|||
*/
|
||||
const struct SDCDriverVMT *vmt;
|
||||
_mmcsd_block_device_data
|
||||
/**
|
||||
* @brief Driver state.
|
||||
*/
|
||||
sdcstate_t state;
|
||||
/**
|
||||
* @brief Current configuration data.
|
||||
*/
|
||||
|
|
103
os/hal/src/sdc.c
103
os/hal/src/sdc.c
|
@ -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;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue