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; }