RabbitECUTeensyMCUXpresso/source/Peripherals/SDHC1HA.c

2881 lines
136 KiB
C

/** ###################################################################
** THIS COMPONENT MODULE IS GENERATED BY THE TOOL. DO NOT MODIFY IT.
** Filename : SDHC1.c
** Project : ProcessorExpert
** Processor : MK60DN512ZVMD10
** Component : SDHC_LDD
** Version : Component 00.001, Driver 01.03, CPU db: 3.00.003
** Compiler : CodeWarrior ARM C Compiler
** Date/Time : 2012-07-29, 21:43, # CodeGen: 371
** Abstract :
** This component implements a SD host controller driver
** interface. Handles control and data transfers to/from
** SD and MMC cards.
** Settings :
** Component name : SDHC1
** Device : SDHC
** Settings :
** Interface : 4-bit data mode
** Bus clock : 390.625 kHz
** Data timeout exponent : 20
** DMA :
** Read watermark : 16
** Write watermark : 16
** Buffers :
** Transfer buffer table size : 8
** Interrupt service/event : Enabled
** SDHC : INT_SDHC
** SDHC priority : medium priority
** Pins : 4-bit data mode
** CLK pin : PTE2/SPI1_SCK/UART1_CTS_b/SDHC0_DCLK/ADC1_SE6a
** CLK pin signal : SD_CLK
** CMD pin : PTE3/SPI1_SIN/UART1_RTS_b/SDHC0_CMD/ADC1_SE7a
** CMD pin signal : SD_CMD
** Data :
** DAT0 pin : PTE1/SPI1_SOUT/UART1_RX/SDHC0_D0/I2C1_SCL/ADC1_SE5a
** DAT0 pin signal : SD_DATA0
** DAT1 : Enabled
** DAT1 pin : PTE0/SPI1_PCS1/UART1_TX/SDHC0_D1/I2C1_SDA/ADC1_SE4a
** DAT1 pin signal : SD_DATA1
** DAT2 : Enabled
** DAT2 pin : PTE5/SPI1_PCS2/UART3_RX/SDHC0_D2
** DAT2 pin signal : SD_DATA2
** DAT3 : Enabled
** DAT3 pin : PTE4/SPI1_PCS0/UART3_TX/SDHC0_D3
** DAT3 pin signal : SD_DATA3
** Initialization :
** Enable device : yes
** Auto initialization : no
** Event mask :
** OnCardInserted : Enabled
** OnCardRemoved : Enabled
** OnFinished : Enabled
** CPU clock/configuration selection :
** Clock configuration 0 : This component enabled
** Clock configuration 1 : This component disabled
** Clock configuration 2 : This component disabled
** Contents :
** Init - LDD_TDeviceData* SDHC1_Init(LDD_TUserData *UserDataPtr);
** Deinit - void SDHC1_Deinit(LDD_TDeviceData *DeviceDataPtr);
** Enable - LDD_TError SDHC1_Enable(LDD_TDeviceData *DeviceDataPtr);
** Disable - LDD_TError SDHC1_Disable(LDD_TDeviceData *DeviceDataPtr);
** SetEventMask - LDD_TError SDHC1_SetEventMask(LDD_TDeviceData *DeviceDataPtr, LDD_TEventMask...
** GetEventMask - LDD_TEventMask SDHC1_GetEventMask(LDD_TDeviceData *DeviceDataPtr);
** DetectCards - LDD_TError SDHC1_DetectCards(LDD_TDeviceData *DeviceDataPtr);
** SelectCard - LDD_TError SDHC1_SelectCard(LDD_TDeviceData *DeviceDataPtr, uint8_t Id);
** GetCardInfo - LDD_TError SDHC1_GetCardInfo(LDD_TDeviceData *DeviceDataPtr,...
** TransferBlocks - LDD_TError SDHC1_TransferBlocks(LDD_TDeviceData *DeviceDataPtr,...
** EraseBlocks - LDD_TError SDHC1_EraseBlocks(LDD_TDeviceData *DeviceDataPtr, uint32_t...
** SetDataWidth - LDD_TError SDHC1_SetDataWidth(LDD_TDeviceData *DeviceDataPtr, uint8_t Width);
** SelectBusClock - LDD_TError SDHC1_SelectBusClock(LDD_TDeviceData *DeviceDataPtr,...
** SetVoltage - LDD_TError SDHC1_SetVoltage(LDD_TDeviceData *DeviceDataPtr, LDD_SDHC_TVoltage...
** SetWriteProtection - LDD_TError SDHC1_SetWriteProtection(LDD_TDeviceData *DeviceDataPtr,...
** GetWriteProtection - LDD_TError SDHC1_GetWriteProtection(LDD_TDeviceData *DeviceDataPtr, uint32_t...
** CancelOperation - LDD_TError SDHC1_CancelOperation(LDD_TDeviceData *DeviceDataPtr);
** GetStatus - LDD_SDHC_TStatus SDHC1_GetStatus(LDD_TDeviceData *DeviceDataPtr);
** GetError - LDD_SDHC_TError SDHC1_GetError(LDD_TDeviceData *DeviceDataPtr, uint32_t...
** ConnectPin - LDD_TError SDHC1_ConnectPin(LDD_TDeviceData *DeviceDataPtr, LDD_TPinMask...
** SetOperationMode - LDD_TError SDHC1_SetOperationMode(LDD_TDeviceData *DeviceDataPtr,...
** GetDriverState - LDD_TDriverState SDHC1_GetDriverState(LDD_TDeviceData *DeviceDataPtr);
**
** Copyright : 1997 - 2011 Freescale Semiconductor, Inc. All Rights Reserved.
**
** http : www.freescale.com
** mail : support@freescale.com
** ###################################################################*/
/* MODULE SDHC1 */
/*lint -save -esym(960,10.1) -e961 Disable MISRA rule (10.1,12.1) checking. */
#include <DECLARATIONS.h>
#include <string.h>
#include <SDHC1HA.h>
#include <SDHCHA.h>
#include "sdhc.h"
#include "mk64f12.h"
#include "sim.h"
#include "irq.h"
LDD_SDHC1_TDeviceData SDHC1_stDeviceData;
/* {FreeRTOS RTOS Adapter} Global variable used for passing a parameter into ISR */
static LDD_SDHC1_TDeviceData* INT_SDHC__BAREBOARD_RTOS_ISRPARAM;
/* Internal method prototypes */
static void VoltageValidation(LDD_SDHC1_TDeviceData *DeviceDataPtr, uint32_t Flags, uint32_t *Response);
static void CardRegistration(LDD_SDHC1_TDeviceData *DeviceDataPtr, uint32_t Flags, uint32_t *Response);
static void CardInfoRetrieval(LDD_SDHC1_TDeviceData *DeviceDataPtr, uint32_t Flags, uint32_t *Response);
static bool CardSelection(LDD_SDHC1_TDeviceData *DeviceDataPtr, uint32_t Flags, uint32_t *Response);
static bool Transfer(LDD_SDHC1_TDeviceData *DeviceDataPtr, uint32_t Flags, uint32_t *Response);
static bool Erasion(LDD_SDHC1_TDeviceData *DeviceDataPtr, uint32_t Flags, uint32_t *Response);
static bool DataWidthSelection(LDD_SDHC1_TDeviceData *DeviceDataPtr, uint32_t Flags, uint32_t *Response);
static bool BusClockSelection(LDD_SDHC1_TDeviceData *DeviceDataPtr, uint32_t Flags, uint32_t *Response);
static bool WriteProtectionSetup(LDD_SDHC1_TDeviceData *DeviceDataPtr, uint32_t Flags, uint32_t *Response);
static bool WriteProtectionRetrieval(LDD_SDHC1_TDeviceData *DeviceDataPtr, uint32_t Flags, uint32_t *Response);
static void SetBusClockPrescalers(LDD_SDHC1_TDeviceData *DeviceDataPtr, SDHC1_TBusClock Frequency);
static LDD_SDHC_TError GetCommandError(LDD_SDHC1_TDeviceData *DeviceDataPtr, uint32_t Flags, uint32_t *Response);
static void SendCardStatusRequest(LDD_SDHC1_TDeviceData *DeviceDataPtr);
static void EventHandler(LDD_SDHC1_TDeviceData *DeviceDataPtr);
/*
** ===================================================================
** Method : SDHC1_Init (component SDHC_LDD)
**
** Description :
** Initializes the device. Allocates memory for the device data
** structure, allocates interrupt vectors and sets interrupt
** priority, sets pin routing, sets timing, etc. If the
** property <"Enable device"> is set to "yes" then the device
** is also enabled (see the description of the <Enable> method).
** In this case the <Enable> method is not necessary and need
** not to be generated. This method can be called only once.
** Before the second call of Init the <Deinit> method must be
** called first.
** Parameters :
** NAME - DESCRIPTION
** * UserDataPtr - Pointer to user data
** structure pointer.
** Returns :
** --- - Pointer to the device data structure.
** ===================================================================
*/
LDD_SDHC1_TDeviceData* SDHC1_Init(LDD_TUserData *UserDataPtr)
{
LDD_SDHC1_TDeviceData *DeviceDataPrv;
uint8_t Id;
/* {FreeRTOS RTOS Adapter} Driver memory allocation: RTOS function call is defined by FreeRTOS RTOS Adapter property */
//DeviceDataPrv = (LDD_SDHC1_TDeviceData *)pvPortMalloc(sizeof(LDD_SDHC1_TDeviceData));
DeviceDataPrv = &SDHC1_stDeviceData;
#if FreeRTOS_CHECK_MEMORY_ALLOCATION_ERRORS
if (DeviceDataPrv == NULL) {
return (NULL);
}
#endif
/* Initialize the device data */
DeviceDataPrv->UserDataPtr = UserDataPtr; /* Store the user data pointer */
DeviceDataPrv->CardId = SDHC1_NO_CARD; /* No card will be selected */
DeviceDataPrv->State = LDD_SDHC_RESET; /* Cards will be reseted after host initialization */
DeviceDataPrv->HighVoltage = TRUE; /* Initially set bus voltage to high */
DeviceDataPrv->LastError = LDD_SDHC_ERR_OK; /* Clear the error code */
for (Id = 0; Id < SDHC1_MAX_CARD_NUMBER; Id++) {
DeviceDataPrv->Cards[Id].Initialized = FALSE;
}
DeviceDataPrv->TransferTable = (SDHC1_TTransferBufferDesc*) /* Align transfer buffer table memory according to hardware requirements */
(((uint32_t)DeviceDataPrv->TransferTableMem + SDHC1_TRANSFER_TABLE_ALIGN) & (uint32_t)(~(uint32_t)(SDHC1_TRANSFER_TABLE_ALIGN - 1U)));
DeviceDataPrv->CSDPtr = (uint8_t*) /* Align CSD (card specific data) card register buffer according to hardware requirements */
(((uint32_t)DeviceDataPrv->CSDMem + SDHC1_TRANSFER_BUFFER_ALIGN) & (uint32_t)(~(uint32_t)(SDHC1_TRANSFER_BUFFER_ALIGN - 1U)));
DeviceDataPrv->BusTestPtr = (uint8_t*) /* Align bus test buffer according to hardware requirements */
(((uint32_t)DeviceDataPrv->BusTestMem + SDHC1_TRANSFER_BUFFER_ALIGN) & (uint32_t)(~(uint32_t)(SDHC1_TRANSFER_BUFFER_ALIGN - 1U)));
DeviceDataPrv->DataWidth = LDD_SDHC_CARD_DATA_WIDTH_4_BIT; /* Set default data width */
DeviceDataPrv->Cancel = FALSE; /* Clear the cancel flag */
DeviceDataPrv->SpeedMode = CPU_CLOCK_CONFIG_0; /* Set initial clock configuration */
DeviceDataPrv->EventMask = /* Initialize the event mask */
LDD_SDHC_ON_CARD_INSERTED |
LDD_SDHC_ON_CARD_REMOVED |
LDD_SDHC_ON_FINISHED |0U;
DeviceDataPrv->EnabledMode = TRUE; /* Enable the device clock configuration */
/* SIM_SCGC3: SDHC=1 */
SIM_vSetReg32( SIM_SCGC3, SIM_SCGC3_SDHC_MASK ); //SIM_SCGC3 |= (uint32_t)0x00020000UL;
/* initialise hardware ports */
SDHC_vHWInit();
/* Configure card detection and DMA mode */
/* SDHC_PROCTL: ??=0,??=0,??=0,??=0,??=0,WECRM=0,WECINS=0,WECINT=0,??=0,??=0,??=0,??=0,IABG=0,RWCTL=0,CREQ=0,SABGREQ=0,??=0,??=0,??=0,??=0,??=0,??=0,DMAS=2,CDSS=0,CDTL=0,EMODE=2,D3CD=0,DTW=0,LCTL=0 */
SDHC_PROCTL = (uint32_t)0x0220UL;
/* Set DMA watermark levels */
/* SDHC_WML: ??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,WRWML=0x10,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,RDWML=0x10 */
SDHC_WML = (uint32_t)0x00100010UL;
/* SDHC_VENDOR: ??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,INTSTVAL=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,EXBLKNU=0,EXTDMAEN=0 */
SDHC_VENDOR = (uint32_t)0x00UL;
/* SIM_SOPT2: SDHCSRC=0 */
SIM_vClrReg32( SIM_SOPT2, SIM_SOPT2_SDHCSRC_MASK ); //SIM_SOPT2 &= (uint32_t)~0x30000000UL;
/* Set bus clock frequency and data timeout */
/* SDHC_SYSCTL: ??=0,??=0,??=0,??=0,INITA=0,RSTD=0,RSTC=0,RSTA=0,??=0,??=0,??=0,??=0,DTOCV=7,SDCLKFS=0x40,DVS=0,SDCLKEN=0,PEREN=0,HCKEN=0,IPGEN=0 */
SDHC_SYSCTL = (uint32_t)0x00074000UL;
while (!SDHC_PDD_IsSDClockStable(SDHC_BASE_PTR)) {} /* Wait for clock to stabilize */
/* Set interrupt priorities */
/* NVICIP80: PRI80=0x80 */
IRQ_vEnableIRQ(SDHC_IRQn, IRQ_enPRIO_15, NULL, NULL); //NVICIP80 = (uint8_t)0x80U;
/* NVICISER2: SETENA|=0x00010000 */
//NVICISER2 |= (uint32_t)0x00010000UL;
/* Allocate the interrupt vector */
/* {FreeRTOS RTOS Adapter} Set interrupt vector: IVT is static, ISR parameter is passed by the global variable */
INT_SDHC__BAREBOARD_RTOS_ISRPARAM = DeviceDataPrv;
/* Enable and clear status flags */
/* SDHC_IRQSTAT: ??=1,??=1,??=1,DMAE=1,??=1,??=1,??=1,AC12E=1,??=1,DEBE=1,DCE=1,DTOE=1,CIE=1,CEBE=1,CCE=1,CTOE=1,??=1,??=1,??=1,??=1,??=1,??=1,??=1,CINT=1,CRM=1,CINS=1,BRR=1,BWR=1,DINT=1,BGE=1,TC=1,CC=1 */
SDHC_IRQSTAT = (uint32_t)0xFFFFFFFFUL;
/* SDHC_IRQSIGEN: ??=0,??=0,??=0,DMAEIEN=0,??=0,??=0,??=0,AC12EIEN=0,??=0,DEBEIEN=0,DCEIEN=0,DTOEIEN=0,CIEIEN=0,CEBEIEN=0,CCEIEN=0,CTOEIEN=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,CINTIEN=0,CRMIEN=0,CINSIEN=0,BRRIEN=0,BWRIEN=0,DINTIEN=0,BGEIEN=0,TCIEN=1,CCIEN=1 */
//SDHC_IRQSIGEN = (uint32_t)0x03UL;
/* SDHC_IRQSTATEN: ??=1,??=1,??=1,DMAESEN=1,??=1,??=1,??=1,AC12ESEN=1,??=1,DEBESEN=1,DCESEN=1,DTOESEN=1,CIESEN=1,CEBESEN=1,CCESEN=1,CTOESEN=1,??=1,??=1,??=1,??=1,??=1,??=1,??=1,CINTSEN=1,CRMSEN=0,CINSEN=0,BRRSEN=0,BWRSEN=0,DINTSEN=1,BGESEN=1,TCSEN=1,CCSEN=1 */
SDHC_IRQSTATEN = (uint32_t)0xFFFFFF0FUL;
/* Power up cards */
SDHC_PDD_InitCard(SDHC_BASE_PTR);
/* SDHC_IRQSIGEN: ??=0,??=0,??=0,DMAEIEN=0,??=0,??=0,??=0,AC12EIEN=0,??=0,DEBEIEN=0,DCEIEN=0,DTOEIEN=0,CIEIEN=0,CEBEIEN=0,CCEIEN=0,CTOEIEN=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,CINTIEN=0,CRMIEN=0,CINSIEN=0,BRRIEN=0,BWRIEN=0,DINTIEN=0,BGEIEN=0,TCIEN=1,CCIEN=1 */
SDHC_IRQSIGEN = (uint32_t)0x03UL;
while (!SDHC_PDD_IsCardInitComplete(SDHC_BASE_PTR)) {}
/* Set transfer timeout to 7 */
SDHC_SYSCTL |= SDHC_SYSCTL_DTOCV(SDHCHA_nTransferTimeoutExponent);
/* Reset cards */
SDHC_PDD_SetCommandArgument(SDHC_BASE_PTR, 0U);
SDHC_PDD_SendCommand(SDHC_BASE_PTR,
SDHC_PDD_CMD0_GO_IDLE_STATE, SDHC_PDD_NO_RESPONSE);
DeviceDataPrv->Enabled = TRUE; /* Enable the component */
//MATTHEW
//DeviceDataPrv->State = LDD_SDHC_IDLE;
/* Registration of the device structure */
PE_LDD_RegisterDeviceStructure(PE_LDD_COMPONENT_SDHC1_ID,DeviceDataPrv);
return DeviceDataPrv;
}
/*
** ===================================================================
** Method : SDHC1_Deinit (component SDHC_LDD)
**
** Description :
** Deinitializes the device. Switches off the device, frees the
** device data structure memory, interrupt vectors, etc.
** Parameters :
** NAME - DESCRIPTION
** * DeviceDataPtr - Pointer to the device
** data structure.
** Returns : Nothing
** ===================================================================
*/
void SDHC1_Deinit(LDD_SDHC1_TDeviceData *DeviceDataPtr)
{
LDD_SDHC1_TDeviceData *DeviceDataPrv = (LDD_SDHC1_TDeviceData*)DeviceDataPtr;
(void)DeviceDataPrv; /* Suppress unused variable warning if needed */
/* Disable interrupts */
SDHC_IRQSIGEN = 0x00;
SDHC_IRQSTATEN = 0x00;
/* {FreeRTOS RTOS Adapter} Restore interrupt vector: IVT is static, no code is generated */
/* Disable the device clock */
SDHC_PDD_EnableSDHCClock(SDHC_BASE_PTR, PDD_DISABLE);
/* Reset the device */
SDHC_PDD_ResetDevice(SDHC_BASE_PTR);
/* Unregistration of the device structure */
//PE_LDD_UnregisterDeviceStructure(PE_LDD_COMPONENT_SDHC1_ID);
/* Deallocation of the internal device data structure */
/* {FreeRTOS RTOS Adapter} Driver memory deallocation: RTOS function call is defined by FreeRTOS RTOS Adapter property */
//vPortFree(DeviceDataPrv);
/* SIM_SCGC3: SDHC=0 */
SIM_vClrReg32( SIM_SCGC3, SIM_SCGC3_SDHC_MASK ); //SIM_SCGC3 &= (uint32_t)~0x00020000UL;
}
/*
** ===================================================================
** Method : SDHC1_Enable (component SDHC_LDD)
**
** Description :
** Enables the component.
** Parameters :
** NAME - DESCRIPTION
** * DeviceDataPtr - Pointer to the device
** data structure.
** Returns :
** --- -
** Error code, possible values:
** ERR_OK - OK
** ===================================================================
*/
LDD_TError SDHC1_Enable(LDD_SDHC1_TDeviceData *DeviceDataPtr)
{
LDD_SDHC1_TDeviceData *DeviceDataPrv = (LDD_SDHC1_TDeviceData*)DeviceDataPtr;
DeviceDataPrv->Enabled = TRUE; /* Enable the component */
return ERR_OK;
}
/*
** ===================================================================
** Method : SDHC1_Disable (component SDHC_LDD)
**
** Description :
** Disables the component.
** Parameters :
** NAME - DESCRIPTION
** * DeviceDataPtr - Pointer to the device
** data structure.
** Returns :
** --- -
** Error code, possible values:
** ERR_OK - OK
** ===================================================================
*/
LDD_TError SDHC1_Disable(LDD_SDHC1_TDeviceData *DeviceDataPtr)
{
LDD_SDHC1_TDeviceData *DeviceDataPrv = (LDD_SDHC1_TDeviceData*)DeviceDataPtr;
DeviceDataPrv->Enabled = FALSE; /* Disable the component */
return ERR_OK;
}
/*
** ===================================================================
** Method : SDHC1_SetEventMask (component SDHC_LDD)
**
** Description :
** Sets event mask.
** Parameters :
** NAME - DESCRIPTION
** * DeviceDataPtr - Pointer to the device
** data structure.
** EventMask - Event mask
** Returns :
** --- -
** Error code, possible values:
** ERR_OK - OK
** ERR_DISABLED - The component is disabled
** ERR_SPEED - The component does not work in
** the active clock configuration
** ERR_PARAM_MASK - Invalid mask (one or more
** event is unmaskable)
** ===================================================================
*/
LDD_TError SDHC1_SetEventMask(LDD_SDHC1_TDeviceData *DeviceDataPtr, LDD_TEventMask EventMask)
{
LDD_SDHC1_TDeviceData *DeviceDataPrv = (LDD_SDHC1_TDeviceData*)DeviceDataPtr;
/* Device state test - this test can be disabled by setting the "Ignore enable test"
property to the "yes" value in the "Configuration inspector" */
if (!DeviceDataPrv->Enabled) {
return ERR_DISABLED;
}
if ((EventMask & (LDD_TEventMask)(~(LDD_TEventMask)(
LDD_SDHC_ON_CARD_INSERTED | LDD_SDHC_ON_CARD_REMOVED | LDD_SDHC_ON_FINISHED))) != 0U) {
return ERR_PARAM_MASK;
}
DeviceDataPrv->EventMask = EventMask;
return ERR_OK;
}
/*
** ===================================================================
** Method : SDHC1_GetEventMask (component SDHC_LDD)
**
** Description :
** Returns event mask.
** Parameters :
** NAME - DESCRIPTION
** * DeviceDataPtr - Pointer to the device
** data structure.
** Returns :
** --- - Current event mask.
** ===================================================================
*/
LDD_TEventMask SDHC1_GetEventMask(LDD_SDHC1_TDeviceData *DeviceDataPtr)
{
LDD_SDHC1_TDeviceData *DeviceDataPrv = (LDD_SDHC1_TDeviceData*)DeviceDataPtr;
return DeviceDataPrv->EventMask;
}
/*
** ===================================================================
** Method : SDHC1_DetectCards (component SDHC_LDD)
**
** Description :
** Detects newly inserted and removed cards. The OnCardInserted
** event will be called for every new card and the
** OnCardRemoved event will be called for every removed card.
** This method should be used when card detection pin is not
** available.
** Parameters :
** NAME - DESCRIPTION
** * DeviceDataPtr - Pointer to the device
** data structure.
** Returns :
** --- -
** Error code, possible values:
** ERR_OK - Card detection started
** ERR_DISABLED - The component is disabled
** ERR_SPEED - The component does not work in
** the active clock configuration
** ERR_BUSY - Another card operation is in
** progress
** ===================================================================
*/
LDD_TError SDHC1_DetectCards(LDD_SDHC1_TDeviceData *DeviceDataPtr)
{
LDD_SDHC1_TDeviceData *DeviceDataPrv = (LDD_SDHC1_TDeviceData*)DeviceDataPtr;
LDD_TError Result = ERR_OK; /* Error code storage */
/* Device state test - this test can be disabled by setting the "Ignore enable test"
property to the "yes" value in the "Configuration inspector" */
if (!DeviceDataPrv->Enabled) {
return ERR_DISABLED;
}
if (DeviceDataPrv->State == LDD_SDHC_IDLE) {
DeviceDataPrv->Cancel = FALSE; /* Clear the cancel flag */
DeviceDataPrv->LastError = LDD_SDHC_ERR_OK; /* Clear the error code */
DeviceDataPrv->LastErrorAddress = 0U; /* Clear the error address */
DeviceDataPrv->State = LDD_SDHC_VOLTAGE_VALIDATION;
DeviceDataPrv->Substate = SDHC1_VV_START;
VoltageValidation(DeviceDataPrv, 0U, SDHC1_NO_RESPONSE); /* Handle the voltage validation state */
} else {
Result = ERR_BUSY; /* Another operation is in progress */
}
return Result;
}
/*
** ===================================================================
** Method : SDHC1_SelectCard (component SDHC_LDD)
**
** Description :
** Selects a card by its identification number. All further
** operations will apply to this card. Special card
** identification number <compId>_NO_CARD will deselect the
** active card.
** Parameters :
** NAME - DESCRIPTION
** * DeviceDataPtr - Pointer to the device
** data structure.
** Id - Card identification number passed by the
** OnCardInserted event parameter.
** Returns :
** --- -
** Error code, possible values:
** ERR_OK - Card selection started
** ERR_DISABLED - The component is disabled
** ERR_SPEED - The component does not work in
** the active clock configuration
** ERR_BUSY - Another card operation is in
** progress
** ERR_PARAM_ID - Invalid card ID
** ===================================================================
*/
LDD_TError SDHC1_SelectCard(LDD_SDHC1_TDeviceData *DeviceDataPtr, uint8_t Id)
{
LDD_SDHC1_TDeviceData *DeviceDataPrv = (LDD_SDHC1_TDeviceData*)DeviceDataPtr;
LDD_TError Result = ERR_OK; /* Error code storage */
uint32_t Argument; /* Card command argument */
/* Device state test - this test can be disabled by setting the "Ignore enable test"
property to the "yes" value in the "Configuration inspector" */
if (!DeviceDataPrv->Enabled) {
return ERR_DISABLED;
}
if (Id != SDHC1_NO_CARD) {
if (!DeviceDataPrv->Cards[Id].Initialized) {
return ERR_PARAM_ID;
}
}
if (DeviceDataPrv->State == LDD_SDHC_IDLE) {
DeviceDataPrv->Cancel = FALSE; /* Clear the cancel flag */
DeviceDataPrv->LastError = LDD_SDHC_ERR_OK; /* Clear the error code */
DeviceDataPrv->LastErrorAddress = 0U; /* Clear the error address */
if (Id != DeviceDataPrv->CardId) { /* Reselecting already selected card is an illegal card operation */
/* Change card selection */
DeviceDataPrv->CardId = Id;
if (Id != SDHC1_NO_CARD) { /* Select card */
DeviceDataPrv->CardType = DeviceDataPrv->Cards[Id].Type; /* Store currently selected card's type */
Argument = SDHC1_CMD_ARG_RCA((uint32_t)DeviceDataPrv->Cards[Id].RCA); /* Select card by its RCA */
} else { /* Unselect card */
Argument = 0U; /* Zero is a special RCA (relative card address) for deselecting all cards */
}
DeviceDataPrv->State = LDD_SDHC_CARD_SELECTION;
/* Send card selection command */
SDHC_PDD_SetCommandArgument(SDHC_BASE_PTR, Argument);
SDHC_PDD_SendCommand(SDHC_BASE_PTR,
SDHC_PDD_CMD7_SELECT_CARD, SDHC_PDD_RESPONSE_LENGTH_48_BUSY_CHECK);
}
} else {
Result = ERR_BUSY; /* Another operation is in progress */
}
return Result;
}
/*
** ===================================================================
** Method : SDHC1_GetCardInfo (component SDHC_LDD)
**
** Description :
** Returns card information about the selected card. Method
** call starts the card information retrieval process. After
** the card information has been received, the OnFinished event
** is called (the component state changes to idle) and the
** information is stored in the specified variable.
** Parameters :
** NAME - DESCRIPTION
** * DeviceDataPtr - Pointer to the device
** data structure.
** * InfoPtr - Pointer to a variable, where card
** information will be stored.
** Returns :
** --- -
** Error code, possible values:
** ERR_OK - Card information retrieval started
** ERR_DISABLED - The component is disabled
** ERR_SPEED - The component does not work in
** the active clock configuration
** ERR_BUSY - Another card operation is in
** progress
** ===================================================================
*/
LDD_TError SDHC1_GetCardInfo(LDD_SDHC1_TDeviceData *DeviceDataPtr, LDD_SDHC_TCardInfo *InfoPtr)
{
LDD_SDHC1_TDeviceData *DeviceDataPrv = (LDD_SDHC1_TDeviceData*)DeviceDataPtr;
LDD_TError Result = ERR_OK; /* Error code storage */
/* Device state test - this test can be disabled by setting the "Ignore enable test"
property to the "yes" value in the "Configuration inspector" */
if (!DeviceDataPrv->Enabled) {
return ERR_DISABLED;
}
if (DeviceDataPrv->State == LDD_SDHC_IDLE) {
DeviceDataPrv->Cancel = FALSE; /* Clear the cancel flag */
DeviceDataPrv->LastError = LDD_SDHC_ERR_OK; /* Clear the error code */
DeviceDataPrv->LastErrorAddress = 0U; /* Clear the error address */
DeviceDataPrv->CardInfoPtr = InfoPtr; /* Store a pointer to the card info variable for later card info update */
/* Start card information retrieval */
DeviceDataPrv->State = LDD_SDHC_CARD_INFO_RETRIEVAL;
DeviceDataPrv->Substate = SDHC1_CIR_START;
CardInfoRetrieval(DeviceDataPrv, 0U, SDHC1_NO_RESPONSE); /* Handle the card info retrieval state */
} else {
Result = ERR_BUSY; /* Another operation is in progress */
}
return Result;
}
/*
** ===================================================================
** Method : SDHC1_TransferBlocks (component SDHC_LDD)
**
** Description :
** Initiates a data block transfer on the selected card.
** Transfer can be a read or write operation depending on the
** transfer operation parameter. Read operation reads data
** blocks from the specified address on a memory card and
** stores their content into buffers specified by the buffer
** descriptor list. Write operation writes data blocks
** specified by the buffer descriptor list to a card memory on
** the specified address. Data blocks should be the same size
** and the block size should be supported by the memory card.
** Buffer addresses should be aligned to a hardware specific
** address boundary.
** Parameters :
** NAME - DESCRIPTION
** * DeviceDataPtr - Pointer to the device
** data structure.
** Operation - Transfer operation
** Address - Card memory address. Byte address
** in case of standard capacity memory cards,
** 512 byte block number in case of high
** capacity memory cards.
** * BufferDescListPtr - Pointer to
** data block buffer descriptor list.
** BufferDescCount - Data block buffer
** descriptor list item count
** Returns :
** --- -
** Error code, possible values:
** ERR_OK - Transfer started
** ERR_DISABLED - The component is disabled
** ERR_SPEED - The component does not work in
** the active clock configuration
** ERR_BUSY - Another card operation is in
** progress
** ERR_PARAM_ADDRESS - Invalid buffer address
** (one or more buffer address from the list
** of buffer descriptors is misaligned)
** ERR_PARAM_BUFFER_COUNT - Buffer count
** exceeds the internal buffer table size
** ===================================================================
*/
LDD_TError SDHC1_TransferBlocks(LDD_SDHC1_TDeviceData *DeviceDataPtr, LDD_SDHC_TTransferOperation Operation, uint32_t Address, LDD_SDHC_TBufferDesc *BufferDescListPtr, uint16_t BufferDescCount)
{
LDD_SDHC1_TDeviceData *DeviceDataPrv = (LDD_SDHC1_TDeviceData*)DeviceDataPtr;
LDD_TError Result = ERR_OK; /* Error code storage */
uint32_t Index; /* Transfer table index */
bool Finished; /* Indicates whether transfer has finished */
/* Device state test - this test can be disabled by setting the "Ignore enable test"
property to the "yes" value in the "Configuration inspector" */
if (!DeviceDataPrv->Enabled) {
return ERR_DISABLED;
}
if ((BufferDescCount == 0U) || (BufferDescCount > SDHC1_BUFFER_TABLE_SIZE)) {
return ERR_PARAM_BUFFER_COUNT;
}
if (DeviceDataPrv->State == LDD_SDHC_IDLE) {
DeviceDataPrv->Cancel = FALSE; /* Clear the cancel flag */
DeviceDataPrv->LastError = LDD_SDHC_ERR_OK; /* Clear the error code */
DeviceDataPrv->LastErrorAddress = 0U; /* Clear the error address */
DeviceDataPrv->TransferBlockSize = BufferDescListPtr[0].Size; /* Determine block size from first buffer size */
DeviceDataPrv->TransferBlockCount = BufferDescCount; /* Determine block count from buffer count */
/* Fill in the transfer descriptors table */
for (Index = 0U; Index < BufferDescCount; Index++) {
DeviceDataPrv->TransferTable[Index].Attributes = /* Mark each transfer buffer descriptor as ready for transfer */
SDHC1_ADMA2_VALID | SDHC1_ADMA2_ATTR_ACT_TRAN;
DeviceDataPrv->TransferTable[Index].Length = BufferDescListPtr[Index].Size; /* Copy transfer buffer size */
DeviceDataPrv->TransferTable[Index].Address = (uint32_t)BufferDescListPtr[Index].DataPtr; /* Copy transfer buffer address */
}
DeviceDataPrv->TransferTable[BufferDescCount - 1U].Attributes |= SDHC1_ADMA2_END; /* Mark the last descriptor as last */
DeviceDataPrv->TransferOperation = Operation; /* Store the transfer operation type */
DeviceDataPrv->Address = Address; /* Store the source/destination address for the read/write operation */
/* Start data transfer */
DeviceDataPrv->State = LDD_SDHC_TRANSFER;
DeviceDataPrv->CmdState = SDHC1_CMD_DATA_LEN;
Finished = Transfer(DeviceDataPrv, 0U, SDHC1_NO_RESPONSE); /* Handle the transfer state */
(void)Finished; /* The return value is not used */
} else {
Result = ERR_BUSY; /* Another operation is in progress */
}
return Result;
}
/*
** ===================================================================
** Method : SDHC1_EraseBlocks (component SDHC_LDD)
**
** Description :
** Initiates a memory area erasion on the selected card. Erase
** operation erases a memory area of the specified size from
** the specified address on a memory card.
** Parameters :
** NAME - DESCRIPTION
** * DeviceDataPtr - Pointer to the device
** data structure.
** Address - Address of the beginning of the
** erased area. Byte address in case of
** standard capacity memory card and 512 byte
** block number in case of high capacity
** memory card.
** Size - Size of the erased area. Byte size in
** case of standard capacity memory card and
** 512 byte blocks count in case of high
** capacity memory card.
** Returns :
** --- -
** Error code, possible values:
** ERR_OK - Erasing started
** ERR_DISABLED - The component is disabled
** ERR_SPEED - The component does not work in
** the active clock configuration
** ERR_BUSY - Another card operation is in
** progress
** ===================================================================
*/
LDD_TError SDHC1_EraseBlocks(LDD_SDHC1_TDeviceData *DeviceDataPtr, uint32_t Address, uint32_t Size)
{
LDD_SDHC1_TDeviceData *DeviceDataPrv = (LDD_SDHC1_TDeviceData*)DeviceDataPtr;
LDD_TError Result = ERR_OK; /* Error code storage */
bool Finished; /* Indicates whether erasion has finished */
/* Device state test - this test can be disabled by setting the "Ignore enable test"
property to the "yes" value in the "Configuration inspector" */
if (!DeviceDataPrv->Enabled) {
return ERR_DISABLED;
}
if (DeviceDataPrv->State == LDD_SDHC_IDLE) {
DeviceDataPrv->Cancel = FALSE; /* Clear the cancel flag */
DeviceDataPrv->LastError = LDD_SDHC_ERR_OK; /* Clear the error code */
DeviceDataPrv->LastErrorAddress = 0U; /* Clear the error address */
DeviceDataPrv->ErasionStart = Address; /* Store the erasion start address */
DeviceDataPrv->ErasionEnd = (Address + Size) - 1U; /* Count the erasion end address */
/* Start data erasion */
DeviceDataPrv->State = LDD_SDHC_ERASION;
DeviceDataPrv->Substate = SDHC1_E_SET_START;
Finished = Erasion(DeviceDataPrv, 0U, SDHC1_NO_RESPONSE); /* Handle the erasion state */
(void)Finished; /* The return value is not used */
} else {
Result = ERR_BUSY; /* Another operation is in progress */
}
return Result;
}
/*
** ===================================================================
** Method : SDHC1_SetDataWidth (component SDHC_LDD)
**
** Description :
** Initiates a data width setup. The card has to support the
** specified data width.
** Parameters :
** NAME - DESCRIPTION
** * DeviceDataPtr - Pointer to the device
** data structure.
** Width - Data bus bit count.
** Returns :
** --- -
** Error code, possible values:
** ERR_OK - Setup started
** ERR_DISABLED - The component is disabled
** ERR_SPEED - The component does not work in
** the active clock configuration
** ERR_BUSY - Another card operation is in
** progress
** ERR_PARAM_WIDTH - Invalid data width
** ===================================================================
*/
LDD_TError SDHC1_SetDataWidth(LDD_SDHC1_TDeviceData *DeviceDataPtr, uint8_t Width)
{
LDD_SDHC1_TDeviceData *DeviceDataPrv = (LDD_SDHC1_TDeviceData*)DeviceDataPtr;
LDD_TError Result = ERR_OK; /* Error code storage */
bool Finished; /* Indicates whether bus width selection has finished */
/* Device state test - this test can be disabled by setting the "Ignore enable test"
property to the "yes" value in the "Configuration inspector" */
if (!DeviceDataPrv->Enabled) {
return ERR_DISABLED;
}
/* Check allowed data width values */
if (DeviceDataPrv->CardType == LDD_SDHC_MMC) {
/* Data widths generaly supported by MMC cards */
if ((Width != LDD_SDHC_CARD_DATA_WIDTH_1_BIT) &&
(Width != LDD_SDHC_CARD_DATA_WIDTH_4_BIT) &&
(Width != LDD_SDHC_CARD_DATA_WIDTH_8_BIT)) {
return ERR_PARAM_WIDTH;
}
} else {
/* Data widths generaly supported by SD cards */
if ((Width != LDD_SDHC_CARD_DATA_WIDTH_1_BIT) &&
(Width != LDD_SDHC_CARD_DATA_WIDTH_4_BIT)) {
return ERR_PARAM_WIDTH;
}
}
if (DeviceDataPrv->State == LDD_SDHC_IDLE) {
DeviceDataPrv->Cancel = FALSE; /* Clear the cancel flag */
DeviceDataPrv->LastError = LDD_SDHC_ERR_OK; /* Clear the error code */
DeviceDataPrv->LastErrorAddress = 0U; /* Clear the error address */
DeviceDataPrv->DataWidth = Width; /* Store the new data width */
/* Start data width selection */
DeviceDataPrv->State = LDD_SDHC_DATA_WIDTH_SELECTION;
DeviceDataPrv->CmdState = SDHC1_CMD_START;
Finished = DataWidthSelection(DeviceDataPrv, 0U, SDHC1_NO_RESPONSE); /* Handle the data width selection state */
(void)Finished; /* The return value is not used */
} else {
Result = ERR_BUSY; /* Another operation is in progress */
}
return Result;
}
/*
** ===================================================================
** Method : SDHC1_SelectBusClock (component SDHC_LDD)
**
** Description :
** Initiates a SD bus clock frequency change. If the frequency
** is for high speed mode, initiates a high speed mode setup on
** the selected card. The card has to support the specified bus
** clock frequency. This method is enabled only if a list of
** bus clock frequencies is specified.
** Parameters :
** NAME - DESCRIPTION
** * DeviceDataPtr - Pointer to the device
** data structure.
** Frequency - Bus clock frequency identifier.
** Returns :
** --- -
** Error code, possible values:
** ERR_OK - Setup started
** ERR_DISABLED - The component is disabled
** ERR_SPEED - The component does not work in
** the active clock configuration
** ERR_BUSY - Another card operation is in
** progress
** ===================================================================
*/
LDD_TError SDHC1_SelectBusClock(LDD_SDHC1_TDeviceData *DeviceDataPtr, SDHC1_TBusClock Frequency)
{
LDD_SDHC1_TDeviceData *DeviceDataPrv = (LDD_SDHC1_TDeviceData*)DeviceDataPtr;
LDD_TError Result = ERR_OK; /* Error code storage */
uint8_t Id = DeviceDataPrv->CardId; /* Card ID storage */
static const uint32_t BusClockList[] = { /* Selectable bus clock frequencies in hertz specified by the timing dialog property */
390625u,
12500000u,
25000000u
};
/* Device state test - this test can be disabled by setting the "Ignore enable test"
property to the "yes" value in the "Configuration inspector" */
if (!DeviceDataPrv->Enabled) {
return ERR_DISABLED;
}
if (DeviceDataPrv->State == LDD_SDHC_IDLE) {
DeviceDataPrv->Cancel = FALSE; /* Clear the cancel flag */
DeviceDataPrv->LastError = LDD_SDHC_ERR_OK; /* Clear the error code */
DeviceDataPrv->LastErrorAddress = 0U; /* Clear the error address */
DeviceDataPrv->Frequency = Frequency; /* Store the new bus clock frequency ID */
/* Start bus clock selection */
DeviceDataPrv->State = LDD_SDHC_BUS_CLOCK_SELECTION;
if (((DeviceDataPrv->Cards[Id].Type == LDD_SDHC_SD) && (BusClockList[Frequency] >= 25000000U)) ||
((DeviceDataPrv->Cards[Id].Type == LDD_SDHC_MMC) && (BusClockList[Frequency] >= 20000000U))) {
/* Card needs speed mode switch */
DeviceDataPrv->CmdState = SDHC1_CMD_START;
} else {
/* Card doesn't need speed mode switch */
DeviceDataPrv->CmdState = SDHC1_CMD_FINISH;
}
if (BusClockSelection(DeviceDataPrv, 0U, SDHC1_NO_RESPONSE)) {
DeviceDataPrv->State = LDD_SDHC_IDLE;
if (DeviceDataPrv->EventMask & LDD_SDHC_ON_FINISHED) {
SDHC1_OnFinished(DeviceDataPrv->UserDataPtr); /* Call the user event */
}
}
} else {
Result = ERR_BUSY; /* Another operation is in progress */
}
return Result;
}
/*
** ===================================================================
** Method : SDHC1_SetVoltage (component SDHC_LDD)
**
** Description :
** Initiates a bus voltage change. The card has to support the
** specified voltage.
** Parameters :
** NAME - DESCRIPTION
** * DeviceDataPtr - Pointer to the device
** data structure.
** Voltage - Voltage identifier.
** Returns :
** --- -
** Error code, possible values:
** ERR_OK - Setup started
** ERR_DISABLED - The component is disabled
** ERR_SPEED - The component does not work in
** the active clock configuration
** ERR_BUSY - Another card operation is in
** progress
** ===================================================================
*/
LDD_TError SDHC1_SetVoltage(LDD_SDHC1_TDeviceData *DeviceDataPtr, LDD_SDHC_TVoltage Voltage)
{
LDD_SDHC1_TDeviceData *DeviceDataPrv = (LDD_SDHC1_TDeviceData*)DeviceDataPtr;
LDD_TError Result = ERR_OK; /* Error code storage */
uint8_t Id; /* Card ID storage */
/* Device state test - this test can be disabled by setting the "Ignore enable test"
property to the "yes" value in the "Configuration inspector" */
if (!DeviceDataPrv->Enabled) {
return ERR_DISABLED;
}
if (DeviceDataPrv->State == LDD_SDHC_IDLE) {
DeviceDataPrv->Cancel = FALSE; /* Clear the cancel flag */
DeviceDataPrv->LastError = LDD_SDHC_ERR_OK; /* Clear the error code */
DeviceDataPrv->LastErrorAddress = 0U; /* Clear the error address */
/* Start a new voltage validation */
DeviceDataPrv->State = LDD_SDHC_VOLTAGE_VALIDATION;
DeviceDataPrv->Substate = SDHC1_VV_START;
DeviceDataPrv->HighVoltage = (Voltage == LDD_SDHC_HIGH_VOLTAGE) ? TRUE : FALSE; /* Store the new voltage configuration */
/* Remove cards from the device data structure */
for (Id = 0U; Id < SDHC1_MAX_CARD_NUMBER; Id++) {
if (DeviceDataPrv->Cards[Id].Initialized) {
DeviceDataPrv->Cards[Id].Initialized = FALSE;
if (DeviceDataPrv->EventMask & LDD_SDHC_ON_CARD_REMOVED) {
SDHC1_OnCardRemoved(DeviceDataPrv->UserDataPtr, Id); /* Call the user event */
}
}
}
DeviceDataPrv->CardId = SDHC1_NO_CARD; /* No card will be selected */
/* Send reset command */
SDHC_PDD_SetCommandArgument(SDHC_BASE_PTR, 0U);
SDHC_PDD_SendCommand(SDHC_BASE_PTR,
SDHC_PDD_CMD0_GO_IDLE_STATE, SDHC_PDD_NO_RESPONSE);
} else {
Result = ERR_BUSY; /* Another operation is in progress */
}
return Result;
}
/*
** ===================================================================
** Method : SDHC1_SetWriteProtection (component SDHC_LDD)
**
** Description :
** Initiates a write protection setup for the selected card. If
** the write protection type is LDD_SDHC_GROUP, write
** protection will be set for the addressed write protection
** group. Write protection group size is contained within the
** card information structure. If the write protection type is
** LDD_SDHC_CARD, write protection will be set for the whole
** card and the address parameter will be ignored. Only a whole
** card write protection clear can remove this protection. The
** card has to support write protection.
** Parameters :
** NAME - DESCRIPTION
** * DeviceDataPtr - Pointer to the device
** data structure.
** Type - Write protection type.
** Address - Address of the write protection
** group, if the write protection type is
** LDD_SDHC_GROUP. Byte address in case of
** standard capacity memory card and 512 byte
** block number in case of high capacity
** memory card.
** Protected - Indicates whether the
** addressed write protection group or card
** should be write protected or not.
** Returns :
** --- -
** Error code, possible values:
** ERR_OK - Setup started
** ERR_DISABLED - The component is disabled
** ERR_SPEED - The component does not work in
** the active clock configuration
** ERR_BUSY - Another card operation is in
** progress
** ===================================================================
*/
LDD_TError SDHC1_SetWriteProtection(LDD_SDHC1_TDeviceData *DeviceDataPtr, LDD_SDHC_TWriteProtectType Type, uint32_t Address, bool Protected)
{
LDD_SDHC1_TDeviceData *DeviceDataPrv = (LDD_SDHC1_TDeviceData*)DeviceDataPtr;
LDD_TError Result = ERR_OK; /* Error code storage */
uint8_t Id = DeviceDataPrv->CardId; /* Card ID storage */
bool Finished; /* Indicates whether write protection setup has finished */
/* Device state test - this test can be disabled by setting the "Ignore enable test"
property to the "yes" value in the "Configuration inspector" */
if (!DeviceDataPrv->Enabled) {
return ERR_DISABLED;
}
if (DeviceDataPrv->State == LDD_SDHC_IDLE) {
DeviceDataPrv->Cancel = FALSE; /* Clear the cancel flag */
DeviceDataPrv->LastError = LDD_SDHC_ERR_OK; /* Clear the error code */
DeviceDataPrv->LastErrorAddress = 0U; /* Clear the error address */
DeviceDataPrv->WriteProtType = Type; /* Store the write protection type to be set */
DeviceDataPrv->Address = Address; /* Store the write protection group address */
DeviceDataPrv->WriteProtFlag = Protected; /* Store whether to clear or set write protection */
/* Start write protection setup */
DeviceDataPrv->State = LDD_SDHC_WRITE_PROTECTION_SETUP;
if (Type == LDD_SDHC_GROUP) { /* Change sector group write protection */
DeviceDataPrv->CmdState = SDHC1_CMD_START;
} else { /* Change the whole card write protection */
if (Protected) {
DeviceDataPrv->Cards[Id].CSD[0] |= SDHC1_R2_TMP_WRITE_PROTECT_MASK; /* Set the temporary write protection bit in the CSD (card specific data) register */
} else {
DeviceDataPrv->Cards[Id].CSD[0] &= (uint32_t)(~(uint32_t)SDHC1_R2_TMP_WRITE_PROTECT_MASK); /* Clear the temporary write protection bit in the CSD (card specific data) register */
}
DeviceDataPrv->CmdState = SDHC1_CMD_START;
}
Finished = WriteProtectionSetup(DeviceDataPrv, 0U, SDHC1_NO_RESPONSE); /* Handle the write protection setup state */
(void)Finished; /* The return value is not used */
} else {
Result = ERR_BUSY; /* Another operation is in progress */
}
return Result;
}
/*
** ===================================================================
** Method : SDHC1_GetWriteProtection (component SDHC_LDD)
**
** Description :
** Initiates a write protection mask retrieval for the selected
** card. After the mask has been received, the OnFinished event
** is called and the mask is stored in the specified variable.
** The returned mask contains a bit mask of write protected
** write protection groups starting at the specified address.
** The least significant bit represents the status of the first
** write protection group. Bits of write protection groups out
** of range are cleared. The card has to support write
** protection.
** Parameters :
** NAME - DESCRIPTION
** * DeviceDataPtr - Pointer to the device
** data structure.
** Address - Address of the write protection
** group. Byte address in case of standard
** capacity memory card and 512 byte block
** number in case of high capacity memory card.
** * MaskPtr - Pointer to a variable, where the
** write protection groups status mask will be
** stored.
** Returns :
** --- -
** Error code, possible values:
** ERR_OK - Write protection mask retrieval
** started
** ERR_DISABLED - The component is disabled
** ERR_SPEED - The component does not work in
** the active clock configuration
** ERR_BUSY - Another card operation is in
** progress
** ===================================================================
*/
LDD_TError SDHC1_GetWriteProtection(LDD_SDHC1_TDeviceData *DeviceDataPtr, uint32_t Address, uint32_t *MaskPtr)
{
LDD_SDHC1_TDeviceData *DeviceDataPrv = (LDD_SDHC1_TDeviceData*)DeviceDataPtr;
LDD_TError Result = ERR_OK; /* Error code storage */
bool Finished; /* Indicates whether write protection retrieval has finished */
/* Device state test - this test can be disabled by setting the "Ignore enable test"
property to the "yes" value in the "Configuration inspector" */
if (!DeviceDataPrv->Enabled) {
return ERR_DISABLED;
}
if (DeviceDataPrv->State == LDD_SDHC_IDLE) {
DeviceDataPrv->Cancel = FALSE; /* Clear the cancel flag */
DeviceDataPrv->LastError = LDD_SDHC_ERR_OK; /* Clear the error code */
DeviceDataPrv->LastErrorAddress = 0U; /* Clear the error address */
DeviceDataPrv->Address = Address; /* Store the write protection group address */
DeviceDataPrv->WriteProtMaskPtr = MaskPtr; /* Store a pointer to the write protection mask variable for later update */
/* Start write protection retrieval */
DeviceDataPrv->State = LDD_SDHC_WRITE_PROTECTION_RETRIEVAL;
DeviceDataPrv->CmdState = SDHC1_CMD_START;
Finished = WriteProtectionRetrieval(DeviceDataPrv, 0U, SDHC1_NO_RESPONSE); /* Handle the write protection retrieval state */
(void)Finished; /* The return value is not used */
} else {
Result = ERR_BUSY; /* Another operation is in progress */
}
return Result;
}
/*
** ===================================================================
** Method : SDHC1_CancelOperation (component SDHC_LDD)
**
** Description :
** Initiates a cancelation of the ongoing operation. The
** OnFinished event will be called for the stopped operation.
** Parameters :
** NAME - DESCRIPTION
** * DeviceDataPtr - Pointer to the device
** data structure.
** Returns :
** --- -
** Error code, possible values:
** ERR_OK - Operation cancelation started
** ERR_DISABLED - The component is disabled
** ERR_SPEED - The component does not work in
** the active clock configuration
** ERR_NOTAVAIL - No operation is in progress
** ===================================================================
*/
LDD_TError SDHC1_CancelOperation(LDD_SDHC1_TDeviceData *DeviceDataPtr)
{
LDD_SDHC1_TDeviceData *DeviceDataPrv = (LDD_SDHC1_TDeviceData*)DeviceDataPtr;
LDD_TError Result = ERR_OK; /* Error code storage */
/* Device state test - this test can be disabled by setting the "Ignore enable test"
property to the "yes" value in the "Configuration inspector" */
if (!DeviceDataPrv->Enabled) {
return ERR_DISABLED;
}
if (DeviceDataPrv->State != LDD_SDHC_IDLE) {
DeviceDataPrv->Cancel = TRUE; /* Set the cancel flag */
if (DeviceDataPrv->CmdState == SDHC1_CMD_DATA) {
/* Send stop transmission command */
SDHC_PDD_SetCommandArgument(SDHC_BASE_PTR, 0U);
SDHC_PDD_SendCommand(SDHC_BASE_PTR,
SDHC_PDD_CMD12_STOP_TRANSMISSION, SDHC_PDD_RESPONSE_LENGTH_48_BUSY_CHECK);
}
} else {
Result = ERR_NOTAVAIL; /* No operation is in progress */
}
return Result;
}
/*
** ===================================================================
** Method : SDHC1_GetStatus (component SDHC_LDD)
**
** Description :
** Returns the current component status, specifying the ongoing
** operation.
** Parameters :
** NAME - DESCRIPTION
** * DeviceDataPtr - Pointer to the device
** data structure.
** Returns :
** --- - Component status.
** ===================================================================
*/
LDD_SDHC_TStatus SDHC1_GetStatus(LDD_SDHC1_TDeviceData *DeviceDataPtr)
{
LDD_SDHC1_TDeviceData *DeviceDataPrv = (LDD_SDHC1_TDeviceData*)DeviceDataPtr;
return DeviceDataPrv->State;
}
/*
** ===================================================================
** Method : SDHC1_GetError (component SDHC_LDD)
**
** Description :
** Returns the last error code and the memory address where the
** error occurred (if applicable).
** Parameters :
** NAME - DESCRIPTION
** * DeviceDataPtr - Pointer to the device
** data structure.
** * AddressPtr - Pointer to a variable, where
** the error address will be stored.
** Returns :
** --- - The last error code.
** ===================================================================
*/
LDD_SDHC_TError SDHC1_GetError(LDD_SDHC1_TDeviceData *DeviceDataPtr, uint32_t *AddressPtr)
{
LDD_SDHC1_TDeviceData *DeviceDataPrv = (LDD_SDHC1_TDeviceData*)DeviceDataPtr;
LDD_SDHC_TError Error; /* Error code storage */
Error = DeviceDataPrv->LastError;
if (AddressPtr) {
*AddressPtr = DeviceDataPrv->LastErrorAddress;
}
return Error;
}
/*
** ===================================================================
** Method : SDHC1_ConnectPin (component SDHC_LDD)
**
** Description :
** This method reconnects the requested pins associated with
** the selected peripheral in the component. This method is
** only available for CPU derivatives and peripherals that
** support the runtime pin sharing with other internal on-chip
** peripherals.
** Parameters :
** NAME - DESCRIPTION
** * DeviceDataPtr - Pointer to device data
** structure.
** PinMask - Mask for the requested pins. The
** peripheral pins are reconnected according
** to this mask.
** Returns :
** --- -
** Error code, possible values:
** ERR_OK - OK
** ERR_PARAM_MASK - Invalid pin mask
** ===================================================================
*/
LDD_TError SDHC1_ConnectPin(LDD_SDHC1_TDeviceData *DeviceDataPtr, LDD_TPinMask PinMask)
{
// (void)DeviceDataPtr; /* Parameter is not used, suppress unused argument warning */
// if (PinMask & (LDD_TPinMask)(~(LDD_TPinMask)(
// LDD_SDHC_CLK_PIN |
// LDD_SDHC_CMD_PIN |
// LDD_SDHC_DAT0_PIN |
// LDD_SDHC_DAT1_PIN |
// LDD_SDHC_DAT2_PIN |
// LDD_SDHC_DAT3_PIN |0U))) {
// return ERR_PARAM_MASK;
// }
// if (PinMask & LDD_SDHC_CLK_PIN) {
// clrSetReg32Bits(PORTE_PCR2, 0x01000300U, 0x0400U); /* MUX=0x04U */
// }
// if (PinMask & LDD_SDHC_CMD_PIN) {
// clrSetReg32Bits(PORTE_PCR3, 0x01000300U, 0x0400U); /* MUX=0x04U */
// PORT_PDD_SetPinPullSelect(PORTE_BASE_PTR, SDHC1_PIN_CMD_PORT_INDEX, PORT_PDD_PULL_UP);
// PORT_PDD_SetPinPullEnable(PORTE_BASE_PTR, SDHC1_PIN_CMD_PORT_INDEX, PORT_PDD_PULL_ENABLE);
// PORT_PDD_SetPinDriveStrength(PORTE_BASE_PTR, SDHC1_PIN_CMD_PORT_INDEX, PORT_PDD_DRIVE_STRENGTH_HIGH);
// }
// if (PinMask & LDD_SDHC_DAT0_PIN) {
// clrSetReg32Bits(PORTE_PCR1, 0x01000300U, 0x0400U); /* MUX=0x04U */
// PORT_PDD_SetPinPullSelect(PORTE_BASE_PTR, SDHC1_PIN_DAT0_PORT_INDEX, PORT_PDD_PULL_UP);
// PORT_PDD_SetPinPullEnable(PORTE_BASE_PTR, SDHC1_PIN_DAT0_PORT_INDEX, PORT_PDD_PULL_ENABLE);
// PORT_PDD_SetPinDriveStrength(PORTE_BASE_PTR, SDHC1_PIN_DAT0_PORT_INDEX, PORT_PDD_DRIVE_STRENGTH_HIGH);
// }
// if (PinMask & LDD_SDHC_DAT1_PIN) {
// clrSetReg32Bits(PORTE_PCR0, 0x01000300U, 0x0400U); /* MUX=0x04U */
// PORT_PDD_SetPinPullSelect(PORTE_BASE_PTR, SDHC1_PIN_DAT1_PORT_INDEX, PORT_PDD_PULL_UP);
// PORT_PDD_SetPinPullEnable(PORTE_BASE_PTR, SDHC1_PIN_DAT1_PORT_INDEX, PORT_PDD_PULL_ENABLE);
// PORT_PDD_SetPinDriveStrength(PORTE_BASE_PTR, SDHC1_PIN_DAT1_PORT_INDEX, PORT_PDD_DRIVE_STRENGTH_HIGH);
// }
// if (PinMask & LDD_SDHC_DAT2_PIN) {
// clrSetReg32Bits(PORTE_PCR5, 0x01000300U, 0x0400U); /* MUX=0x04U */
// PORT_PDD_SetPinPullSelect(PORTE_BASE_PTR, SDHC1_PIN_DAT2_PORT_INDEX, PORT_PDD_PULL_UP);
// PORT_PDD_SetPinPullEnable(PORTE_BASE_PTR, SDHC1_PIN_DAT2_PORT_INDEX, PORT_PDD_PULL_ENABLE);
// PORT_PDD_SetPinDriveStrength(PORTE_BASE_PTR, SDHC1_PIN_DAT2_PORT_INDEX, PORT_PDD_DRIVE_STRENGTH_HIGH);
// }
// if (PinMask & LDD_SDHC_DAT3_PIN) {
// clrSetReg32Bits(PORTE_PCR4, 0x01000300U, 0x0400U); /* MUX=0x04U */
// PORT_PDD_SetPinPullSelect(PORTE_BASE_PTR, SDHC1_PIN_DAT3_PORT_INDEX, PORT_PDD_PULL_UP);
// PORT_PDD_SetPinPullEnable(PORTE_BASE_PTR, SDHC1_PIN_DAT3_PORT_INDEX, PORT_PDD_PULL_ENABLE);
// PORT_PDD_SetPinDriveStrength(PORTE_BASE_PTR, SDHC1_PIN_DAT3_PORT_INDEX, PORT_PDD_DRIVE_STRENGTH_HIGH);
// }
return ERR_OK;
}
/*
** ===================================================================
** Method : SDHC1_SetOperationMode (component SDHC_LDD)
**
** Description :
** This method requests to change the component's operation
** mode. Upon a request to change the operation mode, the
** component will finish a pending job first and then notify a
** caller that an operation mode has been changed. When no job
** is pending (ERR_OK), the component changes an operation mode
** immediately and notify a caller about this change.
** Parameters :
** NAME - DESCRIPTION
** * DeviceDataPtr - Device data structure
** pointer returned by Init method.
** OperationMode - Requested driver
** operation mode.
** ModeChangeCallback - Callback to
** notify the upper layer once a mode has been
** changed.
** * ModeChangeCallbackParamPtr
** - Pointer to callback parameter to notify
** the upper layer once a mode has been
** changed.
** Returns :
** --- - Error code, possible codes:
** ERR_OK - OK
** ERR_DISABLED - The component is disabled
** ERR_SPEED - The component does not work in
** the active clock configuration
** ERR_PARAM_MODE - Invalid operation mode
** ERR_BUSY - A job is pending
** ===================================================================
*/
LDD_TError SDHC1_SetOperationMode(LDD_SDHC1_TDeviceData *DeviceDataPtr, LDD_TDriverOperationMode OperationMode, LDD_TCallback ModeChangeCallback, LDD_TCallbackParam *ModeChangeCallbackParamPtr)
{
LDD_SDHC1_TDeviceData *DeviceDataPrv = (LDD_SDHC1_TDeviceData*)DeviceDataPtr;
/* Device state test - this test can be disabled by setting the "Ignore enable test"
property to the "yes" value in the "Configuration inspector" */
if (!DeviceDataPrv->Enabled) {
return ERR_DISABLED;
}
if (DeviceDataPrv->State != LDD_SDHC_IDLE) {
return ERR_BUSY;
}
switch (OperationMode) {
case DOM_RUN:
/* SIM_SCGC3: SDHC=1 */
SIM_vSetReg32( SIM_SCGC3, SIM_SCGC3_SDHC_MASK ); //SIM_SCGC3 |= (uint32_t)0x00020000UL;
SDHC_PDD_EnableSDHCClock(SDHC_BASE_PTR, PDD_ENABLE);
break;
case DOM_WAIT:
case DOM_SLEEP:
SDHC_PDD_EnableSDHCClock(SDHC_BASE_PTR, PDD_DISABLE);
break;
case DOM_STOP:
SDHC_PDD_EnableSDHCClock(SDHC_BASE_PTR, PDD_DISABLE);
/* SIM_SCGC3: SDHC=0 */
SIM_vClrReg32( SIM_SCGC3, SIM_SCGC3_SDHC_MASK ); //SIM_SCGC3 &= (uint32_t)~0x00020000UL;
break;
default:
return ERR_PARAM_MODE; /* Invalid operation mode parameter */
}
if (ModeChangeCallback != NULL) {
ModeChangeCallback(ModeChangeCallbackParamPtr);
}
return ERR_OK;
}
/*
** ===================================================================
** Method : SDHC1_GetDriverState (component SDHC_LDD)
**
** Description :
** This method returns the current driver status.
** Parameters :
** NAME - DESCRIPTION
** * DeviceDataPtr - Device data structure
** pointer returned by Init method.
** Returns :
** --- -
** The current driver status mask. The
** following status masks defined in PE_LDD.h
** can be used to check the current driver
** status:
** PE_LDD_DRIVER_DISABLED_IN_CLOCK_CONFIGURATION -
** Driver is disabled in the current speed
** mode
** PE_LDD_DRIVER_DISABLED_BY_USER - Driver is
** disabled by the user
** PE_LDD_DRIVER_BUSY - Driver is in the BUSY
** state
** ===================================================================
*/
LDD_TDriverState SDHC1_GetDriverState(LDD_SDHC1_TDeviceData *DeviceDataPtr)
{
LDD_SDHC1_TDeviceData *DeviceDataPrv = (LDD_SDHC1_TDeviceData*)DeviceDataPtr;
LDD_TDriverState DriverState = 0U; /* Driver state storage */
if (!DeviceDataPrv->EnabledMode) {
DriverState |= LDD_DRIVER_DISABLED_IN_CLOCK_CONFIGURATION;
}
if (!DeviceDataPrv->Enabled) {
DriverState |= LDD_DRIVER_DISABLED_BY_USER;
}
if (DeviceDataPrv->State != LDD_SDHC_IDLE) {
DriverState |= LDD_DRIVER_BUSY;
}
return DriverState;
}
/*
** ===================================================================
** Method : SDHC1_VoltageValidation (component SDHC_LDD)
**
** Description :
** Voltage validation state handler.
** This method is internal. It is used by Processor Expert only.
** ===================================================================
*/
static void VoltageValidation(LDD_SDHC1_TDeviceData *DeviceDataPtr, uint32_t Flags, uint32_t *Response)
{
LDD_SDHC1_TDeviceData *DeviceDataPrv = (LDD_SDHC1_TDeviceData*)DeviceDataPtr;
LDD_SDHC_TError Error = LDD_SDHC_ERR_OK; /* Error code storage */
switch (DeviceDataPrv->Substate) {
case SDHC1_VV_START:
DeviceDataPrv->CardsVoltages = 0;
/* Start with SD card version 2.0 or later interface conditions check */
DeviceDataPrv->Substate = SDHC1_VV_SDHC_CHECK;
DeviceDataPrv->CmdState = SDHC1_CMD_START;
VoltageValidation(DeviceDataPrv, 0U, SDHC1_NO_RESPONSE); /* Handle the voltage validation state */
break;
case SDHC1_VV_SDHC_CHECK:
switch (DeviceDataPrv->CmdState) {
case SDHC1_CMD_START:
DeviceDataPrv->CmdState = SDHC1_CMD_FINISH;
/* Send interface conditions request command */
SDHC_PDD_SetCommandArgument(SDHC_BASE_PTR,
((DeviceDataPrv->HighVoltage == TRUE) ? /* Propose bus voltage configuration */
SDHC1_IF_COND_HIGH_VOLTAGE_MASK :
SDHC1_IF_COND_LOW_VOLTAGE_MASK) |
SDHC1_IF_COND_CHECK_PATTERN);
SDHC_PDD_SendCommand(SDHC_BASE_PTR,
SDHC_PDD_CMD8_SEND_EXT_CSD, SDHC_PDD_RESPONSE_LENGTH_48);
break;
case SDHC1_CMD_FINISH:
Error = GetCommandError(DeviceDataPrv, Flags, Response); /* Check host and card error flags */
if (Error == LDD_SDHC_ERR_OK) {
DeviceDataPrv->HighCapacity = TRUE; /* Card is an SD card version 2.0 or later (possibly high capacity) */
} else if (Error == LDD_SDHC_ERR_TIMEOUT) {
DeviceDataPrv->HighCapacity = FALSE; /* Card is a normal SD or other type of card */
} else {
DeviceDataPrv->LastError = Error;
}
/* Continue with SD card interface conditions check */
DeviceDataPrv->Substate = SDHC1_VV_SD_CHECK;
DeviceDataPrv->CmdState = SDHC1_CMD_START;
DeviceDataPrv->RetryCounter = SDHC1_VOLT_VALID_RETRY_COUNT; /* Limit the interface conditions request number */
VoltageValidation(DeviceDataPrv, 0U, SDHC1_NO_RESPONSE); /* Handle the voltage validation state */
break;
default:
break;
}
break;
case SDHC1_VV_SD_CHECK:
switch (DeviceDataPrv->CmdState) {
case SDHC1_CMD_START:
DeviceDataPrv->CmdState = SDHC1_CMD_ACMD;
/* Start application specific command */
SDHC_PDD_SetCommandArgument(SDHC_BASE_PTR, 0U);
SDHC_PDD_SendCommand(SDHC_BASE_PTR,
SDHC_PDD_CMD55_APP_CMD, SDHC_PDD_RESPONSE_LENGTH_48);
break;
case SDHC1_CMD_ACMD:
Error = GetCommandError(DeviceDataPrv, Flags, Response); /* Check host and card error flags */
if ((Error == LDD_SDHC_ERR_OK) || (Error == LDD_SDHC_ERR_INTERNAL_FAILURE)) {
DeviceDataPrv->CmdState = SDHC1_CMD_FINISH;
/* Send OCR (operation conditions register) request */
SDHC_PDD_SetCommandArgument(SDHC_BASE_PTR,
((DeviceDataPrv->HighCapacity == TRUE) ? SDHC1_OCR_HIGH_CAPACITY_MASK : 0U) |
((DeviceDataPrv->HighVoltage == TRUE) ? /* Propose bus voltage configuration */
SDHC1_OCR_HIGH_VOLTAGE_MASK :
SDHC1_OCR_LOW_VOLTAGE_MASK));
SDHC_PDD_SendCommand(SDHC_BASE_PTR,
SDHC_PDD_ACMD41_SD_APP_OP_COND, SDHC_PDD_RESPONSE_LENGTH_48);
} else {
if (Error == LDD_SDHC_ERR_COMMAND_CRC) {
DeviceDataPrv->LastError = Error;
}
/* No more SD card, check MMC cards */
DeviceDataPrv->Substate = SDHC1_VV_MMC_CHECK;
DeviceDataPrv->CmdState = SDHC1_CMD_START;
DeviceDataPrv->RetryCounter = SDHC1_VOLT_VALID_RETRY_COUNT; /* Limit the interface conditions request number */
VoltageValidation(DeviceDataPrv, 0U, SDHC1_NO_RESPONSE); /* Handle the voltage validation state */
}
break;
case SDHC1_CMD_FINISH:
Error = GetCommandError(DeviceDataPrv, Flags, SDHC1_NO_RESPONSE); /* Check host error flags */
if ((Error == LDD_SDHC_ERR_OK) && Response) {
if (SDHC1_R3_OCR_IS_CARD_POWER_UP(Response)) {
/* Card is powered up, start the registration */
DeviceDataPrv->CardType = LDD_SDHC_SD;
DeviceDataPrv->CardsVoltages |= *Response & /* Save card voltage capabilities */
(SDHC1_OCR_HIGH_VOLTAGE_MASK | SDHC1_OCR_LOW_VOLTAGE_MASK);
DeviceDataPrv->HighCapacity = (SDHC1_R3_OCR_IS_CARD_HIGH_CAPACITY(Response)) ? TRUE : FALSE;
DeviceDataPrv->State = LDD_SDHC_CARD_REGISTRATION;
DeviceDataPrv->Substate = SDHC1_CR_START;
CardRegistration(DeviceDataPrv, 0U, SDHC1_NO_RESPONSE); /* Handle the card registration state */
} else if (DeviceDataPrv->RetryCounter--) {
/* Card is not powered up yet, resend request */
DeviceDataPrv->CmdState = SDHC1_CMD_START;
VoltageValidation(DeviceDataPrv, 0U, SDHC1_NO_RESPONSE); /* Handle the voltage validation state */
} else {
/* Power up reached timeout, check MMC cards */
DeviceDataPrv->LastError = LDD_SDHC_ERR_TIMEOUT;
DeviceDataPrv->Substate = SDHC1_VV_MMC_CHECK;
DeviceDataPrv->CmdState = SDHC1_CMD_START;
}
} else {
if (Error == LDD_SDHC_ERR_COMMAND_CRC) {
DeviceDataPrv->LastError = Error;
}
/* No response for ACMD41, check MMC cards */
DeviceDataPrv->Substate = SDHC1_VV_MMC_CHECK;
DeviceDataPrv->CmdState = SDHC1_CMD_START;
}
if (DeviceDataPrv->Substate == SDHC1_VV_MMC_CHECK) {
DeviceDataPrv->RetryCounter = SDHC1_VOLT_VALID_RETRY_COUNT; /* Limit the interface conditions request number */
/* Send reset command */
SDHC_PDD_SetCommandArgument(SDHC_BASE_PTR, 0U);
SDHC_PDD_SendCommand(SDHC_BASE_PTR,
SDHC_PDD_CMD0_GO_IDLE_STATE, SDHC_PDD_NO_RESPONSE);
}
break;
default:
break;
}
break;
case SDHC1_VV_MMC_CHECK:
switch (DeviceDataPrv->CmdState) {
case SDHC1_CMD_START:
DeviceDataPrv->CmdState = SDHC1_CMD_FINISH;
/* Send OCR (operation conditions register) request */
SDHC_PDD_SetCommandArgument(SDHC_BASE_PTR,
((DeviceDataPrv->HighVoltage == TRUE) ? /* Propose bus voltage configuration */
SDHC1_OCR_HIGH_VOLTAGE_MASK :
SDHC1_OCR_LOW_VOLTAGE_MASK) |
SDHC1_OCR_HIGH_CAPACITY_MASK); /* Indicate high capacity card support by the host */
SDHC_PDD_SendCommand(SDHC_BASE_PTR,
SDHC_PDD_CMD1_SEND_OP_COND, SDHC_PDD_RESPONSE_LENGTH_48);
break;
case SDHC1_CMD_FINISH:
Error = GetCommandError(DeviceDataPrv, Flags, SDHC1_NO_RESPONSE); /* Check host error flags */
if ((Error == LDD_SDHC_ERR_OK) && Response) {
if (SDHC1_R3_OCR_IS_CARD_POWER_UP(Response)) {
/* Card is powered up, start the registration */
DeviceDataPrv->CardType = LDD_SDHC_MMC;
DeviceDataPrv->CardsVoltages |= *Response & /* Save card voltage capabilities */
(SDHC1_OCR_HIGH_VOLTAGE_MASK | SDHC1_OCR_LOW_VOLTAGE_MASK);
DeviceDataPrv->HighCapacity = (SDHC1_R3_OCR_IS_CARD_HIGH_CAPACITY(Response)) ? TRUE : FALSE;
DeviceDataPrv->State = LDD_SDHC_CARD_REGISTRATION;
DeviceDataPrv->Substate = SDHC1_CR_START;
CardRegistration(DeviceDataPrv, 0U, SDHC1_NO_RESPONSE); /* Handle the card registration state */
} else if (DeviceDataPrv->RetryCounter--) {
/* Card is not powered up yet, resend request */
DeviceDataPrv->CmdState = SDHC1_CMD_START;
VoltageValidation(DeviceDataPrv, 0U, SDHC1_NO_RESPONSE); /* Handle the voltage validation state */
} else {
/* Power up reached timeout, finish */
DeviceDataPrv->LastError = LDD_SDHC_ERR_TIMEOUT;
DeviceDataPrv->Substate = SDHC1_VV_FINISH;
VoltageValidation(DeviceDataPrv, 0U, SDHC1_NO_RESPONSE); /* Handle the voltage validation state */
}
} else {
if (Error == LDD_SDHC_ERR_COMMAND_CRC) {
DeviceDataPrv->LastError = Error;
}
/* No more MMC card, finish */
DeviceDataPrv->Substate = SDHC1_VV_FINISH;
VoltageValidation(DeviceDataPrv, 0U, SDHC1_NO_RESPONSE); /* Handle the voltage validation state */
}
break;
default:
break;
}
break;
case SDHC1_VV_FINISH:
DeviceDataPrv->State = LDD_SDHC_IDLE;
if (DeviceDataPrv->EventMask & LDD_SDHC_ON_FINISHED) {
SDHC1_OnFinished(DeviceDataPrv->UserDataPtr); /* Call the user event */
}
break;
default:
break;
}
}
/*
** ===================================================================
** Method : CardRegistration (component SDHC_LDD)
**
** Description :
** Card registration state handler.
** This method is internal. It is used by Processor Expert only.
** ===================================================================
*/
static void CardRegistration(LDD_SDHC1_TDeviceData *DeviceDataPtr, uint32_t Flags, uint32_t *Response)
{
LDD_SDHC1_TDeviceData *DeviceDataPrv = (LDD_SDHC1_TDeviceData*)DeviceDataPtr;
LDD_SDHC_TError Error = LDD_SDHC_ERR_OK; /* Error code storage */
uint8_t Id; /* Card ID storage */
uint32_t Index; /* Array index */
switch (DeviceDataPrv->Substate) {
case SDHC1_CR_START:
switch (DeviceDataPrv->CardType) {
case LDD_SDHC_SD:
case LDD_SDHC_MMC:
/* Send CID register request */
SDHC_PDD_SetCommandArgument(SDHC_BASE_PTR, 0U);
SDHC_PDD_SendCommand(SDHC_BASE_PTR,
SDHC_PDD_CMD2_ALL_SEND_CID, SDHC_PDD_RESPONSE_LENGTH_136);
DeviceDataPrv->Substate = SDHC1_CR_GET_CID;
break;
default:
break;
}
break;
case SDHC1_CR_GET_CID:
switch (DeviceDataPrv->CardType) {
case LDD_SDHC_SD:
case LDD_SDHC_MMC:
Error = GetCommandError(DeviceDataPrv, Flags, SDHC1_NO_RESPONSE); /* Check host error flags */
if ((Error == LDD_SDHC_ERR_OK) && Response) {
/* Assign a free data structure to the card */
for (Id = 0U; Id < SDHC1_MAX_CARD_NUMBER; Id++) {
if (!DeviceDataPrv->Cards[Id].Initialized) {
/* Initialize the data structure */
DeviceDataPrv->NewCardId = Id; /* Assign a component related ID to the card */
DeviceDataPrv->Cards[Id].Initialized = TRUE; /* Mark the data structure as used */
DeviceDataPrv->Cards[Id].Type = DeviceDataPrv->CardType;
DeviceDataPrv->Cards[Id].CID[0] = Response[0]; /* Store the received card ID */
DeviceDataPrv->Cards[Id].CID[1] = Response[1];
DeviceDataPrv->Cards[Id].CID[2] = Response[2];
DeviceDataPrv->Cards[Id].CID[3] = Response[3];
for (Index = 0U; Index < sizeof(DeviceDataPrv->Cards[Id].Block); Index++) {
DeviceDataPrv->Cards[Id].Block[Index] = 0U; /* Clear the card info block */
}
DeviceDataPrv->Cards[Id].HighCapacity = DeviceDataPrv->HighCapacity;
DeviceDataPrv->Cards[Id].DataWidths = LDD_SDHC_CARD_DATA_WIDTH_1_BIT; /* Initialize supported data widths */
if (DeviceDataPrv->CardType == LDD_SDHC_SD) {
/* Request an RCA (relative card address) from the card */
SDHC_PDD_SetCommandArgument(SDHC_BASE_PTR, 0U);
} else {
/* Create a new RCA (relative card address) */
DeviceDataPrv->Cards[Id].RCA = (uint16_t)((uint16_t)Id + 2U); /* MMC RCAs must start from 2 */
/* Send the RCA (relative card address) to the card */
SDHC_PDD_SetCommandArgument(SDHC_BASE_PTR, (uint32_t)((uint32_t)Id + 2U) << 16);
}
SDHC_PDD_SendCommand(SDHC_BASE_PTR,
SDHC_PDD_CMD3_SET_RELATIVE_ADDR, SDHC_PDD_RESPONSE_LENGTH_48);
DeviceDataPrv->Substate = SDHC1_CR_GET_RCA;
}
}
} else {
if (Error != LDD_SDHC_ERR_TIMEOUT) {
DeviceDataPrv->LastError = Error;
}
/* No more card for registration */
DeviceDataPrv->Substate = SDHC1_CR_FINISH;
CardRegistration(DeviceDataPrv, 0U, SDHC1_NO_RESPONSE); /* Handle the card registration state */
}
break;
default:
break;
}
break;
case SDHC1_CR_GET_RCA:
switch (DeviceDataPrv->CardType) {
case LDD_SDHC_SD:
case LDD_SDHC_MMC:
Error = GetCommandError(DeviceDataPrv, Flags, SDHC1_NO_RESPONSE); /* Check host error flags */
if ((Error == LDD_SDHC_ERR_OK) && Response) {
Id = DeviceDataPrv->NewCardId;
if (DeviceDataPrv->CardType == LDD_SDHC_SD) {
DeviceDataPrv->Cards[Id].RCA = SDHC1_R6_GET_RCA(Response); /* Store the received RCA (relative card address) */
}
if (DeviceDataPrv->EventMask & LDD_SDHC_ON_CARD_INSERTED) {
SDHC1_OnCardInserted(DeviceDataPrv->UserDataPtr, Id); /* Call the user event */
}
} else {
DeviceDataPrv->LastError = Error;
}
DeviceDataPrv->State = LDD_SDHC_CARD_REGISTRATION;
DeviceDataPrv->Substate = SDHC1_CR_FINISH;
CardRegistration(DeviceDataPrv, 0U, SDHC1_NO_RESPONSE); /* Handle the card registration state */
break;
default:
break;
}
break;
case SDHC1_CR_FINISH:
switch (DeviceDataPrv->CardType) {
case LDD_SDHC_SD:
/* An SD card is registered, finish the voltage validation */
case LDD_SDHC_MMC:
/* MMC cards are checked as the last, finish the voltage validation */
DeviceDataPrv->State = LDD_SDHC_VOLTAGE_VALIDATION;
DeviceDataPrv->Substate = SDHC1_VV_FINISH;
VoltageValidation(DeviceDataPrv, 0U, SDHC1_NO_RESPONSE); /* Handle the voltage validation state */
break;
default:
break;
}
break;
default:
break;
}
}
/*
** ===================================================================
** Method : CardInfoRetrieval (component SDHC_LDD)
**
** Description :
** Card info retrieval state handler.
** This method is internal. It is used by Processor Expert only.
** ===================================================================
*/
static void CardInfoRetrieval(LDD_SDHC1_TDeviceData *DeviceDataPtr, uint32_t Flags, uint32_t *Response)
{
LDD_SDHC1_TDeviceData *DeviceDataPrv = (LDD_SDHC1_TDeviceData*)DeviceDataPtr;
bool Finished = FALSE; /* Indicates card info retrieval end */
LDD_SDHC_TError Error = LDD_SDHC_ERR_OK; /* Error code storage */
LDD_SDHC_TCardInfo *InfoPtr; /* Card info pointer storage */
uint8_t Id = DeviceDataPrv->CardId; /* Card ID storage */
uint8_t BusWidths; /* Supported bus widths storage */
uint32_t Index; /* Array index */
switch (DeviceDataPrv->Substate) {
case SDHC1_CIR_START:
if (DeviceDataPrv->CardState != SDHC1_STAND_BY) {
/* Change card state to stand-by */
DeviceDataPrv->Substate = SDHC1_CIR_STAND_BY_STATE;
/* Send unselect card command */
SDHC_PDD_SetCommandArgument(SDHC_BASE_PTR, 0U); /* Set 0 as command argument to unselect card */
SDHC_PDD_SendCommand(SDHC_BASE_PTR,
SDHC_PDD_CMD7_SELECT_CARD, SDHC_PDD_RESPONSE_LENGTH_48);
} else {
DeviceDataPrv->Substate = SDHC1_CIR_GET_CSD;
CardInfoRetrieval(DeviceDataPrv, 0U, SDHC1_NO_RESPONSE); /* Handle the card info retrieval state */
}
break;
case SDHC1_CIR_STAND_BY_STATE:
Error = GetCommandError(DeviceDataPrv, Flags, Response); /* Check host and card error flags */
if (Error != LDD_SDHC_ERR_TIMEOUT) {
DeviceDataPrv->LastError = Error;
}
DeviceDataPrv->CardState = SDHC1_STAND_BY;
DeviceDataPrv->Substate = SDHC1_CIR_GET_CSD;
/* Send CSD (card specific data) request command */
SDHC_PDD_SetCommandArgument(SDHC_BASE_PTR,
SDHC1_CMD_ARG_RCA((uint32_t)DeviceDataPrv->Cards[Id].RCA)); /* Set the card RCA (relative card address) as command argument */
SDHC_PDD_SendCommand(SDHC_BASE_PTR,
SDHC_PDD_CMD9_SEND_CSD, SDHC_PDD_RESPONSE_LENGTH_136);
break;
case SDHC1_CIR_GET_CSD:
Error = GetCommandError(DeviceDataPrv, Flags, SDHC1_NO_RESPONSE); /* Check host error flags */
if ((Error == LDD_SDHC_ERR_OK) && Response) {
/* Store the CSD (card specific data) register contained in the response */
DeviceDataPrv->Cards[Id].CSD[0] = Response[0];
DeviceDataPrv->Cards[Id].CSD[1] = Response[1];
DeviceDataPrv->Cards[Id].CSD[2] = Response[2];
DeviceDataPrv->Cards[Id].CSD[3] = Response[3];
/* Change card state to transfer */
DeviceDataPrv->Substate = SDHC1_CIR_TRANSFER_STATE;
/* Send card selection command */
SDHC_PDD_SetCommandArgument(SDHC_BASE_PTR,
SDHC1_CMD_ARG_RCA((uint32_t)DeviceDataPrv->Cards[Id].RCA)); /* Set the card RCA (relative card address) as command argument */
SDHC_PDD_SendCommand(SDHC_BASE_PTR,
SDHC_PDD_CMD7_SELECT_CARD, SDHC_PDD_RESPONSE_LENGTH_48_BUSY_CHECK);
} else {
DeviceDataPrv->LastError = Error;
Finished = TRUE;
}
break;
case SDHC1_CIR_TRANSFER_STATE:
Error = GetCommandError(DeviceDataPrv, Flags, Response); /* Check host and card error flags */
if ((Error == LDD_SDHC_ERR_OK) && Response) {
if (SDHC1_R1_IS_READY_FOR_DATA(Response)) {
DeviceDataPrv->CardState = SDHC1_TRANSFER;
if (DeviceDataPrv->CardType == LDD_SDHC_MMC) {
if (SDHC1_R2_MMC_GET_SPEC_VERS(Response) >= SDHC1_MMC_CSD_SPEC_VERS_4_X) {
DeviceDataPrv->Substate = SDHC1_CIR_GET_EXT_CSD;
DeviceDataPrv->CmdState = SDHC1_CMD_START;
} else {
DeviceDataPrv->Substate = SDHC1_CIR_FINISH;
}
//CardInfoRetrieval(DeviceDataPrv, 0U, SDHC1_NO_RESPONSE); /* Handle the card info retrieval state */
} else {
DeviceDataPrv->Substate = SDHC1_CIR_GET_SCR;
DeviceDataPrv->CmdState = SDHC1_CMD_START;
CardInfoRetrieval(DeviceDataPrv, 0U, SDHC1_NO_RESPONSE); /* Handle the card info retrieval state */
}
} else {
/* Send status request command */
SendCardStatusRequest(DeviceDataPrv);
}
} else {
DeviceDataPrv->LastError = Error;
Finished = TRUE;
}
break;
case SDHC1_CIR_GET_EXT_CSD:
switch (DeviceDataPrv->CmdState) {
case SDHC1_CMD_START:
DeviceDataPrv->CmdState = SDHC1_CMD_FINISH;
/* Set data transfer size */
SDHC_PDD_SetBlockSize(SDHC_BASE_PTR, SDHC1_EXT_CSD_SIZE);
SDHC_PDD_SetBlockCount(SDHC_BASE_PTR, 1U);
/* Set DMA transfer properties */
DeviceDataPrv->TransferTable[0].Attributes = SDHC1_SINGLE_BLOCK_TRANS_ATTRS;
DeviceDataPrv->TransferTable[0].Length = SDHC1_EXT_CSD_SIZE;
DeviceDataPrv->TransferTable[0].Address = (uint32_t)DeviceDataPrv->Cards[Id].Block;
SDHC_PDD_SetADMAAddress(SDHC_BASE_PTR, DeviceDataPrv->TransferTable);
/* Send extended CSD (card specific data) request command */
SDHC_PDD_SetCommandArgument(SDHC_BASE_PTR, 0U);
SDHC_PDD_SendCommand(SDHC_BASE_PTR, SDHC_PDD_CMD8_SEND_EXT_CSD,
SDHC_PDD_ENABLE_DMA | SDHC_PDD_DATA_PRESENT | SDHC_PDD_DATA_READ | SDHC_PDD_RESPONSE_LENGTH_48);
break;
case SDHC1_CMD_FINISH:
Error = GetCommandError(DeviceDataPrv, Flags, Response); /* Check host and card error flags */
if (Error == LDD_SDHC_ERR_OK) {
DeviceDataPrv->CmdState = SDHC1_CMD_DATA;
CardInfoRetrieval(DeviceDataPrv, 0U, SDHC1_NO_RESPONSE); /* Handle the card info retrieval state */
} else {
DeviceDataPrv->LastError = Error;
Finished = TRUE;
}
break;
case SDHC1_CMD_DATA:
Error = GetCommandError(DeviceDataPrv, Flags, SDHC1_NO_RESPONSE); /* Check host error flags */
if (Error == LDD_SDHC_ERR_OK) {
/* Start the bus testing procedure */
DeviceDataPrv->Substate = SDHC1_CIR_BUS_TEST_4_BIT_WRITE;
DeviceDataPrv->CmdState = SDHC1_CMD_START;
CardInfoRetrieval(DeviceDataPrv, 0U, SDHC1_NO_RESPONSE); /* Handle the card info retrieval state */
} else {
DeviceDataPrv->LastError = Error;
DeviceDataPrv->LastErrorAddress = SDHC_PDD_GetDMAAddress(SDHC_BASE_PTR);
Finished = TRUE;
}
break;
default:
break;
}
break;
case SDHC1_CIR_BUS_TEST_4_BIT_WRITE:
case SDHC1_CIR_BUS_TEST_8_BIT_WRITE:
switch (DeviceDataPrv->CmdState) {
case SDHC1_CMD_START:
DeviceDataPrv->CmdState = SDHC1_CMD_FINISH;
/* Clear the bus test buffer */
for (Index = 0U; Index < 8U; Index++) {
DeviceDataPrv->BusTestPtr[Index] = 0U;
}
/* Create the bus test pattern */
if (DeviceDataPrv->Substate == SDHC1_CIR_BUS_TEST_4_BIT_WRITE) {
DeviceDataPrv->BusTestPtr[0] = 0x5AU;
} else {
DeviceDataPrv->BusTestPtr[0] = 0x55U;
DeviceDataPrv->BusTestPtr[1] = 0xAAU;
}
SDHC_PDD_SetDataTransferWidth(SDHC_BASE_PTR,
(DeviceDataPrv->Substate == SDHC1_CIR_BUS_TEST_4_BIT_WRITE) ?
SDHC_PDD_4_BIT_MODE : SDHC_PDD_8_BIT_MODE);
/* Set data transfer size */
SDHC_PDD_SetBlockSize(SDHC_BASE_PTR,
(DeviceDataPrv->Substate == SDHC1_CIR_BUS_TEST_4_BIT_WRITE) ? 4U : 8U);
SDHC_PDD_SetBlockCount(SDHC_BASE_PTR, 1U);
/* Set DMA transfer properties */
DeviceDataPrv->TransferTable[0].Attributes = SDHC1_SINGLE_BLOCK_TRANS_ATTRS;
DeviceDataPrv->TransferTable[0].Length =
(DeviceDataPrv->Substate == SDHC1_CIR_BUS_TEST_4_BIT_WRITE) ? 4U : 8U;
DeviceDataPrv->TransferTable[0].Address = (uint32_t)DeviceDataPrv->BusTestPtr;
SDHC_PDD_SetADMAAddress(SDHC_BASE_PTR, DeviceDataPrv->TransferTable);
/* Send bus testing pattern write command */
SDHC_PDD_SetCommandArgument(SDHC_BASE_PTR, 0U);
SDHC_PDD_SendCommand(SDHC_BASE_PTR, SDHC_PDD_CMD19_BUS_TEST_WRITE,
SDHC_PDD_ENABLE_DMA | SDHC_PDD_DATA_PRESENT | SDHC_PDD_DATA_WRITE | SDHC_PDD_RESPONSE_LENGTH_48);
break;
case SDHC1_CMD_FINISH:
Error = GetCommandError(DeviceDataPrv, Flags, Response); /* Check host and card error flags */
if (Error == LDD_SDHC_ERR_OK) {
DeviceDataPrv->CmdState = SDHC1_CMD_DATA;
} else {
DeviceDataPrv->LastError = Error;
Finished = TRUE;
}
break;
case SDHC1_CMD_DATA:
Error = GetCommandError(DeviceDataPrv, Flags, SDHC1_NO_RESPONSE); /* Check host error flags */
if ((Error == LDD_SDHC_ERR_OK) || (Error == LDD_SDHC_ERR_DATA_CRC)) {
DeviceDataPrv->Substate =
(DeviceDataPrv->Substate == SDHC1_CIR_BUS_TEST_4_BIT_WRITE) ?
SDHC1_CIR_BUS_TEST_4_BIT_READ : SDHC1_CIR_BUS_TEST_8_BIT_READ;
DeviceDataPrv->CmdState = SDHC1_CMD_START;
CardInfoRetrieval(DeviceDataPrv, 0U, SDHC1_NO_RESPONSE); /* Handle the card info retrieval state */
} else {
DeviceDataPrv->LastError = Error;
DeviceDataPrv->LastErrorAddress = SDHC_PDD_GetDMAAddress(SDHC_BASE_PTR);
Finished = TRUE;
}
break;
default:
break;
}
break;
case SDHC1_CIR_BUS_TEST_4_BIT_READ:
case SDHC1_CIR_BUS_TEST_8_BIT_READ:
switch (DeviceDataPrv->CmdState) {
case SDHC1_CMD_START:
DeviceDataPrv->CmdState = SDHC1_CMD_FINISH;
/* Set data transfer size */
SDHC_PDD_SetBlockSize(SDHC_BASE_PTR,
(DeviceDataPrv->Substate == SDHC1_CIR_BUS_TEST_4_BIT_READ) ? 4U : 8U);
SDHC_PDD_SetBlockCount(SDHC_BASE_PTR, 1U);
/* Set DMA transfer properties */
DeviceDataPrv->TransferTable[0].Attributes = SDHC1_SINGLE_BLOCK_TRANS_ATTRS;
DeviceDataPrv->TransferTable[0].Length =
(DeviceDataPrv->Substate == SDHC1_CIR_BUS_TEST_4_BIT_READ) ? 4U : 8U;
DeviceDataPrv->TransferTable[0].Address = (uint32_t)DeviceDataPrv->BusTestPtr;
SDHC_PDD_SetADMAAddress(SDHC_BASE_PTR, DeviceDataPrv->TransferTable);
/* Send bus testing pattern write command */
SDHC_PDD_SetCommandArgument(SDHC_BASE_PTR, 0U);
SDHC_PDD_SendCommand(SDHC_BASE_PTR, SDHC_PDD_CMD14_BUS_TEST_READ,
SDHC_PDD_ENABLE_DMA | SDHC_PDD_DATA_PRESENT | SDHC_PDD_DATA_READ | SDHC_PDD_RESPONSE_LENGTH_48);
break;
case SDHC1_CMD_FINISH:
Error = GetCommandError(DeviceDataPrv, Flags, Response); /* Check host and card error flags */
if (Error == LDD_SDHC_ERR_OK) {
DeviceDataPrv->CmdState = SDHC1_CMD_DATA;
} else {
DeviceDataPrv->LastError = Error;
Finished = TRUE;
}
break;
case SDHC1_CMD_DATA:
Error = GetCommandError(DeviceDataPrv, Flags, SDHC1_NO_RESPONSE); /* Check host error flags */
if ((Error == LDD_SDHC_ERR_OK) || (Error == LDD_SDHC_ERR_DATA_CRC)) {
if (DeviceDataPrv->Substate == SDHC1_CIR_BUS_TEST_4_BIT_READ) {
/* XNOR the written bus test pattern with the read bus test result */
DeviceDataPrv->BusTestPtr[0] = (DeviceDataPrv->BusTestPtr[0] & 0x5AU) |
((uint8_t)(~DeviceDataPrv->BusTestPtr[0]) & (uint8_t)(~0x5AU));
if (DeviceDataPrv->BusTestPtr[0] == 0U) {
/* 4-bit data bus test succeeded */
DeviceDataPrv->Substate = SDHC1_CIR_BUS_TEST_8_BIT_WRITE;
DeviceDataPrv->CmdState = SDHC1_CMD_START;
DeviceDataPrv->Cards[Id].DataWidths |= LDD_SDHC_CARD_DATA_WIDTH_4_BIT;
} else {
DeviceDataPrv->Substate = SDHC1_CIR_FINISH;
}
} else {
/* XNOR the written bus test pattern with the read bus test result */
DeviceDataPrv->BusTestPtr[0] = (DeviceDataPrv->BusTestPtr[0] & 0x55U) |
((uint8_t)(~DeviceDataPrv->BusTestPtr[0]) & (uint8_t)(~0x55U));
DeviceDataPrv->BusTestPtr[1] = (DeviceDataPrv->BusTestPtr[1] & 0xAAU) |
((uint8_t)(~DeviceDataPrv->BusTestPtr[1]) & (uint8_t)(~0xAAU));
if ((DeviceDataPrv->BusTestPtr[0] == 0U) && (DeviceDataPrv->BusTestPtr[1] == 0U)) {
/* 8-bit data bus test succeeded */
DeviceDataPrv->Cards[Id].DataWidths |= LDD_SDHC_CARD_DATA_WIDTH_8_BIT;
}
DeviceDataPrv->Substate = SDHC1_CIR_FINISH;
}
} else {
DeviceDataPrv->LastError = Error;
DeviceDataPrv->LastErrorAddress = SDHC_PDD_GetDMAAddress(SDHC_BASE_PTR);
Finished = TRUE;
}
if ((DeviceDataPrv->Substate == SDHC1_CIR_FINISH) || Finished) {
/* Restore the data width */
switch (DeviceDataPrv->DataWidth) {
case LDD_SDHC_CARD_DATA_WIDTH_1_BIT:
SDHC_PDD_SetDataTransferWidth(SDHC_BASE_PTR, SDHC_PDD_1_BIT_MODE);
break;
case LDD_SDHC_CARD_DATA_WIDTH_4_BIT:
SDHC_PDD_SetDataTransferWidth(SDHC_BASE_PTR, SDHC_PDD_4_BIT_MODE);
break;
case LDD_SDHC_CARD_DATA_WIDTH_8_BIT:
SDHC_PDD_SetDataTransferWidth(SDHC_BASE_PTR, SDHC_PDD_8_BIT_MODE);
break;
default:
break;
}
}
if (!Finished) {
CardInfoRetrieval(DeviceDataPrv, 0U, SDHC1_NO_RESPONSE); /* Handle the card info retrieval state */
}
break;
default:
break;
}
break;
case SDHC1_CIR_GET_SCR:
switch (DeviceDataPrv->CmdState) {
case SDHC1_CMD_START:
DeviceDataPrv->CmdState = SDHC1_CMD_ACMD;
/* Start application specific command */
SDHC_PDD_SetCommandArgument(SDHC_BASE_PTR,
SDHC1_CMD_ARG_RCA((uint32_t)DeviceDataPrv->Cards[Id].RCA)); /* Set the card RCA (relative card address) as command argument */
SDHC_PDD_SendCommand(SDHC_BASE_PTR,
SDHC_PDD_CMD55_APP_CMD, SDHC_PDD_RESPONSE_LENGTH_48);
break;
case SDHC1_CMD_ACMD:
Error = GetCommandError(DeviceDataPrv, Flags, Response); /* Check host and card error flags */
if (Error == LDD_SDHC_ERR_OK) {
DeviceDataPrv->CmdState = SDHC1_CMD_FINISH;
/* Set data transfer size */
SDHC_PDD_SetBlockSize(SDHC_BASE_PTR, SDHC1_SCR_SIZE);
SDHC_PDD_SetBlockCount(SDHC_BASE_PTR, 1U);
/* Set DMA transfer properties */
/* Configure card detection and DMA mode */
/* SDHC_PROCTL: ??=0,??=0,??=0,??=0,??=0,WECRM=0,WECINS=0,WECINT=0,??=0,??=0,??=0,??=0,IABG=0,RWCTL=0,CREQ=0,SABGREQ=0,??=0,??=0,??=0,??=0,??=0,??=0,DMAS=2,CDSS=0,CDTL=0,EMODE=2,D3CD=0,DTW=0,LCTL=0 */
SDHC_PROCTL = (uint32_t)0x0220UL;
DeviceDataPrv->TransferTable[0].Attributes = SDHC1_SINGLE_BLOCK_TRANS_ATTRS;
DeviceDataPrv->TransferTable[0].Length = SDHC1_SCR_SIZE;
DeviceDataPrv->TransferTable[0].Address = (uint32_t)DeviceDataPrv->Cards[Id].Block;
SDHC_PDD_SetADMAAddress(SDHC_BASE_PTR, DeviceDataPrv->TransferTable);
/* Send SCR (SD card configuration register) request command */
SDHC_PDD_SetCommandArgument(SDHC_BASE_PTR, 0U);
SDHC_PDD_SendCommand(SDHC_BASE_PTR, SDHC_PDD_ACMD51_SEND_SCR,
SDHC_PDD_ENABLE_DMA | SDHC_PDD_DATA_PRESENT | SDHC_PDD_DATA_READ | SDHC_PDD_RESPONSE_LENGTH_48);
} else {
DeviceDataPrv->LastError = Error;
Finished = TRUE;
}
break;
case SDHC1_CMD_FINISH:
Error = GetCommandError(DeviceDataPrv, Flags, Response); /* Check host and card error flags */
if (Error == LDD_SDHC_ERR_OK) {
DeviceDataPrv->CmdState = SDHC1_CMD_DATA;
//CardInfoRetrieval(DeviceDataPrv, 0U, SDHC1_NO_RESPONSE); /* Handle the card info retrieval state */
} else {
DeviceDataPrv->LastError = Error;
Finished = TRUE;
}
break;
case SDHC1_CMD_DATA:
Error = GetCommandError(DeviceDataPrv, Flags, SDHC1_NO_RESPONSE); /* Check host error flags */
if (Error == LDD_SDHC_ERR_OK) {
if (SDHC1_SCR_GET_SD_SPEC((uint32_t)DeviceDataPrv->Cards[Id].Block) != SDHC1_SCR_SD_SPEC_VERS_1_0X) {
/* Check high speed support */
DeviceDataPrv->Substate = SDHC1_CIR_GET_FUNC_STATUS;
DeviceDataPrv->CmdState = SDHC1_CMD_START;
} else {
DeviceDataPrv->Substate = SDHC1_CIR_FINISH;
}
CardInfoRetrieval(DeviceDataPrv, 0U, SDHC1_NO_RESPONSE); /* Handle the card info retrieval state */
} else {
DeviceDataPrv->LastError = Error;
DeviceDataPrv->LastErrorAddress = SDHC_PDD_GetDMAAddress(SDHC_BASE_PTR);
Finished = TRUE;
}
break;
default:
break;
}
break;
case SDHC1_CIR_GET_FUNC_STATUS:
switch (DeviceDataPrv->CmdState) {
case SDHC1_CMD_START:
DeviceDataPrv->CmdState = SDHC1_CMD_FINISH;
/* Set data transfer size */
SDHC_PDD_SetBlockSize(SDHC_BASE_PTR, SDHC1_SFS_SIZE);
SDHC_PDD_SetBlockCount(SDHC_BASE_PTR, 1U);
/* Set DMA transfer properties */
DeviceDataPrv->TransferTable[0].Attributes = SDHC1_SINGLE_BLOCK_TRANS_ATTRS;
DeviceDataPrv->TransferTable[0].Length = SDHC1_SFS_SIZE;
DeviceDataPrv->TransferTable[0].Address = (uint32_t)&DeviceDataPrv->Cards[Id].Block[SDHC1_SFS_BLOCK_START];
SDHC_PDD_SetADMAAddress(SDHC_BASE_PTR, DeviceDataPrv->TransferTable);
/* Send function check command */
SDHC_PDD_SetCommandArgument(SDHC_BASE_PTR,
SDHC1_SD_CMD6_ARG_MODE(SDHC1_SD_CMD6_CHECK_FUNC) |
SDHC1_SD_CMD6_ARG_GROUP_1(SDHC1_SD_CMD6_GROUP_1_HIGH_SPEED));
SDHC_PDD_SendCommand(SDHC_BASE_PTR, SDHC_PDD_CMD6_SWITCH,
SDHC_PDD_ENABLE_DMA | SDHC_PDD_DATA_PRESENT | SDHC_PDD_DATA_READ | SDHC_PDD_RESPONSE_LENGTH_48);
break;
case SDHC1_CMD_FINISH:
Error = GetCommandError(DeviceDataPrv, Flags, Response); /* Check host and card error flags */
if (Error == LDD_SDHC_ERR_OK) {
DeviceDataPrv->CmdState = SDHC1_CMD_DATA;
//CardInfoRetrieval(DeviceDataPrv, 0U, SDHC1_NO_RESPONSE); /* Handle the card info retrieval state */
} else {
DeviceDataPrv->LastError = Error;
Finished = TRUE;
}
break;
case SDHC1_CMD_DATA:
Error = GetCommandError(DeviceDataPrv, Flags, SDHC1_NO_RESPONSE); /* Check host error flags */
if (Error == LDD_SDHC_ERR_OK) {
DeviceDataPrv->Substate = SDHC1_CIR_FINISH;
CardInfoRetrieval(DeviceDataPrv, 0U, SDHC1_NO_RESPONSE); /* Handle the card info retrieval state */
} else {
DeviceDataPrv->LastError = Error;
DeviceDataPrv->LastErrorAddress = SDHC_PDD_GetDMAAddress(SDHC_BASE_PTR);
Finished = TRUE;
}
break;
default:
break;
}
break;
case SDHC1_CIR_FINISH:
Response = DeviceDataPrv->Cards[Id].CSD; /* Get a pointer to card specific data */
InfoPtr = DeviceDataPrv->CardInfoPtr; /* Get a pointer to the user card info variable */
InfoPtr->Type = DeviceDataPrv->CardType; /* Get card type from selected card type */
/* Extract card information from card registers */
InfoPtr->BlockLength = (uint16_t)((uint16_t)1U << SDHC1_R2_GET_READ_BL_LEN(Response)); /* Block length = 2^READ_BL_LEN */
if ((DeviceDataPrv->CardType != LDD_SDHC_SD) || (SDHC1_R2_GET_CSD_STRUCTURE(Response) == SDHC1_SD_CSD_VERS_1_0)) {
/* CSD (card specific data) version 1.0 */
/* Block count = (C_SIZE + 1) * (2^(C_SIZE_MULT + 2)) */
InfoPtr->BlockCount = (uint16_t)(SDHC1_R2_CSD_V1_GET_C_SIZE(Response) + 1U) *
(uint16_t)((uint16_t)1U << (SDHC1_R2_CSD_V1_GET_C_SIZE_MULT(Response) + 2U));
} else {
/* CSD (card specific data) version 2.0 */
/* Block count = (C_SIZE + 1) * 1k */
InfoPtr->BlockCount = (SDHC1_R2_CSD_V2_GET_C_SIZE(Response) + 1U) * 1024U;
}
InfoPtr->Caps.Operations = (uint8_t)(SDHC1_R2_GET_CCC(Response) >> 2); /* Shift card command classes to fit into a byte (omitting mandatory classes) */
InfoPtr->Caps.HighCapacity = DeviceDataPrv->Cards[Id].HighCapacity; /* Get high capacity flag acquired during voltage validation */
InfoPtr->Caps.LowVoltage = (DeviceDataPrv->CardsVoltages & SDHC1_OCR_LOW_VOLTAGE_MASK) ? TRUE : FALSE; /* Get low voltage support flag acquired during voltage validation */
InfoPtr->Caps.Read.MaxBlockLength = (uint16_t)((uint16_t)1U << SDHC1_R2_GET_READ_BL_LEN(Response)); /* Max. read block length = 2^READ_BL_LEN */
InfoPtr->Caps.Read.MisalignBlock = (SDHC1_R2_GET_READ_BLK_MISALIGN(Response)) ? TRUE : FALSE;
InfoPtr->Caps.Read.PartialBlock = (SDHC1_R2_GET_READ_BL_PARTIAL(Response)) ? TRUE : FALSE;
InfoPtr->Caps.Write.MaxBlockLength = (uint16_t)((uint16_t)1U << SDHC1_R2_GET_WRITE_BL_LEN(Response)); /* Max. write block length = 2^WRITE_BL_LEN */
InfoPtr->Caps.Write.MisalignBlock = (SDHC1_R2_GET_WRITE_BLK_MISALIGN(Response)) ? TRUE : FALSE;
InfoPtr->Caps.Write.PartialBlock = (SDHC1_R2_GET_WRITE_BL_PARTIAL(Response)) ? TRUE : FALSE;
InfoPtr->Caps.WriteProtect.Permanent = (SDHC1_R2_GET_PERM_WRITE_PROTECT(Response)) ? TRUE : FALSE;
if (DeviceDataPrv->CardType == LDD_SDHC_MMC) {
InfoPtr->Caps.DataWidths = DeviceDataPrv->Cards[Id].DataWidths; /* Get data widths acquired during bus testing procedure */
InfoPtr->Caps.HighSpeed = (SDHC1_R2_MMC_GET_SPEC_VERS(Response) == SDHC1_MMC_CSD_SPEC_VERS_4_X) ? TRUE : FALSE; /* High speed supported by MMC cards from version 4.0 */
/* Erase sector size = (ERASE_GRP_SIZE + 1) * (ERASE_GRP_MULT + 1) */
InfoPtr->Caps.Erase.SectorSize = (uint16_t)((SDHC1_R2_MMC_GET_ERASE_GRP_SIZE(Response) + 1U) *
(SDHC1_R2_MMC_GET_ERASE_GRP_MULT(Response) + 1U));
/* Get erased memory byte content from the extended CSD (card specific data) register */
InfoPtr->Caps.Erase.Pattern = DeviceDataPrv->Cards[Id].Block[SDHC1_EXT_CSD_ERASED_MEM_CONT_INDEX];
/* Write protection group size = WP_GRP_SIZE + 1 */
InfoPtr->Caps.WriteProtect.GroupSize = (uint16_t)((SDHC1_R2_GET_WP_GRP_ENABLE(Response)) ?
(SDHC1_R2_MMC_GET_WP_GRP_SIZE(Response) + 1U) : 0U);
} else {
BusWidths = (uint8_t)SDHC1_SCR_GET_SD_BUS_WIDTHS((uint32_t)DeviceDataPrv->Cards[Id].Block);
InfoPtr->Caps.DataWidths = (uint8_t) /* Map SCR (SD card configuration register) values to component constants */
(((BusWidths & SDHC1_SCR_SD_BUS_WIDTH_1_BIT_MASK) ? LDD_SDHC_CARD_DATA_WIDTH_1_BIT : 0U) |
((BusWidths & SDHC1_SCR_SD_BUS_WIDTH_4_BIT_MASK) ? LDD_SDHC_CARD_DATA_WIDTH_4_BIT : 0U));
if (SDHC1_SCR_GET_SD_SPEC((uint32_t)DeviceDataPrv->Cards[Id].Block) == SDHC1_SCR_SD_SPEC_VERS_1_0X) {
/* High speed is not supported in this version of SD card specification */
InfoPtr->Caps.HighSpeed = FALSE;
} else {
/* Get high speed support flag acquired during high speed function check */
InfoPtr->Caps.HighSpeed = (SDHC1_SFS_IS_FUNC_SUPPORTED(
(uint32_t)&DeviceDataPrv->Cards[Id].Block[SDHC1_SFS_BLOCK_START],
SDHC1_SFS_HIGH_SPEED_FUNC_GROUP, SDHC1_SFS_HIGH_SPEED_FUNC_INDEX)) ? TRUE : FALSE;
}
InfoPtr->Caps.Erase.SectorSize = (uint16_t)(SDHC1_R2_SD_GET_SECTOR_SIZE(Response) + 1U);
InfoPtr->Caps.Erase.Pattern = (uint8_t) /* Erase memory byte content is defined by a data status flag */
((SDHC1_SCR_GET_DATA_STAT_AFTER_ERASE((uint32_t)DeviceDataPrv->Cards[Id].Block)) ? 0xFFU : 0x00U);
if (SDHC1_R2_GET_CSD_STRUCTURE(Response) == SDHC1_SD_CSD_VERS_2_0) {
/* CSD (card specific data) structure version 2.0 */
InfoPtr->Caps.WriteProtect.GroupSize = (uint16_t)0U;
} else {
/* CSD (card specific data) structure version 1.0 */
InfoPtr->Caps.WriteProtect.GroupSize = (uint16_t)((SDHC1_R2_GET_WP_GRP_ENABLE(Response)) ?
(SDHC1_R2_SD_GET_WP_GRP_SIZE(Response) + 1U) : 0U);
}
}
Finished = TRUE;
break;
default:
break;
}
if (Finished) {
DeviceDataPrv->State = LDD_SDHC_IDLE;
if (DeviceDataPrv->EventMask & LDD_SDHC_ON_FINISHED) {
SDHC1_OnFinished(DeviceDataPrv->UserDataPtr); /* Call the user event */
}
}
}
/*
** ===================================================================
** Method : CardSelection (component SDHC_LDD)
**
** Description :
** Card selection state handler.
** This method is internal. It is used by Processor Expert only.
** ===================================================================
*/
static bool CardSelection(LDD_SDHC1_TDeviceData *DeviceDataPtr, uint32_t Flags, uint32_t *Response)
{
LDD_SDHC1_TDeviceData *DeviceDataPrv = (LDD_SDHC1_TDeviceData*)DeviceDataPtr;
bool Finished = FALSE; /* Indicates card selection end */
LDD_SDHC_TError Error = LDD_SDHC_ERR_OK; /* Error code storage */
uint8_t Id = DeviceDataPrv->CardId; /* Card ID storage */
Error = GetCommandError(DeviceDataPrv, Flags, Response); /* Check host and card error flags */
if ((Error == LDD_SDHC_ERR_OK) && Response) {
if (SDHC1_R1_IS_READY_FOR_DATA(Response)) {
/* By card selection card has changed its state to transfer */
DeviceDataPrv->CardState = SDHC1_TRANSFER;
Finished = TRUE;
} else {
/* Send status request command again */
SendCardStatusRequest(DeviceDataPrv);
}
} else {
if (Id != SDHC1_NO_CARD) {
DeviceDataPrv->LastError = Error;
DeviceDataPrv->Cards[Id].Initialized = FALSE;
DeviceDataPrv->CardId = SDHC1_NO_CARD; /* Card has been removed */
if (DeviceDataPrv->EventMask & LDD_SDHC_ON_CARD_REMOVED) {
SDHC1_OnCardRemoved(DeviceDataPrv->UserDataPtr, Id); /* Call the user event */
}
} else {
if (Error != LDD_SDHC_ERR_TIMEOUT) {
DeviceDataPrv->LastError = Error;
}
}
Finished = TRUE;
}
return Finished;
}
/*
** ===================================================================
** Method : Transfer (component SDHC_LDD)
**
** Description :
** Transfer state handler.
** This method is internal. It is used by Processor Expert only.
** ===================================================================
*/
static bool Transfer(LDD_SDHC1_TDeviceData *DeviceDataPtr, uint32_t Flags, uint32_t *Response)
{
LDD_SDHC1_TDeviceData *DeviceDataPrv = (LDD_SDHC1_TDeviceData*)DeviceDataPtr;
bool Finished = FALSE; /* Indicates transfer end */
LDD_SDHC_TError Error = LDD_SDHC_ERR_OK; /* Error code storage */
switch (DeviceDataPrv->CmdState) {
case SDHC1_CMD_DATA_LEN:
DeviceDataPrv->CmdState = SDHC1_CMD_START;
/* Send block length */
SDHC_PDD_SetCommandArgument(SDHC_BASE_PTR, DeviceDataPrv->TransferBlockSize);
SDHC_PDD_SendCommand(SDHC_BASE_PTR,
SDHC_PDD_CMD16_SET_BLOCKLEN, SDHC_PDD_RESPONSE_LENGTH_48);
break;
case SDHC1_CMD_START:
Error = GetCommandError(DeviceDataPrv, Flags, Response); /* Check host and card error flags */
if (Error == LDD_SDHC_ERR_OK) {
if (DeviceDataPrv->Cancel) {
Finished = TRUE;
} else {
DeviceDataPrv->CmdState = SDHC1_CMD_FINISH;
SDHC_PDD_SetADMAAddress(SDHC_BASE_PTR, DeviceDataPrv->TransferTable);
/* Set block attributes */
SDHC_PDD_SetBlockSize(SDHC_BASE_PTR, DeviceDataPrv->TransferBlockSize);
SDHC_PDD_SetBlockCount(SDHC_BASE_PTR, DeviceDataPrv->TransferBlockCount);
/* Send transfer command */
SDHC_PDD_SetCommandArgument(SDHC_BASE_PTR, DeviceDataPrv->Address);
SDHC_PDD_SendCommand(SDHC_BASE_PTR,
((DeviceDataPrv->TransferOperation == LDD_SDHC_READ) ?
(uint32_t)((DeviceDataPrv->TransferBlockCount > 1U) ?
SDHC_PDD_CMD18_READ_MULTIPLE_BLOCK : SDHC_PDD_CMD17_READ_SINGLE_BLOCK) :
(uint32_t)((DeviceDataPrv->TransferBlockCount > 1U) ?
SDHC_PDD_CMD25_WRITE_MULTIPLE_BLOCK : SDHC_PDD_CMD24_WRITE_BLOCK)),
((DeviceDataPrv->TransferBlockCount > 1U) ?
(SDHC_PDD_ENABLE_BLOCK_COUNT | SDHC_PDD_ENABLE_AUTO_CMD12 | SDHC_PDD_MULTIPLE_BLOCK) : 0U) |
SDHC_PDD_ENABLE_DMA | SDHC_PDD_DATA_PRESENT | SDHC_PDD_RESPONSE_LENGTH_48 |
((DeviceDataPrv->TransferOperation == LDD_SDHC_READ) ?
SDHC_PDD_DATA_READ : SDHC_PDD_DATA_WRITE));
}
} else {
DeviceDataPrv->LastError = Error;
Finished = TRUE;
}
break;
case SDHC1_CMD_FINISH:
Error = GetCommandError(DeviceDataPrv, Flags, Response); /* Check host and card error flags */
if (Error == LDD_SDHC_ERR_OK) {
DeviceDataPrv->CmdState = SDHC1_CMD_DATA;
} else {
DeviceDataPrv->LastError = Error;
Finished = TRUE;
}
break;
case SDHC1_CMD_DATA:
Error = GetCommandError(DeviceDataPrv, Flags, SDHC1_NO_RESPONSE); /* Check host error flags */
if (Error == LDD_SDHC_ERR_OK) {
DeviceDataPrv->CmdState = SDHC1_CMD_ERROR;
SendCardStatusRequest(DeviceDataPrv);
} else {
DeviceDataPrv->LastError = Error;
DeviceDataPrv->LastErrorAddress = SDHC_PDD_GetDMAAddress(SDHC_BASE_PTR);
Finished = TRUE;
}
break;
case SDHC1_CMD_ERROR:
Error = GetCommandError(DeviceDataPrv, Flags, Response); /* Check host and card error flags */
if ((Error == LDD_SDHC_ERR_OK) && Response) {
if (SDHC1_R1_IS_READY_FOR_DATA(Response)) {
Finished = TRUE;
} else {
/* Send status request command again */
SendCardStatusRequest(DeviceDataPrv);
}
} else {
DeviceDataPrv->LastError = Error;
Finished = TRUE;
}
break;
default:
break;
}
return Finished;
}
/*
** ===================================================================
** Method : Erasion (component SDHC_LDD)
**
** Description :
** Erasion state handler.
** This method is internal. It is used by Processor Expert only.
** ===================================================================
*/
static bool Erasion(LDD_SDHC1_TDeviceData *DeviceDataPtr, uint32_t Flags, uint32_t *Response)
{
LDD_SDHC1_TDeviceData *DeviceDataPrv = (LDD_SDHC1_TDeviceData*)DeviceDataPtr;
bool Finished = FALSE; /* Indicates erasion end */
LDD_SDHC_TError Error = LDD_SDHC_ERR_OK; /* Error code storage */
switch (DeviceDataPrv->Substate) {
case SDHC1_E_SET_START:
DeviceDataPrv->Substate = SDHC1_E_SET_END;
/* Send tag erase start command */
SDHC_PDD_SetCommandArgument(SDHC_BASE_PTR, DeviceDataPrv->ErasionStart);
SDHC_PDD_SendCommand(SDHC_BASE_PTR,
((DeviceDataPrv->CardType == LDD_SDHC_MMC) ? /* Handle different command indices for different card types */
SDHC_PDD_CMD35_TAG_ERASE_GROUP_START : SDHC_PDD_CMD32_TAG_SECTOR_START),
SDHC_PDD_RESPONSE_LENGTH_48);
break;
case SDHC1_E_SET_END:
Error = GetCommandError(DeviceDataPrv, Flags, Response); /* Check host and card error flags */
if (Error == LDD_SDHC_ERR_OK) {
DeviceDataPrv->Substate = SDHC1_E_EXECUTE;
/* Send tag erase end command */
SDHC_PDD_SetCommandArgument(SDHC_BASE_PTR, DeviceDataPrv->ErasionEnd);
SDHC_PDD_SendCommand(SDHC_BASE_PTR,
((DeviceDataPrv->CardType == LDD_SDHC_MMC) ? /* Handle different command indices for different card types */
SDHC_PDD_CMD36_TAG_ERASE_GROUP_END : SDHC_PDD_CMD33_TAG_SECTOR_END),
SDHC_PDD_RESPONSE_LENGTH_48);
} else {
DeviceDataPrv->LastError = Error;
Finished = TRUE;
}
break;
case SDHC1_E_EXECUTE:
Error = GetCommandError(DeviceDataPrv, Flags, Response); /* Check host and card error flags */
if (Error == LDD_SDHC_ERR_OK) {
DeviceDataPrv->Substate = SDHC1_E_FINISH;
/* Send erase command */
SDHC_PDD_SetCommandArgument(SDHC_BASE_PTR, 0U);
SDHC_PDD_SendCommand(SDHC_BASE_PTR,
SDHC_PDD_CMD38_ERASE, SDHC_PDD_RESPONSE_LENGTH_48_BUSY_CHECK);
} else {
DeviceDataPrv->LastError = Error;
Finished = TRUE;
}
break;
case SDHC1_E_FINISH:
Error = GetCommandError(DeviceDataPrv, Flags, Response); /* Check host and card error flags */
if ((Error == LDD_SDHC_ERR_OK) && Response) {
/* Check whether erasion has finished */
if (SDHC1_R1_IS_READY_FOR_DATA(Response)) {
Finished = TRUE;
} else {
/* Send status request command again */
SendCardStatusRequest(DeviceDataPrv);
}
} else {
DeviceDataPrv->LastError = Error;
Finished = TRUE;
}
break;
default:
break;
}
return Finished;
}
/*
** ===================================================================
** Method : DataWidthSelection (component SDHC_LDD)
**
** Description :
** Data width selection state handler.
** This method is internal. It is used by Processor Expert only.
** ===================================================================
*/
static bool DataWidthSelection(LDD_SDHC1_TDeviceData *DeviceDataPtr, uint32_t Flags, uint32_t *Response)
{
LDD_SDHC1_TDeviceData *DeviceDataPrv = (LDD_SDHC1_TDeviceData*)DeviceDataPtr;
bool Finished = FALSE; /* Indicates data width selection end */
LDD_SDHC_TError Error = LDD_SDHC_ERR_OK; /* Error code storage */
uint8_t Id = DeviceDataPrv->CardId; /* Card ID storage */
uint8_t Argument = 0U; /* Command argument */
if (DeviceDataPrv->CardType == LDD_SDHC_MMC) {
switch (DeviceDataPrv->CmdState) {
case SDHC1_CMD_START:
DeviceDataPrv->CmdState = SDHC1_CMD_FINISH;
/* Map data width to an extended CSD (card specific data) register field value */
switch (DeviceDataPrv->DataWidth) {
case LDD_SDHC_CARD_DATA_WIDTH_1_BIT:
Argument = 0U;
break;
case LDD_SDHC_CARD_DATA_WIDTH_4_BIT:
Argument = 1U;
break;
case LDD_SDHC_CARD_DATA_WIDTH_8_BIT:
Argument = 2U;
break;
default:
break;
}
/* Send switch command */
SDHC_PDD_SetCommandArgument(SDHC_BASE_PTR,
SDHC1_MMC_CMD6_ARG_ACCESS(SDHC1_MMC_CMD6_WRITE_BYTES) |
SDHC1_MMC_CMD6_ARG_INDEX(SDHC1_EXT_CSD_BUS_WIDTH_INDEX) |
SDHC1_MMC_CMD6_ARG_VALUE(Argument));
SDHC_PDD_SendCommand(SDHC_BASE_PTR,
SDHC_PDD_CMD6_SWITCH, SDHC_PDD_RESPONSE_LENGTH_48);
break;
case SDHC1_CMD_FINISH:
Error = GetCommandError(DeviceDataPrv, Flags, Response); /* Check host and card error flags */
if ((Error == LDD_SDHC_ERR_OK) && Response) {
if (SDHC1_R1_IS_READY_FOR_DATA(Response)) {
/* Map data widths to host register field values */
switch (DeviceDataPrv->DataWidth) {
case LDD_SDHC_CARD_DATA_WIDTH_1_BIT:
SDHC_PDD_SetDataTransferWidth(SDHC_BASE_PTR, SDHC_PDD_1_BIT_MODE);
break;
case LDD_SDHC_CARD_DATA_WIDTH_4_BIT:
SDHC_PDD_SetDataTransferWidth(SDHC_BASE_PTR, SDHC_PDD_4_BIT_MODE);
break;
case LDD_SDHC_CARD_DATA_WIDTH_8_BIT:
SDHC_PDD_SetDataTransferWidth(SDHC_BASE_PTR, SDHC_PDD_8_BIT_MODE);
break;
default:
break;
}
Finished = TRUE;
} else {
/* Send status request command again */
SendCardStatusRequest(DeviceDataPrv);
}
} else {
DeviceDataPrv->LastError = Error;
Finished = TRUE;
}
break;
default:
break;
}
} else {
switch (DeviceDataPrv->CmdState) {
case SDHC1_CMD_START:
DeviceDataPrv->CmdState = SDHC1_CMD_ACMD;
/* Start application specific command */
SDHC_PDD_SetCommandArgument(SDHC_BASE_PTR,
SDHC1_CMD_ARG_RCA(DeviceDataPrv->Cards[Id].RCA));
SDHC_PDD_SendCommand(SDHC_BASE_PTR,
SDHC_PDD_CMD55_APP_CMD, SDHC_PDD_RESPONSE_LENGTH_48);
break;
case SDHC1_CMD_ACMD:
Error = GetCommandError(DeviceDataPrv, Flags, Response); /* Check host and card error flags */
if (Error == LDD_SDHC_ERR_OK) {
DeviceDataPrv->CmdState = SDHC1_CMD_FINISH;
/* Map data widths to card register field values */
switch (DeviceDataPrv->DataWidth) {
case LDD_SDHC_CARD_DATA_WIDTH_1_BIT:
SDHC_PDD_SetCommandArgument(SDHC_BASE_PTR, 0U);
break;
case LDD_SDHC_CARD_DATA_WIDTH_4_BIT:
SDHC_PDD_SetCommandArgument(SDHC_BASE_PTR, 2U);
break;
default:
break;
}
/* Send bus width set command */
SDHC_PDD_SendCommand(SDHC_BASE_PTR,
SDHC_PDD_ACMD6_SET_BUS_WIDTH, SDHC_PDD_RESPONSE_LENGTH_48);
} else {
DeviceDataPrv->LastError = Error;
Finished = TRUE;
}
break;
case SDHC1_CMD_FINISH:
Error = GetCommandError(DeviceDataPrv, Flags, Response); /* Check host and card error flags */
if (Error == LDD_SDHC_ERR_OK) {
/* Map data widths to host register field values */
switch (DeviceDataPrv->DataWidth) {
case LDD_SDHC_CARD_DATA_WIDTH_1_BIT:
SDHC_PDD_SetDataTransferWidth(SDHC_BASE_PTR, SDHC_PDD_1_BIT_MODE);
break;
case LDD_SDHC_CARD_DATA_WIDTH_4_BIT:
SDHC_PDD_SetDataTransferWidth(SDHC_BASE_PTR, SDHC_PDD_4_BIT_MODE);
break;
default:
break;
}
} else {
DeviceDataPrv->LastError = Error;
}
Finished = TRUE;
break;
default:
break;
}
}
return Finished;
}
/*
** ===================================================================
** Method : BusClockSelection (component SDHC_LDD)
**
** Description :
** Bus clock selection state handler.
** This method is internal. It is used by Processor Expert only.
** ===================================================================
*/
static bool BusClockSelection(LDD_SDHC1_TDeviceData *DeviceDataPtr, uint32_t Flags, uint32_t *Response)
{
LDD_SDHC1_TDeviceData *DeviceDataPrv = (LDD_SDHC1_TDeviceData*)DeviceDataPtr;
bool Finished = FALSE; /* Indicates bus clock selection end */
LDD_SDHC_TError Error = LDD_SDHC_ERR_OK; /* Error code storage */
uint8_t Id = DeviceDataPrv->CardId; /* Card ID storage */
switch (DeviceDataPrv->CmdState) {
case SDHC1_CMD_START:
DeviceDataPrv->CmdState = SDHC1_CMD_FINISH;
if (DeviceDataPrv->Cards[Id].Type == LDD_SDHC_MMC) {
/* Send switch command */
SDHC_PDD_SetCommandArgument(SDHC_BASE_PTR,
SDHC1_MMC_CMD6_ARG_ACCESS(SDHC1_MMC_CMD6_WRITE_BYTES) |
SDHC1_MMC_CMD6_ARG_INDEX(SDHC1_EXT_CSD_HS_TIMING_INDEX) |
SDHC1_MMC_CMD6_ARG_VALUE(1));
SDHC_PDD_SendCommand(SDHC_BASE_PTR,
SDHC_PDD_CMD6_SWITCH, SDHC_PDD_RESPONSE_LENGTH_48);
} else {
/* Send function switch command */
SDHC_PDD_SetCommandArgument(SDHC_BASE_PTR,
SDHC1_SD_CMD6_ARG_MODE(SDHC1_SD_CMD6_SWITCH_FUNC) |
SDHC1_SD_CMD6_ARG_GROUP_1(SDHC1_SD_CMD6_GROUP_1_HIGH_SPEED));
SDHC_PDD_SendCommand(SDHC_BASE_PTR,
SDHC_PDD_CMD6_SWITCH, SDHC_PDD_RESPONSE_LENGTH_48_BUSY_CHECK);
}
break;
case SDHC1_CMD_FINISH:
Finished = TRUE;
Error = GetCommandError(DeviceDataPrv, Flags, Response); /* Check host and card error flags */
if ((Error == LDD_SDHC_ERR_OK) && Response) {
if (DeviceDataPrv->CardType == LDD_SDHC_MMC) {
if (!SDHC1_R1_IS_READY_FOR_DATA(Response)) {
/* Send status request command again */
SendCardStatusRequest(DeviceDataPrv);
Finished = FALSE;
}
}
}
if (Finished) {
SetBusClockPrescalers(DeviceDataPrv, DeviceDataPrv->Frequency);
}
break;
default:
break;
}
return Finished;
}
/*
** ===================================================================
** Method : WriteProtectionSetup (component SDHC_LDD)
**
** Description :
** Write protection setup state handler.
** This method is internal. It is used by Processor Expert only.
** ===================================================================
*/
static bool WriteProtectionSetup(LDD_SDHC1_TDeviceData *DeviceDataPtr, uint32_t Flags, uint32_t *Response)
{
LDD_SDHC1_TDeviceData *DeviceDataPrv = (LDD_SDHC1_TDeviceData*)DeviceDataPtr;
bool Finished = FALSE; /* Indicates write protection setup end */
LDD_SDHC_TError Error = LDD_SDHC_ERR_OK; /* Error code storage */
uint8_t Id = DeviceDataPrv->CardId; /* Card ID storage */
uint32_t Index; /* Array index */
if (DeviceDataPrv->WriteProtType == LDD_SDHC_GROUP) {
switch (DeviceDataPrv->CmdState) {
case SDHC1_CMD_START:
DeviceDataPrv->CmdState = SDHC1_CMD_FINISH;
/* Send write protection set/clear command */
SDHC_PDD_SetCommandArgument(SDHC_BASE_PTR, DeviceDataPrv->Address);
SDHC_PDD_SendCommand(SDHC_BASE_PTR,
(DeviceDataPrv->WriteProtFlag ? /* Choose write protection set or clear command */
SDHC_PDD_CMD28_SET_WRITE_PROT : SDHC_PDD_CMD29_CLR_WRITE_PROT),
SDHC_PDD_RESPONSE_LENGTH_48_BUSY_CHECK);
break;
case SDHC1_CMD_FINISH:
Error = GetCommandError(DeviceDataPrv, Flags, Response); /* Check host and card error flags */
if ((Error == LDD_SDHC_ERR_OK) && Response) {
if (SDHC1_R1_IS_READY_FOR_DATA(Response)) {
Finished = TRUE;
} else {
/* Send status request command again */
SendCardStatusRequest(DeviceDataPrv);
}
} else {
DeviceDataPrv->LastError = Error;
Finished = TRUE;
}
break;
default:
break;
}
} else {
switch (DeviceDataPrv->CmdState) {
case SDHC1_CMD_START:
DeviceDataPrv->CmdState = SDHC1_CMD_FINISH;
/* Order CSD (card specific data) register bytes from MSB to LSB */
for (Index = 0U; Index < (SDHC1_CSD_SIZE - 1U); Index++) {
DeviceDataPrv->CSDPtr[(SDHC1_CSD_SIZE - 1U) - (Index + 1U)] =
(uint8_t)((uint32_t)DeviceDataPrv->Cards[Id].CSD[Index / 4U] >> (8 * ((int32_t)Index % 4))) & 0xFFU;
}
/* Set block attributes */
SDHC_PDD_SetBlockSize(SDHC_BASE_PTR, SDHC1_CSD_SIZE);
SDHC_PDD_SetBlockCount(SDHC_BASE_PTR, 1U);
/* Set DMA transfer properties */
DeviceDataPrv->TransferTable[0].Attributes = SDHC1_SINGLE_BLOCK_TRANS_ATTRS;
DeviceDataPrv->TransferTable[0].Length = SDHC1_CSD_SIZE;
DeviceDataPrv->TransferTable[0].Address = (uint32_t)DeviceDataPrv->CSDPtr;
SDHC_PDD_SetADMAAddress(SDHC_BASE_PTR, DeviceDataPrv->TransferTable);
/* Program CSD (card specific data) register */
SDHC_PDD_SetCommandArgument(SDHC_BASE_PTR, 0U);
SDHC_PDD_SendCommand(SDHC_BASE_PTR, SDHC_PDD_CMD27_PROGRAM_CSD,
SDHC_PDD_ENABLE_DMA | SDHC_PDD_DATA_PRESENT | SDHC_PDD_DATA_WRITE | SDHC_PDD_RESPONSE_LENGTH_48);
break;
case SDHC1_CMD_FINISH:
Error = GetCommandError(DeviceDataPrv, Flags, Response); /* Check host and card error flags */
if (Error == LDD_SDHC_ERR_OK) {
DeviceDataPrv->CmdState = SDHC1_CMD_DATA;
} else {
DeviceDataPrv->LastError = Error;
Finished = TRUE;
}
break;
case SDHC1_CMD_DATA:
Error = GetCommandError(DeviceDataPrv, Flags, SDHC1_NO_RESPONSE); /* Check host error flags */
if (Error != LDD_SDHC_ERR_OK) {
DeviceDataPrv->LastError = Error;
DeviceDataPrv->LastErrorAddress = SDHC_PDD_GetDMAAddress(SDHC_BASE_PTR);
}
Finished = TRUE;
break;
default:
break;
}
}
return Finished;
}
/*
** ===================================================================
** Method : WriteProtectionRetrieval (component SDHC_LDD)
**
** Description :
** Write protection retrieval state handler.
** This method is internal. It is used by Processor Expert only.
** ===================================================================
*/
static bool WriteProtectionRetrieval(LDD_SDHC1_TDeviceData *DeviceDataPtr, uint32_t Flags, uint32_t *Response)
{
LDD_SDHC1_TDeviceData *DeviceDataPrv = (LDD_SDHC1_TDeviceData*)DeviceDataPtr;
bool Finished = FALSE; /* Indicates write protection retrieval end */
LDD_SDHC_TError Error = LDD_SDHC_ERR_OK; /* Error code storage */
switch (DeviceDataPrv->CmdState) {
case SDHC1_CMD_START:
DeviceDataPrv->CmdState = SDHC1_CMD_FINISH;
/* Set block attributes */
SDHC_PDD_SetBlockSize(SDHC_BASE_PTR, SDHC1_WRITE_PROTECT_MASK_SIZE);
SDHC_PDD_SetBlockCount(SDHC_BASE_PTR, 1U);
/* Set DMA transfer properties */
DeviceDataPrv->TransferTable[0].Attributes = SDHC1_SINGLE_BLOCK_TRANS_ATTRS;
DeviceDataPrv->TransferTable[0].Length = SDHC1_WRITE_PROTECT_MASK_SIZE;
DeviceDataPrv->TransferTable[0].Address = (uint32_t)DeviceDataPrv->WriteProtMaskPtr;
SDHC_PDD_SetADMAAddress(SDHC_BASE_PTR, DeviceDataPrv->TransferTable);
/* Send write protection mask request command */
SDHC_PDD_SetCommandArgument(SDHC_BASE_PTR, DeviceDataPrv->Address);
SDHC_PDD_SendCommand(SDHC_BASE_PTR, SDHC_PDD_CMD30_SEND_WRITE_PROT,
SDHC_PDD_ENABLE_DMA | SDHC_PDD_DATA_PRESENT | SDHC_PDD_DATA_READ | SDHC_PDD_RESPONSE_LENGTH_48);
break;
case SDHC1_CMD_FINISH:
Error = GetCommandError(DeviceDataPrv, Flags, Response); /* Check host and card error flags */
if (Error == LDD_SDHC_ERR_OK) {
DeviceDataPrv->CmdState = SDHC1_CMD_DATA;
} else {
DeviceDataPrv->LastError = Error;
Finished = TRUE;
}
break;
case SDHC1_CMD_DATA:
Error = GetCommandError(DeviceDataPrv, Flags, SDHC1_NO_RESPONSE); /* Check host error flags */
if (Error != LDD_SDHC_ERR_OK) {
DeviceDataPrv->LastError = Error;
DeviceDataPrv->LastErrorAddress = SDHC_PDD_GetDMAAddress(SDHC_BASE_PTR);
}
Finished = TRUE;
break;
default:
break;
}
return Finished;
}
/*
** ===================================================================
** Method : SetBusClockPrescalers (component SDHC_LDD)
**
** Description :
** Bus clock prescalers setup.
** This method is internal. It is used by Processor Expert only.
** ===================================================================
*/
static void SetBusClockPrescalers(LDD_SDHC1_TDeviceData *DeviceDataPtr, SDHC1_TBusClock Frequency)
{
LDD_SDHC1_TDeviceData *DeviceDataPrv = (LDD_SDHC1_TDeviceData*)DeviceDataPtr;
static const uint8_t PrescalerValues[][1][2] = { /* Frequency select and divisor values for bus clock frequencies selected by property */
{{ 64u, 0u }},
{{ 2u, 0u }},
{{ 1u, 0u }}
};
SDHC_PDD_EnableSDHCClock(SDHC_BASE_PTR, FALSE);
SDHC_PDD_SetSDHCClockFrequency(SDHC_BASE_PTR,
PrescalerValues[Frequency][DeviceDataPrv->SpeedMode][0]);
SDHC_PDD_SetSDHCClockDivisor(SDHC_BASE_PTR,
PrescalerValues[Frequency][DeviceDataPrv->SpeedMode][1]);
while (!SDHC_PDD_IsSDClockStable(SDHC_BASE_PTR)) {} /* Wait for clock to stabilize */
SDHC_PDD_EnableSDHCClock(SDHC_BASE_PTR, TRUE);
}
/*
** ===================================================================
** Method : GetCommandError (component SDHC_LDD)
**
** Description :
** Extracts error code from the device error flags and the card
** status response.
** This method is internal. It is used by Processor Expert only.
** ===================================================================
*/
static LDD_SDHC_TError GetCommandError(LDD_SDHC1_TDeviceData *DeviceDataPtr, uint32_t Flags, uint32_t *Response)
{
LDD_SDHC_TError Error = LDD_SDHC_ERR_OK; /* Error code storage */
uint32_t AutoCMD12ErrorFlags = SDHC_PDD_GetAutoCMD12ErrorFlags(SDHC_BASE_PTR); /* Auto CMD12 error flags */
(void)DeviceDataPtr; /* Suppress unused parameter warning */
/* Map host error flags to component error codes */
if ((Flags & (SDHC_PDD_COMMAND_TIMEOUT_ERROR_INT | SDHC_PDD_DATA_TIMEOUT_ERROR_INT)) ||
((Flags & SDHC_PDD_AUTO_CMD12_ERROR_INT) && (AutoCMD12ErrorFlags & SDHC_PDD_AUTO_CMD12_TIMEOUT_ERROR))) {
Error = LDD_SDHC_ERR_TIMEOUT;
} else if ((Flags & (SDHC_PDD_COMMAND_CRC_ERROR_INT | SDHC_PDD_COMMAND_END_BIT_ERROR_INT |
SDHC_PDD_COMMAND_INDEX_ERROR_INT)) || ((Flags & SDHC_PDD_AUTO_CMD12_ERROR_INT) &&
(AutoCMD12ErrorFlags & (SDHC_PDD_AUTO_CMD12_CRC_ERROR | SDHC_PDD_AUTO_CMD12_END_BIT_ERROR | SDHC_PDD_AUTO_CMD12_INDEX_ERROR)))) {
Error = LDD_SDHC_ERR_COMMAND_CRC;
} else if (Flags & (SDHC_PDD_DATA_CRC_ERROR_INT | SDHC_PDD_DATA_END_BIT_ERROR_INT)) {
Error = LDD_SDHC_ERR_DATA_CRC;
} else if (Flags & SDHC_PDD_DMA_ERROR_INT) {
Error = LDD_SDHC_ERR_DMA;
} else {
Error = LDD_SDHC_ERR_OK;
}
if ((Error == LDD_SDHC_ERR_OK) && Response) {
/* Map card error flags to component error codes */
if (SDHC1_R1_IS_ERASE_RESET(Response) ||
SDHC1_R1_IS_CSD_OVERWRITE(Response) ||
SDHC1_R1_IS_ERASE_SEQ_ERROR(Response) ||
SDHC1_R1_IS_ILLEGAL_COMMAND(Response)) {
Error = LDD_SDHC_ERR_INTERNAL_FAILURE;
} else if (SDHC1_R1_IS_WP_ERASE_SKIP(Response)) {
Error = LDD_SDHC_ERR_WP_ERASE_SKIP;
} else if (SDHC1_R1_MMC_IS_OVERRUN(Response) ||
SDHC1_R1_MMC_IS_UNDERRUN(Response) ||
SDHC1_R1_IS_ERROR(Response) ||
SDHC1_R1_IS_CC_ERROR(Response) ||
SDHC1_R1_IS_CARD_ECC_FAILED(Response)) {
Error = LDD_SDHC_ERR_CARD_FAILURE;
} else if (SDHC1_R1_IS_COM_CRC_ERROR(Response)) {
Error = LDD_SDHC_ERR_COMMAND_CRC;
} else if (SDHC1_R1_IS_CARD_IS_LOCKED(Response)) {
Error = LDD_SDHC_ERR_CARD_IS_LOCKED;
} else if (SDHC1_R1_IS_WP_VIOLATION(Response)) {
Error = LDD_SDHC_ERR_WP_VIOLATION;
} else if (SDHC1_R1_IS_ERASE_PARAM(Response) ||
SDHC1_R1_IS_ADDRESS_MISALIGN(Response)) {
Error = LDD_SDHC_ERR_ADDRESS_MISALIGN;
} else if (SDHC1_R1_IS_BLOCK_LEN_ERROR(Response)) {
Error = LDD_SDHC_ERR_BLOCK_LEN_ERROR;
} else if (SDHC1_R1_IS_ADDRESS_OUT_OF_RANGE(Response)) {
Error = LDD_SDHC_ERR_ADDRESS_OUT_OF_RANGE;
} else {
Error = LDD_SDHC_ERR_OK;
}
}
return Error;
}
/*
** ===================================================================
** Method : SendCardStatusRequest (component SDHC_LDD)
**
** Description :
** Sends a card status request.
** This method is internal. It is used by Processor Expert only.
** ===================================================================
*/
static void SendCardStatusRequest(LDD_SDHC1_TDeviceData *DeviceDataPtr)
{
LDD_SDHC1_TDeviceData *DeviceDataPrv = (LDD_SDHC1_TDeviceData*)DeviceDataPtr;
uint8_t Id = DeviceDataPrv->CardId; /* Card ID storage */
/* Send status request command */
SDHC_PDD_SetCommandArgument(SDHC_BASE_PTR,
SDHC1_CMD_ARG_RCA(DeviceDataPrv->Cards[Id].RCA));
SDHC_PDD_SendCommand(SDHC_BASE_PTR,
SDHC_PDD_CMD13_SEND_STATUS, SDHC_PDD_RESPONSE_LENGTH_48);
}
/*
** ===================================================================
** Method : SDHC1_Interrupt (component SDHC_LDD)
**
** Description :
** The method services the interrupt of the selected peripheral(s)
** and eventually invokes event(s) of the component.
** This method is internal. It is used by Processor Expert only.
** ===================================================================
*/
//PE_ISR(SDHC1_Interrupt)
void SDHC1_Interrupt( void )
{
/* {FreeRTOS RTOS Adapter} ISR parameter is passed through the global variable */
LDD_SDHC1_TDeviceData* DeviceDataPrv = INT_SDHC__BAREBOARD_RTOS_ISRPARAM;
EventHandler(DeviceDataPrv);
}
/*
** ===================================================================
** Method : EventHandler (component SDHC_LDD)
**
** Description :
** Hardware event handler.
** This method is internal. It is used by Processor Expert only.
** ===================================================================
*/
static void EventHandler(LDD_SDHC1_TDeviceData *DeviceDataPtr)
{
LDD_SDHC1_TDeviceData *DeviceDataPrv = (LDD_SDHC1_TDeviceData*)DeviceDataPtr;
uint32_t IntFlags = SDHC_PDD_GetInterruptFlags(SDHC_BASE_PTR); /* Store interrupt flags */
const uint32_t CompletionFlags = SDHC_PDD_COMMAND_COMPLETE_INT |
SDHC_PDD_TRANSFER_COMPLETE_INT | SDHC_PDD_BUFFER_READ_READY_INT |
SDHC_PDD_BUFFER_WRITE_READY_INT;
const uint32_t CommandErrorFlags = SDHC_PDD_COMMAND_TIMEOUT_ERROR_INT | /* Command error interrupt flags mask */
SDHC_PDD_COMMAND_CRC_ERROR_INT | SDHC_PDD_COMMAND_INDEX_ERROR_INT |
//MATTHEW
0;
//SDHC_PDD_AUTO_CMD12_ERROR_INT;
const uint32_t DataErrorFlags = SDHC_PDD_DATA_TIMEOUT_ERROR_INT | /* Data transfer error interrupt flags mask */
SDHC_PDD_DATA_CRC_ERROR_INT | SDHC_PDD_DATA_END_BIT_ERROR_INT |
SDHC_PDD_DMA_ERROR_INT;
const uint32_t ErrorFlags = CommandErrorFlags | DataErrorFlags; /* Error interrupt flags mask */
bool Finished = FALSE; /* Indicates operation end */
uint32_t Buffer[4]; /* Response buffer */
uint32_t *Response = SDHC1_NO_RESPONSE; /* Response buffer pointer */
if (IntFlags & (CompletionFlags | ErrorFlags)) {
if (IntFlags & SDHC_PDD_COMMAND_COMPLETE_INT) {
SDHC_PDD_ClearInterruptFlags(SDHC_BASE_PTR, SDHC_PDD_COMMAND_COMPLETE_INT);
/* Check command completion errors */
if (IntFlags & CommandErrorFlags) {
SDHC_PDD_ClearInterruptFlags(SDHC_BASE_PTR, CommandErrorFlags);
Response = SDHC1_NO_RESPONSE; /* No valid response has been received */
} else {
SDHC_PDD_GetCommandResponse(SDHC_BASE_PTR, Buffer);
Response = Buffer; /* Assign the response pointer */
}
} else {
if (IntFlags & SDHC_PDD_TRANSFER_COMPLETE_INT) {
SDHC_PDD_ClearInterruptFlags(SDHC_BASE_PTR, SDHC_PDD_TRANSFER_COMPLETE_INT | DataErrorFlags);
}
}
switch (DeviceDataPrv->State) {
case LDD_SDHC_RESET:
Finished = TRUE;
break;
case LDD_SDHC_VOLTAGE_VALIDATION:
VoltageValidation(DeviceDataPrv, IntFlags, Response); /* Handle the voltage validation state */
break;
case LDD_SDHC_CARD_REGISTRATION:
CardRegistration(DeviceDataPrv, IntFlags, Response); /* Handle the card registration state */
break;
case LDD_SDHC_CARD_INFO_RETRIEVAL:
CardInfoRetrieval(DeviceDataPrv, IntFlags, Response); /* Handle the card info retrieval state */
break;
case LDD_SDHC_CARD_SELECTION:
Finished = CardSelection(DeviceDataPrv, IntFlags, Response); /* Handle the card selection state */
break;
case LDD_SDHC_TRANSFER:
Finished = Transfer(DeviceDataPrv, IntFlags, Response); /* Handle the transfer state */
break;
case LDD_SDHC_ERASION:
Finished = Erasion(DeviceDataPrv, IntFlags, Response); /* Handle the erasion state */
break;
case LDD_SDHC_DATA_WIDTH_SELECTION:
Finished = DataWidthSelection(DeviceDataPrv, IntFlags, Response); /* Handle the data width selection state */
break;
case LDD_SDHC_BUS_CLOCK_SELECTION:
Finished = BusClockSelection(DeviceDataPrv, IntFlags, Response); /* Handle the bus clock selection state */
break;
case LDD_SDHC_WRITE_PROTECTION_SETUP:
Finished = WriteProtectionSetup(DeviceDataPrv, IntFlags, Response); /* Handle the write protection setup state */
break;
case LDD_SDHC_WRITE_PROTECTION_RETRIEVAL:
Finished = WriteProtectionRetrieval(DeviceDataPrv, IntFlags, Response); /* Handle the write protection retrieval state */
break;
default:
break;
}
}
if (Finished) {
DeviceDataPrv->State = LDD_SDHC_IDLE;
if (DeviceDataPrv->EventMask & LDD_SDHC_ON_FINISHED) {
SDHC1_OnFinished(DeviceDataPrv->UserDataPtr); /* Call the user event */
}
}
}
/*lint -restore +esym(960,10.1) Enable MISRA rule (10.1,12.1) checking. */
/* END SDHC1 */
/*
** ###################################################################
**
** This file was created by Processor Expert 5.3 [05.01]
** for the Freescale Kinetis series of microcontrollers.
**
** ###################################################################
*/