mp_uint_t sdcard_read_blocks(uint8_t *buff, uint32_t sector, uint32_t count) { HAL_SD_ErrorTypedef err; // If buffer is unaligned or located in CCM don't use DMA. if (CCM_BUFFER(buff) || UNALIGNED_BUFFER(buff)) { if (UNALIGNED_BUFFER(buff)) { printf("unaligned read buf:%p count%lu \n", buff, count); } // This transfer has to be done in an atomic section. mp_uint_t atomic_state = MICROPY_BEGIN_ATOMIC_SECTION(); err = HAL_SD_ReadBlocks(&SDHandle, (uint32_t*)buff, sector * SDCARD_BLOCK_SIZE, SDCARD_BLOCK_SIZE, count); MICROPY_END_ATOMIC_SECTION(atomic_state); } else { // Disable USB IRQ to prevent FatFS/MSC contention HAL_NVIC_DisableIRQ(OTG_FS_IRQn); __DSB(); __ISB(); dma_init(SDIO_TXRX_STREAM, SDIO_TXRX_CHANNEL, DMA_PERIPH_TO_MEMORY); err = HAL_SD_ReadBlocks_DMA(&SDHandle, (uint32_t*)buff, sector * SDCARD_BLOCK_SIZE, SDCARD_BLOCK_SIZE, count); if (err == SD_OK) { err = HAL_SD_CheckReadOperation(&SDHandle, SDIO_TIMEOUT); } if (err != SD_OK) { printf("read buf:%p addr:%lu count%lu error:%d\n", buff, sector, count, err); } dma_deinit(); HAL_NVIC_EnableIRQ(OTG_FS_IRQn); } return (err != SD_OK); }
/** * @brief Reads block(s) from a specified address in an SD card, in DMA mode. * @param pData: Pointer to the buffer that will contain the data to transmit * @param ReadAddr: Address from where data is to be read * @param BlockSize: SD card data block size, that should be 512 * @param NumOfBlocks: Number of SD blocks to read * @retval SD status */ uint8_t BSP_SD_ReadBlocks_DMA(uint32_t *pData, uint64_t ReadAddr, uint32_t BlockSize, uint32_t NumOfBlocks) { uint8_t sd_state = MSD_OK; /* Read block(s) in DMA transfer mode */ if(HAL_SD_ReadBlocks_DMA(&uSdHandle, pData, ReadAddr, BlockSize, NumOfBlocks) != SD_OK) { sd_state = MSD_ERROR; } /* Wait until transfer is complete */ if(sd_state == MSD_OK) { if(HAL_SD_CheckReadOperation(&uSdHandle, (uint32_t)SD_DATATIMEOUT) != SD_OK) { sd_state = MSD_ERROR; } else { sd_state = MSD_OK; } } return sd_state; }
/** * @brief Reads block(s) from a specified address in an SD card, in DMA mode. * @param pData: Pointer to the buffer that will contain the data to transmit * @param ReadAddr: Address from where data is to be read * @param BlockSize: SD card data block size, that should be 512 * @param NumOfBlocks: Number of SD blocks to read * @retval SD status */ unsigned char BSP_SD_ReadBlocks_DMA(unsigned long *pData, unsigned long long ReadAddr, unsigned long BlockSize, unsigned long NumOfBlocks) { unsigned char sd_state = MSD_OK; /* Read block(s) in DMA transfer mode */ if(HAL_SD_ReadBlocks_DMA(&uSdHandle, pData, ReadAddr, BlockSize, NumOfBlocks) != SD_OK) { sd_state = MSD_ERROR; } /* Wait until transfer is complete */ if(sd_state == MSD_OK) { if(HAL_SD_CheckReadOperation(&uSdHandle, (unsigned long)SD_DATATIMEOUT) != SD_OK) { sd_state = MSD_ERROR; } else { sd_state = MSD_OK; } } return sd_state; }
mp_uint_t sdcard_read_blocks(uint8_t *dest, uint32_t block_num, uint32_t num_blocks) { // check that dest pointer is aligned on a 4-byte boundary if (((uint32_t)dest & 3) != 0) { return SD_ERROR; } // check that SD card is initialised if (sd_handle.Instance == NULL) { return SD_ERROR; } HAL_SD_ErrorTypedef err = SD_OK; if (query_irq() == IRQ_STATE_ENABLED) { dma_init(&sd_rx_dma, DMA_STREAM_SDIO_RX, &dma_init_struct_sdio, DMA_CHANNEL_SDIO_RX, DMA_PERIPH_TO_MEMORY, &sd_handle); sd_handle.hdmarx = &sd_rx_dma; err = HAL_SD_ReadBlocks_BlockNumber_DMA(&sd_handle, (uint32_t*)dest, block_num, SDCARD_BLOCK_SIZE, num_blocks); if (err == SD_OK) { // wait for DMA transfer to finish, with a large timeout err = HAL_SD_CheckReadOperation(&sd_handle, 100000000); } dma_deinit(sd_handle.hdmarx); sd_handle.hdmarx = NULL; } else { err = HAL_SD_ReadBlocks_BlockNumber(&sd_handle, (uint32_t*)dest, block_num, SDCARD_BLOCK_SIZE, num_blocks); } return err; }
mp_uint_t sdcard_read_blocks(uint8_t *dest, uint32_t block_num, uint32_t num_blocks) { // check that SD card is initialised if (sd_handle.Instance == NULL) { return SD_ERROR; } HAL_SD_ErrorTypedef err = SD_OK; // check that dest pointer is aligned on a 4-byte boundary uint8_t *orig_dest = NULL; uint32_t saved_word; if (((uint32_t)dest & 3) != 0) { // Pointer is not aligned so it needs fixing. // We could allocate a temporary block of RAM (as sdcard_write_blocks // does) but instead we are going to use the dest buffer inplace. We // are going to align the pointer, save the initial word at the aligned // location, read into the aligned memory, move the memory back to the // unaligned location, then restore the initial bytes at the aligned // location. We should have no trouble doing this as those initial // bytes at the aligned location should be able to be changed for the // duration of this function call. orig_dest = dest; dest = (uint8_t*)((uint32_t)dest & ~3); saved_word = *(uint32_t*)dest; } if (query_irq() == IRQ_STATE_ENABLED) { // we must disable USB irqs to prevent MSC contention with SD card uint32_t basepri = raise_irq_pri(IRQ_PRI_OTG_FS); dma_init(&sd_rx_dma, &SDMMC_RX_DMA, &sd_handle); sd_handle.hdmarx = &sd_rx_dma; // make sure cache is flushed and invalidated so when DMA updates the RAM // from reading the peripheral the CPU then reads the new data MP_HAL_CLEANINVALIDATE_DCACHE(dest, num_blocks * SDCARD_BLOCK_SIZE); err = HAL_SD_ReadBlocks_BlockNumber_DMA(&sd_handle, (uint32_t*)dest, block_num, SDCARD_BLOCK_SIZE, num_blocks); if (err == SD_OK) { // wait for DMA transfer to finish, with a large timeout err = HAL_SD_CheckReadOperation(&sd_handle, 100000000); } dma_deinit(&SDMMC_RX_DMA); sd_handle.hdmarx = NULL; restore_irq_pri(basepri); } else { err = HAL_SD_ReadBlocks_BlockNumber(&sd_handle, (uint32_t*)dest, block_num, SDCARD_BLOCK_SIZE, num_blocks); } if (orig_dest != NULL) { // move the read data to the non-aligned position, and restore the initial bytes memmove(orig_dest, dest, num_blocks * SDCARD_BLOCK_SIZE); memcpy(dest, &saved_word, orig_dest - dest); } return err; }
int readBlock(void* data, uint64_t addr) { HAL_SD_ErrorTypedef status; if ((status = HAL_SD_ReadBlocks_DMA(&uSdHandle, (uint32_t*) data, addr, 512, 1)) != SD_OK) { error("Failed to read block: status = %d\n", status); return 0; } debug("%s: check\n", __func__); if ((status = HAL_SD_CheckReadOperation(&uSdHandle, -1)) != SD_OK) { error("HAL_SD_CheckReadOperation() failed, status=%d\n", status); return 0; } debug("%s: done\n", __func__); return 1; }
bool sdcard_read_blocks_dma(uint8_t *dest, uint32_t block_num, uint32_t num_blocks) { // check that dest pointer is aligned on a 4-byte boundary if (((uint32_t)dest & 3) != 0) { return true; } // check that SD card is initialised if (sd_handle.Instance == NULL) { return true; } // do the read if (HAL_SD_ReadBlocks_BlockNumber_DMA(&sd_handle, (uint32_t*)dest, block_num, SDCARD_BLOCK_SIZE, num_blocks) != SD_OK) { return true; } // wait for DMA transfer to finish, with a large timeout if (HAL_SD_CheckReadOperation(&sd_handle, 100000000) != SD_OK) { return true; } return false; }
/** * @brief Reads block(s) from a specified address in an SD card, in DMA mode. * @param pData: Pointer to the buffer that will contain the data to transmit * @param ReadAddr: Address from where data is to be read * @param BlockSize: SD card data block size, that should be 512 * @param NumOfBlocks: Number of SD blocks to read * @retval SD status */ uint8_t BSP_SD_ReadBlocks_DMA(uint32_t *pData, uint64_t ReadAddr, uint32_t BlockSize, uint32_t NumOfBlocks) { uint8_t state = MSD_OK; /* Invalidate the dma tx handle*/ uSdHandle.hdmatx = NULL; /* Prepare the dma channel for a read operation */ state = ((SD_DMAConfigRx(&uSdHandle) == SD_OK) ? MSD_OK : MSD_ERROR); if(state == MSD_OK) { /* Read block(s) in DMA transfer mode */ state = ((HAL_SD_ReadBlocks_DMA(&uSdHandle, pData, ReadAddr, BlockSize, NumOfBlocks) == SD_OK) ? MSD_OK : MSD_ERROR); /* Wait until transfer is complete */ if(state == MSD_OK) { state = ((HAL_SD_CheckReadOperation(&uSdHandle, (uint32_t)SD_DATATIMEOUT) == SD_OK) ? MSD_OK : MSD_ERROR); } } return state; }
/** * @brief Initializes the SD card device. * @param None * @retval SD status */ uint8_t BSP_SD_Init(void) { uint8_t SD_state = MSD_OK; /* uSD device interface configuration */ #if defined(SDIO) uSdHandle.Instance = SDIO; uSdHandle.Init.ClockEdge = SDIO_CLOCK_EDGE_RISING; uSdHandle.Init.ClockBypass = SDIO_CLOCK_BYPASS_DISABLE; uSdHandle.Init.ClockPowerSave = SDIO_CLOCK_POWER_SAVE_DISABLE; uSdHandle.Init.BusWide = SDIO_BUS_WIDE_1B; uSdHandle.Init.HardwareFlowControl = SDIO_HARDWARE_FLOW_CONTROL_DISABLE; uSdHandle.Init.ClockDiv = SDIO_TRANSFER_CLK_DIV; #elif defined(SDMMC1) uSdHandle.Instance = SDMMC1; uSdHandle.Init.ClockEdge = SDMMC_CLOCK_EDGE_RISING; uSdHandle.Init.ClockBypass = SDMMC_CLOCK_BYPASS_DISABLE; uSdHandle.Init.ClockPowerSave = SDMMC_CLOCK_POWER_SAVE_DISABLE; uSdHandle.Init.BusWide = SDMMC_BUS_WIDE_1B; uSdHandle.Init.HardwareFlowControl = SDMMC_HARDWARE_FLOW_CONTROL_DISABLE; uSdHandle.Init.ClockDiv = SDMMC_TRANSFER_CLK_DIV; #else #error "NOT SUPPORTED!" #endif /* Init GPIO, DMA and NVIC */ SD_MspInit(); /* Check if the SD card is plugged in the slot */ if (BSP_SD_IsDetected() != SD_PRESENT) { return MSD_ERROR; } /* HAL SD initialization */ if (HAL_SD_Init(&uSdHandle, &uSdCardInfo) != SD_OK) { SD_state = MSD_ERROR; } /* Configure SD Bus width */ if (SD_state == MSD_OK) { /* Enable wide operation */ #if defined(SDIO_BUS_WIDE_4B) #if FATFS_SDIO_4BIT == 1 if (HAL_SD_WideBusOperation_Config(&uSdHandle, SDIO_BUS_WIDE_4B) != SD_OK) { #else if (HAL_SD_WideBusOperation_Config(&uSdHandle, SDIO_BUS_WIDE_1B) != SD_OK) { #endif #else #if FATFS_SDIO_4BIT == 1 if (HAL_SD_WideBusOperation_Config(&uSdHandle, SDMMC_BUS_WIDE_4B) != SD_OK) { #else if (HAL_SD_WideBusOperation_Config(&uSdHandle, SDMMC_BUS_WIDE_1B) != SD_OK) { #endif #endif SD_state = MSD_ERROR; } else { SD_state = MSD_OK; } } return SD_state; } /** * @brief Detects if SD card is correctly plugged in the memory slot or not. * @param None * @retval Returns if SD is detected or not */ uint8_t BSP_SD_IsDetected(void) { return SDCARD_IsDetected(); } /** * @brief Detects if SD card is write protected * @param None * @retval Returns if SD is write protected or not. */ uint8_t BSP_SD_IsWriteProtected(void) { return !SDCARD_IsWriteEnabled(); } /** * @brief Reads block(s) from a specified address in an SD card, in polling mode. * @param pData: Pointer to the buffer that will contain the data to transmit * @param ReadAddr: Address from where data is to be read * @param BlockSize: SD card data block size, that should be 512 * @param NumOfBlocks: Number of SD blocks to read * @retval SD status */ uint8_t BSP_SD_ReadBlocks(uint32_t *pData, uint64_t ReadAddr, uint32_t BlockSize, uint32_t NumOfBlocks) { if (HAL_SD_ReadBlocks(&uSdHandle, pData, ReadAddr, BlockSize, NumOfBlocks) != SD_OK) { return MSD_ERROR; } return MSD_OK; } /** * @brief Writes block(s) to a specified address in an SD card, in polling mode. * @param pData: Pointer to the buffer that will contain the data to transmit * @param WriteAddr: Address from where data is to be written * @param BlockSize: SD card data block size, that should be 512 * @param NumOfBlocks: Number of SD blocks to write * @retval SD status */ uint8_t BSP_SD_WriteBlocks(uint32_t *pData, uint64_t WriteAddr, uint32_t BlockSize, uint32_t NumOfBlocks) { if (HAL_SD_WriteBlocks(&uSdHandle, pData, WriteAddr, BlockSize, NumOfBlocks) != SD_OK) { return MSD_ERROR; } return MSD_OK; } /** * @brief Reads block(s) from a specified address in an SD card, in DMA mode. * @param pData: Pointer to the buffer that will contain the data to transmit * @param ReadAddr: Address from where data is to be read * @param BlockSize: SD card data block size, that should be 512 * @param NumOfBlocks: Number of SD blocks to read * @retval SD status */ uint8_t BSP_SD_ReadBlocks_DMA(uint32_t *pData, uint64_t ReadAddr, uint32_t BlockSize, uint32_t NumOfBlocks) { uint8_t SD_state = MSD_OK; /* Read block(s) in DMA transfer mode */ if (HAL_SD_ReadBlocks_DMA(&uSdHandle, pData, ReadAddr, BlockSize, NumOfBlocks) != SD_OK) { SD_state = MSD_ERROR; } /* Wait until transfer is complete */ if (SD_state == MSD_OK) { if (HAL_SD_CheckReadOperation(&uSdHandle, (uint32_t)SD_DATATIMEOUT) != SD_OK) { SD_state = MSD_ERROR; } else { SD_state = MSD_OK; } } return SD_state; } /** * @brief Writes block(s) to a specified address in an SD card, in DMA mode. * @param pData: Pointer to the buffer that will contain the data to transmit * @param WriteAddr: Address from where data is to be written * @param BlockSize: SD card data block size, that should be 512 * @param NumOfBlocks: Number of SD blocks to write * @retval SD status */ uint8_t BSP_SD_WriteBlocks_DMA(uint32_t *pData, uint64_t WriteAddr, uint32_t BlockSize, uint32_t NumOfBlocks) { uint8_t SD_state = MSD_OK; /* Write block(s) in DMA transfer mode */ if (HAL_SD_WriteBlocks_DMA(&uSdHandle, pData, WriteAddr, BlockSize, NumOfBlocks) != SD_OK) { SD_state = MSD_ERROR; } /* Wait until transfer is complete */ if (SD_state == MSD_OK) { if(HAL_SD_CheckWriteOperation(&uSdHandle, (uint32_t)SD_DATATIMEOUT) != SD_OK) { SD_state = MSD_ERROR; } else { SD_state = MSD_OK; } } return SD_state; } /** * @brief Erases the specified memory area of the given SD card. * @param StartAddr: Start byte address * @param EndAddr: End byte address * @retval SD status */ uint8_t BSP_SD_Erase(uint64_t StartAddr, uint64_t EndAddr) { if (HAL_SD_Erase(&uSdHandle, StartAddr, EndAddr) != SD_OK) { return MSD_ERROR; } return MSD_OK; } /** * @brief Initializes the SD MSP. * @param None * @retval None */ static void SD_MspInit(void) { static DMA_HandleTypeDef dmaRxHandle; static DMA_HandleTypeDef dmaTxHandle; SD_HandleTypeDef *hsd = &uSdHandle; uint16_t gpio_af; /* Get GPIO alternate function */ #if defined(GPIO_AF12_SDIO) gpio_af = GPIO_AF12_SDIO; #endif #if defined(GPIO_AF12_SDMMC1) gpio_af = GPIO_AF12_SDMMC1; #endif /* Enable SDIO clock */ __HAL_RCC_SDIO_CLK_ENABLE(); /* Enable DMA2 clocks */ __DMAx_TxRx_CLK_ENABLE(); /* Detect pin, write protect pin */ #if FATFS_USE_DETECT_PIN > 0 TM_GPIO_Init(FATFS_DETECT_PORT, FATFS_DETECT_PIN, TM_GPIO_Mode_IN, TM_GPIO_OType_PP, TM_GPIO_PuPd_UP, TM_GPIO_Speed_Low); #endif #if FATFS_USE_WRITEPROTECT_PIN > 0 TM_GPIO_Init(FATFS_WRITEPROTECT_PORT, FATFS_WRITEPROTECT_PIN, TM_GPIO_Mode_IN, TM_GPIO_OType_PP, TM_GPIO_PuPd_UP, TM_GPIO_Speed_Low); #endif /* SDIO/SDMMC pins */ #if FATFS_SDIO_4BIT == 1 TM_GPIO_InitAlternate(GPIOC, GPIO_PIN_8 | GPIO_PIN_9 | GPIO_PIN_10 | GPIO_PIN_11 | GPIO_PIN_12, TM_GPIO_OType_PP, TM_GPIO_PuPd_UP, TM_GPIO_Speed_Fast, gpio_af); #else TM_GPIO_InitAlternate(GPIOC, GPIO_PIN_8 | GPIO_PIN_12, TM_GPIO_OType_PP, TM_GPIO_PuPd_UP, TM_GPIO_Speed_Fast, gpio_af); #endif TM_GPIO_InitAlternate(GPIOD, GPIO_PIN_2, TM_GPIO_OType_PP, TM_GPIO_PuPd_UP, TM_GPIO_Speed_Fast, gpio_af); /* NVIC configuration for SDIO interrupts */ HAL_NVIC_SetPriority(SDIO_IRQn, 5, 0); HAL_NVIC_EnableIRQ(SDIO_IRQn); /* Configure DMA Rx parameters */ dmaRxHandle.Init.Channel = SD_DMAx_Rx_CHANNEL; dmaRxHandle.Init.Direction = DMA_PERIPH_TO_MEMORY; dmaRxHandle.Init.PeriphInc = DMA_PINC_DISABLE; dmaRxHandle.Init.MemInc = DMA_MINC_ENABLE; dmaRxHandle.Init.PeriphDataAlignment = DMA_PDATAALIGN_WORD; dmaRxHandle.Init.MemDataAlignment = DMA_MDATAALIGN_WORD; dmaRxHandle.Init.Mode = DMA_PFCTRL; dmaRxHandle.Init.Priority = DMA_PRIORITY_VERY_HIGH; dmaRxHandle.Init.FIFOMode = DMA_FIFOMODE_ENABLE; dmaRxHandle.Init.FIFOThreshold = DMA_FIFO_THRESHOLD_FULL; dmaRxHandle.Init.MemBurst = DMA_MBURST_INC4; dmaRxHandle.Init.PeriphBurst = DMA_PBURST_INC4; dmaRxHandle.Instance = SD_DMAx_Rx_STREAM; /* Associate the DMA handle */ __HAL_LINKDMA(hsd, hdmarx, dmaRxHandle); /* Deinitialize the stream for new transfer */ HAL_DMA_DeInit(&dmaRxHandle); /* Configure the DMA stream */ HAL_DMA_Init(&dmaRxHandle); /* Configure DMA Tx parameters */ dmaTxHandle.Init.Channel = SD_DMAx_Tx_CHANNEL; dmaTxHandle.Init.Direction = DMA_MEMORY_TO_PERIPH; dmaTxHandle.Init.PeriphInc = DMA_PINC_DISABLE; dmaTxHandle.Init.MemInc = DMA_MINC_ENABLE; dmaTxHandle.Init.PeriphDataAlignment = DMA_PDATAALIGN_WORD; dmaTxHandle.Init.MemDataAlignment = DMA_MDATAALIGN_WORD; dmaTxHandle.Init.Mode = DMA_PFCTRL; dmaTxHandle.Init.Priority = DMA_PRIORITY_VERY_HIGH; dmaTxHandle.Init.FIFOMode = DMA_FIFOMODE_ENABLE; dmaTxHandle.Init.FIFOThreshold = DMA_FIFO_THRESHOLD_FULL; dmaTxHandle.Init.MemBurst = DMA_MBURST_INC4; dmaTxHandle.Init.PeriphBurst = DMA_PBURST_INC4; dmaTxHandle.Instance = SD_DMAx_Tx_STREAM; /* Associate the DMA handle */ __HAL_LINKDMA(hsd, hdmatx, dmaTxHandle); /* Deinitialize the stream for new transfer */ HAL_DMA_DeInit(&dmaTxHandle); /* Configure the DMA stream */ HAL_DMA_Init(&dmaTxHandle); /* NVIC configuration for DMA transfer complete interrupt */ HAL_NVIC_SetPriority(SD_DMAx_Rx_IRQn, 6, 0); HAL_NVIC_EnableIRQ(SD_DMAx_Rx_IRQn); /* NVIC configuration for DMA transfer complete interrupt */ HAL_NVIC_SetPriority(SD_DMAx_Tx_IRQn, 6, 0); HAL_NVIC_EnableIRQ(SD_DMAx_Tx_IRQn); } /** * @brief Get SD information about specific SD card. * @param CardInfo: Pointer to HAL_SD_CardInfoTypedef structure * @retval None */ void BSP_SD_GetCardInfo(HAL_SD_CardInfoTypedef *CardInfo) { /* Get SD card Information */ HAL_SD_Get_CardInfo(&uSdHandle, CardInfo); }