refactor: SD card SPI HAL (#3957)
* refactor: SD card SPI driver * Removed SPI and DMA StdPeriph drivers * Allow for disabling SPI DMA support * Disable SPI sdcard CRC support * Fix 2MHz timer on NV14 * Shared VS1053b driver * Fix: SPI2 uses PCLK1 * feat: new generic diskio API * More generic SD_CARD_PRESENT() * Fixes * Flush incoming block on token mismatch * Scratch buffer test * Incredible hack to re-sync sd card * fix: SDIO driver
This commit is contained in:
@@ -19,19 +19,37 @@
|
||||
* GNU General Public License for more details.
|
||||
*/
|
||||
|
||||
/* Low level disk I/O module skeleton for FatFs (C)ChaN, 2007 */
|
||||
/*-----------------------------------------------------------------------*/
|
||||
/* This is a stub disk I/O module that acts as front end of the existing */
|
||||
/* disk I/O modules and attach it to FatFs module with common interface. */
|
||||
/*-----------------------------------------------------------------------*/
|
||||
#include "diskio_sdio.h"
|
||||
|
||||
#include "stm32_dma.h"
|
||||
#include "stm32_hal.h"
|
||||
#include "sdio_sd.h"
|
||||
#include "stm32_hal_ll.h"
|
||||
#include "stm32_gpio_driver.h"
|
||||
|
||||
#include "FatFs/diskio.h"
|
||||
#include "hal.h"
|
||||
|
||||
// #include "delays_driver.h"
|
||||
#include "debug.h"
|
||||
|
||||
#include <string.h>
|
||||
#include "debug.h"
|
||||
|
||||
/* Configure PC.08, PC.09, PC.10, PC.11 pins: D0, D1, D2, D3 pins */
|
||||
#if !defined(SD_SDIO_DATA_GPIO) && !defined(SD_SDIO_DATA_GPIO_PINS)
|
||||
#define SD_SDIO_DATA_GPIO GPIOC
|
||||
#define SD_SDIO_DATA_GPIO_PINS \
|
||||
(LL_GPIO_PIN_8 | LL_GPIO_PIN_9 | LL_GPIO_PIN_10 | LL_GPIO_PIN_11)
|
||||
#endif
|
||||
|
||||
/* Configure PD.02 CMD line */
|
||||
#if !defined(SD_SDIO_CMD_GPIO) && !defined(SD_SDIO_CMD_GPIO_PIN)
|
||||
#define SD_SDIO_CMD_GPIO GPIOD
|
||||
#define SD_SDIO_CMD_GPIO_PIN LL_GPIO_PIN_2
|
||||
#endif
|
||||
|
||||
#if !defined(SD_SDIO_CLK_GPIO) && !defined(SD_SDIO_CLK_GPIO_PIN)
|
||||
#define SD_SDIO_CLK_GPIO GPIOC
|
||||
#define SD_SDIO_CLK_GPIO_PIN LL_GPIO_PIN_12
|
||||
#endif
|
||||
|
||||
#if FF_MAX_SS != FF_MIN_SS
|
||||
#error "Variable sector size is not supported"
|
||||
@@ -40,33 +58,103 @@
|
||||
#define BLOCK_SIZE FF_MAX_SS
|
||||
#define SD_TIMEOUT 300 /* 300ms */
|
||||
|
||||
// HAL state
|
||||
static SD_HandleTypeDef sdio;
|
||||
static DMA_HandleTypeDef sdioTxDma;
|
||||
|
||||
// Disk status
|
||||
extern volatile uint32_t WriteStatus;
|
||||
extern volatile uint32_t ReadStatus;
|
||||
static volatile uint32_t WriteStatus;
|
||||
static volatile uint32_t ReadStatus;
|
||||
|
||||
/*-----------------------------------------------------------------------*/
|
||||
/* Inidialize a Drive */
|
||||
|
||||
DSTATUS disk_initialize (
|
||||
BYTE drv /* Physical drive nmuber (0..) */
|
||||
)
|
||||
static void sdio_low_level_init(void)
|
||||
{
|
||||
DSTATUS stat = 0;
|
||||
/* Enable the SDIO APB2 Clock */
|
||||
__HAL_RCC_SDIO_CLK_ENABLE();
|
||||
|
||||
/* Supports only single drive */
|
||||
if (drv)
|
||||
{
|
||||
stat |= STA_NOINIT;
|
||||
LL_GPIO_InitTypeDef GPIO_InitStructure;
|
||||
LL_GPIO_StructInit(&GPIO_InitStructure);
|
||||
|
||||
stm32_gpio_enable_clock(SD_SDIO_DATA_GPIO);
|
||||
stm32_gpio_enable_clock(SD_SDIO_CMD_GPIO);
|
||||
stm32_gpio_enable_clock(SD_SDIO_CLK_GPIO);
|
||||
|
||||
GPIO_InitStructure.Pin = SD_SDIO_DATA_GPIO_PINS;
|
||||
GPIO_InitStructure.Speed = LL_GPIO_SPEED_FREQ_VERY_HIGH;
|
||||
GPIO_InitStructure.Mode = LL_GPIO_MODE_ALTERNATE;
|
||||
GPIO_InitStructure.OutputType = LL_GPIO_OUTPUT_PUSHPULL;
|
||||
GPIO_InitStructure.Pull = LL_GPIO_PULL_UP;
|
||||
GPIO_InitStructure.Alternate = LL_GPIO_AF_12; // SDIO
|
||||
LL_GPIO_Init(SD_SDIO_DATA_GPIO, &GPIO_InitStructure);
|
||||
|
||||
GPIO_InitStructure.Pin = SD_SDIO_CMD_GPIO_PIN;
|
||||
LL_GPIO_Init(SD_SDIO_CMD_GPIO, &GPIO_InitStructure);
|
||||
|
||||
/* Configure PC.12 pin: CLK pin */
|
||||
GPIO_InitStructure.Pin = SD_SDIO_CLK_GPIO_PIN;
|
||||
GPIO_InitStructure.Pull = LL_GPIO_PULL_NO;
|
||||
LL_GPIO_Init(SD_SDIO_CLK_GPIO, &GPIO_InitStructure);
|
||||
|
||||
// SDIO Interrupt ENABLE
|
||||
NVIC_SetPriority(SDIO_IRQn, 0);
|
||||
NVIC_EnableIRQ(SDIO_IRQn);
|
||||
|
||||
// Init SDIO DMA instance
|
||||
sdioTxDma.Instance = SD_SDIO_DMA_STREAM;
|
||||
sdioTxDma.Init.Channel = SD_SDIO_DMA_CHANNEL;
|
||||
sdioTxDma.Init.PeriphInc = DMA_PINC_DISABLE;
|
||||
sdioTxDma.Init.MemInc = DMA_MINC_ENABLE;
|
||||
sdioTxDma.Init.PeriphDataAlignment = DMA_PDATAALIGN_WORD;
|
||||
sdioTxDma.Init.MemDataAlignment = DMA_MDATAALIGN_WORD;
|
||||
sdioTxDma.Init.Mode = DMA_PFCTRL;
|
||||
sdioTxDma.Init.Priority = DMA_PRIORITY_VERY_HIGH;
|
||||
sdioTxDma.Init.FIFOMode = DMA_FIFOMODE_ENABLE;
|
||||
sdioTxDma.Init.FIFOThreshold = DMA_FIFO_THRESHOLD_FULL;
|
||||
sdioTxDma.Init.MemBurst = DMA_MBURST_INC4;
|
||||
sdioTxDma.Init.PeriphBurst = DMA_PBURST_INC4;
|
||||
|
||||
stm32_dma_enable_clock(SD_SDIO_DMA);
|
||||
HAL_DMA_Init(&sdioTxDma);
|
||||
|
||||
__HAL_LINKDMA(&sdio, hdmatx, sdioTxDma);
|
||||
__HAL_LINKDMA(&sdio, hdmarx, sdioTxDma);
|
||||
|
||||
// DMA2 STREAMx Interrupt ENABLE
|
||||
NVIC_SetPriority(SD_SDIO_DMA_IRQn, 0);
|
||||
NVIC_EnableIRQ(SD_SDIO_DMA_IRQn);
|
||||
}
|
||||
|
||||
static DSTATUS sdio_initialize(BYTE lun)
|
||||
{
|
||||
/* SDIO Peripheral Low Level Init */
|
||||
sdio_low_level_init();
|
||||
|
||||
/*!< Configure the SDIO peripheral */
|
||||
/*!< SDIO_CK = SDIOCLK / (SDIO_TRANSFER_CLK_DIV + 2) */
|
||||
/*!< on STM32F4xx devices, SDIOCLK is fixed to 48MHz */
|
||||
sdio.Instance = SDIO;
|
||||
sdio.Init.ClockEdge = SDIO_CLOCK_EDGE_RISING;
|
||||
sdio.Init.ClockPowerSave = SDIO_CLOCK_POWER_SAVE_DISABLE;
|
||||
sdio.Init.ClockBypass = SDIO_CLOCK_BYPASS_DISABLE;
|
||||
sdio.Init.BusWide = SDIO_BUS_WIDE_1B;
|
||||
sdio.Init.HardwareFlowControl = SDIO_HARDWARE_FLOW_CONTROL_DISABLE;
|
||||
sdio.Init.ClockDiv = SD_SDIO_TRANSFER_CLK_DIV;
|
||||
HAL_SD_DeInit(&sdio);
|
||||
|
||||
HAL_StatusTypeDef halStatus = HAL_SD_Init(&sdio);
|
||||
if (halStatus != HAL_OK) {
|
||||
TRACE("HAL_SD_Init() status=%d", halStatus);
|
||||
/*!< CMD Response TimeOut (wait for CMDSENT flag) */
|
||||
return STA_NOINIT;
|
||||
}
|
||||
|
||||
/*-------------------------- SD Init ----------------------------- */
|
||||
SD_Error res = SD_Init();
|
||||
if (res != SD_OK)
|
||||
{
|
||||
TRACE("SD_Init() failed: %d", res);
|
||||
stat |= STA_NOINIT;
|
||||
HAL_SD_CardInfoTypeDef cardInfo;
|
||||
HAL_StatusTypeDef es = HAL_SD_GetCardInfo(&sdio, &cardInfo);
|
||||
if(es != HAL_OK) {
|
||||
return STA_NOINIT;
|
||||
}
|
||||
|
||||
HAL_SD_ConfigWideBusOperation(&sdio, SDIO_BUS_WIDE_4B);
|
||||
|
||||
TRACE("SD card info:");
|
||||
TRACE("type: %u", (uint32_t)(SD_GetCardType()));
|
||||
TRACE("class: %u", (uint32_t)(SD_GetCardClass()));
|
||||
@@ -74,110 +162,95 @@ DSTATUS disk_initialize (
|
||||
TRACE("sector size: %u", (uint32_t)(SD_GetSectorSize()));
|
||||
TRACE("block size: %u", (uint32_t)(SD_GetBlockSize()));
|
||||
|
||||
return(stat);
|
||||
return RES_OK;
|
||||
}
|
||||
|
||||
DWORD scratch[BLOCK_SIZE / 4] __DMA;
|
||||
// DMA scratch buffer used in case the input buffer is not aligned
|
||||
static uint8_t scratch[BLOCK_SIZE] __DMA;
|
||||
|
||||
/*-----------------------------------------------------------------------*/
|
||||
/* Return Disk Status */
|
||||
|
||||
DSTATUS disk_status (
|
||||
BYTE drv /* Physical drive nmuber (0..) */
|
||||
)
|
||||
typedef enum
|
||||
{
|
||||
DSTATUS stat = 0;
|
||||
SD_TRANSFER_OK = 0,
|
||||
SD_TRANSFER_BUSY = 1,
|
||||
SD_TRANSFER_ERROR
|
||||
} SDTransferState;
|
||||
|
||||
if (SD_Detect() != SD_PRESENT)
|
||||
stat |= STA_NODISK;
|
||||
|
||||
// STA_NOTINIT - Subsystem not initailized
|
||||
// STA_PROTECTED - Write protected, MMC/SD switch if available
|
||||
|
||||
return(stat);
|
||||
}
|
||||
|
||||
uint32_t sdReadRetries = 0;
|
||||
|
||||
/*-----------------------------------------------------------------------*/
|
||||
/* Read Sector(s) */
|
||||
|
||||
|
||||
// Please note:
|
||||
// this functions assumes that buff is properly aligned
|
||||
// and in the right RAM segment for DMA
|
||||
//
|
||||
DRESULT disk_read_dma(BYTE drv, BYTE * buff, DWORD sector, UINT count)
|
||||
static SDTransferState sdio_check_card_state()
|
||||
{
|
||||
DRESULT res = RES_ERROR;
|
||||
HAL_SD_CardStateTypeDef cardstate = HAL_SD_GetCardState(&sdio);
|
||||
|
||||
for (int retry = 0; retry < 3; retry++) {
|
||||
|
||||
ReadStatus = 0;
|
||||
SD_Error Status = SD_ReadBlocks(buff, sector, BLOCK_SIZE, count);
|
||||
if (Status != SD_OK) {
|
||||
TRACE("SD ReadBlocks=%d, s:%u c: %u", Status, sector, (uint32_t)count);
|
||||
++sdReadRetries;
|
||||
continue;
|
||||
}
|
||||
|
||||
// Wait that the reading process is completed or a timeout occurs
|
||||
uint32_t timeout = HAL_GetTick();
|
||||
while((ReadStatus == 0) && ((HAL_GetTick() - timeout) < SD_TIMEOUT));
|
||||
|
||||
if (ReadStatus == 0) {
|
||||
TRACE("SD read timeout, s:%u c:%u", sector, (uint32_t)count);
|
||||
++sdReadRetries;
|
||||
continue;
|
||||
}
|
||||
|
||||
ReadStatus = 0;
|
||||
timeout = HAL_GetTick();
|
||||
|
||||
while((HAL_GetTick() - timeout) < SD_TIMEOUT) {
|
||||
if (SD_GetStatus() == SD_TRANSFER_OK) {
|
||||
res = RES_OK;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (res == RES_OK) {
|
||||
// exit retry loop
|
||||
break;
|
||||
}
|
||||
|
||||
TRACE("SD getstatus timeout, s:%u c:%u", sector, (uint32_t)count);
|
||||
if (cardstate == HAL_SD_CARD_TRANSFER) {
|
||||
return SD_TRANSFER_OK;
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
DRESULT __disk_read(BYTE drv, BYTE * buff, DWORD sector, UINT count)
|
||||
{
|
||||
// If unaligned, do the single block reads with a scratch buffer.
|
||||
// If aligned and single sector, do a single block read.
|
||||
// If aligned and multiple sectors, try multi block read.
|
||||
// If multi block read fails, try single block reads without
|
||||
// an intermediate buffer (move trough the provided buffer)
|
||||
|
||||
// TRACE("disk_read %d %p %10d %d", drv, buff, sector, count);
|
||||
if (SD_Detect() != SD_PRESENT) {
|
||||
TRACE("SD_Detect() != SD_PRESENT");
|
||||
return RES_NOTRDY;
|
||||
}
|
||||
|
||||
if (SD_CheckStatusWithTimeout(SD_TIMEOUT) < 0) {
|
||||
return RES_ERROR;
|
||||
else if (cardstate == HAL_SD_CARD_ERROR) {
|
||||
return SD_TRANSFER_ERROR;
|
||||
}
|
||||
|
||||
DRESULT res = RES_OK;
|
||||
if (count == 0) return res;
|
||||
return SD_TRANSFER_BUSY;
|
||||
}
|
||||
|
||||
if ((DWORD)buff < 0x20000000 || ((DWORD)buff & 3)) {
|
||||
// buffer is not aligned, use scratch buffer that is aligned
|
||||
TRACE("disk_read bad alignment (%p)", buff);
|
||||
static int sdio_check_card_state_with_timeout(uint32_t timeout)
|
||||
{
|
||||
uint32_t timer = HAL_GetTick();
|
||||
/* block until SDIO IP is ready again or a timeout occur */
|
||||
while(HAL_GetTick() - timer < timeout) {
|
||||
auto state = sdio_check_card_state();
|
||||
if (state != SD_TRANSFER_BUSY) {
|
||||
return state == SD_TRANSFER_OK ? 0 : -1;
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
static DSTATUS sdio_status(BYTE lun)
|
||||
{
|
||||
DSTATUS stat = RES_OK;
|
||||
|
||||
#if defined(SD_PRESENT_GPIO)
|
||||
if ((LL_GPIO_ReadInputPort(SD_PRESENT_GPIO) & SD_PRESENT_LL_GPIO_PIN) != 0) {
|
||||
stat |= STA_NODISK;
|
||||
}
|
||||
#endif
|
||||
|
||||
return stat;
|
||||
}
|
||||
|
||||
static DRESULT _read_dma(BYTE* buff, DWORD sector, UINT count)
|
||||
{
|
||||
ReadStatus = 0;
|
||||
if (HAL_SD_ReadBlocks_DMA(&sdio, buff, sector, count) != HAL_OK) {
|
||||
TRACE("SD ReadBlocks failed (s:%u/c:%u)", sector, (uint32_t)count);
|
||||
return RES_ERROR;
|
||||
}
|
||||
|
||||
// Wait for the reading process to complete or a timeout to occur
|
||||
uint32_t timeout = HAL_GetTick();
|
||||
while((ReadStatus == 0) && ((HAL_GetTick() - timeout) < SD_TIMEOUT));
|
||||
|
||||
if (ReadStatus == 0) {
|
||||
TRACE("SD read timeout (s:%u c:%u)", sector, (uint32_t)count);
|
||||
return RES_ERROR;
|
||||
}
|
||||
|
||||
ReadStatus = 0;
|
||||
return RES_OK;
|
||||
}
|
||||
|
||||
static DRESULT sdio_read(BYTE lun, BYTE * buff, DWORD sector, UINT count)
|
||||
{
|
||||
DRESULT res = RES_OK;
|
||||
|
||||
// TRACE("disk_read %d %p %10d %d", drv, buff, sector, count);
|
||||
|
||||
if (sdio_check_card_state_with_timeout(SD_TIMEOUT) < 0) {
|
||||
return RES_ERROR;
|
||||
}
|
||||
|
||||
if ((DWORD)buff < SRAM_BASE || ((DWORD)buff & 3)) {
|
||||
// TRACE("disk_read bad alignment (%p)", buff);
|
||||
while (count--) {
|
||||
res = disk_read_dma(drv, (BYTE *)scratch, sector++, 1);
|
||||
res = _read_dma(scratch, sector++, 1);
|
||||
if (res != RES_OK) break;
|
||||
memcpy(buff, scratch, BLOCK_SIZE);
|
||||
buff += BLOCK_SIZE;
|
||||
@@ -185,60 +258,25 @@ DRESULT __disk_read(BYTE drv, BYTE * buff, DWORD sector, UINT count)
|
||||
return res;
|
||||
}
|
||||
|
||||
res = disk_read_dma(drv, buff, sector, count);
|
||||
if (res != RES_OK && count > 1) {
|
||||
// multi-read failed, try reading same sectors, one by one
|
||||
TRACE("disk_read() multi-block failed, trying single block reads...");
|
||||
while (count--) {
|
||||
res = disk_read_dma(drv, buff, sector++, 1);
|
||||
if (res != RES_OK) break;
|
||||
buff += BLOCK_SIZE;
|
||||
res = _read_dma(buff, sector, count);
|
||||
if (res != RES_OK) return res;
|
||||
|
||||
uint32_t timeout = HAL_GetTick();
|
||||
while((HAL_GetTick() - timeout) < SD_TIMEOUT) {
|
||||
if (sdio_check_card_state() == SD_TRANSFER_OK) {
|
||||
return RES_OK;
|
||||
}
|
||||
}
|
||||
|
||||
return res;
|
||||
TRACE("SD getstatus timeout, s:%u c:%u", sector, (uint32_t)count);
|
||||
return RES_ERROR;
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------*/
|
||||
/* Write Sector(s) */
|
||||
|
||||
#if _READONLY == 0
|
||||
DRESULT __disk_write(
|
||||
BYTE drv, /* Physical drive nmuber (0..) */
|
||||
const BYTE *buff, /* Data to be written */
|
||||
DWORD sector, /* Sector address (LBA) */
|
||||
UINT count /* Number of sectors to write (1..255) */
|
||||
)
|
||||
static DRESULT _write_dma(const BYTE *buff, DWORD sector, UINT count)
|
||||
{
|
||||
DRESULT res = RES_OK;
|
||||
|
||||
// TRACE("disk_write %d %p %10d %d", drv, buff, sector, count);
|
||||
|
||||
if (SD_Detect() != SD_PRESENT)
|
||||
return RES_NOTRDY;
|
||||
|
||||
if (SD_CheckStatusWithTimeout(SD_TIMEOUT) < 0) {
|
||||
return RES_ERROR;
|
||||
}
|
||||
|
||||
if ((DWORD)buff < 0x20000000 || ((DWORD)buff & 3)) {
|
||||
//TRACE("disk_write bad alignment (%p)", buff);
|
||||
while(count--) {
|
||||
memcpy(scratch, buff, BLOCK_SIZE);
|
||||
|
||||
res = __disk_write(drv, (BYTE *)scratch, sector++, 1);
|
||||
|
||||
if (res != RES_OK)
|
||||
break;
|
||||
|
||||
buff += BLOCK_SIZE;
|
||||
}
|
||||
return(res);
|
||||
}
|
||||
|
||||
SD_Error Status = SD_WriteBlocks((uint8_t *)buff, sector, BLOCK_SIZE, count);
|
||||
if (Status != SD_OK) {
|
||||
TRACE("SD WriteBlocks=%d, s:%u c: %u", Status, sector, (uint32_t)count);
|
||||
WriteStatus = 0;
|
||||
if (HAL_SD_WriteBlocks_DMA(&sdio, (uint8_t*)buff, sector, count) != HAL_OK) {
|
||||
TRACE("SD WriteBlocks failed (s:%u/c:%u)", sector, (uint32_t)count);
|
||||
return RES_ERROR;
|
||||
}
|
||||
|
||||
@@ -247,94 +285,148 @@ DRESULT __disk_write(
|
||||
while((WriteStatus == 0) && ((HAL_GetTick() - timeout) < SD_TIMEOUT));
|
||||
|
||||
if (WriteStatus == 0) {
|
||||
TRACE("SD write timeout, s:%u c:%u", sector, (uint32_t)count);
|
||||
TRACE("SD write timeout (s:%u/c:%u)", sector, (uint32_t)count);
|
||||
return RES_ERROR;
|
||||
}
|
||||
|
||||
WriteStatus = 0;
|
||||
res = RES_ERROR;
|
||||
timeout = HAL_GetTick();
|
||||
return RES_OK;
|
||||
}
|
||||
|
||||
static DRESULT sdio_write(BYTE lun, const BYTE *buff, DWORD sector, UINT count)
|
||||
{
|
||||
DRESULT res = RES_OK;
|
||||
|
||||
// TRACE("disk_write %d %p %10d %d", drv, buff, sector, count);
|
||||
|
||||
if (sdio_check_card_state_with_timeout(SD_TIMEOUT) < 0) {
|
||||
return RES_ERROR;
|
||||
}
|
||||
|
||||
if ((DWORD)buff < SRAM_BASE || ((DWORD)buff & 3)) {
|
||||
//TRACE("disk_write bad alignment (%p)", buff);
|
||||
while(count--) {
|
||||
memcpy(scratch, buff, BLOCK_SIZE);
|
||||
res = _write_dma((BYTE *)scratch, sector++, 1);
|
||||
if (res != RES_OK) break;
|
||||
buff += BLOCK_SIZE;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
res = _write_dma(buff, sector, count);
|
||||
if (res != RES_OK) return res;
|
||||
|
||||
uint32_t timeout = HAL_GetTick();
|
||||
while((HAL_GetTick() - timeout) < SD_TIMEOUT) {
|
||||
if (SD_GetStatus() == SD_TRANSFER_OK) {
|
||||
res = RES_OK;
|
||||
break;
|
||||
if (sdio_check_card_state() == SD_TRANSFER_OK) {
|
||||
return RES_OK;
|
||||
}
|
||||
}
|
||||
|
||||
if (res != RES_OK) {
|
||||
TRACE("SD getstatus timeout, s:%u c: %u", sector, (uint32_t)count);
|
||||
res = RES_ERROR;
|
||||
TRACE("SD getstatus timeout, s:%u c: %u", sector, (uint32_t)count);
|
||||
return RES_ERROR;
|
||||
}
|
||||
|
||||
static DRESULT sdio_get_sector_count(DWORD* sectors)
|
||||
{
|
||||
HAL_SD_CardInfoTypeDef cardInfo;
|
||||
if(HAL_SD_GetCardInfo(&sdio, &cardInfo) != HAL_OK) {
|
||||
return RES_ERROR;
|
||||
}
|
||||
|
||||
*sectors = cardInfo.LogBlockNbr;
|
||||
return RES_OK;
|
||||
}
|
||||
|
||||
static DRESULT sdio_get_sector_size(DWORD* sector_size)
|
||||
{
|
||||
HAL_SD_CardInfoTypeDef cardInfo;
|
||||
if(HAL_SD_GetCardInfo(&sdio, &cardInfo) != HAL_OK) {
|
||||
return RES_ERROR;
|
||||
}
|
||||
|
||||
*sector_size = cardInfo.LogBlockSize;
|
||||
return RES_OK;
|
||||
}
|
||||
|
||||
static DRESULT sdio_get_block_size(DWORD* block_size)
|
||||
{
|
||||
DWORD sector_size;
|
||||
DRESULT res = sdio_get_sector_size(§or_size);
|
||||
if (res == RES_OK) {
|
||||
*block_size = sector_size / BLOCK_SIZE;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
#endif /* _READONLY */
|
||||
|
||||
/*-----------------------------------------------------------------------*/
|
||||
/* Miscellaneous Functions */
|
||||
|
||||
DRESULT disk_ioctl (
|
||||
BYTE drv, /* Physical drive nmuber (0..) */
|
||||
BYTE ctrl, /* Control code */
|
||||
void *buff /* Buffer to send/receive control data */
|
||||
)
|
||||
DRESULT sdio_ioctl(BYTE lun, BYTE ctrl, void *buff)
|
||||
{
|
||||
DRESULT res;
|
||||
uint32_t tmp;
|
||||
|
||||
if (drv) return RES_PARERR;
|
||||
|
||||
res = RES_ERROR;
|
||||
|
||||
DRESULT res = RES_OK;
|
||||
switch (ctrl) {
|
||||
case GET_SECTOR_COUNT : /* Get number of sectors on the disk (DWORD) */
|
||||
tmp = SD_GetSectorCount();
|
||||
|
||||
if(tmp == 0) {
|
||||
res = RES_ERROR;
|
||||
break;
|
||||
}
|
||||
|
||||
*(DWORD*)buff = tmp;
|
||||
res = RES_OK;
|
||||
res = sdio_get_sector_count((DWORD*)buff);
|
||||
break;
|
||||
|
||||
case GET_SECTOR_SIZE : /* Get R/W sector size (WORD) */
|
||||
tmp = SD_GetSectorSize();
|
||||
|
||||
if(tmp == 0) {
|
||||
res = RES_ERROR;
|
||||
break;
|
||||
}
|
||||
|
||||
*(WORD*)buff = tmp;
|
||||
res = RES_OK;
|
||||
res = sdio_get_sector_size((DWORD*)buff);
|
||||
break;
|
||||
|
||||
case GET_BLOCK_SIZE : /* Get erase block size in unit of sector (DWORD) */
|
||||
tmp = SD_GetBlockSize() / BLOCK_SIZE;
|
||||
|
||||
if(tmp == 0) {
|
||||
res = RES_ERROR;
|
||||
break;
|
||||
}
|
||||
|
||||
*(DWORD*)buff = tmp;
|
||||
res = RES_OK;
|
||||
res = sdio_get_block_size((DWORD*)buff);
|
||||
break;
|
||||
|
||||
case CTRL_SYNC:
|
||||
/* Complete pending write process (needed at _FS_READONLY == 0) */
|
||||
while (SD_GetStatus() == SD_TRANSFER_BUSY);
|
||||
res = RES_OK;
|
||||
/* Complete pending write process */
|
||||
while (sdio_check_card_state() == SD_TRANSFER_BUSY);
|
||||
break;
|
||||
|
||||
default:
|
||||
res = RES_OK;
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
const diskio_driver_t sdio_diskio_driver = {
|
||||
.initialize = sdio_initialize,
|
||||
.status = sdio_status,
|
||||
.read = sdio_read,
|
||||
.write = sdio_write,
|
||||
.ioctl = sdio_ioctl,
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Tx Transfer completed callbacks
|
||||
* @param hsd: SD handle
|
||||
* @retval None
|
||||
*/
|
||||
|
||||
extern "C" void HAL_SD_TxCpltCallback(SD_HandleTypeDef *hsd)
|
||||
{
|
||||
UNUSED(hsd);
|
||||
WriteStatus = 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Rx Transfer completed callbacks
|
||||
* @param hsd: SD handle
|
||||
* @retval None
|
||||
*/
|
||||
|
||||
extern "C" void HAL_SD_RxCpltCallback(SD_HandleTypeDef *hsd)
|
||||
{
|
||||
UNUSED(hsd);
|
||||
ReadStatus = 1;
|
||||
}
|
||||
|
||||
extern "C" void SDIO_IRQHandler(void)
|
||||
{
|
||||
DEBUG_INTERRUPT(INT_SDIO);
|
||||
HAL_SD_IRQHandler(&sdio);
|
||||
}
|
||||
extern "C" void SD_SDIO_DMA_IRQHANDLER(void)
|
||||
{
|
||||
DEBUG_INTERRUPT(INT_SDIO_DMA);
|
||||
HAL_DMA_IRQHandler(&sdioTxDma);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user