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=unused-but-set-variable
|
||||
CFLAGS += -Wno-error=unused-variable
|
||||
CFLAGS += -Wno-error=unused-function
|
||||
|
||||
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
|
||||
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) {
|
||||
crc = crc32_table[*data ^ ((crc >> 24) & 0xff)] ^ (crc << 8);
|
||||
data++;
|
||||
crc = crc32_table[*buf ^ ((crc >> 24) & 0xff)] ^ (crc << 8);
|
||||
buf++;
|
||||
len--;
|
||||
}
|
||||
|
||||
|
@ -181,8 +181,5 @@ void main()
|
||||
theta += half_degree;
|
||||
frame_ix = (frame_ix + 1) & 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) {
|
||||
state.port[port].ap__lm = 0;
|
||||
} 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;
|
||||
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]);
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
using namespace serial_load;
|
||||
@ -309,8 +317,7 @@ void render_fsm_state(char * dst)
|
||||
render_write_state(dst);
|
||||
break;
|
||||
case fsm_state::read:
|
||||
render_line("read", &dst[0]);
|
||||
render_clear(&dst[8], 24);
|
||||
render_read_state(dst);
|
||||
break;
|
||||
case fsm_state::jump:
|
||||
render_line("jump", &dst[0]);
|
||||
@ -355,7 +362,8 @@ void main() __attribute__((section(".text.main")));
|
||||
|
||||
void main()
|
||||
{
|
||||
serial::init(0);
|
||||
constexpr uint32_t serial_speed = 0;
|
||||
serial_load::init(serial_speed);
|
||||
|
||||
struct maple_display_poll_state state = {0};
|
||||
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);
|
||||
framebuffer[1] = renderer1.fb;
|
||||
|
||||
state.want_start = 1;
|
||||
serial_load::init();
|
||||
|
||||
// reset serial status
|
||||
sh7091.SCIF.SCFSR2 = 0;
|
||||
// reset line status
|
||||
sh7091.SCIF.SCLSR2 = 0;
|
||||
|
||||
uint32_t last_scfsr2 = -1;
|
||||
uint32_t last_sclsr2 = -1;
|
||||
|
||||
serial::string("ready\n");
|
||||
|
||||
error_counter.brk = 0;
|
||||
@ -393,7 +395,7 @@ void main()
|
||||
error_counter.brk += 1;
|
||||
error_counter.er += (scfsr2 & scfsr2::er::bit_mask) != 0;
|
||||
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();
|
||||
} else if (scfsr2 & scfsr2::er::bit_mask) {
|
||||
// clear framing error
|
||||
@ -418,11 +420,7 @@ void main()
|
||||
serial_load::tick();
|
||||
render(renderer0, renderer1);
|
||||
|
||||
//if (sclsr2 != last_sclsr2 || scfsr2 != last_scfsr2) {
|
||||
state.want_start = 1;
|
||||
//}
|
||||
last_scfsr2 = scfsr2;
|
||||
last_sclsr2 = sclsr2;
|
||||
handle_maple(state);
|
||||
}
|
||||
}
|
||||
|
@ -3,7 +3,7 @@ MEMORY
|
||||
{
|
||||
p1ram : ORIGIN = 0xac005000, LENGTH = 0x0000
|
||||
p2ram : ORIGIN = 0xac010000, LENGTH = 0xff0000
|
||||
ldram : ORIGIN = 0xacffe000, LENGTH = 0x2000
|
||||
ldram : ORIGIN = 0xacffd000, LENGTH = 0x3000
|
||||
}
|
||||
SECTIONS
|
||||
{
|
||||
|
2
main.lds
2
main.lds
@ -7,4 +7,4 @@ MEMORY
|
||||
|
||||
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.fsm_state = fsm_state::idle;
|
||||
state.speed = speed & 0xff;
|
||||
sh7091.DMAC.CHCR1 = 0;
|
||||
serial::init(state.speed);
|
||||
}
|
||||
|
||||
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::integer<uint32_t>(addr);
|
||||
// save our stack
|
||||
asm volatile ("ldc r15, gbr; "
|
||||
"mov #0, r15; "
|
||||
asm volatile ("mov.l r14,@-r15; "
|
||||
"ldc r15, gbr; "
|
||||
"jsr @%0; "
|
||||
"nop; "
|
||||
"mov #0, r15; "
|
||||
"stc gbr, r15; "
|
||||
"mov.l @r15+,r14; "
|
||||
:
|
||||
: "r"(addr) /* input */
|
||||
/* 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
|
||||
}
|
||||
@ -57,6 +60,15 @@ static inline void prestart_write()
|
||||
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[] = {
|
||||
{command::write, reply::write, fsm_state::write},
|
||||
{command::read , reply::read , fsm_state::read },
|
||||
@ -82,6 +94,8 @@ void recv(uint8_t c)
|
||||
state.len = 0;
|
||||
union command_reply reply = command_reply(sar.reply, state.buf.arg[0], state.buf.arg[1]);
|
||||
serial::string(reply.u8, 16);
|
||||
|
||||
if (state.buf.cmd == command::read) prestart_read();
|
||||
return;
|
||||
} else {
|
||||
/*
|
||||
@ -115,8 +129,8 @@ void tick()
|
||||
uint32_t dar1 = sh7091.DMAC.DAR1;
|
||||
if (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);
|
||||
state.write_crc.value = crc32_update(state.write_crc.value, dest, len);
|
||||
const uint8_t * buf = reinterpret_cast<const uint8_t *>(state.write_crc.offset);
|
||||
state.write_crc.value = crc32_update(state.write_crc.value, buf, len);
|
||||
state.write_crc.offset += len;
|
||||
}
|
||||
if (chcr1 & dmac::chcr::te::transfers_completed) {
|
||||
@ -132,6 +146,27 @@ void tick()
|
||||
}
|
||||
break;
|
||||
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;
|
||||
case fsm_state::jump:
|
||||
{
|
||||
@ -144,6 +179,11 @@ void tick()
|
||||
const uint32_t dest = state.buf.arg[0];
|
||||
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
|
||||
state.fsm_state = fsm_state::idle;
|
||||
}
|
||||
@ -151,7 +191,8 @@ void tick()
|
||||
case fsm_state::speed:
|
||||
{
|
||||
const uint32_t speed = state.buf.arg[0];
|
||||
serial::init(speed & 0xff);
|
||||
state.speed = speed & 0xff;
|
||||
serial::init(state.speed);
|
||||
|
||||
// transition to next state
|
||||
state.fsm_state = fsm_state::idle;
|
||||
|
@ -6,7 +6,7 @@
|
||||
|
||||
namespace serial_load {
|
||||
|
||||
void init();
|
||||
void init(uint32_t speed);
|
||||
void recv(uint8_t c);
|
||||
void tick();
|
||||
|
||||
@ -35,6 +35,7 @@ struct state {
|
||||
enum fsm_state fsm_state;
|
||||
struct incremental_crc write_crc;
|
||||
struct incremental_crc read_crc;
|
||||
uint32_t speed;
|
||||
};
|
||||
|
||||
extern struct state state;
|
||||
|
@ -39,12 +39,14 @@ namespace reply {
|
||||
constexpr uint32_t jump = gen_cmd("jump");
|
||||
constexpr uint32_t speed = gen_cmd("sped");
|
||||
constexpr uint32_t write_crc = gen_cmd("crcW");
|
||||
constexpr uint32_t read_crc = gen_cmd("crcR");
|
||||
|
||||
static_assert(write == 0x8c661aaa);
|
||||
static_assert(read == 0x512f23b5);
|
||||
static_assert(jump == 0x06cb1b4a);
|
||||
static_assert(speed == 0x8705dd86);
|
||||
static_assert(write_crc == 0x1cced074);
|
||||
static_assert(read_crc == 0xb9ce82f4);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
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
|
||||
}
|
||||
@ -48,11 +48,6 @@ void init(uint8_t bit_rate)
|
||||
sh7091.SCIF.SCFCR2 = scfcr2::tfrst::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
|
||||
| scsmr2::pe::parity_disabled
|
||||
| scsmr2::stop::_1_stop_bit
|
||||
@ -72,6 +67,11 @@ void init(uint8_t bit_rate)
|
||||
// wait 1 bit interval
|
||||
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
|
||||
| scscr2::re::reception_enabled;
|
||||
|
||||
@ -84,7 +84,7 @@ void character(const char c)
|
||||
// wait for transmit fifo to become partially empty
|
||||
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);
|
||||
}
|
||||
|
@ -78,7 +78,7 @@ static void recv_dma(uint32_t destination_address, uint32_t length)
|
||||
// DE channel enable
|
||||
sh7091.DMAC.CHCR1 = chcr::dm::destination_address_incremented
|
||||
| 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::ts::_8_bit /* transfer size */
|
||||
//| 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 */
|
||||
}
|
||||
|
||||
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",
|
||||
"sped",
|
||||
"crcW",
|
||||
"crcR",
|
||||
]
|
||||
|
||||
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)
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
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);
|
||||
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);
|
||||
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) {
|
||||
@ -208,12 +216,14 @@ int read_reply(struct ftdi_context * ftdi, uint32_t expected_cmd, union serial_l
|
||||
dump_command_reply(reply);
|
||||
return -1;
|
||||
}
|
||||
dump_command_reply(reply);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int do_write(struct ftdi_context * ftdi, const uint8_t * buf, const uint32_t size)
|
||||
{
|
||||
fprintf(stderr, "do_write\n");
|
||||
int res;
|
||||
|
||||
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;
|
||||
res = read_reply(ftdi, serial_load::reply::write, reply);
|
||||
if (res != 0) {
|
||||
return -1;
|
||||
return -2;
|
||||
}
|
||||
fprintf(stderr, "remote: dest: %08x size: %08x\n", reply.arg[0], reply.arg[1]);
|
||||
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)
|
||||
{
|
||||
fprintf(stderr, "do_jump\n");
|
||||
int res;
|
||||
|
||||
const uint32_t dest = 0xac010000;
|
||||
@ -266,7 +277,7 @@ int do_jump(struct ftdi_context * ftdi)
|
||||
union serial_load::command_reply reply;
|
||||
res = read_reply(ftdi, serial_load::reply::jump, reply);
|
||||
if (res != 0) {
|
||||
return -1;
|
||||
return -2;
|
||||
}
|
||||
fprintf(stderr, "remote: jump: %08x\n", reply.arg[0]);
|
||||
if (reply.arg[0] != dest || reply.arg[1] != 0) {
|
||||
@ -276,47 +287,91 @@ int do_jump(struct ftdi_context * ftdi)
|
||||
return 0;
|
||||
}
|
||||
|
||||
int main(int argc, char * argv[])
|
||||
int read_file(const char * filename, uint8_t ** buf, uint32_t * size)
|
||||
{
|
||||
if (argc < 2) {
|
||||
fprintf(stderr, "argc\n");
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
FILE * file = fopen(argv[1], "r");
|
||||
FILE * file = fopen(filename, "r");
|
||||
if (file == NULL) {
|
||||
fprintf(stderr, "fopen\n");
|
||||
return EXIT_FAILURE;
|
||||
return -1;
|
||||
}
|
||||
|
||||
int ret;
|
||||
ret = fseek(file, 0L, SEEK_END);
|
||||
if (ret < 0) {
|
||||
fprintf(stderr, "seek(SEEK_END)");
|
||||
return EXIT_FAILURE;
|
||||
fprintf(stderr, "fseek(SEEK_END)");
|
||||
return -1;
|
||||
}
|
||||
|
||||
long off = ftell(file);
|
||||
|
||||
ret = fseek(file, 0L, SEEK_SET);
|
||||
if (ret < 0) {
|
||||
fprintf(stderr, "seek(SEEK_SET)");
|
||||
return EXIT_FAILURE;
|
||||
fprintf(stderr, "fseek(SEEK_SET)");
|
||||
return -1;
|
||||
}
|
||||
|
||||
fprintf(stderr, "%s off %ld\n", argv[1], off);
|
||||
//uint8_t buf[off];
|
||||
uint8_t * buf = (uint8_t *)malloc(off);
|
||||
ssize_t size = fread(buf, 1, off, file);
|
||||
if (size < 0) {
|
||||
fprintf(stderr, "read");
|
||||
return EXIT_FAILURE;
|
||||
fprintf(stderr, "%s size %ld\n", filename, off);
|
||||
*buf = (uint8_t *)malloc(off);
|
||||
ssize_t fread_size = fread(*buf, 1, off, file);
|
||||
if (fread_size < 0) {
|
||||
fprintf(stderr, "fread");
|
||||
return -1;
|
||||
}
|
||||
printf("%02x\n", buf[0]);
|
||||
|
||||
ret = fclose(file);
|
||||
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;
|
||||
}
|
||||
|
||||
@ -336,15 +391,23 @@ int main(int argc, char * argv[])
|
||||
|
||||
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 end;
|
||||
res = clock_gettime(CLOCK_MONOTONIC, &start);
|
||||
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);
|
||||
assert(res >= 0);
|
||||
fprintf(stderr, "do_write time: %.03f\n", timespec_difference(&end, &start));
|
||||
if (do_write_ret == 0) {
|
||||
//do_read(ftdi);
|
||||
do_jump(ftdi);
|
||||
} else {
|
||||
return_code = EXIT_FAILURE;
|
||||
|
Loading…
x
Reference in New Issue
Block a user