📄 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;
uint8 prev_lun;
//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...");
//on a good case prev_lun will be SD. But there might have been an interrupt
//that wrote a different lun to this slot. The prev_lun will capture that.
//also protect this code with a critical section... what is the interrupt sneaks in between the
//below two lines of code.
mcu_begin_critical_section();
prev_lun = _lun_log2phy(g_lun_phy2log_map[k_lun_sd]);
_lun_map_log2phy(g_lun_phy2log_map[k_lun_sd], k_lun_mmc);
mcu_end_critical_section();
//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
dev_common_media_led_on();
#endif
thread_return_dfa(k_success);
EXIT_NO_MEDIA:
trace0(0, sd, 99, "no media");
_sd_pwr_off();
//if the condition below is not true then the table has been altered somewhere
//between the time we wrote k_lun_mmc to the SD's slot
mcu_begin_critical_section();
if ( _lun_log2phy(g_lun_phy2log_map[k_lun_sd]) == k_lun_mmc)
{
_lun_map_log2phy(g_lun_phy2log_map[k_lun_sd], prev_lun);
}
mcu_end_critical_section();
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
dev_common_media_led_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));
// check for hardware write protection...
// -- AM
trace1(0, sd, 1, "g_dev_attr_lo = %02x",g_dev_attr_lo);
if ((g_dev_attr_lo & kbm_attr_lo_sd_wp_readonly))
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -