From 0641bdb4a55e89acb3dcfb7785df57304d82f155 Mon Sep 17 00:00:00 2001 From: Waldemar Brodkorb Date: Sat, 16 Jun 2018 19:03:23 +0200 Subject: add etrax-tools --- package/etrax-tools/src/e100boot/cbl/src/common.c | 486 ++++++++++++++++++++++ 1 file changed, 486 insertions(+) create mode 100644 package/etrax-tools/src/e100boot/cbl/src/common.c (limited to 'package/etrax-tools/src/e100boot/cbl/src/common.c') diff --git a/package/etrax-tools/src/e100boot/cbl/src/common.c b/package/etrax-tools/src/e100boot/cbl/src/common.c new file mode 100644 index 000000000..e4ebdc40d --- /dev/null +++ b/package/etrax-tools/src/e100boot/cbl/src/common.c @@ -0,0 +1,486 @@ +#include "hwregs.h" +#include "e100boot.h" + +static void toggle_led(void); + +static void read_load_info(void); +static void decode_load_info(void); + +static void read_file(byte* addr, udword size); + +#if USE_PRINT_DESCR +static void print_descr(dma_descr_T *d); +#endif + +static int memory_test(udword addr, udword size, udword *failed_address); +static void memory_dump(udword *from, udword *to); + +extern byte _Stext[]; +extern byte _Edata[]; + +#ifdef USE_BAUDRATE_CHANGING +byte change_baudrate; +udword new_baudrate; +#endif + +void +level2_boot(void) +{ +#if USE_LEDS + REG_SET(R_PORT_PA_DATA, data_out, 0xaa); +#endif + +#if 0 + io_buf_next = (byte*)IO_BUF_START; + io_buf_cur = (byte*)IO_BUF_START; +#endif + +#if 1 + send_string("\r\n\r\nDevice ID = "); + send_hex(ntohl(tx_header.id), NL); + send_string(e100boot_version); +#endif + +#if 1 + { + udword sum = 0; + byte *b; + + for (b = (byte*)_Stext; b != (byte*)_Edata; b++) { + sum += *b; + } + send_string("Checksum of bootloader is "); + send_hex(sum, NL); + } +#endif + + read_load_info(); + + __asm__ volatile ("jump _start"); +} + +void +toggle_led(void) +{ +#if USE_LEDS + REG_SET(R_PORT_PA_DATA, data_out, 0x55); + + while (1) { + REG_SET(R_PORT_PA_DATA, data_out, ~REG_GET(R_PORT_PA_READ, data_in)); + { + volatile udword i; + + for (i = 0; i != 2000000; i++) + ; + } + } +#else + while (1) { + } +#endif +} + +void +read_load_info(void) +{ +#ifdef USE_BAUDRATE_CHANGING + change_baudrate = 0; +#endif + + send_string("Waiting for load info.\r\n"); + + send_ack(); + + read_file((byte*)IO_BUF_START, IO_BUF_END - IO_BUF_START - CRC_LEN); + send_string("Got load info.\r\n"); + decode_load_info(); + +#ifdef USE_BAUDRATE_CHANGING + if (change_baudrate) { + REG_WR(R_SERIAL0_BAUD, new_baudrate); + { + udword i = 0; + + while (i++ < 1000000) + ; + } + send_ack(); + } +#endif + + toggle_led(); +} + +void +decode_load_info(void) +{ + udword *type_p = (udword*)IO_BUF_START; + udword failed_address; + udword i; + command_T *cmd; + + while (type_p != (udword*)(IO_BUF_END - CRC_LEN)) { /* !!! */ +// send_hex(type_p, NL); + *type_p = ntohl(*type_p); +// send_hex(*type_p, NL); + type_p++; + } + +// memory_dump(IO_BUF_START, IO_BUF_END); + + cmd = (command_T*)IO_BUF_START; + while (cmd->type) { + switch (cmd->type) { + case PACKET_INFO: + send_string("PACKET_INFO\r\n"); + send_hex(cmd->args.packet_info.addr, NL); + send_hex(cmd->args.packet_info.size, NL); + + seq--; + send_ack(); + seq++; + + read_file((byte*)cmd->args.packet_info.addr, cmd->args.packet_info.size); + + (byte*)cmd += sizeof cmd->type + sizeof cmd->args.packet_info; + break; + + case SET_REGISTER: + send_string("SET_REGISTER\r\n"); + send_hex(cmd->args.set_register.addr, NL); + send_hex(cmd->args.set_register.val, NL); + + *(udword*)cmd->args.set_register.addr = cmd->args.set_register.val; + + (byte*)cmd += sizeof cmd->type + sizeof cmd->args.set_register; + break; + + case GET_REGISTER: + send_string("GET_REGISTER\r\n"); + send_hex(cmd->args.get_register.addr, NL); + send_hex(*(udword*)cmd->args.get_register.addr, NL); + + (byte*)cmd += sizeof cmd->type + sizeof cmd->args.get_register; + break; + + case PAUSE_LOOP: + send_string("PAUSE_LOOP\r\n"); + send_hex(cmd->args.pause_loop.pause, NL); + + for (i = cmd->args.pause_loop.pause; i; i--) + ; + + (byte*)cmd += sizeof cmd->type + sizeof cmd->args.pause_loop; + break; + + case MEM_VERIFY: + send_string("MEM_VERIFY\r\n"); + send_hex(cmd->args.mem_verify.addr, NL); + send_hex(cmd->args.mem_verify.val, NL); + + if (*(udword*)cmd->args.mem_verify.addr != cmd->args.mem_verify.val) { + send_string("verify failed\r\n"); + goto decode_failed; + } + + (byte*)cmd += sizeof cmd->type + sizeof cmd->args.mem_verify; + break; + + case MEM_TEST: + send_string("MEM_TEST\r\n"); + send_hex(cmd->args.mem_test.from, NL); + send_hex(cmd->args.mem_test.to, NL); + + if (!memory_test(cmd->args.mem_test.from, + cmd->args.mem_test.to, + &failed_address)) { + send_string("### Memory test failed at "); + send_hex(failed_address, NL); + memory_dump((udword*)DWORD_ALIGN(failed_address - 64), + (udword*)DWORD_ALIGN(failed_address + 64)); + goto decode_failed; + } + send_string("Passed memory test.\r\n"); + + (byte*)cmd += sizeof cmd->type + sizeof cmd->args.mem_test; + break; + + case MEM_DUMP: + send_string("MEM_DUMP\r\n"); + send_hex(cmd->args.mem_dump.from_addr, NL); + send_hex(cmd->args.mem_dump.to_addr, NL); + + memory_dump((udword*)cmd->args.mem_dump.from_addr, + (udword*)cmd->args.mem_dump.to_addr); + + (byte*)cmd += sizeof cmd->type + sizeof cmd->args.mem_dump; + break; + + case MEM_CLEAR: + send_string("MEM_CLEAR\r\n"); + send_hex(cmd->args.mem_clear.from_addr, NL); + send_hex(cmd->args.mem_clear.to_addr, NL); + + for (i = cmd->args.mem_clear.from_addr; + i <= cmd->args.mem_clear.to_addr; + i++) { + *(byte*)i = 0x00; + } + + (byte*)cmd += sizeof cmd->type + sizeof cmd->args.mem_clear; + break; + + case FLASH: + send_string("FLASH\r\n"); + send_hex((udword)cmd->args.flash.source, NL); + send_hex(cmd->args.flash.offset, NL); + send_hex(cmd->args.flash.size, NL); + + if ((i = flash_write(cmd->args.flash.source, + cmd->args.flash.offset, + cmd->args.flash.size)) != ERR_FLASH_OK) { + if (i == ERR_FLASH_VERIFY) { + udword size = + (cmd->args.flash.size < 65536 ? cmd->args.flash.size : 65536); + + /* Try to erase the first block(s) we tried to flash to prevent a + unit which failed to flash correctly from booting */ + flash_write(NULL, cmd->args.flash.offset, size); + } + + goto decode_failed; + } + + (byte*)cmd += sizeof cmd->type + sizeof cmd->args.flash; + break; + + case JUMP: +#if 1 + /* for the printf function in our libc */ + REG_WR(R_DMA_CH8_FIRST, *(udword*)&tx_header.dest[0]); + REG_WR(R_DMA_CH9_FIRST, *(uword*)&tx_header.dest[4]); +// REG_WR(R_NETWORK_SA_1, &tx_header.dest[4]); +// REG_WR(R_NETWORK_SA_2, tx_header.id); +#endif + send_string("JUMP\r\n"); + send_hex(cmd->args.jump.addr, NL); + send_string("END\r\n"); + + __asm__ volatile ("jump %0" :: "r" (cmd->args.jump.addr)); + + (byte*)cmd += sizeof cmd->type + sizeof cmd->args.jump; + break; + + case LOOP: + send_string("LOOP\r\n"); + send_hex(cmd->args.bne.addr, NL); + send_hex(cmd->args.bne.target, NL); + + if (*(udword*)cmd->args.bne.addr) { + (*(udword*)cmd->args.bne.addr)--; + (byte*)cmd = cmd->args.bne.target; + } + else { + (byte*)cmd += sizeof cmd->type + sizeof cmd->args.bne; + } + break; + +#ifdef USE_BAUDRATE_CHANGING + case BAUDRATE: + send_string("BAUDRATE\r\n"); + send_hex(cmd->args.br.baudrate, NL); + + new_baudrate = cmd->args.br.baudrate; + + (byte*)cmd += sizeof cmd->type + sizeof cmd->args.br; + break; +#endif + + default: + send_string("### Unknown type: "); + send_hex(cmd->type, NL); + + goto decode_failed; + break; + } + } + +decode_failed: + send_string("END\r\n"); +} + +void +read_file(byte* addr, udword size) +{ + udword nbr_read_last; + udword sum; + byte *b; + byte *from; + +/* send_string(">read_file\r\n"); */ + + nbr_read = 0; + nbr_read_last = 0; + target_address = (udword)addr; + + if (interface == NETWORK) { + rx_descr2.buf = (udword)addr; + bytes_to_read = size; + rx_descr2.sw_len = size + CRC_LEN > 1500 ? 1500 : size + CRC_LEN; +/* rx_descr2.sw_len = 1500; */ + + REG_SET(R_DMA_CH1_FIRST, first, (udword)&rx_descr); + + /* Restart receiver so descriptor is re-read. */ + REG_SET(R_DMA_CH1_CMD, cmd, reset); + while (REG_EQL(R_DMA_CH1_CMD, cmd, reset)) { + } + + REG_SET(R_DMA_CH1_CMD, cmd, start); + + while (1) { +/* send_hex(rx_descr2.hw_len, NL); */ + from = (byte*)rx_descr2.buf; + if (read_data()) { + if (nbr_read < size) { + REG_SET(R_DMA_CH1_CMD, cmd, start); + } + +#if USE_PRINT_DESCR + print_descr(&rx_descr); + print_descr(&rx_descr2); +#endif + +#if 0 + send_string("Read "); + send_hex(rx_descr2.hw_len - CRC_LEN, NO_NL); + send_string(" bytes. "); + send_hex((udword)from, NO_NL); + send_string(" - "); + send_hex(rx_descr2.buf-1, NO_NL); + send_string(" ("); + send_hex(nbr_read, NO_NL); + send_string("/"); + send_hex(size, NO_NL); + send_string(")\r\n"); +#endif + + nbr_read_last = nbr_read; +/* from = (byte*)rx_descr2.buf; */ + + if (nbr_read >= size) { + break; + } + } + } + } + else { /* interface != NETWORK */ + while (nbr_read < size) { + read_data(); + } + } + + sum = 0; + for (b = addr; b != (byte*)(addr+size); b++) { + sum += *b; + } + send_string("Checksum of file is "); + send_hex(sum, NL); + +/* memory_dump((udword*)addr, (udword*)addr+size); */ +/* send_string("ctrl, NL); + + send_string("sw_len : "); + send_hex(d->sw_len, NL); + + send_string("next : "); + send_hex(d->next, NL); + + send_string("buf : "); + send_hex(d->buf, NL); + + send_string("status : "); + send_hex(d->status, NL); + + send_string("hw_len : "); + send_hex(d->hw_len, NL); +} +#endif + +int +memory_test(udword from, udword to, udword *failed_address) +{ + udword i; + udword j; + byte b; + + /* At each dword (but bytewise) write the inverse of the adress, + check that it worked, then write the inverse of the last byte + written. Exit on fail. The memory after a successfull test will + be: + + 0xC0000000 : 0xC0000000 0xC0000004 0xC0000008 0xC000000C + 0xC0000010 : 0xC0000010 0xC0000014 0xC0000018 0xC000001C + */ + + for (i = from; i < to; i += 4) { + for (j = 0; (j != sizeof(udword)) && (i+j < to); j++) { + b = ((~i) >> (j*8)) & 0xff; + *(volatile byte*)(i+j) = b; + if (*(volatile byte*)(i+j) == b) { + *(volatile byte*)(i+j) = ~b; + } + else { + *failed_address = i+j; + send_string("### Memory test 1 failed at "); + send_hex(*failed_address, NL); + return FALSE; + } + } + } + + /* Run through entire region, check bytewise that the dwords contain + the address to the dword. Exit on fail. */ + + for (i = from; i < to; i += 4) { + for (j = 0; (j != sizeof(udword)) && (i+j < to); j++) { + b = (i >> (j*8)) & 0xff; + if (*(volatile byte*)(i+j) != b) { + *failed_address = i+j; + send_string("### Memory test 2 failed at "); + send_hex(*failed_address, NL); + return FALSE; + } + } + } + + return TRUE; +} + +void +memory_dump(udword *from, udword *to) +{ + udword *i = from; + int j; + + for (; i <= to; i += 4) { + send_hex((udword)i, NO_NL); + send_string(" :"); + for(j = 0; j != 4 && (i+j <= to); j++) { + send_string(" "); + send_hex(*(udword*)(i+j), NO_NL); + } + send_string("\r\n"); + } +} -- cgit v1.2.3