📄 mmc_sd.c
字号:
//! 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 + -