本帖最后由 WT_0213 于 2024-1-19 15:00 编辑
发现小安派AiPi-Eyes-R1和AiPi-Eyes-R2都有预留TF卡槽的位置,未焊接卡槽。
如果 AiPi-Eyes-Rx 补焊 TF卡槽,是否可以直接使用。与哪些硬件冲突呢。
想要在TF卡里面存一些图片或者音视频文件。是否可行。
如果可行的话,希望官方大佬能出个相关的教程,自带的存储有限存不了太多东西。 😄
sdcard
sdh_sdcard.h
/**
* @file sdh_sdcard.h
* @brief
*
* Copyright (c) 2021 Bouffalolab team
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership. The
* ASF licenses this file to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance with the
* License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*
*/
#ifndef _SDH_SDCARD_H
#define _SDH_SDCARD_H
#include <stdint.h>
#if defined(BL808)
#include "bl808_common.h"
#include "bl808_glb.h"
#include "bl808_sdh.h"
#elif defined(BL606P)
#include "bl606p_common.h"
#include "bl606p_glb.h"
#include "bl606p_sdh.h"
#elif defined(BL616)
#include "bl616_common.h"
#include "bl616_glb.h"
#include "bl616_sdh.h"
#elif defined(BL628)
#include "bl628_common.h"
#include "bl628_glb.h"
#include "bl628_smih.h"
#else
#define _SDH_SDCARD_CHECK
#endif
#ifndef _SDH_SDCARD_CHECK
#define _SDH_SDCARD_CHECK
/*! @brief Reverse byte sequence in uint32_t */
#define SWAP_WORD_BYTE_SEQUENCE(x) (__REV(x))
/*! @brief Default block size */
#define SDH_DEFAULT_BLOCK_SIZE (512U)
typedef enum {
SD_OK = 0,
SD_CMD_ERROR,
SD_DataCfg_ERROR,
SD_WAITING,
} SD_Error;
/*! @brief Type used for all status and error return values. */
typedef int32_t status_t;
/*! @brief Construct a status code value from a group and code number. */
#define MAKE_STATUS(group, code) ((((group)*100) + (code)))
/*! @brief Status group numbers. */
enum _status_groups {
StatusGroup_Generic = 0, /*!< Group number for generic status codes. */
StatusGroup_SDH = 1, /*!< Group number for SDHC status code */
};
/*! @brief Generic status return codes. */
enum _generic_status {
Status_Success = MAKE_STATUS(StatusGroup_Generic, 0),
Status_Fail = MAKE_STATUS(StatusGroup_Generic, 1),
Status_OutOfRange = MAKE_STATUS(StatusGroup_Generic, 2),
Status_InvalidArgument = MAKE_STATUS(StatusGroup_Generic, 3),
Status_Timeout = MAKE_STATUS(StatusGroup_Generic, 4),
};
/*! @brief SD/MMC card API's running status. */
enum _sdmmc_status {
Status_SDH_NotSupportYet = MAKE_STATUS(StatusGroup_SDH, 0U), /*!< Haven't supported */
Status_SDH_TransferFailed = MAKE_STATUS(StatusGroup_SDH, 1U), /*!< Send command failed */
Status_SDH_SetCardBlockSizeFailed = MAKE_STATUS(StatusGroup_SDH, 2U), /*!< Set block size failed */
Status_SDH_HostNotSupport = MAKE_STATUS(StatusGroup_SDH, 3U), /*!< Host doesn't support */
Status_SDH_CardNotSupport = MAKE_STATUS(StatusGroup_SDH, 4U), /*!< Card doesn't support */
Status_SDH_AllSendCidFailed = MAKE_STATUS(StatusGroup_SDH, 5U), /*!< Send CID failed */
Status_SDH_SendRelativeAddressFailed = MAKE_STATUS(StatusGroup_SDH, 6U), /*!< Send relative address failed */
Status_SDH_SendCsdFailed = MAKE_STATUS(StatusGroup_SDH, 7U), /*!< Send CSD failed */
Status_SDH_SelectCardFailed = MAKE_STATUS(StatusGroup_SDH, 8U), /*!< Select card failed */
Status_SDH_SendScrFailed = MAKE_STATUS(StatusGroup_SDH, 9U), /*!< Send SCR failed */
Status_SDH_SetDataBusWidthFailed = MAKE_STATUS(StatusGroup_SDH, 10U), /*!< Set bus width failed */
Status_SDH_GoIdleFailed = MAKE_STATUS(StatusGroup_SDH, 11U), /*!< Go idle failed */
Status_SDH_HandShakeOperationConditionFailed = MAKE_STATUS(StatusGroup_SDH, 12U), /*!< Send Operation Condition failed */
Status_SDH_SendApplicationCommandFailed = MAKE_STATUS(StatusGroup_SDH, 13U), /*!< Send application command failed */
Status_SDH_SwitchFailed = MAKE_STATUS(StatusGroup_SDH, 14U), /*!< Switch command failed */
Status_SDH_StopTransmissionFailed = MAKE_STATUS(StatusGroup_SDH, 15U), /*!< Stop transmission failed */
Status_SDH_WaitWriteCompleteFailed = MAKE_STATUS(StatusGroup_SDH, 16U), /*!< Wait write complete failed */
Status_SDH_SetBlockCountFailed = MAKE_STATUS(StatusGroup_SDH, 17U), /*!< Set block count failed */
Status_SDH_SetRelativeAddressFailed = MAKE_STATUS(StatusGroup_SDH, 18U), /*!< Set relative address failed */
Status_SDH_SwitchBusTimingFailed = MAKE_STATUS(StatusGroup_SDH, 19U), /*!< Switch high speed failed */
Status_SDH_SendExtendedCsdFailed = MAKE_STATUS(StatusGroup_SDH, 20U), /*!< Send EXT_CSD failed */
Status_SDH_ConfigureBootFailed = MAKE_STATUS(StatusGroup_SDH, 21U), /*!< Configure boot failed */
Status_SDH_ConfigureExtendedCsdFailed = MAKE_STATUS(StatusGroup_SDH, 22U), /*!< Configure EXT_CSD failed */
Status_SDH_EnableHighCapacityEraseFailed = MAKE_STATUS(StatusGroup_SDH, 23U), /*!< Enable high capacity erase failed */
Status_SDH_SendTestPatternFailed = MAKE_STATUS(StatusGroup_SDH, 24U), /*!< Send test pattern failed */
Status_SDH_ReceiveTestPatternFailed = MAKE_STATUS(StatusGroup_SDH, 25U), /*!< Receive test pattern failed */
Status_SDH_SDIO_ResponseError = MAKE_STATUS(StatusGroup_SDH, 26U), /*!< sdio response error */
Status_SDH_SDIO_InvalidArgument = MAKE_STATUS(StatusGroup_SDH, 27U), /*!< sdio invalid argument response error */
Status_SDH_SDIO_SendOperationConditionFail = MAKE_STATUS(StatusGroup_SDH, 28U), /*!< sdio send operation condition fail */
Status_SDH_InvalidVoltage = MAKE_STATUS(StatusGroup_SDH, 29U), /*!< invaild voltage */
Status_SDH_SDIO_SwitchHighSpeedFail = MAKE_STATUS(StatusGroup_SDH, 30U), /*!< switch to high speed fail */
Status_SDH_SDIO_ReadCISFail = MAKE_STATUS(StatusGroup_SDH, 31U), /*!< read CIS fail */
Status_SDH_SDIO_InvalidCard = MAKE_STATUS(StatusGroup_SDH, 32U), /*!< invaild SDIO card */
Status_SDH_TuningFail = MAKE_STATUS(StatusGroup_SDH, 33U), /*!< tuning fail */
Status_SDH_SwitchVoltageFail = MAKE_STATUS(StatusGroup_SDH, 34U), /*!< switch voltage fail*/
Status_SDH_ReTuningRequest = MAKE_STATUS(StatusGroup_SDH, 35U), /*!< retuning request */
Status_SDH_SetDriverStrengthFail = MAKE_STATUS(StatusGroup_SDH, 36U), /*!< set driver strength fail */
Status_SDH_SetPowerClassFail = MAKE_STATUS(StatusGroup_SDH, 37U), /*!< set power class fail */
Status_SDH_HostNotReady = MAKE_STATUS(StatusGroup_SDH, 38U), /*!< host controller not ready */
Status_SDH_CardDetectFailed = MAKE_STATUS(StatusGroup_SDH, 39U), /*!< card detect failed */
Status_SDH_CmdResponseError = MAKE_STATUS(StatusGroup_SDH, 40U), /*!< cmd response timeout */
Status_SDH_SendSsrFailed = MAKE_STATUS(StatusGroup_SDH, 41U), /*!< Send SSR failed */
};
/**
* @brief SDIO Transfer state
*/
typedef enum {
SD_TRANSFER_OK = 0,
SD_TRANSFER_BUSY = 1,
SD_TRANSFER_ERROR
} SDTransferState;
/**
* @brief SD Card States
*/
typedef enum {
SD_CARD_READY = ((uint32_t)0x00000001),
SD_CARD_IDENTIFICATION = ((uint32_t)0x00000002),
SD_CARD_STANDBY = ((uint32_t)0x00000003),
SD_CARD_TRANSFER = ((uint32_t)0x00000004),
SD_CARD_SENDING = ((uint32_t)0x00000005),
SD_CARD_RECEIVING = ((uint32_t)0x00000006),
SD_CARD_PROGRAMMING = ((uint32_t)0x00000007),
SD_CARD_DISCONNECTED = ((uint32_t)0x00000008),
SD_CARD_ERROR = ((uint32_t)0x000000FF)
} SDCardState;
/**
* @brief Card Specific Data: CSD Register
*/
typedef struct
{
uint8_t CSDStruct; /*!< CSD structure */
uint8_t SysSpecVersion; /*!< System specification version */
uint8_t Reserved1; /*!< Reserved */
uint8_t TAAC; /*!< Data read access-time 1 */
uint8_t NSAC; /*!< Data read access-time 2 in CLK cycles */
uint8_t MaxBusClkFrec; /*!< Max. bus clock frequency */
uint16_t CardComdClasses; /*!< Card command classes */
uint8_t RdBlockLen; /*!< Max. read data block length */
uint8_t PartBlockRead; /*!< Partial blocks for read allowed */
uint8_t WrBlockMisalign; /*!< Write block misalignment */
uint8_t RdBlockMisalign; /*!< Read block misalignment */
uint8_t DSRImpl; /*!< DSR implemented */
uint8_t Reserved2; /*!< Reserved */
uint32_t DeviceSize; /*!< Device Size */
uint8_t MaxRdCurrentVDDMin; /*!< Max. read current @ VDD min */
uint8_t MaxRdCurrentVDDMax; /*!< Max. read current @ VDD max */
uint8_t MaxWrCurrentVDDMin; /*!< Max. write current @ VDD min */
uint8_t MaxWrCurrentVDDMax; /*!< Max. write current @ VDD max */
uint8_t DeviceSizeMul; /*!< Device size multiplier */
uint8_t EraseGrSize; /*!< Erase group size */
uint8_t EraseGrMul; /*!< Erase group size multiplier */
uint8_t WrProtectGrSize; /*!< Write protect group size */
uint8_t WrProtectGrEnable; /*!< Write protect group enable */
uint8_t ManDeflECC; /*!< Manufacturer default ECC */
uint8_t WrSpeedFact; /*!< Write speed factor */
uint8_t MaxWrBlockLen; /*!< Max. write data block length */
uint8_t WriteBlockPaPartial; /*!< Partial blocks for write allowed */
uint8_t Reserved3; /*!< Reserded */
uint8_t ContentProtectAppli; /*!< Content protection application */
uint8_t FileFormatGrouop; /*!< File format group */
uint8_t CopyFlag; /*!< Copy flag (OTP) */
uint8_t PermWrProtect; /*!< Permanent write protection */
uint8_t TempWrProtect; /*!< Temporary write protection */
uint8_t FileFormat; /*!< File Format */
uint8_t ECC; /*!< ECC code */
} SD_CSD;
/**
* @brief Card Identification Data: CID Register
*/
typedef struct
{
uint8_t ManufacturerID; /*!< ManufacturerID */
uint8_t OEM_AppliID[3]; /*!< OEM/Application ID end with 0 for str display*/
uint8_t ProdName[6]; /*!< Product Name part1 end with 0 for str display*/
uint8_t ProdRev; /*!< Product Revision */
uint32_t ProdSN; /*!< Product Serial Number */
uint8_t month; /*!< Reserved1 */
uint32_t year; /*!< Manufacturing Date */
} SD_CID;
/**
* @brief SD Card Status
*/
typedef struct
{
uint8_t DAT_BUS_WIDTH;
uint8_t SECURED_MODE;
uint16_t SD_CARD_TYPE;
uint32_t SIZE_OF_PROTECTED_AREA;
uint8_t SPEED_CLASS;
uint8_t PERFORMANCE_MOVE;
uint8_t AU_SIZE;
uint16_t ERASE_SIZE;
uint8_t ERASE_TIMEOUT;
uint8_t ERASE_OFFSET;
} SD_CardStatus;
/*******************************************************************************
* Definitions
******************************************************************************/
/*! @brief OCR register in SD card */
enum _sd_ocr_flag {
SD_OcrHostCapacitySupportFlag = (1U << 30U), /*!< Card capacity status */
SD_OcrCardCapacitySupportFlag = SD_OcrHostCapacitySupportFlag, /*!< Card capacity status */
SD_OcrSwitch18RequestFlag = (1U << 24U), /*!< Switch to 1.8V request */
SD_OcrSwitch18AcceptFlag = SD_OcrSwitch18RequestFlag, /*!< Switch to 1.8V accepted */
SD_OcrVdd27_28Flag = (1U << 15U), /*!< VDD 2.7-2.8 */
SD_OcrVdd28_29Flag = (1U << 16U), /*!< VDD 2.8-2.9 */
SD_OcrVdd29_30Flag = (1U << 17U), /*!< VDD 2.9-3.0 */
SD_OcrVdd30_31Flag = (1U << 18U), /*!< VDD 2.9-3.0 */
SD_OcrVdd31_32Flag = (1U << 19U), /*!< VDD 3.0-3.1 */
SD_OcrVdd32_33Flag = (1U << 20U), /*!< VDD 3.1-3.2 */
SD_OcrVdd33_34Flag = (1U << 21U), /*!< VDD 3.2-3.3 */
SD_OcrVdd34_35Flag = (1U << 22U), /*!< VDD 3.3-3.4 */
SD_OcrVdd35_36Flag = (1U << 23U), /*!< VDD 3.4-3.5 */
};
/*! @brief SD card flags */
enum _sd_card_flag {
SD_SupportHighCapacityFlag = (1U << 1U), /*!< Support high capacity */
SD_Support4BitWidthFlag = (1U << 2U), /*!< Support 4-bit data width */
SD_SupportSdhcFlag = (1U << 3U), /*!< Card is SDHC */
SD_SupportSdxcFlag = (1U << 4U), /*!< Card is SDXC */
SD_SupportVoltage180v = (1U << 5U), /*!< card support 1.8v voltage*/
SD_SupportSetBlockCountCmd = (1U << 6U), /*!< card support cmd23 flag*/
SD_SupportSpeedClassControlCmd = (1U << 7U), /*!< card support speed class control flag */
};
/*! @brief SD card CID register */
typedef struct _sd_cid {
uint8_t manufacturerID; /*!< Manufacturer ID [127:120] */
uint16_t applicationID; /*!< OEM/Application ID [119:104] */
uint8_t productName[5]; /*!< Product name [103:64] */
uint8_t productVersion; /*!< Product revision [63:56] */
uint32_t productSerialNumber; /*!< Product serial number [55:24] */
uint16_t manufacturerData; /*!< Manufacturing date [19:8] */
} sd_cid_t;
/*! @brief SD card SCR register flags */
enum _sd_scr_flag {
SD_ScrDataStatusAfterErase = (1U << 0U), /*!< Data status after erases [55:55] */
SD_ScrSdSpecification3 = (1U << 1U), /*!< Specification version 3.00 or higher [47:47]*/
};
/*! @brief SD card CSD register */
typedef struct _sd_csd {
uint8_t csdStructure; /*!< CSD structure [127:126] */
uint8_t dataReadAccessTime1; /*!< Data read access-time-1 [119:112] */
uint8_t dataReadAccessTime2; /*!< Data read access-time-2 in clock cycles (NSAC*100) [111:104] */
uint8_t transferSpeed; /*!< Maximum data transfer rate [103:96] */
uint16_t cardCommandClass; /*!< Card command classes [95:84] */
uint8_t readBlockLength; /*!< Maximum read data block length [83:80] */
uint16_t flags; /*!< Flags in _sd_csd_flag */
uint32_t deviceSize; /*!< Device size [73:62] */
/* Following fields from 'readCurrentVddMin' to 'deviceSizeMultiplier' exist in CSD version 1 */
uint8_t readCurrentVddMin; /*!< Maximum read current at VDD min [61:59] */
uint8_t readCurrentVddMax; /*!< Maximum read current at VDD max [58:56] */
uint8_t writeCurrentVddMin; /*!< Maximum write current at VDD min [55:53] */
uint8_t writeCurrentVddMax; /*!< Maximum write current at VDD max [52:50] */
uint8_t deviceSizeMultiplier; /*!< Device size multiplier [49:47] */
uint8_t eraseSectorSize; /*!< Erase sector size [45:39] */
uint8_t writeProtectGroupSize; /*!< Write protect group size [38:32] */
uint8_t writeSpeedFactor; /*!< Write speed factor [28:26] */
uint8_t writeBlockLength; /*!< Maximum write data block length [25:22] */
uint8_t fileFormat; /*!< File format [11:10] */
} sd_csd_t;
/*! @brief SD card SCR register */
typedef struct _sd_scr {
uint8_t scrStructure; /*!< SCR Structure [63:60] */
uint8_t sdSpecification; /*!< SD memory card specification version [59:56] */
uint16_t flags; /*!< SCR flags in _sd_scr_flag */
uint8_t sdSecurity; /*!< Security specification supported [54:52] */
uint8_t sdBusWidths; /*!< Data bus widths supported [51:48] */
uint8_t extendedSecurity; /*!< Extended security support [46:43] */
uint8_t commandSupport; /*!< Command support bits [33:32] 33-support CMD23, 32-support cmd20*/
uint32_t reservedForManufacturer; /*!< reserved for manufacturer usage [31:0] */
} sd_scr_t;
/*! @brief SD Status register */
typedef struct _sd_ssr {
uint8_t dataBusWidth; /*!< Data Bus Width [511:510] 0b00--1line, 0b10--4line*/
uint8_t secureMode; /*!< Secure Mode [509] */
uint16_t SDCardType; /*!< SD Card Type [495:480] */
uint32_t sizeOfProtectedArea; /*!< Size Of Protected area [479:448] */
uint8_t speedClass; /*!< speed classes [447:440] */
uint8_t performanceMove; /*!< performance move [439:432] */
uint8_t AUSize; /*!< AU size [431:428] */
uint16_t eraseSize; /*!< erase size [423:408] */
uint8_t eraseTimeOut; /*!< erase timeout [407:402] */
uint8_t eraseOffset; /*!< erase offset [401:400] */
uint8_t UHSSpeedGrade; /*!< UHS speed grade [399:396] */
uint8_t UHSAUSize; /*!< UHS AU size [395:392] */
} sd_ssr_t;
/*!
* @brief SD card state
*
* Define the card structure including the necessary fields to identify and describe the card.
*/
typedef struct _sd_card {
uint32_t relativeAddress; /*!< Relative address of the card */
uint32_t version; /*!< Card version */
uint32_t flags; /*!< Flags in _sd_card_flag */
uint32_t rawCid[4U]; /*!< Raw CID content */
uint32_t rawCsd[4U]; /*!< Raw CSD content */
uint32_t rawScr[2U]; /*!< Raw CSD content */
uint32_t rawSsr[16U]; /*!< Raw CSD content */
uint32_t ocr; /*!< Raw OCR content */
sd_cid_t cid; /*!< CID */
sd_csd_t csd; /*!< CSD */
sd_scr_t scr; /*!< SCR */
sd_ssr_t ssr; /*!< SCR */
uint32_t blockCount; /*!< Card total block number */
uint32_t blockSize; /*!< Card block size */
} sd_card_t;
/**
* @brief SDIO Commands Index
*/
#define SD_CMD_GO_IDLE_STATE ((uint8_t)0)
#define SD_CMD_SEND_OP_COND ((uint8_t)1)
#define SD_CMD_ALL_SEND_CID ((uint8_t)2)
#define SD_CMD_SET_REL_ADDR ((uint8_t)3) /*!< SDIO_SEND_REL_ADDR for SD Card */
#define SD_CMD_SET_DSR ((uint8_t)4)
#define SD_CMD_SDIO_SEN_OP_COND ((uint8_t)5)
#define SD_CMD_HS_SWITCH ((uint8_t)6)
#define SD_CMD_SEL_DESEL_CARD ((uint8_t)7)
#define SD_CMD_HS_SEND_EXT_CSD ((uint8_t)8)
#define SDIO_SEND_IF_COND ((uint8_t)8)
#define SD_CMD_SEND_CSD ((uint8_t)9)
#define SD_CMD_SEND_CID ((uint8_t)10)
#define SD_CMD_READ_DAT_UNTIL_STOP ((uint8_t)11) /*!< SD Card doesn't support it */
#define SD_CMD_STOP_TRANSMISSION ((uint8_t)12)
#define SD_CMD_SEND_STATUS ((uint8_t)13)
#define SD_CMD_HS_BUSTEST_READ ((uint8_t)14)
#define SD_CMD_GO_INACTIVE_STATE ((uint8_t)15)
#define SD_CMD_SET_BLOCKLEN ((uint8_t)16)
#define SD_CMD_READ_SINGLE_BLOCK ((uint8_t)17)
#define SD_CMD_READ_MULT_BLOCK ((uint8_t)18)
#define SD_CMD_HS_BUSTEST_WRITE ((uint8_t)19)
#define SD_CMD_WRITE_DAT_UNTIL_STOP ((uint8_t)20) /*!< SD Card doesn't support it */
#define SD_CMD_SET_BLOCK_COUNT ((uint8_t)23) /*!< SD Card doesn't support it */
#define SD_CMD_WRITE_SINGLE_BLOCK ((uint8_t)24)
#define SD_CMD_WRITE_MULT_BLOCK ((uint8_t)25)
#define SD_CMD_PROG_CID ((uint8_t)26) /*!< reserved for manufacturers */
#define SD_CMD_PROG_CSD ((uint8_t)27)
#define SD_CMD_SET_WRITE_PROT ((uint8_t)28)
#define SD_CMD_CLR_WRITE_PROT ((uint8_t)29)
#define SD_CMD_SEND_WRITE_PROT ((uint8_t)30)
#define SD_CMD_SD_ERASE_GRP_START ((uint8_t)32) /*!< To set the address of the first write
block to be erased. (For SD card only) */
#define SD_CMD_SD_ERASE_GRP_END ((uint8_t)33) /*!< To set the address of the last write block of the
continuous range to be erased. (For SD card only) */
#define SD_CMD_ERASE_GRP_START ((uint8_t)35) /*!< To set the address of the first write block to be erased.
(For MMC card only spec 3.31) */
#define SD_CMD_ERASE_GRP_END ((uint8_t)36) /*!< To set the address of the last write block of the
continuous range to be erased. (For MMC card only spec 3.31) */
#define SD_CMD_ERASE ((uint8_t)38)
#define SD_CMD_FAST_IO ((uint8_t)39) /*!< SD Card doesn't support it */
#define SD_CMD_GO_IRQ_STATE ((uint8_t)40) /*!< SD Card doesn't support it */
#define SD_CMD_LOCK_UNLOCK ((uint8_t)42)
#define SD_CMD_APP_CMD ((uint8_t)55)
#define SD_CMD_GEN_CMD ((uint8_t)56)
#define SD_CMD_NO_CMD ((uint8_t)64)
/**
* @brief Following commands are SD Card Specific commands.
* SDIO_APP_CMD :CMD55 should be sent before sending these commands.
*/
#define SD_CMD_APP_SD_SET_BUSWIDTH ((uint8_t)6) /*!< For SD Card only */
#define SD_CMD_SD_APP_STAUS ((uint8_t)13) /*!< For SD Card only */
#define SD_CMD_SD_APP_SEND_NUM_WRITE_BLOCKS ((uint8_t)22) /*!< For SD Card only */
#define SD_CMD_SD_APP_OP_COND ((uint8_t)41) /*!< For SD Card only */
#define SD_CMD_SD_APP_SET_CLR_CARD_DETECT ((uint8_t)42) /*!< For SD Card only */
#define SD_CMD_SD_APP_SEND_SCR ((uint8_t)51) /*!< For SD Card only */
#define SD_CMD_SDIO_RW_DIRECT ((uint8_t)52) /*!< For SD I/O Card only */
#define SD_CMD_SDIO_RW_EXTENDED ((uint8_t)53) /*!< For SD I/O Card only */
/**
* @brief Following commands are SD Card Specific security commands.
* SDIO_APP_CMD should be sent before sending these commands.
*/
#define SD_CMD_SD_APP_GET_MKB ((uint8_t)43) /*!< For SD Card only */
#define SD_CMD_SD_APP_GET_MID ((uint8_t)44) /*!< For SD Card only */
#define SD_CMD_SD_APP_SET_CER_RN1 ((uint8_t)45) /*!< For SD Card only */
#define SD_CMD_SD_APP_GET_CER_RN2 ((uint8_t)46) /*!< For SD Card only */
#define SD_CMD_SD_APP_SET_CER_RES2 ((uint8_t)47) /*!< For SD Card only */
#define SD_CMD_SD_APP_GET_CER_RES1 ((uint8_t)48) /*!< For SD Card only */
#define SD_CMD_SD_APP_SECURE_READ_MULTIPLE_BLOCK ((uint8_t)18) /*!< For SD Card only */
#define SD_CMD_SD_APP_SECURE_WRITE_MULTIPLE_BLOCK ((uint8_t)25) /*!< For SD Card only */
#define SD_CMD_SD_APP_SECURE_ERASE ((uint8_t)38) /*!< For SD Card only */
#define SD_CMD_SD_APP_CHANGE_SECURE_AREA ((uint8_t)49) /*!< For SD Card only */
#define SD_CMD_SD_APP_SECURE_WRITE_MKB ((uint8_t)48) /*!< For SD Card only */
/**
* @brief Mask for errors Card Status R1 (CSR Register)
*/
#define SD_CSR_ADDR_OUT_OF_RANGE ((uint32_t)0x80000000)
#define SD_CSR_ADDR_MISALIGNED ((uint32_t)0x40000000)
#define SD_CSR_BLOCK_LEN_ERR ((uint32_t)0x20000000)
#define SD_CSR_ERASE_SEQ_ERR ((uint32_t)0x10000000)
#define SD_CSR_BAD_ERASE_PARAM ((uint32_t)0x08000000)
#define SD_CSR_WRITE_PROT_VIOLATION ((uint32_t)0x04000000)
#define SD_CSR_LOCK_UNLOCK_FAILED ((uint32_t)0x01000000)
#define SD_CSR_COM_CRC_FAILED ((uint32_t)0x00800000)
#define SD_CSR_ILLEGAL_CMD ((uint32_t)0x00400000)
#define SD_CSR_CARD_ECC_FAILED ((uint32_t)0x00200000)
#define SD_CSR_CC_ERROR ((uint32_t)0x00100000)
#define SD_CSR_GENERAL_UNKNOWN_ERROR ((uint32_t)0x00080000)
#define SD_CSR_STREAM_READ_UNDERRUN ((uint32_t)0x00040000)
#define SD_CSR_STREAM_WRITE_OVERRUN ((uint32_t)0x00020000)
#define SD_CSR_CID_CSD_OVERWRIETE ((uint32_t)0x00010000)
#define SD_CSR_WP_ERASE_SKIP ((uint32_t)0x00008000)
#define SD_CSR_CARD_ECC_DISABLED ((uint32_t)0x00004000)
#define SD_CSR_ERASE_RESET ((uint32_t)0x00002000)
#define SD_CSR_AKE_SEQ_ERROR ((uint32_t)0x00000008)
#define SD_CSR_ERRORBITS ((uint32_t)0xFDFFE008)
#define SD_MAX_VOLT_TRIAL ((uint32_t)0x0000FFFF)
#define SD_ALLZERO ((uint32_t)0x00000000)
#define SD_WIDE_BUS_SUPPORT ((uint32_t)0x00040000)
#define SD_SINGLE_BUS_SUPPORT ((uint32_t)0x00010000)
#define SD_CARD_LOCKED ((uint32_t)0x02000000)
#define SD_0TO7BITS ((uint32_t)0x000000FF)
#define SD_8TO15BITS ((uint32_t)0x0000FF00)
#define SD_16TO23BITS ((uint32_t)0x00FF0000)
#define SD_24TO31BITS ((uint32_t)0xFF000000)
#define SD_MAX_DATA_LENGTH ((uint32_t)0x01FFFFFF)
/**
* @brief Masks for R7 Response
*/
#define SD_VOLTAGE_WINDOW_SD ((uint32_t)0x00100000)
#define SD_HIGH_CAPACITY ((uint32_t)0x40000000)
#define SD_STD_CAPACITY ((uint32_t)0x00000000)
#define SD_CHECK_PATTERN ((uint32_t)0x000001AA)
/**
* @brief Supported SD Memory Cards
*/
#define SDIO_STD_CAPACITY_SD_CARD_V1_1 ((uint32_t)0x00000000)
#define SDIO_STD_CAPACITY_SD_CARD_V2_0 ((uint32_t)0x00000001)
#define SDIO_HIGH_CAPACITY_SD_CARD ((uint32_t)0x00000002)
#define SDIO_MULTIMEDIA_CARD ((uint32_t)0x00000003)
#define SDIO_SECURE_DIGITAL_IO_CARD ((uint32_t)0x00000004)
#define SDIO_HIGH_SPEED_MULTIMEDIA_CARD ((uint32_t)0x00000005)
#define SDIO_SECURE_DIGITAL_IO_COMBO_CARD ((uint32_t)0x00000006)
#define SDIO_HIGH_CAPACITY_MMC_CARD ((uint32_t)0x00000007)
/*! @brief SD group number */
typedef enum _sd_group_num {
SDH_GroupTimingMode = 0U, /*!< acess mode group*/
SDH_GroupCommandSystem = 1U, /*!< command system group*/
SDH_GroupDriverStrength = 2U, /*!< driver strength group*/
SDH_GroupCurrentLimit = 3U, /*!< current limit group*/
} sd_group_num;
/*! @brief SD card timing mode flags */
typedef enum _sd_timing_mode {
SDH_TimingSDR12DefaultMode = 0U, /*!< Identification mode & SDR12 */
SDH_TimingSDR25HighSpeedMode = 1U, /*!< High speed mode & SDR25 */
SDH_TimingSDR50Mode = 2U, /*!< SDR50 mode*/
SDH_TimingSDR104Mode = 3U, /*!< SDR104 mode */
SDH_TimingDDR50Mode = 4U, /*!< DDR50 mode */
} sd_timing_mode_t;
/*! @brief SD card specification version number */
enum _sd_specification_version {
SD_SpecificationVersion1_0 = (1U << 0U), /*!< SD card version 1.0-1.01 */
SD_SpecificationVersion1_1 = (1U << 1U), /*!< SD card version 1.10 */
SD_SpecificationVersion2_0 = (1U << 2U), /*!< SD card version 2.00 */
SD_SpecificationVersion3_0 = (1U << 3U), /*!< SD card version 3.0 */
};
/*! @brief SD card switch mode */
typedef enum _sd_switch_mode {
SDH_SwitchCheck = 0U, /*!< SD switch mode 0: check function */
SDH_SwitchSet = 1U, /*!< SD switch mode 1: set function */
} sd_switch_mode_t;
// #define SDH_DEBUG
#ifdef SDH_DEBUG
#define SDH_MSG(a, ...) printf(a, ##__VA_ARGS__)
#else
#define SDH_MSG(a, ...)
#endif
/*
bus_wide shoud be SDH_DATA_BUS_WIDTH_1BIT/SDH_DATA_BUS_WIDTH_4BITS/SDH_DATA_BUS_WIDTH_8BITS
*/
status_t SDH_ClockSet(uint32_t clockInit, uint32_t clockSrc, uint32_t clockTransfer);
status_t SDH_Init(uint32_t bus_wide, sd_card_t *pOutCardInfo);
status_t SD_Erase(uint32_t startaddr, uint32_t endaddr);
status_t SDH_ReadMultiBlocks(uint8_t *readbuff, uint32_t ReadAddr, uint16_t BlockSize, uint32_t NumberOfBlocks);
status_t SDH_WriteMultiBlocks(uint8_t *writebuff, uint32_t WriteAddr, uint16_t BlockSize, uint32_t NumberOfBlocks);
#endif
#endif
sdh_sdcard.c
/**
* @file sdh_sdcard.c
* @brief
*
* Copyright (c) 2021 Bouffalolab team
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership. The
* ASF licenses this file to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance with the
* License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*
*/
#if defined(BL616) || defined(BL808) || defined(BL628) || defined(BL606P)
#include "sdh_sdcard.h"
#include "bflb_mtimer.h"
#include "bflb_l1c.h"
#define SDIO_CMDTIMEOUT_MS (1000)
#define SDIO_SDCARD_INT_MODE (0) /* Interrupt mode, which can be paired with the OS */
/* Private variables ---------------------------------------------------------*/
static uint32_t sdhClockInit = 100ul;
static uint32_t sdhClockSrc = 100ul;
static uint32_t sdhClockTransfer = 100ul;
static sd_card_t *pSDCardInfo = NULL;
static SDH_Cfg_Type SDH_Cfg_Type_Instance;
#if SDIO_SDCARD_INT_MODE
static volatile SD_Error SDH_DataWaitStatus = SD_WAITING;
static volatile SD_Error SDH_CMDWaitStatus = SD_WAITING;
static SDH_Trans_Callback_Cfg_Type SDH_Trans_Callback_Cfg_TypeInstance;
static SDH_Handle_Cfg_Type SDH_Handle_Cfg_TypeInstance;
#endif
static SDH_DMA_Cfg_Type SDH_DMA_Cfg_TypeInstance;
/*causion: ADMA related variables must on OCRAM or shared ram*/
static __attribute__((aligned(32), section(".noncacheable"))) SDH_ADMA2_Desc_Type adma2Entries[16];
/* Private function prototypes -----------------------------------------------*/
static void SD_DecodeCid(sd_card_t *card, uint32_t *rawCid);
static void SD_DecodeCsd(sd_card_t *card, uint32_t *rawCsd);
static void SD_DecodeScr(sd_card_t *card, uint32_t *rawScr);
#if SDIO_SDCARD_INT_MODE
static void SDH_INT_Init(void);
#endif
static status_t SDH_SendCardCommand(SDH_CMD_Cfg_Type *cmd);
static void SDH_HostInit(void);
static status_t SDH_GoIdle(void);
static status_t SD_SendApplicationCmd(uint32_t relativeAddress);
static status_t SD_SendInterfaceCondition(void);
static status_t SD_ApplicationSendOperationCondition(sd_card_t *card, uint32_t argument);
static status_t SD_AllSendCid(sd_card_t *card);
static status_t SD_SendRca(sd_card_t *card);
static status_t SD_SendCsd(sd_card_t *card);
static status_t SD_SelectCard(sd_card_t *card, BL_Fun_Type NewState);
static status_t SD_SendScr(sd_card_t *card);
static status_t SD_SendSsr(sd_card_t *card);
static status_t SD_SetDataBusWidth(sd_card_t *card, SDH_Data_Bus_Width_Type width);
static status_t SD_SwitchFunction(uint32_t mode, uint32_t group, uint32_t number, uint32_t status[16]);
static status_t SD_SelectFunction(uint32_t group, uint32_t function);
static status_t SD_SetBlockSize(uint32_t blockSize);
static status_t SDH_SDCardInit(uint32_t bus_wide, sd_card_t *card);
static status_t WaitInProgramming(void);
static status_t IsCardProgramming(uint8_t *pstatus);
static status_t SDH_CardTransferNonBlocking(SDH_DMA_Cfg_Type *dmaCfg, SDH_Trans_Cfg_Type *transfer);
static void SD_DecodeCid(sd_card_t *card, uint32_t *rawCid)
{
sd_cid_t *cid;
cid = &(card->cid);
cid->manufacturerID = (uint8_t)((rawCid[3U] & 0xFF0000U) >> 16U);
cid->applicationID = (uint16_t)((rawCid[3U] & 0xFFFFU) >> 0U);
cid->productName[0U] = (uint8_t)((rawCid[1U] & 0xFF000000U) >> 24);
cid->productName[1U] = (uint8_t)((rawCid[2U] & 0xFF) >> 0U);
cid->productName[2U] = (uint8_t)((rawCid[2U] & 0xFF00U) >> 8U);
cid->productName[3U] = (uint8_t)((rawCid[2U] & 0xFF0000U) >> 16U);
cid->productName[4U] = (uint8_t)((rawCid[2U] & 0xFF000000U) >> 24U);
cid->productVersion = (uint8_t)((rawCid[1U] & 0xFF0000U) >> 16U);
cid->productSerialNumber = (uint32_t)((rawCid[1U] & 0xFFFFU) << 16U);
cid->productSerialNumber |= (uint32_t)((rawCid[0U] & 0xFFFF0000U) >> 16U);
cid->manufacturerData = (uint16_t)((rawCid[0U] & 0xFFFU) >> 0U);
}
static void SD_DecodeCsd(sd_card_t *card, uint32_t *rawCsd)
{
sd_csd_t *csd;
csd = &(card->csd);
csd->csdStructure = (uint8_t)((rawCsd[3U] & 0xC00000U) >> 22U);
csd->dataReadAccessTime1 = (uint8_t)((rawCsd[3U] & 0xFF00U) >> 8U);
csd->dataReadAccessTime2 = (uint8_t)((rawCsd[3U] & 0xFFU) >> 0U);
csd->transferSpeed = (uint8_t)((rawCsd[2U] & 0xFF000000U) >> 24);
csd->cardCommandClass = (uint16_t)((rawCsd[2U] & 0xFFF000U) >> 12U);
csd->readBlockLength = (uint8_t)((rawCsd[2U] & 0xF00U) >> 8U);
switch (csd->csdStructure) {
/*csd version 1.1*/
case 0:
csd->deviceSize = (uint32_t)((rawCsd[2U] & 0x3U) << 10U);
csd->deviceSize |= (uint32_t)((rawCsd[1U] & 0xFFC00000U) >> 22U);
csd->deviceSizeMultiplier = (uint8_t)((rawCsd[1U] & 0x380U) >> 7U);
/* Get card total block count and block size. */
card->blockCount = ((csd->deviceSize + 1U) << (csd->deviceSizeMultiplier + 2U));
card->blockSize = (1U << (csd->readBlockLength));
if (card->blockSize != SDH_DEFAULT_BLOCK_SIZE) {
card->blockCount = (card->blockCount * card->blockSize);
card->blockSize = SDH_DEFAULT_BLOCK_SIZE;
card->blockCount = (card->blockCount / card->blockSize);
}
break;
/*csd version 2.0*/
case 1:
card->blockSize = SDH_DEFAULT_BLOCK_SIZE;
csd->deviceSize = (uint32_t)((rawCsd[1U] & 0x3FFFFF00U) >> 8U);
if (csd->deviceSize >= 0xFFFFU) {
card->flags |= SD_SupportSdxcFlag;
}
card->blockCount = ((csd->deviceSize + 1U) * 1024U);
break;
default:
break;
}
}
static void SD_DecodeScr(sd_card_t *card, uint32_t *rawScr)
{
sd_scr_t *scr;
scr = &(card->scr);
scr->scrStructure = (uint8_t)((rawScr[1U] & 0xF0000000U) >> 28U);
scr->sdSpecification = (uint8_t)((rawScr[1U] & 0xF000000U) >> 24U);
if ((uint8_t)((rawScr[1U] & 0x800000U) >> 23U)) {
scr->flags |= SD_ScrDataStatusAfterErase;
}
scr->sdSecurity = (uint8_t)((rawScr[1U] & 0x700000U) >> 20U);
scr->sdBusWidths = (uint8_t)((rawScr[1U] & 0xF0000U) >> 16U);
if ((uint8_t)((rawScr[0U] & 0x8000U) >> 15U)) {
scr->flags |= SD_ScrSdSpecification3;
}
scr->extendedSecurity = (uint8_t)((rawScr[1U] & 0x7800U) >> 10U);
scr->commandSupport = (uint8_t)(rawScr[1U] & 0x3U);
scr->reservedForManufacturer = rawScr[0U];
/* Get specification version. */
switch (scr->sdSpecification) {
case 0U:
card->version = SD_SpecificationVersion1_0;
break;
case 1U:
card->version = SD_SpecificationVersion1_1;
break;
case 2U:
card->version = SD_SpecificationVersion2_0;
if (card->scr.flags & SD_ScrSdSpecification3) {
card->version = SD_SpecificationVersion3_0;
}
break;
default:
break;
}
if (card->scr.sdBusWidths & 0x4U) {
card->flags |= SD_Support4BitWidthFlag;
}
/* speed class control cmd */
if (card->scr.commandSupport & 0x01U) {
card->flags |= SD_SupportSpeedClassControlCmd;
}
/* set block count cmd */
if (card->scr.commandSupport & 0x02U) {
card->flags |= SD_SupportSetBlockCountCmd;
}
}
#if SDIO_SDCARD_INT_MODE
/*!< SDH transfer complete callback */
void SDH_DataTransferFinished_CallBack(SDH_Handle_Cfg_Type *handle, SDH_Stat_Type status, void *userData)
{
//bflb_platform_printf("Interrupt occurs! intFlag=0x%02x,\r\n",handle->intFlag);
if (status != SDH_STAT_SUCCESS) {
SDH_DataWaitStatus = SD_DataCfg_ERROR;
} else {
SDH_DataWaitStatus = SD_OK;
}
}
/*!< SDH transfer complete callback */
void SDH_CMDTransferFinished_CallBack(SDH_Handle_Cfg_Type *handle, SDH_Stat_Type status, void *userData)
{
//bflb_platform_printf("Interrupt occurs! intFlag=0x%02x,\r\n",handle->intFlag);
if (status != SDH_STAT_SUCCESS) {
SDH_CMDWaitStatus = SD_CMD_ERROR;
} else {
SDH_CMDWaitStatus = SD_OK;
}
}
extern void SDH_MMC1_IRQHandler(void);
static void sdh_isr(int irq, void *arg)
{
SDH_MMC1_IRQHandler();
}
/****************************************************************************/ /**
* @brief SDH INT init
*
* @param None
*
* @return None
*
*******************************************************************************/
static void SDH_INT_Init(void)
{
bflb_irq_attach(33, sdh_isr, NULL);
bflb_irq_enable(33);
SDH_EnableIntStatus(SDH_INT_ALL);
SDH_DisableIntSource(SDH_INT_ALL);
SDH_Trans_Callback_Cfg_TypeInstance.SDH_CallBack_TransferFinished = SDH_DataTransferFinished_CallBack;
SDH_Trans_Callback_Cfg_TypeInstance.SDH_CMDCallBack_TransferFinished = SDH_CMDTransferFinished_CallBack;
SDH_InstallHandleCallback(&SDH_Handle_Cfg_TypeInstance, &SDH_Trans_Callback_Cfg_TypeInstance, NULL);
}
#endif
static status_t SDH_SendCardCommand(SDH_CMD_Cfg_Type *cmd)
{
status_t errorstatus = Status_Success;
SD_Error sd_status;
uint32_t time_node;
SDH_ClearIntStatus(SDH_INT_CMD_COMPLETED | SDH_INT_CMD_ERRORS);
SDH_SendCommand(cmd);
time_node = (uint32_t)bflb_mtimer_get_time_ms();
#if SDIO_SDCARD_INT_MODE
SDH_CMDWaitStatus = SD_WAITING;
SDH_EnableIntSource(SDH_INT_CMD_COMPLETED | SDH_INT_CMD_ERRORS);
/*wait for Xfer status. might pending here in multi-task OS*/
while (SDH_CMDWaitStatus == SD_WAITING) {
if ((uint32_t)bflb_mtimer_get_time_ms() - time_node > SDIO_CMDTIMEOUT_MS) {
SDH_MSG("SDH send CMD%ld timeout: %ld ms\r\n", cmd->index, (uint32_t)bflb_mtimer_get_time_ms() - time_node);
SDH_DisableIntSource(SDH_INT_CMD_COMPLETED | SDH_INT_CMD_ERRORS);
return Status_Timeout;
}
BL_DRV_DUMMY;
BL_DRV_DUMMY;
}
sd_status = SDH_CMDWaitStatus;
SDH_DisableIntSource(SDH_INT_CMD_COMPLETED | SDH_INT_CMD_ERRORS);
#else
uint32_t intFlag;
while (1) {
intFlag = SDH_GetIntStatus();
if (intFlag & SDH_INT_CMD_ERRORS) {
sd_status = SD_CMD_ERROR;
break;
} else if (intFlag & SDH_INT_CMD_COMPLETED) {
sd_status = SD_OK;
break;
} else if ((uint32_t)bflb_mtimer_get_time_ms() - time_node > SDIO_CMDTIMEOUT_MS) {
SDH_MSG("SDH send CMD%ld timeout: %ld ms\r\n", cmd->index, (uint32_t)bflb_mtimer_get_time_ms() - time_node);
return Status_Timeout;
}
BL_DRV_DUMMY;
BL_DRV_DUMMY;
}
SDH_ClearIntStatus(intFlag & (SDH_INT_CMD_ERRORS | SDH_INT_CMD_COMPLETED));
#endif
// SDH_MSG("SDH send CMD%ld used time : %d\r\n", cmd->index, (uint32_t)bflb_mtimer_get_time_ms() - time_node);
if (sd_status != SD_OK) {
SDH_MSG("SDH send CMD%ld error\r\n", cmd->index);
errorstatus = Status_SDH_CmdResponseError;
} else {
SDH_GetCmdResp(cmd);
SDH_MSG("SDH send CMD%ld success\r\n", cmd->index);
}
return errorstatus;
}
static void SDH_HostInit(void)
{
GLB_Set_SDH_CLK(ENABLE, GLB_SDH_CLK_WIFIPLL_96M, 7);
/* initialise SDH controller*/
SDH_Cfg_Type_Instance.vlot18Enable = DISABLE;
SDH_Cfg_Type_Instance.highSpeed = ENABLE;
SDH_Cfg_Type_Instance.dataWidth = SDH_DATA_BUS_WIDTH_1BIT;
SDH_Cfg_Type_Instance.volt = SDH_VOLTAGE_3P3V;
SDH_Cfg_Type_Instance.srcClock = sdhClockSrc;
SDH_Cfg_Type_Instance.busClock = sdhClockInit;
SDH_Ctrl_Init(&SDH_Cfg_Type_Instance);
/*setup timeout counter*/
SDH_Set_Timeout(0x0e);
/*power on host controller*/
SDH_Powon();
}
/*
* GO_IDLE_STATE, send card to reset state
*/
static status_t SDH_GoIdle(void)
{
status_t errorstatus = Status_Success;
SDH_CMD_Cfg_Type SDH_CMD_Cfg_TypeInstance;
/*CMD0: GO_IDLE_STATE, send card to reset state*/
SDH_CMD_Cfg_TypeInstance.index = SD_CMD_GO_IDLE_STATE;
SDH_CMD_Cfg_TypeInstance.argument = 0;
SDH_CMD_Cfg_TypeInstance.type = SDH_CMD_NORMAL;
SDH_CMD_Cfg_TypeInstance.respType = SDH_RESP_NONE;
SDH_CMD_Cfg_TypeInstance.flag = SDH_TRANS_FLAG_NONE;
errorstatus = SDH_SendCardCommand(&SDH_CMD_Cfg_TypeInstance);
return errorstatus;
}
static status_t SD_SendApplicationCmd(uint32_t relativeAddress)
{
status_t errorstatus = Status_Success;
SDH_CMD_Cfg_Type SDH_CMD_Cfg_TypeInstance;
/* send CMD55 */
SDH_CMD_Cfg_TypeInstance.index = SD_CMD_APP_CMD;
SDH_CMD_Cfg_TypeInstance.argument = relativeAddress;
SDH_CMD_Cfg_TypeInstance.type = SDH_CMD_NORMAL;
SDH_CMD_Cfg_TypeInstance.respType = SDH_RESP_R1;
SDH_CMD_Cfg_TypeInstance.flag = SDH_TRANS_FLAG_NONE;
errorstatus = SDH_SendCardCommand(&SDH_CMD_Cfg_TypeInstance);
if (errorstatus != Status_Success) {
return Status_SDH_CmdResponseError;
} else if (SDH_CMD_Cfg_TypeInstance.response[0] & SD_CSR_ERRORBITS) {
return Status_SDH_CmdResponseError;
}
return errorstatus;
}
static status_t SD_SendInterfaceCondition(void)
{
status_t errorstatus = Status_Success;
SDH_CMD_Cfg_Type SDH_CMD_Cfg_TypeInstance;
/* CMD8: SEND_IF_COND */
SDH_CMD_Cfg_TypeInstance.index = SD_CMD_HS_SEND_EXT_CSD;
SDH_CMD_Cfg_TypeInstance.argument = SD_CHECK_PATTERN;
SDH_CMD_Cfg_TypeInstance.type = SDH_CMD_NORMAL;
SDH_CMD_Cfg_TypeInstance.respType = SDH_RESP_R7;
SDH_CMD_Cfg_TypeInstance.flag = SDH_TRANS_FLAG_NONE;
errorstatus = SDH_SendCardCommand(&SDH_CMD_Cfg_TypeInstance);
if (errorstatus != Status_Success) {
return Status_SDH_CmdResponseError;
}
SDH_MSG("Response to CMD8 is: 0x%02x.\r\n", SDH_CMD_Cfg_TypeInstance.response[0]);
if ((SDH_CMD_Cfg_TypeInstance.response[0U] & 0xFFU) != (SD_CHECK_PATTERN & 0xff)) {
return Status_SDH_CardNotSupport;
}
return errorstatus;
}
static status_t SD_ApplicationSendOperationCondition(sd_card_t *card, uint32_t argument)
{
status_t errorstatus = Status_Success;
uint32_t response = 0, count = 0, validvoltage = 0;
SDH_CMD_Cfg_Type SDH_CMD_Cfg_TypeInstance;
do {
if (Status_Success != (errorstatus = SD_SendApplicationCmd(0))) {
return errorstatus;
}
/*ACMD41*/
SDH_CMD_Cfg_TypeInstance.index = SD_CMD_SD_APP_OP_COND;
SDH_CMD_Cfg_TypeInstance.argument = argument;
SDH_CMD_Cfg_TypeInstance.type = SDH_CMD_NORMAL;
SDH_CMD_Cfg_TypeInstance.respType = SDH_RESP_R3;
SDH_CMD_Cfg_TypeInstance.flag = SDH_TRANS_FLAG_NONE;
errorstatus = SDH_SendCardCommand(&SDH_CMD_Cfg_TypeInstance);
if (errorstatus != Status_Success) {
return Status_SDH_CmdResponseError;
}
response = SDH_CMD_Cfg_TypeInstance.response[0];
validvoltage = (((response >> 31) == 1) ? 1 : 0);
count++;
} while ((!validvoltage) && (count < SD_MAX_VOLT_TRIAL));
if (count == SD_MAX_VOLT_TRIAL) {
return Status_Timeout;
} else {
card->ocr = response;
if (response &= SD_OcrHostCapacitySupportFlag) {
/* change from sdsc to sdhc */
card->flags |= SD_SupportHighCapacityFlag;
}
}
return errorstatus;
}
static status_t SD_AllSendCid(sd_card_t *card)
{
status_t errorstatus = Status_Success;
SDH_CMD_Cfg_Type SDH_CMD_Cfg_TypeInstance;
/* CMD2: SD_CMD_ALL_SEND_CID */
SDH_CMD_Cfg_TypeInstance.index = SD_CMD_ALL_SEND_CID;
SDH_CMD_Cfg_TypeInstance.argument = 0;
SDH_CMD_Cfg_TypeInstance.type = SDH_CMD_NORMAL;
SDH_CMD_Cfg_TypeInstance.respType = SDH_RESP_R2;
SDH_CMD_Cfg_TypeInstance.flag = SDH_TRANS_FLAG_NONE;
errorstatus = SDH_SendCardCommand(&SDH_CMD_Cfg_TypeInstance);
if (errorstatus != Status_Success) {
return Status_SDH_CmdResponseError;
}
card->rawCid[0] = SDH_CMD_Cfg_TypeInstance.response[0];
card->rawCid[1] = SDH_CMD_Cfg_TypeInstance.response[1];
card->rawCid[2] = SDH_CMD_Cfg_TypeInstance.response[2];
card->rawCid[3] = SDH_CMD_Cfg_TypeInstance.response[3];
SD_DecodeCid(card, card->rawCid);
return errorstatus;
}
static status_t SD_SendRca(sd_card_t *card)
{
status_t errorstatus = Status_Success;
SDH_CMD_Cfg_Type SDH_CMD_Cfg_TypeInstance;
/*CMD3: send relative card address*/
SDH_CMD_Cfg_TypeInstance.index = SD_CMD_SET_REL_ADDR;
SDH_CMD_Cfg_TypeInstance.argument = 0;
SDH_CMD_Cfg_TypeInstance.type = SDH_CMD_NORMAL;
SDH_CMD_Cfg_TypeInstance.respType = SDH_RESP_R6;
SDH_CMD_Cfg_TypeInstance.flag = SDH_TRANS_FLAG_NONE;
errorstatus = SDH_SendCardCommand(&SDH_CMD_Cfg_TypeInstance);
if (errorstatus != Status_Success) {
return Status_SDH_CmdResponseError;
}
card->relativeAddress = SDH_CMD_Cfg_TypeInstance.response[0] >> 16;
return errorstatus;
}
static status_t SD_SendCsd(sd_card_t *card)
{
status_t errorstatus = Status_Success;
SDH_CMD_Cfg_Type SDH_CMD_Cfg_TypeInstance;
/*CMD9: send card-specific data(CSD)*/
SDH_CMD_Cfg_TypeInstance.index = SD_CMD_SEND_CSD;
SDH_CMD_Cfg_TypeInstance.argument = (uint32_t)((card->relativeAddress) << 16);
SDH_CMD_Cfg_TypeInstance.type = SDH_CMD_NORMAL;
SDH_CMD_Cfg_TypeInstance.respType = SDH_RESP_R2;
SDH_CMD_Cfg_TypeInstance.flag = SDH_TRANS_FLAG_NONE;
errorstatus = SDH_SendCardCommand(&SDH_CMD_Cfg_TypeInstance);
if (errorstatus != Status_Success) {
return Status_SDH_CmdResponseError;
}
card->rawCsd[0] = SDH_CMD_Cfg_TypeInstance.response[0];
card->rawCsd[1] = SDH_CMD_Cfg_TypeInstance.response[1];
card->rawCsd[2] = SDH_CMD_Cfg_TypeInstance.response[2];
card->rawCsd[3] = SDH_CMD_Cfg_TypeInstance.response[3];
SD_DecodeCsd(card, card->rawCsd);
return errorstatus;
}
static status_t SD_SelectCard(sd_card_t *card, BL_Fun_Type NewState)
{
status_t errorstatus = Status_Success;
SDH_CMD_Cfg_Type SDH_CMD_Cfg_TypeInstance;
/* CMD7: select/deselect specified card */
SDH_CMD_Cfg_TypeInstance.index = SD_CMD_SEL_DESEL_CARD;
if (NewState == ENABLE) {
SDH_CMD_Cfg_TypeInstance.argument = (uint32_t)((card->relativeAddress) << 16);
SDH_CMD_Cfg_TypeInstance.respType = SDH_RESP_R1B;
} else {
SDH_CMD_Cfg_TypeInstance.argument = 0;
SDH_CMD_Cfg_TypeInstance.respType = SDH_RESP_NONE;
}
SDH_CMD_Cfg_TypeInstance.type = SDH_CMD_NORMAL;
SDH_CMD_Cfg_TypeInstance.flag = SDH_TRANS_FLAG_NONE;
errorstatus = SDH_SendCardCommand(&SDH_CMD_Cfg_TypeInstance);
if (errorstatus != Status_Success) {
return Status_SDH_TransferFailed;
} else if ((NewState == ENABLE) && (SDH_CMD_Cfg_TypeInstance.response[0] & SD_CSR_ERRORBITS)) {
return Status_SDH_CmdResponseError;
}
return errorstatus;
}
/* get CSR */
static status_t SD_SendScr(sd_card_t *card)
{
status_t errorstatus = Status_Success;
SDH_Stat_Type stat = SDH_STAT_SUCCESS;
SD_Error sd_status;
SDH_CMD_Cfg_Type SDH_CMD_Cfg_TypeInstance;
SDH_Data_Cfg_Type SDH_Data_Cfg_TypeInstance;
uint32_t tempscr[2] = { 0, 0 };
uint32_t time_node;
/* send CMD55 */
errorstatus = SD_SendApplicationCmd((uint32_t)((card->relativeAddress) << 16));
if (errorstatus != Status_Success) {
goto out;
}
/*!< Set Block Size To 8 Bytes */
SDH_Data_Cfg_TypeInstance.enableAutoCommand12 = DISABLE;
SDH_Data_Cfg_TypeInstance.enableAutoCommand23 = DISABLE;
SDH_Data_Cfg_TypeInstance.enableIgnoreError = DISABLE;
SDH_Data_Cfg_TypeInstance.dataType = SDH_TRANS_DATA_NORMAL;
SDH_Data_Cfg_TypeInstance.blockSize = 8;
SDH_Data_Cfg_TypeInstance.blockCount = 1;
SDH_Data_Cfg_TypeInstance.rxDataLen = 0;
SDH_Data_Cfg_TypeInstance.rxData = tempscr;
SDH_Data_Cfg_TypeInstance.txDataLen = 0;
SDH_Data_Cfg_TypeInstance.txData = NULL;
/* Config the data transfer parameter */
stat = SDH_ConfigDataTranfer(&SDH_Data_Cfg_TypeInstance);
if (SDH_STAT_SUCCESS != stat) {
return Status_SDH_TransferFailed;
}
/*!< Send ACMD51 SD_APP_SEND_SCR with argument as 0 */
SDH_CMD_Cfg_TypeInstance.index = SD_CMD_SD_APP_SEND_SCR;
SDH_CMD_Cfg_TypeInstance.argument = 0;
SDH_CMD_Cfg_TypeInstance.type = SDH_CMD_NORMAL;
SDH_CMD_Cfg_TypeInstance.respType = SDH_RESP_R1;
SDH_CMD_Cfg_TypeInstance.flag = SDH_TRANS_FLAG_DATA_PRESENT;
errorstatus = SDH_SendCardCommand(&SDH_CMD_Cfg_TypeInstance);
if (errorstatus != Status_Success) {
goto out;
} else if (SDH_CMD_Cfg_TypeInstance.response[0] & SD_CSR_ERRORBITS) {
errorstatus = Status_SDH_CmdResponseError;
goto out;
}
/* Waiting for CSR data */
time_node = (uint32_t)bflb_mtimer_get_time_ms();
#if SDIO_SDCARD_INT_MODE
SDH_DataWaitStatus = SD_WAITING;
SDH_EnableIntSource(SDH_INT_BUFFER_READ_READY | SDH_INT_DATA_COMPLETED | SDH_INT_DATA_ERRORS | SDH_INT_DMA_ERROR | SDH_INT_AUTO_CMD12_ERROR);
/*wait for Xfer status. might pending here in multi-task OS*/
while (SDH_DataWaitStatus == SD_WAITING) {
if ((uint32_t)bflb_mtimer_get_time_ms() - time_node > SDIO_CMDTIMEOUT_MS) {
SDH_MSG("sdh get csr data timeout: %ld ms\r\n", (uint32_t)bflb_mtimer_get_time_ms() - time_node);
SDH_DisableIntSource(SDH_INT_BUFFER_READ_READY | SDH_INT_DATA_COMPLETED | SDH_INT_DATA_ERRORS | SDH_INT_DMA_ERROR | SDH_INT_AUTO_CMD12_ERROR);
errorstatus = Status_Timeout;
goto out;
}
BL_DRV_DUMMY;
BL_DRV_DUMMY;
}
SDH_DisableIntSource(SDH_INT_BUFFER_READ_READY | SDH_INT_DATA_COMPLETED | SDH_INT_DATA_ERRORS | SDH_INT_DMA_ERROR | SDH_INT_AUTO_CMD12_ERROR);
sd_status = SDH_DataWaitStatus;
#else
uint32_t intFlag;
while (1) {
intFlag = SDH_GetIntStatus();
if (intFlag & SDH_INT_DATA_ERRORS || intFlag & SDH_INT_DMA_ERROR) {
sd_status = SD_DataCfg_ERROR;
break;
} else if (intFlag & SDH_INT_BUFFER_READ_READY || intFlag & SDH_INT_DATA_COMPLETED) {
sd_status = SD_OK;
break;
} else if ((uint32_t)bflb_mtimer_get_time_ms() - time_node > SDIO_CMDTIMEOUT_MS) {
SDH_MSG("SDH get csr data timeout: %ld ms\r\n", (uint32_t)bflb_mtimer_get_time_ms() - time_node);
return Status_Timeout;
}
BL_DRV_DUMMY;
BL_DRV_DUMMY;
}
SDH_ClearIntStatus(intFlag);
#endif
if (sd_status == SD_OK) {
SDH_ReadDataPort(&SDH_Data_Cfg_TypeInstance);
card->rawScr[1] = ((tempscr[0] & SD_0TO7BITS) << 24) | ((tempscr[0] & SD_8TO15BITS) << 8) | ((tempscr[0] & SD_16TO23BITS) >> 8) | ((tempscr[0] & SD_24TO31BITS) >> 24);
card->rawScr[0] = ((tempscr[1] & SD_0TO7BITS) << 24) | ((tempscr[1] & SD_8TO15BITS) << 8) | ((tempscr[1] & SD_16TO23BITS) >> 8) | ((tempscr[1] & SD_24TO31BITS) >> 24);
SD_DecodeScr(card, card->rawScr);
SDH_MSG("SDH get csr success\r\n");
} else {
errorstatus = Status_SDH_TransferFailed;
SDH_MSG("SDH get csr failed\r\n");
goto out;
}
out:
return errorstatus;
}
/* get SSR */
static status_t SD_SendSsr(sd_card_t *card)
{
status_t errorstatus = Status_Success;
SDH_Stat_Type stat = SDH_STAT_SUCCESS;
SD_Error sd_status;
uint32_t time_node;
SDH_CMD_Cfg_Type SDH_CMD_Cfg_TypeInstance;
SDH_Data_Cfg_Type SDH_Data_Cfg_TypeInstance;
errorstatus = SD_SendApplicationCmd((uint32_t)((card->relativeAddress) << 16));
if (errorstatus != Status_Success) {
goto out;
}
/*!< Set Block Size To 512 Bytes */
SDH_Data_Cfg_TypeInstance.enableAutoCommand12 = DISABLE;
SDH_Data_Cfg_TypeInstance.enableAutoCommand23 = DISABLE;
SDH_Data_Cfg_TypeInstance.enableIgnoreError = DISABLE;
SDH_Data_Cfg_TypeInstance.dataType = SDH_TRANS_DATA_NORMAL;
SDH_Data_Cfg_TypeInstance.blockSize = 64;
SDH_Data_Cfg_TypeInstance.blockCount = 1;
SDH_Data_Cfg_TypeInstance.rxDataLen = 0;
SDH_Data_Cfg_TypeInstance.rxData = card->rawSsr;
SDH_Data_Cfg_TypeInstance.txDataLen = 0;
SDH_Data_Cfg_TypeInstance.txData = NULL;
/* Config the data transfer parameter */
stat = SDH_ConfigDataTranfer(&SDH_Data_Cfg_TypeInstance);
if (SDH_STAT_SUCCESS != stat) {
return Status_SDH_TransferFailed;
}
/*!< Send ACMD13 SD_APP_SEND_SCR with argument as 0 */
SDH_CMD_Cfg_TypeInstance.index = SD_CMD_SD_APP_STAUS;
SDH_CMD_Cfg_TypeInstance.argument = 0;
SDH_CMD_Cfg_TypeInstance.type = SDH_CMD_NORMAL;
SDH_CMD_Cfg_TypeInstance.respType = SDH_RESP_R1;
SDH_CMD_Cfg_TypeInstance.flag = SDH_TRANS_FLAG_DATA_PRESENT;
errorstatus = SDH_SendCardCommand(&SDH_CMD_Cfg_TypeInstance);
if (errorstatus != Status_Success) {
goto out;
} else if (SDH_CMD_Cfg_TypeInstance.response[0] & SD_CSR_ERRORBITS) {
errorstatus = Status_SDH_CmdResponseError;
goto out;
}
/* Waiting for SSR data */
time_node = (uint32_t)bflb_mtimer_get_time_ms();
#if SDIO_SDCARD_INT_MODE
SDH_DataWaitStatus = SD_WAITING;
SDH_EnableIntSource(SDH_INT_BUFFER_READ_READY | SDH_INT_DATA_COMPLETED | SDH_INT_DATA_ERRORS | SDH_INT_DMA_ERROR | SDH_INT_AUTO_CMD12_ERROR);
/*wait for Xfer status. might pending here in multi-task OS*/
while (SDH_DataWaitStatus == SD_WAITING) {
if ((uint32_t)bflb_mtimer_get_time_ms() - time_node > SDIO_CMDTIMEOUT_MS) {
SDH_MSG("SDH get ssr data timeout: %ld ms\r\n", (uint32_t)bflb_mtimer_get_time_ms() - time_node);
SDH_DisableIntSource(SDH_INT_BUFFER_READ_READY | SDH_INT_DATA_COMPLETED | SDH_INT_DATA_ERRORS | SDH_INT_DMA_ERROR | SDH_INT_AUTO_CMD12_ERROR);
errorstatus = Status_Timeout;
goto out;
}
BL_DRV_DUMMY;
BL_DRV_DUMMY;
}
SDH_DisableIntSource(SDH_INT_BUFFER_READ_READY | SDH_INT_DATA_COMPLETED | SDH_INT_DATA_ERRORS | SDH_INT_DMA_ERROR | SDH_INT_AUTO_CMD12_ERROR);
sd_status = SDH_DataWaitStatus;
#else
uint32_t intFlag;
while (1) {
intFlag = SDH_GetIntStatus();
if (intFlag & SDH_INT_DATA_ERRORS || intFlag & SDH_INT_DMA_ERROR) {
sd_status = SD_DataCfg_ERROR;
break;
} else if (intFlag & SDH_INT_BUFFER_READ_READY || intFlag & SDH_INT_DATA_COMPLETED) {
sd_status = SD_OK;
break;
} else if ((uint32_t)bflb_mtimer_get_time_ms() - time_node > SDIO_CMDTIMEOUT_MS) {
SDH_MSG("SDH get ssr data timeout: %ld ms\r\n", (uint32_t)bflb_mtimer_get_time_ms() - time_node);
errorstatus = Status_Timeout;
goto out;
}
BL_DRV_DUMMY;
BL_DRV_DUMMY;
}
SDH_ClearIntStatus(intFlag);
#endif
if (sd_status == SD_OK) {
SDH_ReadDataPort(&SDH_Data_Cfg_TypeInstance);
SDH_MSG("SDH get ssr success\r\n");
} else {
errorstatus = Status_SDH_TransferFailed;
SDH_MSG("SDH get ssr failed\r\n");
goto out;
}
out:
return errorstatus;
}
/* Set Data Bus Width */
static status_t SD_SetDataBusWidth(sd_card_t *card, SDH_Data_Bus_Width_Type width)
{
status_t errorstatus = Status_Success;
SDH_CMD_Cfg_Type SDH_CMD_Cfg_TypeInstance;
if (width == SDH_DATA_BUS_WIDTH_1BIT) {
SDH_CMD_Cfg_TypeInstance.argument = 0;
} else if (width == SDH_DATA_BUS_WIDTH_4BITS) {
SDH_CMD_Cfg_TypeInstance.argument = 2;
} else {
return Status_InvalidArgument;
}
errorstatus = SD_SendApplicationCmd((uint32_t)((card->relativeAddress) << 16));
if (errorstatus != Status_Success) {
goto out;
}
/*!< Send ACMD6 APP_CMD with argument as 2 for wide bus mode */
SDH_CMD_Cfg_TypeInstance.index = SD_CMD_APP_SD_SET_BUSWIDTH;
SDH_CMD_Cfg_TypeInstance.type = SDH_CMD_NORMAL;
SDH_CMD_Cfg_TypeInstance.respType = SDH_RESP_R1;
SDH_CMD_Cfg_TypeInstance.flag = SDH_TRANS_FLAG_NONE;
errorstatus = SDH_SendCardCommand(&SDH_CMD_Cfg_TypeInstance);
if (errorstatus != Status_Success) {
goto out;
} else if (SDH_CMD_Cfg_TypeInstance.response[0] & SD_CSR_ERRORBITS) {
errorstatus = Status_SDH_CmdResponseError;
goto out;
}
GLB_Set_SDH_CLK(ENABLE, GLB_SDH_CLK_WIFIPLL_96M, 1);
/* reinitialise SDH controller*/
SDH_Cfg_Type_Instance.vlot18Enable = DISABLE;
SDH_Cfg_Type_Instance.highSpeed = ENABLE;
SDH_Cfg_Type_Instance.dataWidth = width;
SDH_Cfg_Type_Instance.volt = SDH_VOLTAGE_3P3V;
SDH_Cfg_Type_Instance.srcClock = sdhClockSrc;
SDH_Cfg_Type_Instance.busClock = sdhClockTransfer;
SDH_Ctrl_Init(&SDH_Cfg_Type_Instance);
out:
return errorstatus;
}
/* switch function
mode: 0 check function, 1 set function
group: group number,1~6
number:
*/
static status_t SD_SwitchFunction(uint32_t mode, uint32_t group, uint32_t number, uint32_t status[16])
{
status_t errorstatus = Status_Success;
SDH_Stat_Type stat = SDH_STAT_SUCCESS;
SD_Error sd_status;
uint32_t time_node;
SDH_CMD_Cfg_Type SDH_CMD_Cfg_TypeInstance;
SDH_Data_Cfg_Type SDH_Data_Cfg_TypeInstance;
/*!< Set Block Size To 64 Bytes */
SDH_Data_Cfg_TypeInstance.enableAutoCommand12 = DISABLE;
SDH_Data_Cfg_TypeInstance.enableAutoCommand23 = DISABLE;
SDH_Data_Cfg_TypeInstance.enableIgnoreError = DISABLE;
SDH_Data_Cfg_TypeInstance.dataType = SDH_TRANS_DATA_NORMAL;
SDH_Data_Cfg_TypeInstance.blockSize = 64;
SDH_Data_Cfg_TypeInstance.blockCount = 1;
SDH_Data_Cfg_TypeInstance.rxDataLen = 0;
SDH_Data_Cfg_TypeInstance.rxData = status;
SDH_Data_Cfg_TypeInstance.txDataLen = 0;
SDH_Data_Cfg_TypeInstance.txData = NULL;
/* Config the data transfer parameter */
stat = SDH_ConfigDataTranfer(&SDH_Data_Cfg_TypeInstance);
if (SDH_STAT_SUCCESS != stat) {
return Status_SDH_TransferFailed;
}
/*!< Send CMD6 SD_CMD_HS_SWITCH with argument as 0 */
SDH_CMD_Cfg_TypeInstance.index = SD_CMD_HS_SWITCH;
SDH_CMD_Cfg_TypeInstance.argument = (mode << 31U | 0x00FFFFFFU);
SDH_CMD_Cfg_TypeInstance.argument &= ~((uint32_t)(0xFU) << (group * 4U));
SDH_CMD_Cfg_TypeInstance.argument |= (number << (group * 4U));
SDH_CMD_Cfg_TypeInstance.type = SDH_CMD_NORMAL;
SDH_CMD_Cfg_TypeInstance.respType = SDH_RESP_R1;
SDH_CMD_Cfg_TypeInstance.flag = SDH_TRANS_FLAG_DATA_PRESENT;
errorstatus = SDH_SendCardCommand(&SDH_CMD_Cfg_TypeInstance);
if (errorstatus != Status_Success) {
goto out;
} else if (SDH_CMD_Cfg_TypeInstance.response[0] & SD_CSR_ERRORBITS) {
errorstatus = Status_SDH_CmdResponseError;
goto out;
}
/* Waiting for CSR data */
time_node = (uint32_t)bflb_mtimer_get_time_ms();
#if SDIO_SDCARD_INT_MODE
SDH_DataWaitStatus = SD_WAITING;
SDH_EnableIntSource(SDH_INT_BUFFER_READ_READY | SDH_INT_DATA_COMPLETED | SDH_INT_DATA_ERRORS | SDH_INT_DMA_ERROR);
/*wait for Xfer status. might pending here in multi-task OS*/
while (SDH_DataWaitStatus == SD_WAITING) {
if ((uint32_t)bflb_mtimer_get_time_ms() - time_node > SDIO_CMDTIMEOUT_MS) {
SDH_MSG("SDH get CMD6 status data timeout: %ld ms\r\n", (uint32_t)bflb_mtimer_get_time_ms() - time_node);
SDH_DisableIntSource(SDH_INT_BUFFER_READ_READY | SDH_INT_DATA_COMPLETED | SDH_INT_DATA_ERRORS | SDH_INT_DMA_ERROR);
errorstatus = Status_Timeout;
goto out;
}
BL_DRV_DUMMY;
BL_DRV_DUMMY;
}
SDH_DisableIntSource(SDH_INT_BUFFER_READ_READY | SDH_INT_DATA_COMPLETED | SDH_INT_DATA_ERRORS | SDH_INT_DMA_ERROR);
sd_status = SDH_DataWaitStatus;
#else
uint32_t intFlag;
while (1) {
intFlag = SDH_GetIntStatus();
if (intFlag & SDH_INT_DATA_ERRORS || intFlag & SDH_INT_DMA_ERROR) {
sd_status = SD_DataCfg_ERROR;
break;
} else if (intFlag & SDH_INT_BUFFER_READ_READY || intFlag & SDH_INT_DATA_COMPLETED) {
sd_status = SD_OK;
break;
} else if ((uint32_t)bflb_mtimer_get_time_ms() - time_node > SDIO_CMDTIMEOUT_MS) {
SDH_MSG("SDH get CMD6 status data timeout: %ld ms\r\n", (uint32_t)bflb_mtimer_get_time_ms() - time_node);
return Status_Timeout;
}
BL_DRV_DUMMY;
BL_DRV_DUMMY;
}
SDH_ClearIntStatus(intFlag);
#endif
if (sd_status == SD_OK) {
SDH_ReadDataPort(&SDH_Data_Cfg_TypeInstance);
SDH_MSG("SDH get CMD6 status data success\r\n");
} else {
errorstatus = Status_SDH_TransferFailed;
SDH_MSG("SDH get CMD6 status data failed\r\n");
goto out;
}
out:
return errorstatus;
}
/* */
static __USED status_t SD_SelectFunction(uint32_t group, uint32_t function)
{
status_t errorstatus = Status_Success;
uint32_t cmd6Status[16] = { 0 };
uint16_t functionGroupInfo[6U] = { 0 };
uint32_t currentFunctionStatus = 0U;
uint32_t i;
/* Check if card support high speed mode. */
if (Status_Success != SD_SwitchFunction(SDH_SwitchCheck, group, function, cmd6Status)) {
return Status_SDH_SDIO_SwitchHighSpeedFail;
}
for (i = 0; i < 16; i++) {
SDH_MSG("cmd6Status[%d]=0x%x.\r\n", i, cmd6Status[i]);
}
/* In little endian mode, SD bus byte transferred first is the byte stored in lowest byte position in
a word which will cause 4 byte's sequence in a word is not consistent with their original sequence from
card. So the sequence of 4 bytes received in a word should be converted. */
cmd6Status[0U] = SWAP_WORD_BYTE_SEQUENCE(cmd6Status[0U]);
cmd6Status[1U] = SWAP_WORD_BYTE_SEQUENCE(cmd6Status[1U]);
cmd6Status[2U] = SWAP_WORD_BYTE_SEQUENCE(cmd6Status[2U]);
cmd6Status[3U] = SWAP_WORD_BYTE_SEQUENCE(cmd6Status[3U]);
cmd6Status[4U] = SWAP_WORD_BYTE_SEQUENCE(cmd6Status[4U]);
functionGroupInfo[5U] = (uint16_t)cmd6Status[0U];
functionGroupInfo[4U] = (uint16_t)(cmd6Status[1U] >> 16U);
functionGroupInfo[3U] = (uint16_t)(cmd6Status[1U]);
functionGroupInfo[2U] = (uint16_t)(cmd6Status[2U] >> 16U);
functionGroupInfo[1U] = (uint16_t)(cmd6Status[2U]);
functionGroupInfo[0U] = (uint16_t)(cmd6Status[3U] >> 16U);
currentFunctionStatus = ((cmd6Status[3U] & 0xFFFFU) << 8U) | (cmd6Status[4U] >> 24U);
for (i = 0; i < 6; i++) {
SDH_MSG("functionGroupInfo[%d]=0x%x.\r\n", i, functionGroupInfo[i]);
}
SDH_MSG("currentFunctionStatus = 0x%x.\r\n", currentFunctionStatus);
/* check if function is support */
if (((functionGroupInfo[group] & (1 << function)) == 0U) ||
((currentFunctionStatus >> (group * 4U)) & 0xFU) != function) {
return Status_SDH_SDIO_SwitchHighSpeedFail;
}
/* Check if card support high speed mode. */
if (Status_Success != SD_SwitchFunction(SDH_SwitchSet, group, function, cmd6Status)) {
return Status_SDH_SDIO_SwitchHighSpeedFail;
}
/* In little endian mode is little endian, SD bus byte transferred first is the byte stored in lowest byte
position in a word which will cause 4 byte's sequence in a word is not consistent with their original
sequence from card. So the sequence of 4 bytes received in a word should be converted. */
cmd6Status[3U] = SWAP_WORD_BYTE_SEQUENCE(cmd6Status[3U]);
cmd6Status[4U] = SWAP_WORD_BYTE_SEQUENCE(cmd6Status[4U]);
/* According to the "switch function status[bits 511~0]" return by switch command in mode "set function":
-check if group 1 is successfully changed to function 1 by checking if bits 379~376 equal value 1;
*/
currentFunctionStatus = ((cmd6Status[3U] & 0xFFFFU) << 8U) | (cmd6Status[4U] >> 24U);
SDH_MSG("currentFunctionStatus = 0x%x.\r\n", currentFunctionStatus);
if (((currentFunctionStatus >> (group * 4U)) & 0xFU) != function) {
return Status_SDH_SDIO_SwitchHighSpeedFail;
}
return errorstatus;
}
static status_t SD_SetBlockSize(uint32_t blockSize)
{
status_t errorstatus = Status_Success;
SDH_CMD_Cfg_Type SDH_CMD_Cfg_TypeInstance;
/*!< Set Block Size for SDSC Card,cmd16,no impact on SDHC card */
SDH_CMD_Cfg_TypeInstance.index = SD_CMD_SET_BLOCKLEN;
SDH_CMD_Cfg_TypeInstance.argument = (uint32_t)blockSize;
SDH_CMD_Cfg_TypeInstance.type = SDH_CMD_NORMAL;
SDH_CMD_Cfg_TypeInstance.respType = SDH_RESP_R1;
SDH_CMD_Cfg_TypeInstance.flag = SDH_TRANS_FLAG_NONE;
errorstatus = SDH_SendCardCommand(&SDH_CMD_Cfg_TypeInstance);
if (errorstatus != Status_Success) {
goto out;
} else if (SDH_CMD_Cfg_TypeInstance.response[0] & SD_CSR_ERRORBITS) {
errorstatus = Status_SDH_CmdResponseError;
goto out;
}
out:
return errorstatus;
}
static status_t SDH_SDCardInit(uint32_t bus_wide, sd_card_t *card)
{
status_t errorstatus = Status_Success;
uint32_t applicationCommand41Argument = SD_OcrVdd33_34Flag | SD_OcrVdd32_33Flag;
/* reset variables */
card->flags = 0U;
SDH_MSG("SD CARD GO IDEL...\r\n");
errorstatus = SDH_GoIdle();
if (errorstatus != SD_OK) {
return Status_SDH_GoIdleFailed;
}
SDH_MSG("SD CARD GO IDEL END\r\n");
for (uint16_t i = 0; i < 4; i++) {
/* send CMD8 */
errorstatus = SD_SendInterfaceCondition();
/* check response */
if (errorstatus == Status_Success) {
/* SDHC or SDXC card */
applicationCommand41Argument |= SD_OcrHostCapacitySupportFlag;
card->flags |= SD_SupportSdhcFlag;
break;
} else {
/* Try sending CMD8 again */
SDH_MSG("Try sending CMD8 again:%d\r\n", i + 1);
errorstatus = SDH_GoIdle();
if (errorstatus != Status_Success) {
return Status_SDH_GoIdleFailed;
}
}
}
/* Set card interface condition according to SDHC capability and card's supported interface condition. */
errorstatus = SD_ApplicationSendOperationCondition(card, applicationCommand41Argument);
if (errorstatus != Status_Success) {
return Status_SDH_SendApplicationCommandFailed;
}
SDH_MSG("\r\nOCR is: 0x%02x.\r\n", card->ocr);
SDH_MSG("\t SDHC supported[%s].\r\n\r\n", ((card->flags & SD_SupportHighCapacityFlag) ? "YES" : "NO"));
errorstatus = SD_AllSendCid(card);
if (errorstatus != Status_Success) {
return Status_SDH_AllSendCidFailed;
}
SDH_MSG("\r\nCID is: 0x%02x-0x%02x-0x%02x-0x%02x.\r\n",
card->rawCid[0], card->rawCid[1], card->rawCid[2], card->rawCid[3]);
SDH_MSG("\t manufacturerID is: 0x%02x.\r\n", card->cid.manufacturerID);
SDH_MSG("\t applicationID is: %c%c.\r\n", (card->cid.applicationID) >> 8, card->cid.applicationID);
SDH_MSG("\t productName is: %c%c%c%c%c.\r\n",
card->cid.productName[0], card->cid.productName[1], card->cid.productName[2], card->cid.productName[3], card->cid.productName[4]);
SDH_MSG("\t manufacturerData is: 0x%02x.\r\n\r\n", card->cid.manufacturerData);
errorstatus = SD_SendRca(card);
if (errorstatus != Status_Success) {
return Status_SDH_SendRelativeAddressFailed;
}
SDH_MSG("\r\nRCA is: 0x%02x.\r\n\r\n", card->relativeAddress);
errorstatus = SD_SendCsd(card);
if (errorstatus != Status_Success) {
return Status_SDH_SendCsdFailed;
}
SDH_MSG("\r\nCSD is: 0x%02x-0x%02x-0x%02x-0x%02x.\r\n",
card->rawCsd[0], card->rawCsd[1], card->rawCsd[2], card->rawCsd[3]);
SDH_MSG("\t CSD Version is: %s .\r\n", card->csd.csdStructure ? "csd version 2.0" : "csd version 1.0");
SDH_MSG("\t blockLen=%d, blockCounter=%d, CardSize is %d[MBytes].\r\n\r\n", card->blockSize, card->blockCount, (card->blockCount) >> 11);
errorstatus = SD_SelectCard(card, ENABLE);
if (errorstatus != Status_Success) {
return Status_SDH_SelectCardFailed;
}
errorstatus = SD_SendScr(card);
if (errorstatus != Status_Success) {
return Status_SDH_SendScrFailed;
}
SDH_MSG("\r\nSCR is: 0x%x-0x%x.\r\n", card->rawScr[0], card->rawScr[1]);
SDH_MSG("\t SD Spec Version is: [0x%02x]%s.\r\n", card->version,
(card->version & SD_SpecificationVersion3_0) ? "V3.0" : ((card->version & SD_SpecificationVersion2_0) ? "V2.0" : ((card->version & SD_SpecificationVersion1_1) ? "V1.1" : "V1.0")));
SDH_MSG("\t Erased bit is %d.\r\n", (card->scr.flags & SD_ScrDataStatusAfterErase));
SDH_MSG("\t 4-line supported[%s].\r\n", ((card->flags & SD_Support4BitWidthFlag) ? "YES" : "NO"));
SDH_MSG("\t SetBlockCountCmd supported[%s].\r\n", ((card->flags & SD_SupportSetBlockCountCmd) ? "YES" : "NO"));
SDH_MSG("\t SDXC supported[%s].\r\n\r\n", ((card->flags & SD_SupportSdxcFlag) ? "YES" : "NO"));
if (card->flags & SD_Support4BitWidthFlag) {
errorstatus = SD_SetDataBusWidth(card, (SDH_Data_Bus_Width_Type)bus_wide);
} else {
errorstatus = SD_SetDataBusWidth(card, SDH_DATA_BUS_WIDTH_1BIT);
}
if (errorstatus != Status_Success) {
return Status_SDH_SetDataBusWidthFailed;
}
errorstatus = SD_SendSsr(card);
if (errorstatus != Status_Success) {
return Status_SDH_SendSsrFailed;
}
SDH_MSG("\r\nSSR[0] is: 0x%x.\r\n", card->rawSsr[0]);
SDH_MSG("\t Current is %d-line mode.\r\n\r\n", (card->rawSsr[0] & 0x80) ? 4 : 1);
errorstatus = SD_SetBlockSize(SDH_DEFAULT_BLOCK_SIZE);
if (errorstatus != Status_Success) {
return Status_SDH_SetCardBlockSizeFailed;
}
//SD_SelectFunction(SDH_GroupTimingMode,SDH_TimingSDR25HighSpeedMode);
return errorstatus;
}
/**
* @brief Initializes SD Card clock.
* @retval SD status
*/
// status_t SDH_ClockSet(uint32_t clockInit, uint32_t clockSrc, uint32_t clockTransfer)
// {
// sdhClockInit = clockInit;
// sdhClockSrc = clockSrc;
// sdhClockTransfer = clockTransfer;
// return Status_Success;
// }
/**
* @brief Initializes the SD card device.
* @retval SD status
*/
status_t SDH_Init(uint32_t bus_wide, sd_card_t *pOutCardInfo)
{
pSDCardInfo = pOutCardInfo;
#if SDIO_SDCARD_INT_MODE
SDH_INT_Init();
#endif
/* reset SDH controller*/
SDH_Reset();
SDH_HostInit();
if (pOutCardInfo == NULL) {
return Status_InvalidArgument;
} else {
return SDH_SDCardInit(bus_wide, pOutCardInfo);
}
}
/**
* @brief Allows to erase memory area specified for the given card.
* @param startaddr: the start address.
* @param endaddr: the end address.
* @retval SD_Error: SD Card Error code.
*/
status_t SD_Erase(uint32_t startaddr, uint32_t endaddr)
{
status_t errorstatus = Status_Success;
uint8_t cardstate = 0;
SDH_CMD_Cfg_Type SDH_CMD_Cfg_TypeInstance;
/* SDSC card uses byte unit address*/
if (!(pSDCardInfo->flags & SD_SupportHighCapacityFlag)) {
startaddr *= 512;
endaddr *= 512;
}
/*!< Send CMD32 SD_ERASE_GRP_START with argument as addr */
SDH_CMD_Cfg_TypeInstance.index = SD_CMD_SD_ERASE_GRP_START;
SDH_CMD_Cfg_TypeInstance.argument = startaddr;
SDH_CMD_Cfg_TypeInstance.type = SDH_CMD_NORMAL;
SDH_CMD_Cfg_TypeInstance.respType = SDH_RESP_R1;
SDH_CMD_Cfg_TypeInstance.flag = SDH_TRANS_FLAG_NONE;
errorstatus = SDH_SendCardCommand(&SDH_CMD_Cfg_TypeInstance);
if (errorstatus != Status_Success) {
goto out;
} else if (SDH_CMD_Cfg_TypeInstance.response[0] & SD_CSR_ERRORBITS) {
errorstatus = Status_SDH_CmdResponseError;
goto out;
}
/*!< Send CMD33 SD_ERASE_GRP_END with argument as addr */
SDH_CMD_Cfg_TypeInstance.index = SD_CMD_SD_ERASE_GRP_END;
SDH_CMD_Cfg_TypeInstance.argument = endaddr;
SDH_CMD_Cfg_TypeInstance.type = SDH_CMD_NORMAL;
SDH_CMD_Cfg_TypeInstance.respType = SDH_RESP_R1;
SDH_CMD_Cfg_TypeInstance.flag = SDH_TRANS_FLAG_NONE;
errorstatus = SDH_SendCardCommand(&SDH_CMD_Cfg_TypeInstance);
if (errorstatus != Status_Success) {
goto out;
} else if (SDH_CMD_Cfg_TypeInstance.response[0] & SD_CSR_ERRORBITS) {
errorstatus = Status_SDH_CmdResponseError;
goto out;
}
/*!< Send CMD38 ERASE */
SDH_CMD_Cfg_TypeInstance.index = SD_CMD_ERASE;
SDH_CMD_Cfg_TypeInstance.argument = 0;
SDH_CMD_Cfg_TypeInstance.type = SDH_CMD_NORMAL;
SDH_CMD_Cfg_TypeInstance.respType = SDH_RESP_R1B;
SDH_CMD_Cfg_TypeInstance.flag = SDH_TRANS_FLAG_NONE;
errorstatus = SDH_SendCardCommand(&SDH_CMD_Cfg_TypeInstance);
if (errorstatus != Status_Success) {
goto out;
} else if (SDH_CMD_Cfg_TypeInstance.response[0] & SD_CSR_ERRORBITS) {
errorstatus = Status_SDH_CmdResponseError;
goto out;
}
/*!< Wait till the card is in programming state */
errorstatus = IsCardProgramming(&cardstate);
while ((errorstatus == SD_OK) && ((SD_CARD_PROGRAMMING == cardstate) || (SD_CARD_RECEIVING == cardstate))) {
errorstatus = IsCardProgramming(&cardstate);
}
out:
return errorstatus;
}
static status_t WaitInProgramming(void)
{
uint8_t cardstate = 0;
status_t errorstatus = Status_Success;
//uint32_t maxdelay = 0;
//maxdelay = 120000/(sdhClockSrc/sdhClockTransfer);
//while(maxdelay--){}
/*!< Wait till the card is in programming state */
errorstatus = IsCardProgramming(&cardstate);
while ((errorstatus == Status_Success) && ((SD_CARD_PROGRAMMING == cardstate) || (SD_CARD_RECEIVING == cardstate))) {
errorstatus = IsCardProgramming(&cardstate);
}
return errorstatus;
}
/*check sd card state*/
static status_t IsCardProgramming(uint8_t *pstatus)
{
status_t errorstatus = Status_Success;
SDH_CMD_Cfg_Type SDH_CMD_Cfg_TypeInstance;
/*cmd13 addressed card send its status*/
SDH_CMD_Cfg_TypeInstance.index = SD_CMD_SEND_STATUS;
SDH_CMD_Cfg_TypeInstance.argument = (uint32_t)(pSDCardInfo->relativeAddress) << 16;
SDH_CMD_Cfg_TypeInstance.type = SDH_CMD_NORMAL;
SDH_CMD_Cfg_TypeInstance.respType = SDH_RESP_R1;
SDH_CMD_Cfg_TypeInstance.flag = SDH_TRANS_FLAG_NONE;
errorstatus = SDH_SendCardCommand(&SDH_CMD_Cfg_TypeInstance);
if (errorstatus != Status_Success) {
goto out;
} else if (SDH_CMD_Cfg_TypeInstance.response[0] & SD_CSR_ERRORBITS) {
errorstatus = Status_SDH_CmdResponseError;
goto out;
}
/*!< Find out card status */
*pstatus = (uint8_t)((SDH_CMD_Cfg_TypeInstance.response[0] >> 9) & 0x0000000F); //status[12:9] :cardstate
out:
return (errorstatus);
}
/* Transmit data in non-blocking mode, Only the sending status of commands is checked */
static status_t SDH_CardTransferNonBlocking(SDH_DMA_Cfg_Type *dmaCfg, SDH_Trans_Cfg_Type *transfer)
{
status_t errorstatus = Status_Success;
SDH_Stat_Type stat = SDH_STAT_SUCCESS;
stat = SDH_TransferNonBlocking(dmaCfg, transfer);
if (stat != SDH_STAT_SUCCESS) {
return Status_SDH_TransferFailed;
}
/* Flush ADMA2-descriptor-table to RAM, Otherwise ADMA2 will fail */
bflb_l1c_dcache_clean_range((void *)(dmaCfg->admaEntries), dmaCfg->maxEntries * sizeof(SDH_ADMA2_Desc_Type));
errorstatus = SDH_SendCardCommand(transfer->cmdCfg);
if (errorstatus != Status_Success) {
return errorstatus;
} else if (transfer->cmdCfg->response[0] & SD_CSR_ERRORBITS) {
return Status_SDH_CmdResponseError;
}
return errorstatus;
}
status_t SDH_ReadMultiBlocks(uint8_t *readbuff, uint32_t ReadAddr, uint16_t BlockSize, uint32_t NumberOfBlocks)
{
status_t errorstatus = Status_Success;
SD_Error sd_status;
uint32_t time_node;
static SDH_CMD_Cfg_Type SDH_CMD_Cfg_TypeInstance;
static SDH_Data_Cfg_Type SDH_Data_Cfg_TypeInstance;
static SDH_Trans_Cfg_Type SDH_Trans_Cfg_TypeInstance = { &SDH_Data_Cfg_TypeInstance, &SDH_CMD_Cfg_TypeInstance };
#if defined(BL808) || defined(BL606P)
/* BL808/BL606 supports only 8-byte aligned addresses */
if ((uintptr_t)readbuff % 8 != 0) {
return Status_InvalidArgument;
}
#endif
/* SDSC card uses byte unit address*/
if (!(pSDCardInfo->flags & SD_SupportHighCapacityFlag)) {
BlockSize = 512;
ReadAddr *= 512;
}
SDH_MSG("\r\nRead-->IN, block num: %d, block addr: %d, read buffer addr: 0x%p.\r\n", NumberOfBlocks, ReadAddr, readbuff);
/*set cmd parameter for READ_MULTIPLE_BLOCK*/
if (NumberOfBlocks <= 1) {
SDH_CMD_Cfg_TypeInstance.index = SD_CMD_READ_SINGLE_BLOCK;
} else {
SDH_CMD_Cfg_TypeInstance.index = SD_CMD_READ_MULT_BLOCK;
}
SDH_CMD_Cfg_TypeInstance.argument = (uint32_t)ReadAddr;
SDH_CMD_Cfg_TypeInstance.type = SDH_CMD_NORMAL;
SDH_CMD_Cfg_TypeInstance.respType = SDH_RESP_R1;
SDH_CMD_Cfg_TypeInstance.flag = SDH_TRANS_FLAG_DATA_PRESENT;
/*set data parameter for READ_MULTIPLE_BLOCK*/
if (NumberOfBlocks <= 1) {
SDH_Data_Cfg_TypeInstance.enableAutoCommand12 = DISABLE;
SDH_Data_Cfg_TypeInstance.enableAutoCommand23 = DISABLE;
} else {
if (pSDCardInfo->flags & SD_SupportSetBlockCountCmd) {
SDH_Data_Cfg_TypeInstance.enableAutoCommand23 = ENABLE;
SDH_Data_Cfg_TypeInstance.enableAutoCommand12 = DISABLE;
} else {
SDH_Data_Cfg_TypeInstance.enableAutoCommand23 = DISABLE;
SDH_Data_Cfg_TypeInstance.enableAutoCommand12 = ENABLE;
}
}
SDH_Data_Cfg_TypeInstance.enableIgnoreError = DISABLE;
SDH_Data_Cfg_TypeInstance.dataType = SDH_TRANS_DATA_NORMAL;
SDH_Data_Cfg_TypeInstance.blockSize = BlockSize;
SDH_Data_Cfg_TypeInstance.blockCount = NumberOfBlocks;
SDH_Data_Cfg_TypeInstance.rxDataLen = 0;
SDH_Data_Cfg_TypeInstance.rxData = (uint32_t *)readbuff;
SDH_Data_Cfg_TypeInstance.txDataLen = 0;
SDH_Data_Cfg_TypeInstance.txData = NULL;
SDH_Data_Cfg_TypeInstance.txDataLen = 0;
SDH_Data_Cfg_TypeInstance.txData = NULL;
/*set parameters for SDH_DMA_Cfg_TypeInstance*/
SDH_DMA_Cfg_TypeInstance.dmaMode = SDH_DMA_MODE_ADMA2;
SDH_DMA_Cfg_TypeInstance.burstSize = SDH_BURST_SIZE_128_BYTES;
SDH_DMA_Cfg_TypeInstance.fifoThreshold = SDH_BURST_SIZE_128_BYTES;
SDH_DMA_Cfg_TypeInstance.admaEntries = (uint32_t *)adma2Entries;
SDH_DMA_Cfg_TypeInstance.maxEntries = sizeof(adma2Entries) / sizeof(adma2Entries[0]);
errorstatus = SDH_CardTransferNonBlocking(&SDH_DMA_Cfg_TypeInstance, &SDH_Trans_Cfg_TypeInstance);
if (errorstatus != Status_Success) {
SDH_MSG("SDH Transfer err:%d\r\n", errorstatus);
goto out;
}
time_node = (uint32_t)bflb_mtimer_get_time_ms();
#if SDIO_SDCARD_INT_MODE
SDH_DataWaitStatus = SD_WAITING;
SDH_EnableIntSource(SDH_INT_DATA_COMPLETED | SDH_INT_DATA_ERRORS | SDH_INT_DMA_ERROR | SDH_INT_AUTO_CMD12_ERROR);
/*wait for Xfer status. might pending here in multi-task OS*/
while (SDH_DataWaitStatus == SD_WAITING) {
if ((uint32_t)bflb_mtimer_get_time_ms() - time_node > SDIO_CMDTIMEOUT_MS) {
SDH_MSG("SDH read data timeout: %ld", (uint32_t)bflb_mtimer_get_time_ms() - time_node);
SDH_DisableIntSource(SDH_INT_DATA_COMPLETED | SDH_INT_DATA_ERRORS | SDH_INT_DMA_ERROR | SDH_INT_AUTO_CMD12_ERROR);
return Status_Timeout;
}
BL_DRV_DUMMY;
BL_DRV_DUMMY;
}
sd_status = SDH_DataWaitStatus;
SDH_DisableIntSource(SDH_INT_DATA_COMPLETED | SDH_INT_DATA_ERRORS | SDH_INT_DMA_ERROR | SDH_INT_AUTO_CMD12_ERROR);
#else
uint32_t intFlag;
while (1) {
intFlag = SDH_GetIntStatus();
if (intFlag & SDH_INT_DATA_ERRORS || intFlag & SDH_INT_DMA_ERROR || intFlag & SDH_INT_AUTO_CMD12_ERROR) {
sd_status = SD_CMD_ERROR;
break;
} else if (intFlag & SDH_INT_DATA_COMPLETED) {
sd_status = SD_OK;
break;
} else if ((uint32_t)bflb_mtimer_get_time_ms() - time_node > SDIO_CMDTIMEOUT_MS) {
SDH_MSG("SDH read data timeout: %ld ms\r\n", (uint32_t)bflb_mtimer_get_time_ms() - time_node);
return Status_Timeout;
}
BL_DRV_DUMMY;
BL_DRV_DUMMY;
}
SDH_ClearIntStatus(intFlag);
#endif
if (sd_status != SD_OK) {
errorstatus = Status_SDH_TransferFailed;
goto out;
}
bflb_l1c_dcache_invalidate_range((void *)(readbuff), BlockSize * NumberOfBlocks);
SDH_MSG("Read data used time: %ld ms\r\n", (uint32_t)bflb_mtimer_get_time_ms() - time_node);
SDH_MSG("Read-->OUT, block num: %d, block addr: %d, read buffer addr: 0x%p.\r\n", NumberOfBlocks, ReadAddr, readbuff);
out:
return (errorstatus);
}
status_t SDH_WriteMultiBlocks(uint8_t *writebuff, uint32_t WriteAddr, uint16_t BlockSize, uint32_t NumberOfBlocks)
{
status_t errorstatus = Status_Success;
SD_Error sd_status;
uint32_t time_node;
static SDH_CMD_Cfg_Type SDH_CMD_Cfg_TypeInstance;
static SDH_Data_Cfg_Type SDH_Data_Cfg_TypeInstance;
static SDH_Trans_Cfg_Type SDH_Trans_Cfg_TypeInstance = { &SDH_Data_Cfg_TypeInstance, &SDH_CMD_Cfg_TypeInstance };
#if defined(BL808) || defined(BL606P)
/* BL808/BL606 supports only 8-byte aligned addresses */
if ((uintptr_t)writebuff % 8 != 0) {
return Status_InvalidArgument;
}
#endif
if ((pSDCardInfo != NULL) && (!(pSDCardInfo->flags & SD_SupportHighCapacityFlag))) {
/* It's SDCS card,SDSC card uses byte unit address*/
BlockSize = 512;
WriteAddr *= 512;
}
SDH_MSG("\r\nWrite-->IN, block num: %d, block addr: %d, read buffer addr: 0x%p.\r\n", NumberOfBlocks, WriteAddr, writebuff);
/*set cmd parameter for SD_CMD_WRITE_MULT_BLOCK*/
if (NumberOfBlocks <= 1) {
SDH_CMD_Cfg_TypeInstance.index = SD_CMD_WRITE_SINGLE_BLOCK;
} else {
SDH_CMD_Cfg_TypeInstance.index = SD_CMD_WRITE_MULT_BLOCK;
}
SDH_CMD_Cfg_TypeInstance.argument = (uint32_t)WriteAddr;
SDH_CMD_Cfg_TypeInstance.type = SDH_CMD_NORMAL;
SDH_CMD_Cfg_TypeInstance.respType = SDH_RESP_R1;
SDH_CMD_Cfg_TypeInstance.flag = SDH_TRANS_FLAG_DATA_PRESENT;
/*set data parameter for WRITE_MULTIPLE_BLOCK*/
if (NumberOfBlocks <= 1) {
SDH_Data_Cfg_TypeInstance.enableAutoCommand12 = DISABLE;
SDH_Data_Cfg_TypeInstance.enableAutoCommand23 = DISABLE;
} else {
if (pSDCardInfo->flags & SD_SupportSetBlockCountCmd) {
SDH_Data_Cfg_TypeInstance.enableAutoCommand23 = ENABLE;
SDH_Data_Cfg_TypeInstance.enableAutoCommand12 = DISABLE;
} else {
SDH_Data_Cfg_TypeInstance.enableAutoCommand23 = DISABLE;
SDH_Data_Cfg_TypeInstance.enableAutoCommand12 = ENABLE;
}
}
SDH_Data_Cfg_TypeInstance.enableIgnoreError = DISABLE;
SDH_Data_Cfg_TypeInstance.dataType = SDH_TRANS_DATA_NORMAL;
SDH_Data_Cfg_TypeInstance.blockSize = BlockSize;
SDH_Data_Cfg_TypeInstance.blockCount = NumberOfBlocks;
SDH_Data_Cfg_TypeInstance.rxDataLen = 0;
SDH_Data_Cfg_TypeInstance.rxData = NULL;
SDH_Data_Cfg_TypeInstance.txDataLen = 0;
SDH_Data_Cfg_TypeInstance.txData = (uint32_t *)writebuff;
/*set parameters for SDH_DMA_Cfg_TypeInstance*/
SDH_DMA_Cfg_TypeInstance.dmaMode = SDH_DMA_MODE_ADMA2;
SDH_DMA_Cfg_TypeInstance.burstSize = SDH_BURST_SIZE_128_BYTES;
SDH_DMA_Cfg_TypeInstance.fifoThreshold = SDH_FIFO_THRESHOLD_256_BYTES;
SDH_DMA_Cfg_TypeInstance.admaEntries = (uint32_t *)adma2Entries;
SDH_DMA_Cfg_TypeInstance.maxEntries = sizeof(adma2Entries) / sizeof(adma2Entries[0]);
bflb_l1c_dcache_clean_range((void *)(writebuff), BlockSize * NumberOfBlocks);
errorstatus = SDH_CardTransferNonBlocking(&SDH_DMA_Cfg_TypeInstance, &SDH_Trans_Cfg_TypeInstance);
if (errorstatus != Status_Success) {
SDH_MSG("SDH Transfer err:%d\r\n", errorstatus);
return errorstatus;
}
time_node = (uint32_t)bflb_mtimer_get_time_ms();
#if SDIO_SDCARD_INT_MODE
SDH_DataWaitStatus = SD_WAITING;
SDH_EnableIntSource(SDH_INT_DATA_COMPLETED | SDH_INT_DATA_ERRORS | SDH_INT_DMA_ERROR | SDH_INT_AUTO_CMD12_ERROR);
/*wait for Xfer status. might pending here in multi-task OS*/
while (SDH_DataWaitStatus == SD_WAITING) {
if ((uint32_t)bflb_mtimer_get_time_ms() - time_node > SDIO_CMDTIMEOUT_MS) {
SDH_MSG("SDH write data timeout: %ld ms\r\n", (uint32_t)bflb_mtimer_get_time_ms() - time_node);
SDH_DisableIntSource(SDH_INT_DATA_COMPLETED | SDH_INT_DATA_ERRORS | SDH_INT_DMA_ERROR | SDH_INT_AUTO_CMD12_ERROR);
errorstatus = Status_Timeout;
goto out;
}
BL_DRV_DUMMY;
BL_DRV_DUMMY;
}
SDH_DisableIntSource(SDH_INT_DATA_COMPLETED | SDH_INT_DATA_ERRORS | SDH_INT_DMA_ERROR | SDH_INT_AUTO_CMD12_ERROR);
sd_status = SDH_DataWaitStatus;
#else
uint32_t intFlag;
while (1) {
intFlag = SDH_GetIntStatus();
if (intFlag & SDH_INT_DATA_ERRORS || intFlag & SDH_INT_DMA_ERROR || intFlag & SDH_INT_AUTO_CMD12_ERROR) {
sd_status = SD_DataCfg_ERROR;
break;
} else if (intFlag & SDH_INT_DATA_COMPLETED) {
sd_status = SD_OK;
break;
} else if ((uint32_t)bflb_mtimer_get_time_ms() - time_node > SDIO_CMDTIMEOUT_MS) {
SDH_MSG("SDH write data timeout: %ld ms\r\n", (uint32_t)bflb_mtimer_get_time_ms() - time_node);
return Status_Timeout;
}
BL_DRV_DUMMY;
BL_DRV_DUMMY;
}
SDH_ClearIntStatus(intFlag);
#endif
if (sd_status != SD_OK) {
errorstatus = Status_SDH_TransferFailed;
goto out;
} else {
errorstatus = WaitInProgramming();
}
SDH_MSG("Write data used time: %ld ms\r\n", (uint32_t)bflb_mtimer_get_time_ms() - time_node);
SDH_MSG("Write-->OUT, block num: %d, block addr: %d, read buffer addr: 0x%p.\r\n", NumberOfBlocks, WriteAddr, writebuff);
out:
return (errorstatus);
}
#endif
找到了一个关于sdcard操作的类