Index: firmware/App/Services/FPGA.c =================================================================== diff -u -rf760ffc4b10556e5186e9ceb90294262063440ca -r0d115952bc81497cb5f8fcf37f361521fad610b3 --- firmware/App/Services/FPGA.c (.../FPGA.c) (revision f760ffc4b10556e5186e9ceb90294262063440ca) +++ firmware/App/Services/FPGA.c (.../FPGA.c) (revision 0d115952bc81497cb5f8fcf37f361521fad610b3) @@ -44,8 +44,6 @@ FPGA_STATE_RCV_HEADER, ///< Receive header state for the FPGA. FPGA_STATE_WRITE_ALL_ACTUATORS, ///< Write actuators command state for the FPGA. FPGA_STATE_RCV_ALL_SENSORS, ///< Receive sensors state for the FPGA. - FPGA_STATE_READ_ALL_SENSORS_ASYNC, ///< Read async sensors state for the FPGA. - FPGA_STATE_RCV_ALL_SENSORS_ASYNC, ///< Receive async sensors state for the FPGA. FPGA_STATE_FAILED, ///< Failed state for the FPGA. NUM_OF_FPGA_STATES ///< Number of FPGA states. } FPGA_STATE_T; @@ -56,7 +54,6 @@ #define FPGA_HEADER_START_ADDR 0x0000 ///< Start address for FPGA header data. #define FPGA_BULK_READ_START_ADDR 0x0100 ///< Start address for FPGA continuous priority reads. #define FPGA_BULK_WRITE_START_ADDR 0x000B ///< Start address for FPGA continuous priority writes. -#define FPGA_BULK_ASYNC_READ_START_ADDR 0x0200 ///< Start address for FPGA async reads. #define FPGA_WRITE_CMD_BUFFER_LEN (FPGA_PAGE_SIZE+8) ///< FPGA write command buffer byte length. #define FPGA_READ_CMD_BUFFER_LEN 8 ///< FPGA read command buffer byte length. @@ -78,8 +75,6 @@ #define SCI2_RECEIVE_DMA_REQUEST 28 ///< Serial port 2 receive DMA request line. #define SCI2_TRANSMIT_DMA_REQUEST 29 ///< Serial port 2 transmit DMA request line. -#define MAX_COMM_ERROR_RETRIES 10 ///< Maximum consecutive FPGA communication error retries. - #define FPGA_INPUT_VOLTAGE_SCALE 3.0F ///< FPGA source and aux voltage. #define FPGA_PVN_VOLTAGE_SCALE 1.0F ///< FPGA pvn voltage. @@ -117,6 +112,10 @@ #define PROCESSOR_FPGA_CLOCK_DIFF_TOLERANCE 1 ///< Tolerance for processor clock speed check against FPGA clock. #define FPGA_VALVES_MIN_PWM_MODE_COUNT 2500 ///< FPGA valves minimum PWM in PWM mode in counts. +#define MAX_FPGA_COMM_FAILURES_WINDOW_MS ( 1 * SEC_PER_MIN * MS_PER_SECOND ) ///< FPGA comm failures window +#define MAX_FPGA_COMM_FAILURES 3 ///< FPGA maximum comm failures per MAX_FPGA_COMM_FAILURES_WINDOW_MS +#define MIN_POWER_ON_TIME_FOR_COMM_FAILS ( 1 * MS_PER_SECOND ) ///< Allow FPGA comm errors for first second after power-up + // FPGA Sensors Record #pragma pack(push,1) /// Record structure for FPGA header read. @@ -127,17 +126,12 @@ U08 fpgaRevMajor; ///< Reg 2. FPGA revision (major) being reported. U08 fpgaRevLab; ///< Reg 3. FPGA revision (lab) being reported. U16 fpgaStatus; ///< Reg 4. FPGA status register. - U08 fpgaDiag; ///< Reg 6. FPGA diagnostic (R/W) register. - U08 adc1Control; ///< Reg 7. ADC1 control register. Bit 0=auto read enable. - U08 flowDAQ1Cmd; ///< Reg 8. Command passed to flow DAQ #1. - U08 flowDAQ2Cmd; ///< Reg 9. Command passed to flow DAQ #2. - U08 accelCmd; ///< Reg 10. Command passed to accelerometer. } FPGA_HEADER_T; // Read only on FPGA /// Record structure for FPGA continuous priority reads. typedef struct { - U08 errorCountProcessor; ///< Reg 256. TBD. + U08 errorCountProcessor; ///< Reg 256. Error count for processor communications U08 errorCountPC; ///< Reg 257. TBD. U08 fpgaHWConfigReg; ///< Reg 258. Hardware configuration register (i.e. BETA or DVT) U08 sPumpDACRdStatus; ///< Reg 259. Syringe pump DAC read status. @@ -273,39 +267,13 @@ U08 bloodLeakUARTControl; ///< Reg 43. Blood leak UART control. U08 bloodLeakFIFOTransmit; ///< Reg 44. Character word store in FIFO to be transmitted into blood leak UART interface. } FPGA_ACTUATORS_T; - -// TODO clean up the struct -/// Record structure for FPGA async (as needed) reads. -typedef struct -{ - U16 fpgaDieTemp; ///< Reg 512. Internal FPGA die temperature. - U16 fpgaADCVccVoltage; ///< Reg 514. Internal FPGA Vcc voltage. - U16 fpgaADCVccAuxVoltage; ///< Reg 516. Internal FPGA Vcc aux voltage. - U16 fpgaADCVpvnVoltage; ///< Reg 518. Internal FPGA VPVN voltage. - U16 fpgaVAux0Voltage; ///< Reg 520. Aux. voltage 0. - U16 fpgaVAux1Voltage; ///< Reg 522. Aux. voltage 1. - U16 fpgaVAux2Voltage; ///< Reg 524. Aux. voltage 2. - U16 fpgaVAux3Voltage; ///< Reg 526. Aux. voltage 3. - U16 fpgaVAux8Voltage; ///< Reg 528. Aux. voltage 8. - U16 fpgaVAux9Voltage; ///< Reg 530. Aux. voltage 9. - U16 fpgaVAux10Voltage; ///< Reg 532. Aux. voltage 10. - U16 fpgaVAux11Voltage; ///< Reg 534. Aux. voltage 11. - F32 bloodFlowSoundSpeed; ///< Reg 536. Blood flow sound speed. - F32 bloodFlowAccFlow; ///< Reg 540. Blood flow accumulated flow. - F32 reserved15; ///< Reg 544. Reserved. - F32 dialysateInFlowSoundSpeed; ///< Reg 548. Dialysate inlet flow sound speed. - F32 dialysateInFlowAccFlow; ///< Reg 552. Dialysate inlet flow accumulated flow. - F32 dialysateInFlowSignalStrength; ///< Reg 556. Dialysate inlet flow signal strength. - U16 fpgaVAux5Voltage; ///< Reg 560. Aux. voltage 5. -} FPGA_SENSORS_ASYNC_T; #pragma pack(pop) // ********** private data ********** // FPGA state static FPGA_STATE_T fpgaState = FPGA_STATE_START; ///< Current FPGA state. -static U32 fpgaCommRetryCount = 0; ///< FPGA communication retry counter. static U32 fpgaReceiptCounter = 0; ///< FPGA response receipt counter. static U32 fpgaTransmitCounter = 0; ///< FPGA command transmit counter. static BOOL fpgaWriteCommandInProgress = FALSE; ///< Flag indicating an FPGA write command is in progress. @@ -330,12 +298,8 @@ static FPGA_HEADER_T fpgaHeader; ///< Record of last received FPGA header data. static FPGA_SENSORS_T fpgaSensorReadings; ///< Record of last received FPGA priority sensor data. static FPGA_ACTUATORS_T fpgaActuatorSetPoints; ///< Record of next transmitted FPGA priority actuator data. +static U08 fpgaReadByteSize; ///< FPGA read byte size. -#ifndef DEBUG_ENABLED -static U16 currentFPGATimerCount_ms; ///< Current FPGA timer count in ms. -static U32 currentTimerCount_ms; ///< Current processor timer count in ms. -#endif - // ********** private function prototypes ********** static FPGA_STATE_T handleFPGAReadHeaderState( void ); @@ -355,6 +319,7 @@ static void consumeUnexpectedData( void ); static void monitorFPGAPowerStatus( void ); +static BOOL checkFPGACommFailure( void ); /*********************************************************************//** * @brief @@ -471,6 +436,10 @@ // There should not be any data pending yet consumeUnexpectedData(); + + // initialize FPGA comm failures windowed timer count + initTimeWindowedCount( TIME_WINDOWED_COUNT_FPGA_COMM_FAILURES, MAX_FPGA_COMM_FAILURES, MAX_FPGA_COMM_FAILURES_WINDOW_MS); + } /*********************************************************************//** @@ -579,17 +548,6 @@ break; } - // If retries for commands exceeds limit, fault - if ( ( fpgaCommRetryCount > MAX_COMM_ERROR_RETRIES ) -#ifdef _RELEASE_ - || ( fpgaSensorReadings.errorCountProcessor > MAX_COMM_ERROR_RETRIES ) ) -#else - ) -#endif - { - SET_ALARM_WITH_2_U32_DATA( ALARM_ID_HD_FPGA_COMM_TIMEOUT, fpgaCommRetryCount, (U32)fpgaSensorReadings.errorCountProcessor ) - } - // Reset comm flags after processing incoming responses resetFPGACommFlags(); @@ -690,24 +648,23 @@ // Does the FPGA response CRC check out? if ( crc == crc16( fpgaReadResponseBuffer, rspSize ) ) { - fpgaCommRetryCount = 0; // Capture the read values memcpy( &fpgaHeader, &fpgaReadResponseBuffer[ FPGA_READ_RSP_HDR_LEN ], sizeof( FPGA_HEADER_T ) ); result = FPGA_STATE_WRITE_ALL_ACTUATORS; } else { - fpgaCommRetryCount++; + checkFPGACommFailure(); } } else // Header read was NAK'd { - fpgaCommRetryCount++; + checkFPGACommFailure(); } } else // No response to read command { - fpgaCommRetryCount++; + checkFPGACommFailure(); } // Should not be any data received at this time @@ -751,9 +708,11 @@ // Prep DMA for sending the bulk write cmd and receiving its response setupDMAForWriteCmd( FPGA_WRITE_CMD_HDR_LEN + sizeof( FPGA_ACTUATORS_T ) + FPGA_CRC_LEN ); setupDMAForWriteResp( FPGA_WRITE_RSP_HDR_LEN + FPGA_CRC_LEN ); + // Prep DMA for sending the bulk read cmd and receiving its response setupDMAForReadCmd( FPGA_READ_CMD_HDR_LEN + FPGA_CRC_LEN ); setupDMAForReadResp( FPGA_READ_RSP_HDR_LEN + sizeof( FPGA_SENSORS_T ) + FPGA_CRC_LEN ); + // Set fpga comm flags for bulk write cmd and follow-up bulk read command fpgaWriteCommandInProgress = TRUE; fpgaBulkWriteAndReadInProgress = TRUE; @@ -776,46 +735,78 @@ { FPGA_STATE_T result = FPGA_STATE_WRITE_ALL_ACTUATORS; - // Check bulk write command success - if ( ( FALSE == fpgaWriteCommandResponseReceived ) || ( fpgaWriteResponseBuffer[ 0 ] != FPGA_WRITE_CMD_ACK ) ) + // check bulk write command success + if ( TRUE == fpgaWriteCommandResponseReceived ) { - fpgaCommRetryCount++; + // The write command completed so check for validity + if ( fpgaWriteResponseBuffer[ 0 ] == FPGA_WRITE_CMD_ACK) + { + // Message is an ack - check CRC + 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 ) ) + { + // CRC failed + checkFPGACommFailure(); + } + } + else + { + // Not an ACK + checkFPGACommFailure(); + } } + else + { + // Timeout - communication error + checkFPGACommFailure(); + } - // If bulk read command is ACK'd, collect the readings - if ( TRUE == fpgaReadCommandResponseReceived ) + /* If the write command response (ACK) was not received, the read response + * was not issued. If this is the case the read response will also + * timeout. For FPGA V&V testing this will cause two timeouts to occur. + * The V&V expectation is that when the timeout test is executed a + * single timeout will occur. + */ + if ( TRUE == fpgaWriteCommandResponseReceived ) { - // Did FPGA Ack the read command? - if ( fpgaReadResponseBuffer[ 0 ] == FPGA_READ_CMD_ACK ) + // if bulk read command is ACK'd, collect the readings + if ( TRUE == fpgaReadCommandResponseReceived ) { - U32 rspSize = FPGA_READ_RSP_HDR_LEN + sizeof(FPGA_SENSORS_T); - U32 crcPos = rspSize; - U16 crc = MAKE_WORD_OF_BYTES( fpgaReadResponseBuffer[ crcPos ], fpgaReadResponseBuffer[ crcPos + 1 ] ); - - // Does the FPGA response CRC check out? - if ( crc == crc16( fpgaReadResponseBuffer, rspSize ) ) + // did FPGA ACK the read command? + if ( fpgaReadResponseBuffer[ 0 ] == FPGA_READ_CMD_ACK ) { - fpgaCommRetryCount = 0; - // Capture the read values - memcpy( &fpgaSensorReadings, &fpgaReadResponseBuffer[ FPGA_READ_RSP_HDR_LEN ], sizeof( FPGA_SENSORS_T ) ); - result = FPGA_STATE_WRITE_ALL_ACTUATORS; + U32 rspSize = FPGA_READ_RSP_HDR_LEN + fpgaReadByteSize; + U32 crcPos = rspSize; + U16 crc = MAKE_WORD_OF_BYTES( fpgaReadResponseBuffer[ crcPos ], fpgaReadResponseBuffer[ crcPos + 1 ] ); + + // does the FPGA response CRC check out? + if ( crc == crc16( fpgaReadResponseBuffer, rspSize ) ) + { + // capture the read values + memcpy( &fpgaSensorReadings, &fpgaReadResponseBuffer[ FPGA_READ_RSP_HDR_LEN ], fpgaReadByteSize ); + result = FPGA_STATE_WRITE_ALL_ACTUATORS; + } + else // bad CRC + { + checkFPGACommFailure(); + } } - else // Bad CRC + else // read command was NAK'd { - fpgaCommRetryCount++; + checkFPGACommFailure(); } } - else // Read command was NAK'd + else // no response to read command { - fpgaCommRetryCount++; + checkFPGACommFailure(); } } - else // No response to read command - { - fpgaCommRetryCount++; - } - // Should not be any data received at this time + // There should not be any data received at this time consumeUnexpectedData(); return result; @@ -865,26 +856,34 @@ *************************************************************************/ void execFPGAClockSpeedTest( void ) { -#ifndef DEBUG_ENABLED + /* DEBUG WARNING + * It may be necessary to comment out the following + * code to prevent the alarm from occurring while + * debugging. + */ + + static U16 currentFPGATimerCount_ms = 0; + static U32 currentTimerCount_ms = 0; + U16 const newFPGATimerCount_ms = getFPGATimerCount(); - U32 const newTimerCount_ms = getMSTimerCount(); - U32 const diffFPGATimerCount = (U32)u16DiffWithWrap( currentFPGATimerCount_ms, newFPGATimerCount_ms ); - U32 const diffTimerCount = u32DiffWithWrap( currentTimerCount_ms, newTimerCount_ms ); + U32 const newTimerCount_ms = getMSTimerCount(); + U32 const diffFPGATimerCount = (U32)u16DiffWithWrap( currentFPGATimerCount_ms, newFPGATimerCount_ms ); + U32 const diffTimerCount = u32DiffWithWrap( currentTimerCount_ms, newTimerCount_ms ); - if ( getCurrentOperationMode() != MODE_INIT ) + if ( getCurrentOperationMode() != DG_MODE_INIT ) { if ( abs( diffFPGATimerCount - diffTimerCount ) > PROCESSOR_FPGA_CLOCK_DIFF_TOLERANCE ) { if ( TRUE == incTimeWindowedCount( TIME_WINDOWED_COUNT_FPGA_CLOCK_SPEED_ERROR ) ) { - SET_ALARM_WITH_2_U32_DATA( ALARM_ID_HD_FPGA_CLOCK_SPEED_CHECK_FAILURE, diffFPGATimerCount, diffTimerCount ); + SET_ALARM_WITH_2_U32_DATA( ALARM_ID_DG_FPGA_CLOCK_SPEED_CHECK_FAILURE, diffFPGATimerCount, diffTimerCount ); } } } currentFPGATimerCount_ms = newFPGATimerCount_ms; - currentTimerCount_ms = newTimerCount_ms; -#endif + currentTimerCount_ms = newTimerCount_ms; + } /*********************************************************************//** @@ -2324,4 +2323,30 @@ } #endif +/*********************************************************************//** + * @brief + * The checkFPGACommFailure function increments the FPGA comm failure + * windowed timer and returns whether or not the number of failures in + * the window have been reached. + * @details Inputs: none + * @details Outputs: none + * @return TRUE if windowed count exceeded, else false. + *************************************************************************/ +static BOOL checkFPGACommFailure( void ) +{ + BOOL status = false; + + if ( getMSTimerCount() > MIN_POWER_ON_TIME_FOR_COMM_FAILS ) + { + if ( TRUE == incTimeWindowedCount( TIME_WINDOWED_COUNT_FPGA_COMM_FAILURES ) ) + { + SET_ALARM_WITH_2_U32_DATA( ALARM_ID_HD_FPGA_COMM_TIMEOUT, MAX_FPGA_COMM_FAILURES, (U32)fpgaSensorReadings.errorCountProcessor ) + status = TRUE; + } + } + + return status; + +} + /**@}*/