📄 mmc_drv.c
字号:
//! @file mmc_drv.c,v
//!
//! Copyright (c) 2004 Atmel.
//!
//! Please read file license.txt for copyright notice.
//!
//! @brief This file contains the MMC driver routines
//!
//! @version 1.16 snd3-refd1-1_9_5 $Id: mmc_drv.c,v 1.16 2007/07/24 09:48:30 sguyon Exp $
//!
//! @todo
//! @bug
//#define MMC_USE_INTERRUPT
//_____ I N C L U D E S ___________________________________________________
#include "config.h"
#include "mmc_drv.h"
#include "lib_mcu\int\int_drv.h"
#include "lib_mcu\power\power_drv.h" // Power management definition
#include "lib_mcu\clock\clock_drv.h"
// Include the timer macros
#include "lib_mcu\timer\timer_drv.h"
#include "conf\conf_access.h"
#if( MEM_MMC != DISABLED )
//_____ M A C R O S ________________________________________________________
//_____ D E F I N I T I O N ________________________________________________
#define CRC7_MSK 0x01
//_____ D E C L A R A T I O N ______________________________________________
_MEM_TYPE_MEDSLOW_ U8 cmdcon;
//_____ F U N C T I O N S __________________________________________________
//! Enable MMC driver
//!
void mmc_drv_on( void )
{
// for SD_Host initial, 100KHz~400KHz
// Either VBUS in or not
if( gfSysUSBMP3Mode )
{
// in USB mode
SDH_CLOCK = 0x4C;
}
else
{
// in MP3 mode
SDH_CLOCK = 0x1F; // CLK down to 380(375)KHz for MMC card,
} // but In USB V_Bus mode will be 375*2.5=937KHz
// select SD DMA Buffer
//SDH_DMA_CS = 0x00; // select buffer 0 at 0x9000
SDH_DMA_CS = 0x01; // select buffer 0 at 0x9000
//varAl.USB_DMA_CS = 0;
BLKCNT11_08 = 0;
BLKCNT07_00 = 0;
BLKLEN11_08 = 0x02;
BLKLEN07_00 = 0x00;
DATACON = 0x00;
// pls note that new FPGA has added one byte timer count
DTIMER15_08 = 0xFF;
DTIMER07_00 = 0xFF;
SDIFCON0 = CLK_EN; //clock enable
}
//! Disable MMC driver
//!
void mmc_drv_off( void )
{
// for SD_Host initial, 100KHz~400KHz
// Either VBUS in or not
if( gfSysUSBMP3Mode )
{
// in USB mode
SDH_CLOCK = 0x4C;
}
else
{
// in MP3 mode
SDH_CLOCK = 0x1F; // CLK down to 380(375)KHz for MMC card,
} // but In USB V_Bus mode will be 375*2.5=937KHz
// select SD DMA Buffer
//SDH_DMA_CS = 0x00; // select buffer 0 at 0x9000
SDH_DMA_CS = 0x01; // select buffer 0 at 0x9000
//varAl.USB_DMA_CS = 0;
BLKCNT11_08 = 0;
BLKCNT07_00 = 0;
BLKLEN11_08 = 0x02;
BLKLEN07_00 = 0x00;
DATACON = 0x00;
// pls note that new FPGA has added one byte timer count
DTIMER15_08 = 0xFF;
DTIMER07_00 = 0xFF;
SDIFCON0 &= ~CLK_EN;
}
//! Send a command on the bus
//!
//! The fifo lock flag is not tested it is under firmware responsability to
//! take care of inter-command delays
//!
//! @param
//! index: command index
//! argument: argument (32 bits) of the command to send
//! response: expected response to the command to send
//!
Bool mmc_drv_send_cmd( Byte index, Uint32 argument, Byte response )
{
ARG31_24 = MSB0( argument );
ARG23_16 = MSB1( argument );
ARG15_08 = MSB2( argument );
ARG07_00 = MSB3( argument );
switch (response)
{
case MMC_RESP_R1:
case MMC_RESP_R4:
case MMC_RESP_R5:
case SD_RESP_R6:
case SD_RESP_R7:
CMDCON = WAITRSP; // set 48 bits response
cmdcon |= CRC7_MSK; // set response with CRC7
// send command with response
break;
case MMC_RESP_R2:
CMDCON = LONGRSP | WAITRSP; // set 136 bits response
cmdcon &= ~CRC7_MSK; // without CRC7 because other internal CRC7 management
// send command with response
break;
case MMC_RESP_R3:
CMDCON = WAITRSP; // set 48 bits response without CRC7
cmdcon &= ~CRC7_MSK; // send command with response
break;
case MMC_NO_RESP:
default:
CMDCON = 0; // send command without response
CMDINDEX = index;
mmc_drv_wait_cmd_trans();
STATUS07_00 = 0xFF;
return TRUE;
}
CMDINDEX = index;
// Execpt MMC_NO_RESP, you shall wait response
mmc_drv_wait_cmd_resp();
return mmc_drv_check_response();
}
//! Send a short command on the bus
//!
//! The fifo lock flag is not tested it is under firmware responsability to
//! take care of inter-command delays
//!
//! @param
//! index: command index
//! response: expected response to the command to send
#if ( 0 )
void mmc_drv_send_scmd (Byte index, Byte response)
{
MMCMD = index;
MMCMD = (Byte)MMC_NO_ARG;
MMCMD = (Byte)MMC_NO_ARG;
MMCMD = (Byte)MMC_NO_ARG;
MMCMD = (Byte)MMC_NO_ARG;
switch (response)
{
case MMC_RESP_R1:
case MMC_RESP_R4:
case MMC_RESP_R5:
case SD_RESP_R6:
case SD_RESP_R7:
{
MMCON0 |= MSK_RFMT; // set 48 bits response
MMCON0 &= ~MSK_CRCDIS; // set response with CRC7
MMCON1 |= (MSK_TXCEN|MSK_RXCEN); // send command with response
break;
}
case MMC_RESP_R2:
{
MMCON0 &= ~(MSK_RFMT | MSK_CRCDIS); // set 136 bits response with CRC7
MMCON1 |= (MSK_TXCEN|MSK_RXCEN); // send command with response
break;
}
case MMC_RESP_R3:
{
MMCON0 |= (MSK_RFMT | MSK_CRCDIS); // set 48 bits response without CRC7
MMCON1 |= (MSK_TXCEN|MSK_RXCEN); // send command with response
break;
}
case MMC_NO_RESP:
default:
{
MMCON1 |= MSK_TXCEN; // send command without response
break;
}
}
}
#endif
//! This fonction waits the end of command and eventualy response reception
//!
//! the time out must wait 48 bits are transmited or received
//! with frequency of 400KHz to 25MHz
//! time out length depends on mmc frequency 120us at 400KHz
//! 2,4us at 20MHz
//!
//! @return OK, or KO for timeout
//!
static Bool mmc_drv_wait( Bool rep_check )
{
_MEM_TYPE_SLOW_ U32 u32_timeout;
u32_timeout = Timer_set_timer( TIMER_MS( 10 ));
while( 1 )
{
if( !Mmc_cmd_in_progress())
{
if( !rep_check )
break;
if( Mmc_resp_received() )
break;
}
if( Timer_is_timeout( u32_timeout ))
return KO; // No reponse
}
return OK;
}
//! This fonction waits the end of command response reception
//!
//! @return OK, or KO for timeout
//!
Bool mmc_drv_wait_cmd_resp( void )
{
return mmc_drv_wait( TRUE );
}
//! This fonction waits the end of command transmission
//!
//! @return OK, or KO for timeout
//!
Bool mmc_drv_wait_cmd_trans( void )
{
return mmc_drv_wait( FALSE );
}
//! Check command response
//!
//! @return
//! MMC_ERR_RESP : no response or bad format received
//! MMC_RESP_OK : response received
//!
Bool mmc_drv_check_response( void )
{
if( !Mmc_resp_received())
{
STATUS07_00 = 0xFF;
return FALSE; // no response received
}
// here, response received
if(( cmdcon & CRC7_MSK ) == 0 )
{
STATUS07_00 = 0xFF;
return TRUE; // CRC7 not computed
}
if(( STATUS07_00 & CRC7ERROR ) != 0 )
{
STATUS07_00 = 0xFF;
return FALSE; // format or CRC7 error
}
STATUS07_00 = 0xFF;
return TRUE; // CRC7 computed and OK
}
//! Read command argument response
//!
//! @return
//! 4-byte argument of the response
//!
Uint32 mmc_drv_read_response (void)
{
U32 argument;
((Byte*)&argument)[0] = RESP119_112;
((Byte*)&argument)[1] = RREP111_104;
((Byte*)&argument)[2] = RREP103_096;
((Byte*)&argument)[3] = RREP095_088;
return argument;
}
//! Waits the end of busy signal on DAT0
//! There is no time out cause the signal goes high when the card is removed
//!
void mmc_wait_busy_signal ( void )
{
Mmc_force_clk();
while(Mmc_read_busy_signal() == 0);
Mmc_unforce_clk();
}
#ifdef MMC_USE_INTERRUPT
//! MMC interrupt service routine
//!
//! Signals some events to the system
//! power mode entry is disabled to avoid delay in event treatment
//!
Interrupt(mmc_drv_int(void), IRQ_MMC)
{
Mcu_set_sfr_page_power();
Pow_power_mode_disable(); // disable power mode entry
Mcu_set_sfr_page_default();
g_u8_int |= MMINT;
if( Mmc_int_isack_block_sent() )
{
g_u16_blockctn++;
}
}
//! Check and clear MMC interrupt flag
//!
Bool mmc_drv_check_clear_int( U8 flag )
{
if( (g_u8_int & flag) != flag )
return FALSE; // no interrupt
Mcu_set_sfr_page_int();
Int_mmc_disable();
g_u8_int &= ~flag;
Int_mmc_enable();
Mcu_set_sfr_page_mmc();
return TRUE;
}
//! Reset counter block
//!
void mmc_blockctn_reset( void )
{
Mcu_set_sfr_page_int();
Int_mmc_disable();
g_u16_blockctn = 0;
Int_mmc_enable();
Mcu_set_sfr_page_mmc();
}
//! Get counter block
//!
U16 mmc_blockctn_get( void )
{
U16 tmp;
Mcu_set_sfr_page_int();
Int_mmc_disable();
tmp = g_u16_blockctn;
Int_mmc_enable();
Mcu_set_sfr_page_mmc();
return tmp;
}
#endif // MMC_USE_INTERRUPT
#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -