/********************************************************************* * @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; }
/********************************************************************* * @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; } }
/******************************************************************************* * @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 OADTarget_imgIdentifyWrite * * @brief Process the Image Identify Write. Determined if the image * header identified here should or should not be downloaded by * this application. * * @param connHandle - connection message was received on * @param pValue - pointer to image header data * * @return status */ bStatus_t OADTarget_imgIdentifyWrite(uint16_t connHandle, uint8_t *pValue) { static img_hdr_t rxHdr; static img_hdr_t ImgHdr; oadBlkNum = 0; rxHdr.ver = BUILD_UINT16(pValue[0], pValue[1]); rxHdr.len = BUILD_UINT16(pValue[2], pValue[3]); (void)memcpy(rxHdr.uid, pValue+4, sizeof(rxHdr.uid)); // Read out running image's header. uint8_t *flashAddr = (uint8_t *)(APP_IMAGE_START + OAD_IMG_HDR_OSET); memcpy(&ImgHdr,flashAddr,sizeof(img_hdr_t)); // Calculate block total of the new image. // total Blocks = (length in HAL Flash words) / ((16 Byte Block)/(4 Byte Word)) oadBlkTot = rxHdr.len / (OAD_BLOCK_SIZE / HAL_FLASH_WORD_SIZE); /* Requirements to begin OAD: * 1) LSB of image version cannot be the same, this would imply a code overlap * between currently running image and new image, which is illegal. * 2) Total blocks of new image must not exceed maximum blocks supported, else * the new image cannot fit. * 3) New image must not be empty header. * 4) Optional: Add customer criteria for initiating OAD here. */ if ( (oadBlkTot <= OAD_BLOCK_MAX) && (oadBlkTot != 0)) { oadBlkNum = 0; // Image accepted, request image. OADTarget_getNextBlockReq(connHandle, 0); } else { // Image rejected, identify current image to OAD manager. OADTarget_rejectImage(connHandle, &ImgHdr); } // Ready to go: open flash driver flashOk = extFlashOpen(); return (flashOk ? SUCCESS : FAILURE); }
/******************************************************************************* * @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; }
/********************************************************************* * @fn OADTarget_open * * @brief Open an OAD target for download. * * @param none * * @return TRUE if OAD target successfully opened */ uint8_t OADTarget_open(void) { isOpen = extFlashOpen(); return isOpen; }