From 12939a0f8236dc88f200eeecb87d70fd95f6aa69 Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Sun, 10 Apr 2016 17:15:59 -0700 Subject: [PATCH] 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. --- .../os/hal/platforms/LPC43xx/sdc_lld.c | 75 +++++++++++-------- .../os/hal/platforms/LPC43xx/sdc_lld.h | 9 +++ 2 files changed, 54 insertions(+), 30 deletions(-) diff --git a/firmware/chibios-portapack/os/hal/platforms/LPC43xx/sdc_lld.c b/firmware/chibios-portapack/os/hal/platforms/LPC43xx/sdc_lld.c index 212af995..be0e2599 100644 --- a/firmware/chibios-portapack/os/hal/platforms/LPC43xx/sdc_lld.c +++ b/firmware/chibios-portapack/os/hal/platforms/LPC43xx/sdc_lld.c @@ -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 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.*/ diff --git a/firmware/chibios-portapack/os/hal/platforms/LPC43xx/sdc_lld.h b/firmware/chibios-portapack/os/hal/platforms/LPC43xx/sdc_lld.h index 58d3fe93..eae0fc67 100644 --- a/firmware/chibios-portapack/os/hal/platforms/LPC43xx/sdc_lld.h +++ b/firmware/chibios-portapack/os/hal/platforms/LPC43xx/sdc_lld.h @@ -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. */ /*===========================================================================*/