📄 sd.c
字号:
t_result tbh_wait_status_with_timeout(uint8 mask, uint16 ticks) reentrant;
t_result tbh_wait_status_with_timeout(uint8 mask, uint16 ticks) reentrant
{
uint8 status;
t_sync sync;
trace0(0, sd, 10, "tbh_wait_status_with_timeout()");
// do this to get kbm_sync_abort delivered of there is traffic on the control pipe
_isr_bind_dma_owner(g_tid, kbm_sync_none);
thread_set_timer(ticks+1);
do
{
_mcu_begin_critical_section();
sync = _thread_got_sync(kbm_sync_abort |kbm_sync_usbrst |kbm_sync_timer);
_mcu_end_critical_section();
thread_clr_sync(sync);
status = _sd_register_rd(x_sdc_stat);
if(sync & kbm_sync_abort)
{
trace0(0, sd, 10, "tbh_wait_status_with_timeout() - error: kbm_sync_abort");
// must delay some after this, but unknown how long, assume a few instruction cycles...
_sd_register_wr(sdc_ctl, kbm_sdc_ctl_sdc_rst);
return k_aborted;
}
if(sync & kbm_sync_usbrst)
{
trace0(0, sd, 10, "tbh_wait_status_with_timeout() - error: kbm_sync_usbrst");
// must delay some after this, but unknown how long, assume a few instruction cycles...
_sd_register_wr(sdc_ctl, kbm_sdc_ctl_sdc_rst);
return k_usbreset;
}
if(sync & kbm_sync_timer)
{
trace0(0, sd, 10, "tbh_wait_status_with_timeout() - error: kbm_sync_timer");
// must delay some after this, but unknown how long, assume a few instruction cycles...
_sd_register_wr(sdc_ctl, kbm_sdc_ctl_sdc_rst);
return k_timeout;
}
} while((status & mask) != mask);
return k_success;
}
//------------------------------------------------------------------------------
// issuing CMD0 - go idle - is the same as power on reset
// power cycling the card is easier and faster
//------------------------------------------------------------------------------
void dfa_sd_reset() reentrant
{
trace0(0, sd, 99, "sd_reset()");
//Jump to this location on an "Emergency Exit" due to sync_abort or sync_usbreset
if(setjmp(_sd_context))
{
trace0(0, sd, 99, "EMERGENCY EXIT!!");
thread_return_dfa(k_error);
}
_mcu_register_clr_bits(x_fmc_clk_ctl, k_fmc_clk_ctl_sd_disable);
_mcu_register_set_bits(x_fmc_clk_ctl, k_fmc_clk_ctl_sd_200khz);
_sd_register_set_bits(sdc_ctl, kbm_sdc_bus_type);
g_sdc_rca_h = 0x00;
g_sdc_rca_l = 0x00;
_sd_write_protected = k_false;
_sd_card_active = k_true;
_sd_data_loaded = k_false;
_sd_state = 0x00;
_sd_pwr_on();
// can afford a 2msec blocking loop here, hopefully
thread_set_timer(2);
while(!thread_got_sync(kbm_sync_timer));
//Now issue the reset command as well
trace1(0, sd, 1, "The sdc_ctl register %02x",sdc_ctl);
trace1(0, sd, 1, "The crd_ps register %02x",_mcu_register_rd(x_crd_ps));
sd_pre_cmd();
trace1(0, sd, 1, "The stat register %02x",_mcu_register_rd(x_sdc_stat));
//fill the command buffer
sdc_cmd_rsp_buf[0] = 0x40;
sdc_cmd_rsp_buf[1] = 0x00;
sdc_cmd_rsp_buf[2] = 0x00;
sdc_cmd_rsp_buf[3] = 0x00;
sdc_cmd_rsp_buf[4] = 0x00;
sd_display_rsp_buf();
//reset mode control register
sdc_mode_ctl = 0;
sdc_mode_ctl |= (kbm_sdc_cmd_no_rsp | kbm_sdc_rsp_crc_ds); // Disable Crc 7
thread_set_timer(1);
while(!(thread_got_sync(kbm_sync_timer)));
thread_clr_sync(kbm_sync_timer);
thread_return_dfa(k_success);
}
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
void dfa_sd_initialize() reentrant
{
t_result rslt;
//Jump to this location on an "Emergency Exit" due to sync_abort or sync_usbreset
trace0(0, sd, 99, "dfa_sd_initialize()");
// assmume no media
_lun_data_wr(k_lun_sd, media, (_lun_data_rd(k_lun_sd, media)&~(kbm_lun_media_present |kbm_lun_media_unknown |kbm_lun_media_changed)));
_lun_data_wr(k_lun_mmc, media, (_lun_data_rd(k_lun_mmc, media)&~(kbm_lun_media_present |kbm_lun_media_unknown |kbm_lun_media_changed)));
// clear the rsp buf byte 1 so we don't see remnant of previous operation
sdc_cmd_rsp_buf[1] = 0;
// monitor the card's busy bit - $$$need a symbol instead of a hex constant...
while(!(sdc_cmd_rsp_buf[1] & 0x80))
{
trace1(0, sd, 0, "top of while loop, _sd_card_active:%d", _sd_card_active);
// probe for SD card. if not found probe for MMC card.
if(k_lun_sd == g_active_lun)
{
_mcu_register_wr(x_sdc_stat, kbm_sdc_stat_rsp_rdy);
_mcu_register_wr(x_sdc_stat, kbm_sdc_stat_crc_err);
_sd_register_clr_bits(sdc_ctl, kbm_sdc_id_data);
if(k_success != tbh_wait_status_with_timeout(kbm_sdc_stat_crd_rdy, 5))
goto SWITCH_TO_MMC;
if(k_success != tbh_wait_status_with_timeout(kbm_sdc_stat_cmd_rdy, 5))
goto SWITCH_TO_MMC;
sdc_cmd_rsp_buf[0] = 0x77;
sdc_cmd_rsp_buf[1] = g_sdc_rca_h;
sdc_cmd_rsp_buf[2] = g_sdc_rca_l;
sdc_cmd_rsp_buf[3] = 0x00;
sdc_cmd_rsp_buf[4] = 0x00;
sdc_mode_ctl = 0;
sdc_mode_ctl |= kbm_sdc_cmd_48b_rsp;
rslt = tbh_wait_status_with_timeout(kbm_sdc_stat_rsp_rdy, 5);
sdc_read_rsp(5);
if(k_timeout == rslt)
{
SWITCH_TO_MMC:
trace0(0, sd, 0, "try mmc...");
_lun_map_log2phy(k_log_lun_sd, k_lun_mmc);
//g_active_lun = k_lun_mmc;
lun_set_active(k_lun_mmc);
_sd_card_active = k_true;
} else
if(k_success != rslt)
goto EXIT_NO_MEDIA;
}
// issue ACMD41
trace0(0, sd, 1, "Issuing ACMD41");
_mcu_register_wr(x_sdc_stat, kbm_sdc_stat_rsp_rdy);
_mcu_register_wr(x_sdc_stat, kbm_sdc_stat_crc_err);
_sd_register_clr_bits(sdc_ctl, kbm_sdc_id_data);
if(k_success != tbh_wait_status_with_timeout(kbm_sdc_stat_crd_rdy, 5))
goto EXIT_NO_MEDIA;
if(k_success != tbh_wait_status_with_timeout(kbm_sdc_stat_cmd_rdy, 5))
goto EXIT_NO_MEDIA;
if(k_lun_mmc == g_active_lun)
sdc_cmd_rsp_buf[0] = 0x41;
else
sdc_cmd_rsp_buf[0] = 0x69;
sdc_cmd_rsp_buf[1] = 0x80; // Voltage range 2.0 - 2.1
sdc_cmd_rsp_buf[2] = 0xFF;
sdc_cmd_rsp_buf[3] = 0x80;
sdc_cmd_rsp_buf[4] = 0x00;
sd_display_rsp_buf();
sdc_mode_ctl = 0;
sdc_mode_ctl |= (kbm_sdc_cmd_48b_rsp | kbm_sdc_rsp_crc_ds);
if(k_success != tbh_wait_status_with_timeout(kbm_sdc_stat_rsp_rdy, 5))
goto EXIT_NO_MEDIA;
sdc_read_rsp(5);
_mcu_register_wr(x_sdc_stat, kbm_sdc_stat_rsp_rdy);
}
// was there a card in the slot? if so g_active_lun is set to the correct phy lun index.
if(_sd_card_active)
{
// found a card
// clear the media changed flag so the framework will move on and establish the geometry
_lun_data(media) |= (kbm_lun_media_present |kbm_lun_media_unknown);
// need to set sense code here to get it reported (different from other luns)
_lun_data(sensep) = &sense_media_change;
switch(g_active_lun)
{
case k_lun_sd:
trace0(0, sd, 99, "media is SD");
_mcu_register_set_bits(x_crd_ps, kbm_crd_ps_sd);
break;
case k_lun_mmc:
trace0(0, sd, 99, "media is MMC");
_mcu_register_set_bits(x_crd_ps, kbm_crd_ps_mmc);
break;
}
}
irq_control(k_irq_sd_insert_eject, kbm_irqctl_clear |kbm_irqctl_unmask);
trace0(0, sd, 99, "media");
#ifdef k_pfm_led
_mcu_register_set_bits(x_gpiob_out, kbm_gpio15); //on
#endif
thread_return_dfa(k_success);
EXIT_NO_MEDIA:
trace0(0, sd, 99, "no media");
_sd_pwr_off();
_lun_map_log2phy(k_log_lun_sd, k_lun_sd);
irq_control(k_irq_sd_insert_eject, kbm_irqctl_clear |kbm_irqctl_unmask);
#ifdef k_pfm_led
_mcu_register_clr_bits(x_gpiob_out, kbm_gpio15); //off
#endif
thread_return_dfa(k_success);
}
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
void dfa_sd_identify_device() reentrant
{
uint8 i =0;
//local variables for calculating the size
uint8 read_bl_len, c_size_mult;
uint16 c_size, block_len, mult;
uint32 blocknr;
uint8 Result = 0;
//Jump to this location on an "Emergency Exit" due to sync_abort or sync_usbreset
if(setjmp(_sd_context))
{
trace0(0, sd, 0, "EMERGENCY EXIT!!");
thread_return_dfa(k_error);
}
trace0(0, sd, 1, "+sd_identify_device()");
//This will det the identification data from the sd device
trace1(0, sd, 1, "The sdc_ctl register %02x",sdc_ctl);
sd_pre_cmd();
trace1(0, sd, 1, "The stat register %02x",_mcu_register_rd(x_sdc_stat));
sdc_cmd_rsp_buf[0] = 0x42;
sdc_cmd_rsp_buf[1] = 0x00;
sdc_cmd_rsp_buf[2] = 0x00;
sdc_cmd_rsp_buf[3] = 0x00;
sdc_cmd_rsp_buf[4] = 0x00;
sdc_cmd_rsp_buf[5] = 0x00;
//sd_display_rsp_buf();
//reset mode control register
sdc_mode_ctl = 0;
//ready to receive the response
sdc_mode_ctl |= (kbm_sdc_cmd_136b_rsp );
trace1(0, sd, 1, "The sdc_mode_ctl register %02x",sdc_mode_ctl);
trace1(0, sd, 1, "The stat register %02x",_mcu_register_rd(x_sdc_stat));
sdc_wait_status_with_timeout(kbm_sdc_stat_rsp_rdy,300);
trace1(0, sd, 1, "The stat register %02x",_mcu_register_rd(x_sdc_stat));
sdc_read_rsp(17);
//sd_display_rsp_buf();
_mcu_register_wr(x_sdc_stat, kbm_sdc_stat_rsp_rdy);
//Issue CMD3 Or GetRCA
trace1(0, sd, 1, "The sdc_ctl register %02x",sdc_ctl);
sd_pre_cmd();
trace1(0, sd, 1, "The stat register %02x",_mcu_register_rd(x_sdc_stat));
//If the device is mmc then we need to preset the rca
if(g_active_lun == k_lun_mmc)
{
g_sdc_rca_h = 0x01;
g_sdc_rca_l = 0x02;
}
sdc_cmd_rsp_buf[0] = 0x43;
sdc_cmd_rsp_buf[1] = g_sdc_rca_h;
sdc_cmd_rsp_buf[2] = g_sdc_rca_l;
sdc_cmd_rsp_buf[3] = 0x00;
sdc_cmd_rsp_buf[4] = 0x00;
sdc_cmd_rsp_buf[5] = 0x00;
//sd_display_rsp_buf();
_sd_wait_48b_resp();
if(g_active_lun == k_lun_sd)
{
g_sdc_rca_h = sdc_cmd_rsp_buf[1];
g_sdc_rca_l = sdc_cmd_rsp_buf[2];
}
//sd_display_rsp_buf();
sdc_read_rsp(5);
_mcu_register_wr(x_sdc_stat, kbm_sdc_stat_rsp_rdy);
//sd_get_status();
//sdc_read_rsp(17);
//SEND_CSD or CMD9
trace0(0, sd, 1, "Issue SEND_CSD");
sd_pre_cmd();
trace1(0, sd, 1, "The stat register %02x",_mcu_register_rd(x_sdc_stat));
sdc_cmd_rsp_buf[0] = 0x49;
sdc_cmd_rsp_buf[1] = g_sdc_rca_h;
sdc_cmd_rsp_buf[2] = g_sdc_rca_l;
sdc_cmd_rsp_buf[3] = 0x00;
sdc_cmd_rsp_buf[4] = 0x00;
sdc_cmd_rsp_buf[5] = 0x00;
//reset mode control register
sdc_mode_ctl = 0;
//ready to receive the response
sdc_mode_ctl |= (kbm_sdc_cmd_136b_rsp);
trace1(0, sd, 1, "The sdc_mode_ctl register %02x",sdc_mode_ctl);
trace1(0, sd, 1, "The stat register %02x",_mcu_register_rd(x_sdc_stat));
sdc_wait_status_with_timeout(kbm_sdc_stat_rsp_rdy,300);
trace1(0, sd, 1, "The stat register %02x",_mcu_register_rd(x_sdc_stat));
sd_display_rsp_buf();
//Calculate LBA max
read_bl_len = (sdc_cmd_rsp_buf[6] & 0x0f);
c_size = (sdc_cmd_rsp_buf[7] & 0x03);
c_size = (c_size << 10);
c_size += ((uint16)sdc_cmd_rsp_buf[8] << 2);
c_size += ((sdc_cmd_rsp_buf[9] & 0xc0) >> 6);
c_size &= 0x0fff;
c_size_mult = (sdc_cmd_rsp_buf[10] & 0x03);
c_size_mult = (c_size_mult << 1);
c_size_mult += ((sdc_cmd_rsp_buf[11] & 0x80) >> 7);
trace3(0, sd, 1, " The read_bl_len is %d , c_size is %04x, c_size_mult : %d ", read_bl_len,c_size,c_size_mult);
block_len = (1 << read_bl_len);
mult = (1 << (c_size_mult + 2));
trace2(0, sd, 1, " Block_len is %d, mult = %d",block_len, mult);
blocknr = (((uint32)c_size + (uint32)1) * (uint32)mult);
trace2(0, sd, 1, "the blocknr is %04x%04x", _hw(blocknr),_lw(blocknr));
blocknr = blocknr - (uint32) 1;
trace2(0, sd, 1, "the blocknr is %04x%04x", _hw(blocknr),_lw(blocknr));
_lun_data(capacity).lba_max.u32 = blocknr;
_lun_data(capacity).lba_sz.u32 = block_len;
trace2(0, sd, 1, "Total User-addressable Sectors: %04X%04X", _hw(_lun_data(capacity).lba_max.u32), _lw(_lun_data(capacity).lba_max.u32));
//Is the media write protected?
//Check for hardware write protection...
if(_mcu_register_rd(x_media_sts) & 0x01)
_sd_write_protected = k_true;
//Check for software write protection
if((sdc_cmd_rsp_buf[15] & 0x04) || (sdc_cmd_rsp_buf[15] & 0x08))
_sd_write_protected = k_true;
if(_sd_write_protected == k_true)
{
_lun_data(media) |= kbm_lun_media_wrprot;
} else
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -