⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 mmc_drv.c

📁 mp3播放器
💻 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 + -