/************************************************************************************************** * @fn sblExec * * @brief Infinite SBL execute loop that returns upon receiving a code enable. * * input parameters * * None. * * output parameters * * None. * * @return None. ************************************************************************************************** */ static void sblExec(void) { uint32 dlyCnt = 0; vddWait(VDD_MIN_NV); HAL_ENABLE_INTERRUPTS(); while (1) { if (dlyCnt++ & 0x4000) { SB_TOGGLE_LED1(); } HalUARTPollUSB(); if (sbExec()) { break; } } SB_TURN_ON_LED1(); SB_TURN_ON_LED2(); // Delay to allow the SB_ENABLE_CMD response to be flushed. for (dlyCnt = 0; dlyCnt < 0x40000; dlyCnt++) { HalUARTPollUSB(); } }
/****************************************************************************** * @fn bootMain * * @brief ISR for the reset vector. * * @param None. * * @return None. */ void bootMain(void) { extern void _ivecRst2(void); // hal_ivec.s43 defines this reset re-direct operation. HAL_BOOT_INIT(); vddWait(VDD_MIN_RUN); while (1) { uint16 crc[2]; crc[0] = *((uint16*)LO_ROM_BEG); crc[1] = *((uint16*)LO_ROM_BEG+1); if (crc[0] == crc[1]) { break; } else if ((crc[0] != 0) && (crc[0] == crcCalc())) { FCTL3 = FWKEY; // Clear Lock bit. FCTL1 = FWKEY + WRT; // Set WRT bit for write operation *((uint16*)LO_ROM_BEG+1) = crc[0]; // Write CRC shadow FCTL1 = FWKEY; // Clear WRT bit FCTL3 = FWKEY + LOCK; // Set LOCK bit } else { dl2rc(); } } _ivecRst2(); }
/************************************************************************************************** * @fn sblInit * * @brief Initialization for SBL. * * input parameters * * None. * * output parameters * * None. * * @return None. ************************************************************************************************** */ static void sblInit(void) { HAL_BOARD_INIT(); vddWait(VDD_MIN_RUN); magicByte = SB_MAGIC_VALUE; /* This is in place of calling HalDmaInit() which would require init of the other 4 DMA * descriptors in addition to just Channel 0. */ HAL_DMA_SET_ADDR_DESC0(&dmaCh0); HalUARTInitUSB(); }
/************************************************************************************************** * @fn sblExec * * @brief Infinite SBL execute loop that returns upon receiving a code enable. * * input parameters * * None. * * output parameters * * None. * * @return None. ************************************************************************************************** */ static void sblExec(void) { uint32 dlyCnt = 0; uint8 sbExec_rc; if (znpCfg1 == ZNP_CFG1_UART) { URX0IE = 1; HAL_ENABLE_INTERRUPTS(); sbReportState(SB_STATE_BOOTLOADER_ACTIVE); } else { /* For preventing an unknown delay after sending SB_FORCE_BOOT and before being able to send SB_HANDSHAKE_CMD, this call was moved to the processing of SB_HANDSHAKE_CMD, which has an associated response (SB_FORCE_BOOT does not have any response). This change was required for the bootloader to work on the Alektrona gateway reference board. It was verified only with UART, so at the moment the behavior for SPI is left unchanged. */ vddWait(VDD_MIN_NV); } while (1) { if (znpCfg1 == ZNP_CFG1_UART) { sbUartPoll(); } sbExec_rc = sbExec(); if (sbExec_rc == SB_CMND_ENABLE_STATE_REPORTING) { sbReportState(SB_STATE_BOOTLOADER_ACTIVE); } else if (sbExec_rc == SB_CMND_ENABLED_CMD_OK) { // Delay to allow the SB_ENABLE_CMD response to be flushed. if (znpCfg1 == ZNP_CFG1_UART) { for (dlyCnt = 0; dlyCnt < 0x40000; dlyCnt++) { sbUartPoll(); } URX0IE = 0; } break; } } }
/************************************************************************************************** * @fn sblInit * * @brief Initialization for SBL. * * input parameters * * None. * * output parameters * * None. * * @return None. ************************************************************************************************** */ static void sblInit(void) { HAL_BOARD_INIT(); vddWait(VDD_MIN_RUN); magicByte = SB_MAGIC_VALUE; /* This is in place of calling HalDmaInit() which would require init of the other 4 DMA * descriptors in addition to just Channel 0. */ HAL_DMA_SET_ADDR_DESC0(&dmaCh0); #if defined CC2530_MK znpCfg1 = ZNP_CFG1_SPI; #else znpCfg1 = P2_0; #endif if (znpCfg1 == ZNP_CFG1_SPI) { SRDY_CLR(); // Select general purpose on I/O pins. P0SEL &= ~(NP_RDYIn_BIT); // P0.3 MRDY - GPIO P0SEL &= ~(NP_RDYOut_BIT); // P0.4 SRDY - GPIO // Select GPIO direction. P0DIR &= ~NP_RDYIn_BIT; // P0.3 MRDY - IN P0DIR |= NP_RDYOut_BIT; // P0.4 SRDY - OUT P0INP &= ~NP_RDYIn_BIT; // Pullup/down enable of MRDY input. P2INP &= ~BV(5); // Pullup all P0 inputs. HalUARTInitSPI(); } else { halUARTCfg_t uartConfig; HalUARTInitISR(); uartConfig.configured = TRUE; uartConfig.baudRate = HAL_UART_BR_115200; uartConfig.flowControl = FALSE; uartConfig.flowControlThreshold = 0; // CC2530 by #define - see hal_board_cfg.h uartConfig.rx.maxBufSize = 0; // CC2530 by #define - see hal_board_cfg.h uartConfig.tx.maxBufSize = 0; // CC2530 by #define - see hal_board_cfg.h uartConfig.idleTimeout = 0; // CC2530 by #define - see hal_board_cfg.h uartConfig.intEnable = TRUE; uartConfig.callBackFunc = NULL; HalUARTOpenISR(&uartConfig); } }
/************************************************************************************************** * @fn main * * @brief C-code main functionality. * * input parameters * * None. * * output parameters * * None. * * @return None. ************************************************************************************************** */ void main(void) { vddWait(VDD_MIN_RUN); HAL_BOARD_INIT(); // make sure the DMA channel is selected before we attempt to // to write anything to flash. sblInit(); if (sbImgValid()) { if ((SB_UART_DELAY == 0) || ResetWasWatchDog) { sblJump(); } sblWait(); } vddWait(VDD_MIN_NV); sblExec(); HAL_SYSTEM_RESET(); }
/************************************************************************************************** * @fn main * * @brief C-code main functionality. * * input parameters * * None. * * output parameters * * None. * * @return None. ************************************************************************************************** */ void main(void) { vddWait(VDD_MIN_RUN); HAL_BOARD_INIT(); if (sbImgValid()) { if ((SB_UART_DELAY == 0) || ResetWasWatchDog) { sblJump(); } sblInit(); sblWait(); } else { sblInit(); } vddWait(VDD_MIN_NV); sblExec(); HAL_SYSTEM_RESET(); }
/****************************************************************************** * @fn dl2rc * * @brief Copy the DL image to the RC image location. * * NOTE: Assumes that DL image at least fills lower flash. * Assumes that DL image ends on a flash page boundary. * * @param None. * * @return None. */ static void dl2rc(void) { uint32 addr = DATA_OFFSET; uint32 addr2 = HI_ROM_BEG; uint16 *ptr; preamble_t preamble; uint16 buf; uint8 cnt = 0; vddWait(VDD_MIN_OTA); HalOTARead(DATA_OFFSET+PREAMBLE_OFFSET, (uint8 *)&preamble, sizeof(preamble_t), HAL_OTA_DL); FCTL3 = FWKEY; // Clear Lock bit. for (ptr = (uint16 *)LO_ROM_BEG; ptr <= (uint16 *)LO_ROM_END ; ) { FCTL1 = FWKEY + ERASE; // Set Erase bit. *ptr = 0; // Dummy write to erase Flash segment. FCTL1 = FWKEY + WRT; // Set WRT bit for write operation do { HalXNVRead(addr, (uint8 *)&buf, 2); *ptr++ = buf; addr += 2; } while (--cnt); // Wrap a uint8 once to count 256 * 2 = 512. } for (; addr < preamble.programLength+DATA_OFFSET; ) { FCTL1 = FWKEY + ERASE; // Set Erase bit. __data20_write_char(addr2,0); // Dummy write to erase Flash segment. FCTL1 = FWKEY + WRT; // Set WRT bit for write operation do { HalXNVRead(addr, (uint8 *)&buf, 2); __data20_write_short(addr2, buf); addr2 += 2; addr += 2; } while (--cnt); // Wrap a uint8 once to count 256 * 2 = 512. } FCTL1 = FWKEY; // Clear WRT bit FCTL3 = FWKEY + LOCK; // Set LOCK bit }
/************************************************************************************************** * @fn main * * @brief C-code main function. * * input parameters * * None. * * output parameters * * None. * * @return None. ************************************************************************************************** */ void main(void) { vddWait(); HAL_BOARD_INIT(); /* This is in place of calling HalDmaInit() which would require init of the other 4 DMA * descriptors in addition to just Channel 0. */ HAL_DMA_SET_ADDR_DESC0(&dmaCh0); // Map flash bank #7 into XDATA for access to "ROM mapped as data". MEMCTR = (MEMCTR & 0xF8) | 0x07; imgSelect(); // Attempt to select and run an image. SLEEPCMD |= 0x03; // PM3, All clock oscillators off, voltage regulator off. halSleepExec(); HAL_SYSTEM_RESET(); // Should not get here. }
/************************************************************************************************** * @fn main * * @brief C-code main functionality. * * input parameters * * None. * * output parameters * * None. * * @return None. ************************************************************************************************** */ void main(void) { uint8 time_spent_validating; uint8 bootloaderForcedByMainApp = FALSE; uint32 mainAppCommandLocal = mainAppCommand; vddWait(VDD_MIN_RUN); mainAppCommand = MAIN_APP_CMD_NONE; if (mainAppCommandLocal == MAIN_APP_CMD_FORCE_BOOTLOADER) { bootloaderForcedByMainApp = TRUE; } else if ((mainAppCommandLocal == MAIN_APP_CMD_PASS_THROUGH) || ((SLEEPSTA & LRESET) == RESETWD)) { // If reset due to WatchDog Timer - Transfer control to the main application immediately. // WatchDog Timer reset causes the hardware to disconnect the USB. Withought this jump here, // the SBL code will try to initiaize the CDC too early, which causes undesired behavior on the host // (e.g. on beaglebone black - the host gets stuck) asm("LJMP 0x2000\n"); } sblInit(bootloaderForcedByMainApp); HAL_TURN_ON_LED1(); HAL_TURN_ON_LED2(); if ((!bootloaderForcedByMainApp) && (sbImgValid(&time_spent_validating))) { HAL_TURN_OFF_LED2(); if (sblWait(SBL_WAIT_TIME > time_spent_validating ? SBL_WAIT_TIME - time_spent_validating : 0)) { HAL_TURN_OFF_LED1(); sbReportState(SB_STATE_EXECUTING_IMAGE); while(sblIsUartTxPending()) { sbUartPoll(); } SLEEP(0x2600); //Give the last bytes in the HW TX fifo (if any) enough time to be transmitted while (SB1_PRESS || SB2_PRESS); sblUnInit(); // Simulate a reset for the Application code by an absolute jump to location 0x2000. asm("LJMP 0x2000\n"); } } HAL_TURN_OFF_LED1(); HAL_TURN_ON_LED2(); vddWait(VDD_MIN_NV); sblExec(); sblUnInit(); asm("LJMP 0x2000\n"); }