/* * NVDataMgmt.c * * Created on: Aug 7, 2024 * Author: fw */ #include "F021.h" #include "string.h" #include "system.h" // For fapi operations #include "NVDataMgmt.h" #define BANK0_NUM_OF_SECTORS 16 #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. #define FIRMWARE_START_ADDRESS 0x00010000 #define MAX_FALSH_WRITE_BUFFER_BYTES 16U // TODO remove ///< Max allowed bytes for an EEPROM write (16 bytes). /// 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 typedef struct Flash_Write_Status { BOOL hasFlashBeenErased; U32 currentWriteAddress; } SW_UPDATE_FALSH_STATUS_T; typedef struct Sectors { U32 startAddress; U32 length; // number of 32-bit words U32 bankNumber; U32 sectorNumber; } BANK0_SECTORS_T; 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 }; static SW_UPDATE_FALSH_STATUS_T SWUpdateFlashStatus; static BOOL eraseFlashSectors( void ); static BOOL writeFlashSectors( U08* data ); void initNVDataMgmt( void ) { Fapi_initializeFlashBanks( ROUNDED_HCLK_FREQ ); Fapi_setActiveFlashBank( Fapi_FlashBank0 ); Fapi_enableMainBankSectors(0xFFFF); /* used for API 2.01*/ while( FAPI_CHECK_FSM_READY_BUSY != Fapi_Status_FsmReady ); SWUpdateFlashStatus.hasFlashBeenErased = FALSE; SWUpdateFlashStatus.currentWriteAddress = FIRMWARE_START_ADDRESS; } BOOL handleUpdatingFlash( U08* dataToWrite ) { BOOL status = FALSE; if ( FALSE == SWUpdateFlashStatus.hasFlashBeenErased ) { BOOL eraseStatus = FALSE; eraseStatus = eraseFlashSectors(); SWUpdateFlashStatus.hasFlashBeenErased = ( TRUE == eraseStatus ? TRUE : FALSE ); writeFlashSectors( dataToWrite ); } else { writeFlashSectors( dataToWrite ); } return status; } // ********** private functions ********** 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; } static BOOL writeFlashSectors( U08* data ) { Fapi_FlashStatusWordType writeVerifyReason; Fapi_StatusType writeVerifyStatus; U08 removeThis; U08 dataRead2Verify[ SW_UPDATE_FLASH_BUFFER_SIZE ]; BOOL status = FALSE; U08 bytesWritten = 0; U32 startAddress = SWUpdateFlashStatus.currentWriteAddress; for ( removeThis = 0; removeThis < SW_UPDATE_FLASH_BUFFER_SIZE; removeThis++ ) { // TODO this is temporary until the ROTTING is removed from the APP data[ removeThis ] = 0xFF & ( data[removeThis] - 27 ); } memcpy( dataRead2Verify, data, SW_UPDATE_FLASH_BUFFER_SIZE ); 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 ); 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 ); status = ( Fapi_Status_Success == writeVerifyStatus ? TRUE : FALSE ); return status; }