📄 sd.c
字号:
{
_lun_data(media) &= ~kbm_lun_media_wrprot;
}
sdc_read_rsp(17);
_mcu_register_wr(x_sdc_stat, kbm_sdc_stat_rsp_rdy);
//Put the device into transfer mode and get ready to roll
sd_get_status();
//select the crd
sd_pre_cmd();
sdc_cmd_rsp_buf[0] = 0x47;
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;
sd_display_rsp_buf();
trace1(0, sd, 1, "The stat register %02x",_mcu_register_rd(x_sdc_stat));
_sd_wait_48b_resp();
sd_display_rsp_buf();
sd_get_status();
sdc_read_rsp(5);
//**********************************
//Set the block length
trace0(0, sd, 1, "Set the block length to 512")
sd_pre_cmd();
sdc_cmd_rsp_buf[0] = 0x50;
sdc_cmd_rsp_buf[1] = 0x00;
sdc_cmd_rsp_buf[2] = 0x00;
sdc_cmd_rsp_buf[3] = 0x02;
sdc_cmd_rsp_buf[4] = 0x00;
//sd_display_rsp_buf();
trace1(0, sd, 0, "The stat register %02x",_mcu_register_rd(x_sdc_stat));
_sd_wait_48b_resp();
sd_display_rsp_buf();
sd_get_status();
sdc_read_rsp(5);
//********************************************
//set the data bus to 4 bit wide
if(g_active_lun == k_lun_sd)
{
sd_set_bus_width(k_four_data_lines);
}
sd_get_status();
_lun_data(media) &= ~kbm_lun_media_unknown;
_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_20mhz);
//Enough time to let the clk freq change... should be changed to more accurate time.
thread_set_timer(1);
while(!(thread_got_sync(kbm_sync_timer)));
thread_clr_sync(kbm_sync_timer);
thread_return_dfa(k_success);
}
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
void sd_pre_erase() reentrant
{
trace0(0, sd, 0, "+sd_pre_erase();");
sd_app_cmd();
sd_pre_cmd();
sdc_cmd_rsp_buf[0] = 0x57; //pre_ERASE
sdc_cmd_rsp_buf[1] = 0X00;
sdc_cmd_rsp_buf[2] = 0X00;
sdc_cmd_rsp_buf[3] = g_n_lb_this_split.u8.hl;
sdc_cmd_rsp_buf[4] = g_n_lb_this_split.u8.lo;
_sd_wait_48b_resp();
sd_display_rsp_buf();
sdc_read_rsp(5);
return;
}
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
t_result sd_read_write_begin_xfer() reentrant
{
uint32 n_bytes_this_xfer = 0;
//The max lbs we can transfer is however much the host asks for
if(sie_is_high_speed())
{
// timer1 disabled during sd transfers to avoid data corruption issue. bug report #343
#if 0
//Turn off the timer interrupt for 2.0 reads
irq_control(k_irq_cpu_t1, kbm_irqctl_mask);
//Put the led in the opposite state of idle
if (g_led_stays_on) //opposite of idle state
gpio_clrbit(0);
else
gpio_setbit(0);
#endif
_lun_data(max_lb_per_split) =_fmc_get_lb_count_32();
_lun_data(max_lb_per_burst) = _fmc_get_lb_count_32();
} else
{
if(_sd_data_xfer_cmd == k_sdc_cmd_write_mult_blocks) // we can issue mult write cmd
{
_lun_data(max_lb_per_split) = _fmc_get_lb_count_32();
_lun_data(max_lb_per_burst) = 1;
//Turn off Auto xfer and exit on count zero
_fmc_set_options(kbm_fmc_disable_auto_xfer |kbm_fmc_end_burst_on_count_down |kbm_fmc_xfer_512_byte_pkt);
} else
{ //1.1 reads
_lun_data(max_lb_per_split) = 1;
_lun_data(max_lb_per_burst) = 1;
//Turn off Auto xfer
_fmc_set_options(kbm_fmc_disable_auto_xfer |kbm_fmc_xfer_512_byte_pkt);
trace1(0, sd, 3, "Setting the 512 byte pkt bit.. %02x", g_fmc_options);
}
}
//Even though the timeout should be calculated based on the CSD register, we shall calculate based on 1.1
//transfer speed. Currently we are at 200kBPS and this is the slowest part of the equation.
//On future releases, when we have overcome the hardware limitations, we shall calculate the timeout using
//the media-dependant values from the CSD register.
//Since any 16 or 32 bit computation slows down the reads/writes.. this value is computed offline
//It takes 2.5 ms to xfer a block of data at 200 KBPS. Let us round it to 3 ms. The multiply by 2 to add a margin.
//g_fmc_timeout = ( 6 * _fmc_get_lb_count_32());
// if(g_fmc_timeout < 250)
// g_fmc_timeout = 250; // Set the minimum timeout to 50 ms, to care of the device overhead
//The speeds of cards vary. So the timeout value is being set to a big number 10 sec, following the
//other luns
_fmc_set_timeout(10000);
trace1(0, sd, 0, "Setting the timeout value to.. %04x", g_fmc_timeout);
//Clear and unmask the CRC error interrupt
irq_control(k_irq_fmc_sdc_crc_err, kbm_irqctl_clear |kbm_irqctl_unmask);
return k_success;
}
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
t_result sd_read_write_end_xfer() reentrant
{
t_result Result = 0;
trace0(0, sd, 3, "sd_read_write_end_xfer");
//Did we get here on a failure?
if(k_success !=_fmc_get_result())
{
//did the media get removed
if(!(_mcu_register_rd(x_crd_ps) & (kbm_crd_ps_sd |kbm_crd_ps_mmc)))
return _fmc_get_result();
//Issue a get status to see if the device is alive and kicking ?
sd_get_status();
//Did a CRC Error occur? or Did we exit on a sd_blk_ovrrun error Or the card is dead?
if((_mcu_register_rd(x_sdc_stat) & kbm_sdc_stat_crc_err) || (_mcu_register_rd(x_fmc_err) & kbm_fmc_err_sd_blk_ovrun)
|| (_sd_card_active == k_false))
{
if(_sd_data_xfer_cmd == k_sdc_cmd_write_mult_blocks)
{
_lun_data(sensep) = &sense_write_error;
} else
{
//if the sd_blk_ovrrun error occurred there are atleast 2 blocks that were not received by the host
//This has not been observed in 1.1 speeds as we hand fill the buffers
if((_mcu_register_rd(x_fmc_err) & kbm_fmc_err_sd_blk_ovrun) && sie_is_high_speed())
{
_mscbot_incr_residue(0x400);
}
_lun_data(sensep) = &sense_read_error;
}
}
}
//We are done with the data transfer... so issue the stop command
//NB:- The SD spec says in section 4.3.3 'Some cards may require long an unpredictable times to write a block of data"
// So, how long should we wait? On trial and error basis I have set the timeout to 1 sec. We have good
// reasons now why lesser values will not work.
sdc_wait_status_with_timeout(kbm_sdc_stat_crd_rdy,1000);
//Only on 2.0 speeds and in writes
if(sie_is_high_speed() || ( _sd_data_xfer_cmd == k_sdc_cmd_write_mult_blocks))
sd_stop_transfer();
// timer1 disabled during sd transfers to avoid data corruption issue. bug report #343
#if 0
if(sie_is_high_speed())
{
//Turn on the timer interrupt
irq_control(k_irq_cpu_t1, kbm_irqctl_unmask);
if (g_led_stays_on) //restore to idle state
gpio_setbit(0);
else
gpio_clrbit(0);
}
#endif
return _fmc_get_result();
}
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
t_result sd_read_write_begin_split() reentrant
{
trace0(0, sd, 3, "sd_read_write_begin_split");
#ifdef Debug_On
gpio_bit_is_output(5);
gpio_setbit(5);
#endif
//did the media get removed
if((_sd_card_active == k_false)||(!(_mcu_register_rd(x_crd_ps) & (kbm_crd_ps_sd |kbm_crd_ps_mmc))))
return k_error;
//issue the cmd
//check to see if the device is done with previous transfer
if(!(x_sdc_stat & kbm_sdc_stat_crd_rdy))
sdc_wait_status_with_timeout(kbm_sdc_stat_crd_rdy,1000);
//we have some data to start with ... so do the prep
trace1(0, tm, 0, "@%d Start wait state tran", g_cdm0);
sd_get_status();
while((_sd_state != k_sdc_state_tran) && (_sd_card_active == k_true))
{
sd_get_status();
}
trace1(0, tm, 3, "@%d End wait state tran", g_cdm0);
//did the media get removed
if(_sd_card_active == k_false)
return k_error;
//Issue the Read/write command CMD18
trace1(0, sd, 3, "The stat register %02x",_mcu_register_rd(x_sdc_stat));
//if it is a write issue pre erase
if((_sd_data_xfer_cmd == k_sdc_cmd_write_mult_blocks) && (g_active_lun == k_lun_sd))
sd_pre_erase();
_mcu_register_wr(x_sdc_stat, kbm_sdc_stat_rsp_rdy);
if(g_active_lun == k_lun_sd)
sdc_ctl |= (kbm_sdc_id_data | kbm_sdc_bus_type);
else
sdc_ctl |= (kbm_sdc_id_data);
trace1(0, sd, 3, "The fmc_clk_ctl register %02x",x_fmc_clk_ctl);
trace1(0, sd, 3, "The sdc_ctl register %02x",sdc_ctl);
//sdc_wait_status_with_timeout(kbm_sdc_stat_crd_rdy,1000);
if(!(x_sdc_stat & kbm_sdc_stat_cmd_rdy))
sdc_wait_status_with_timeout(kbm_sdc_stat_cmd_rdy,1000);
_sd_start_addr_this_xfer.u32 = _fmc_get_start_lb_32();
trace2(0, sd, 3, "read/write addr:%04X%04X ", _hw(_sd_start_addr_this_xfer.u32), _lw(_sd_start_addr_this_xfer.u32));
_sd_start_addr_this_xfer.u32 = _sd_start_addr_this_xfer.u32 * (uint32) 512;
trace2(0, sd, 3, "read/write addr:%04X%04X ", _hw(_sd_start_addr_this_xfer.u32), _lw(_sd_start_addr_this_xfer.u32));
sdc_cmd_rsp_buf[0] = _sd_data_xfer_cmd;
sdc_cmd_rsp_buf[1] = _sd_start_addr_this_xfer.u8.hi;
sdc_cmd_rsp_buf[2] = _sd_start_addr_this_xfer.u8.lh;
sdc_cmd_rsp_buf[3] = _sd_start_addr_this_xfer.u8.hl;
sdc_cmd_rsp_buf[4] = _sd_start_addr_this_xfer.u8.lo;
sd_display_rsp_buf();
trace1(0, sd, 3, "The stat register %02x",_mcu_register_rd(x_sdc_stat));
trace0(0, sd, 0, "I am HERE!!!");
//Not calling the macro coz we have to wait a little longer for the response
// _sd_wait_48b_resp();
sdc_mode_ctl = 0;
trace1(0, sd, 0, "The stat register %02x",_mcu_register_rd(x_sdc_stat));
sdc_mode_ctl |= kbm_sdc_cmd_48b_rsp;
trace1(0, sd, 0, "The sdc_mode_ctl register %02x",sdc_mode_ctl);
sdc_wait_status_with_timeout(kbm_sdc_stat_rsp_rdy,2000);
trace1(0, sd, 0, "The stat register %02x",_mcu_register_rd(x_sdc_stat));
//did the media get removed
if(_sd_card_active == k_false)
return k_error;
trace1(0, sd, 3, "The stat register %02x",_mcu_register_rd(x_sdc_stat));
_mcu_register_wr(x_sdc_stat, kbm_sdc_stat_rsp_rdy);
_mcu_register_wr(x_sdc_stat, kbm_sdc_stat_crc_err);
_mcu_register_clr_bits(x_sdc_stat_msk,kbm_sdc_stat_crc_err);
trace1(0, sd, 3, "The stat register %02x",_mcu_register_rd(x_sdc_stat));
trace1(0, sd, 3, "The stat msk register %02x",x_sdc_stat_msk);
#ifdef Debug_On
gpio_clrbit(5);
#endif
return k_success;
}
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
xdata t_udw32 _current_byte_count;
t_result sd_read_intra_burst() reentrant
{
//get the buffer ready to receive data
trace0(0, sd, 3, "sd_read_intra_burst");
if (!sie_is_high_speed())
{
#ifdef k_dbg_on
dbg_bufferstat();
#endif
_mcu_register_clr_bits(x_ep2_ctl, kbm_ep2_ctl_ramwr_tog | kbm_ep2_ctl_rdtog_valid);
_mcu_register_set_bits(x_ep2_ctl, kbm_ep2_ctl_wrtog_valid);
_mcu_register_wr(x_isr0, kbm_isr0_ramwr_a);
#ifdef k_dbg_on
dbg_bufferstat();
#endif
}
else
{
//make a copy of this register for read retries
_current_byte_count.u8.hi = _mcu_register_rd(x_fmc_cnt3);
_current_byte_count.u8.lh = _mcu_register_rd(x_fmc_cnt2);
_current_byte_count.u8.hl = _mcu_register_rd(x_fmc_cnt1);
_current_byte_count.u8.lo = _mcu_register_rd(x_fmc_cnt0);
}
return sd_read_write_begin_split();
}
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
uint8 k;
uint8 xdata * data data_ptr;
uint8 xdata temp_buf[64];
t_result sd_read_end_burst() reentrant
{
//allocate 64 bytes of xdata space for the temporary holder
uint8 n, Result = 0;
uint16 offset = 0;
t_udw32 n_bytes;
trace0(0, sd, 3, "sd_read_end_burst");
g_cdm0 = 0;
//Did a CRC Error occur?
if (_mcu_register_rd(x_sdc_stat) & kbm_sdc_stat_crc_err)
{
trace0(0, sd, 0, "A CRC Error occurred");
return k_error;
}
//Just for High speed
if (sie_is_high_speed())
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -