2881 lines
136 KiB
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.
|
|
**
|
|
** ###################################################################
|
|
*/
|