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

📄 mmc_sd.c

📁 mp3播放器
💻 C
📖 第 1 页 / 共 2 页
字号:


//! Return information about a plug IN/OUT on MMC/SD socket
//!
Bool mmc_state_change( void )
{
   if( b_flag_change_detected || mmc_state_change_check() )
   {
      b_flag_change_detected = FALSE;
      return TRUE;
   }
   return FALSE;
}


#if 0
//! Check a plug IN/OUT on MMC/SD socket
//!
#define MMC_DEBOUNCE_TIME     TIMER_MS( 150 )
Bool mmc_state_change_check( void )
{
   if( Mmc_drv_card_change())
   {
      // rebounce control
      _MEM_TYPE_SLOW_ U32 timer = Timer_set_timer( MMC_DEBOUNCE_TIME );
      while (!Timer_is_timeout(timer));
      // card has been removed or inserted, then uninstall previous card
      b_card_ready = CARD_UNINSTALLED;
      mmc_drv_off();
      b_flag_change_detected = TRUE;
      return TRUE;
   }
   return FALSE;
}
#endif

//! This function returns the capacity of the memory
//!
//! @return *u16_nb_sector LBA of last sector (sector = 512B)
//! @return                          Ctrl_status
//!   It is ready                ->    CTRL_GOOD
//!   Memory unplug              ->    CTRL_NO_PRESENT
//!   Not initialized or changed ->    CTRL_BUSY
//!   An error occur             ->    CTRL_FAIL
//!
Ctrl_status mmc_read_capacity( U32 _MEM_TYPE_SLOW_ *u32_nb_sector )
{
   Ctrl_status status;
   status = mmc_test_unit_ready();
   if( CTRL_GOOD == status )
   {
      // A card is present and install
      *u32_nb_sector = g_u32_card_size - 1; // send the last LBA
   }
   else
   {
      *u32_nb_sector = 0;
   }
   return status;
}


//! This function returns the write protected mode
//!
//! Only used by memory removal with a HARDWARE SPECIFIC write protected detection
//! !!! The customer must be unplug the card for change this write protected mode.
//!
//! @return TRUE  -> the memory is protected
//!         FALSE -> the memory is protected
//!         FALSE -> the memory is not present
//!
Bool mmc_wr_protect( void )
{
   if( CTRL_GOOD !=  mmc_test_unit_ready())
      return FALSE; // Card not present or not install

   // Card present and install, then read the lock switch
   return Mmc_card_wp();
}


//! This function inform about the memory type
//!
//! @return TRUE  -> The memory is removal
//!
#if 0
Bool  mmc_removal(void)
{
   return TRUE;
}
#endif


//------------ STANDARD FUNCTION for open in read/write mode the device ---------------

//! This function initialise the memory for a read/write operation
//!
//! (sector = 512B)
//! @param addr         Sector address to start read/write
//! @param nb_sector    Number of sectors to transfer
//! @param sense        MMC_READ for a read, MMC_WRITE for a write
//!
//! @return                          Ctrl_status
//!   Memory unplug                 ->   CTRL_NO_PRESENT
//!   A error occur                 ->   CTRL_FAIL
//!   card not in transfer mode     ->   CTRL_FAIL
//!   memory size default           ->   CTRL_FAIL
//!   command not send              ->   CTRL_FAIL
//!   response not received         ->   CTRL_FAIL
//!   bad response received         ->   CTRL_FAIL
//!   transfer ready                ->   CTRL_GOOD
//!
Ctrl_status mmc_10( U32 addr, U16 nb_sector, Mmc_sense sense )
{
   // Check card state
   if( CTRL_GOOD != mmc_test_unit_ready())
   {
      return CTRL_NO_PRESENT;
   }
   // Here the card is present and install

   // check if card is ready
   mmc_wait_busy_signal();

   // check memory size
   if( g_u32_card_size < addr + nb_sector )
   {
      b_card_ready = CARD_UNINSTALLED;
      return CTRL_FAIL;
   }

   //** (CMD13)
   // Necessary to clear flag error "ADDRESS_OUT_OF_RANGE" (ID LABO = MMC15)
   if( !mmc_drv_send_cmd( MMC_SEND_STATUS, g_u32_card_rca, MMC_RESP_R1 ))
   {
      b_card_ready = CARD_UNINSTALLED;
      return CTRL_FAIL;
   }
   mmc_drv_read_response();

   // save address and nb of sector in case of transfer abort
   g_u32_addr      = addr;
   g_u16_nb_sector = nb_sector;

   // initialise mmc for multiple block reception
   /*if ( MMC_READ==sense ) { Mmc_set_read(); }
   else                   { Mmc_set_write();}
   Mmc_set_multi_block();                    // enable multiple block data format
   Mmc_enable_data();                        // enable data reception after response has been received
*/
   // send command
   if( !( CARD_SD_HC & g_u8_card_type ))
   {
      addr <<= 9; // For NO SD HC tha address must be translate in byte address
   }
   if( MMC_READ == sense )
   {
      //** (CMD18)
      if( !mmc_drv_send_cmd( MMC_READ_MULTIPLE_BLOCK, addr, MMC_RESP_R1 ))
      {
         b_card_ready = CARD_UNINSTALLED;
         return CTRL_FAIL;
      }
   }
   else
   {
      //** (CMD25)
      if( !mmc_drv_send_cmd( MMC_WRITE_MULTIPLE_BLOCK, addr, MMC_RESP_R1 ))
      {
         b_card_ready = CARD_UNINSTALLED;
         return CTRL_FAIL;
      }
   }

   // check response
   if(( mmc_drv_read_response() & CS_FLAGERROR_RD_WR ) != 0)
   {
      b_card_ready = CARD_UNINSTALLED;
      return CTRL_FAIL;
   }
   b_card_access_run = TRUE;
   return CTRL_GOOD;
}


//------------ SPECIFIC FUNCTION FOR DFC TRANSFER -----------------------------------------

// For a several memory mem_dfc_ read and write functions are the same.

//! This function resume the dfc interface of the memory initialized by scsi_read_10
//!
//! @return p_n_sector     number of sector transfered (only for information, it may be alway 0)
//! @return                                Ctrl_status
//!   It is running                    ->    CTRL_BUSY
//!   It is fininsh                    ->    CTRL_GOOD
//!   A error occur, transfer stopped  ->    CTRL_FAIL
//!
Ctrl_status mmc_dfc_read_resume(void)
{
   return mmc_dfc_state();
}


//! This function resume the dfc interface of the memory initialized by scsi_write_10
//!
//! @return p_n_sector     number of sector transfered (only for information, it may be alway 0)
//! @return                                Ctrl_status
//!   It is running                    ->    CTRL_BUSY
//!   It is fininsh                    ->    CTRL_GOOD
//!   A error occur, transfer stopped  ->    CTRL_FAIL
//!
Ctrl_status mmc_dfc_write_resume(void)
{
   return mmc_dfc_state();
}


//! This function stop the dfc interface of the memory
//!
Ctrl_status  mmc_dfc_read_stop(void)
{
   Ctrl_status status;

   if( !b_card_access_run )
      return CTRL_FAIL;
   b_card_access_run = FALSE;

   status = mmc_dfc_stop();
   Mmc_reset_data_fifos();                      // remove spurious data received
   return status;
}


//! This function stop the dfc interface of the memory
//!
Ctrl_status  mmc_dfc_write_stop(void)
{
   if( !b_card_access_run )
      return CTRL_FAIL;
   b_card_access_run = FALSE;

   return mmc_dfc_stop();
}


//! This function interrupts the current transfer and save the value necessary for restart the transfer
//!
//! @param  u16_nb_sector_remaining     number of sector remaining after the stop
//!
void  mmc_dfc_read_standby(U16 u16_nb_sector_remaining)
{
   g_u32_save_addr = g_u32_addr + (g_u16_nb_sector-u16_nb_sector_remaining);
   g_u16_save_nb_sector = u16_nb_sector_remaining;
   mmc_dfc_read_stop();
}


//! This function interrupts the current transfer and save the value necessary for restart the transfer
//!
//! @param  u16_nb_sector_remaining     number of sector remaining after the stop
//!
void  mmc_dfc_write_standby(U16 u16_nb_sector_remaining)
{
   g_u32_save_addr = g_u32_addr + (g_u16_nb_sector-u16_nb_sector_remaining);
   g_u16_save_nb_sector = u16_nb_sector_remaining;
   mmc_dfc_write_stop();
}


//! This function restarts the interrupted transfer
//!
void  mmc_dfc_read_restart(void)
{
   mmc_10( g_u32_save_addr, g_u16_save_nb_sector, MMC_READ );
}


//! This function restarts the interrupted transfer
//!
void  mmc_dfc_write_restart(void)
{
   mmc_10( g_u32_save_addr , g_u16_save_nb_sector, MMC_WRITE );
}


//! This function gives the state of the card during a transfer
//!
//! @return                                Ctrl_status
//!
//!      card not present           ->    CTRL_FAIL
//!      card not initialized       ->    CTRL_FAIL
//!      card still present         ->    CTRL_GOOD
//!
Ctrl_status mmc_dfc_state(void)
{
   // Check card state
   if (CTRL_GOOD != mmc_test_unit_ready())
      return CTRL_FAIL;
   // Here the card is present and install
   return CTRL_GOOD;
}

//! This function stops transfer from or to the card
//!
//!
Ctrl_status mmc_dfc_stop(void)
{
   // stop transmission
   Mmc_force_clk();
   if( !mmc_drv_send_cmd( MMC_STOP_TRANSMISSION, 0xFFFFFFFF, MMC_RESP_R1 ) )
   {  // if command is not interpreted, it is tryed again
      mmc_drv_send_cmd( MMC_STOP_TRANSMISSION, 0xFFFFFFFF, MMC_RESP_R1 );
   }
   mmc_drv_read_response();
   Mmc_unforce_clk();
   if( Mmc_crc16s_ko() )
   {
trace("Error CRC16\n");
      Mmc_reset_data_error();
      return CTRL_FAIL;  // An CRC error has been seen
   }
   return CTRL_GOOD;
}


//! This function sets the card data block length in bytes
//!
//! @param  U16 length : The length in bytes.
//!
Bool  mmc_set_block_len( U16 length )
{
   if( !mmc_drv_send_cmd( MMC_SET_BLOCK_LEN, length, MMC_RESP_R1 ))
      return FALSE;

   // check response, card must be in TRAN state
   if(( mmc_drv_read_response() & MMC_TRAN_STATE_MSK) != MMC_TRAN_STATE )
      return FALSE;

   Mmc_set_block_size(length);
   return TRUE;
}


#if (MMC_CARD_SECU_FUNC == ENABLE)

//! This function sends lock/unlock commands for sd or mmc
//!
//! @param
//!	Byte command_byte : CMD_FULL_ERASE ; CMD_LOCK ; CMD_UNLOCK...
//!	Byte pwd_len : password length in bytes (limited to 253)
//!	unsigned char* password : the password content
//!
//! @return Ctrl_status
//!
//!      an error occurs      ->    CTRL_FAIL
//!      command is sent      ->    CTRL_GOOD
//!
//! TODO
//! test lock/unlock error bit in status register after end of busy

Ctrl_status mmc_lock_unlock (Byte command_byte, U8 pwd_len, unsigned char * password) // password length in Bytes (possible values : 2,6,14)
{
   _MEM_TYPE_SLOW_ Byte block_count;

   if (CTRL_FAIL == mmc_set_block_len ((U8) pwd_len+2))
   {
      return CTRL_FAIL;
   }

   // initialise mmc for single block transmission
   Mmc_set_write();                          // set data dir in reception
   Mmc_enable_data();                        // enable data reception after response has been received
   Mmc_set_single_block();                   // enable multiple block data format

   Mmc_send_cmd_p_rep1 (MMC_LOCK_UNLOCK, 0, 0, 0, 0); // Sends the lock/unlock command
   // wait response
   if (KO == mmc_drv_wait_cmd_resp())
   {
      return CTRL_FAIL;
   }
   // check response
   if ((mmc_drv_read_response() & MMC_TRAN_STATE_MSK) != MMC_TRAN_STATE)
   {
      return CTRL_FAIL;
   }

   // Sends the command
   Mmc_wr_byte((Byte) command_byte);
   // Sends the data
   if (command_byte!=CMD_FULL_ERASE)
   {
      Mmc_wr_byte((Byte) pwd_len); // PWD_LENGTH
   }
   for ( block_count = 0 ; block_count < pwd_len ; block_count++) //PWD
   {
      Mmc_wr_byte((Byte) *(password+block_count));
   }

   if (!mmc_set_block_len( MMC_BLOCK_LENGTH_512B ))
      return CTRL_FAIL;

   return CTRL_GOOD;
}


//! Get sd status register and look if card is locked by a password
//!
//! @return:
//!	1 the card is locked
//!	0 the card is unlocked
//!
Bool mmc_is_locked()
{
   _MEM_TYPE_SLOW_ Uint32 response;

   // ask status
   if (!mmc_cmd_send_status())
      return 1;
   response = mmc_drv_read_response();
   if ((((Byte)(response>>24))&0x02)!=0x00)
   { // Then it is locked
      return 1;
   }
   return 0;
}


//! Get sd status register and look if the lock/unlock command was ok.
//!
//! @ return:
//!	1 lock/unlock command failed
//!	0 lock/unlock command was successfull
//!
Bool mmc_lock_unlock_failed()
{
   _MEM_TYPE_SLOW_ Uint32 response;

   // ask status
   if (!mmc_cmd_send_status())
      return 1;
   response = mmc_drv_read_response();
   if ((((Byte)(response>>24))&0x01)!=0x00)
   {  // Then it failed
      return 0;
   }
   return 1;
}
#endif      // end FUNC_MMC_CARD_SECU


//! ask mmc status register
//!
//! response must be read outside this function
//!
//! @ return:
//!	1 cmd response is good
//!	0 cmd response failed
//!
Bool  mmc_cmd_send_status(void)
{
   return mmc_drv_send_cmd( MMC_SEND_STATUS, g_u32_card_rca, MMC_RESP_R1 );
}

#endif // MMC enabled

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -