initial check in based on SVN revision 575
This commit is contained in:
343
source/Loader/flashUpdate.c
Normal file
343
source/Loader/flashUpdate.c
Normal file
@@ -0,0 +1,343 @@
|
||||
/*
|
||||
* flashUpdate.c
|
||||
*
|
||||
* Created on: Oct 23, 2023
|
||||
* Author: Brian.Bailey
|
||||
*/
|
||||
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#include "usbComms.h"
|
||||
#include "sha256.h"
|
||||
|
||||
#include "flashUpdate.h"
|
||||
|
||||
#include "fsl_common.h"
|
||||
#include "fsl_iap.h"
|
||||
|
||||
#include "bootloader.h"
|
||||
#include "eeprom.h"
|
||||
/*******************************************************************************
|
||||
* Definitions
|
||||
******************************************************************************/
|
||||
|
||||
#define null 0 //NULL is defined at (void *)0 so it causes errors
|
||||
|
||||
//sector0~2 for bootloader, sector3~7 for APP
|
||||
#define IAP_FLASH_SECTOR_START (3)
|
||||
#define IAP_FLASH_SECTOR_END (7)
|
||||
// #define IAP_FLASH_SECTOR_END (3) //for test
|
||||
|
||||
/*******************************************************************************
|
||||
* Variables
|
||||
******************************************************************************/
|
||||
FLASH_UPDATE_t fu;
|
||||
extern USB_t usb;
|
||||
extern BL_DATA_t blData;
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
* Static Function Declarations
|
||||
******************************************************************************/
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
* Static Functions
|
||||
******************************************************************************/
|
||||
|
||||
/*
|
||||
* Convert the source string to bytes & store in *dst
|
||||
* Converts 32 ASCII chars to 16 bytes
|
||||
*/
|
||||
static void ConvertStringToHalfHash(uint8_t *src, uint8_t *dst)
|
||||
{
|
||||
//32 ASCII chars to 16 bytes
|
||||
for(uint32_t i = 0; i < SHA256_BLOCK_SIZE/2; i++)
|
||||
{
|
||||
//sscanf(&src[i*2], "%02hhX", &dst[i]); //This works in the RX but has problems when ASCII is > 127?
|
||||
|
||||
uint8_t temp[3];
|
||||
temp[0] = src[i*2];
|
||||
temp[1] = src[i*2+1];
|
||||
temp[3] = 0;
|
||||
|
||||
dst[i] = strtol(temp, NULL, 16);
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
* @brief Convert uint8 to uint32.
|
||||
*
|
||||
* @param len length of arr8.
|
||||
*/
|
||||
static void ConvertUint8ToUint32(uint8_t *arr8, uint32_t *arr32, uint32_t len) {
|
||||
|
||||
uint32_t temp;
|
||||
for (uint32_t i = 0; i < FSL_FEATURE_SYSCON_FLASH_PAGE_SIZE_BYTES; i++)
|
||||
{
|
||||
*(((uint8_t *)arr32) + i) = 0xFF;
|
||||
}
|
||||
//get the length of arr32
|
||||
if(len % 4){
|
||||
len /= 4;
|
||||
len += 1;
|
||||
}
|
||||
else{
|
||||
len /= 4;
|
||||
}
|
||||
for(uint32_t i = 0; i < len; i++) {
|
||||
temp = (uint32_t)arr8[3] << 24;
|
||||
temp |= (uint32_t)arr8[2] << 16;
|
||||
temp |= (uint32_t)arr8[1] << 8;
|
||||
temp |= (uint32_t)arr8[0];
|
||||
arr8 += 4;
|
||||
arr32[i] = temp;
|
||||
}
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* Public Functions
|
||||
******************************************************************************/
|
||||
|
||||
|
||||
/* Setup for FLASH programming
|
||||
* /arg *data: csv string: pProgramSetup,<numBytes>,<hash>
|
||||
* Use program length to calculate number of FLASH sectors to erase
|
||||
* Save hash, program size, and calculated parameters
|
||||
* Set usb.programMode
|
||||
* Send ACK / NAK
|
||||
*/
|
||||
void FU_ProgramSetup(uint8_t *data)
|
||||
{
|
||||
//reset variables
|
||||
fu.imageReceived = false;
|
||||
fu.flashHashMatch = false;
|
||||
fu.numBytesToProgram = 0;
|
||||
fu.numBytesProgrammed = 0;
|
||||
|
||||
bool error = false;
|
||||
|
||||
//Parse Program message
|
||||
static uint8_t *p; //pointer for strtok - static so it doesn't get optimized out.
|
||||
p = strtok(data, ","); //points to "pProgramSetup"
|
||||
p = strtok(null, ","); //number of bytes in the image
|
||||
fu.numBytesToProgram = atoi(p);
|
||||
|
||||
p = strtok(null, ","); //hash - sent as string
|
||||
ConvertStringToHalfHash(p, fu.hostHash);
|
||||
|
||||
//clear programmed flag in EEPROM
|
||||
blData.transmitterProgrammed = 0;
|
||||
EE_WriteMemoryUINT32(BL_PROGRAMMED_EEPROM_ADDR, &blData.transmitterProgrammed);
|
||||
|
||||
//Erase APP flash
|
||||
//USB_SendString("Erasing flash..."); //or to LCD
|
||||
IAP_PrepareSectorForWrite(IAP_FLASH_SECTOR_START, IAP_FLASH_SECTOR_END);
|
||||
IAP_EraseSector(IAP_FLASH_SECTOR_START, IAP_FLASH_SECTOR_END, SystemCoreClock);
|
||||
//USB_SendString("Erase flash completed"); //OR TO LCD
|
||||
status_t status;
|
||||
status = IAP_BlankCheckSector(IAP_FLASH_SECTOR_START, IAP_FLASH_SECTOR_END);
|
||||
if (status != kStatus_IAP_Success)
|
||||
{
|
||||
error = 1;
|
||||
// PRINTF("\r\nSector erase failed\r\n"); //to LCD
|
||||
}
|
||||
|
||||
//Initialize fu
|
||||
memset(fu.rxPageData, 0xff, sizeof(fu.rxPageData));
|
||||
fu.flashProgramTargetAddress = BL_APP_IMAGE_ADDR;
|
||||
|
||||
|
||||
if(error)
|
||||
{
|
||||
USB_SendString(NAK);
|
||||
}
|
||||
else
|
||||
{
|
||||
usb.programMode = true;
|
||||
USB_SendString(ACK);
|
||||
}
|
||||
}
|
||||
|
||||
/* Write received data to FLASH using fu struct information
|
||||
* This function is called repeatedly to write program FLASH
|
||||
* When all data received, function sends ACK or NACK via USB
|
||||
*/
|
||||
void FU_WriteProgramDataToFLASH(void)
|
||||
{
|
||||
bool error = false;
|
||||
|
||||
//Verify packet: check header and check that size matches
|
||||
if (USB_PACKET_START_BYTE != usb.rxDataBuffer[USB_PACKET_HEADER_OFFSET])
|
||||
{
|
||||
error = true;
|
||||
}
|
||||
|
||||
uint32_t packetSize = usb.rxDataBuffer[USB_PACKET_LENGTH_H_OFFSET] * 256; //high byte
|
||||
packetSize += usb.rxDataBuffer[USB_PACKET_LENGTH_L_OFFSET]; //low byte
|
||||
|
||||
if(packetSize != usb.rxDataIndex) //check that computed packet size matches number of bytes received
|
||||
{
|
||||
error = true;
|
||||
}
|
||||
|
||||
//Write data to FLASH
|
||||
//you can use packetSize. It is the size of the data in bytes
|
||||
//Best to wait for a whole page or sector of data before writing to FLASH.
|
||||
//faster this way
|
||||
uint32_t rxData[64];
|
||||
|
||||
if(!error){
|
||||
//Judge whether it is the last packet
|
||||
if((packetSize - USB_PACKET_HEADER_SIZE + fu.numBytesProgrammed) == fu.numBytesToProgram)
|
||||
{
|
||||
//Judge whether the page is going to be full
|
||||
if((fu.numBytesInPageData + packetSize - USB_PACKET_HEADER_SIZE) >= FSL_FEATURE_SYSCON_FLASH_PAGE_SIZE_BYTES)
|
||||
{
|
||||
uint16_t numBytesCurrentPage;
|
||||
numBytesCurrentPage = FSL_FEATURE_SYSCON_FLASH_PAGE_SIZE_BYTES - fu.numBytesInPageData;
|
||||
memcpy(&fu.rxPageData[fu.numBytesInPageData], &usb.rxDataBuffer[USB_PACKET_PAYLOAD_OFFSET], numBytesCurrentPage);
|
||||
|
||||
ConvertUint8ToUint32(fu.rxPageData, rxData, FSL_FEATURE_SYSCON_FLASH_PAGE_SIZE_BYTES);
|
||||
IAP_PrepareSectorForWrite(IAP_FLASH_SECTOR_START, IAP_FLASH_SECTOR_END);
|
||||
IAP_CopyRamToFlash(fu.flashProgramTargetAddress, rxData, FSL_FEATURE_SYSCON_FLASH_PAGE_SIZE_BYTES, SystemCoreClock);
|
||||
fu.flashProgramTargetAddress += FSL_FEATURE_SYSCON_FLASH_PAGE_SIZE_BYTES;
|
||||
|
||||
//start the next FLASH page
|
||||
memset(fu.rxPageData, 0xff, sizeof(fu.rxPageData));
|
||||
fu.numBytesInPageData = 0;
|
||||
memcpy(&fu.rxPageData[fu.numBytesInPageData], &usb.rxDataBuffer[USB_PACKET_PAYLOAD_OFFSET + numBytesCurrentPage], (packetSize - USB_PACKET_HEADER_SIZE - numBytesCurrentPage));
|
||||
fu.numBytesInPageData += (packetSize - USB_PACKET_HEADER_SIZE - numBytesCurrentPage);
|
||||
|
||||
//write to FLASH
|
||||
ConvertUint8ToUint32(fu.rxPageData, rxData, FSL_FEATURE_SYSCON_FLASH_PAGE_SIZE_BYTES);
|
||||
IAP_PrepareSectorForWrite(IAP_FLASH_SECTOR_START, IAP_FLASH_SECTOR_END);
|
||||
IAP_CopyRamToFlash(fu.flashProgramTargetAddress, rxData, FSL_FEATURE_SYSCON_FLASH_PAGE_SIZE_BYTES, SystemCoreClock);
|
||||
fu.flashProgramTargetAddress += FSL_FEATURE_SYSCON_FLASH_PAGE_SIZE_BYTES;
|
||||
}
|
||||
else
|
||||
{
|
||||
//write the final page to FLASH
|
||||
memcpy(&fu.rxPageData[fu.numBytesInPageData], &usb.rxDataBuffer[USB_PACKET_PAYLOAD_OFFSET], (packetSize - USB_PACKET_HEADER_SIZE)); //copy packet to fu.rxPageData
|
||||
fu.numBytesInPageData += (packetSize - USB_PACKET_HEADER_SIZE);
|
||||
|
||||
ConvertUint8ToUint32(fu.rxPageData, rxData, FSL_FEATURE_SYSCON_FLASH_PAGE_SIZE_BYTES);
|
||||
IAP_PrepareSectorForWrite(IAP_FLASH_SECTOR_START, IAP_FLASH_SECTOR_END);
|
||||
IAP_CopyRamToFlash(fu.flashProgramTargetAddress, rxData, FSL_FEATURE_SYSCON_FLASH_PAGE_SIZE_BYTES, SystemCoreClock);
|
||||
fu.flashProgramTargetAddress += FSL_FEATURE_SYSCON_FLASH_PAGE_SIZE_BYTES;
|
||||
}
|
||||
}
|
||||
else{
|
||||
//Judge whether the page is going to be full
|
||||
if((fu.numBytesInPageData + packetSize - USB_PACKET_HEADER_SIZE) >= FSL_FEATURE_SYSCON_FLASH_PAGE_SIZE_BYTES){
|
||||
uint16_t numBytesCurrentPage;
|
||||
numBytesCurrentPage = FSL_FEATURE_SYSCON_FLASH_PAGE_SIZE_BYTES - fu.numBytesInPageData;
|
||||
memcpy(&fu.rxPageData[fu.numBytesInPageData], &usb.rxDataBuffer[USB_PACKET_PAYLOAD_OFFSET], numBytesCurrentPage);
|
||||
|
||||
ConvertUint8ToUint32(fu.rxPageData, rxData, FSL_FEATURE_SYSCON_FLASH_PAGE_SIZE_BYTES);
|
||||
IAP_PrepareSectorForWrite(IAP_FLASH_SECTOR_START, IAP_FLASH_SECTOR_END);
|
||||
IAP_CopyRamToFlash(fu.flashProgramTargetAddress, rxData, FSL_FEATURE_SYSCON_FLASH_PAGE_SIZE_BYTES, SystemCoreClock);
|
||||
fu.flashProgramTargetAddress += FSL_FEATURE_SYSCON_FLASH_PAGE_SIZE_BYTES;
|
||||
|
||||
//start the next FLASH page
|
||||
memset(fu.rxPageData, 0xff, sizeof(fu.rxPageData));
|
||||
fu.numBytesInPageData = 0;
|
||||
memcpy(&fu.rxPageData[fu.numBytesInPageData], &usb.rxDataBuffer[USB_PACKET_PAYLOAD_OFFSET + numBytesCurrentPage], (packetSize - USB_PACKET_HEADER_SIZE - numBytesCurrentPage));
|
||||
fu.numBytesInPageData += (packetSize - USB_PACKET_HEADER_SIZE - numBytesCurrentPage);
|
||||
}
|
||||
else{
|
||||
memcpy(&fu.rxPageData[fu.numBytesInPageData], &usb.rxDataBuffer[USB_PACKET_PAYLOAD_OFFSET], (packetSize - USB_PACKET_HEADER_SIZE));
|
||||
fu.numBytesInPageData += (packetSize - USB_PACKET_HEADER_SIZE);
|
||||
}
|
||||
}
|
||||
|
||||
fu.numBytesProgrammed += packetSize - USB_PACKET_HEADER_SIZE;
|
||||
}
|
||||
|
||||
//Test for all data transferred
|
||||
if(fu.numBytesProgrammed >= fu.numBytesToProgram)
|
||||
{
|
||||
usb.programMode = false;
|
||||
fu.imageReceived = true;
|
||||
}
|
||||
|
||||
if(error)
|
||||
{
|
||||
USB_SendString(NAK);
|
||||
}
|
||||
else
|
||||
{
|
||||
USB_SendString(ACK);
|
||||
}
|
||||
}
|
||||
|
||||
/* Verify FLASH image using sha256 hash
|
||||
* Compute sha256 hash of program image
|
||||
* Compare to fu.hostHash
|
||||
*/
|
||||
void FU_VerifyImage()
|
||||
{
|
||||
//TODO: Compute sha256 hash of program image from FLASH
|
||||
static uint32_t dstAddr = BL_APP_IMAGE_ADDR;
|
||||
uint8_t rxData[FSL_FEATURE_SYSCON_FLASH_PAGE_SIZE_BYTES];
|
||||
uint32_t i = 0;
|
||||
SHA256_CTX ctx;
|
||||
|
||||
/* EMAMPLE: (Also see sha256_test())
|
||||
* SHA256_CTX ctx;
|
||||
* sha256_init(&ctx); //initialize
|
||||
* sha256_update(&ctx, data, dataLength); //call this for each block of data
|
||||
* sha256_final(&ctx, fu.flashHash); //finish
|
||||
*/
|
||||
|
||||
sha256_init(&ctx);
|
||||
for(i = 0; i < (fu.numBytesToProgram / FSL_FEATURE_SYSCON_FLASH_PAGE_SIZE_BYTES); i++){
|
||||
//read flash
|
||||
for(uint32_t j = 0; j < FSL_FEATURE_SYSCON_FLASH_PAGE_SIZE_BYTES; j++) //read 256 bytes from FLASH to rxData
|
||||
{
|
||||
rxData[j] = *(uint8_t *)(dstAddr + FSL_FEATURE_SYSCON_FLASH_PAGE_SIZE_BYTES * i + j);
|
||||
}
|
||||
//calculate sha256
|
||||
// sha256_update(&ctx, rxData, strlen((char *)rxData));
|
||||
sha256_update(&ctx, rxData, FSL_FEATURE_SYSCON_FLASH_PAGE_SIZE_BYTES);
|
||||
}
|
||||
for(uint32_t j = 0; j < (fu.numBytesToProgram % FSL_FEATURE_SYSCON_FLASH_PAGE_SIZE_BYTES); j++){
|
||||
rxData[j] = *(uint8_t *)(dstAddr + FSL_FEATURE_SYSCON_FLASH_PAGE_SIZE_BYTES * i + j);
|
||||
}
|
||||
sha256_update(&ctx, rxData, (fu.numBytesToProgram % FSL_FEATURE_SYSCON_FLASH_PAGE_SIZE_BYTES));
|
||||
sha256_final(&ctx, fu.flashHash);
|
||||
|
||||
//Compare fu.flashHash with fu.hostHash - FIRST HALF ONLY!
|
||||
if(0 == memcmp(fu.hostHash, fu.flashHash, SHA256_BLOCK_SIZE/2)) //Failed, I don't know the reason.
|
||||
// if(1) //for test, bypass verification and it works
|
||||
{
|
||||
//set programmed flag in EEPROM
|
||||
blData.transmitterProgrammed = true;
|
||||
EE_WriteMemoryUINT32(BL_PROGRAMMED_EEPROM_ADDR, &blData.transmitterProgrammed);
|
||||
USB_SendString(ACK);
|
||||
}
|
||||
else
|
||||
{
|
||||
USB_SendString(NAK);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Reset the processor
|
||||
* Works even if in ISR
|
||||
*/
|
||||
void FU_ResetProcessor(void)
|
||||
{
|
||||
//Disable interrupts.
|
||||
__disable_irq();
|
||||
|
||||
// Memory barriers for good measure.
|
||||
__ISB();
|
||||
__DSB();
|
||||
|
||||
//Reset
|
||||
NVIC_SystemReset();
|
||||
}
|
||||
Reference in New Issue
Block a user