diff --git a/esp-link/cgioptiboot.c b/esp-link/cgioptiboot.c index d9e20f1..6594973 100644 --- a/esp-link/cgioptiboot.c +++ b/esp-link/cgioptiboot.c @@ -10,11 +10,11 @@ #include "serbridge.h" #include "serled.h" -#define SYNC_TIMEOUT 4800 // to achieve sync, in milliseconds -#define SYNC_INTERVAL 77 // interval at which we try to sync +#define INIT_DELAY 150 // wait this many millisecs before sending anything #define BAUD_INTERVAL 600 // interval after which we change baud rate -#define PGM_TIMEOUT 20000 // timeout when sync is achieved, in milliseconds +#define PGM_TIMEOUT 20000 // timeout after sync is achieved, in milliseconds #define PGM_INTERVAL 200 // send sync at this interval in ms when in programming mode +#define ATTEMPTS 8 // number of attempts total to make #ifdef OPTIBOOT_DBG #define DBG(format, ...) do { os_printf(format, ## __VA_ARGS__); } while(0) @@ -29,15 +29,14 @@ static ETSTimer optibootTimer; static enum { // overall programming states - stateSync = 0, // trying to get initial response - stateSync2, // trying to get in sync - stateSync3, // trying to get second sync + stateInit = 0, // initial delay + stateSync, // waiting to hear back stateGetSig, // reading device signature stateGetVersLo, // reading optiboot version, low bits stateGetVersHi, // reading optiboot version, high bits stateProg, // programming... } progState; -static short syncCnt; // counter & timeout for sync attempts +static char* progStates[] = { "init", "sync", "sig", "ver0", "ver1", "prog" }; static short baudCnt; // counter for sync attempts at different baud rates static short ackWait; // counter of expected ACKs static uint16_t optibootVers; @@ -70,12 +69,11 @@ static void optibootTimerCB(void *); static void optibootUartRecv(char *buffer, short length); static bool processRecord(char *buf, short len); static bool programPage(void); -static void armTimer(void); +static void armTimer(uint32_t ms); static void initBaud(void); static void ICACHE_FLASH_ATTR optibootInit() { - progState = stateSync; - syncCnt = 0; + progState = stateInit; baudCnt = 0; uart0_baud(flashConfig.baud_rate); ackWait = 0; @@ -142,7 +140,7 @@ int ICACHE_FLASH_ATTR cgiOptibootSync(HttpdConnData *connData) { // start sync timer os_timer_disarm(&optibootTimer); os_timer_setfn(&optibootTimer, optibootTimerCB, NULL); - os_timer_arm(&optibootTimer, 50, 0); // fire in 50ms and don't recur + os_timer_arm(&optibootTimer, INIT_DELAY, 0); // respond with optimistic OK noCacheHeaders(connData, 204); @@ -155,7 +153,7 @@ int ICACHE_FLASH_ATTR cgiOptibootSync(HttpdConnData *connData) { if (!errMessage[0] && progState >= stateProg) { char buf[64]; DBG("OB got sync\n"); - os_sprintf(buf, "SYNC at %ld baud: Optiboot %d.%d", + os_sprintf(buf, "SYNC at %ld baud: bootloader v%d.%d", baudRate, optibootVers>>8, optibootVers&0xff); httpdSend(connData, buf, -1); } else if (errMessage[0] && progState == stateSync) { @@ -202,7 +200,8 @@ static uint32_t ICACHE_FLASH_ATTR getHexValue(char *buf, short len) { //===== Cgi to write firmware to Optiboot, requires prior sync call int ICACHE_FLASH_ATTR cgiOptibootData(HttpdConnData *connData) { if (connData->conn==NULL) return HTTPD_CGI_DONE; // Connection aborted. Clean up. - DBG("OB pgm: state=%d PrivData=%p postLen=%d\n", progState, connData->cgiPrivData, connData->post->len); + if (!optibootData) + DBG("OB pgm: state=%d postLen=%d\n", progState, connData->post->len); // check that we have sync if (errMessage[0] || progState < stateProg) { @@ -427,7 +426,7 @@ static bool pollAck() { // Program a flash page static bool ICACHE_FLASH_ATTR programPage(void) { if (optibootData->pageLen == 0) return true; - armTimer(); // keep the timerCB out of the picture + armTimer(PGM_TIMEOUT); // keep the timerCB out of the picture if (ackWait > 7) { os_sprintf(errMessage, "Lost sync while programming\n"); @@ -436,7 +435,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%lx ackWait=%d\n", pgmLen, optibootData->address, ackWait); + DBG("OB pgm %d@0x%lx\n", pgmLen, optibootData->address); // send address to optiboot (little endian format) #ifdef DBG_GPIO5 @@ -448,12 +447,12 @@ static bool ICACHE_FLASH_ATTR programPage(void) { uart0_write_char(addr & 0xff); uart0_write_char(addr >> 8); uart0_write_char(CRC_EOP); - armTimer(); + armTimer(PGM_TIMEOUT); if (!pollAck()) { DBG("OB pgm failed in load address\n"); return false; } - armTimer(); + armTimer(PGM_TIMEOUT); // send page length (big-endian format, go figure...) #ifdef DBG_GPIO5 @@ -470,9 +469,9 @@ static bool ICACHE_FLASH_ATTR programPage(void) { uart0_write_char(optibootData->pageBuf[i]); uart0_write_char(CRC_EOP); - armTimer(); + armTimer(PGM_TIMEOUT); bool ok = pollAck(); - armTimer(); + armTimer(PGM_TIMEOUT); if (!ok) { DBG("OB pgm failed in prog page\n"); return false; @@ -490,18 +489,17 @@ static bool ICACHE_FLASH_ATTR programPage(void) { //===== Rebooting and getting sync -static void ICACHE_FLASH_ATTR armTimer() { +static void ICACHE_FLASH_ATTR armTimer(uint32_t ms) { os_timer_disarm(&optibootTimer); - // time-out every 50ms, except when programming to allow for 9600baud (133ms for 128 bytes) - os_timer_arm(&optibootTimer, progState==stateProg ? PGM_INTERVAL : SYNC_INTERVAL, 0); + os_timer_arm(&optibootTimer, ms, 0); } static int baudRates[] = { 0, 9600, 57600, 115200 }; static void ICACHE_FLASH_ATTR setBaud() { - baudRate = baudRates[(syncCnt / (BAUD_INTERVAL/SYNC_INTERVAL)) % 4]; + baudRate = baudRates[(baudCnt++) % 4]; uart0_baud(baudRate); - //DBG("OB changing to %d baud\n", b); + //DBG("OB changing to %ld baud\n", baudRate); } static void ICACHE_FLASH_ATTR initBaud() { @@ -511,45 +509,41 @@ static void ICACHE_FLASH_ATTR initBaud() { static void ICACHE_FLASH_ATTR optibootTimerCB(void *arg) { // see whether we've issued so many sync in a row that it's time to give up - syncCnt++; switch (progState) { - case stateSync: // we're trying to get sync, all we do here is send a sync request - if (syncCnt >= SYNC_TIMEOUT/SYNC_INTERVAL) { + case stateInit: // initial delay expired, send sync chars + uart0_write_char(STK_GET_SYNC); + uart0_write_char(CRC_EOP); + progState++; + armTimer(BAUD_INTERVAL-INIT_DELAY); + return; + case stateSync: // oops, must have not heard back!? + if (baudCnt > ATTEMPTS) { // we're doomed, give up - DBG("OB sync abandoned after timeout, state=%d syncCnt=%d\n", progState, syncCnt); + DBG("OB abandoned after %d attempts\n", baudCnt); optibootInit(); - strcpy(errMessage, "sync abandoned after timeout"); + strcpy(errMessage, "sync abandoned after 8 attempts"); return; } - if (syncCnt % (BAUD_INTERVAL/SYNC_INTERVAL) == 0) { - // time to switch baud rate and issue a reset - setBaud(); - serbridgeReset(); - // no point sending chars if we just switched - } else { - //uart0_write_char(STK_GET_SYNC); - uart0_write_char(CRC_EOP); - uart0_write_char(CRC_EOP); - } - break; - case stateSync2: // need one more CRC_EOP? - uart0_write_char(CRC_EOP); - progState++; - break; + // time to switch baud rate and issue a reset + DBG("OB no sync response @%ld baud\n", baudRate); + setBaud(); + serbridgeReset(); + progState = stateInit; + armTimer(INIT_DELAY); + return; case stateProg: // we're programming and we timed-out of inaction uart0_write_char(STK_GET_SYNC); uart0_write_char(CRC_EOP); ackWait++; // we now expect an ACK - break; + armTimer(PGM_INTERVAL); + return; default: // we're trying to get some info from optiboot and it should have responded! optibootInit(); // abort - os_sprintf(errMessage, "No response in state %d\n", progState); + os_sprintf(errMessage, "No response in state %s(%d) @%ld baud\n", + progStates[progState], progState, baudRate); DBG("OB %s\n", errMessage); return; // do not re-arm timer } - - // we need to come back... - armTimer(); } // skip in-sync responses @@ -575,8 +569,9 @@ static void ICACHE_FLASH_ATTR optibootUartRecv(char *buf, short length) { // dispatch based the current state switch (progState) { - case stateSync: // we're trying to get a sync response - case stateSync3: // we're trying to get a second sync response + case stateInit: // we haven't sent anything, this must be garbage + break; + case stateSync: // we're trying to get a sync response // look for STK_INSYNC+STK_OK at end of buffer if (responseLen > 0 && responseBuf[responseLen-1] == STK_INSYNC) { // missing STK_OK after STK_INSYNC, shift stuff out and try again @@ -584,19 +579,14 @@ static void ICACHE_FLASH_ATTR optibootUartRecv(char *buf, short length) { responseLen = 1; } else if (responseLen > 1 && responseBuf[responseLen-2] == STK_INSYNC && responseBuf[responseLen-1] == STK_OK) { - // got sync response, send more... + // got sync response os_memcpy(responseBuf, responseBuf+2, responseLen-2); responseLen -= 2; - if (progState==stateSync) { - // need to deal with odd-even sync issue, send one more to see whether we get a response - uart0_write_char(CRC_EOP); - } else { - // got clean sync, send request to get signature - uart0_write_char(STK_READ_SIGN); - uart0_write_char(CRC_EOP); - } + // send request to get signature + uart0_write_char(STK_READ_SIGN); + uart0_write_char(CRC_EOP); progState++; - armTimer(); // reset timer + armTimer(PGM_INTERVAL); // reset timer } else { // nothing useful, keep at most half the buffer for error message purposes if (responseLen > RESP_SZ/2) { @@ -606,18 +596,6 @@ static void ICACHE_FLASH_ATTR optibootUartRecv(char *buf, short length) { } } break; - case stateSync2: // we're trying to actually get in sync - if (responseLen > 1 && responseBuf[responseLen-2] == STK_INSYNC && - responseBuf[responseLen-1] == STK_OK) { - // got sync response, send signature request - os_memcpy(responseBuf, responseBuf+2, responseLen-2); - responseLen -= 2; - uart0_write_char(STK_READ_SIGN); - uart0_write_char(CRC_EOP); - progState = stateGetSig; - } - armTimer(); // reset timer - break; case stateGetSig: // expecting signature responseLen = skipInSync(responseBuf, responseLen); if (responseLen >= 5 && responseBuf[0] == STK_INSYNC && responseBuf[4] == STK_OK) { @@ -627,7 +605,7 @@ static void ICACHE_FLASH_ATTR optibootUartRecv(char *buf, short length) { uart0_write_char(STK_GET_PARAMETER); uart0_write_char(0x82); uart0_write_char(CRC_EOP); - armTimer(); // reset timer + armTimer(PGM_INTERVAL); // reset timer } else { optibootInit(); // abort os_sprintf(errMessage, "Bad programmer signature: 0x%02x 0x%02x 0x%02x\n", @@ -646,7 +624,7 @@ static void ICACHE_FLASH_ATTR optibootUartRecv(char *buf, short length) { uart0_write_char(STK_GET_PARAMETER); uart0_write_char(0x81); uart0_write_char(CRC_EOP); - armTimer(); // reset timer + armTimer(PGM_INTERVAL); // reset timer } break; case stateGetVersHi: // expecting version @@ -655,7 +633,7 @@ static void ICACHE_FLASH_ATTR optibootUartRecv(char *buf, short length) { progState++; os_memcpy(responseBuf, responseBuf+3, responseLen-3); responseLen -= 3; - armTimer(); // reset timer + armTimer(PGM_INTERVAL); // reset timer ackWait = 0; } break; @@ -666,7 +644,7 @@ static void ICACHE_FLASH_ATTR optibootUartRecv(char *buf, short length) { os_memmove(responseBuf, responseBuf+2, responseLen-2); responseLen -= 2; } - armTimer(); // reset timer + armTimer(PGM_INTERVAL); // reset timer default: break; } diff --git a/serial/serbridge.c b/serial/serbridge.c index 696d635..1e82e3d 100644 --- a/serial/serbridge.c +++ b/serial/serbridge.c @@ -445,11 +445,11 @@ serbridgeInitPins() #endif if (flashConfig.swap_uart) { - PIN_FUNC_SELECT(PERIPHS_IO_MUX_MTCK_U, 4); - PIN_FUNC_SELECT(PERIPHS_IO_MUX_MTDO_U, 4); - PIN_PULLUP_DIS(PERIPHS_IO_MUX_MTCK_U); - if (flashConfig.rx_pullup) PIN_PULLUP_EN(PERIPHS_IO_MUX_MTDO_U); - else PIN_PULLUP_DIS(PERIPHS_IO_MUX_MTDO_U); + PIN_FUNC_SELECT(PERIPHS_IO_MUX_MTCK_U, 4); // RX + PIN_FUNC_SELECT(PERIPHS_IO_MUX_MTDO_U, 4); // TX + PIN_PULLUP_DIS(PERIPHS_IO_MUX_MTDO_U); + if (flashConfig.rx_pullup) PIN_PULLUP_EN(PERIPHS_IO_MUX_MTCK_U); + else PIN_PULLUP_DIS(PERIPHS_IO_MUX_MTCK_U); system_uart_swap(); } else { PIN_FUNC_SELECT(PERIPHS_IO_MUX_U0TXD_U, 0);