From 82f529d70e6e0c3e1af5d2598809f307f40c95c0 Mon Sep 17 00:00:00 2001 From: gdisirio Date: Sun, 8 May 2011 09:58:19 +0000 Subject: SDC write implemented (not tested yet=, optimizations to the SDC read. git-svn-id: svn://svn.code.sf.net/p/chibios/svn/trunk@2934 35acf78f-673a-0410-8e92-d51de3d6d3f4 --- os/hal/platforms/STM32/sdc_lld.c | 78 +++++++++++++++++++++++++++++++++++----- 1 file changed, 70 insertions(+), 8 deletions(-) (limited to 'os/hal') diff --git a/os/hal/platforms/STM32/sdc_lld.c b/os/hal/platforms/STM32/sdc_lld.c index d6876d3be..a7a598c45 100644 --- a/os/hal/platforms/STM32/sdc_lld.c +++ b/os/hal/platforms/STM32/sdc_lld.c @@ -70,7 +70,9 @@ CH_IRQ_HANDLER(SDIO_IRQHandler) { } chSysUnlockFromIsr(); - SDIO->ICR = 0xFFFFFFFF; + /* Disables the source but the status flags are not reset because the + read/write function need to check them.*/ + SDIO->MASK = 0; CH_IRQ_EPILOGUE(); } @@ -332,7 +334,7 @@ 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 sta, resp[1]; + uint32_t resp[1]; /* Setting up data transfer. Options: Card to Controller, Block mode, DMA mode, 512 bytes blocks.*/ @@ -353,26 +355,27 @@ bool_t sdc_lld_read(SDCDriver *sdcp, uint32_t startblk, DMA_CCR1_PSIZE_1 | DMA_CCR1_MSIZE_1 | DMA_CCR1_EN); + /* Read multiple blocks command.*/ if (sdc_lld_send_cmd_short_crc(sdcp, SDC_CMD_READ_MULTIPLE_BLOCK, startblk, resp) || (resp[0] & SDC_R1_ERROR_MASK)) goto error; + /* Note the mask is checked before going to sleep because the interrupt + may have occurred before reaching the critical zone.*/ chSysLock(); - sta = SDIO->STA; - if ((sta & (SDIO_STA_DCRCFAIL | SDIO_STA_DTIMEOUT | - SDIO_STA_DATAEND | SDIO_STA_STBITERR)) == 0) { - chDbgAssert(sdcp->thread == NULL, "sdc_lld_read_blocks(), #1", "not NULL"); + 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_blocks(), #2", "not NULL"); + chDbgAssert(sdcp->thread == NULL, "sdc_lld_read(), #2", "not NULL"); if (chThdSelf()->p_u.rdymsg != RDY_OK) { chSysUnlock(); goto error; } } else { - if ((sta & SDIO_STA_DATAEND) == 0) { + if ((SDIO->STA & SDIO_STA_DATAEND) == 0) { chSysUnlock(); goto error; } @@ -410,7 +413,66 @@ error: */ bool_t sdc_lld_write(SDCDriver *sdcp, uint32_t startblk, const uint8_t *buf, uint32_t n) { + uint32_t resp[1]; + /* Write multiple blocks command.*/ + if (sdc_lld_send_cmd_short_crc(sdcp, SDC_CMD_WRITE_MULTIPLE_BLOCK, + startblk, resp) || + (resp[0] & SDC_R1_ERROR_MASK)) + 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.*/ + /* 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_DIR | DMA_CCR1_EN); + + /* 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 (chThdSelf()->p_u.rdymsg != RDY_OK) { + chSysUnlock(); + goto error; + } + } + else { + if ((SDIO->STA & SDIO_STA_DATAEND) == 0) { + chSysUnlock(); + goto error; + } + } + dmaDisableChannel(STM32_DMA2, STM32_DMA_CHANNEL_4); + SDIO->ICR = 0xFFFFFFFF; + SDIO->MASK = 0; + SDIO->DCTRL = 0; + chSysUnlock(); + + if (sdc_lld_send_cmd_short_crc(sdcp, SDC_CMD_STOP_TRANSMISSION, 0, resp)) + goto error; + return FALSE; +error: + dmaDisableChannel(STM32_DMA2, STM32_DMA_CHANNEL_4); + SDIO->ICR = 0xFFFFFFFF; + SDIO->MASK = 0; + SDIO->DCTRL = 0; return TRUE; } -- cgit v1.2.3