Support larger SDC LLD transactions

Use chained DMA buffers -- limit is now 16Kbytes, adjustable by LPC_SDC_SDIO_DESCRIPTOR_COUNT. More descriptors require more stack.
This commit is contained in:
Jared Boone 2016-04-10 17:15:59 -07:00
parent f76750e55b
commit 12939a0f82
2 changed files with 54 additions and 30 deletions

View File

@ -241,6 +241,41 @@ static void sdio_dma_interrupts_clear(void) {
;
}
static bool_t sdc_llc_prepare_descriptors_chained(LPC_SDMMC_DESC_Type desc[],
const uint32_t desc_count,
const uint8_t* const buffer,
uint32_t byte_count) {
const uint32_t buffer_size = LPC_SDC_SDIO_MAX_DESCRIPTOR_BYTES;
uint32_t p = (uint32_t)buffer;
for(uint32_t i=0; i<desc_count; i++) {
uint32_t buffer_1_size = (byte_count > buffer_size) ? buffer_size : byte_count;
desc[i].DESC2 = p; //(buffer_1_size == 0) ? 0 : p;
p += buffer_1_size;
byte_count -= buffer_1_size;
uint32_t buffer_2_size = 0;
desc[i].DESC1 =
(buffer_1_size << 0)
| (buffer_2_size << 13)
;
desc[i].DESC3 = (uint32_t)&desc[i+1];
const bool_t first_descriptor = (i == 0);
const bool_t last_descriptor = (byte_count == 0);
desc[i].DESC0 =
(last_descriptor ? 0 : (1U << 1)) /* Disable interrupt on completion */
| (last_descriptor ? (1U << 2) : 0) /* Last descriptor */
| (first_descriptor ? (1U << 3) : 0) /* First descriptor */
| (1U << 4) /* ! Second address chained */
| (1U << 31) /* Descriptor is owned by DMA controller */
;
}
return (byte_count == 0) ? CH_SUCCESS : CH_FAILED;
}
/**
* @brief Wait end of data transaction and performs finalizations.
*
@ -798,8 +833,7 @@ bool_t sdc_lld_send_cmd_long_crc(SDCDriver *sdcp, uint8_t cmd, uint32_t arg,
bool_t sdc_lld_read_aligned(SDCDriver *sdcp, uint32_t startblk,
uint8_t *buf, uint32_t n) {
/* TODO: Documentation suggests max transfer size is 8192, but... */
chDbgCheck((n <= (4096 / MMCSD_BLOCK_SIZE)), "max transaction size");
chDbgCheck((n <= (LPC_SDC_SDIO_DESCRIPTOR_COUNT * LPC_SDC_SDIO_MAX_DESCRIPTOR_BYTES / MMCSD_BLOCK_SIZE)), "max transaction size");
/* TODO: Handle SDHC block indexing? */
@ -810,19 +844,10 @@ bool_t sdc_lld_read_aligned(SDCDriver *sdcp, uint32_t startblk,
sdio_reset_dma_and_fifo();
/* Prepares the DMA channel for writing.*/
LPC_SDMMC_DESC_Type desc;
desc.DESC0 =
(1U << 2) /* Last descriptor */
| (1U << 3) /* First descriptor */
| (1U << 4) /* Second address chained */
| (1U << 31) /* Descriptor is owned by DMA controller */
;
desc.DESC1 =
((n * MMCSD_BLOCK_SIZE) << 0)
| (0U << 13)
;
desc.DESC2 = (uint32_t)buf;
desc.DESC3 = 0;
LPC_SDMMC_DESC_Type desc[LPC_SDC_SDIO_DESCRIPTOR_COUNT];
if (sdc_llc_prepare_descriptors_chained(desc, sizeof(desc) / sizeof(desc[0]), buf, n * MMCSD_BLOCK_SIZE) == TRUE)
goto error;
LPC_SDMMC->DBADDR = (uint32_t)&desc; /* DMA is now armed? */
/* Setting up data transfer.*/
@ -873,8 +898,7 @@ error:
bool_t sdc_lld_write_aligned(SDCDriver *sdcp, uint32_t startblk,
const uint8_t *buf, uint32_t n) {
/* TODO: Documentation suggests max transfer size is 8192, but... */
chDbgCheck((n <= (4096 / MMCSD_BLOCK_SIZE)), "max transaction size");
chDbgCheck((n <= (LPC_SDC_SDIO_DESCRIPTOR_COUNT * LPC_SDC_SDIO_MAX_DESCRIPTOR_BYTES / MMCSD_BLOCK_SIZE)), "max transaction size");
/* Checks for errors and waits for the card to be ready for writing.*/
if (_sdc_wait_for_transfer_state(sdcp))
@ -883,19 +907,10 @@ bool_t sdc_lld_write_aligned(SDCDriver *sdcp, uint32_t startblk,
sdio_reset_dma_and_fifo();
/* Prepares the DMA channel for writing.*/
LPC_SDMMC_DESC_Type desc;
desc.DESC0 =
(1U << 2) /* Last descriptor */
| (1U << 3) /* First descriptor */
| (1U << 4) /* Second address chained */
| (1U << 31) /* Descriptor is owned by DMA controller */
;
desc.DESC1 =
((n * MMCSD_BLOCK_SIZE) << 0)
| (0U << 13)
;
desc.DESC2 = (uint32_t)buf;
desc.DESC3 = 0;
LPC_SDMMC_DESC_Type desc[LPC_SDC_SDIO_DESCRIPTOR_COUNT];
if (sdc_llc_prepare_descriptors_chained(desc, sizeof(desc) / sizeof(desc[0]), buf, n * MMCSD_BLOCK_SIZE) == TRUE)
goto error;
LPC_SDMMC->DBADDR = (uint32_t)&desc; /* DMA is now armed? */
/* Setting up data transfer.*/

View File

@ -55,6 +55,13 @@
#define LPC_SDC_SDIO_IRQ_PRIORITY 7
#endif
/**
* @brief SDIO read/write descriptor count.
*/
#if !defined(LPC_SDC_SDIO_DESCRIPTOR_COUNT) || defined(__DOXYGEN__)
#define LPC_SDC_SDIO_DESCRIPTOR_COUNT 4
#endif
/** @} */
/*===========================================================================*/
@ -178,6 +185,8 @@ struct SDCDriver {
#define MMCSD_R1_IS_CARD_LOCKED(r1) (((r1) >> 21) & 1)
/** @} */
#define LPC_SDC_SDIO_MAX_DESCRIPTOR_BYTES 0x1000
/*===========================================================================*/
/* External declarations. */
/*===========================================================================*/