#include // For memcpy and memset #include "F021.h" // For fapi operations #include "system.h" // For fapi operations #include "NVDataMgmt.h" /** * @addtogroup NVDataMgmt * @{ */ /* * TODO * 1. Clean up the flash with the bad data packets */ // ********** private definitions ********** #define BANK0_NUM_OF_SECTORS 16 ///< Bank0 number of sectors. #define FLOAT_TO_INT_ROUNDUP_OFFSET 0.5F ///< Offset to add to a floating point value for rounding rounding when converting to integer. #define ROUNDED_HCLK_FREQ ((HCLK_FREQ) < 0.0F ? (S32)((HCLK_FREQ) - FLOAT_TO_INT_ROUNDUP_OFFSET) : \ (S32)((HCLK_FREQ) + FLOAT_TO_INT_ROUNDUP_OFFSET)) ///< Rounded HCLK for flash clock. /// EEPROM functions use the buffer length as the size of U32. So before send the length to any of FAPI functions, it should be divided by 4. #define EEPROM_OPS_SIZE_OF_CONVERTER 4 #define NUM_OF_BYTES_WRITE_TO_FALSH 16 ///< Number of bytes to write. #define NUM_OF_FIRMWARE_CRC_TABLE_BYTES 1 ///< Number of firmware CRC table bytes. #define VALUE_OF_AN_ERASED_FLASH 0xFFFFFFFF ///< Value of an erased flash. /// Flash write status structure typedef struct Flash_Write_Status { BOOL hasFlashBeenErased; ///< Boolean flag to indicate flash has been erased. U32 currentWriteAddress; ///< Current write address in the flash memory. } SW_UPDATE_FALSH_STATUS_T; /// Bank 0 sectors status structure typedef struct Sectors { U32 startAddress; ///< Start address. U32 length; // number of 32-bit words ///< Length of data (word or 4 bytes). U32 bankNumber; ///< Bank number. U32 sectorNumber; ///< Sector number. } BANK0_SECTORS_T; /// Bank sectors array const BANK0_SECTORS_T bank0Sectors[ BANK0_NUM_OF_SECTORS ]= { 0x00000000, 0x04000, 0, 0, 0x00004000, 0x04000, 0, 1, 0x00008000, 0x04000, 0, 2, 0x0000C000, 0x04000, 0, 3, 0x00010000, 0x04000, 0, 4, 0x00014000, 0x04000, 0, 5, 0x00018000, 0x08000, 0, 6, 0x00020000, 0x20000, 0, 7, 0x00040000, 0x20000, 0, 8, 0x00060000, 0x20000, 0, 9, 0x00080000, 0x20000, 0, 10, 0x000A0000, 0x20000, 0, 11, 0x000C0000, 0x20000, 0, 12, 0x000E0000, 0x20000, 0, 13, 0x00100000, 0x20000, 0, 14, 0x00120000, 0x20000, 0, 15 }; // ********** private data ********** static SW_UPDATE_FALSH_STATUS_T SWUpdateFlashStatus; ///< Software update flash status. // ********** private function prototypes ********** static BOOL eraseFlashSectors( void ); static BOOL writeFlashSectors( U08* data ); /*********************************************************************//** * @brief * The initNVDataMgmt function initializes the module. * @details \b Inputs: none * @details \b Outputs: initializes flash bank 0. * @return none *************************************************************************/ void initNVDataMgmt( void ) { // Setup the flash bank clock Fapi_initializeFlashBanks( ROUNDED_HCLK_FREQ ); // Activate flash bank 0 Fapi_setActiveFlashBank( Fapi_FlashBank0 ); Fapi_enableMainBankSectors( 0xFFFF ); /* used for API 2.01*/ while( FAPI_CHECK_FSM_READY_BUSY != Fapi_Status_FsmReady ); clearSWUpdateNVStatus(); } /*********************************************************************//** * @brief * The clearSWUpdateNVStatus function clears the variables that are used * in software update. * @details \b Inputs: none * @details \b Outputs: SWUpdateFlashStatus * @return none *************************************************************************/ void clearSWUpdateNVStatus( void ) { SWUpdateFlashStatus.hasFlashBeenErased = FALSE; SWUpdateFlashStatus.currentWriteAddress = FIRMWARE_START_ADDRESS; } /*********************************************************************//** * @brief * The handleUpdatingFlash function handles updating the flash. If the sectors * have not been erased first, they are erased. * @details \b Inputs: none * @details \b Outputs: SWUpdateFlashStatus * @param data to write pointer to the buffer that is going to be written * to flash * @return TRUE if the write and erase was successful otherwise, FALSE *************************************************************************/ BOOL handleUpdatingFlash( U08* dataToWrite ) { BOOL status = FALSE; if ( FALSE == SWUpdateFlashStatus.hasFlashBeenErased ) { // TODO what should we do if the erase failed? try again? SWUpdateFlashStatus.hasFlashBeenErased = eraseFlashSectors(); if ( TRUE == SWUpdateFlashStatus.hasFlashBeenErased ) { status = writeFlashSectors( dataToWrite ); } } else { status = writeFlashSectors( dataToWrite ); } return status; } /*********************************************************************//** * @brief * The isFWCRCTableValid function checks whether the firmware CRC table is * valid or not. This function reads a word data starting from the firmware * start address. Then it is verified to make sure it is not 0xFFFFFFFF. * @details \b Inputs: none * @details \b Outputs: none * @return TRUE if the firmware CRC is valid otherwise, FALSE *************************************************************************/ BOOL isFWCRCTableValid( void ) { Fapi_FlashStatusWordType crcVerifyReason; U32 erasedFlashedValue[ NUM_OF_FIRMWARE_CRC_TABLE_BYTES ]; BOOL crcVerifyStatus = FALSE; // Create a buffer of 1 byte and write 0xFFFFFFFF to it memset( erasedFlashedValue, VALUE_OF_AN_ERASED_FLASH, sizeof( erasedFlashedValue ) ); // Verify the value is not 0xFFFFFFFF reading from the firmware start address crcVerifyStatus = Fapi_doVerify( (U32*)FIRMWARE_CRC_TABLE_ADDRESS, NUM_OF_FIRMWARE_CRC_TABLE_BYTES, (U32*)&erasedFlashedValue, &crcVerifyReason ); // Wait for the FAPI respond while( FAPI_CHECK_FSM_READY_BUSY == Fapi_Status_FsmBusy ); // TODO timeout or count so we wont get stuck here for ever // Check if the value of the provided buffer is the same as the what was found in the firmware start address crcVerifyStatus = ( Fapi_Status_Success == crcVerifyStatus ? FALSE : TRUE ); return crcVerifyStatus; } // ********** private functions ********** /*********************************************************************//** * @brief * The eraseFlashSectors function erases the flash sectors. It starts from * the sectors of the firmware start address and erases until the end of bank 0. * @details \b Inputs: none * @details \b Outputs: none * @return TRUE if the erase was successful otherwise, FALSE *************************************************************************/ static BOOL eraseFlashSectors( void ) { U08 i; BOOL status = FALSE; for ( i = 0; i < BANK0_NUM_OF_SECTORS; i++ ) { if ( bank0Sectors[ i ].startAddress >= FIRMWARE_START_ADDRESS ) { Fapi_issueAsyncCommandWithAddress( Fapi_EraseSector, (U32*)bank0Sectors[ i ].startAddress ); while( FAPI_CHECK_FSM_READY_BUSY == Fapi_Status_FsmBusy ); while(FAPI_GET_FSM_STATUS != Fapi_Status_Success); status |= TRUE; } } // TODO check the erased sectors return status; } /*********************************************************************//** * @brief * The writeFlashSectors function writes to a sector of the flash. * @details \b Inputs: SWUpdateFlashStatus * @details \b Outputs: none * @return TRUE if the write was successful otherwise, FALSE *************************************************************************/ static BOOL writeFlashSectors( U08* data ) { Fapi_FlashStatusWordType writeVerifyReason; Fapi_StatusType writeVerifyStatus; U08 dataRead2Verify[ SW_UPDATE_FLASH_BUFFER_SIZE ]; BOOL status = FALSE; U08 bytesWritten = 0; U32 startAddress = SWUpdateFlashStatus.currentWriteAddress; memcpy( dataRead2Verify, data, SW_UPDATE_FLASH_BUFFER_SIZE ); // Keep writing until the buffer is finished while ( bytesWritten < SW_UPDATE_FLASH_BUFFER_SIZE ) { Fapi_issueProgrammingCommand( (U32*)SWUpdateFlashStatus.currentWriteAddress, data, NUM_OF_BYTES_WRITE_TO_FALSH, 0x00, 0, Fapi_DataOnly ); while( FAPI_CHECK_FSM_READY_BUSY == Fapi_Status_FsmBusy ); // Update the write pointer. Update the current write address in the flash data += NUM_OF_BYTES_WRITE_TO_FALSH; SWUpdateFlashStatus.currentWriteAddress += NUM_OF_BYTES_WRITE_TO_FALSH; bytesWritten += NUM_OF_BYTES_WRITE_TO_FALSH; } writeVerifyStatus = Fapi_doVerify( (U32*)startAddress, ( SW_UPDATE_FLASH_BUFFER_SIZE / SW_UPDATE_FLASH_BUFFER_SIZE ), (U32*)&dataRead2Verify, &writeVerifyReason ); while( FAPI_CHECK_FSM_READY_BUSY == Fapi_Status_FsmBusy ); // TODO timeout or count so we wont get stuck here forever status = ( Fapi_Status_Success == writeVerifyStatus ? TRUE : FALSE ); return status; } /**@}*/