/************************************************************************************************** * @fn sblPoll * * @brief Boot Loader main executive processing. * * input parameters * * None. * * output parameters * * None. * * @return TRUE if sbCmnd() returns TRUE, indicating that an SB_ENABLE_CMD succeeded; * FALSE otherwise. ************************************************************************************************** */ uint8 sblPoll(void) { /* Parse the incoming packet’s header, and verify its FCS. Valid packets are transferred to * sbCmnd() for further processing. For detailed packet format, please see the document "Serial * Boot Loader for CC2538". */ static uint8 sbFrameId, sbCmd, sbFcs, sbSte = SB_SOF_STATE; static uint32 sbLen; static uint32 sbIdx; uint8 ch, rtrn = FALSE; while(sbRx(&ch, 1)) { switch (sbSte) { case SB_SOF_STATE: if (SB_SOF == ch) { sbSte = SB_LEN_STATE; sbIdx = 0; } break; /* this field is kept for backward compatibility of the protocol. */ case SB_LEN_STATE: /* In case the length is larger than 254, this fields is set to 0xFF, * and there is an additional 32bit length, located in another location * in this header. */ sbLen = ch; sbFcs = 0; sbSte = SB_FRAME_ID_STATE; break; case SB_FRAME_ID_STATE: sbFrameId = ch; sbSte = SB_CMD_STATE; break; case SB_CMD_STATE: sbCmd = ch; switch (sbLen) { case 0: sbSte = SB_FCS_STATE; break; case 0xFF: sbSte = SB_LEN1_STATE; break; default: sbSte = SB_DATA_STATE; break; } break; case SB_LEN1_STATE: sbLen = ch; sbSte = SB_LEN2_STATE; break; case SB_LEN2_STATE: sbLen += ch << 8; sbSte = SB_LEN3_STATE; break; case SB_LEN3_STATE: sbLen += ch << 16; sbSte = SB_LEN4_STATE; break; case SB_LEN4_STATE: sbLen += ch << 24; sbSte = (sbLen) ? SB_DATA_STATE : SB_FCS_STATE; break; case SB_DATA_STATE: if (sbIdx >= sizeof(_sbBuf)) { /* discard this packet. the payload is too long. */ sbSte = SB_SOF_STATE; } else { sbBuf[sbIdx] = ch; sbIdx++; if (sbIdx == sbLen) { sbSte = SB_FCS_STATE; } } break; case SB_FCS_STATE: if ((sbFcs == ch) && (sbFrameId == SB_RPC_SYS_BOOT)) { rtrn = sbCmnd(sbCmd, sbLen); } sbSte = SB_SOF_STATE; break; default: break; } sbFcs ^= ch; } return rtrn; }
/************************************************************************************************** * @fn sblWait * * @brief A timed-out wait loop that exits early upon receiving a force code/sbl byte. * * input parameters * * None. * * output parameters * * None. * * @return TRUE to run the code image, FALSE to run the SBL. ************************************************************************************************** */ static uint8 sblWait(uint16 sbl_wait_time) { uint32 dlyCnt; uint8 rtrn = FALSE; uint8 sbExec_rc; uint8 ch; if (znpCfg1 == ZNP_CFG1_SPI) { // Slave signals ready for read by setting its ready flag first. SRDY_SET(); // Flag to sbRx() to poll for 1 Rx byte instead of blocking read until MRDY_CLR. spiPoll = TRUE; dlyCnt = 0x38; // About 50 msecs. } else { URX0IE = 1; HAL_ENABLE_INTERRUPTS(); dlyCnt = (uint32)0x7332 * sbl_wait_time; //0x7332 gives about 1 second sbReportState(SB_STATE_WAITING); } while (1) { if (znpCfg1 == ZNP_CFG1_UART) { sbUartPoll(); sbExec_rc = sbExec(); if (sbExec_rc == SB_CMND_ENABLE_STATE_REPORTING) { sbReportState(SB_STATE_WAITING); } else if (sbExec_rc == SB_CMND_FORCE_RUN) { dlyCnt = 0; } else if ((sbExec_rc != SB_CMND_IDLE) && (sbExec_rc != SB_CMND_UNSUPPORTED)) { break; } } else // Note: the SPI implementation was left unchanged, since the new implementation // (as implemented for the UART) was not tested with SPI at this time. { if (sbRx(&ch, 1)) { if (ch == SB_FORCE_BOOT) { break; } else if (ch == SB_FORCE_RUN) { dlyCnt = 0; } } } if (dlyCnt-- == 0) { rtrn = TRUE; break; } } if (znpCfg1 == ZNP_CFG1_SPI) { // Master blocks waiting for slave to clear its ready flag before continuing. SRDY_CLR(); // Flag to sbRx() to now block while reading Rx bytes until MRDY_CLR. spiPoll = FALSE; } else { HAL_DISABLE_INTERRUPTS(); URX0IE = 0; } return rtrn; }