serial_transfer: add read command
This commit is contained in:
parent
ff7a03a75c
commit
45c6bcf211
1
base.mk
1
base.mk
@ -9,6 +9,7 @@ CFLAGS += -Wno-array-bounds
|
|||||||
CFLAGS += -Wno-error=maybe-uninitialized
|
CFLAGS += -Wno-error=maybe-uninitialized
|
||||||
CFLAGS += -Wno-error=unused-but-set-variable
|
CFLAGS += -Wno-error=unused-but-set-variable
|
||||||
CFLAGS += -Wno-error=unused-variable
|
CFLAGS += -Wno-error=unused-variable
|
||||||
|
CFLAGS += -Wno-error=unused-function
|
||||||
|
|
||||||
CXXFLAGS += -fno-exceptions -fno-non-call-exceptions -fno-rtti -fno-threadsafe-statics
|
CXXFLAGS += -fno-exceptions -fno-non-call-exceptions -fno-rtti -fno-threadsafe-statics
|
||||||
|
|
||||||
|
6
crc32.c
6
crc32.c
@ -72,11 +72,11 @@ const uint32_t crc32_table[256] = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
uint32_t
|
uint32_t
|
||||||
crc32_update(uint32_t crc, const uint8_t * data, uint32_t len)
|
crc32_update(uint32_t crc, const uint8_t * buf, uint32_t len)
|
||||||
{
|
{
|
||||||
while (len > 0) {
|
while (len > 0) {
|
||||||
crc = crc32_table[*data ^ ((crc >> 24) & 0xff)] ^ (crc << 8);
|
crc = crc32_table[*buf ^ ((crc >> 24) & 0xff)] ^ (crc << 8);
|
||||||
data++;
|
buf++;
|
||||||
len--;
|
len--;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -181,8 +181,5 @@ void main()
|
|||||||
theta += half_degree;
|
theta += half_degree;
|
||||||
frame_ix = (frame_ix + 1) & 1;
|
frame_ix = (frame_ix + 1) & 1;
|
||||||
frame += 1;
|
frame += 1;
|
||||||
|
|
||||||
if (frame > 10)
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -173,7 +173,7 @@ void recv_device_status(struct maple_display_poll_state &state)
|
|||||||
if (bus_data.command_code != maple::device_status::command_code) {
|
if (bus_data.command_code != maple::device_status::command_code) {
|
||||||
state.port[port].ap__lm = 0;
|
state.port[port].ap__lm = 0;
|
||||||
} else {
|
} else {
|
||||||
auto& data_fields = bus_data.data_fields;
|
//auto& data_fields = bus_data.data_fields;
|
||||||
|
|
||||||
uint8_t lm = bus_data.source_ap & ap::lm_bus::bit_mask;
|
uint8_t lm = bus_data.source_ap & ap::lm_bus::bit_mask;
|
||||||
state.port[port].ap__lm = lm;
|
state.port[port].ap__lm = lm;
|
||||||
@ -298,6 +298,14 @@ void render_write_state(char * dst)
|
|||||||
render_u32(serial_load::state.write_crc.value, &dst[24]);
|
render_u32(serial_load::state.write_crc.value, &dst[24]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void render_read_state(char * dst)
|
||||||
|
{
|
||||||
|
render_line("read", &dst[0]);
|
||||||
|
render_u32(sh7091.DMAC.DMATCR1, &dst[8]);
|
||||||
|
render_u32(sh7091.DMAC.SAR1, &dst[16]);
|
||||||
|
render_u32(serial_load::state.read_crc.value, &dst[24]);
|
||||||
|
}
|
||||||
|
|
||||||
void render_fsm_state(char * dst)
|
void render_fsm_state(char * dst)
|
||||||
{
|
{
|
||||||
using namespace serial_load;
|
using namespace serial_load;
|
||||||
@ -309,8 +317,7 @@ void render_fsm_state(char * dst)
|
|||||||
render_write_state(dst);
|
render_write_state(dst);
|
||||||
break;
|
break;
|
||||||
case fsm_state::read:
|
case fsm_state::read:
|
||||||
render_line("read", &dst[0]);
|
render_read_state(dst);
|
||||||
render_clear(&dst[8], 24);
|
|
||||||
break;
|
break;
|
||||||
case fsm_state::jump:
|
case fsm_state::jump:
|
||||||
render_line("jump", &dst[0]);
|
render_line("jump", &dst[0]);
|
||||||
@ -355,7 +362,8 @@ void main() __attribute__((section(".text.main")));
|
|||||||
|
|
||||||
void main()
|
void main()
|
||||||
{
|
{
|
||||||
serial::init(0);
|
constexpr uint32_t serial_speed = 0;
|
||||||
|
serial_load::init(serial_speed);
|
||||||
|
|
||||||
struct maple_display_poll_state state = {0};
|
struct maple_display_poll_state state = {0};
|
||||||
const uint8_t * font = reinterpret_cast<const uint8_t *>(&_binary_font_portfolio_6x8);
|
const uint8_t * font = reinterpret_cast<const uint8_t *>(&_binary_font_portfolio_6x8);
|
||||||
@ -364,17 +372,11 @@ void main()
|
|||||||
auto renderer1 = maple::display::font_renderer(font);
|
auto renderer1 = maple::display::font_renderer(font);
|
||||||
framebuffer[1] = renderer1.fb;
|
framebuffer[1] = renderer1.fb;
|
||||||
|
|
||||||
state.want_start = 1;
|
|
||||||
serial_load::init();
|
|
||||||
|
|
||||||
// reset serial status
|
// reset serial status
|
||||||
sh7091.SCIF.SCFSR2 = 0;
|
sh7091.SCIF.SCFSR2 = 0;
|
||||||
// reset line status
|
// reset line status
|
||||||
sh7091.SCIF.SCLSR2 = 0;
|
sh7091.SCIF.SCLSR2 = 0;
|
||||||
|
|
||||||
uint32_t last_scfsr2 = -1;
|
|
||||||
uint32_t last_sclsr2 = -1;
|
|
||||||
|
|
||||||
serial::string("ready\n");
|
serial::string("ready\n");
|
||||||
|
|
||||||
error_counter.brk = 0;
|
error_counter.brk = 0;
|
||||||
@ -393,7 +395,7 @@ void main()
|
|||||||
error_counter.brk += 1;
|
error_counter.brk += 1;
|
||||||
error_counter.er += (scfsr2 & scfsr2::er::bit_mask) != 0;
|
error_counter.er += (scfsr2 & scfsr2::er::bit_mask) != 0;
|
||||||
sh7091.SCIF.SCFSR2 = scfsr2 & ~(scfsr2::brk::bit_mask | scfsr2::er::bit_mask);
|
sh7091.SCIF.SCFSR2 = scfsr2 & ~(scfsr2::brk::bit_mask | scfsr2::er::bit_mask);
|
||||||
serial_load::init();
|
serial_load::init(serial_load::state.speed);
|
||||||
serial::reset_txrx();
|
serial::reset_txrx();
|
||||||
} else if (scfsr2 & scfsr2::er::bit_mask) {
|
} else if (scfsr2 & scfsr2::er::bit_mask) {
|
||||||
// clear framing error
|
// clear framing error
|
||||||
@ -418,11 +420,7 @@ void main()
|
|||||||
serial_load::tick();
|
serial_load::tick();
|
||||||
render(renderer0, renderer1);
|
render(renderer0, renderer1);
|
||||||
|
|
||||||
//if (sclsr2 != last_sclsr2 || scfsr2 != last_scfsr2) {
|
state.want_start = 1;
|
||||||
state.want_start = 1;
|
|
||||||
//}
|
|
||||||
last_scfsr2 = scfsr2;
|
|
||||||
last_sclsr2 = sclsr2;
|
|
||||||
handle_maple(state);
|
handle_maple(state);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3,7 +3,7 @@ MEMORY
|
|||||||
{
|
{
|
||||||
p1ram : ORIGIN = 0xac005000, LENGTH = 0x0000
|
p1ram : ORIGIN = 0xac005000, LENGTH = 0x0000
|
||||||
p2ram : ORIGIN = 0xac010000, LENGTH = 0xff0000
|
p2ram : ORIGIN = 0xac010000, LENGTH = 0xff0000
|
||||||
ldram : ORIGIN = 0xacffe000, LENGTH = 0x2000
|
ldram : ORIGIN = 0xacffd000, LENGTH = 0x3000
|
||||||
}
|
}
|
||||||
SECTIONS
|
SECTIONS
|
||||||
{
|
{
|
||||||
|
2
main.lds
2
main.lds
@ -7,4 +7,4 @@ MEMORY
|
|||||||
|
|
||||||
INCLUDE "common.lds"
|
INCLUDE "common.lds"
|
||||||
|
|
||||||
__stack_end = ORIGIN(p1ram) + LENGTH(p1ram) - 0x2000;
|
__stack_end = ORIGIN(p1ram) + LENGTH(p1ram) - 0x3000;
|
||||||
|
@ -23,11 +23,13 @@ static void move(void *dst, const void *src, uint32_t n)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void init()
|
void init(uint32_t speed)
|
||||||
{
|
{
|
||||||
state.len = 0;
|
state.len = 0;
|
||||||
state.fsm_state = fsm_state::idle;
|
state.fsm_state = fsm_state::idle;
|
||||||
|
state.speed = speed & 0xff;
|
||||||
sh7091.DMAC.CHCR1 = 0;
|
sh7091.DMAC.CHCR1 = 0;
|
||||||
|
serial::init(state.speed);
|
||||||
}
|
}
|
||||||
|
|
||||||
void jump_to_func(const uint32_t addr)
|
void jump_to_func(const uint32_t addr)
|
||||||
@ -35,15 +37,16 @@ void jump_to_func(const uint32_t addr)
|
|||||||
serial::string("jump to: ");
|
serial::string("jump to: ");
|
||||||
serial::integer<uint32_t>(addr);
|
serial::integer<uint32_t>(addr);
|
||||||
// save our stack
|
// save our stack
|
||||||
asm volatile ("ldc r15, gbr; "
|
asm volatile ("mov.l r14,@-r15; "
|
||||||
"mov #0, r15; "
|
"ldc r15, gbr; "
|
||||||
"jsr @%0; "
|
"jsr @%0; "
|
||||||
"nop; "
|
"mov #0, r15; "
|
||||||
"stc gbr, r15; "
|
"stc gbr, r15; "
|
||||||
|
"mov.l @r15+,r14; "
|
||||||
:
|
:
|
||||||
: "r"(addr) /* input */
|
: "r"(addr) /* input */
|
||||||
/* clobbered register */
|
/* clobbered register */
|
||||||
: "r0","r1","r2","r3","r4","r5","r6","r7","r8","r9","r10","r11","r12","macl","mach","gbr","pr"
|
: "r0","r1","r2","r3","r4","r5","r6","r7","r8","r9","r10","r11","r12","r13","macl","mach","gbr","pr"
|
||||||
);
|
);
|
||||||
// restore our stack
|
// restore our stack
|
||||||
}
|
}
|
||||||
@ -57,6 +60,15 @@ static inline void prestart_write()
|
|||||||
state.write_crc.offset = dest;
|
state.write_crc.offset = dest;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline void prestart_read()
|
||||||
|
{
|
||||||
|
uint32_t src = state.buf.arg[0];
|
||||||
|
uint32_t size = state.buf.arg[1];
|
||||||
|
serial::send_dma(src, size);
|
||||||
|
state.read_crc.value = 0xffffffff;
|
||||||
|
state.read_crc.offset = src;
|
||||||
|
}
|
||||||
|
|
||||||
struct state_arglen_reply command_list[] = {
|
struct state_arglen_reply command_list[] = {
|
||||||
{command::write, reply::write, fsm_state::write},
|
{command::write, reply::write, fsm_state::write},
|
||||||
{command::read , reply::read , fsm_state::read },
|
{command::read , reply::read , fsm_state::read },
|
||||||
@ -82,6 +94,8 @@ void recv(uint8_t c)
|
|||||||
state.len = 0;
|
state.len = 0;
|
||||||
union command_reply reply = command_reply(sar.reply, state.buf.arg[0], state.buf.arg[1]);
|
union command_reply reply = command_reply(sar.reply, state.buf.arg[0], state.buf.arg[1]);
|
||||||
serial::string(reply.u8, 16);
|
serial::string(reply.u8, 16);
|
||||||
|
|
||||||
|
if (state.buf.cmd == command::read) prestart_read();
|
||||||
return;
|
return;
|
||||||
} else {
|
} else {
|
||||||
/*
|
/*
|
||||||
@ -115,8 +129,8 @@ void tick()
|
|||||||
uint32_t dar1 = sh7091.DMAC.DAR1;
|
uint32_t dar1 = sh7091.DMAC.DAR1;
|
||||||
if (dar1 > state.write_crc.offset) {
|
if (dar1 > state.write_crc.offset) {
|
||||||
uint32_t len = dar1 - state.write_crc.offset;
|
uint32_t len = dar1 - state.write_crc.offset;
|
||||||
const uint8_t * dest = reinterpret_cast<const uint8_t *>(state.write_crc.offset);
|
const uint8_t * buf = reinterpret_cast<const uint8_t *>(state.write_crc.offset);
|
||||||
state.write_crc.value = crc32_update(state.write_crc.value, dest, len);
|
state.write_crc.value = crc32_update(state.write_crc.value, buf, len);
|
||||||
state.write_crc.offset += len;
|
state.write_crc.offset += len;
|
||||||
}
|
}
|
||||||
if (chcr1 & dmac::chcr::te::transfers_completed) {
|
if (chcr1 & dmac::chcr::te::transfers_completed) {
|
||||||
@ -132,6 +146,27 @@ void tick()
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case fsm_state::read:
|
case fsm_state::read:
|
||||||
|
{
|
||||||
|
uint32_t chcr1 = sh7091.DMAC.CHCR1;
|
||||||
|
uint32_t sar1 = sh7091.DMAC.SAR1;
|
||||||
|
if (sar1 > state.read_crc.offset) {
|
||||||
|
uint32_t len = sar1 - state.read_crc.offset;
|
||||||
|
const uint8_t * buf = reinterpret_cast<const uint8_t *>(state.read_crc.offset);
|
||||||
|
state.read_crc.value = crc32_update(state.read_crc.value, buf, len);
|
||||||
|
state.read_crc.offset += len;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (chcr1 & dmac::chcr::te::transfers_completed) {
|
||||||
|
state.read_crc.value ^= 0xffffffff;
|
||||||
|
union command_reply reply = read_crc_reply(state.read_crc.value);
|
||||||
|
serial::string(reply.u8, 16);
|
||||||
|
|
||||||
|
sh7091.DMAC.CHCR1 = 0;
|
||||||
|
|
||||||
|
// transition to next state
|
||||||
|
//state.fsm_state = fsm_state::idle;
|
||||||
|
}
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case fsm_state::jump:
|
case fsm_state::jump:
|
||||||
{
|
{
|
||||||
@ -144,6 +179,11 @@ void tick()
|
|||||||
const uint32_t dest = state.buf.arg[0];
|
const uint32_t dest = state.buf.arg[0];
|
||||||
jump_to_func(dest);
|
jump_to_func(dest);
|
||||||
|
|
||||||
|
// cautiously re-initialize serial; it is possible the called
|
||||||
|
// function modified serial state
|
||||||
|
serial::init(state.speed);
|
||||||
|
sh7091.DMAC.CHCR1 = 0;
|
||||||
|
|
||||||
// transition to next state
|
// transition to next state
|
||||||
state.fsm_state = fsm_state::idle;
|
state.fsm_state = fsm_state::idle;
|
||||||
}
|
}
|
||||||
@ -151,7 +191,8 @@ void tick()
|
|||||||
case fsm_state::speed:
|
case fsm_state::speed:
|
||||||
{
|
{
|
||||||
const uint32_t speed = state.buf.arg[0];
|
const uint32_t speed = state.buf.arg[0];
|
||||||
serial::init(speed & 0xff);
|
state.speed = speed & 0xff;
|
||||||
|
serial::init(state.speed);
|
||||||
|
|
||||||
// transition to next state
|
// transition to next state
|
||||||
state.fsm_state = fsm_state::idle;
|
state.fsm_state = fsm_state::idle;
|
||||||
|
@ -6,7 +6,7 @@
|
|||||||
|
|
||||||
namespace serial_load {
|
namespace serial_load {
|
||||||
|
|
||||||
void init();
|
void init(uint32_t speed);
|
||||||
void recv(uint8_t c);
|
void recv(uint8_t c);
|
||||||
void tick();
|
void tick();
|
||||||
|
|
||||||
@ -35,6 +35,7 @@ struct state {
|
|||||||
enum fsm_state fsm_state;
|
enum fsm_state fsm_state;
|
||||||
struct incremental_crc write_crc;
|
struct incremental_crc write_crc;
|
||||||
struct incremental_crc read_crc;
|
struct incremental_crc read_crc;
|
||||||
|
uint32_t speed;
|
||||||
};
|
};
|
||||||
|
|
||||||
extern struct state state;
|
extern struct state state;
|
||||||
|
@ -39,12 +39,14 @@ namespace reply {
|
|||||||
constexpr uint32_t jump = gen_cmd("jump");
|
constexpr uint32_t jump = gen_cmd("jump");
|
||||||
constexpr uint32_t speed = gen_cmd("sped");
|
constexpr uint32_t speed = gen_cmd("sped");
|
||||||
constexpr uint32_t write_crc = gen_cmd("crcW");
|
constexpr uint32_t write_crc = gen_cmd("crcW");
|
||||||
|
constexpr uint32_t read_crc = gen_cmd("crcR");
|
||||||
|
|
||||||
static_assert(write == 0x8c661aaa);
|
static_assert(write == 0x8c661aaa);
|
||||||
static_assert(read == 0x512f23b5);
|
static_assert(read == 0x512f23b5);
|
||||||
static_assert(jump == 0x06cb1b4a);
|
static_assert(jump == 0x06cb1b4a);
|
||||||
static_assert(speed == 0x8705dd86);
|
static_assert(speed == 0x8705dd86);
|
||||||
static_assert(write_crc == 0x1cced074);
|
static_assert(write_crc == 0x1cced074);
|
||||||
|
static_assert(read_crc == 0xb9ce82f4);
|
||||||
}
|
}
|
||||||
|
|
||||||
union command_reply {
|
union command_reply {
|
||||||
@ -121,4 +123,9 @@ constexpr union command_reply write_crc_reply(uint32_t crc)
|
|||||||
return command_reply(reply::write_crc, crc, 0);
|
return command_reply(reply::write_crc, crc, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
constexpr union command_reply read_crc_reply(uint32_t crc)
|
||||||
|
{
|
||||||
|
return command_reply(reply::read_crc, crc, 0);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -19,7 +19,7 @@ static inline void init_wait()
|
|||||||
sh7091.TMU.TSTR |= tmu::tstr::str1::counter_start;
|
sh7091.TMU.TSTR |= tmu::tstr::str1::counter_start;
|
||||||
|
|
||||||
uint32_t start = sh7091.TMU.TCNT1;
|
uint32_t start = sh7091.TMU.TCNT1;
|
||||||
while ((start - sh7091.TMU.TCNT1) < 1);
|
while ((start - sh7091.TMU.TCNT1) < 20);
|
||||||
|
|
||||||
sh7091.TMU.TSTR &= (~tmu::tstr::str1::counter_start) & 0xff; // stop TCNT1
|
sh7091.TMU.TSTR &= (~tmu::tstr::str1::counter_start) & 0xff; // stop TCNT1
|
||||||
}
|
}
|
||||||
@ -48,11 +48,6 @@ void init(uint8_t bit_rate)
|
|||||||
sh7091.SCIF.SCFCR2 = scfcr2::tfrst::reset_operation_enabled
|
sh7091.SCIF.SCFCR2 = scfcr2::tfrst::reset_operation_enabled
|
||||||
| scfcr2::rfrst::reset_operation_enabled;
|
| scfcr2::rfrst::reset_operation_enabled;
|
||||||
|
|
||||||
sh7091.SCIF.SCFCR2 = scfcr2::rtrg::trigger_on_1_byte
|
|
||||||
| scfcr2::ttrg::trigger_on_8_bytes
|
|
||||||
//| scfcr2::mce::modem_signals_enabled
|
|
||||||
;
|
|
||||||
|
|
||||||
sh7091.SCIF.SCSMR2 = scsmr2::chr::_8_bit_data
|
sh7091.SCIF.SCSMR2 = scsmr2::chr::_8_bit_data
|
||||||
| scsmr2::pe::parity_disabled
|
| scsmr2::pe::parity_disabled
|
||||||
| scsmr2::stop::_1_stop_bit
|
| scsmr2::stop::_1_stop_bit
|
||||||
@ -72,6 +67,11 @@ void init(uint8_t bit_rate)
|
|||||||
// wait 1 bit interval
|
// wait 1 bit interval
|
||||||
init_wait();
|
init_wait();
|
||||||
|
|
||||||
|
sh7091.SCIF.SCFCR2 = scfcr2::rtrg::trigger_on_1_byte
|
||||||
|
| scfcr2::ttrg::trigger_on_8_bytes
|
||||||
|
//| scfcr2::mce::modem_signals_enabled
|
||||||
|
;
|
||||||
|
|
||||||
sh7091.SCIF.SCSCR2 = scscr2::te::transmission_enabled
|
sh7091.SCIF.SCSCR2 = scscr2::te::transmission_enabled
|
||||||
| scscr2::re::reception_enabled;
|
| scscr2::re::reception_enabled;
|
||||||
|
|
||||||
@ -84,7 +84,7 @@ void character(const char c)
|
|||||||
// wait for transmit fifo to become partially empty
|
// wait for transmit fifo to become partially empty
|
||||||
while ((sh7091.SCIF.SCFSR2 & scfsr2::tdfe::bit_mask) == 0);
|
while ((sh7091.SCIF.SCFSR2 & scfsr2::tdfe::bit_mask) == 0);
|
||||||
|
|
||||||
sh7091.SCIF.SCFSR2 = static_cast<uint16_t>(~scfsr2::tdfe::bit_mask);
|
sh7091.SCIF.SCFSR2 &= ~scfsr2::tdfe::bit_mask;
|
||||||
|
|
||||||
sh7091.SCIF.SCFTDR2 = static_cast<uint8_t>(c);
|
sh7091.SCIF.SCFTDR2 = static_cast<uint8_t>(c);
|
||||||
}
|
}
|
||||||
|
@ -78,7 +78,7 @@ static void recv_dma(uint32_t destination_address, uint32_t length)
|
|||||||
// DE channel enable
|
// DE channel enable
|
||||||
sh7091.DMAC.CHCR1 = chcr::dm::destination_address_incremented
|
sh7091.DMAC.CHCR1 = chcr::dm::destination_address_incremented
|
||||||
| chcr::sm::source_address_fixed
|
| chcr::sm::source_address_fixed
|
||||||
| chcr::rs::resource_select(0b1011) /* SCIF */
|
| chcr::rs::resource_select(0b1011) /* SCFRDR2 → external address space */
|
||||||
| chcr::tm::cycle_steal_mode /* transmit mode */
|
| chcr::tm::cycle_steal_mode /* transmit mode */
|
||||||
| chcr::ts::_8_bit /* transfer size */
|
| chcr::ts::_8_bit /* transfer size */
|
||||||
//| chcr::ie::interrupt_request_generated
|
//| chcr::ie::interrupt_request_generated
|
||||||
@ -89,4 +89,23 @@ static void recv_dma(uint32_t destination_address, uint32_t length)
|
|||||||
| dmaor::dme::operation_enabled_on_all_channels; /* DMAC master enable */
|
| dmaor::dme::operation_enabled_on_all_channels; /* DMAC master enable */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void send_dma(uint32_t source_address, uint32_t length)
|
||||||
|
{
|
||||||
|
using namespace dmac;
|
||||||
|
|
||||||
|
sh7091.DMAC.CHCR1 = 0;
|
||||||
|
|
||||||
|
sh7091.DMAC.SAR1 = source_address;
|
||||||
|
sh7091.DMAC.DAR1 = reinterpret_cast<uint32_t>(&sh7091.SCIF.SCFTDR2);
|
||||||
|
sh7091.DMAC.DMATCR1 = length & 0x00ff'ffff;
|
||||||
|
|
||||||
|
sh7091.DMAC.CHCR1 = chcr::dm::destination_address_fixed
|
||||||
|
| chcr::sm::source_address_incremented
|
||||||
|
| chcr::rs::resource_select(0b1010) /* external address space → SCFTDR2 */
|
||||||
|
| chcr::tm::cycle_steal_mode /* transmit mode */
|
||||||
|
| chcr::ts::_8_bit /* transfer size */
|
||||||
|
//| chcr::ie::interrupt_request_generated
|
||||||
|
| chcr::de::channel_operation_enabled;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -25,6 +25,7 @@ replies = [
|
|||||||
"jump",
|
"jump",
|
||||||
"sped",
|
"sped",
|
||||||
"crcW",
|
"crcW",
|
||||||
|
"crcR",
|
||||||
]
|
]
|
||||||
|
|
||||||
for c in commands:
|
for c in commands:
|
||||||
|
@ -176,7 +176,7 @@ double timespec_difference(struct timespec const * const a, struct timespec cons
|
|||||||
void dump_command_reply(union serial_load::command_reply& cr)
|
void dump_command_reply(union serial_load::command_reply& cr)
|
||||||
{
|
{
|
||||||
for (uint32_t i = 0; i < (sizeof (union serial_load::command_reply)) / (sizeof (uint32_t)); i++) {
|
for (uint32_t i = 0; i < (sizeof (union serial_load::command_reply)) / (sizeof (uint32_t)); i++) {
|
||||||
fprintf(stderr, " %08x\n", cr.u32[i]);
|
fprintf(stderr, " %08x\n", serial_load::le_bswap(cr.u32[i]));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -192,15 +192,23 @@ int read_reply(struct ftdi_context * ftdi, uint32_t expected_cmd, union serial_l
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (uint32_t i = 0; i < (sizeof (reply)) / (sizeof (uint32_t)); i++) {
|
|
||||||
reply.u32[i] = le_bswap(reply.u32[i]);
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32_t crc = crc32(&reply.u8[0], 12);
|
uint32_t crc = crc32(&reply.u8[0], 12);
|
||||||
if (crc != reply.crc) {
|
if (crc != reply.crc) {
|
||||||
fprintf(stderr, "crc mismatch; remote crc: %08x; local crc: %08x\n", reply.crc, crc);
|
fprintf(stderr, "reply crc mismatch; remote crc: %08x; local crc: %08x\n", reply.crc, crc);
|
||||||
dump_command_reply(reply);
|
dump_command_reply(reply);
|
||||||
return -1;
|
|
||||||
|
/*
|
||||||
|
uint8_t buf[16] = {0};
|
||||||
|
long length = read_with_timeout(ftdi, reply.u8, 16);
|
||||||
|
if (length > 0) {
|
||||||
|
fprintf(stderr, "trailing data:\n");
|
||||||
|
for (int i = 0; i < length; i++) {
|
||||||
|
fprintf(stderr, "%02x ", buf[i]);
|
||||||
|
}
|
||||||
|
fprintf(stderr, "\n");
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
return -2;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (reply.cmd != expected_cmd) {
|
if (reply.cmd != expected_cmd) {
|
||||||
@ -208,12 +216,14 @@ int read_reply(struct ftdi_context * ftdi, uint32_t expected_cmd, union serial_l
|
|||||||
dump_command_reply(reply);
|
dump_command_reply(reply);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
dump_command_reply(reply);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int do_write(struct ftdi_context * ftdi, const uint8_t * buf, const uint32_t size)
|
int do_write(struct ftdi_context * ftdi, const uint8_t * buf, const uint32_t size)
|
||||||
{
|
{
|
||||||
|
fprintf(stderr, "do_write\n");
|
||||||
int res;
|
int res;
|
||||||
|
|
||||||
const uint32_t dest = 0xac010000;
|
const uint32_t dest = 0xac010000;
|
||||||
@ -223,7 +233,7 @@ int do_write(struct ftdi_context * ftdi, const uint8_t * buf, const uint32_t siz
|
|||||||
union serial_load::command_reply reply;
|
union serial_load::command_reply reply;
|
||||||
res = read_reply(ftdi, serial_load::reply::write, reply);
|
res = read_reply(ftdi, serial_load::reply::write, reply);
|
||||||
if (res != 0) {
|
if (res != 0) {
|
||||||
return -1;
|
return -2;
|
||||||
}
|
}
|
||||||
fprintf(stderr, "remote: dest: %08x size: %08x\n", reply.arg[0], reply.arg[1]);
|
fprintf(stderr, "remote: dest: %08x size: %08x\n", reply.arg[0], reply.arg[1]);
|
||||||
if (reply.arg[0] != dest || reply.arg[1] != size) {
|
if (reply.arg[0] != dest || reply.arg[1] != size) {
|
||||||
@ -255,6 +265,7 @@ int do_write(struct ftdi_context * ftdi, const uint8_t * buf, const uint32_t siz
|
|||||||
|
|
||||||
int do_jump(struct ftdi_context * ftdi)
|
int do_jump(struct ftdi_context * ftdi)
|
||||||
{
|
{
|
||||||
|
fprintf(stderr, "do_jump\n");
|
||||||
int res;
|
int res;
|
||||||
|
|
||||||
const uint32_t dest = 0xac010000;
|
const uint32_t dest = 0xac010000;
|
||||||
@ -266,7 +277,7 @@ int do_jump(struct ftdi_context * ftdi)
|
|||||||
union serial_load::command_reply reply;
|
union serial_load::command_reply reply;
|
||||||
res = read_reply(ftdi, serial_load::reply::jump, reply);
|
res = read_reply(ftdi, serial_load::reply::jump, reply);
|
||||||
if (res != 0) {
|
if (res != 0) {
|
||||||
return -1;
|
return -2;
|
||||||
}
|
}
|
||||||
fprintf(stderr, "remote: jump: %08x\n", reply.arg[0]);
|
fprintf(stderr, "remote: jump: %08x\n", reply.arg[0]);
|
||||||
if (reply.arg[0] != dest || reply.arg[1] != 0) {
|
if (reply.arg[0] != dest || reply.arg[1] != 0) {
|
||||||
@ -276,47 +287,91 @@ int do_jump(struct ftdi_context * ftdi)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int main(int argc, char * argv[])
|
int read_file(const char * filename, uint8_t ** buf, uint32_t * size)
|
||||||
{
|
{
|
||||||
if (argc < 2) {
|
FILE * file = fopen(filename, "r");
|
||||||
fprintf(stderr, "argc\n");
|
|
||||||
return EXIT_FAILURE;
|
|
||||||
}
|
|
||||||
|
|
||||||
FILE * file = fopen(argv[1], "r");
|
|
||||||
if (file == NULL) {
|
if (file == NULL) {
|
||||||
fprintf(stderr, "fopen\n");
|
fprintf(stderr, "fopen\n");
|
||||||
return EXIT_FAILURE;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
int ret;
|
int ret;
|
||||||
ret = fseek(file, 0L, SEEK_END);
|
ret = fseek(file, 0L, SEEK_END);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
fprintf(stderr, "seek(SEEK_END)");
|
fprintf(stderr, "fseek(SEEK_END)");
|
||||||
return EXIT_FAILURE;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
long off = ftell(file);
|
long off = ftell(file);
|
||||||
|
|
||||||
ret = fseek(file, 0L, SEEK_SET);
|
ret = fseek(file, 0L, SEEK_SET);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
fprintf(stderr, "seek(SEEK_SET)");
|
fprintf(stderr, "fseek(SEEK_SET)");
|
||||||
return EXIT_FAILURE;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
fprintf(stderr, "%s off %ld\n", argv[1], off);
|
fprintf(stderr, "%s size %ld\n", filename, off);
|
||||||
//uint8_t buf[off];
|
*buf = (uint8_t *)malloc(off);
|
||||||
uint8_t * buf = (uint8_t *)malloc(off);
|
ssize_t fread_size = fread(*buf, 1, off, file);
|
||||||
ssize_t size = fread(buf, 1, off, file);
|
if (fread_size < 0) {
|
||||||
if (size < 0) {
|
fprintf(stderr, "fread");
|
||||||
fprintf(stderr, "read");
|
return -1;
|
||||||
return EXIT_FAILURE;
|
|
||||||
}
|
}
|
||||||
printf("%02x\n", buf[0]);
|
|
||||||
|
|
||||||
ret = fclose(file);
|
ret = fclose(file);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
fprintf(stderr, "close");
|
fprintf(stderr, "fclose");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
*size = off;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int do_read(struct ftdi_context * ftdi)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "do_read\n");
|
||||||
|
|
||||||
|
int res;
|
||||||
|
|
||||||
|
const uint32_t src = 0xac010000;
|
||||||
|
const uint32_t size = 51584;
|
||||||
|
union serial_load::command_reply command = serial_load::read_command(src, size);
|
||||||
|
res = ftdi_write_data(ftdi, command.u8, (sizeof (command)));
|
||||||
|
assert(res == (sizeof (command)));
|
||||||
|
union serial_load::command_reply reply;
|
||||||
|
res = read_reply(ftdi, serial_load::reply::read, reply);
|
||||||
|
if (res != 0) {
|
||||||
|
return -2;
|
||||||
|
}
|
||||||
|
fprintf(stderr, "remote: src: %08x size: %08x\n", reply.arg[0], reply.arg[1]);
|
||||||
|
if (reply.arg[0] != src || reply.arg[1] != size) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t * buf = (uint32_t *)malloc(size);
|
||||||
|
res = ftdi_read_data(ftdi, (uint8_t *)buf, size);
|
||||||
|
assert(res >= 0);
|
||||||
|
assert((uint32_t)res == size);
|
||||||
|
|
||||||
|
uint32_t buf_crc = crc32((uint8_t*)buf, size);
|
||||||
|
|
||||||
|
union serial_load::command_reply crc_reply;
|
||||||
|
res = read_reply(ftdi, serial_load::reply::read_crc, crc_reply);
|
||||||
|
if (res != 0) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
fprintf(stderr, "remote crc: %08x; local crc %08x\n", crc_reply.arg[0], buf_crc);
|
||||||
|
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int argc, char * argv[])
|
||||||
|
{
|
||||||
|
if (argc < 2) {
|
||||||
|
fprintf(stderr, "argc\n");
|
||||||
return EXIT_FAILURE;
|
return EXIT_FAILURE;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -336,15 +391,23 @@ int main(int argc, char * argv[])
|
|||||||
|
|
||||||
int return_code = EXIT_SUCCESS;
|
int return_code = EXIT_SUCCESS;
|
||||||
|
|
||||||
|
uint8_t * buf;
|
||||||
|
uint32_t size;
|
||||||
|
res = read_file(argv[1], &buf, &size);
|
||||||
|
if (res < 0) {
|
||||||
|
return EXIT_FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
struct timespec start;
|
struct timespec start;
|
||||||
struct timespec end;
|
struct timespec end;
|
||||||
res = clock_gettime(CLOCK_MONOTONIC, &start);
|
res = clock_gettime(CLOCK_MONOTONIC, &start);
|
||||||
assert(res >= 0);
|
assert(res >= 0);
|
||||||
int do_write_ret = do_write(ftdi, buf, off);
|
int do_write_ret = do_write(ftdi, buf, size);
|
||||||
res = clock_gettime(CLOCK_MONOTONIC, &end);
|
res = clock_gettime(CLOCK_MONOTONIC, &end);
|
||||||
assert(res >= 0);
|
assert(res >= 0);
|
||||||
fprintf(stderr, "do_write time: %.03f\n", timespec_difference(&end, &start));
|
fprintf(stderr, "do_write time: %.03f\n", timespec_difference(&end, &start));
|
||||||
if (do_write_ret == 0) {
|
if (do_write_ret == 0) {
|
||||||
|
//do_read(ftdi);
|
||||||
do_jump(ftdi);
|
do_jump(ftdi);
|
||||||
} else {
|
} else {
|
||||||
return_code = EXIT_FAILURE;
|
return_code = EXIT_FAILURE;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user