Index: firmware/App/Modes/ModeStandby.c =================================================================== diff -u -r621896c8a4cc9204a12a7243ccef729c37e50c52 -r2823873d5790228595fb991e52e78e2fd0d5987c --- firmware/App/Modes/ModeStandby.c (.../ModeStandby.c) (revision 621896c8a4cc9204a12a7243ccef729c37e50c52) +++ firmware/App/Modes/ModeStandby.c (.../ModeStandby.c) (revision 2823873d5790228595fb991e52e78e2fd0d5987c) @@ -19,7 +19,7 @@ // ********** private definitions ********** -#define WAIT_FOR_UPDATE_FROM_UI_MS 1000 // TODO make this 3 seconds ///< Wait for update timeout in milliseconds. +#define WAIT_FOR_UPDATE_FROM_UI_MS 2000 ///< Wait for update timeout in milliseconds. // ********** private data ********** Index: firmware/App/Services/Download.c =================================================================== diff -u -r621896c8a4cc9204a12a7243ccef729c37e50c52 -r2823873d5790228595fb991e52e78e2fd0d5987c --- firmware/App/Services/Download.c (.../Download.c) (revision 621896c8a4cc9204a12a7243ccef729c37e50c52) +++ firmware/App/Services/Download.c (.../Download.c) (revision 2823873d5790228595fb991e52e78e2fd0d5987c) @@ -215,9 +215,6 @@ { if ( TRUE == isMessageComplete( mailBox ) ) { - // If the command buffer has been received, get it from the comm buffer and process it - //SW_UPDATE_CMD_STATUS_T SWUpdateCmdStatus; - getCommBuffer( mailBox, (U08*)&SWUpdateCmdStatus, sizeof( SW_UPDATE_CMD_STATUS_T ) ); BOOL hasCRCPassed = FALSE; Index: firmware/App/Services/FPGA.c =================================================================== diff -u -r621896c8a4cc9204a12a7243ccef729c37e50c52 -r2823873d5790228595fb991e52e78e2fd0d5987c --- firmware/App/Services/FPGA.c (.../FPGA.c) (revision 621896c8a4cc9204a12a7243ccef729c37e50c52) +++ firmware/App/Services/FPGA.c (.../FPGA.c) (revision 2823873d5790228595fb991e52e78e2fd0d5987c) @@ -67,6 +67,8 @@ #define FPGA_FIFO_COUNT_MASK 0x03FF ///< FPGA FIFO count in FIFO mask. #define FPGA_INIT_STAGE_TIMEOUT_MS 6000 ///< FPGA initialization stage timeout in milliseconds. #define FPGA_PRE_SELF_CONFIG_TIMEOUT_MS 10000 ///< FPGA pre self configure timeout in milliseconds. +#define FPGA_SELF_CONFIG_TIMEOUT_MS 10000 ///< FPGA self configure timeout in milliseconds. +#define FPGA_OPS_TIMEOUT_MS 40 ///< FPGA operations (read/write) timeout in milliseconds. /// FPGA communication status enumeration typedef enum @@ -87,6 +89,8 @@ FPGA_UPDATE_STAGE_UPDATE, ///< FPGA update stage update. FPGA_UPDATE_STAGE_PREPARE_FOR_SELF_CONFIGURE, ///< FPGA update stage prepare for self configure. FPGA_UPDATE_STAGE_SELF_CONFIGURE, ///< FPGA update stage self configure. + FPGA_UPDATE_STAGE_UPDATE_COMPLETE, ///< FPGA update stage update is complete. + FPGA_UPDATE_STAGE_UPDATE_FAILED, ///< FPGA update stage update failed. NUM_OF_FPGA_UPDATE_STAGES ///< Number of FPGA update stages. } FPGA_UPDATE_STAGE_T; @@ -120,6 +124,7 @@ U16 fpgaJobAddress; ///< FPGA job address. U16 fpgaJobSize; ///< FPGA job size. BOOL fpgaIsJobWrite; ///< FPGA boolean flag to indicate this is a write job or not. + BOOL fpgaSendAckNackImmediately; ///< FPGA send ack/nack immediately. U08* fpgaWriteStartAddress; ///< FPGA write buffer start address. } FPGA_JOB_SPECS_T; @@ -209,17 +214,17 @@ /// FPGA jobs specifications. static const FPGA_JOB_SPECS_T JOBS_SPECS[ NUM_OF_FPGA_JOBS ] = { - { FPGA_HEADER_START_ADDR, sizeof( FPGA_HEADER_T ), FALSE, (U08*)&DUMMY_WRITE_ADDR_IN_READ_STRUCT, }, // FPGA_READ_HEADER + { FPGA_HEADER_START_ADDR, sizeof( FPGA_HEADER_T ), FALSE, FALSE, (U08*)&DUMMY_WRITE_ADDR_IN_READ_STRUCT, }, // FPGA_READ_HEADER - { FPGA_FLASH_CONTROL_REG_ADDR, sizeof( U08 ), TRUE , (U08*)&FPGA_RESET_FLASH_CMD, }, // FPGA_RESET_FLASH + { FPGA_FLASH_CONTROL_REG_ADDR, sizeof( U08 ), TRUE , FALSE, (U08*)&FPGA_RESET_FLASH_CMD, }, // FPGA_RESET_FLASH - { FPGA_FLASH_CONTROL_REG_ADDR, sizeof( U08 ), TRUE , (U08*)&FPGA_ERASE_FIFO_CMD, }, // FPGA_ERASE_FIFO - { FPGA_FLASH_CONTROL_REG_ADDR, sizeof( U08 ), TRUE , (U08*)&FPGA_ENABLE_FLASH_CMD, }, // FPGA_ENABLE_FLASH + { FPGA_FLASH_CONTROL_REG_ADDR, sizeof( U08 ), TRUE , FALSE, (U08*)&FPGA_ERASE_FIFO_CMD, }, // FPGA_ERASE_FIFO + { FPGA_FLASH_CONTROL_REG_ADDR, sizeof( U08 ), TRUE , FALSE, (U08*)&FPGA_ENABLE_FLASH_CMD, }, // FPGA_ENABLE_FLASH - { FPGA_MULTI_BOOT_STATUS_ADDR, sizeof( FPGA_READ_REGS_T ), FALSE, (U08*)&DUMMY_WRITE_ADDR_IN_READ_STRUCT, }, // FPGA_READ_MULTI_BOOT_STATUS + { FPGA_MULTI_BOOT_STATUS_ADDR, sizeof( FPGA_READ_REGS_T ), FALSE, FALSE, (U08*)&DUMMY_WRITE_ADDR_IN_READ_STRUCT, }, // FPGA_READ_MULTI_BOOT_STATUS - { FPGA_FLASH_DATA_REG_ADDR, SW_UPDATE_FLASH_BUFFER_SIZE, TRUE , (U08*)&fpgaDataToWriteBuffer, }, // FPGA_FLASH_WRITE_DATA - { FPGA_ICAPE2_REG_ADDR, sizeof( U08 ), TRUE , (U08*)&FPGA_SELF_CONFIG_CMD, } // FPGA_SELF_CONFIGURE + { FPGA_FLASH_DATA_REG_ADDR, SW_UPDATE_FLASH_BUFFER_SIZE, TRUE , TRUE , (U08*)&fpgaDataToWriteBuffer, }, // FPGA_FLASH_WRITE_DATA + { FPGA_ICAPE2_REG_ADDR, sizeof( U08 ), TRUE , FALSE, (U08*)&FPGA_SELF_CONFIG_CMD, } // FPGA_SELF_CONFIGURE }; // ********** private function prototypes ********** @@ -229,6 +234,7 @@ static void processFPGAFlashRegistersRead( void ); static void processFPGAUpdateInitStatus( void ); static void processFPGAPrepareForSelfConfigureStatus( void ); +static void processFPGACheckSelfConfigureStatus( void ); static void setupDMAForReadResp( U32 bytes2Receive ); static void setupDMAForReadCmd( U32 bytes2Transmit ); @@ -354,6 +360,7 @@ *************************************************************************/ BOOL isFPGAIDValid( void ) { + // TODO do we still need to check the FPGA ID? //BOOL status = ( STACK_FPGA_ID[ BL_STACK_ID ] == fpgaHeader.fpgaId ? TRUE : FALSE ); BOOL status = FALSE; @@ -371,9 +378,9 @@ *************************************************************************/ BOOL isFPGAFlashComplete( void ) { - //return fpgaFlashStatus.isFPGAFlashComplete; // TODO clean this up + BOOL status = ( FPGA_UPDATE_STAGE_UPDATE_COMPLETE == fpgaFlashStatus.fpgaUpdateStage ? TRUE : FALSE ); - return TRUE; + return status; } /*********************************************************************//** @@ -631,14 +638,51 @@ { if ( FALSE == isQueueFull() ) { - fpgaFlashStatus.fpgaUpdateStage = FPGA_UPDATE_STAGE_SELF_CONFIGURE; + fpgaFlashStatus.fpgaUpdateStage = FPGA_UPDATE_STAGE_SELF_CONFIGURE; + fpgaFlashStatus.fpgaUpdateCmdStartTimeMS = getMSTimerCount(); enqueue( FPGA_SELF_CONFIGURE ); } } } /*********************************************************************//** * @brief + * The processFPGACheckSelfConfigureStatus function checks for the status + * of the self configure. + * @details \b Inputs: fpgaFlashStatus + * @details \b Outputs: fpgaFlashStatus + * @return none + *************************************************************************/ +static void processFPGACheckSelfConfigureStatus( void ) +{ + ACK_NACK_STATUS_T ackStatus = NACK; + BOOL status = FALSE; + + // TODO once FPGA is updated check bits 12 and 13. + if ( fpgaFlashStatus.fpgaInitStatus != 0 ) + { + fpgaFlashStatus.fpgaUpdateStage = FPGA_UPDATE_STAGE_UPDATE_COMPLETE; + ackStatus = ACK; + status = TRUE; + // Once the self configure is complete and successful request a header read + enqueue( FPGA_READ_HEADER ); + } + + if ( TRUE == didTimeout( fpgaFlashStatus.fpgaUpdateCmdStartTimeMS, FPGA_SELF_CONFIG_TIMEOUT_MS ) ) + { + // Timeout and FPGA is not responsive + fpgaFlashStatus.fpgaUpdateStage = FPGA_UPDATE_STAGE_UPDATE_FAILED; + status = TRUE; + } + + if ( TRUE == status ) + { + sendFPGAAckNackStatus( ackStatus, FALSE ); + } +} + +/*********************************************************************//** + * @brief * The setupDMAForReadResp function sets the expected byte count for the * next DMA read command response from the FPGA. * @details \b Inputs: none @@ -897,11 +941,16 @@ processFPGAPrepareForSelfConfigureStatus(); break; + case FPGA_UPDATE_STAGE_SELF_CONFIGURE: + processFPGACheckSelfConfigureStatus(); + break; + default: // Do nothing for the rest of the commands break; } + // Keep updating the operations start to prevent a read or write getting stuck fpgaFlashStatus.fpgaReadWriteOpsStartTimeMS = getMSTimerCount(); if ( fpgaJobsQStatus.fpgaJobsQueueCount > 0 ) @@ -938,19 +987,47 @@ U16 firstCRCIndex = 0; U16 secondCRCIndex = 0; - if ( FPGA_FLASH_WRITE_DATA == fpgaJobsQStatus.fpgaCurrentJob ) + switch ( fpgaJobsQStatus.fpgaCurrentJob ) { - // Set the write length from the buffer length provided - jobSize = (U16)fpgaDataLenToWrite; - } + case FPGA_FLASH_WRITE_DATA: + // Set the write length from the buffer length provided + jobSize = (U16)fpgaDataLenToWrite; + break; - if ( FPGA_SELF_CONFIGURE == fpgaJobsQStatus.fpgaCurrentJob ) - { - // Once self configure is sent the FPGA will be unresponsive so there will be no ack back - // Signal FPGA is completed - state = FPGA_IDLE_STATE; + case FPGA_SELF_CONFIGURE: + // Clear the read memories when the self configure command is sent. Clear the multi boot status. This is to make sure that once the FPGA is + // back from self configuring, it the read data is non-zero + memset( &fpgaReadResponseBuffer, 0x0, FPGA_READ_RSP_BUFFER_LEN ); + memcpy( &fpgaReadRegsStatus, &fpgaReadResponseBuffer[ FPGA_READ_RSP_HDR_LEN ], JOBS_SPECS[ FPGA_READ_MULTI_BOOT_STATUS ].fpgaJobSize ); + processFPGAFlashRegistersRead(); + + // Once self configure is sent the FPGA will be unresponsive so there will be no ack back + state = FPGA_IDLE_STATE; + break; + + default: + // Do nothing + break; } + + //if ( FPGA_FLASH_WRITE_DATA == fpgaJobsQStatus.fpgaCurrentJob ) + //{ + // // Set the write length from the buffer length provided + // jobSize = (U16)fpgaDataLenToWrite; + //} + // + //if ( FPGA_SELF_CONFIGURE == fpgaJobsQStatus.fpgaCurrentJob ) + //{ + // // TODO remove? + // memset( &fpgaReadResponseBuffer, 0x0, FPGA_READ_RSP_BUFFER_LEN ); + // memcpy( &fpgaReadRegsStatus, &fpgaReadResponseBuffer[ FPGA_READ_RSP_HDR_LEN ], JOBS_SPECS[ FPGA_READ_MULTI_BOOT_STATUS ].fpgaJobSize ); + // processFPGAFlashRegistersRead(); + // + // // Once self configure is sent the FPGA will be unresponsive so there will be no ack back + // state = FPGA_IDLE_STATE; + //} + firstCRCIndex = FPGA_WRITE_CMD_HDR_LEN + jobSize; secondCRCIndex = FPGA_WRITE_CMD_HDR_LEN + jobSize + 1; @@ -995,40 +1072,48 @@ *************************************************************************/ static FPGA_STATE_T handleFPGAReceiveWriteRespFromFPGAState( void ) { - FPGA_STATE_T state = FPGA_RCV_WRITE_RESP_FROM_FPGA_STATE; + FPGA_STATE_T state = FPGA_RCV_WRITE_RESP_FROM_FPGA_STATE; + ACK_NACK_STATUS_T ackStatus = NACK; if ( FPGA_COMM_WRITE_RESP_RECEIVED == fpgaJobsQStatus.fpgaCommWrite ) { if ( FPGA_WRITE_CMD_ACK == fpgaWriteResponseBuffer[ 0 ] ) { // Message is an ack - check CRC - ACK_NACK_STATUS_T ackStatus = NACK; - U32 rspSize = FPGA_READ_RSP_HDR_LEN; - U32 crcPos = rspSize; - U16 crc = MAKE_WORD_OF_BYTES( fpgaWriteResponseBuffer[ crcPos ], fpgaWriteResponseBuffer[ crcPos + 1 ] ); + U32 rspSize = FPGA_READ_RSP_HDR_LEN; + U32 crcPos = rspSize; + U16 crc = MAKE_WORD_OF_BYTES( fpgaWriteResponseBuffer[ crcPos ], fpgaWriteResponseBuffer[ crcPos + 1 ] ); // Does the FPGA response CRC checkout? if ( crc == crc16( fpgaWriteResponseBuffer, rspSize ) ) { - if ( FPGA_FLASH_WRITE_DATA == fpgaJobsQStatus.fpgaCurrentJob ) - { - ackStatus = ACK; - } + ackStatus = ACK; if ( FPGA_ENABLE_FLASH == fpgaJobsQStatus.fpgaCurrentJob ) { + // Enable flash is the last command of the prepare sequence. Once the enable flash went through and got the ack back, start the timer. fpgaFlashStatus.fpgaUpdateStage = FPGA_UPDATE_STAGE_CHECK_UPDATE_INIT; fpgaFlashStatus.fpgaUpdateCmdStartTimeMS = getMSTimerCount(); } + } - // CRC passed - state = FPGA_IDLE_STATE; + if ( TRUE == JOBS_SPECS[ fpgaJobsQStatus.fpgaCurrentJob ].fpgaSendAckNackImmediately ) + { + sendFPGAAckNackStatus( ackStatus, TRUE ); } - sendFPGAAckNackStatus( ackStatus, TRUE ); + // Whether CRC passed or failed, transition back to Idle. + // TODO should we try the command one more time? + state = FPGA_IDLE_STATE; } } + if ( TRUE == didTimeout( fpgaFlashStatus.fpgaReadWriteOpsStartTimeMS, FPGA_OPS_TIMEOUT_MS ) ) + { + sendFPGAAckNackStatus( ackStatus, TRUE ); + state = FPGA_IDLE_STATE; + } + return state; } @@ -1089,6 +1174,7 @@ static FPGA_STATE_T handleFPGAReceiveReadRespFromFPGAState( void ) { FPGA_STATE_T state = FPGA_RCV_READ_RESP_FROM_FPGA_STATE; + // If the job is read hear, use the queue job otherwise use the multi-boot status since it is read frequently but it is not scheduled in the queue to speed the update up U08 currentJob = ( FPGA_READ_HEADER == fpgaJobsQStatus.fpgaCurrentJob ? fpgaJobsQStatus.fpgaCurrentJob : FPGA_READ_MULTI_BOOT_STATUS ); U16 jobSize = JOBS_SPECS[ currentJob ].fpgaJobSize; @@ -1119,18 +1205,16 @@ // Do nothing break; } - - memset( &fpgaReadResponseBuffer, 0x0, FPGA_READ_RSP_BUFFER_LEN ); - state = FPGA_IDLE_STATE; } + + // Clear the buffer whether the CRC passed or failed + memset( &fpgaReadResponseBuffer, 0x0, FPGA_READ_RSP_BUFFER_LEN ); + state = FPGA_IDLE_STATE; } } - if ( TRUE == didTimeout( fpgaFlashStatus.fpgaReadWriteOpsStartTimeMS, 40 ) ) + if ( TRUE == didTimeout( fpgaFlashStatus.fpgaReadWriteOpsStartTimeMS, FPGA_OPS_TIMEOUT_MS ) ) { - memset( &fpgaReadResponseBuffer, 0x0, FPGA_READ_RSP_BUFFER_LEN ); - memcpy( &fpgaReadRegsStatus, &fpgaReadResponseBuffer[ FPGA_READ_RSP_HDR_LEN ], jobSize ); - processFPGAFlashRegistersRead(); state = FPGA_IDLE_STATE; } Index: firmware/source/sys_link.cmd =================================================================== diff -u -rf6fd9dfd1a30412e237ff45ebee44854f0e2d4b2 -r2823873d5790228595fb991e52e78e2fd0d5987c --- firmware/source/sys_link.cmd (.../sys_link.cmd) (revision f6fd9dfd1a30412e237ff45ebee44854f0e2d4b2) +++ firmware/source/sys_link.cmd (.../sys_link.cmd) (revision 2823873d5790228595fb991e52e78e2fd0d5987c) @@ -72,6 +72,10 @@ parity_mask = 0x0c /* Set which ECC bits are Even and Odd parity */ mirroring = F021 /* RM57Lx and TMS570LCx are build in F021 */ } +#if 0 +/* NOTE: the default section has been disabled to run crc check of the image + in the user defined section below. +*/ /* USER CODE END */ /*----------------------------------------------------------------------------*/ @@ -90,6 +94,21 @@ /* USER CODE BEGIN (4) */ +#endif +/* Override Sections with CRCs here */ +SECTIONS +{ + .intvecs : {} > VECTORS, crc_table( _crc_table, algorithm=CRC32_C ) + .text : {} > FLASH0, crc_table( _crc_table, algorithm=CRC32_C ) + .const : {} > FLASH0, crc_table( _crc_table, algorithm=CRC32_C ) + .cinit : {} > FLASH0, crc_table( _crc_table, algorithm=CRC32_C ) + .pinit : {} > FLASH0 + .bss : {} > RAM + .data : {} > RAM + .sysmem : {} > RAM + + //.TI.crctab : {} > CRCMEM // TODo uncomment + flashAPI: { NVDataMgmt.obj (.text) Index: firmware/source/sys_main.c =================================================================== diff -u -rf6fd9dfd1a30412e237ff45ebee44854f0e2d4b2 -r2823873d5790228595fb991e52e78e2fd0d5987c --- firmware/source/sys_main.c (.../sys_main.c) (revision f6fd9dfd1a30412e237ff45ebee44854f0e2d4b2) +++ firmware/source/sys_main.c (.../sys_main.c) (revision 2823873d5790228595fb991e52e78e2fd0d5987c) @@ -85,6 +85,7 @@ * https://e2e.ti.com/support/tools/code-composer-studio-group/ccs/f/code-composer-studio-forum/403240/change-load-address-when-debugging-with-tm4c129cnczad * https://e2e.ti.com/support/microcontrollers/arm-based-microcontrollers-group/arm-based-microcontrollers/f/arm-based-microcontrollers-forum/1218850/rm46l852-booting-main-application-from-can-bootloader-results-in-prefetchentry-system-interrupt */ +static void copyFlashAPI2RAM( void ); static void initProcessor( void ); static void initSoftware( void ); static void initTasks( void ); @@ -93,9 +94,7 @@ int main(void) { /* USER CODE BEGIN (3) */ - memcpy(&apiRunStart, &apiLoadStart, (uint32)&apiLoadSize); - - + copyFlashAPI2RAM(); initProcessor(); initSoftware(); initTasks(); @@ -110,6 +109,18 @@ /* USER CODE BEGIN (4) */ /************************************************************************* + * @brief copyFlashAPI2RAM + * The copyFlashAPI2RAM function copies the flash API to RAM. + * @details Inputs: none + * @details Outputs:none + * @return none + *************************************************************************/ +static void copyFlashAPI2RAM( void ) +{ + memcpy( &apiRunStart, &apiLoadStart, (U32)&apiLoadSize ); +} + +/************************************************************************* * @brief initProcessor * The initProcessor function initializes and configures the processor \n * peripherals. Index: firmware/source/sys_startup.c =================================================================== diff -u -rf6fd9dfd1a30412e237ff45ebee44854f0e2d4b2 -r2823873d5790228595fb991e52e78e2fd0d5987c --- firmware/source/sys_startup.c (.../sys_startup.c) (revision f6fd9dfd1a30412e237ff45ebee44854f0e2d4b2) +++ firmware/source/sys_startup.c (.../sys_startup.c) (revision 2823873d5790228595fb991e52e78e2fd0d5987c) @@ -614,12 +614,12 @@ /* USER CODE BEGIN (74) */ // Shuffle IRQ priorities per design requirements - vimChannelMap( 3, 40, &rtiCompare1Interrupt ); - vimChannelMap( 5, 64, &rtiCompare3Interrupt ); - vimChannelMap( 13, 3, &linHighLevelInterrupt ); + vimChannelMap( 3, 40, &rtiCompare1Interrupt ); + vimChannelMap( 5, 64, &rtiCompare3Interrupt ); + vimChannelMap( 13, 3, &linHighLevelInterrupt ); vimChannelMap( 16, 15, &can1HighLevelInterrupt ); vimChannelMap( 29, 13, &can1LowLevelInterrupt ); - vimChannelMap( 40, 5, &dmaBTCAInterrupt ); + vimChannelMap( 40, 5, &dmaBTCAInterrupt ); vimChannelMap( 64, 16, &sciHighLevelInterrupt ); /* USER CODE END */ @@ -629,7 +629,8 @@ /* initialize copy table */ __TI_auto_init(); /* USER CODE BEGIN (75) */ - // _copyAPI2RAM_(); + // NOTE: undefentry or dabort sys_intvecs.asm are triggered. Per debugging flash_run fails. + // _copyAPI2RAM_(); /* USER CODE END */ /* call the application */