Improvements to the STM32 SDC driver.

git-svn-id: svn://svn.code.sf.net/p/chibios/svn/trunk@3001 35acf78f-673a-0410-8e92-d51de3d6d3f4
master
gdisirio 2011-05-29 09:09:22 +00:00
parent a3239bf257
commit 88e92b3fc3
9 changed files with 417 additions and 124 deletions

View File

@ -31,7 +31,7 @@ PROJECT_NAME = ChibiOS/RT
# This could be handy for archiving the generated documentation or
# if some version control system is used.
PROJECT_NUMBER = 2.3.3
PROJECT_NUMBER = 2.3.4
# Using the PROJECT_BRIEF tag one can provide an optional one line description
# for a project that appears at the top of each page and should give viewer

View File

@ -31,7 +31,7 @@ PROJECT_NAME = ChibiOS/RT
# This could be handy for archiving the generated documentation or
# if some version control system is used.
PROJECT_NUMBER = 2.3.3
PROJECT_NUMBER = 2.3.4
# Using the PROJECT_BRIEF tag one can provide an optional one line description
# for a project that appears at the top of each page and should give viewer

View File

@ -74,8 +74,10 @@
#define SDC_CMD_STOP_TRANSMISSION 12
#define SDC_CMD_SEND_STATUS 13
#define SDC_CMD_SET_BLOCKLEN 16
#define SDC_CMD_READ_SINGLE_BLOCK 17
#define SDC_CMD_READ_MULTIPLE_BLOCK 18
#define SDC_CMD_SET_BLOCK_COUNT 23
#define SDC_CMD_WRITE_BLOCK 24
#define SDC_CMD_WRITE_MULTIPLE_BLOCK 25
#define SDC_CMD_APP_OP_COND 41
#define SDC_CMD_LOCK_UNLOCK 42

View File

@ -26,6 +26,8 @@
* @{
*/
#include <string.h>
#include "ch.h"
#include "hal.h"
@ -42,10 +44,339 @@ SDCDriver SDCD1;
/* Driver local variables. */
/*===========================================================================*/
#if STM32_SDC_UNALIGNED_SUPPORT
/**
* @brief Buffer for temporary storage during unaligned transfers.
*/
static union {
uint32_t alignment;
uint8_t buf[SDC_BLOCK_SIZE];
} u;
#endif
/*===========================================================================*/
/* Driver local functions. */
/*===========================================================================*/
/**
* @brief Reads one or more blocks.
*
* @param[in] sdcp pointer to the @p SDCDriver object
* @param[in] startblk first block to read
* @param[out] buf pointer to the read buffer, it must be aligned to
* four bytes boundary
* @param[in] n number of blocks to read
* @return The operation status.
* @retval FALSE operation succeeded, the requested blocks have been
* read.
* @retval TRUE operation failed, the state of the buffer is uncertain.
*
* @notapi
*/
static bool_t sdc_lld_read_multiple(SDCDriver *sdcp, uint32_t startblk,
uint8_t *buf, uint32_t n) {
uint32_t resp[1];
/* Checks for errors and waits for the card to be ready for reading.*/
if (sdc_wait_for_transfer_state(sdcp))
return TRUE;
/* Prepares the DMA channel for reading.*/
dmaChannelSetup(&STM32_DMA2->channels[STM32_DMA_CHANNEL_4],
(n * SDC_BLOCK_SIZE) / sizeof (uint32_t), buf,
(STM32_SDC_SDIO_DMA_PRIORITY << 12) |
DMA_CCR1_PSIZE_1 | DMA_CCR1_MSIZE_1 |
DMA_CCR1_MINC);
/* Setting up data transfer.
Options: Card to Controller, Block mode, DMA mode, 512 bytes blocks.*/
SDIO->ICR = 0xFFFFFFFF;
SDIO->MASK = SDIO_MASK_DCRCFAILIE | SDIO_MASK_DTIMEOUTIE |
SDIO_MASK_DATAENDIE | SDIO_MASK_STBITERRIE;
SDIO->DLEN = n * SDC_BLOCK_SIZE;
SDIO->DCTRL = SDIO_DCTRL_DTDIR |
SDIO_DCTRL_DBLOCKSIZE_3 | SDIO_DCTRL_DBLOCKSIZE_0 |
SDIO_DCTRL_DMAEN |
SDIO_DCTRL_DTEN;
/* DMA channel activation.*/
dmaEnableChannel(STM32_DMA2, STM32_DMA_CHANNEL_4);
/* Read multiple blocks command.*/
if ((sdcp->cardmode & SDC_MODE_HIGH_CAPACITY) == 0)
startblk *= SDC_BLOCK_SIZE;
if (sdc_lld_send_cmd_short_crc(sdcp, SDC_CMD_READ_MULTIPLE_BLOCK,
startblk, resp) ||
SDC_R1_ERROR(resp[0]))
goto error;
chSysLock();
if (SDIO->MASK != 0) {
chDbgAssert(sdcp->thread == NULL,
"sdc_lld_read_multiple(), #1", "not NULL");
sdcp->thread = chThdSelf();
chSchGoSleepS(THD_STATE_SUSPENDED);
chDbgAssert(sdcp->thread == NULL,
"sdc_lld_read_multiple(), #2", "not NULL");
}
if ((SDIO->STA & SDIO_STA_DATAEND) == 0) {
chSysUnlock();
goto error;
}
dmaDisableChannel(STM32_DMA2, STM32_DMA_CHANNEL_4);
SDIO->ICR = 0xFFFFFFFF;
SDIO->DCTRL = 0;
chSysUnlock();
return sdc_lld_send_cmd_short_crc(sdcp, SDC_CMD_STOP_TRANSMISSION, 0, resp);
error:
dmaDisableChannel(STM32_DMA2, STM32_DMA_CHANNEL_4);
SDIO->ICR = 0xFFFFFFFF;
SDIO->MASK = 0;
SDIO->DCTRL = 0;
return TRUE;
}
/**
* @brief Reads one block.
*
* @param[in] sdcp pointer to the @p SDCDriver object
* @param[in] startblk first block to read
* @param[out] buf pointer to the read buffer, it must be aligned to
* four bytes boundary
* @return The operation status.
* @retval FALSE operation succeeded, the requested blocks have been
* read.
* @retval TRUE operation failed, the state of the buffer is uncertain.
*
* @notapi
*/
static bool_t sdc_lld_read_single(SDCDriver *sdcp, uint32_t startblk,
uint8_t *buf) {
uint32_t resp[1];
/* Checks for errors and waits for the card to be ready for reading.*/
if (sdc_wait_for_transfer_state(sdcp))
return TRUE;
/* Prepares the DMA channel for reading.*/
dmaChannelSetup(&STM32_DMA2->channels[STM32_DMA_CHANNEL_4],
SDC_BLOCK_SIZE / sizeof (uint32_t), buf,
(STM32_SDC_SDIO_DMA_PRIORITY << 12) |
DMA_CCR1_PSIZE_1 | DMA_CCR1_MSIZE_1 |
DMA_CCR1_MINC);
/* Setting up data transfer.
Options: Card to Controller, Block mode, DMA mode, 512 bytes blocks.*/
SDIO->ICR = 0xFFFFFFFF;
SDIO->MASK = SDIO_MASK_DCRCFAILIE | SDIO_MASK_DTIMEOUTIE |
SDIO_MASK_DATAENDIE | SDIO_MASK_STBITERRIE;
SDIO->DLEN = SDC_BLOCK_SIZE;
SDIO->DCTRL = SDIO_DCTRL_DTDIR |
SDIO_DCTRL_DBLOCKSIZE_3 | SDIO_DCTRL_DBLOCKSIZE_0 |
SDIO_DCTRL_DMAEN |
SDIO_DCTRL_DTEN;
/* DMA channel activation.*/
dmaEnableChannel(STM32_DMA2, STM32_DMA_CHANNEL_4);
/* Read single block command.*/
if ((sdcp->cardmode & SDC_MODE_HIGH_CAPACITY) == 0)
startblk *= SDC_BLOCK_SIZE;
if (sdc_lld_send_cmd_short_crc(sdcp, SDC_CMD_READ_SINGLE_BLOCK,
startblk, resp) ||
SDC_R1_ERROR(resp[0]))
goto error;
chSysLock();
if (SDIO->MASK != 0) {
chDbgAssert(sdcp->thread == NULL,
"sdc_lld_read_single(), #1", "not NULL");
sdcp->thread = chThdSelf();
chSchGoSleepS(THD_STATE_SUSPENDED);
chDbgAssert(sdcp->thread == NULL,
"sdc_lld_read_single(), #2", "not NULL");
}
if ((SDIO->STA & SDIO_STA_DATAEND) == 0) {
chSysUnlock();
goto error;
}
dmaDisableChannel(STM32_DMA2, STM32_DMA_CHANNEL_4);
SDIO->ICR = 0xFFFFFFFF;
SDIO->DCTRL = 0;
chSysUnlock();
return FALSE;
error:
dmaDisableChannel(STM32_DMA2, STM32_DMA_CHANNEL_4);
SDIO->ICR = 0xFFFFFFFF;
SDIO->MASK = 0;
SDIO->DCTRL = 0;
return TRUE;
}
/**
* @brief Writes one or more blocks.
*
* @param[in] sdcp pointer to the @p SDCDriver object
* @param[in] startblk first block to write
* @param[out] buf pointer to the write buffer, it must be aligned to
* four bytes boundary
* @param[in] n number of blocks to write
* @return The operation status.
* @retval FALSE operation succeeded, the requested blocks have been
* written.
* @retval TRUE operation failed.
*
* @notapi
*/
static bool_t sdc_lld_write_multiple(SDCDriver *sdcp, uint32_t startblk,
const uint8_t *buf, uint32_t n) {
uint32_t resp[1];
/* Checks for errors and waits for the card to be ready for writing.*/
if (sdc_wait_for_transfer_state(sdcp))
return TRUE;
/* Prepares the DMA channel for writing.*/
dmaChannelSetup(&STM32_DMA2->channels[STM32_DMA_CHANNEL_4],
(n * SDC_BLOCK_SIZE) / sizeof (uint32_t), buf,
(STM32_SDC_SDIO_DMA_PRIORITY << 12) |
DMA_CCR1_PSIZE_1 | DMA_CCR1_MSIZE_1 |
DMA_CCR1_MINC | DMA_CCR1_DIR);
/* Write multiple blocks command.*/
if ((sdcp->cardmode & SDC_MODE_HIGH_CAPACITY) == 0)
startblk *= SDC_BLOCK_SIZE;
if (sdc_lld_send_cmd_short_crc(sdcp, SDC_CMD_WRITE_MULTIPLE_BLOCK,
startblk, resp) ||
SDC_R1_ERROR(resp[0]))
return TRUE;
/* Setting up data transfer.
Options: Controller to Card, Block mode, DMA mode, 512 bytes blocks.*/
SDIO->ICR = 0xFFFFFFFF;
SDIO->MASK = SDIO_MASK_DCRCFAILIE | SDIO_MASK_DTIMEOUTIE |
SDIO_MASK_DATAENDIE | SDIO_MASK_TXUNDERRIE |
SDIO_MASK_STBITERRIE;
SDIO->DLEN = n * SDC_BLOCK_SIZE;
SDIO->DCTRL = SDIO_DCTRL_DBLOCKSIZE_3 | SDIO_DCTRL_DBLOCKSIZE_0 |
SDIO_DCTRL_DMAEN |
SDIO_DCTRL_DTEN;
/* DMA channel activation.*/
dmaEnableChannel(STM32_DMA2, STM32_DMA_CHANNEL_4);
/* Note the mask is checked before going to sleep because the interrupt
may have occurred before reaching the critical zone.*/
chSysLock();
if (SDIO->MASK != 0) {
chDbgAssert(sdcp->thread == NULL,
"sdc_lld_write_multiple(), #1", "not NULL");
sdcp->thread = chThdSelf();
chSchGoSleepS(THD_STATE_SUSPENDED);
chDbgAssert(sdcp->thread == NULL,
"sdc_lld_write_multiple(), #2", "not NULL");
}
if ((SDIO->STA & SDIO_STA_DATAEND) == 0) {
chSysUnlock();
goto error;
}
dmaDisableChannel(STM32_DMA2, STM32_DMA_CHANNEL_4);
SDIO->ICR = 0xFFFFFFFF;
SDIO->DCTRL = 0;
chSysUnlock();
return sdc_lld_send_cmd_short_crc(sdcp, SDC_CMD_STOP_TRANSMISSION, 0, resp);
error:
dmaDisableChannel(STM32_DMA2, STM32_DMA_CHANNEL_4);
SDIO->ICR = 0xFFFFFFFF;
SDIO->MASK = 0;
SDIO->DCTRL = 0;
return TRUE;
}
/**
* @brief Writes one block.
*
* @param[in] sdcp pointer to the @p SDCDriver object
* @param[in] startblk first block to write
* @param[out] buf pointer to the write buffer, it must be aligned to
* four bytes boundary
* @param[in] n number of blocks to write
* @return The operation status.
* @retval FALSE operation succeeded, the requested blocks have been
* written.
* @retval TRUE operation failed.
*
* @notapi
*/
static bool_t sdc_lld_write_single(SDCDriver *sdcp, uint32_t startblk,
const uint8_t *buf) {
uint32_t resp[1];
/* Checks for errors and waits for the card to be ready for writing.*/
if (sdc_wait_for_transfer_state(sdcp))
return TRUE;
/* Prepares the DMA channel for writing.*/
dmaChannelSetup(&STM32_DMA2->channels[STM32_DMA_CHANNEL_4],
SDC_BLOCK_SIZE / sizeof (uint32_t), buf,
(STM32_SDC_SDIO_DMA_PRIORITY << 12) |
DMA_CCR1_PSIZE_1 | DMA_CCR1_MSIZE_1 |
DMA_CCR1_MINC | DMA_CCR1_DIR);
/* Write single block command.*/
if ((sdcp->cardmode & SDC_MODE_HIGH_CAPACITY) == 0)
startblk *= SDC_BLOCK_SIZE;
if (sdc_lld_send_cmd_short_crc(sdcp, SDC_CMD_WRITE_BLOCK,
startblk, resp) ||
SDC_R1_ERROR(resp[0]))
return TRUE;
/* Setting up data transfer.
Options: Controller to Card, Block mode, DMA mode, 512 bytes blocks.*/
SDIO->ICR = 0xFFFFFFFF;
SDIO->MASK = SDIO_MASK_DCRCFAILIE | SDIO_MASK_DTIMEOUTIE |
SDIO_MASK_DATAENDIE | SDIO_MASK_TXUNDERRIE |
SDIO_MASK_STBITERRIE;
SDIO->DLEN = SDC_BLOCK_SIZE;
SDIO->DCTRL = SDIO_DCTRL_DBLOCKSIZE_3 | SDIO_DCTRL_DBLOCKSIZE_0 |
SDIO_DCTRL_DMAEN |
SDIO_DCTRL_DTEN;
/* DMA channel activation.*/
dmaEnableChannel(STM32_DMA2, STM32_DMA_CHANNEL_4);
/* Note the mask is checked before going to sleep because the interrupt
may have occurred before reaching the critical zone.*/
chSysLock();
if (SDIO->MASK != 0) {
chDbgAssert(sdcp->thread == NULL,
"sdc_lld_write_single(), #1", "not NULL");
sdcp->thread = chThdSelf();
chSchGoSleepS(THD_STATE_SUSPENDED);
chDbgAssert(sdcp->thread == NULL,
"sdc_lld_write_single(), #2", "not NULL");
}
if ((SDIO->STA & SDIO_STA_DATAEND) == 0) {
chSysUnlock();
goto error;
}
dmaDisableChannel(STM32_DMA2, STM32_DMA_CHANNEL_4);
SDIO->ICR = 0xFFFFFFFF;
SDIO->DCTRL = 0;
chSysUnlock();
return FALSE;
error:
dmaDisableChannel(STM32_DMA2, STM32_DMA_CHANNEL_4);
SDIO->ICR = 0xFFFFFFFF;
SDIO->MASK = 0;
SDIO->DCTRL = 0;
return TRUE;
}
/*===========================================================================*/
/* Driver interrupt handlers. */
/*===========================================================================*/
@ -331,61 +662,23 @@ bool_t sdc_lld_send_cmd_long_crc(SDCDriver *sdcp, uint8_t cmd, uint32_t arg,
*/
bool_t sdc_lld_read(SDCDriver *sdcp, uint32_t startblk,
uint8_t *buf, uint32_t n) {
uint32_t resp[1];
/* Checks for errors and waits for the card to be ready for reading.*/
if (sdc_wait_for_transfer_state(sdcp))
return TRUE;
/* Prepares the DMA channel for reading.*/
dmaChannelSetup(&STM32_DMA2->channels[STM32_DMA_CHANNEL_4],
(n * SDC_BLOCK_SIZE) / sizeof (uint32_t), buf,
(STM32_SDC_SDIO_DMA_PRIORITY << 12) |
DMA_CCR1_PSIZE_1 | DMA_CCR1_MSIZE_1 |
DMA_CCR1_MINC);
/* Setting up data transfer.
Options: Card to Controller, Block mode, DMA mode, 512 bytes blocks.*/
SDIO->ICR = 0xFFFFFFFF;
SDIO->MASK = SDIO_MASK_DCRCFAILIE | SDIO_MASK_DTIMEOUTIE |
SDIO_MASK_DATAENDIE | SDIO_MASK_STBITERRIE;
SDIO->DLEN = n * SDC_BLOCK_SIZE;
SDIO->DCTRL = SDIO_DCTRL_DTDIR |
SDIO_DCTRL_DBLOCKSIZE_3 | SDIO_DCTRL_DBLOCKSIZE_0 |
SDIO_DCTRL_DMAEN |
SDIO_DCTRL_DTEN;
/* DMA channel activation.*/
dmaEnableChannel(STM32_DMA2, STM32_DMA_CHANNEL_4);
if (sdc_lld_send_cmd_short_crc(sdcp, SDC_CMD_READ_MULTIPLE_BLOCK,
startblk, resp) ||
SDC_R1_ERROR(resp[0]))
goto error;
chSysLock();
if (SDIO->MASK != 0) {
chDbgAssert(sdcp->thread == NULL, "sdc_lld_read(), #1", "not NULL");
sdcp->thread = chThdSelf();
chSchGoSleepS(THD_STATE_SUSPENDED);
chDbgAssert(sdcp->thread == NULL, "sdc_lld_read(), #2", "not NULL");
#if STM32_SDC_UNALIGNED_SUPPORT
if (((unsigned)buf & 3) != 0) {
uint32_t i;
for (i = 0; i < n; i++) {
if (sdc_lld_read_single(sdcp, startblk, u.buf))
return TRUE;
memcpy(buf, u.buf, SDC_BLOCK_SIZE);
buf += SDC_BLOCK_SIZE;
startblk++;
}
return FALSE;
}
if ((SDIO->STA & SDIO_STA_DATAEND) == 0) {
chSysUnlock();
goto error;
}
dmaDisableChannel(STM32_DMA2, STM32_DMA_CHANNEL_4);
SDIO->ICR = 0xFFFFFFFF;
SDIO->DCTRL = 0;
chSysUnlock();
return sdc_lld_send_cmd_short_crc(sdcp, SDC_CMD_STOP_TRANSMISSION, 0, resp);
error:
dmaDisableChannel(STM32_DMA2, STM32_DMA_CHANNEL_4);
SDIO->ICR = 0xFFFFFFFF;
SDIO->MASK = 0;
SDIO->DCTRL = 0;
return TRUE;
#endif
if (n == 1)
return sdc_lld_read_single(sdcp, startblk, buf);
return sdc_lld_read_multiple(sdcp, startblk, buf, n);
}
/**
@ -404,64 +697,23 @@ error:
*/
bool_t sdc_lld_write(SDCDriver *sdcp, uint32_t startblk,
const uint8_t *buf, uint32_t n) {
uint32_t resp[1];
/* Checks for errors and waits for the card to be ready for writing.*/
if (sdc_wait_for_transfer_state(sdcp))
return TRUE;
/* Prepares the DMA channel for writing.*/
dmaChannelSetup(&STM32_DMA2->channels[STM32_DMA_CHANNEL_4],
(n * SDC_BLOCK_SIZE) / sizeof (uint32_t), buf,
(STM32_SDC_SDIO_DMA_PRIORITY << 12) |
DMA_CCR1_PSIZE_1 | DMA_CCR1_MSIZE_1 |
DMA_CCR1_MINC | DMA_CCR1_DIR);
/* Write multiple blocks command.*/
if (sdc_lld_send_cmd_short_crc(sdcp, SDC_CMD_WRITE_MULTIPLE_BLOCK,
startblk, resp) ||
SDC_R1_ERROR(resp[0]))
return TRUE;
/* Setting up data transfer.
Options: Controller to Card, Block mode, DMA mode, 512 bytes blocks.*/
SDIO->ICR = 0xFFFFFFFF;
SDIO->MASK = SDIO_MASK_DCRCFAILIE | SDIO_MASK_DTIMEOUTIE |
SDIO_MASK_DATAENDIE | SDIO_MASK_TXUNDERRIE |
SDIO_MASK_STBITERRIE;
SDIO->DLEN = n * SDC_BLOCK_SIZE;
SDIO->DCTRL = SDIO_DCTRL_DBLOCKSIZE_3 | SDIO_DCTRL_DBLOCKSIZE_0 |
SDIO_DCTRL_DMAEN |
SDIO_DCTRL_DTEN;
/* DMA channel activation.*/
dmaEnableChannel(STM32_DMA2, STM32_DMA_CHANNEL_4);
/* Note the mask is checked before going to sleep because the interrupt
may have occurred before reaching the critical zone.*/
chSysLock();
if (SDIO->MASK != 0) {
chDbgAssert(sdcp->thread == NULL, "sdc_lld_write(), #1", "not NULL");
sdcp->thread = chThdSelf();
chSchGoSleepS(THD_STATE_SUSPENDED);
chDbgAssert(sdcp->thread == NULL, "sdc_lld_write(), #2", "not NULL");
#if STM32_SDC_UNALIGNED_SUPPORT
if (((unsigned)buf & 3) != 0) {
uint32_t i;
for (i = 0; i < n; i++) {
memcpy(u.buf, buf, SDC_BLOCK_SIZE);
buf += SDC_BLOCK_SIZE;
if (sdc_lld_write_single(sdcp, startblk, u.buf))
return TRUE;
startblk++;
}
return FALSE;
}
if ((SDIO->STA & SDIO_STA_DATAEND) == 0) {
chSysUnlock();
goto error;
}
dmaDisableChannel(STM32_DMA2, STM32_DMA_CHANNEL_4);
SDIO->ICR = 0xFFFFFFFF;
SDIO->DCTRL = 0;
chSysUnlock();
return sdc_lld_send_cmd_short_crc(sdcp, SDC_CMD_STOP_TRANSMISSION, 0, resp);
error:
dmaDisableChannel(STM32_DMA2, STM32_DMA_CHANNEL_4);
SDIO->ICR = 0xFFFFFFFF;
SDIO->MASK = 0;
SDIO->DCTRL = 0;
return TRUE;
#endif
if (n == 1)
return sdc_lld_write_single(sdcp, startblk, buf);
return sdc_lld_write_multiple(sdcp, startblk, buf, n);
}
#endif /* HAL_USE_SDC */

View File

@ -61,6 +61,13 @@
#define STM32_SDC_SDIO_IRQ_PRIORITY 9
#endif
/**
* @brief SDIO support for unaligned transfers.
*/
#if !defined(STM32_SDC_UNALIGNED_SUPPORT) || defined(__DOXYGEN__)
#define STM32_SDC_UNALIGNED_SUPPORT TRUE
#endif
/*===========================================================================*/
/* Derived constants and error checks. */
/*===========================================================================*/

View File

@ -343,9 +343,6 @@ bool_t sdcRead(SDCDriver *sdcp, uint32_t startblk,
sdcp->state = SDC_READING;
chSysUnlock();
if ((sdcp->cardmode & SDC_MODE_HIGH_CAPACITY) == 0)
startblk *= SDC_BLOCK_SIZE;
err = sdc_lld_read(sdcp, startblk, buf, n);
sdcp->state = SDC_ACTIVE;
return err;
@ -371,16 +368,13 @@ bool_t sdcWrite(SDCDriver *sdcp, uint32_t startblk,
const uint8_t *buf, uint32_t n) {
bool_t err;
chDbgCheck((sdcp != NULL) && (buf != NULL) && (n > 0), "sdcRead");
chDbgCheck((sdcp != NULL) && (buf != NULL) && (n > 0), "sdcWrite");
chSysLock();
chDbgAssert(sdcp->state == SDC_ACTIVE, "sdcWrite(), #1", "invalid state");
sdcp->state = SDC_WRITING;
chSysUnlock();
if ((sdcp->cardmode & SDC_MODE_HIGH_CAPACITY) == 0)
startblk *= SDC_BLOCK_SIZE;
err = sdc_lld_write(sdcp, startblk, buf, n);
sdcp->state = SDC_ACTIVE;
return err;

View File

@ -40,7 +40,7 @@
/**
* @brief Kernel version string.
*/
#define CH_KERNEL_VERSION "2.3.3unstable"
#define CH_KERNEL_VERSION "2.3.4unstable"
/**
* @brief Kernel version major number.
@ -55,7 +55,7 @@
/**
* @brief Kernel version patch number.
*/
#define CH_KERNEL_PATCH 3
#define CH_KERNEL_PATCH 4
/*
* Common values.

View File

@ -70,6 +70,9 @@
*** Releases ***
*****************************************************************************
*** 2.3.4 ***
- NEW: Now the STM32 SDC driver supports unaligned buffers transparently.
*** 2.3.3 ***
- FIX: Fixed race condition in output queues (bug 3303908)(backported
to 2.2.4).

View File

@ -28,7 +28,7 @@ static const SDCConfig sdccfg = {
0
};
static uint8_t blkbuf[SDC_BLOCK_SIZE * 4];
static uint8_t blkbuf[SDC_BLOCK_SIZE * 4 + 1];
/*
* Application entry point.
@ -51,12 +51,36 @@ int main(void) {
sdcStart(&SDCD1, &sdccfg);
if (!sdcConnect(&SDCD1)) {
int i;
/* Repeated multiple reads.*/
for (i = 0; i < 5000; i++) {
/* Single aligned read.*/
if (sdcRead(&SDCD1, 0, blkbuf, 1))
chSysHalt();
/* Single unaligned read.*/
if (sdcRead(&SDCD1, 0, blkbuf + 1, 1))
chSysHalt();
/* Multiple aligned read.*/
if (sdcRead(&SDCD1, 0, blkbuf, 4))
chSysHalt();
/* Multiple unaligned read.*/
if (sdcRead(&SDCD1, 0, blkbuf + 1, 4))
chSysHalt();
/* Repeated multiple aligned reads.*/
for (i = 0; i < 1000; i++) {
if (sdcRead(&SDCD1, 0, blkbuf, 4))
chSysHalt();
}
/* Repeated multiple write.*/
/* Repeated multiple unaligned reads.*/
for (i = 0; i < 1000; i++) {
if (sdcRead(&SDCD1, 0, blkbuf + 1, 4))
chSysHalt();
}
/* Repeated multiple aligned writes.*/
for (i = 0; i < 100; i++) {
if (sdcRead(&SDCD1, 0x10000, blkbuf, 4))
chSysHalt();
@ -65,6 +89,17 @@ int main(void) {
if (sdcWrite(&SDCD1, 0x10000, blkbuf, 4))
chSysHalt();
}
/* Repeated multiple unaligned writes.*/
for (i = 0; i < 100; i++) {
if (sdcRead(&SDCD1, 0x10000, blkbuf + 1, 4))
chSysHalt();
if (sdcWrite(&SDCD1, 0x10000, blkbuf + 1, 4))
chSysHalt();
if (sdcWrite(&SDCD1, 0x10000, blkbuf + 1, 4))
chSysHalt();
}
if (sdcDisconnect(&SDCD1))
chSysHalt();
}