void readExtFlash(void) { RadioInfoPacket_t packet; bool prevMissed = false; while (extFlashAddress < EXT_FLASH_SIZE) { extFlashRead(extFlashAddress, &packet, sizeof(packet)); if (packet.crc == crc16((uint8_t *)&packet, sizeof(packet) - sizeof(uint16_t))) { if (prevMissed) { PRINT("corrupt packet\n"); } prevMissed = false; printPacket(&packet); } else { // XXX: this is supposed to find first non-packet, but it will find first two invalid packets!! if (!prevMissed) { prevMissed = true; } else { break; } } extFlashAddress += sizeof(packet); } // PRINTF("flash packet offset=%lu\n", extFlashAddress - EXT_FLASH_RESERVED); }
/********************************************************************* * @fn checkDL * * @brief Check validity of the downloaded image. * * input parameters * * None. * * output parameters * * None. * * @return TRUE or FALSE for image valid. */ static uint8_t checkDL(void) { bool ret; uint16_t crc[2]; ret = extFlashOpen(); if (ret) { ret = extFlashRead((size_t)APP_IMAGE_START, sizeof(crc), (uint8_t*)crc); if (ret) { if ((crc[0] == 0xFFFF) || (crc[0] == 0x0000)) { ret = false; } if (crc[1] == 0xFFFF || crc[1] == 0x0000) { crc[1] = crcCalcDL(); } ret = crc[0] == crc[1]; } extFlashClose(); } return ret ? TRUE : FALSE; }
void readExtFlash(void) { DataPacket_t packet; bool prevMissed = false; while (extFlashAddress < EXT_FLASH_SIZE) { extFlashRead(extFlashAddress, &packet, sizeof(packet)); bool valid = true; if (packet.crc != crc16((uint8_t *)&packet, sizeof(packet) - sizeof(uint16_t))) { valid = false; } else { if (packet.dataSeqnum == 0) valid = false; } if (valid) { if (prevMissed) { PRINT("corrupt packet\n"); } prevMissed = false; printPacket(&packet); } else { // XXX: this is supposed to find first non-packet, but it will find first two invalid packets!! if (!prevMissed) { prevMissed = true; } else { // break; PRINT("bad!\n"); } } extFlashAddress += sizeof(packet); } }
/********************************************************************* * @fn OADTarget_getCurrentImageHeader * * @brief Get the header of the running image. * * @param pValue - pointer to store running image header. * * @return none */ void OADTarget_getCurrentImageHeader(img_hdr_t *pHdr) { if (extFlashOpen()) { //N.B: it is assumed that OADTarget_storeImageHeader() has been called prior // to this function. uint32_t metaDataAddr; ExtImageInfo_t tempHdr; if (imgInfo.imgType == EFL_OAD_IMG_TYPE_STACK || imgInfo.imgType == EFL_OAD_IMG_TYPE_NP) { metaDataAddr = EFL_IMAGE_INFO_ADDR_BLE; } else // Assume imgInfo.imgType == EFL_OAD_IMG_TYPE_APP { metaDataAddr = EFL_IMAGE_INFO_ADDR_APP; } extFlashRead(metaDataAddr, sizeof(ExtImageInfo_t), (uint8_t*)&tempHdr); extFlashClose(); pHdr->len = tempHdr.len; pHdr->ver = tempHdr.ver == 0xFF ? 0x00 : tempHdr.ver; // In case metadata does not exist. memcpy(pHdr->uid,tempHdr.uid,sizeof(tempHdr.uid)); pHdr->res[0] = HI_UINT16(tempHdr.addr); pHdr->res[1] = LO_UINT16(tempHdr.addr); pHdr->res[2] = tempHdr.imgType; pHdr->res[3] = 0xFF; } }
void prepareExtFlash(void) { extFlashWake(); // check if old records exist DataPacket_t packet; bool oneInvalid = false; extFlashAddress = EXT_FLASH_RESERVED; while (extFlashAddress < EXT_FLASH_SIZE) { extFlashRead(extFlashAddress, &packet, sizeof(packet)); // PRINT("read packet:\n"); // printPacket(&packet); bool valid = true; if (packet.crc != crc16((uint8_t *)&packet, sizeof(packet) - sizeof(uint16_t))) { valid = false; } else { if (packet.dataSeqnum == 0) valid = false; } if (valid) { oneInvalid = false; } else { // XXX: this is supposed to find first non-packet, but it will find first two invalid packets!! if (!oneInvalid) { oneInvalid = true; } else { extFlashAddress -= sizeof(packet); break; } } extFlashAddress += sizeof(packet); } PRINTF("flash packet offset=%lu\n", extFlashAddress - EXT_FLASH_RESERVED); }
void flashRead(uint32_t address) { uint16_t i; uint8_t readBuffer[BUFFER_SIZE]; extFlashRead(address, readBuffer, BUFFER_SIZE); for (i = 0; i < BUFFER_SIZE; ++i) { ASSERT(readBuffer[i] == buffer[i]); } }
void readSensors(DataPacket_t *packet) { DPRINTF("reading sensors...\n"); ledOn(); humidityOn(); packet->timestamp = getJiffies(); packet->sourceAddress = localAddress; packet->dataSeqnum = ++dataSeqnum; if (localAddress != 0x0796) { if (!islRead(&packet->islLight, true)) { PRINT("islRead failed\n"); packet->islLight = 0xffff; } packet->sq100Light = 0xffff; } else { packet->islLight = 0xffff; if (!readAds(&packet->sq100Light)) { PRINT("readAdsRegister failed\n"); packet->sq100Light = 0xffff; } } packet->internalVoltage = adcRead(ADC_INTERNAL_VOLTAGE); packet->internalTemperature = adcRead(ADC_INTERNAL_TEMPERATURE); DPRINT("read hum\n"); packet->sht75Humidity = humidityRead(); packet->sht75Temperature = temperatureRead(); DPRINT("read done\n"); packet->crc = crc16((uint8_t *) packet, sizeof(*packet) - 2); #if WRITE_TO_FLASH if (extFlashAddress < EXT_FLASH_SIZE) { DPRINT("Writing to flash\n"); extFlashWrite(extFlashAddress, packet, sizeof(*packet)); DataPacket_t verifyRecord; memset(&verifyRecord, 0, sizeof(verifyRecord)); extFlashRead(extFlashAddress, &verifyRecord, sizeof(verifyRecord)); if (memcmp(packet, &verifyRecord, sizeof(verifyRecord))) { ASSERT("writing in flash failed!" && false); } extFlashAddress += sizeof(verifyRecord); } #endif humidityOff(); ledOff(); }
/******************************************************************************* * @fn SensorTag_saveFactoryImage * * @brief Save the current image to external flash as a factory image * * @return none */ static bool SensorTag_saveFactoryImage(void) { bool success; success = extFlashOpen(); if (success) { uint32_t address; // Erase external flash for (address= 0; address<EFL_FLASH_SIZE; address+=EFL_PAGE_SIZE) { extFlashErase(address,EFL_PAGE_SIZE); } // Install factory image for (address=0; address<EFL_SIZE_RECOVERY && success; address+=EFL_PAGE_SIZE) { success = extFlashErase(EFL_ADDR_RECOVERY+address, EFL_PAGE_SIZE); if (success) { size_t offset; static uint8_t buf[256]; // RAM storage needed due to SPI/DMA limitation for (offset=0; offset<EFL_PAGE_SIZE; offset+=sizeof(buf)) { const uint8_t *pIntFlash; // Copy from internal to external flash pIntFlash = (const uint8_t*)address + offset; memcpy(buf,pIntFlash,sizeof(buf)); success = extFlashWrite(EFL_ADDR_RECOVERY+address+offset, sizeof(buf), buf); // Verify first few bytes if (success) { extFlashRead(EFL_ADDR_RECOVERY+address+offset, sizeof(buf), buf); success = buf[2] == pIntFlash[2] && buf[3] == pIntFlash[3]; } } } } extFlashClose(); } return success; }
/********************************************************************* * @fn crcCalcDL * * @brief Run the CRC16 Polynomial calculation over the DL image. * * input parameters * * None. * * output parameters * * None. * * @return The CRC16 calculated. */ static uint16_t crcCalcDL(void) { volatile uint16_t imageCRC; uint16_t remBytes; uint8_t lastPage; lastPage = ( oadBlkTot / OAD_BLOCKS_PER_PAGE ); remBytes = (oadBlkTot - (lastPage * OAD_BLOCKS_PER_PAGE)) * OAD_BLOCK_SIZE; lastPage += FIRST_PAGE; imageCRC = 0; for (uint8_t page = APP_IMAGE_START / HAL_FLASH_PAGE_SIZE; ; page++) { for (uint16_t offset = 0; offset < HAL_FLASH_PAGE_SIZE; offset += HAL_FLASH_WORD_SIZE) { if ((page == FIRST_PAGE) && (offset == OAD_IMG_CRC_OSET)) { continue; // Skip the CRC and shadow. } else if ((page == lastPage) && (offset == remBytes)) { // IAR note explains that poly must be run with value // zero for each byte of crc. imageCRC = crc16(imageCRC, 0); imageCRC = crc16(imageCRC, 0); return imageCRC; } else { uint8_t buf[HAL_FLASH_WORD_SIZE]; uint16_t addr; // Read from external flash and calculate CRC addr = (page * HAL_FLASH_PAGE_SIZE) + offset; extFlashRead(addr, HAL_FLASH_WORD_SIZE, buf); for (uint8_t idx = 0; idx < HAL_FLASH_WORD_SIZE; idx++) { imageCRC = crc16(imageCRC, buf[idx]); } } } } }
/******************************************************************************* * @fn SensorTag_hasFactoryImage * * @brief Determine if the SensorTag has a pre-programmed factory image * in external flash. Criteria for deciding if a factory image is * present is that the reset vector stored in external flash is valid. * * @return none */ static bool SensorTag_hasFactoryImage(void) { bool valid; valid = extFlashOpen(); if (valid) { uint16_t buffer[2]; // 1. Check reset vector valid = extFlashRead(EFL_ADDR_RECOVERY,sizeof(buffer),(uint8_t*)buffer); if (valid) { valid = (buffer[0] != 0xFFFF && buffer[1] != 0xFFFF) && (buffer[0] != 0x0000 && buffer[1] != 0x0000); } extFlashClose(); } return valid; }
int main(void) { // Make sure all interrupts are disabled. // This must be the first step, because in some cases interupt vectors are totally wrong // (e.g. when we get here after a soft reboot from another application) msp430ClearAllInterruptsNosave(); msp430WatchdogStop(); ledsInit(); flashLeds(LEDS_BOOTLOADER_START); BootParams_t bootParams; intFlashRead(BOOT_PARAMS_ADDRESS, &bootParams, sizeof(bootParams)); ++bootParams.bootRetryCount; if (bootParams.bootRetryCount > MAX_RETRY_COUNT) { bootParams.bootRetryCount = 0; bootParams.extFlashAddress = GOLDEN_IMAGE_ADDRESS; bootParams.doReprogramming = 1; } // make sure internal flash address is sane if (bootParams.intFlashAddress == 0xffff || bootParams.intFlashAddress < BOOTLOADER_END) { bootParams.intFlashAddress = SYSTEM_CODE_START; } // read voltage, and quit if not enough for writing in flash if (readVoltage() < THRESHOLD_VOLTAGE) { flashLeds(LEDS_LOW_BATTERY); goto exec; } // write the updated info back in flash intFlashErase(BOOT_PARAMS_ADDRESS, sizeof(bootParams)); intFlashWrite(BOOT_PARAMS_ADDRESS, &bootParams, sizeof(bootParams)); if (bootParams.doReprogramming) { redLedOn(); // will be using external flash extFlashInit(); extFlashWake(); uint32_t extAddress = bootParams.extFlashAddress; // read number of blocks uint16_t imageBlockCount; extFlashRead(extAddress, &imageBlockCount, sizeof(uint16_t)); extAddress += 2; while (imageBlockCount) { // read a block from external flash ExternalFlashBlock_t block; extFlashRead(extAddress, &block, sizeof(block)); if (block.crc != crc16((uint8_t *)&block, sizeof(block) - 2)) { // the best we can do is to reboot now; // after a few tries the golden image will be loaded flashLeds(LEDS_CRC_ERROR); // no need to disable all of the interrupts (they already are), // just write in watchdog timer wihout password, it will generate reset. watchdogRebootSimple(); } bool firstBlockInChunk = block.address & 0x1; block.address &= ~0x1; if (firstBlockInChunk) { // prepare internal flash to be written intFlashErase(block.address, INT_FLASH_SEGMENT_SIZE); } // program internal flash COMPILE_TIME_ASSERT(sizeof(block.data) == INT_FLASH_BLOCK_SIZE, ifs); intFlashWriteBlock(block.address, block.data, INT_FLASH_BLOCK_SIZE); --imageBlockCount; extAddress += sizeof(ExternalFlashBlock_t); } extFlashSleep(); redLedOff(); } #if ENABLE_BOOT_DELAY // delay for a second or so to allow the user to interrupt booting (by pressing the reset button) flashLeds(LEDS_BOOTLOADER_END); #endif // execute the program exec: ((ApplicationStartExec)bootParams.intFlashAddress)(); }
/********************************************************************* * @fn OADTarget_readFlash * * @brief Read data from flash. * * @param page - page to read from in flash * @param offset - offset into flash page to begin reading * @param pBuf - pointer to buffer into which data is read. * @param len - length of data to read in bytes. * * @return None. */ void OADTarget_readFlash(uint8_t page, uint32_t offset, uint8_t *pBuf, uint16_t len) { extFlashRead(FLASH_ADDRESS(page,offset), len, pBuf); }