📄 ms.c
字号:
// Return:
// A t_result indicating:
// k_success - status & mask == value.
// k_usbrst - usb reset signalling was detected while waiting.
// k_aborted - traffic occurred on the control pipe while waiting (probably a mass storage reset).
// k_timeout - timeout limit exceeded.
//
// Notes:
// This is a FUNCTION, not a DFA.
//
// Since:
// fmc-1.0
//------------------------------------------------------------------------------
t_result ms_wait_fifo_with_timeout(uint8 msk, uint8 val, uint8 ticks) reentrant;
t_result ms_wait_fifo_with_timeout(uint8 msk, uint8 val, uint8 ticks) reentrant
{
//uint8 status;
//t_sync sync;
trace3(0, ms, 1, "ms_wait_fifo_with_timeout(mask:%02X val:%02X ticks:%d)", msk, val, ticks);
//_stack_check();
thread_set_timer(ticks+1);
do
{
status = _ms_register_rd(ms_fifo_stat);
sync = thread_got_sync(kbm_sync_usbrst |kbm_sync_abort |kbm_sync_timer);
_thread_clr_sync(sync);
if (sync & kbm_sync_abort)
{
trace0(0, err, 110, "ms_wait_fifo_with_timeout() - error: kbm_sync_abort");
return k_aborted;
}
if (sync & kbm_sync_usbrst)
{
trace0(0, err, 110, "ms_wait_fifo_with_timeout() - error: kbm_sync_usbrst");
return k_usbreset;
}
if (sync & kbm_sync_timer)
{
trace0(0, err, 110, "ms_wait_fifo_with_timeout() - error: kbm_sync_timer");
return k_timeout;
}
} while ((status & msk) != val);
return k_success;
}
//+-----------------------------------------------------------------------------
// Name:
// ms_set_tpc
//
// Declaration:
// t_result ms_set_tpc(uint8 tpc, uint8 count);
//
// Purpose:
// Send a transfer protocol command (TPC) to the MS card.
//
// Arguments:
// tpc - a uint8 indicating the tpc.
// count - a uint8 indicating the number of bytes to move during this command.
//
// Return:
// A t_result indicating:
// k_success - tpc issued.
// k_error - failed to issue tpc.
//
// Notes:
// This is a FUNCTION, not a DFA.
//
// Since:
// fmc-1.0
//------------------------------------------------------------------------------
t_result ms_set_tpc(uint8 tpc, uint8 count) reentrant;
t_result ms_set_tpc(uint8 tpc, uint8 count) reentrant
{
// profile:
// during read:
// ms_set_tpc 48usec to 76usec
// wait rdy bit 46usec to 74usec
//_profile_on(5);
trace2(0, ms, 0, "ms_set_tpc() tpc:%02X count:%02X", tpc, count);
//_stack_check();
// wait for the rdy bit in msc_stat to go hi
//_profile_on(4);
if (k_success != ms_wait_msc_stat_rdy_with_timeout(10))
return k_error;
//_profile_off(4);
// write the byte count
_ms_register_wr(ms_bc, count);
// write the tpc
_ms_register_wr(ms_tpc_cmd, tpc);
//_profile_off(5);
return k_success;
}
//+-----------------------------------------------------------------------------
// Name:
// ms_get_int
//
// Declaration:
// t_result ms_get_int(uint8 ticks);
//
// Purpose:
// Issue a getint command to solicit the result of the previous command.
//
// Arguments:
// ticks - a uint8 representing the timeout period in milliseconds.
//
// Return:
// A t_result indicating:
// k_success - the module global variable _factor contains the results.
// k_error - either cannot issue the command or read back the results.
// contents of _factor undefined.
//
// Notes:
// This is a FUNCTION, not a DFA.
// The module global variable _factor is written with the results as a side effect.
//
// Since:
// fmc-1.0
//------------------------------------------------------------------------------
t_result ms_get_int(uint8 ticks) reentrant;
t_result ms_get_int(uint8 ticks) reentrant
{
// profile:
// during read:
// ms_get_int 108 to 133usec
// wait sif 52usec
// ms_set_tpc 52usec to 76usec
// wait fifo empty 2usec
//_profile_on(6);
trace0(0, ms, 0, "ms_get_int()");
//_stack_check();
// if you dont have this in here sisoft sandra fails. tbh...
// the problem may well be a stack overflow...
#if 1
//_profile_on(6);
// new - dont wait if its already there
if ((_ms_register_rd(ms_alt_stat) & kbm_msc_stat_sif) == kbm_msc_stat_sif)
{_mcu_register_wr(x_msc_stat, kbm_msc_stat_sif);}
else
// end of new
#endif
if (k_success != ms_wait_msc_stat_sif_with_timeout(ticks))
return k_error;
//_profile_off(6);
// write the tpc
//_profile_on(5);
ms_set_tpc(k_ms_tpc_get_int, 1);
//_profile_off(5);
//_profile_on(4);
// wait rx fifo not empty
if (_ms_rx_data_fifo_is_empty())
if (k_success != ms_wait_fifo_with_timeout(ms_fifo_stat_r_buf_e, 0, 3))
return k_error;
//_profile_off(4);
// read the interrupt data
_factor = _ms_register_rd(ms_rx_db_lsb);
g_tmp = _ms_register_rd(ms_rx_db_msb); // throw away
trace1(0, ms, 0, "_factor:%02X", _factor);
//_profile_off(6);
return k_success;
}
// so far i haven't got the acd code to work correctly...
// but since it doesn't improve performance anyhow, there's not much point...
//#define k_use_acd
#ifdef k_use_acd
//+-----------------------------------------------------------------------------
// Name:
// ms_get_int_acd
//
// Declaration:
// t_result ms_get_int_acd(uint8 ticks);
//
// Purpose:
// Issue a getint command to solicit the result of the previous command.
// Only to be used with ACD mode.
// Allows skipping the wait for SIF, and the set-tpc for getint.
// The goal is to use it to slightly improve the read performance.
//
// Arguments:
// None.
//
// Return:
// A t_result indicating:
// k_success - the module global variable _factor contains the results.
// k_error - either cannot issue the command or read back the results.
// contents of _factor undefined.
//
// Notes:
// This is a FUNCTION, not a DFA.
// The module global variable _factor is written with the results as a side effect.
//
// Since:
// fmc-1.0
//------------------------------------------------------------------------------
t_result ms_get_int_acd(void) reentrant;
t_result ms_get_int_acd(void) reentrant
{
trace0(0, ms, 0, "ms_get_int_acd()");
//_stack_check();
// wait rx fifo not empty
if (_ms_rx_data_fifo_is_empty())
if (k_success != ms_wait_fifo_with_timeout(ms_fifo_stat_r_buf_e, 0, 3))
return k_error;
// read the interrupt data
_factor = _ms_register_rd(ms_rx_db_lsb);
g_tmp = _ms_register_rd(ms_rx_db_msb); // throw away
trace1(0, ms, 0, "_factor:%02X", _factor);
return k_success;
}
#endif
//+-----------------------------------------------------------------------------
// Name:
// ms_set_cmd
//
// Declaration:
// t_result ms_set_cmd(uint8 cmd);
//
// Purpose:
// Send a flash command to the MS card.
//
// Arguments:
// cmd - a uint8 representing the command id.
//
// Return:
// A t_result indicating:
// k_success - command issued.
// k_error - failed to issue command.
//
// Notes:
// This is a FUNCTION, not a DFA.
//
// Since:
// fmc-1.0
//------------------------------------------------------------------------------
t_result ms_set_cmd(uint8 cmd) reentrant;
t_result ms_set_cmd(uint8 cmd) reentrant
{
trace1(0, ms, 0, "ms_set_cmd() cmd:%02X", cmd);
//_stack_check();
// write the tpc
if (k_success != ms_set_tpc(k_ms_tpc_set_cmd, 1))
return k_error;
// write the command
_ms_register_wr(ms_tx_db_msb, 0);
_ms_register_wr(ms_tx_db_lsb, cmd);
return k_success;
}
//+-----------------------------------------------------------------------------
// Name:
// ms_set_read_reg_addrs
//
// Declaration:
// t_result ms_set_read_reg_addrs(uint8 start, uint8 count);
//
// Purpose:
// Tell the MS card that its registers are to be read by specifying the starting
// register offset and the number of registers to be read.
//
// Arguments:
// start - the offset of the first register to read.
// count - the number of consecutive registers to read.
//
// Return:
// A t_result indicating:
// k_success - read register start/count are delivered to the card.
// k_error - failed to configure the card for a register read.
//
// Notes:
// This is a FUNCTION, not a DFA.
//
// Since:
// fmc-1.0
//------------------------------------------------------------------------------
t_result ms_set_read_reg_addrs(uint8 start, uint8 count) reentrant;
t_result ms_set_read_reg_addrs(uint8 start, uint8 count) reentrant
{
trace2(0, ms, 0, "ms_set_read_reg_addrs() start:0x%02X count:0x%02X", start, count);
//_stack_check();
// write the tpc
if (k_success != ms_set_tpc(k_ms_tpc_set_rw_reg, 4))
return k_error;
// write the command
_ms_register_wr(ms_tx_db_msb, count);
_ms_register_wr(ms_tx_db_lsb, start);
if (!_ms_tx_data_fifo_is_empty())
if (k_success != ms_wait_fifo_with_timeout(ms_fifo_stat_t_buf_e, ms_fifo_stat_t_buf_e, 3))
return k_error;
_ms_register_wr(ms_tx_db_msb, 0);
_ms_register_wr(ms_tx_db_lsb, k_ms_parm_system);
if (!_ms_tx_data_fifo_is_empty())
if (k_success != ms_wait_fifo_with_timeout(ms_fifo_stat_t_buf_e, ms_fifo_stat_t_buf_e, 3))
return k_error;
return k_success;
}
//+-----------------------------------------------------------------------------
// Name:
// ms_set_write_reg_addrs
//
// Declaration:
// t_result ms_set_write_reg_addrs(uint8 start, uint8 count);
//
// Purpose:
// Tell the MS card that its registers are to be written by specifying the starting
// register offset and the number of registers to be written.
//
// Arguments:
// start - the offset of the first register to write.
// count - the number of consecutive registers to write.
//
// Return:
// A t_result indicating:
// k_success - write register start/count are delivered to the card.
// k_error - failed to configure the card for a register write.
//
// Notes:
// This is a FUNCTION, not a DFA.
//
// Since:
// fmc-1.0
//------------------------------------------------------------------------------
t_result ms_set_write_reg_addrs(uint8 start, uint8 count) reentrant;
t_result ms_set_write_reg_addrs(uint8 start, uint8 count) reentrant
{
//_profile_on(6);
trace2(0, ms, 0, "ms_set_write_reg_addrs() start:%02X count:0x%02X", start, count);
//_stack_check();
// write the tpc
if (k_success != ms_set_tpc(k_ms_tpc_set_rw_reg, 4))
return k_error;
// write the command
_ms_register_wr(ms_tx_db_msb, k_ms_ext_ovwr_flg);
_ms_register_wr(ms_tx_db_lsb, 0);
if (!_ms_tx_data_fifo_is_empty())
if (k_success != ms_wait_fifo_with_timeout(ms_fifo_stat_t_buf_e, ms_fifo_stat_t_buf_e, 3))
return k_error;
_ms_register_wr(ms_tx_db_msb, count);
_ms_register_wr(ms_tx_db_lsb, start);
if (!_ms_tx_data_fifo_is_empty())
if (k_success != ms_wait_fifo_with_timeout(ms_fifo_stat_t_buf_e, ms_fifo_stat_t_buf_e, 3))
return k_error;
//_profile_off(6);
return k_success;
}
//+-----------------------------------------------------------------------------
// Name:
// ms_read_status
//
// Declaration:
// t_result ms_read_status(void);
//
// Purpose:
// After an error read the status registers to determine the cause.
//
// Arguments:
// None.
//
// Return:
// A t_result indicating:
// k_success - the module global variables _status0 and _status1 contain the status.
// k_error - failed to obtain the status.
// contents of _status0 and _status1 undefined.
//
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -