serial_transfer: add read command

This commit is contained in:
Zack Buhman 2024-10-26 08:03:50 -05:00
parent ff7a03a75c
commit 45c6bcf211
13 changed files with 200 additions and 72 deletions

View File

@ -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

View File

@ -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--;
} }

View File

@ -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;
} }
} }

View File

@ -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);
} }
} }

View File

@ -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
{ {

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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);
}
} }

View File

@ -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);
} }

View File

@ -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;
}
} }

View File

@ -25,6 +25,7 @@ replies = [
"jump", "jump",
"sped", "sped",
"crcW", "crcW",
"crcR",
] ]
for c in commands: for c in commands:

View File

@ -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;