mirror of
https://github.com/hathach/tinyusb.git
synced 2025-01-17 05:32:55 +08:00
updating lib *.c
This commit is contained in:
parent
239864c6cf
commit
8a8537d7e5
@ -190,7 +190,7 @@ void data_out(unsigned char i, SSP_DATA_SETUP_Type *xferConfig) //Data Output Se
|
|||||||
//CS = 0; //Chip Select = Active
|
//CS = 0; //Chip Select = Active
|
||||||
GPIO_ClearValue(3,(1<<12));
|
GPIO_ClearValue(3,(1<<12));
|
||||||
//A0 = 1 = Data
|
//A0 = 1 = Data
|
||||||
GPIO_SetValue(4,(1<<10));
|
//GPIO_SetValue(4,(1<<10));
|
||||||
//delay(1);
|
//delay(1);
|
||||||
|
|
||||||
Tx_Buf[0] = i;
|
Tx_Buf[0] = i;
|
||||||
@ -206,7 +206,7 @@ void comm_out(unsigned char j, SSP_DATA_SETUP_Type *xferConfig) //Command Output
|
|||||||
{
|
{
|
||||||
//unsigned int n;
|
//unsigned int n;
|
||||||
//CS = 0; //Chip Select = Active
|
//CS = 0; //Chip Select = Active
|
||||||
GPIO_ClearValue(3,(1<<12));
|
//GPIO_ClearValue(3,(1<<12));
|
||||||
//A0 = 0;
|
//A0 = 0;
|
||||||
GPIO_ClearValue(4,(1<<10));
|
GPIO_ClearValue(4,(1<<10));
|
||||||
//delay(1);
|
//delay(1);
|
||||||
|
@ -280,6 +280,13 @@ void debug_frmwrk_init_clk(uint32_t Clock_Speed)
|
|||||||
*/
|
*/
|
||||||
scu_pinmux(0xC ,13 , MD_PDN, FUNC2); // PC.13 : UART1_TXD
|
scu_pinmux(0xC ,13 , MD_PDN, FUNC2); // PC.13 : UART1_TXD
|
||||||
scu_pinmux(0xC ,14 , MD_PLN|MD_EZI|MD_ZI, FUNC2); // PC.14 : UART1_RXD
|
scu_pinmux(0xC ,14 , MD_PLN|MD_EZI|MD_ZI, FUNC2); // PC.14 : UART1_RXD
|
||||||
|
#elif (USED_UART_DEBUG_PORT==3)
|
||||||
|
/*
|
||||||
|
* Initialize UART3 pin connect
|
||||||
|
*/
|
||||||
|
scu_pinmux(0x2 ,3 , MD_PUP, FUNC2); // P2.3 : UART3_TXD
|
||||||
|
scu_pinmux(0x2 ,4 , MD_PLN|MD_EZI|MD_ZI, FUNC2); // P2.4 : UART3_RXD
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Initialize UART Configuration parameter structure to default state:
|
/* Initialize UART Configuration parameter structure to default state:
|
||||||
|
@ -107,6 +107,10 @@ void ADC_DeInit(LPC_ADCn_Type *ADCx)
|
|||||||
{
|
{
|
||||||
CHECK_PARAM(PARAM_ADCx(ADCx));
|
CHECK_PARAM(PARAM_ADCx(ADCx));
|
||||||
|
|
||||||
|
if (ADCx->CR & ADC_CR_START_MASK) //need to stop START bits before DeInit
|
||||||
|
ADCx->CR &= ~ADC_CR_START_MASK;
|
||||||
|
// Clear SEL bits
|
||||||
|
ADCx->CR &= ~0xFF;
|
||||||
// Clear PDN bit
|
// Clear PDN bit
|
||||||
ADCx->CR &= ~ADC_CR_PDN;
|
ADCx->CR &= ~ADC_CR_PDN;
|
||||||
// Turn on power and clock
|
// Turn on power and clock
|
||||||
@ -251,6 +255,8 @@ void ADC_ChannelCmd (LPC_ADCn_Type *ADCx, uint8_t Channel, FunctionalState NewSt
|
|||||||
if (NewState == ENABLE) {
|
if (NewState == ENABLE) {
|
||||||
ADCx->CR |= ADC_CR_CH_SEL(Channel);
|
ADCx->CR |= ADC_CR_CH_SEL(Channel);
|
||||||
} else {
|
} else {
|
||||||
|
if (ADCx->CR & ADC_CR_START_MASK) //need to stop START bits before disable channel
|
||||||
|
ADCx->CR &= ~ADC_CR_START_MASK;
|
||||||
ADCx->CR &= ~ADC_CR_CH_SEL(Channel);
|
ADCx->CR &= ~ADC_CR_CH_SEL(Channel);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -203,7 +203,6 @@ uint32_t CGU_Init(void){
|
|||||||
CGU_EnableEntity(CGU_CLKSRC_PLL1, ENABLE);
|
CGU_EnableEntity(CGU_CLKSRC_PLL1, ENABLE);
|
||||||
CGU_EntityConnect(CGU_CLKSRC_PLL1, CGU_BASE_M4);
|
CGU_EntityConnect(CGU_CLKSRC_PLL1, CGU_BASE_M4);
|
||||||
CGU_UpdateClock();
|
CGU_UpdateClock();
|
||||||
SystemCoreClock = 6*12000000;
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -401,7 +400,7 @@ void CGU_UpdateClock(void){
|
|||||||
CGU_ClockSourceFrequency[CGU_CLKSRC_32KHZ_OSC] = 0;
|
CGU_ClockSourceFrequency[CGU_CLKSRC_32KHZ_OSC] = 0;
|
||||||
/*PLL0*/
|
/*PLL0*/
|
||||||
/* PLL1 */
|
/* PLL1 */
|
||||||
if(ISBITCLR(LPC_CGU->PLL1_CTRL,0) /* Enabled */ /* EA ANDLI: Original code tested bit 1 which is BYPASS, not PD */
|
if(ISBITCLR(LPC_CGU->PLL1_CTRL,1) /* Enabled */
|
||||||
&& (LPC_CGU->PLL1_STAT&1)){ /* Locked? */
|
&& (LPC_CGU->PLL1_STAT&1)){ /* Locked? */
|
||||||
ClkSrc = (LPC_CGU->PLL1_CTRL & CGU_CTRL_SRC_MASK)>>24;
|
ClkSrc = (LPC_CGU->PLL1_CTRL & CGU_CTRL_SRC_MASK)>>24;
|
||||||
CGU_ClockSourceFrequency[CGU_CLKSRC_PLL1] = CGU_ClockSourceFrequency[ClkSrc] *
|
CGU_ClockSourceFrequency[CGU_CLKSRC_PLL1] = CGU_ClockSourceFrequency[ClkSrc] *
|
||||||
|
@ -377,7 +377,7 @@ Status I2S_FreqConfig(LPC_I2Sn_Type *I2Sx, uint32_t Freq, uint8_t TRMode) {
|
|||||||
divider = ((uint64_t)(Freq *( bitrate+1) * 2)<<16) / i2sPclk;
|
divider = ((uint64_t)(Freq *( bitrate+1) * 2)<<16) / i2sPclk;
|
||||||
|
|
||||||
/* find N that make x/y <= 1 -> divider <= 2^16 */
|
/* find N that make x/y <= 1 -> divider <= 2^16 */
|
||||||
for(N=64;N>=0;N--){
|
for(N=64;N>0;N--){
|
||||||
if((divider*N) < (1<<16)) break;
|
if((divider*N) < (1<<16)) break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -407,11 +407,11 @@ Status I2S_FreqConfig(LPC_I2Sn_Type *I2Sx, uint32_t Freq, uint8_t TRMode) {
|
|||||||
if(x_divide == 0) x_divide = 1;
|
if(x_divide == 0) x_divide = 1;
|
||||||
if (TRMode == I2S_TX_MODE)// Transmitter
|
if (TRMode == I2S_TX_MODE)// Transmitter
|
||||||
{
|
{
|
||||||
I2Sx->TXBITRATE = N;
|
I2Sx->TXBITRATE = N - 1;
|
||||||
I2Sx->TXRATE = y_divide | (x_divide << 8);
|
I2Sx->TXRATE = y_divide | (x_divide << 8);
|
||||||
} else //Receiver
|
} else //Receiver
|
||||||
{
|
{
|
||||||
I2Sx->RXBITRATE = N;
|
I2Sx->RXBITRATE = N - 1;
|
||||||
I2Sx->RXRATE = y_divide | (x_divide << 8);
|
I2Sx->RXRATE = y_divide | (x_divide << 8);
|
||||||
}
|
}
|
||||||
return SUCCESS;
|
return SUCCESS;
|
||||||
|
@ -109,11 +109,11 @@ void LCD_Init(LPC_LCD_Type *LCDx, LCD_CFG_Type *LCD_ConfigStruct){
|
|||||||
break;
|
break;
|
||||||
case LCD_TFT:
|
case LCD_TFT:
|
||||||
default:
|
default:
|
||||||
regValue |= 1<<26 | (((LCD_ConfigStruct->screen_width-1) & 0x3FF) << 16);
|
regValue |= /* 1<<26 |*/ (((LCD_ConfigStruct->screen_width-1) & 0x3FF) << 16);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* panel clock divisor */
|
/* panel clock divisor */
|
||||||
pcd = 0; // TODO: should be calculated from LCDDCLK
|
pcd = 6; // TODO: should be calculated from LCDDCLK
|
||||||
pcd &= 0x3FF;
|
pcd &= 0x3FF;
|
||||||
regValue |= ((pcd>>5)<<27) | ((pcd)&0x1F);
|
regValue |= ((pcd>>5)<<27) | ((pcd)&0x1F);
|
||||||
|
|
||||||
|
@ -292,6 +292,7 @@ void QEI_SetTimerReload(uint8_t qeiId, QEI_RELOADCFG_Type *QEIReloadStruct)
|
|||||||
#if 1
|
#if 1
|
||||||
// pclk = CGU_GetPCLKFrequency(CGU_PERIPHERAL_M3CORE);
|
// pclk = CGU_GetPCLKFrequency(CGU_PERIPHERAL_M3CORE);
|
||||||
pclk = CGU_GetPCLKFrequency(CGU_PERIPHERAL_M4CORE);
|
pclk = CGU_GetPCLKFrequency(CGU_PERIPHERAL_M4CORE);
|
||||||
|
|
||||||
pclk = (pclk /(1000000/QEIReloadStruct->ReloadValue)) - 1;
|
pclk = (pclk /(1000000/QEIReloadStruct->ReloadValue)) - 1;
|
||||||
|
|
||||||
pQei->LOAD = (uint32_t)pclk;
|
pQei->LOAD = (uint32_t)pclk;
|
||||||
|
@ -209,7 +209,7 @@ void RTC_CntIncrIntConfig (LPC_RTC_Type *RTCx, uint32_t CntIncrIntType, \
|
|||||||
{
|
{
|
||||||
RTCx->CIIR |= tem;
|
RTCx->CIIR |= tem;
|
||||||
}
|
}
|
||||||
//while((RTCx->CIIR & tem)== 0);
|
while((RTCx->CIIR & tem)== 0);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -217,7 +217,7 @@ void RTC_CntIncrIntConfig (LPC_RTC_Type *RTCx, uint32_t CntIncrIntType, \
|
|||||||
{
|
{
|
||||||
RTCx->CIIR &= (~tem) & RTC_CIIR_BITMASK;
|
RTCx->CIIR &= (~tem) & RTC_CIIR_BITMASK;
|
||||||
}
|
}
|
||||||
//while(RTCx->CIIR & tem);
|
while(RTCx->CIIR & tem);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -284,7 +284,7 @@ void RTC_AlarmIntConfig (LPC_RTC_Type *RTCx, uint32_t AlarmTimeType, \
|
|||||||
{
|
{
|
||||||
RTCx->AMR &= (~tem) & RTC_AMR_BITMASK;
|
RTCx->AMR &= (~tem) & RTC_AMR_BITMASK;
|
||||||
}
|
}
|
||||||
//while(RTCx->AMR & tem);
|
while(RTCx->AMR & tem);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -292,7 +292,7 @@ void RTC_AlarmIntConfig (LPC_RTC_Type *RTCx, uint32_t AlarmTimeType, \
|
|||||||
{
|
{
|
||||||
RTCx->AMR |= (tem);
|
RTCx->AMR |= (tem);
|
||||||
}
|
}
|
||||||
//while((RTCx->AMR & tem)== 0);
|
while((RTCx->AMR & tem)== 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -699,7 +699,7 @@ void RTC_CalibConfig(LPC_RTC_Type *RTCx, uint32_t CalibValue, uint8_t CalibDir)
|
|||||||
CHECK_PARAM(PARAM_RTC_CALIB_DIR(CalibDir));
|
CHECK_PARAM(PARAM_RTC_CALIB_DIR(CalibDir));
|
||||||
CHECK_PARAM(CalibValue < RTC_CALIBRATION_MAX);
|
CHECK_PARAM(CalibValue < RTC_CALIBRATION_MAX);
|
||||||
|
|
||||||
RTCx->CALIBRATION = ((CalibValue - 1) & RTC_CALIBRATION_CALVAL_MASK) \
|
RTCx->CALIBRATION = (CalibValue & RTC_CALIBRATION_CALVAL_MASK) \
|
||||||
| ((CalibDir == RTC_CALIB_DIR_BACKWARD) ? RTC_CALIBRATION_LIBDIR : 0);
|
| ((CalibDir == RTC_CALIB_DIR_BACKWARD) ? RTC_CALIBRATION_LIBDIR : 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -39,21 +39,60 @@
|
|||||||
#include "lpc_types.h"
|
#include "lpc_types.h"
|
||||||
#include "lpc43xx_scu.h"
|
#include "lpc43xx_scu.h"
|
||||||
|
|
||||||
|
/* Pin modes
|
||||||
|
* =========
|
||||||
|
* The EPUN and EPD bits in the SFS registers allow the selection of weak on-chip
|
||||||
|
* pull-up or pull-down resistors with a typical value of 50 kOhm for each pin or the
|
||||||
|
* selection of the repeater mode.
|
||||||
|
* The possible on-chip resistor configurations are pull-up enabled, pull-down enabled, or no
|
||||||
|
* pull-up/pull-down. The default value is pull-up enabled.
|
||||||
|
*
|
||||||
|
* The repeater mode enables the pull-up resistor if the pin is at a logic HIGH and enables
|
||||||
|
* the pull-down resistor if the pin is at a logic LOW. This causes the pin to retain its last
|
||||||
|
* known state if it is configured as an input and is not driven externally. Repeater mode may
|
||||||
|
* typically be used to prevent a pin from floating (and potentially using significant power if it
|
||||||
|
* floats to an indeterminate state) if it is temporarily not driven.
|
||||||
|
* Repeater mode is enabled when both pull-up and pull-down are enabled.
|
||||||
|
*
|
||||||
|
* To be able to receive a digital signal, the input buffer must be enabled through bit EZI in
|
||||||
|
* the pin configuration registers. By default, the input buffer is disabled.
|
||||||
|
* For pads that support both a digital and an analog function, the input buffer must be
|
||||||
|
* disabled before enabling the analog function.
|
||||||
|
*
|
||||||
|
* All digital pins support a programmable glitch filter (bit ZIF), which can be switched on or
|
||||||
|
* off. By default, the glitch filter is on. The glitch filter should be disabled for
|
||||||
|
* clocking signals with frequencies higher than 30 MHz.
|
||||||
|
*
|
||||||
|
* Normal-drive and high-speed pins support a programmable slew rate (bit EHS) to select
|
||||||
|
* between lower noise and low speed or higher noise and high speed . The typical
|
||||||
|
* frequencies supported are 50 MHz/80 MHz for normal-drive pins and 75 MHz/180 MHz for
|
||||||
|
* high-speed pins.
|
||||||
|
*/
|
||||||
|
|
||||||
/*********************************************************************//**
|
/*********************************************************************//**
|
||||||
* @brief Configure pin function
|
* @brief Configure pin function
|
||||||
* @param[in] port Port number, should be: 0..15
|
* @param[in] port Port number, should be: 0..15
|
||||||
* @param[in] pin Pin number, should be: 0..31
|
* @param[in] pin Pin number, should be: 0..31
|
||||||
* @param[in] mode Pin mode, should be:
|
* @param[in] mode Pin mode, should be:
|
||||||
* - MD_PUP :Pull-up enabled
|
* - MD_PUP :Pull-up enabled
|
||||||
* - MD_BUK :Plain input
|
* - MD_BUK :Plain input
|
||||||
* - MD_PLN :Repeater mode
|
* - MD_PLN :Repeater mode
|
||||||
* - MD_PDN :Pull-down enabled
|
* - MD_PDN :Pull-down enabled
|
||||||
|
* - MD_EHS :Slew rate
|
||||||
|
* - MD_EZI :Input buffer enable
|
||||||
|
* - MD_ZI :Glitch filter enabled
|
||||||
|
* - MD_EHD0 :High drive 8 mA
|
||||||
|
* - MD_EHD1 :High drive 14 mA
|
||||||
|
* - MD_EHD2 :High drive 20 mA
|
||||||
* @param[in] func Function mode, should be:
|
* @param[in] func Function mode, should be:
|
||||||
* - FUNC0 :Function 0
|
* - FUNC0 :Function 0
|
||||||
* - FUNC1 :Function 1
|
* - FUNC1 :Function 1
|
||||||
* - FUNC2 :Function 2
|
* - FUNC2 :Function 2
|
||||||
* - FUNC3 :Function 3
|
* - FUNC3 :Function 3
|
||||||
|
* - FUNC4 :Function 4
|
||||||
|
* - FUNC5 :Function 5
|
||||||
|
* - FUNC6 :Function 6
|
||||||
|
* - FUNC7 :Function 7
|
||||||
* @return None
|
* @return None
|
||||||
**********************************************************************/
|
**********************************************************************/
|
||||||
void scu_pinmux(uint8_t port, uint8_t pin, uint8_t mode, uint8_t func)
|
void scu_pinmux(uint8_t port, uint8_t pin, uint8_t mode, uint8_t func)
|
||||||
|
401
demos/bsp/lpc43xx/CMSIS_LPC43xx_DriverLib/src/lpc43xx_sdif.c
Normal file
401
demos/bsp/lpc43xx/CMSIS_LPC43xx_DriverLib/src/lpc43xx_sdif.c
Normal file
@ -0,0 +1,401 @@
|
|||||||
|
/**********************************************************************
|
||||||
|
* $Id$ lpc43xx_sdif.c 2012-Aug-15
|
||||||
|
*//**
|
||||||
|
* @file lpc43xx_sdif.c
|
||||||
|
* @brief LPC43xx SD interface driver
|
||||||
|
* @version 1.0
|
||||||
|
* @date 15. Aug. 2012
|
||||||
|
* @author NXP MCU SW Application Team
|
||||||
|
*
|
||||||
|
* Copyright(C) 2011, NXP Semiconductor
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
***********************************************************************
|
||||||
|
* Software that is described herein is for illustrative purposes only
|
||||||
|
* which provides customers with programming information regarding the
|
||||||
|
* products. This software is supplied "AS IS" without any warranties.
|
||||||
|
* NXP Semiconductors assumes no responsibility or liability for the
|
||||||
|
* use of the software, conveys no license or title under any patent,
|
||||||
|
* copyright, or mask work right to the product. NXP Semiconductors
|
||||||
|
* reserves the right to make changes in the software without
|
||||||
|
* notification. NXP Semiconductors also make no representation or
|
||||||
|
* warranty that such application will be suitable for the specified
|
||||||
|
* use without further testing or modification.
|
||||||
|
* Permission to use, copy, modify, and distribute this software and its
|
||||||
|
* documentation is hereby granted, under NXP Semiconductors'
|
||||||
|
* relevant copyright in the software, without fee, provided that it
|
||||||
|
* is used in conjunction with NXP Semiconductors microcontrollers. This
|
||||||
|
* copyright, permission, and disclaimer notice must appear in all copies of
|
||||||
|
* this code.
|
||||||
|
**********************************************************************/
|
||||||
|
|
||||||
|
/* Peripheral group ----------------------------------------------------------- */
|
||||||
|
/** @addtogroup SDIF
|
||||||
|
* @{
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Includes ------------------------------------------------------------------- */
|
||||||
|
#include "LPC43xx.h" /* LPC43xx definitions */
|
||||||
|
#include "system_LPC43xx.h"
|
||||||
|
#include "lpc_sdmmc.h"
|
||||||
|
#include "lpc43xx_sdif.h"
|
||||||
|
#include "lpc43xx_cgu.h"
|
||||||
|
|
||||||
|
/* If this source file built with example, the lpc43xx FW library configuration
|
||||||
|
* file in each example directory ("lpc43xx_libcfg.h") must be included,
|
||||||
|
* otherwise the default FW library configuration file must be included instead
|
||||||
|
*/
|
||||||
|
#ifdef __BUILD_WITH_EXAMPLE__
|
||||||
|
#include "lpc43xx_libcfg.h"
|
||||||
|
#else
|
||||||
|
#include "lpc43xx_libcfg_default.h"
|
||||||
|
#endif /* __BUILD_WITH_EXAMPLE__ */
|
||||||
|
|
||||||
|
#ifdef _SDIF
|
||||||
|
|
||||||
|
/* Local data structure for the SDIF driver */
|
||||||
|
struct _sdif_device {
|
||||||
|
MCI_IRQ_CB_FUNC_T irq_cb;
|
||||||
|
LPC_SDMMC_DMA_Type mci_dma_dd[1 + (0x10000 / MCI_DMADES1_MAXTR)];
|
||||||
|
uint32_t sdio_clk_rate;
|
||||||
|
uint32_t sdif_slot_clk_rate;
|
||||||
|
int32_t clock_enabled;
|
||||||
|
};
|
||||||
|
static struct _sdif_device sdif_dev;
|
||||||
|
|
||||||
|
/*********************************************************************//**
|
||||||
|
* @brief Enables the SDIO controller clock
|
||||||
|
* @param[in] None
|
||||||
|
* @return None
|
||||||
|
**********************************************************************/
|
||||||
|
static void sdif_enable_clock(void)
|
||||||
|
{
|
||||||
|
if (!sdif_dev.clock_enabled)
|
||||||
|
{
|
||||||
|
/* Enable SD MMC clock */
|
||||||
|
CGU_ConfigPWR(CGU_PERIPHERAL_SDIO, ENABLE);
|
||||||
|
sdif_dev.clock_enabled = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*********************************************************************//**
|
||||||
|
* @brief Disables the SDIO controller clock
|
||||||
|
* @param[in] None
|
||||||
|
* @return None
|
||||||
|
**********************************************************************/
|
||||||
|
static void sdif_disable_clock(void)
|
||||||
|
{
|
||||||
|
if (!sdif_dev.clock_enabled)
|
||||||
|
{
|
||||||
|
/* Disable SD MMC clock */
|
||||||
|
CGU_ConfigPWR(CGU_PERIPHERAL_SDIO, (FunctionalState)FALSE);
|
||||||
|
sdif_dev.clock_enabled = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Public Functions ----------------------------------------------------------- */
|
||||||
|
/** @defgroup SDIF_Public_Functions
|
||||||
|
* @ingroup SDIF
|
||||||
|
* @{
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*********************************************************************//**
|
||||||
|
* @brief Setup DMA descriptors
|
||||||
|
* @param[in] addr Address of buffer (source or destination)
|
||||||
|
* @param[in] size size of buffer in bytes (64K max)
|
||||||
|
* @return None
|
||||||
|
**********************************************************************/
|
||||||
|
void sdif_dma_setup(uint32_t addr, uint32_t size)
|
||||||
|
{
|
||||||
|
int i = 0;
|
||||||
|
uint32_t ctrl, maxs;
|
||||||
|
|
||||||
|
/* Reset DMA */
|
||||||
|
LPC_SDMMC->CTRL |= MCI_CTRL_DMA_RESET | MCI_CTRL_FIFO_RESET;
|
||||||
|
while (LPC_SDMMC->CTRL & MCI_CTRL_DMA_RESET);
|
||||||
|
|
||||||
|
/* Build a descriptor list using the chained DMA method */
|
||||||
|
while (size > 0)
|
||||||
|
{
|
||||||
|
/* Limit size of the transfer to maximum buffer size */
|
||||||
|
maxs = size;
|
||||||
|
if (maxs > MCI_DMADES1_MAXTR)
|
||||||
|
maxs = MCI_DMADES1_MAXTR;
|
||||||
|
size -= maxs;
|
||||||
|
|
||||||
|
/* Set buffer size */
|
||||||
|
sdif_dev.mci_dma_dd[i].des1 = MCI_DMADES1_BS1(maxs);
|
||||||
|
|
||||||
|
/* Setup buffer address (chained) */
|
||||||
|
sdif_dev.mci_dma_dd[i].des2 = addr + (i * MCI_DMADES1_MAXTR);
|
||||||
|
|
||||||
|
/* Setup basic control */
|
||||||
|
ctrl = MCI_DMADES0_OWN | MCI_DMADES0_CH;
|
||||||
|
if (i == 0)
|
||||||
|
ctrl |= MCI_DMADES0_FS; /* First DMA buffer */
|
||||||
|
|
||||||
|
/* No more data? Then this is the last descriptor */
|
||||||
|
if (!size)
|
||||||
|
ctrl |= MCI_DMADES0_LD;
|
||||||
|
else
|
||||||
|
ctrl |= MCI_DMADES0_DIC;
|
||||||
|
|
||||||
|
/* Another descriptor is needed */
|
||||||
|
sdif_dev.mci_dma_dd[i].des3 = (uint32_t) &sdif_dev.mci_dma_dd[i + 1];
|
||||||
|
sdif_dev.mci_dma_dd[i].des0 = ctrl;
|
||||||
|
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Set DMA derscriptor base address */
|
||||||
|
LPC_SDMMC->DBADDR = (uint32_t) &sdif_dev.mci_dma_dd[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
/*********************************************************************//**
|
||||||
|
* @brief Function to send command to Card interface unit (CIU)
|
||||||
|
* @param[in] cmd Command with all flags set
|
||||||
|
* @param[in] arg Argument for the command
|
||||||
|
* @return TRUE on times-out, otherwise FALSE
|
||||||
|
**********************************************************************/
|
||||||
|
int32_t sdif_send_cmd(uint32_t cmd, uint32_t arg)
|
||||||
|
{
|
||||||
|
volatile int32_t tmo = 50;
|
||||||
|
volatile int delay;
|
||||||
|
|
||||||
|
/* set command arg reg*/
|
||||||
|
LPC_SDMMC->CMDARG = arg;
|
||||||
|
LPC_SDMMC->CMD = MCI_CMD_START | cmd;
|
||||||
|
|
||||||
|
/* poll untill command is accepted by the CIU */
|
||||||
|
while (--tmo && (LPC_SDMMC->CMD & MCI_CMD_START))
|
||||||
|
{
|
||||||
|
if (tmo & 1)
|
||||||
|
delay = 50;
|
||||||
|
else
|
||||||
|
delay = 18000;
|
||||||
|
|
||||||
|
while (--delay > 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
return (tmo < 1) ? 1 : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*********************************************************************//**
|
||||||
|
* @brief Function to retrieve command response
|
||||||
|
* @param[in] pdev Pointer to card info structure
|
||||||
|
* @return None
|
||||||
|
**********************************************************************/
|
||||||
|
void sdif_get_response(uint32_t *resp)
|
||||||
|
{
|
||||||
|
/* on this chip response is not a fifo so read all 4 regs */
|
||||||
|
resp[0] = LPC_SDMMC->RESP0;
|
||||||
|
resp[1] = LPC_SDMMC->RESP1;
|
||||||
|
resp[2] = LPC_SDMMC->RESP2;
|
||||||
|
resp[3] = LPC_SDMMC->RESP3;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*********************************************************************//**
|
||||||
|
* @brief Function to set speed of the clock going to card
|
||||||
|
* @param[in] speed Desired clock speed to the card
|
||||||
|
* @return None
|
||||||
|
**********************************************************************/
|
||||||
|
void sdif_set_clock(uint32_t speed)
|
||||||
|
{
|
||||||
|
/* compute SD/MMC clock dividers */
|
||||||
|
uint32_t div;
|
||||||
|
|
||||||
|
/* Exit if the clock is already set at the passed speed */
|
||||||
|
if (sdif_dev.sdif_slot_clk_rate == speed)
|
||||||
|
return;
|
||||||
|
|
||||||
|
div = ((sdif_dev.sdio_clk_rate / speed) + 2) >> 1;
|
||||||
|
sdif_dev.sdif_slot_clk_rate = speed;
|
||||||
|
|
||||||
|
if ((div == LPC_SDMMC->CLKDIV) && LPC_SDMMC->CLKENA)
|
||||||
|
return; /* Closest speed is already set */
|
||||||
|
|
||||||
|
/* disable clock */
|
||||||
|
LPC_SDMMC->CLKENA = 0;
|
||||||
|
|
||||||
|
/* User divider 0 */
|
||||||
|
LPC_SDMMC->CLKSRC = MCI_CLKSRC_CLKDIV0;
|
||||||
|
|
||||||
|
/* inform CIU */
|
||||||
|
sdif_send_cmd(MCI_CMD_UPD_CLK | MCI_CMD_PRV_DAT_WAIT, 0);
|
||||||
|
|
||||||
|
/* set divider 0 to desired value */
|
||||||
|
LPC_SDMMC->CLKDIV = MCI_CLOCK_DIVIDER(0, div);
|
||||||
|
|
||||||
|
/* inform CIU */
|
||||||
|
sdif_send_cmd(MCI_CMD_UPD_CLK | MCI_CMD_PRV_DAT_WAIT, 0);
|
||||||
|
|
||||||
|
/* enable clock */
|
||||||
|
LPC_SDMMC->CLKENA = MCI_CLKEN_ENABLE;
|
||||||
|
|
||||||
|
/* inform CIU */
|
||||||
|
sdif_send_cmd(MCI_CMD_UPD_CLK | MCI_CMD_PRV_DAT_WAIT, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*********************************************************************//**
|
||||||
|
* @brief Detect if an SD card is inserted
|
||||||
|
* @param[in] None
|
||||||
|
* @return Returns 0 if a card is detected, otherwise 1
|
||||||
|
**********************************************************************/
|
||||||
|
int32_t sdif_card_ndetect(void)
|
||||||
|
{
|
||||||
|
/* No card = high state in regsiter */
|
||||||
|
if (LPC_SDMMC->CDETECT & 1)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*********************************************************************//**
|
||||||
|
* @brief Detect if write protect is enabled
|
||||||
|
* @param[in] None
|
||||||
|
* @return Returns 1 if card is write protected, otherwise 0
|
||||||
|
**********************************************************************/
|
||||||
|
int32_t sdif_card_wp_on(void)
|
||||||
|
{
|
||||||
|
if (LPC_SDMMC->WRTPRT & 1)
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*********************************************************************//**
|
||||||
|
* @brief Enable or disable slot power
|
||||||
|
* @param[in] enable !0 to enable, or 0 to disable
|
||||||
|
* @return None
|
||||||
|
**********************************************************************/
|
||||||
|
void sdif_power_onoff(int32_t enable)
|
||||||
|
{
|
||||||
|
if (enable)
|
||||||
|
LPC_SDMMC->PWREN = 1;
|
||||||
|
else
|
||||||
|
LPC_SDMMC->PWREN = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*********************************************************************//**
|
||||||
|
* @brief Reset card in slot
|
||||||
|
* @param[in] reset Sets SD_RST to passed state
|
||||||
|
* @return None
|
||||||
|
**********************************************************************/
|
||||||
|
void sdif_reset(int32_t reset)
|
||||||
|
{
|
||||||
|
if (reset)
|
||||||
|
LPC_SDMMC->RST_N = 1;
|
||||||
|
else
|
||||||
|
LPC_SDMMC->RST_N = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*********************************************************************//**
|
||||||
|
* @brief Set block size for transfer
|
||||||
|
* @param[in] bytes Lock size in bytes
|
||||||
|
* @return None
|
||||||
|
**********************************************************************/
|
||||||
|
void sdif_set_blksize(uint32_t bytes)
|
||||||
|
{
|
||||||
|
LPC_SDMMC->BLKSIZ = bytes;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*********************************************************************//**
|
||||||
|
* @brief Enter or exit low power mode (disables clocking)
|
||||||
|
* @param[in] lpmode !0 to enable low power mode, 0 = exit
|
||||||
|
* @return None
|
||||||
|
**********************************************************************/
|
||||||
|
void sdif_set_lowpower_mode(int32_t lpmode)
|
||||||
|
{
|
||||||
|
/* Once in low power mode, no SDIF functions should ever be
|
||||||
|
called, as it can hang the chip. Always exit low power mode
|
||||||
|
prior to resuming SDIF functions */
|
||||||
|
if (lpmode)
|
||||||
|
sdif_disable_clock();
|
||||||
|
else
|
||||||
|
sdif_enable_clock();
|
||||||
|
}
|
||||||
|
|
||||||
|
/*********************************************************************//**
|
||||||
|
* @brief Initializes the MCI card controller
|
||||||
|
* @param[in] waitfunc Pointer to wait function to be used during for poll command status
|
||||||
|
* @param[in] irq_callback Pointer to IRQ callback function
|
||||||
|
* @return None
|
||||||
|
**********************************************************************/
|
||||||
|
void sdif_init(uint32_t sdio_clock, MCI_IRQ_CB_FUNC_T irq_callback)
|
||||||
|
{
|
||||||
|
volatile uint32_t i;
|
||||||
|
|
||||||
|
sdif_dev.sdio_clk_rate = sdio_clock;
|
||||||
|
sdif_dev.irq_cb = irq_callback;
|
||||||
|
|
||||||
|
/* enable SD/MMC clock */
|
||||||
|
sdif_enable_clock();
|
||||||
|
|
||||||
|
/* Software reset */
|
||||||
|
LPC_SDMMC->BMOD = MCI_BMOD_SWR;
|
||||||
|
|
||||||
|
/* reset all blocks */
|
||||||
|
LPC_SDMMC->CTRL = MCI_CTRL_RESET | MCI_CTRL_FIFO_RESET |
|
||||||
|
MCI_CTRL_DMA_RESET;
|
||||||
|
while (LPC_SDMMC->CTRL &
|
||||||
|
(MCI_CTRL_RESET | MCI_CTRL_FIFO_RESET | MCI_CTRL_DMA_RESET));
|
||||||
|
|
||||||
|
/* Internal DMA setup for control register */
|
||||||
|
LPC_SDMMC->CTRL = MCI_CTRL_USE_INT_DMAC | MCI_CTRL_INT_ENABLE;
|
||||||
|
LPC_SDMMC->INTMASK = 0;
|
||||||
|
|
||||||
|
/* Clear the interrupts for the host controller */
|
||||||
|
LPC_SDMMC->RINTSTS = 0xFFFFFFFF;
|
||||||
|
|
||||||
|
/* Put in max timeout */
|
||||||
|
LPC_SDMMC->TMOUT = 0xFFFFFFFF;
|
||||||
|
|
||||||
|
/* FIFO threshold settings for DMA, DMA burst of 4,
|
||||||
|
FIFO watermark at 16 */
|
||||||
|
LPC_SDMMC->FIFOTH = MCI_FIFOTH_DMA_MTS_4 |
|
||||||
|
MCI_FIFOTH_RX_WM((SD_FIFO_SZ / 2) - 1) |
|
||||||
|
MCI_FIFOTH_TX_WM(SD_FIFO_SZ / 2);
|
||||||
|
|
||||||
|
/* Enable internal DMA, burst size of 4, fixed burst */
|
||||||
|
LPC_SDMMC->BMOD = MCI_BMOD_DE | MCI_BMOD_PBL4 | MCI_BMOD_DSL(4);
|
||||||
|
|
||||||
|
/* disable clock to CIU (needs latch) */
|
||||||
|
LPC_SDMMC->CLKENA = 0;
|
||||||
|
LPC_SDMMC->CLKSRC = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*********************************************************************//**
|
||||||
|
* @brief Close the MCI
|
||||||
|
* @param[in] None
|
||||||
|
* @return None
|
||||||
|
**********************************************************************/
|
||||||
|
void sdif_deinit(void)
|
||||||
|
{
|
||||||
|
/* clear mmc structure*/
|
||||||
|
sdif_disable_clock();
|
||||||
|
}
|
||||||
|
|
||||||
|
/*********************************************************************//**
|
||||||
|
* @brief SDIO controller interrupt handler
|
||||||
|
* @param[in] None
|
||||||
|
* @return None
|
||||||
|
**********************************************************************/
|
||||||
|
void SDIO_IRQHandler(void)
|
||||||
|
{
|
||||||
|
/* All SD based register handling is done in the callback
|
||||||
|
function. The SDIO interrupt is not enabled as part of this
|
||||||
|
driver and needs to be enabled/disabled in the callbacks or
|
||||||
|
application as needed. This is to allow flexibility with IRQ
|
||||||
|
handling for applicaitons and RTOSes. */
|
||||||
|
sdif_dev.irq_cb(LPC_SDMMC->RINTSTS);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @}
|
||||||
|
*/
|
||||||
|
|
||||||
|
#endif /* _SDIF */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @}
|
||||||
|
*/
|
694
demos/bsp/lpc43xx/CMSIS_LPC43xx_DriverLib/src/lpc43xx_sdmmc.c
Normal file
694
demos/bsp/lpc43xx/CMSIS_LPC43xx_DriverLib/src/lpc43xx_sdmmc.c
Normal file
@ -0,0 +1,694 @@
|
|||||||
|
/**********************************************************************
|
||||||
|
* $Id$ lpc43xx_sdmmc.c 2012-Aug-15
|
||||||
|
*//**
|
||||||
|
* @file lpc43xx_sdmmc.c
|
||||||
|
* @brief SD/MMC card access and data driver
|
||||||
|
* @version 1.0
|
||||||
|
* @date 15. Aug. 2012
|
||||||
|
* @author NXP MCU SW Application Team
|
||||||
|
*
|
||||||
|
* Copyright(C) 2011, NXP Semiconductor
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
***********************************************************************
|
||||||
|
* Software that is described herein is for illustrative purposes only
|
||||||
|
* which provides customers with programming information regarding the
|
||||||
|
* products. This software is supplied "AS IS" without any warranties.
|
||||||
|
* NXP Semiconductors assumes no responsibility or liability for the
|
||||||
|
* use of the software, conveys no license or title under any patent,
|
||||||
|
* copyright, or mask work right to the product. NXP Semiconductors
|
||||||
|
* reserves the right to make changes in the software without
|
||||||
|
* notification. NXP Semiconductors also make no representation or
|
||||||
|
* warranty that such application will be suitable for the specified
|
||||||
|
* use without further testing or modification.
|
||||||
|
* Permission to use, copy, modify, and distribute this software and its
|
||||||
|
* documentation is hereby granted, under NXP Semiconductors'
|
||||||
|
* relevant copyright in the software, without fee, provided that it
|
||||||
|
* is used in conjunction with NXP Semiconductors microcontrollers. This
|
||||||
|
* copyright, permission, and disclaimer notice must appear in all copies of
|
||||||
|
* this code.
|
||||||
|
**********************************************************************/
|
||||||
|
|
||||||
|
/* Example group ----------------------------------------------------------- */
|
||||||
|
/** @addtogroup SDMMC
|
||||||
|
* @{
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Includes ------------------------------------------------------------------- */
|
||||||
|
#include "string.h"
|
||||||
|
#include "lpc_sdmmc.h"
|
||||||
|
#include "lpc43xx_sdif.h"
|
||||||
|
#include "lpc43xx_sdmmc.h"
|
||||||
|
|
||||||
|
/* If this source file built with example, the lpc43xx FW library configuration
|
||||||
|
* file in each example directory ("lpc43xx_libcfg.h") must be included,
|
||||||
|
* otherwise the default FW library configuration file must be included instead
|
||||||
|
*/
|
||||||
|
#ifdef __BUILD_WITH_EXAMPLE__
|
||||||
|
#include "lpc43xx_libcfg.h"
|
||||||
|
#else
|
||||||
|
#include "lpc43xx_libcfg_default.h"
|
||||||
|
#endif /* __BUILD_WITH_EXAMPLE__ */
|
||||||
|
|
||||||
|
#ifdef _SDMMC
|
||||||
|
|
||||||
|
/* Global instance of the current card */
|
||||||
|
static struct _mci_card_struct *g_card_info;
|
||||||
|
|
||||||
|
/* Pointer to event setup functions */
|
||||||
|
static MCI_EVSETUP_FUNC_T sdmmc_evsetup_cb;
|
||||||
|
|
||||||
|
/* Pointer to wait functions */
|
||||||
|
static MCI_WAIT_CB_FUNC_T sdmmc_wait_cb;
|
||||||
|
|
||||||
|
/* Pointer to mS delay functin */
|
||||||
|
static MCI_MSDELAY_FUNC_T sdmmc_msdelay_cb;
|
||||||
|
|
||||||
|
/* Helper definition: all SD error conditions in the status word */
|
||||||
|
#define SD_INT_ERROR (MCI_INT_RESP_ERR | MCI_INT_RCRC | MCI_INT_DCRC | \
|
||||||
|
MCI_INT_RTO | MCI_INT_DTO | MCI_INT_HTO | MCI_INT_FRUN | MCI_INT_HLE | \
|
||||||
|
MCI_INT_SBE | MCI_INT_EBE)
|
||||||
|
|
||||||
|
/*********************************************************************//**
|
||||||
|
* @brief Helper function to get a bit field withing multi-word
|
||||||
|
* buffer. Used to get fields with-in CSD & EXT-CSD
|
||||||
|
* structures.
|
||||||
|
* @param[in] start Starting bit
|
||||||
|
* @param[in] end Ending bit
|
||||||
|
* @param[in] data Pointer to data patternf or bit extraction
|
||||||
|
* @return None
|
||||||
|
**********************************************************************/
|
||||||
|
static uint32_t prv_get_bits(int32_t start, int32_t end, uint32_t* data)
|
||||||
|
{
|
||||||
|
uint32_t v;
|
||||||
|
uint32_t i = end >> 5;
|
||||||
|
uint32_t j = start & 0x1f;
|
||||||
|
|
||||||
|
if (i == (start >> 5))
|
||||||
|
v = (data[i] >> j);
|
||||||
|
else
|
||||||
|
v = ((data[i] << (32 - j)) | (data[start >> 5] >> j));
|
||||||
|
|
||||||
|
return (v & ((1 << (end - start + 1)) - 1));
|
||||||
|
}
|
||||||
|
|
||||||
|
/*********************************************************************//**
|
||||||
|
* @brief Function to execute a command
|
||||||
|
* @param[in] cmd Command with all flags set
|
||||||
|
* @param[in] arg Argument for the command
|
||||||
|
* @param[in] wait_status Status bits to poll for command completion
|
||||||
|
* @return 0 on success, or error code (-1)
|
||||||
|
**********************************************************************/
|
||||||
|
static int32_t sdmmc_execute_command(uint32_t cmd, uint32_t arg,
|
||||||
|
uint32_t wait_status)
|
||||||
|
{
|
||||||
|
int32_t step = (cmd & CMD_BIT_APP) ? 2 : 1;
|
||||||
|
int32_t status = 0;
|
||||||
|
uint32_t cmd_reg = 0;
|
||||||
|
|
||||||
|
if (!wait_status)
|
||||||
|
wait_status = (cmd & CMD_MASK_RESP) ? MCI_INT_CMD_DONE : MCI_INT_DATA_OVER;
|
||||||
|
|
||||||
|
/* Clear the interrupts & FIFOs*/
|
||||||
|
if (cmd & CMD_BIT_DATA)
|
||||||
|
{
|
||||||
|
/* reset all blocks */
|
||||||
|
LPC_SDMMC->CTRL |= MCI_CTRL_FIFO_RESET;
|
||||||
|
|
||||||
|
/* wait till resets clear */
|
||||||
|
while (LPC_SDMMC->CTRL & MCI_CTRL_FIFO_RESET);
|
||||||
|
|
||||||
|
/* Clear interrupt status */
|
||||||
|
LPC_SDMMC->RINTSTS = 0xFFFFFFFF;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* also check error conditions */
|
||||||
|
wait_status |= MCI_INT_EBE | MCI_INT_SBE | MCI_INT_HLE |
|
||||||
|
MCI_INT_RTO | MCI_INT_RCRC | MCI_INT_RESP_ERR;
|
||||||
|
if (wait_status & MCI_INT_DATA_OVER)
|
||||||
|
wait_status |= MCI_INT_FRUN | MCI_INT_HTO | MCI_INT_DTO | MCI_INT_DCRC;
|
||||||
|
|
||||||
|
while (step)
|
||||||
|
{
|
||||||
|
sdif_set_clock((cmd & CMD_BIT_LS) ? SD_MMC_ENUM_CLOCK : g_card_info->speed);
|
||||||
|
|
||||||
|
/* Clear the interrupts */
|
||||||
|
LPC_SDMMC->RINTSTS = 0xFFFFFFFF;
|
||||||
|
sdmmc_evsetup_cb(wait_status);
|
||||||
|
|
||||||
|
switch (step)
|
||||||
|
{
|
||||||
|
case 1: /* Execute command */
|
||||||
|
cmd_reg = ((cmd & CMD_MASK_CMD) >> CMD_SHIFT_CMD) |
|
||||||
|
((cmd & CMD_BIT_INIT) ? MCI_CMD_INIT : 0) |
|
||||||
|
((cmd & CMD_BIT_DATA) ? (MCI_CMD_DAT_EXP | MCI_CMD_PRV_DAT_WAIT) : 0) |
|
||||||
|
(((cmd & CMD_MASK_RESP) == CMD_RESP_R2) ? MCI_CMD_RESP_LONG : 0) |
|
||||||
|
((cmd & CMD_MASK_RESP) ? MCI_CMD_RESP_EXP : 0) |
|
||||||
|
((cmd & CMD_BIT_WRITE) ? MCI_CMD_DAT_WR : 0) |
|
||||||
|
((cmd & CMD_BIT_STREAM) ? MCI_CMD_STRM_MODE : 0) |
|
||||||
|
((cmd & CMD_BIT_BUSY) ? MCI_CMD_STOP : 0) |
|
||||||
|
((cmd & CMD_BIT_AUTO_STOP) ? MCI_CMD_SEND_STOP : 0) |
|
||||||
|
MCI_CMD_START;
|
||||||
|
|
||||||
|
/* wait for previos data finsh for select/deselect commands */
|
||||||
|
if (((cmd & CMD_MASK_CMD) >> CMD_SHIFT_CMD) == MMC_SELECT_CARD)
|
||||||
|
{
|
||||||
|
cmd_reg |= MCI_CMD_PRV_DAT_WAIT;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* wait for command to be accepted by CIU */
|
||||||
|
if (sdif_send_cmd(cmd_reg, arg) == 0)
|
||||||
|
--step;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 0:
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
case 2: /* APP prefix */
|
||||||
|
cmd_reg = MMC_APP_CMD | MCI_CMD_RESP_EXP |
|
||||||
|
((cmd & CMD_BIT_INIT) ? MCI_CMD_INIT : 0) |
|
||||||
|
MCI_CMD_START;
|
||||||
|
|
||||||
|
if (sdif_send_cmd(cmd_reg, g_card_info->rca << 16) == 0)
|
||||||
|
--step;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* wait for command response */
|
||||||
|
status = sdmmc_wait_cb(wait_status);
|
||||||
|
|
||||||
|
/* We return an error if there is a timeout, even if we've fetched
|
||||||
|
a response */
|
||||||
|
if (status & SD_INT_ERROR)
|
||||||
|
return status;
|
||||||
|
|
||||||
|
if (status & MCI_INT_CMD_DONE)
|
||||||
|
{
|
||||||
|
switch (cmd & CMD_MASK_RESP)
|
||||||
|
{
|
||||||
|
case 0:
|
||||||
|
break;
|
||||||
|
|
||||||
|
case CMD_RESP_R1:
|
||||||
|
case CMD_RESP_R3:
|
||||||
|
sdif_get_response(&g_card_info->response[0]);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case CMD_RESP_R2:
|
||||||
|
sdif_get_response(&g_card_info->response[0]);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*********************************************************************//**
|
||||||
|
* @brief Checks whether card is acquired properly or not
|
||||||
|
* @return !0 if card has been acquired, otherwise 0
|
||||||
|
**********************************************************************/
|
||||||
|
static int32_t prv_card_acquired(void)
|
||||||
|
{
|
||||||
|
return (g_card_info->cid[0] != 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*********************************************************************//**
|
||||||
|
* @brief Function to process the CSD & EXT-CSD of the card
|
||||||
|
* @param[in] None
|
||||||
|
* @return None
|
||||||
|
**********************************************************************/
|
||||||
|
static void prv_process_csd(void)
|
||||||
|
{
|
||||||
|
int32_t status = 0;
|
||||||
|
int32_t c_size = 0;
|
||||||
|
int32_t c_size_mult = 0;
|
||||||
|
int32_t mult = 0;
|
||||||
|
|
||||||
|
/* compute block length based on CSD response */
|
||||||
|
g_card_info->block_len = 1 << prv_get_bits(80, 83, g_card_info->csd);
|
||||||
|
|
||||||
|
if ((g_card_info->card_type & CARD_TYPE_HC) &&
|
||||||
|
(g_card_info->card_type & CARD_TYPE_SD))
|
||||||
|
{
|
||||||
|
/* See section 5.3.3 CSD Register (CSD Version 2.0) of SD2.0 spec
|
||||||
|
an explanation for the calculation of these values */
|
||||||
|
c_size = prv_get_bits(48, 63, (uint32_t*)g_card_info->csd) + 1;
|
||||||
|
g_card_info->blocknr = c_size << 10; /* 512 byte blocks */
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* See section 5.3 of the 4.1 revision of the MMC specs for
|
||||||
|
an explanation for the calculation of these values */
|
||||||
|
c_size = prv_get_bits(62, 73, (uint32_t*)g_card_info->csd);
|
||||||
|
c_size_mult = prv_get_bits(47, 49, (uint32_t*)g_card_info->csd);
|
||||||
|
mult = 1 << (c_size_mult + 2);
|
||||||
|
g_card_info->blocknr = (c_size + 1) * mult;
|
||||||
|
|
||||||
|
/* adjust blocknr to 512/block */
|
||||||
|
if (g_card_info->block_len > MMC_SECTOR_SIZE)
|
||||||
|
g_card_info->blocknr = g_card_info->blocknr *
|
||||||
|
(g_card_info->block_len >> 9);
|
||||||
|
|
||||||
|
/* get extended CSD for newer MMC cards CSD spec >= 4.0*/
|
||||||
|
if (((g_card_info->card_type & CARD_TYPE_SD) == 0) &&
|
||||||
|
(prv_get_bits(122, 125, (uint32_t*)g_card_info->csd) >= 4))
|
||||||
|
{
|
||||||
|
/* put card in trans state */
|
||||||
|
status = sdmmc_execute_command(CMD_SELECT_CARD,
|
||||||
|
g_card_info->rca << 16, 0);
|
||||||
|
|
||||||
|
/* set block size and byte count */
|
||||||
|
LPC_SDMMC->BLKSIZ = MMC_SECTOR_SIZE;
|
||||||
|
LPC_SDMMC->BYTCNT = MMC_SECTOR_SIZE;
|
||||||
|
|
||||||
|
/* send EXT_CSD command */
|
||||||
|
sdif_dma_setup((uint32_t) g_card_info->ext_csd, MMC_SECTOR_SIZE);
|
||||||
|
status = sdmmc_execute_command(CMD_SEND_EXT_CSD, 0, 0 |
|
||||||
|
MCI_INT_DATA_OVER);
|
||||||
|
if ((status & SD_INT_ERROR) == 0)
|
||||||
|
{
|
||||||
|
/* check EXT_CSD_VER is greater than 1.1 */
|
||||||
|
if ((g_card_info->ext_csd[48] & 0xFF) > 1)
|
||||||
|
g_card_info->blocknr = g_card_info->ext_csd[53]; /* bytes 212:215 represent sec count */
|
||||||
|
|
||||||
|
/* switch to 52MHz clock if card type is set to 1 or else set to 26MHz */
|
||||||
|
if ((g_card_info->ext_csd[49] & 0xFF) == 1)
|
||||||
|
{
|
||||||
|
/* for type 1 MMC cards high speed is 52MHz */
|
||||||
|
g_card_info->speed = MMC_HIGH_BUS_MAX_CLOCK;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* for type 0 MMC cards high speed is 26MHz */
|
||||||
|
g_card_info->speed = MMC_LOW_BUS_MAX_CLOCK;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
g_card_info->device_size = g_card_info->blocknr << 9; /* blocknr * 512 */
|
||||||
|
}
|
||||||
|
|
||||||
|
/*********************************************************************//**
|
||||||
|
* @brief Puts current selected card in trans state
|
||||||
|
* @param[in] None
|
||||||
|
* @return 0 on success, or error code (-1)
|
||||||
|
**********************************************************************/
|
||||||
|
static int32_t prv_set_trans_state(void)
|
||||||
|
{
|
||||||
|
uint32_t status;
|
||||||
|
|
||||||
|
/* get current state of the card */
|
||||||
|
status = sdmmc_execute_command(CMD_SEND_STATUS, g_card_info->rca << 16, 0);
|
||||||
|
if (status & MCI_INT_RTO)
|
||||||
|
{
|
||||||
|
/* unable to get the card state. So return immediatly. */
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* check card state in response */
|
||||||
|
status = R1_CURRENT_STATE(g_card_info->response[0]);
|
||||||
|
switch (status)
|
||||||
|
{
|
||||||
|
case SDMMC_STBY_ST:
|
||||||
|
/* put card in 'Trans' state */
|
||||||
|
status = sdmmc_execute_command(CMD_SELECT_CARD, g_card_info->rca << 16, 0);
|
||||||
|
if (status != 0)
|
||||||
|
{
|
||||||
|
/* unable to put the card in Trans state. So return immediatly. */
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case SDMMC_TRAN_ST:
|
||||||
|
/*do nothing */
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
/* card shouldn't be in other states so return */
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*********************************************************************//**
|
||||||
|
* @brief Sets card data width and block size
|
||||||
|
* @param[in] None
|
||||||
|
* @return 0 on success, or error code (-1)
|
||||||
|
**********************************************************************/
|
||||||
|
static int32_t prv_set_card_params(void)
|
||||||
|
{
|
||||||
|
uint32_t status;
|
||||||
|
|
||||||
|
#if SDIO_BUS_WIDTH > 1
|
||||||
|
if (g_card_info->card_type & CARD_TYPE_SD)
|
||||||
|
{
|
||||||
|
status = sdmmc_execute_command(CMD_SD_SET_WIDTH, 2, 0);
|
||||||
|
if (status != 0)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
/* if positive response */
|
||||||
|
LPC_SDMMC->CTYPE = MCI_CTYPE_4BIT;
|
||||||
|
}
|
||||||
|
#elif SDIO_BUS_WIDTH > 4
|
||||||
|
#error 8-bit mode not supported yet!
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* set block length */
|
||||||
|
LPC_SDMMC->BLKSIZ = MMC_SECTOR_SIZE;
|
||||||
|
status = sdmmc_execute_command(CMD_SET_BLOCKLEN, MMC_SECTOR_SIZE, 0);
|
||||||
|
if (status != 0)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Public Functions ----------------------------------------------------------- */
|
||||||
|
/** @defgroup SDMMC_Public_Functions
|
||||||
|
* @ingroup SDMMC
|
||||||
|
* @{
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*********************************************************************//**
|
||||||
|
* @brief Function to enumerate the SD/MMC/SDHC/MMC+ cards
|
||||||
|
* @param[in] evsetup_cb Pointer to event setup function callback
|
||||||
|
* @param[in] waitfunc_cb Pointer to wait function callback
|
||||||
|
* @param[in] msdelay_func Pointer to function that delays
|
||||||
|
* @param[in] pcardinfo Pointer to pre-allocated card info structure
|
||||||
|
* @return 1 if a card is acquired, otherwise 0
|
||||||
|
**********************************************************************/
|
||||||
|
int32_t sdmmc_acquire(MCI_EVSETUP_FUNC_T evsetup_cb,
|
||||||
|
MCI_WAIT_CB_FUNC_T waitfunc_cb, MCI_MSDELAY_FUNC_T msdelay_func,
|
||||||
|
struct _mci_card_struct *pcardinfo)
|
||||||
|
{
|
||||||
|
int32_t status;
|
||||||
|
int32_t tries = 0;
|
||||||
|
uint32_t ocr = OCR_VOLTAGE_RANGE_MSK;
|
||||||
|
uint32_t r;
|
||||||
|
int32_t state = 0;
|
||||||
|
uint32_t command = 0;
|
||||||
|
|
||||||
|
g_card_info = pcardinfo;
|
||||||
|
|
||||||
|
/* Make sure callbacks are valid */
|
||||||
|
if ((waitfunc_cb == NULL) || (msdelay_func == NULL) ||
|
||||||
|
(evsetup_cb == NULL))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
sdmmc_evsetup_cb = evsetup_cb;
|
||||||
|
sdmmc_wait_cb = waitfunc_cb;
|
||||||
|
sdmmc_msdelay_cb = msdelay_func;
|
||||||
|
|
||||||
|
/* clear card struct */
|
||||||
|
memset(g_card_info, 0, sizeof(*g_card_info));
|
||||||
|
|
||||||
|
/* clear card type */
|
||||||
|
LPC_SDMMC->CTYPE = 0;
|
||||||
|
|
||||||
|
/* set high speed for the card as 20MHz */
|
||||||
|
g_card_info->speed = MMC_MAX_CLOCK;
|
||||||
|
|
||||||
|
status = sdmmc_execute_command(CMD_IDLE, 0, MCI_INT_CMD_DONE);
|
||||||
|
|
||||||
|
while (state < 100)
|
||||||
|
{
|
||||||
|
switch (state)
|
||||||
|
{
|
||||||
|
case 0: /* Setup for SD */
|
||||||
|
/* check if it is SDHC card */
|
||||||
|
status = sdmmc_execute_command( CMD_SD_SEND_IF_COND, SD_SEND_IF_ARG, 0);
|
||||||
|
if (!(status & MCI_INT_RTO))
|
||||||
|
{
|
||||||
|
/* check response has same echo pattern */
|
||||||
|
if ((g_card_info->response[0] & SD_SEND_IF_ECHO_MSK) == SD_SEND_IF_RESP)
|
||||||
|
ocr |= OCR_HC_CCS;
|
||||||
|
}
|
||||||
|
|
||||||
|
++state;
|
||||||
|
command = CMD_SD_OP_COND;
|
||||||
|
tries = INIT_OP_RETRIES;
|
||||||
|
|
||||||
|
/* assume SD card */
|
||||||
|
g_card_info->card_type |= CARD_TYPE_SD;
|
||||||
|
g_card_info->speed = SD_MAX_CLOCK;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 10: /* Setup for MMC */
|
||||||
|
/* start fresh for MMC crds */
|
||||||
|
g_card_info->card_type &= ~CARD_TYPE_SD;
|
||||||
|
status = sdmmc_execute_command(CMD_IDLE, 0, MCI_INT_CMD_DONE);
|
||||||
|
command = CMD_MMC_OP_COND;
|
||||||
|
tries = INIT_OP_RETRIES;
|
||||||
|
ocr |= OCR_HC_CCS;
|
||||||
|
++state;
|
||||||
|
|
||||||
|
/* for MMC cards high speed is 20MHz */
|
||||||
|
g_card_info->speed = MMC_MAX_CLOCK;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 1:
|
||||||
|
case 11:
|
||||||
|
status = sdmmc_execute_command(command, 0, 0);
|
||||||
|
if (status & MCI_INT_RTO)
|
||||||
|
state += 9; /* Mode unavailable */
|
||||||
|
else
|
||||||
|
++state;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 2: /* Initial OCR check */
|
||||||
|
case 12:
|
||||||
|
ocr = g_card_info->response[0] | (ocr & OCR_HC_CCS);
|
||||||
|
if (ocr & OCR_ALL_READY)
|
||||||
|
++state;
|
||||||
|
else
|
||||||
|
state += 2;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 3: /* Initial wait for OCR clear */
|
||||||
|
case 13:
|
||||||
|
while ((ocr & OCR_ALL_READY) && --tries > 0)
|
||||||
|
{
|
||||||
|
sdmmc_msdelay_cb(MS_ACQUIRE_DELAY);
|
||||||
|
status = sdmmc_execute_command(command, 0, 0);
|
||||||
|
ocr = g_card_info->response[0] | (ocr & OCR_HC_CCS);
|
||||||
|
}
|
||||||
|
if (ocr & OCR_ALL_READY)
|
||||||
|
state += 7;
|
||||||
|
else
|
||||||
|
++state;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 14:
|
||||||
|
/* for MMC cards set high capacity bit */
|
||||||
|
ocr |= OCR_HC_CCS;
|
||||||
|
case 4: /* Assign OCR */
|
||||||
|
tries = SET_OP_RETRIES;
|
||||||
|
ocr &= OCR_VOLTAGE_RANGE_MSK | OCR_HC_CCS; /* Mask for the bits we care about */
|
||||||
|
do
|
||||||
|
{
|
||||||
|
sdmmc_msdelay_cb(MS_ACQUIRE_DELAY);
|
||||||
|
status = sdmmc_execute_command(command, ocr, 0);
|
||||||
|
r = g_card_info->response[0];
|
||||||
|
} while (!(r & OCR_ALL_READY) && --tries > 0);
|
||||||
|
|
||||||
|
if (r & OCR_ALL_READY)
|
||||||
|
{
|
||||||
|
/* is it high capacity card */
|
||||||
|
g_card_info->card_type |= (r & OCR_HC_CCS);
|
||||||
|
++state;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
state += 6;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 5: /* CID polling */
|
||||||
|
case 15:
|
||||||
|
status = sdmmc_execute_command(CMD_ALL_SEND_CID, 0, 0);
|
||||||
|
memcpy(&g_card_info->cid, &g_card_info->response[0], 16);
|
||||||
|
++state;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 6: /* RCA send, for SD get RCA */
|
||||||
|
status = sdmmc_execute_command(CMD_SD_SEND_RCA, 0, 0);
|
||||||
|
g_card_info->rca = (g_card_info->response[0]) >> 16;
|
||||||
|
++state;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 16: /* RCA assignment for MMC set to 1 */
|
||||||
|
g_card_info->rca = 1;
|
||||||
|
status = sdmmc_execute_command(CMD_MMC_SET_RCA, g_card_info->rca << 16, 0);
|
||||||
|
++state;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 7:
|
||||||
|
case 17:
|
||||||
|
status = sdmmc_execute_command(CMD_SEND_CSD, g_card_info->rca << 16, 0);
|
||||||
|
memcpy(&g_card_info->csd, &g_card_info->response[0], 16);
|
||||||
|
state = 100;
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
state += 100; /* break from while loop */
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Compute card size, block size and no. of blocks
|
||||||
|
based on CSD response recived. */
|
||||||
|
if (prv_card_acquired()) {
|
||||||
|
prv_process_csd();
|
||||||
|
|
||||||
|
/* Setup card data width and block size (once) */
|
||||||
|
if (prv_set_trans_state() != 0)
|
||||||
|
return 0;
|
||||||
|
if (prv_set_card_params() != 0)
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return prv_card_acquired();
|
||||||
|
}
|
||||||
|
|
||||||
|
/*********************************************************************//**
|
||||||
|
* @brief Get card's current state (idle, transfer, program, etc.)
|
||||||
|
* @param[in] None
|
||||||
|
* @return Current transfer state (0 -
|
||||||
|
**********************************************************************/
|
||||||
|
int32_t sdmmc_get_state(void)
|
||||||
|
{
|
||||||
|
uint32_t status;
|
||||||
|
|
||||||
|
/* get current state of the card */
|
||||||
|
status = sdmmc_execute_command(CMD_SEND_STATUS, g_card_info->rca << 16, 0);
|
||||||
|
if (status & MCI_INT_RTO)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
/* check card state in response */
|
||||||
|
return (int32_t) R1_CURRENT_STATE(g_card_info->response[0]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*********************************************************************//**
|
||||||
|
* @brief Get the device size of SD/MMC card
|
||||||
|
* @param[in] None
|
||||||
|
* @return Device size
|
||||||
|
**********************************************************************/
|
||||||
|
int32_t sdmmc_get_device_size(void)
|
||||||
|
{
|
||||||
|
return g_card_info->device_size;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*********************************************************************//**
|
||||||
|
* @brief Performs the read of data from the SD/MMC card
|
||||||
|
* @param[in] buffer Pointer to data buffer to copy to
|
||||||
|
* @param[in] start_block Start block number
|
||||||
|
* @param[in] end_block End block number
|
||||||
|
* @return Bytes read, or 0 on error
|
||||||
|
**********************************************************************/
|
||||||
|
int32_t sdmmc_read_blocks(void* buffer, int32_t start_block,
|
||||||
|
int32_t end_block)
|
||||||
|
{
|
||||||
|
int32_t cbRead = (end_block - start_block + 1) * MMC_SECTOR_SIZE;
|
||||||
|
int32_t status = 0;
|
||||||
|
int32_t index;
|
||||||
|
|
||||||
|
/* if card is not acquired return immediately */
|
||||||
|
if ((end_block < start_block) || (start_block < 0) ||
|
||||||
|
(end_block > g_card_info->blocknr))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
/* put card in trans state */
|
||||||
|
if (prv_set_trans_state() != 0)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
/* set number of bytes to read */
|
||||||
|
LPC_SDMMC->BYTCNT = cbRead;
|
||||||
|
|
||||||
|
/* if high capacity card use block indexing */
|
||||||
|
if (g_card_info->card_type & CARD_TYPE_HC)
|
||||||
|
index = start_block;
|
||||||
|
else/*fix at 512 bytes*/
|
||||||
|
index = start_block << 9;//\* g_card_info->block_len;
|
||||||
|
|
||||||
|
sdif_dma_setup((uint32_t) buffer, cbRead);
|
||||||
|
|
||||||
|
/* Select single or multiple read based on number of blocks */
|
||||||
|
if (end_block == start_block)
|
||||||
|
status = sdmmc_execute_command(CMD_READ_SINGLE,
|
||||||
|
index, 0 | MCI_INT_DATA_OVER);
|
||||||
|
else
|
||||||
|
status = sdmmc_execute_command(CMD_READ_MULTIPLE,
|
||||||
|
index, 0 | MCI_INT_DATA_OVER);
|
||||||
|
|
||||||
|
if (status != 0)
|
||||||
|
cbRead = 0;
|
||||||
|
/*Wait for card program to finish*/
|
||||||
|
while (sdmmc_get_state() != SDMMC_TRAN_ST);
|
||||||
|
|
||||||
|
return cbRead;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*********************************************************************//**
|
||||||
|
* @brief Performs write of data to the SD/MMC card
|
||||||
|
* @param[in] buffer Pointer to data buffer to copy to
|
||||||
|
* @param[in] start_block Start block number
|
||||||
|
* @param[in] end_block End block number
|
||||||
|
* @return Number of bytes actually written, or 0 on error
|
||||||
|
**********************************************************************/
|
||||||
|
int32_t sdmmc_write_blocks(void* buffer,
|
||||||
|
int32_t start_block,
|
||||||
|
int32_t end_block)
|
||||||
|
{
|
||||||
|
int32_t cbWrote = (end_block - start_block + 1) * MMC_SECTOR_SIZE;
|
||||||
|
int32_t status;
|
||||||
|
int32_t index;
|
||||||
|
|
||||||
|
/* if card is not acquired return immediately */
|
||||||
|
if ((end_block < start_block) || (start_block < 0) ||
|
||||||
|
(end_block > g_card_info->blocknr))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
/*Wait for card program to finish*/
|
||||||
|
while (sdmmc_get_state() != SDMMC_TRAN_ST);
|
||||||
|
|
||||||
|
/* put card in trans state */
|
||||||
|
if (prv_set_trans_state() != 0)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
/* set number of bytes to write */
|
||||||
|
LPC_SDMMC->BYTCNT = cbWrote;
|
||||||
|
|
||||||
|
/* if high capacity card use block indexing */
|
||||||
|
if (g_card_info->card_type & CARD_TYPE_HC)
|
||||||
|
index = start_block;
|
||||||
|
else/*fix at 512 bytes*/
|
||||||
|
index = start_block << 9;//* g_card_info->block_len;
|
||||||
|
|
||||||
|
sdif_dma_setup((uint32_t) buffer, cbWrote);
|
||||||
|
|
||||||
|
/*Wait for card program to finish*/
|
||||||
|
while (sdmmc_get_state() != SDMMC_TRAN_ST);
|
||||||
|
|
||||||
|
/* Select single or multiple write based on number of blocks */
|
||||||
|
if (end_block == start_block)
|
||||||
|
status = sdmmc_execute_command(CMD_WRITE_SINGLE,
|
||||||
|
index, 0 | MCI_INT_DATA_OVER);
|
||||||
|
else
|
||||||
|
status = sdmmc_execute_command(CMD_WRITE_MULTIPLE, index,
|
||||||
|
0 | MCI_INT_DATA_OVER);
|
||||||
|
|
||||||
|
if (status != 0)
|
||||||
|
cbWrote = 0;
|
||||||
|
|
||||||
|
return cbWrote;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @}
|
||||||
|
*/
|
||||||
|
|
||||||
|
#endif /* _SDMMC */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @}
|
||||||
|
*/
|
@ -341,7 +341,7 @@ int32_t SSP_ReadWrite (LPC_SSPn_Type *SSPx, SSP_DATA_SETUP_Type *dataCfg, \
|
|||||||
|
|
||||||
// Clear status
|
// Clear status
|
||||||
SSPx->ICR = SSP_ICR_BITMASK;
|
SSPx->ICR = SSP_ICR_BITMASK;
|
||||||
if(SSP_GetDataSize(SSPx)>8)
|
if(SSP_GetDataSize(SSPx) > SSP_DATABIT_8)
|
||||||
dataword = 1;
|
dataword = 1;
|
||||||
else dataword = 0;
|
else dataword = 0;
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user