From 7dd77c6ad48c181ece6ce2c5d74b10b477ed7b03 Mon Sep 17 00:00:00 2001 From: dannybackx Date: Sat, 11 Feb 2017 16:12:29 +0100 Subject: [PATCH] This is not correct yet but it successfully flashes the big test HEX file supplied by uzi18 --- esp-link/cgimega.c | 60 +++++++++++++++++++++++++++++++++++----------- 1 file changed, 46 insertions(+), 14 deletions(-) diff --git a/esp-link/cgimega.c b/esp-link/cgimega.c index 1f12543..c0d99a3 100644 --- a/esp-link/cgimega.c +++ b/esp-link/cgimega.c @@ -9,6 +9,24 @@ * * Documentation about the protocol used : see http://www.atmel.com/Images/doc2591.pdf * + * Note the Intel HEX format is read by this code. + * Format description is e.g. in http://www.keil.com/support/docs/1584/ + * Summary : each line (HEX file record) is formatted as ":llaaaatt[dd...]cc" + * : is the colon that starts every Intel HEX record. + * ll is the record-length field that represents the number of data bytes (dd) in the record. + * aaaa is the address field that represents the starting address for subsequent data. + * tt is the field that represents the HEX record type, which may be one of the following: + * 00 - data record + * 01 - end-of-file record + * 02 - extended segment address record + * 04 - extended linear address record + * 05 - start linear address record (MDK-ARM only) + * dd is a data field that represents one byte of data. A record may have multiple data bytes. + * The number of data bytes in the record must match the number specified by the ll field. + * cc is the checksum field that represents the checksum of the record. The checksum is + * calculated by summing the values of all hexadecimal digit pairs in the record modulo + * 256 and taking the two's complement. + * */ #include @@ -77,6 +95,7 @@ static struct optibootData { uint16_t pgmSz; // size of flash page to be programmed at a time uint16_t pgmDone; // number of bytes programmed uint32_t address; // address to write next page to + uint32_t segment; // for extended segment addressing, added to the address field uint32_t startTime; // time of program POST request HttpdConnData *conn; // request doing the programming, so we can cancel it bool eof; // got EOF record @@ -660,7 +679,10 @@ int ICACHE_FLASH_ATTR cgiMegaData(HttpdConnData *connData) { optibootData->pgmSz = 128; // hard coded for 328p for now, should be query string param #endif DBG("OB data alloc\n"); - optibootData->address = 0x80000000; // HACK FIX ME + +// optibootData->address = 0x80000000; // HACK FIX ME + // optibootData->segment = 0x0; // Not necessary, os_zalloc() does this + optibootData->address = optibootData->segment; } // iterate through the data received and program the AVR one block at a time @@ -790,7 +812,7 @@ static bool ICACHE_FLASH_ATTR processRecord(char *buf, short len) { // dispatch based on record type uint8_t type = getHexValue(buf+6, 2); switch (type) { - case 0x00: { // data + case 0x00: { // Intel HEX data record //DBG("OB REC data %ld pglen=%d\n", getHexValue(buf, 2), optibootData->pageLen); uint32_t addr = getHexValue(buf+2, 4); // check whether we need to program previous record(s) @@ -812,16 +834,16 @@ static bool ICACHE_FLASH_ATTR processRecord(char *buf, short len) { // program page, if we have a full page if (optibootData->pageLen >= optibootData->pgmSz) { //DBG("OB full\n"); - os_printf("processRecord %d, call programPage() %08x\n", optibootData->pgmSz, optibootData->address); + // os_printf("processRecord %d, call programPage() %08x\n", optibootData->pgmSz, optibootData->address + optibootData->segment); if (!programPage()) return false; } break; } - case 0x01: // EOF + case 0x01: // Intel HEX EOF record DBG("OB EOF\n"); // program any remaining partial page #if 1 if (optibootData->pageLen > 0) { - os_printf("processRecord remaining partial page, len %d, addr 0x%04x\n", optibootData->pageLen, optibootData->address); + // os_printf("processRecord remaining partial page, len %d, addr 0x%04x\n", optibootData->pageLen, optibootData->address + optibootData->segment); if (!programPage()) return false; } optibootData->eof = true; @@ -836,21 +858,31 @@ static bool ICACHE_FLASH_ATTR processRecord(char *buf, short len) { optibootData->eof = true; #endif break; - case 0x04: // address + case 0x04: // Intel HEX address record DBG("OB address 0x%x\n", getHexValue(buf+8, 4) << 16); // program any remaining partial page if (optibootData->pageLen > 0) { - os_printf("processRecord 0x04 remaining partial page, len %d, addr 0x%04x\n", optibootData->pageLen, optibootData->address); + os_printf("processRecord 0x04 remaining partial page, len %d, addr 0x%04x\n", + optibootData->pageLen, optibootData->address + optibootData->segment); if (!programPage()) return false; } optibootData->address = getHexValue(buf+8, 4) << 16; break; - case 0x05: // start address + case 0x05: // Intel HEX start address (MDK-ARM only) // ignore, there's no way to tell optiboot that... break; + case 0x02: // Intel HEX extended segment address record + // Depending on the case, just ignoring this record could solve the problem + // optibootData->segment = getHexValue(buf+8, 4) << 4; + DBG("OB segment 0x%08X\n", optibootData->segment); + return true; default: DBG("OB bad record type\n"); +#if 0 os_sprintf(errMessage, "Invalid/unknown record type: 0x%02x", type); +#else + os_sprintf(errMessage, "Invalid/unknown record type: 0x%02x, packet %s", type, buf); +#endif return false; } return true; @@ -859,7 +891,7 @@ static bool ICACHE_FLASH_ATTR processRecord(char *buf, short len) { // Program a flash page static bool ICACHE_FLASH_ATTR programPage(void) { if (debug()) - os_printf("programPage len %d addr 0x%04x\n", optibootData->pageLen, optibootData->address); + os_printf("programPage len %d addr 0x%04x\n", optibootData->pageLen, optibootData->address + optibootData->segment); if (optibootData->pageLen == 0) return true; @@ -868,7 +900,7 @@ static bool ICACHE_FLASH_ATTR programPage(void) { uint16_t pgmLen = optibootData->pageLen; if (pgmLen > optibootData->pgmSz) pgmLen = optibootData->pgmSz; - // DBG("OB pgm %d@0x%x\n", pgmLen, optibootData->address); + // DBG("OB pgm %d@0x%x\n", pgmLen, optibootData->address + optibootData->segment); // send address to optiboot (little endian format) #ifdef DBG_GPIO5 @@ -876,7 +908,7 @@ static bool ICACHE_FLASH_ATTR programPage(void) { #endif ackWait++; - uint32_t addr = optibootData->address; + uint32_t addr = optibootData->address + optibootData->segment; sendLoadAddressQuery(addr); readLoadAddressReply(); @@ -902,12 +934,12 @@ static bool ICACHE_FLASH_ATTR programPage(void) { // shift data out of buffer os_memmove(optibootData->pageBuf, optibootData->pageBuf+pgmLen, optibootData->pageLen-pgmLen); optibootData->pageLen -= pgmLen; -#if 0 +#if 1 optibootData->address += pgmLen; #else - os_printf("Address old %08x ", optibootData->address); + os_printf("Address old %08x ", optibootData->address + optibootData->segment); optibootData->address += pgmLen; - os_printf(" new %08x\n", optibootData->address); + os_printf(" new %08x\n", optibootData->address + optibootData->segment); #endif optibootData->pgmDone += pgmLen;