summaryrefslogtreecommitdiffhomepage
path: root/digital/zigbit/bitcloud/stack/Components/HAL/drivers/USBClasses/MSD/src/mmc.c
diff options
context:
space:
mode:
Diffstat (limited to 'digital/zigbit/bitcloud/stack/Components/HAL/drivers/USBClasses/MSD/src/mmc.c')
-rw-r--r--digital/zigbit/bitcloud/stack/Components/HAL/drivers/USBClasses/MSD/src/mmc.c618
1 files changed, 618 insertions, 0 deletions
diff --git a/digital/zigbit/bitcloud/stack/Components/HAL/drivers/USBClasses/MSD/src/mmc.c b/digital/zigbit/bitcloud/stack/Components/HAL/drivers/USBClasses/MSD/src/mmc.c
new file mode 100644
index 00000000..b512bd04
--- /dev/null
+++ b/digital/zigbit/bitcloud/stack/Components/HAL/drivers/USBClasses/MSD/src/mmc.c
@@ -0,0 +1,618 @@
+/****************************************************************************//**
+ \files mmc.c
+
+ \brief Implementation of mmc protocol.
+
+ \author
+ Atmel Corporation: http://www.atmel.com \n
+ Support email: avr@atmel.com
+
+ Copyright (c) 2008-2011, Atmel Corporation. All rights reserved.
+ Licensed under Atmel's Limited License Agreement (BitCloudTM).
+
+ \internal
+ History:
+ 30/08/11 N. Fomin - Created
+*******************************************************************************/
+/******************************************************************************
+ Includes section
+******************************************************************************/
+#include <mem.h>
+
+/******************************************************************************
+ Define(s) section
+******************************************************************************/
+// card voltage ranges
+#define OCR_VDD_16_17 (1 << 4)
+#define OCR_VDD_17_18 (1 << 5)
+#define OCR_VDD_18_19 (1 << 6)
+#define OCR_VDD_19_20 (1 << 7)
+#define OCR_VDD_20_21 (1 << 8)
+#define OCR_VDD_21_22 (1 << 9)
+#define OCR_VDD_22_23 (1 << 10)
+#define OCR_VDD_23_24 (1 << 11)
+#define OCR_VDD_24_25 (1 << 12)
+#define OCR_VDD_25_26 (1 << 13)
+#define OCR_VDD_26_27 (1 << 14)
+#define OCR_VDD_27_28 (1 << 15)
+#define OCR_VDD_28_29 (1 << 16)
+#define OCR_VDD_29_30 (1 << 17)
+#define OCR_VDD_30_31 (1 << 18)
+#define OCR_VDD_31_32 (1 << 19)
+#define OCR_VDD_32_33 (1 << 20)
+#define OCR_VDD_33_34 (1 << 21)
+#define OCR_VDD_34_35 (1 << 22)
+#define OCR_VDD_35_36 (1 << 23)
+// R1 response statuses
+#define STATUS_APP_CMD (1UL << 5)
+#define STATUS_SWITCH_ERROR (1UL << 7)
+#define STATUS_READY_FOR_DATA (1UL << 8)
+#define STATUS_IDLE (0UL << 9)
+#define STATUS_READY (1UL << 9)
+#define STATUS_IDENT (2UL << 9)
+#define STATUS_STBY (3UL << 9)
+#define STATUS_TRAN (4UL << 9)
+#define STATUS_DATA (5UL << 9)
+#define STATUS_RCV (6UL << 9)
+#define STATUS_PRG (7UL << 9)
+#define STATUS_DIS (8UL << 9)
+#define STATUS_STATE (0xFUL << 9)
+#define STATUS_ERASE_RESET (1UL << 13)
+#define STATUS_WP_ERASE_SKIP (1UL << 15)
+#define STATUS_CIDCSD_OVERWRITE (1UL << 16)
+#define STATUS_OVERRUN (1UL << 17)
+#define STATUS_UNERRUN (1UL << 18)
+#define STATUS_ERROR (1UL << 19)
+#define STATUS_CC_ERROR (1UL << 20)
+#define STATUS_CARD_ECC_FAILED (1UL << 21)
+#define STATUS_ILLEGAL_COMMAND (1UL << 22)
+#define STATUS_COM_CRC_ERROR (1UL << 23)
+#define STATUS_UN_LOCK_FAILED (1UL << 24)
+#define STATUS_CARD_IS_LOCKED (1UL << 25)
+#define STATUS_WP_VIOLATION (1UL << 26)
+#define STATUS_ERASE_PARAM (1UL << 27)
+#define STATUS_ERASE_SEQ_ERROR (1UL << 28)
+#define STATUS_BLOCK_LEN_ERROR (1UL << 29)
+#define STATUS_ADDRESS_MISALIGN (1UL << 30)
+#define STATUS_ADDR_OUT_OR_RANGE (1UL << 31)
+// R1 response sets
+#define ERROR_STATUS (STATUS_ADDR_OUT_OR_RANGE | STATUS_ADDRESS_MISALIGN | STATUS_BLOCK_LEN_ERROR | STATUS_ERASE_SEQ_ERROR | \
+ STATUS_ERASE_PARAM | STATUS_WP_VIOLATION | STATUS_CARD_IS_LOCKED | STATUS_UN_LOCK_FAILED | \
+ STATUS_COM_CRC_ERROR | STATUS_ILLEGAL_COMMAND | STATUS_CARD_ECC_FAILED | STATUS_CC_ERROR | STATUS_ERROR | \
+ STATUS_UNERRUN | STATUS_OVERRUN | STATUS_CIDCSD_OVERWRITE | STATUS_SWITCH_ERROR)
+// command arguments
+#define CMD0_IDLE_STATE_ARGUMENT 0
+#define CMD1_ACCESS_MODE_SECTOR (1UL << 30)
+#define CMD1_HOST_VOLTAGE_RANGE (OCR_VDD_27_28 | OCR_VDD_28_29 | OCR_VDD_29_30 | OCR_VDD_30_31 | \
+ OCR_VDD_31_32 | OCR_VDD_32_33 | OCR_VDD_33_34 | OCR_VDD_34_35 | \
+ OCR_VDD_35_36)
+#define CMD2_ARGUMENT 0
+#define CMD6_SET_4_LINE_BUS 0x03B70100
+#define CMD6_SET_HS_MODE 0x03B90100
+// relative card address
+#define REVALITE_CARD_ADDRESS (1 << 16)
+// command responses length
+#define NO_RESPONSE_LENGTH 0
+#define R1_RESPONSE_LENGTH 1
+#define R2_RESPONSE_LENGTH 4
+#define R3_RESPONSE_LENGTH 1
+// retry amount of card initialization
+#define RETRY_AMOUNT 10000
+// memory frequency masks for CDS memory register
+#define FREQ_UNITS_MASK 0x07
+#define FREQ_MULTIPLIER_MASK 0x78
+#define FREQ_MULTIPLIER_OFFSET 0x03
+// csd register definitions
+#define CSD_SPEC_VERS_FOUR 4
+
+/******************************************************************************
+ External global variables section
+******************************************************************************/
+/******************************************************************************
+ Types section
+******************************************************************************/
+typedef union
+{
+ uint32_t reg;
+ struct
+ {
+ uint32_t reserved1 : 5;
+ uint32_t appCmd : 1;
+ uint32_t urgentBkops : 1;
+ uint32_t switchError : 1;
+ uint32_t readyForData : 1;
+ uint32_t currentState : 4;
+ uint32_t eraseReset : 1;
+ uint32_t reserved2 : 1;
+ uint32_t wpEraseSkip : 1;
+ uint32_t cidCsdOverwrite : 1;
+ uint32_t overrun : 1;
+ uint32_t underrun : 1;
+ uint32_t error : 1;
+ uint32_t ccEror : 1;
+ uint32_t cardEccFailed : 1;
+ uint32_t illegalCommand : 1;
+ uint32_t comCrcError : 1;
+ uint32_t lockUnlockFailed : 1;
+ uint32_t cardIsLocked : 1;
+ uint32_t wpViolation : 1;
+ uint32_t eraseParam : 1;
+ uint32_t eraseSeqError : 1;
+ uint32_t blockLenError : 1;
+ uint32_t addressMisalign : 1;
+ uint32_t addressOutOfRange: 1;
+ };
+} MmcCardStatus_t;
+
+typedef union
+{
+ uint32_t reg;
+ struct
+ {
+ uint32_t reserverd1 : 7;
+ uint32_t voltage170_195: 1;
+ uint32_t voltage20_26 : 7;
+ uint32_t voltage27_36 : 9;
+ uint32_t reserved2 : 5;
+ uint32_t accessMode : 2;
+ uint32_t busy : 1;
+ };
+} MmcOcrRegister_t;
+
+typedef struct
+{
+ uint8_t tranSpeed;
+ uint8_t nsac;
+ uint8_t taac;
+ uint8_t reserved3 : 2;
+ uint8_t specVersion : 4;
+ uint8_t csdStructure : 2;
+ uint32_t cSizeDown : 10;
+ uint32_t reserved2 : 2;
+ uint32_t dsrImp : 1;
+ uint32_t readBlkMisalign : 1;
+ uint32_t writeBlkMisalign: 1;
+ uint32_t readBlPartial : 1;
+ uint32_t readBlLen : 4;
+ uint32_t ccc : 12;
+ uint32_t wpGroupSize : 5;
+ uint32_t eraseGroupMult : 5;
+ uint32_t eraseGroupSize : 5;
+ uint32_t cSizeMult : 3;
+ uint32_t vddWCurrMax : 3;
+ uint32_t vddWCurrMin : 3;
+ uint32_t vddRCurrMax : 3;
+ uint32_t vddRCurrMin : 3;
+ uint32_t cSizeUp : 2;
+ uint8_t notUsed : 1;
+ uint8_t crc : 7;
+ uint8_t ecc : 2;
+ uint8_t fileFormat : 2;
+ uint8_t tmpWriteProtect : 1;
+ uint8_t permWriteProtect : 1;
+ uint8_t copy : 1;
+ uint8_t fileFormatGroup : 1;
+ uint16_t contentPropApp : 1;
+ uint16_t reserved1 : 4;
+ uint16_t writeBlPartial : 1;
+ uint16_t writeBlLen : 4;
+ uint16_t r2wFactor : 3;
+ uint16_t defaultEcc : 2;
+ uint16_t wpGroupEnable : 1;
+} MmcCSDRegister_t;
+
+/******************************************************************************
+ Constants section
+******************************************************************************/
+static const uint32_t mmcFrequencyUnits[8] = {100, 1000, 10000, 100000, 0, 0, 0, 0};
+static const uint32_t mmcFrequencyMulptiplier[16] = {0, 10, 12, 13, 15, 20, 26, 30, 35, 40, 45, 52, 55, 60, 70, 80};
+
+/******************************************************************************
+ Prototypes section
+******************************************************************************/
+static bool memSendCommand(HAL_HsmciDescriptor_t *descriptor, uint32_t command, uint32_t argument, uint8_t respLength);
+static bool memCheckState(HAL_HsmciDescriptor_t *descriptor, uint16_t state);
+static bool setMaximumCommunicationFrequency(HAL_HsmciDescriptor_t *descriptor, uint8_t freqCode, bool hsMode);
+static MemStatus_t setBusWidthAndHsMode(HAL_HsmciDescriptor_t *descriptor, MmcCSDRegister_t *csdReg);
+static void (*absMemoryCallback)(MemStatus_t) = NULL;
+static HAL_HsmciDescriptor_t *memDescriptor = NULL;
+
+/******************************************************************************
+ Implementations section
+******************************************************************************/
+/**************************************************************************//**
+\brief HSMCI write callback.
+******************************************************************************/
+void memWriteCallback(void)
+{
+ MmcCardStatus_t *cardStatus;
+
+ cardStatus = (MmcCardStatus_t *)(memDescriptor->commandDescriptor->responseBuffer);
+ if (0 != (cardStatus->reg & ERROR_STATUS))
+ absMemoryCallback(hsmciWriteError);
+ absMemoryCallback(memSuccess);
+}
+
+/**************************************************************************//**
+\brief HSMCI read callback.
+******************************************************************************/
+void memReadCallback(void)
+{
+ MmcCardStatus_t *cardStatus;
+
+ cardStatus = (MmcCardStatus_t *)(memDescriptor->commandDescriptor->responseBuffer);
+ if (0 != (cardStatus->reg & ERROR_STATUS))
+ absMemoryCallback(hsmciReadError);
+ absMemoryCallback(memSuccess);
+}
+/**************************************************************************//**
+\brief Performs MMC memory initialization.
+\param[in]
+ commandDescr - pointer to hsmci command descriptor.
+\return
+ status of initialization procedure.
+******************************************************************************/
+MemStatus_t memInit(HAL_HsmciDescriptor_t *descriptor)
+{
+ uint16_t i = RETRY_AMOUNT;
+ MmcCardStatus_t *cardStatus;
+ MmcOcrRegister_t *ocrRegister;
+ MmcCSDRegister_t *csdReg;
+ HAL_HsmciCommandDescriptor_t *commandDescr = descriptor->commandDescriptor;
+ uint32_t sendOpCondResponse;
+ MemStatus_t status;
+
+ /* send first command - CMD0 with power init parameters */
+ if (!memSendCommand(descriptor, POWER_ON_INIT, CMD0_IDLE_STATE_ARGUMENT, NO_RESPONSE_LENGTH))
+ return hsmciError;
+ /* wait for hsmci bus becomes free */
+ while (!HAL_HsmciCheckReady());
+ /* send CMD0 command to go to idle mode */
+ if (!memSendCommand(descriptor, GO_IDLE_STATE, CMD0_IDLE_STATE_ARGUMENT, NO_RESPONSE_LENGTH))
+ return hsmciError;
+ /* wait for hsmci bus becomes free */
+ while (!HAL_HsmciCheckReady());
+ /* wait for internal initialization process */
+ for (; i > 0; i--)
+ {
+ /* send CMD1 command to check host and device voltage correlation */
+ if (!memSendCommand(descriptor, SEND_OP_COND, CMD1_HOST_VOLTAGE_RANGE | CMD1_ACCESS_MODE_SECTOR, R3_RESPONSE_LENGTH))
+ return hsmciError;
+ /* wait for hsmci bus becomes free */
+ while (!HAL_HsmciCheckReady());
+ ocrRegister = (MmcOcrRegister_t *)(commandDescr->responseBuffer);
+ if (!(ocrRegister->reg & CMD1_HOST_VOLTAGE_RANGE))
+ return voltageError;
+ if (0 == ocrRegister->busy)
+ continue;
+ break;
+ }
+ if (0 == i)
+ return initTimeoutError;
+ sendOpCondResponse = commandDescr->responseBuffer[0];
+ i = RETRY_AMOUNT;
+ while (i--)
+ {
+ /* send CMD2 command to get card CID number */
+ if (!memSendCommand(descriptor, ALL_SEND_CID, CMD2_ARGUMENT, R2_RESPONSE_LENGTH))
+ return hsmciError;
+ /* wait for hsmci bus becomes free */
+ while (!HAL_HsmciCheckReady());
+ if (sendOpCondResponse != commandDescr->responseBuffer[0])
+ break;
+ }
+ if (0 == i)
+ return stateError;
+ /* send CMD3 command to set card relative address */
+ if (!memSendCommand(descriptor, SEND_RELATIVE_ADDR, REVALITE_CARD_ADDRESS, R1_RESPONSE_LENGTH))
+ return hsmciError;
+ /* wait for hsmci bus becomes free */
+ while (!HAL_HsmciCheckReady());
+ cardStatus = (MmcCardStatus_t *)(commandDescr->responseBuffer);
+ if (0 != (cardStatus->reg & ERROR_STATUS))
+ return commandError;
+ if (!memCheckState(descriptor, STATUS_STBY))
+ return stateError;
+ /* send CMD9 command to read CSD register */
+ if (!memSendCommand(descriptor, SEND_CSD, REVALITE_CARD_ADDRESS, R2_RESPONSE_LENGTH))
+ return hsmciError;
+ /* wait for hsmci bus becomes free */
+ while (!HAL_HsmciCheckReady());
+ /* read allowed maximum communication frequency and set it */
+ csdReg = (MmcCSDRegister_t *)(commandDescr->responseBuffer);
+ status = setBusWidthAndHsMode(descriptor, csdReg);
+ if (status != memSuccess)
+ return setMaxFreqError;
+
+ return memSuccess;
+}
+
+/**************************************************************************//**
+\brief Reads MMC memory capacity.
+\param[in]
+ descriptor - pointer to hsmci descriptor.
+\param[out]
+ capInfo - pointer to memory capacity structure.
+\return
+ status of read capacity procedure.
+******************************************************************************/
+MemStatus_t memGetCapacityInfo(HAL_HsmciDescriptor_t *descriptor, MemCapacityInfo_t *capInfo)
+{
+ MmcCardStatus_t *cardStatus;
+ MmcCSDRegister_t *csdReg;
+ HAL_HsmciCommandDescriptor_t *commandDescr = descriptor->commandDescriptor;
+
+ /* send CMD13 command to discover current state */
+ if (!memSendCommand(descriptor, SEND_STATUS, REVALITE_CARD_ADDRESS, R1_RESPONSE_LENGTH))
+ return hsmciError;
+ /* wait for hsmci bus becomes free */
+ while (!HAL_HsmciCheckReady());
+
+ cardStatus = (MmcCardStatus_t *)(commandDescr->responseBuffer);
+ if (STATUS_TRAN == (cardStatus->reg & STATUS_TRAN))
+ {
+ /* send CMD7 command to switch to stand-by state*/
+ if (!memSendCommand(descriptor, SELECT_CARD, ~REVALITE_CARD_ADDRESS, R1_RESPONSE_LENGTH))
+ return hsmciError;
+ /* wait for hsmci bus becomes free */
+ while (!HAL_HsmciCheckReady());
+ cardStatus = (MmcCardStatus_t *)(commandDescr->responseBuffer);
+ if (0 != (cardStatus->reg & ERROR_STATUS))
+ return commandError;
+ if (!memCheckState(descriptor, STATUS_STBY))
+ return stateError;
+ }
+ /* send CMD9 command to read CSD register */
+ if (!memSendCommand(descriptor, SEND_CSD, REVALITE_CARD_ADDRESS, R2_RESPONSE_LENGTH))
+ return hsmciError;
+ /* wait for hsmci bus becomes free */
+ while (!HAL_HsmciCheckReady());
+
+ capInfo->logicalBlockLength = STANDARD_BLOCK_LENGTH;
+ csdReg = (MmcCSDRegister_t *)(commandDescr->responseBuffer);
+ capInfo->lastLogicalBlock = (1 << (csdReg->cSizeMult + 2)) * (csdReg->cSizeUp + 1 + (csdReg->cSizeDown << 2)) * ((1 << csdReg->readBlLen) / STANDARD_BLOCK_LENGTH) - 1;
+
+ if (!memCheckState(descriptor, STATUS_STBY))
+ return stateError;
+
+ /* send CMD7 command to switch to transfer state */
+ if (!memSendCommand(descriptor, SELECT_CARD, REVALITE_CARD_ADDRESS, R1_RESPONSE_LENGTH))
+ return hsmciError;
+ /* wait for hsmci bus becomes free */
+ while (!HAL_HsmciCheckReady());
+ cardStatus = (MmcCardStatus_t *)(commandDescr->responseBuffer);
+ if (0 != (cardStatus->reg & ERROR_STATUS))
+ return commandError;
+ if (!memCheckState(descriptor, STATUS_TRAN))
+ return stateError;
+
+ return memSuccess;
+}
+
+/**************************************************************************//**
+\brief Checks MMC memory state.
+\param[in]
+ descriptor - pointer to hsmci descriptor;
+ state - state in which MMC memory meant to be.
+\return
+ false - check failed;
+ true - check success.
+******************************************************************************/
+static bool memSendCommand(HAL_HsmciDescriptor_t *descriptor, uint32_t command, uint32_t argument, uint8_t respLength)
+{
+ descriptor->commandDescriptor->command = command;
+ descriptor->commandDescriptor->argument = argument;
+ descriptor->commandDescriptor->responseLength = respLength;
+
+ if (-1 == HAL_WriteHsmciCommand(descriptor))
+ return false;
+
+ return true;
+}
+
+/**************************************************************************//**
+\brief Sends MMC command.
+\param[in]
+ descriptor - pointer to hsmci descriptor;
+ command - command index and attributes;
+ argument - command argument;
+ respLength - command response length.
+\return
+ false - command sent failed;
+ true - command sent success.
+******************************************************************************/
+static bool memCheckState(HAL_HsmciDescriptor_t *descriptor, uint16_t state)
+{
+ MmcCardStatus_t *cardStatus;
+ /* send CMD13 command to discover current state */
+ if (!memSendCommand(descriptor, SEND_STATUS, REVALITE_CARD_ADDRESS, R1_RESPONSE_LENGTH))
+ return hsmciError;
+ /* wait for hsmci bus becomes free */
+ while (!HAL_HsmciCheckReady());
+ cardStatus = (MmcCardStatus_t *)(descriptor->commandDescriptor->responseBuffer);
+
+ return (cardStatus->reg & STATUS_STATE) == state;
+}
+
+/**************************************************************************//**
+\brief Writes one data block to MMC memory at "address".
+\param[in]
+ descriptor - pointer to hsmci descriptor;
+ address - address of block to write.
+\return
+ status of write procedure.
+******************************************************************************/
+MemStatus_t memWriteBlock(HAL_HsmciDescriptor_t *descriptor, uint32_t address, void (*callback)(MemStatus_t))
+{
+ HAL_HsmciCommandDescriptor_t *commandDescr = descriptor->commandDescriptor;
+ HAL_HsmciDataTransferDescriptor_t *dataDescr = descriptor->dataTransferDescriptor;
+
+ memDescriptor = descriptor;
+
+ if (!memCheckState(descriptor, STATUS_TRAN))
+ return stateError;
+
+ commandDescr->command = WRITE_BLOCK;
+ commandDescr->argument = address << 9;
+ commandDescr->responseLength = R1_RESPONSE_LENGTH;
+
+ dataDescr->direction = HSMCI_WRITE;
+ dataDescr->blockSize = STANDARD_BLOCK_LENGTH;
+ absMemoryCallback = callback;
+ descriptor->callback = memWriteCallback;
+
+ if (-1 == HAL_WriteHsmci(descriptor))
+ return hsmciWriteError;
+
+ return memSuccess;
+}
+
+/**************************************************************************//**
+\brief Reads one data block from MMC memory at "address".
+\param[in]
+ descriptor - pointer to hsmci descriptor;
+ address - address of block to read.
+\return
+ status of read procedure.
+******************************************************************************/
+MemStatus_t memReadBlock(HAL_HsmciDescriptor_t *descriptor, uint32_t address, void (*callback)(MemStatus_t))
+{
+ HAL_HsmciCommandDescriptor_t *commandDescr = descriptor->commandDescriptor;
+ HAL_HsmciDataTransferDescriptor_t *dataDescr = descriptor->dataTransferDescriptor;
+
+ memDescriptor = descriptor;
+
+ if (!memCheckState(descriptor, STATUS_TRAN))
+ return stateError;
+
+ commandDescr->command = READ_SINGLE_BLOCK;
+ commandDescr->argument = address << 9;
+ commandDescr->responseLength = R1_RESPONSE_LENGTH;
+
+ dataDescr->direction = HSMCI_READ;
+ dataDescr->blockSize = STANDARD_BLOCK_LENGTH;
+ absMemoryCallback = callback;
+ descriptor->callback = memReadCallback;
+
+ if (-1 == HAL_ReadHsmci(descriptor))
+ return hsmciReadError;
+
+ return memSuccess;
+}
+
+/**************************************************************************//**
+\brief Checks if MMC memory is ready for any data transfer.
+\return
+ false - memory is busy;
+ true - memory is ready.
+******************************************************************************/
+bool memIsBusy(void)
+{
+ return HAL_HsmciCheckReady();
+}
+
+/**************************************************************************//**
+\brief Sets maximum bus frequency for MMC memory.
+\param[in]
+ descriptor - pointer to hsmci descriptor;
+ freqCode - frequency code.
+\return
+ false - setting failed;
+ true - setting success.
+******************************************************************************/
+static bool setMaximumCommunicationFrequency(HAL_HsmciDescriptor_t *descriptor, uint8_t freqCode, bool hsMode)
+{
+ uint32_t freqUnit = mmcFrequencyUnits[freqCode & FREQ_UNITS_MASK];
+ uint32_t freqMult = mmcFrequencyMulptiplier[(freqCode & FREQ_MULTIPLIER_MASK) >> FREQ_MULTIPLIER_OFFSET];
+
+ descriptor->clockRate = freqUnit * freqMult * 100;
+ if (hsMode)
+ descriptor->clockRate *= 2;
+ if (-1 == HAL_SetHsmciSpeed(descriptor))
+ return false;
+
+ return true;
+}
+
+/**************************************************************************//**
+\brief Sets maximum 4-line dat bus and high speed mode if card supports it.
+\param[in]
+ descriptor - pointer to hsmci descriptor;
+ csdReg - pointer to csd register structure.
+\return
+ status of operation.
+******************************************************************************/
+static MemStatus_t setBusWidthAndHsMode(HAL_HsmciDescriptor_t *descriptor, MmcCSDRegister_t *csdReg)
+{
+ MmcCardStatus_t *cardStatus;
+ uint8_t specVersion = csdReg->specVersion;
+ uint8_t tranSpeed = csdReg->tranSpeed;
+ HAL_HsmciCommandDescriptor_t *commandDescr = descriptor->commandDescriptor;
+
+ /* send CMD7 command to switch to transfer state */
+ if (!memSendCommand(descriptor, SELECT_CARD, REVALITE_CARD_ADDRESS, R1_RESPONSE_LENGTH))
+ return hsmciError;
+ /* wait for hsmci bus becomes free */
+ while (!HAL_HsmciCheckReady());
+ cardStatus = (MmcCardStatus_t *)(commandDescr->responseBuffer);
+ if (0 != (cardStatus->reg & ERROR_STATUS))
+ return commandError;
+ if (!memCheckState(descriptor, STATUS_TRAN))
+ return stateError;
+
+ /* send CMD16 command to set card block length */
+ if (!memSendCommand(descriptor, SET_BLOCKLEN, STANDARD_BLOCK_LENGTH, R1_RESPONSE_LENGTH))
+ return hsmciError;
+ /* wait for hsmci bus becomes free */
+ while (!HAL_HsmciCheckReady());
+ cardStatus = (MmcCardStatus_t *)(commandDescr->responseBuffer);
+ if (0 != (cardStatus->reg & ERROR_STATUS))
+ return commandError;
+ if (!memCheckState(descriptor, STATUS_TRAN))
+ return stateError;
+
+ if (specVersion < CSD_SPEC_VERS_FOUR)
+ {
+ if (!setMaximumCommunicationFrequency(descriptor, tranSpeed, false))
+ return hsmciError;
+ else
+ return memSuccess;
+ }
+
+ /* send CMD6 command to switch to 4-line bus */
+ if (!memSendCommand(descriptor, SWITCH, CMD6_SET_4_LINE_BUS, R1_RESPONSE_LENGTH))
+ return hsmciError;
+ /* wait for hsmci bus becomes free */
+ while (!HAL_HsmciCheckReady());
+ cardStatus = (MmcCardStatus_t *)(commandDescr->responseBuffer);
+ if (0 != (cardStatus->reg & ERROR_STATUS))
+ return commandError;
+ if (!memCheckState(descriptor, STATUS_TRAN))
+ return stateError;
+
+ descriptor->busWidth = HSMCI_BUS_WIDTH_4;
+ if (-1 == HAL_SetHsmciBusWidth(descriptor))
+ return hsmciError;
+
+ /* send CMD6 command to switch to high speed mode */
+ if (!memSendCommand(descriptor, SWITCH, CMD6_SET_HS_MODE, R1_RESPONSE_LENGTH))
+ return hsmciError;
+ /* wait for hsmci bus becomes free */
+ while (!HAL_HsmciCheckReady());
+ cardStatus = (MmcCardStatus_t *)(commandDescr->responseBuffer);
+ if (0 != (cardStatus->reg & ERROR_STATUS))
+ return commandError;
+ if (!memCheckState(descriptor, STATUS_TRAN))
+ return stateError;
+
+ descriptor->highSpeedMode = true;
+ if (-1 == HAL_SetHsmciHighSpeedMode(descriptor))
+ return hsmciError;
+
+ if (!setMaximumCommunicationFrequency(descriptor, tranSpeed, false))
+ return hsmciError;
+
+ return memSuccess;
+}
+
+//eof mmc.c