From ffb9497d8ae8178683f2ccb2f73f5afb2f2356aa Mon Sep 17 00:00:00 2001 From: jflyper Date: Thu, 9 May 2019 21:01:59 +0900 Subject: [PATCH] [H7] Enable SDCard/SDIO using HAL driver --- src/main/drivers/sdcard_sdio_baremetal.c | 16 +- src/main/drivers/sdio_f4xx.c | 28 -- src/main/drivers/sdio_f7xx.c | 28 -- src/main/drivers/sdio_h7xx.c | 539 +++++++++++++++++++++++ src/main/drivers/sdmmc_sdio.h | 3 - src/main/fc/init.c | 5 + src/main/io/asyncfatfs/asyncfatfs.c | 5 + src/main/msc/usbd_storage_sdio.c | 20 +- 8 files changed, 574 insertions(+), 70 deletions(-) create mode 100644 src/main/drivers/sdio_h7xx.c diff --git a/src/main/drivers/sdcard_sdio_baremetal.c b/src/main/drivers/sdcard_sdio_baremetal.c index dae92d1068..588ca95a3b 100644 --- a/src/main/drivers/sdcard_sdio_baremetal.c +++ b/src/main/drivers/sdcard_sdio_baremetal.c @@ -88,7 +88,7 @@ static void sdcard_reset(void) { if (SD_Init() != 0) { sdcard.failureCount++; - if (sdcard.failureCount >= SDCARD_MAX_CONSECUTIVE_FAILURES || sdcard_isInserted() == SD_NOT_PRESENT) { + if (sdcard.failureCount >= SDCARD_MAX_CONSECUTIVE_FAILURES || !sdcard_isInserted()) { sdcard.state = SDCARD_STATE_NOT_PRESENT; } else { sdcard.operationStartTime = millis(); @@ -174,7 +174,10 @@ static bool sdcard_checkInitDone(void) { if (SD_GetState()) { SD_CardType_t *sdtype = &SD_CardType; - SD_GetCardInfo(); + SD_Error_t errorState = SD_GetCardInfo(); + if (errorState != SD_OK) { + return false; + } sdcard.version = (*sdtype) ? 2 : 1; sdcard.highCapacity = (*sdtype == 2) ? 1 : 0; @@ -198,6 +201,7 @@ static void sdcardSdio_init(const sdcardConfig_t *config, const spiPinConfig_t * return; } +#ifdef USE_DMA_SPEC const dmaChannelSpec_t *dmaChannelSpec = dmaGetChannelSpecByPeripheral(DMA_PERIPH_SDIO, 0, sdioConfig()->dmaopt); if (!dmaChannelSpec) { @@ -211,6 +215,7 @@ static void sdcardSdio_init(const sdcardConfig_t *config, const spiPinConfig_t * sdcard.state = SDCARD_STATE_NOT_PRESENT; return; } +#endif if (config->cardDetectTag) { sdcard.cardDetectPin = IOGetByTag(config->cardDetectTag); } else { @@ -224,8 +229,13 @@ static void sdcardSdio_init(const sdcardConfig_t *config, const spiPinConfig_t * } else { sdcard.useCache = 0; } +#ifdef USE_DMA_SPEC SD_Initialize_LL(dmaChannelSpec->ref); - if (SD_IsDetected()) { +#else + SD_Initialize_LL(SDCARD_SDIO_DMA_OPT); +#endif + + if (sdcard_isInserted()) { if (SD_Init() != 0) { sdcard.state = SDCARD_STATE_NOT_PRESENT; sdcard.failureCount++; diff --git a/src/main/drivers/sdio_f4xx.c b/src/main/drivers/sdio_f4xx.c index 9729895e50..8fe3a173c5 100644 --- a/src/main/drivers/sdio_f4xx.c +++ b/src/main/drivers/sdio_f4xx.c @@ -261,28 +261,6 @@ void SDIO_DMA_ST6_IRQHandler(dmaChannelDescriptor_t *dma); //static void SD_PowerOFF (void); -/** -----------------------------------------------------------------------------------------------------------------*/ -/** SD_IsDetected - * - * @brief Test if card is present - * @param bool true or false - */ -bool SD_IsDetected(void) -{ - __IO uint8_t status = SD_PRESENT; - - /*!< Check GPIO to detect SD */ - #ifdef SDCARD_DETECT_PIN - const IO_t sd_det = IOGetByTag(IO_TAG(SDCARD_DETECT_PIN)); - if (IORead(sd_det) != 0) - { - status = SD_NOT_PRESENT; - } - #endif - return status; -} - - /** -----------------------------------------------------------------------------------------------------------------*/ /** DataTransferInit * @@ -1681,12 +1659,6 @@ bool SD_Init(void) { SD_Error_t ErrorState; - // Check if SD card is present - if(SD_IsDetected() != SD_PRESENT) - { - return false; - } - // Initialize SDIO peripheral interface with default configuration for SD card initialization MODIFY_REG(SDIO->CLKCR, CLKCR_CLEAR_MASK, (uint32_t) SDIO_INIT_CLK_DIV); diff --git a/src/main/drivers/sdio_f7xx.c b/src/main/drivers/sdio_f7xx.c index 07fa8367af..150c3a464a 100644 --- a/src/main/drivers/sdio_f7xx.c +++ b/src/main/drivers/sdio_f7xx.c @@ -259,28 +259,6 @@ void SDMMC_DMA_ST6_IRQHandler(dmaChannelDescriptor_t *dma); //static void SD_PowerOFF (void); -/** -----------------------------------------------------------------------------------------------------------------*/ -/** SD_IsDetected - * - * @brief Test if card is present - * @param bool true or false - */ -bool SD_IsDetected(void) -{ - __IO uint8_t status = SD_PRESENT; - - /*!< Check GPIO to detect SD */ - #ifdef SDCARD_DETECT_PIN - const IO_t sd_det = IOGetByTag(IO_TAG(SDCARD_DETECT_PIN)); - if (IORead(sd_det) != 0) - { - status = SD_NOT_PRESENT; - } - #endif - return status; -} - - /** -----------------------------------------------------------------------------------------------------------------*/ /** DataTransferInit * @@ -1680,12 +1658,6 @@ bool SD_Init(void) { SD_Error_t ErrorState; - // Check if SD card is present - if(SD_IsDetected() != SD_PRESENT) - { - return false; - } - // Initialize SDMMC1 peripheral interface with default configuration for SD card initialization MODIFY_REG(SDMMC1->CLKCR, CLKCR_CLEAR_MASK, (uint32_t) SDMMC_INIT_CLK_DIV); diff --git a/src/main/drivers/sdio_h7xx.c b/src/main/drivers/sdio_h7xx.c new file mode 100644 index 0000000000..867edb365b --- /dev/null +++ b/src/main/drivers/sdio_h7xx.c @@ -0,0 +1,539 @@ +/* + * This file is part of Cleanflight and Betaflight. + * + * Cleanflight and Betaflight are free software. You can redistribute + * this software and/or modify this software under the terms of the + * GNU General Public License as published by the Free Software + * Foundation, either version 3 of the License, or (at your option) + * any later version. + * + * Cleanflight and Betaflight are distributed in the hope that they + * will be useful, but WITHOUT ANY WARRANTY; without even the implied + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this software. + * + * If not, see . + */ + +/* + * Original author: Alain (https://github.com/aroyer-qc) + * Modified for BF source: Chris Hockuba (https://github.com/conkerkh) + */ + +/* Include(s) -------------------------------------------------------------------------------------------------------*/ + +#include "stdbool.h" +#include + +#include "platform.h" + +#ifdef USE_SDCARD_SDIO + +#include "sdmmc_sdio.h" + +#include "pg/pg.h" +#include "pg/sdio.h" + +#include "drivers/io.h" +#include "drivers/io_impl.h" + +typedef struct SD_Handle_s +{ + uint32_t CSD[4]; // SD card specific data table + uint32_t CID[4]; // SD card identification number table + volatile uint32_t RXCplt; // SD RX Complete is equal 0 when no transfer + volatile uint32_t TXCplt; // SD TX Complete is equal 0 when no transfer +} SD_Handle_t; + +SD_HandleTypeDef hsd1; + + +SD_CardInfo_t SD_CardInfo; +SD_CardType_t SD_CardType; + +static SD_Handle_t SD_Handle; + +void HAL_SD_MspInit(SD_HandleTypeDef* hsd) +{ + if(hsd->Instance==SDMMC1) + { + /* Peripheral clock enable */ + //__HAL_RCC_SDMMC1_CLK_ENABLE(); // DC - already done in enableGPIOPowerUsageAndNoiseReductions + //__HAL_RCC_GPIOC_CLK_ENABLE(); // DC - already done in enableGPIOPowerUsageAndNoiseReductions + //__HAL_RCC_GPIOD_CLK_ENABLE(); // DC - already done in enableGPIOPowerUsageAndNoiseReductions + + /**SDMMC1 GPIO Configuration + PC8 ------> SDMMC1_D0 + PC9 ------> SDMMC1_D1 + PC10 ------> SDMMC1_D2 + PC11 ------> SDMMC1_D3 + PC12 ------> SDMMC1_CK + PD2 ------> SDMMC1_CMD + */ + + uint8_t is4BitWidth = sdioConfig()->use4BitWidth; + + const IO_t d0 = IOGetByTag(IO_TAG(PC8)); + const IO_t d1 = IOGetByTag(IO_TAG(PC9)); + const IO_t d2 = IOGetByTag(IO_TAG(PC10)); + const IO_t d3 = IOGetByTag(IO_TAG(PC11)); + const IO_t clk = IOGetByTag(IO_TAG(PC12)); + const IO_t cmd = IOGetByTag(IO_TAG(PD2)); + +#define SDMMC_DATA IO_CONFIG(GPIO_MODE_AF_PP, GPIO_SPEED_FREQ_VERY_HIGH, GPIO_NOPULL) +#define SDMMC_CMD IO_CONFIG(GPIO_MODE_AF_PP, GPIO_SPEED_FREQ_VERY_HIGH, GPIO_NOPULL) +#define SDMMC_CLK IO_CONFIG(GPIO_MODE_AF_PP, GPIO_SPEED_FREQ_VERY_HIGH, GPIO_NOPULL) + + IOConfigGPIOAF(d0, SDMMC_DATA, GPIO_AF12_SDMMC1); + if(is4BitWidth) { + IOConfigGPIOAF(d1, SDMMC_DATA, GPIO_AF12_SDMMC1); + IOConfigGPIOAF(d2, SDMMC_DATA, GPIO_AF12_SDMMC1); + IOConfigGPIOAF(d3, SDMMC_DATA, GPIO_AF12_SDMMC1); + } + IOConfigGPIOAF(clk, SDMMC_CLK, GPIO_AF12_SDMMC1); + IOConfigGPIOAF(cmd, SDMMC_CMD, GPIO_AF12_SDMMC1); + + HAL_NVIC_SetPriority(SDMMC1_IRQn, 0, 0); + HAL_NVIC_EnableIRQ(SDMMC1_IRQn); + } +} + +void SDIO_GPIO_Init(void) +{ + + /* GPIO Ports Clock Enable */ + //__HAL_RCC_GPIOC_CLK_ENABLE(); // DC - already done in enableGPIOPowerUsageAndNoiseReductions + //__HAL_RCC_GPIOD_CLK_ENABLE(); // DC - already done in enableGPIOPowerUsageAndNoiseReductions + + uint8_t is4BitWidth = sdioConfig()->use4BitWidth; + + const IO_t d0 = IOGetByTag(IO_TAG(PC8)); + const IO_t d1 = IOGetByTag(IO_TAG(PC9)); + const IO_t d2 = IOGetByTag(IO_TAG(PC10)); + const IO_t d3 = IOGetByTag(IO_TAG(PC11)); + const IO_t clk = IOGetByTag(IO_TAG(PC12)); + const IO_t cmd = IOGetByTag(IO_TAG(PD2)); + + IOInit(d0, OWNER_SDCARD, 0); + if (is4BitWidth) { + IOInit(d1, OWNER_SDCARD, 0); + IOInit(d2, OWNER_SDCARD, 0); + IOInit(d3, OWNER_SDCARD, 0); + } + IOInit(clk, OWNER_SDCARD, 0); + IOInit(cmd, OWNER_SDCARD, 0); + + // + // Setting all the SDIO pins to high for a short time results in more robust initialisation. + // + IOHi(d0); + IOConfigGPIO(d0, IOCFG_OUT_PP); + + if(is4BitWidth) { + IOHi(d1); + IOHi(d2); + IOHi(d3); + IOConfigGPIO(d1, IOCFG_OUT_PP); + IOConfigGPIO(d2, IOCFG_OUT_PP); + IOConfigGPIO(d3, IOCFG_OUT_PP); + } + + IOHi(clk); + IOHi(cmd); + IOConfigGPIO(clk, IOCFG_OUT_PP); + IOConfigGPIO(cmd, IOCFG_OUT_PP); +} + +void SD_Initialize_LL(DMA_Stream_TypeDef *dma) +{ + UNUSED(dma); + + __HAL_RCC_SDMMC1_CLK_ENABLE(); +} + +bool SD_GetState(void) +{ + HAL_SD_CardStateTypedef cardState = HAL_SD_GetCardState(&hsd1); + + return (cardState == HAL_SD_CARD_TRANSFER); +} + +/* + * return FALSE for OK! + * The F4/F7 code actually returns an SD_Error_t if the card is detected + * SD_OK == 0, SD_* are non-zero and indicate errors. e.g. SD_ERROR = 42 + */ +bool SD_Init(void) +{ + bool failureResult = SD_ERROR; // FIXME fix the calling code, this false for success is bad. + bool successResult = false; + + HAL_StatusTypeDef status; + + memset(&hsd1, 0, sizeof(hsd1)); + + hsd1.Instance = SDMMC1; + hsd1.Init.ClockEdge = SDMMC_CLOCK_EDGE_RISING; + hsd1.Init.ClockPowerSave = SDMMC_CLOCK_POWER_SAVE_ENABLE; + if (sdioConfig()->use4BitWidth) { + hsd1.Init.BusWide = SDMMC_BUS_WIDE_4B; + } else { + hsd1.Init.BusWide = SDMMC_BUS_WIDE_1B; // FIXME untested + } + hsd1.Init.HardwareFlowControl = SDMMC_HARDWARE_FLOW_CONTROL_ENABLE; + hsd1.Init.ClockDiv = 1; // 200Mhz / (2 * 1 ) = 100Mhz, used for "UltraHigh speed SD card" only, see HAL_SD_ConfigWideBusOperation, SDMMC_HSpeed_CLK_DIV, SDMMC_NSpeed_CLK_DIV + + status = HAL_SD_Init(&hsd1); + if (status != HAL_OK) { + return failureResult; + } + + switch(hsd1.SdCard.CardType) { + case CARD_SDSC: + switch (hsd1.SdCard.CardVersion) { + case CARD_V1_X: + SD_CardType = SD_STD_CAPACITY_V1_1; + break; + case CARD_V2_X: + SD_CardType = SD_STD_CAPACITY_V2_0; + break; + default: + return failureResult; + } + break; + + case CARD_SDHC_SDXC: + SD_CardType = SD_HIGH_CAPACITY; + break; + + default: + return failureResult; + } + + STATIC_ASSERT(sizeof(SD_Handle.CSD) == sizeof(hsd1.CSD), hal-csd-size-error); + memcpy(&SD_Handle.CSD, &hsd1.CSD, sizeof(SD_Handle.CSD)); + + STATIC_ASSERT(sizeof(SD_Handle.CID) == sizeof(hsd1.CID), hal-cid-size-error); + memcpy(&SD_Handle.CID, &hsd1.CID, sizeof(SD_Handle.CID)); + + return successResult; +} + +SD_Error_t SD_GetCardInfo(void) +{ + SD_Error_t ErrorState = SD_OK; + + // fill in SD_CardInfo + + uint32_t Temp = 0; + + // Byte 0 + Temp = (SD_Handle.CSD[0] & 0xFF000000) >> 24; + SD_CardInfo.SD_csd.CSDStruct = (uint8_t)((Temp & 0xC0) >> 6); + SD_CardInfo.SD_csd.SysSpecVersion = (uint8_t)((Temp & 0x3C) >> 2); + SD_CardInfo.SD_csd.Reserved1 = Temp & 0x03; + + // Byte 1 + Temp = (SD_Handle.CSD[0] & 0x00FF0000) >> 16; + SD_CardInfo.SD_csd.TAAC = (uint8_t)Temp; + + // Byte 2 + Temp = (SD_Handle.CSD[0] & 0x0000FF00) >> 8; + SD_CardInfo.SD_csd.NSAC = (uint8_t)Temp; + + // Byte 3 + Temp = SD_Handle.CSD[0] & 0x000000FF; + SD_CardInfo.SD_csd.MaxBusClkFrec = (uint8_t)Temp; + + // Byte 4 + Temp = (SD_Handle.CSD[1] & 0xFF000000) >> 24; + SD_CardInfo.SD_csd.CardComdClasses = (uint16_t)(Temp << 4); + + // Byte 5 + Temp = (SD_Handle.CSD[1] & 0x00FF0000) >> 16; + SD_CardInfo.SD_csd.CardComdClasses |= (uint16_t)((Temp & 0xF0) >> 4); + SD_CardInfo.SD_csd.RdBlockLen = (uint8_t)(Temp & 0x0F); + + // Byte 6 + Temp = (SD_Handle.CSD[1] & 0x0000FF00) >> 8; + SD_CardInfo.SD_csd.PartBlockRead = (uint8_t)((Temp & 0x80) >> 7); + SD_CardInfo.SD_csd.WrBlockMisalign = (uint8_t)((Temp & 0x40) >> 6); + SD_CardInfo.SD_csd.RdBlockMisalign = (uint8_t)((Temp & 0x20) >> 5); + SD_CardInfo.SD_csd.DSRImpl = (uint8_t)((Temp & 0x10) >> 4); + SD_CardInfo.SD_csd.Reserved2 = 0; /*!< Reserved */ + + if((SD_CardType == SD_STD_CAPACITY_V1_1) || (SD_CardType == SD_STD_CAPACITY_V2_0)) { + SD_CardInfo.SD_csd.DeviceSize = (Temp & 0x03) << 10; + + // Byte 7 + Temp = (uint8_t)(SD_Handle.CSD[1] & 0x000000FF); + SD_CardInfo.SD_csd.DeviceSize |= (Temp) << 2; + + // Byte 8 + Temp = (uint8_t)((SD_Handle.CSD[2] & 0xFF000000) >> 24); + SD_CardInfo.SD_csd.DeviceSize |= (Temp & 0xC0) >> 6; + + SD_CardInfo.SD_csd.MaxRdCurrentVDDMin = (Temp & 0x38) >> 3; + SD_CardInfo.SD_csd.MaxRdCurrentVDDMax = (Temp & 0x07); + + // Byte 9 + Temp = (uint8_t)((SD_Handle.CSD[2] & 0x00FF0000) >> 16); + SD_CardInfo.SD_csd.MaxWrCurrentVDDMin = (Temp & 0xE0) >> 5; + SD_CardInfo.SD_csd.MaxWrCurrentVDDMax = (Temp & 0x1C) >> 2; + SD_CardInfo.SD_csd.DeviceSizeMul = (Temp & 0x03) << 1; + + // Byte 10 + Temp = (uint8_t)((SD_Handle.CSD[2] & 0x0000FF00) >> 8); + SD_CardInfo.SD_csd.DeviceSizeMul |= (Temp & 0x80) >> 7; + + SD_CardInfo.CardCapacity = (SD_CardInfo.SD_csd.DeviceSize + 1) ; + SD_CardInfo.CardCapacity *= (1 << (SD_CardInfo.SD_csd.DeviceSizeMul + 2)); + SD_CardInfo.CardBlockSize = 1 << (SD_CardInfo.SD_csd.RdBlockLen); + SD_CardInfo.CardCapacity *= SD_CardInfo.CardBlockSize; + } else if(SD_CardType == SD_HIGH_CAPACITY) { + // Byte 7 + Temp = (uint8_t)(SD_Handle.CSD[1] & 0x000000FF); + SD_CardInfo.SD_csd.DeviceSize = (Temp & 0x3F) << 16; + + // Byte 8 + Temp = (uint8_t)((SD_Handle.CSD[2] & 0xFF000000) >> 24); + + SD_CardInfo.SD_csd.DeviceSize |= (Temp << 8); + + // Byte 9 + Temp = (uint8_t)((SD_Handle.CSD[2] & 0x00FF0000) >> 16); + + SD_CardInfo.SD_csd.DeviceSize |= (Temp); + + // Byte 10 + Temp = (uint8_t)((SD_Handle.CSD[2] & 0x0000FF00) >> 8); + + SD_CardInfo.CardCapacity = ((uint64_t)SD_CardInfo.SD_csd.DeviceSize + 1) * 1024; + SD_CardInfo.CardBlockSize = 512; + } else { + // Not supported card type + ErrorState = SD_ERROR; + } + + SD_CardInfo.SD_csd.EraseGrSize = (Temp & 0x40) >> 6; + SD_CardInfo.SD_csd.EraseGrMul = (Temp & 0x3F) << 1; + + // Byte 11 + Temp = (uint8_t)(SD_Handle.CSD[2] & 0x000000FF); + SD_CardInfo.SD_csd.EraseGrMul |= (Temp & 0x80) >> 7; + SD_CardInfo.SD_csd.WrProtectGrSize = (Temp & 0x7F); + + // Byte 12 + Temp = (uint8_t)((SD_Handle.CSD[3] & 0xFF000000) >> 24); + SD_CardInfo.SD_csd.WrProtectGrEnable = (Temp & 0x80) >> 7; + SD_CardInfo.SD_csd.ManDeflECC = (Temp & 0x60) >> 5; + SD_CardInfo.SD_csd.WrSpeedFact = (Temp & 0x1C) >> 2; + SD_CardInfo.SD_csd.MaxWrBlockLen = (Temp & 0x03) << 2; + + // Byte 13 + Temp = (uint8_t)((SD_Handle.CSD[3] & 0x00FF0000) >> 16); + SD_CardInfo.SD_csd.MaxWrBlockLen |= (Temp & 0xC0) >> 6; + SD_CardInfo.SD_csd.WriteBlockPaPartial = (Temp & 0x20) >> 5; + SD_CardInfo.SD_csd.Reserved3 = 0; + SD_CardInfo.SD_csd.ContentProtectAppli = (Temp & 0x01); + + // Byte 14 + Temp = (uint8_t)((SD_Handle.CSD[3] & 0x0000FF00) >> 8); + SD_CardInfo.SD_csd.FileFormatGrouop = (Temp & 0x80) >> 7; + SD_CardInfo.SD_csd.CopyFlag = (Temp & 0x40) >> 6; + SD_CardInfo.SD_csd.PermWrProtect = (Temp & 0x20) >> 5; + SD_CardInfo.SD_csd.TempWrProtect = (Temp & 0x10) >> 4; + SD_CardInfo.SD_csd.FileFormat = (Temp & 0x0C) >> 2; + SD_CardInfo.SD_csd.ECC = (Temp & 0x03); + + // Byte 15 + Temp = (uint8_t)(SD_Handle.CSD[3] & 0x000000FF); + SD_CardInfo.SD_csd.CSD_CRC = (Temp & 0xFE) >> 1; + SD_CardInfo.SD_csd.Reserved4 = 1; + + // Byte 0 + Temp = (uint8_t)((SD_Handle.CID[0] & 0xFF000000) >> 24); + SD_CardInfo.SD_cid.ManufacturerID = Temp; + + // Byte 1 + Temp = (uint8_t)((SD_Handle.CID[0] & 0x00FF0000) >> 16); + SD_CardInfo.SD_cid.OEM_AppliID = Temp << 8; + + // Byte 2 + Temp = (uint8_t)((SD_Handle.CID[0] & 0x000000FF00) >> 8); + SD_CardInfo.SD_cid.OEM_AppliID |= Temp; + + // Byte 3 + Temp = (uint8_t)(SD_Handle.CID[0] & 0x000000FF); + SD_CardInfo.SD_cid.ProdName1 = Temp << 24; + + // Byte 4 + Temp = (uint8_t)((SD_Handle.CID[1] & 0xFF000000) >> 24); + SD_CardInfo.SD_cid.ProdName1 |= Temp << 16; + + // Byte 5 + Temp = (uint8_t)((SD_Handle.CID[1] & 0x00FF0000) >> 16); + SD_CardInfo.SD_cid.ProdName1 |= Temp << 8; + + // Byte 6 + Temp = (uint8_t)((SD_Handle.CID[1] & 0x0000FF00) >> 8); + SD_CardInfo.SD_cid.ProdName1 |= Temp; + + // Byte 7 + Temp = (uint8_t)(SD_Handle.CID[1] & 0x000000FF); + SD_CardInfo.SD_cid.ProdName2 = Temp; + + // Byte 8 + Temp = (uint8_t)((SD_Handle.CID[2] & 0xFF000000) >> 24); + SD_CardInfo.SD_cid.ProdRev = Temp; + + // Byte 9 + Temp = (uint8_t)((SD_Handle.CID[2] & 0x00FF0000) >> 16); + SD_CardInfo.SD_cid.ProdSN = Temp << 24; + + // Byte 10 + Temp = (uint8_t)((SD_Handle.CID[2] & 0x0000FF00) >> 8); + SD_CardInfo.SD_cid.ProdSN |= Temp << 16; + + // Byte 11 + Temp = (uint8_t)(SD_Handle.CID[2] & 0x000000FF); + SD_CardInfo.SD_cid.ProdSN |= Temp << 8; + + // Byte 12 + Temp = (uint8_t)((SD_Handle.CID[3] & 0xFF000000) >> 24); + SD_CardInfo.SD_cid.ProdSN |= Temp; + + // Byte 13 + Temp = (uint8_t)((SD_Handle.CID[3] & 0x00FF0000) >> 16); + SD_CardInfo.SD_cid.Reserved1 |= (Temp & 0xF0) >> 4; + SD_CardInfo.SD_cid.ManufactDate = (Temp & 0x0F) << 8; + + // Byte 14 + Temp = (uint8_t)((SD_Handle.CID[3] & 0x0000FF00) >> 8); + SD_CardInfo.SD_cid.ManufactDate |= Temp; + + // Byte 15 + Temp = (uint8_t)(SD_Handle.CID[3] & 0x000000FF); + SD_CardInfo.SD_cid.CID_CRC = (Temp & 0xFE) >> 1; + SD_CardInfo.SD_cid.Reserved2 = 1; + + return ErrorState; +} + +SD_Error_t SD_CheckWrite(void) { + if (SD_Handle.TXCplt != 0) return SD_BUSY; + return SD_OK; +} + +SD_Error_t SD_CheckRead(void) { + if (SD_Handle.RXCplt != 0) return SD_BUSY; + return SD_OK; +} + +SD_Error_t SD_WriteBlocks_DMA(uint64_t WriteAddress, uint32_t *buffer, uint32_t BlockSize, uint32_t NumberOfBlocks) +{ + SD_Error_t ErrorState = SD_OK; + SD_Handle.TXCplt = 1; + + if (BlockSize != 512) { + return SD_ERROR; // unsupported. + } + + /* + the SCB_CleanDCache_by_Addr() requires a 32-Byte aligned address + adjust the address and the D-Cache size to clean accordingly. + */ + uint32_t alignedAddr = (uint32_t)buffer & ~0x1F; + SCB_CleanDCache_by_Addr((uint32_t*)alignedAddr, NumberOfBlocks * BlockSize + ((uint32_t)buffer - alignedAddr)); + + HAL_StatusTypeDef status; + if ((status = HAL_SD_WriteBlocks_DMA(&hsd1, (uint8_t *)buffer, WriteAddress, NumberOfBlocks)) != HAL_OK) { + return SD_ERROR; + } + + return ErrorState; +} + +typedef struct { + uint32_t *buffer; + uint32_t BlockSize; + uint32_t NumberOfBlocks; +} sdReadParameters_t; + +sdReadParameters_t sdReadParameters; + +SD_Error_t SD_ReadBlocks_DMA(uint64_t ReadAddress, uint32_t *buffer, uint32_t BlockSize, uint32_t NumberOfBlocks) +{ + SD_Error_t ErrorState = SD_OK; + + if (BlockSize != 512) { + return SD_ERROR; // unsupported. + } + + SD_Handle.RXCplt = 1; + + sdReadParameters.buffer = buffer; + sdReadParameters.BlockSize = BlockSize; + sdReadParameters.NumberOfBlocks = NumberOfBlocks; + + + HAL_StatusTypeDef status; + if ((status = HAL_SD_ReadBlocks_DMA(&hsd1, (uint8_t *)buffer, ReadAddress, NumberOfBlocks)) != HAL_OK) { + return SD_ERROR; + } + + return ErrorState; +} + +/** + * @brief Tx Transfer completed callback + * @param hsd: SD handle + * @retval None + */ +void HAL_SD_TxCpltCallback(SD_HandleTypeDef *hsd) +{ + UNUSED(hsd); + + SD_Handle.TXCplt = 0; +} + +/** + * @brief Rx Transfer completed callback + * @param hsd: SD handle + * @retval None + */ +void HAL_SD_RxCpltCallback(SD_HandleTypeDef *hsd) +{ + UNUSED(hsd); + + SD_Handle.RXCplt = 0; + + /* + the SCB_InvalidateDCache_by_Addr() requires a 32-Byte aligned address, + adjust the address and the D-Cache size to invalidate accordingly. + */ + uint32_t alignedAddr = (uint32_t)sdReadParameters.buffer & ~0x1F; + SCB_InvalidateDCache_by_Addr((uint32_t*)alignedAddr, sdReadParameters.NumberOfBlocks * sdReadParameters.BlockSize + ((uint32_t)sdReadParameters.buffer - alignedAddr)); +} + +void HAL_SD_AbortCallback(SD_HandleTypeDef *hsd) +{ + UNUSED(hsd); + + SD_Handle.TXCplt = 0; + SD_Handle.RXCplt = 0; +} + + +/** +* @brief This function handles SDMMC1 global interrupt. +*/ +void SDMMC1_IRQHandler(void) +{ + HAL_SD_IRQHandler(&hsd1); +} + +#endif diff --git a/src/main/drivers/sdmmc_sdio.h b/src/main/drivers/sdmmc_sdio.h index 075768189d..937091b08d 100644 --- a/src/main/drivers/sdmmc_sdio.h +++ b/src/main/drivers/sdmmc_sdio.h @@ -64,9 +64,6 @@ #define MSD_ERROR ((uint8_t)0x01) #define MSD_ERROR_SD_NOT_PRESENT ((uint8_t)0x02) -#define SD_PRESENT ((uint8_t)0x01) -#define SD_NOT_PRESENT ((uint8_t)0x00) - #define SD_DATATIMEOUT ((uint32_t)100000000) #define SD_DETECT_GPIO_PORT GPIOC diff --git a/src/main/fc/init.c b/src/main/fc/init.c index f10e772a6e..b1266083c4 100644 --- a/src/main/fc/init.c +++ b/src/main/fc/init.c @@ -501,6 +501,11 @@ void init(void) updateHardwareRevision(); #endif +#if defined(STM32H7) && defined(USE_SDCARD_SDIO) // H7 only for now, likely should be applied to F4/F7 too + void SDIO_GPIO_Init(void); + SDIO_GPIO_Init(); +#endif + #ifdef USE_VTX_RTC6705 bool useRTC6705 = rtc6705IOInit(vtxIOConfig()); #endif diff --git a/src/main/io/asyncfatfs/asyncfatfs.c b/src/main/io/asyncfatfs/asyncfatfs.c index 1aaccf4ed9..b91545b699 100644 --- a/src/main/io/asyncfatfs/asyncfatfs.c +++ b/src/main/io/asyncfatfs/asyncfatfs.c @@ -457,7 +457,12 @@ typedef struct afatfs_t { } initState; #endif + +#ifdef STM32H7 + uint8_t cache[AFATFS_SECTOR_SIZE * AFATFS_NUM_CACHE_SECTORS] __attribute__((aligned(32))); +#else uint8_t cache[AFATFS_SECTOR_SIZE * AFATFS_NUM_CACHE_SECTORS]; +#endif afatfsCacheBlockDescriptor_t cacheDescriptor[AFATFS_NUM_CACHE_SECTORS]; uint32_t cacheTimer; diff --git a/src/main/msc/usbd_storage_sdio.c b/src/main/msc/usbd_storage_sdio.c index a47b7863bb..fc7d690b9f 100644 --- a/src/main/msc/usbd_storage_sdio.c +++ b/src/main/msc/usbd_storage_sdio.c @@ -38,6 +38,7 @@ #include "drivers/sdmmc_sdio.h" #include "drivers/light_led.h" #include "drivers/io.h" +#include "drivers/sdcard.h" #include "pg/pg.h" #include "pg/sdcard.h" @@ -170,12 +171,15 @@ static int8_t STORAGE_Init (uint8_t lun) SD_Initialize_LL(dmaChannelSpec->ref); #else - SD_Initialize_LL(SDIO_DMA); + SD_Initialize_LL(SDCARD_SDIO_DMA_OPT); #endif - if (SD_Init() != 0) { - return 1; - } + if (!sdcard_isInserted()) { + return 1; + } + if (SD_Init() != 0) { + return 1; + } LED0_ON; @@ -196,7 +200,7 @@ static int8_t STORAGE_GetCapacity (uint8_t lun, uint32_t *block_num, uint32_t *b #endif { UNUSED(lun); - if (SD_IsDetected() == 0) { + if (!sdcard_isInserted()) { return -1; } SD_GetCardInfo(); @@ -217,7 +221,7 @@ static int8_t STORAGE_IsReady (uint8_t lun) { UNUSED(lun); int8_t ret = -1; - if (SD_GetState() == true && SD_IsDetected() == SD_PRESENT) { + if (SD_GetState() == true && sdcard_isInserted()) { ret = 0; } return ret; @@ -249,7 +253,7 @@ static int8_t STORAGE_Read (uint8_t lun, uint16_t blk_len) { UNUSED(lun); - if (SD_IsDetected() == 0) { + if (!sdcard_isInserted()) { return -1; } LED1_ON; @@ -276,7 +280,7 @@ static int8_t STORAGE_Write (uint8_t lun, uint16_t blk_len) { UNUSED(lun); - if (SD_IsDetected() == 0) { + if (!sdcard_isInserted()) { return -1; } LED1_ON;