Index: firmware/App/Services/FPGA.c =================================================================== diff -u -r83b12013a84403fe4d7d6f70b516d623bfb2fcfd -r7d4711edd7b40cd3e29f43e766f79a8a09586fe9 --- firmware/App/Services/FPGA.c (.../FPGA.c) (revision 83b12013a84403fe4d7d6f70b516d623bfb2fcfd) +++ firmware/App/Services/FPGA.c (.../FPGA.c) (revision 7d4711edd7b40cd3e29f43e766f79a8a09586fe9) @@ -1,15 +1,15 @@ /************************************************************************** * -* Copyright (c) 2019-2023 Diality Inc. - All Rights Reserved. +* Copyright (c) 2019-2024 Diality Inc. - All Rights Reserved. * * THIS CODE MAY NOT BE COPIED OR REPRODUCED IN ANY FORM, IN PART OR IN * WHOLE, WITHOUT THE EXPLICIT PERMISSION OF THE COPYRIGHT OWNER. * * @file FPGA.c * * @author (last) Dara Navaei -* @date (last) 19-Jan-2023 +* @date (last) 26-Sep-2023 * * @author (original) Dara Navaei * @date (original) 05-Nov-2019 @@ -107,8 +107,9 @@ #define PROCESSOR_FPGA_CLOCK_DIFF_TOLERANCE 1 ///< Tolerance for processor clock speed check against FPGA clock. -#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 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 header struct. #pragma pack(push,1) @@ -323,7 +324,7 @@ U16 fpgaDACRegFIn; ///< Reg 126. Debug DAC channel F output U16 fpgaDACRegGIn; ///< Reg 128. Debug DAC channel G output U16 fpgaDACRegHIn; ///< Reg 130. Debug DAC channel H output - U08 fgpaNewCP2Control; ///< Reg 132. Concentrate pump 2 control + U08 fpgaNewCP2Control; ///< Reg 132. Concentrate pump 2 control U08 fpgaNewCP1Control; ///< Reg 133. Concentrate pump 1 control } FPGA_ACTUATORS_T; #pragma pack(pop) @@ -355,11 +356,6 @@ static FPGA_HEADER_T fpgaHeader; ///< FPGA header structure. static DG_FPGA_SENSORS_T fpgaSensorReadings; ///< DG FPGA sensors structure. static FPGA_ACTUATORS_T fpgaActuatorSetPoints; ///< FPGA actuator set points structure. -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 ********** @@ -379,9 +375,9 @@ static void startDMAReceiptOfReadResp( void ); static void consumeUnexpectedData( void ); -static void monitorFPGAPowerStatus( void ); static BOOL checkFPGACommFailure( void ); +static BOOL checkFPGAFEOEFailure( void ); /*********************************************************************//** * @brief @@ -499,9 +495,6 @@ // there shouldn't be any data pending yet consumeUnexpectedData(); - // Initialize the persistent alarm for FPGA power out - initPersistentAlarm( ALARM_ID_DG_FPGA_POWER_OUT_TIMEOUT, FPGA_POWER_OUT_TIMEOUT_MS, FPGA_POWER_OUT_TIMEOUT_MS ); - // initialize FPGA clock speed error time windowed count initTimeWindowedCount( TIME_WINDOWED_COUNT_FPGA_COMM_FAILURES, MAX_FPGA_COMM_FAILURES, MAX_FPGA_COMM_FAILURES_WINDOW_MS); @@ -581,7 +574,8 @@ *************************************************************************/ void execFPGAIn( void ) { - fpgaReadByteSize = sizeof( DG_FPGA_SENSORS_T ); + // Check if FE or OE error has occurred + checkFPGAFEOEFailure(); // FPGA incoming state machine switch ( fpgaState ) @@ -614,19 +608,9 @@ break; } - // if retries for commands exceeds limit or FPGA reports comm error, fault -#ifdef _RELEASE_ - if ( fpgaSensorReadings.fpgaIOErrorCntProcessor > MAX_COMM_ERROR_RETRIES ) - { - SET_ALARM_WITH_2_U32_DATA( ALARM_ID_DG_FPGA_COMM_TIMEOUT, MAX_FPGA_COMM_FAILURES, (U32)fpgaSensorReadings.fpgaIOErrorCntProcessor ) - } -#endif - // reset comm flags after processing incoming responses resetFPGACommFlags(); - // Check the FPGA power status - monitorFPGAPowerStatus(); } /*********************************************************************//** @@ -638,8 +622,6 @@ *************************************************************************/ void execFPGAOut( void ) { - fpgaReadByteSize = sizeof( DG_FPGA_SENSORS_T ); - // FPGA outgoing state machine switch ( fpgaState ) { @@ -774,15 +756,15 @@ // reset one-time sets after actuator set points xmit message created fpgaActuatorSetPoints.fpgaNewCP1Control &= ~FPGA_CONC_PUMP_PARK_COMMAND; // clear concentrate pump park command bits - fpgaActuatorSetPoints.fgpaNewCP2Control &= ~FPGA_CONC_PUMP_PARK_COMMAND; + fpgaActuatorSetPoints.fpgaNewCP2Control &= ~FPGA_CONC_PUMP_PARK_COMMAND; fpgaActuatorSetPoints.fpgaCP1Control &= ~FPGA_CONC_PUMP_PARK_COMMAND; fpgaActuatorSetPoints.fpgaCP2Control &= ~FPGA_CONC_PUMP_PARK_COMMAND; // construct bulk read command to read sensor data registers starting at address 8 fpgaReadCmdBuffer[ 0 ] = FPGA_READ_CMD_CODE; fpgaReadCmdBuffer[ 1 ] = GET_LSB_OF_WORD( FPGA_BULK_READ_START_ADDR ); fpgaReadCmdBuffer[ 2 ] = GET_MSB_OF_WORD( FPGA_BULK_READ_START_ADDR ); - fpgaReadCmdBuffer[ 3 ] = fpgaReadByteSize; + fpgaReadCmdBuffer[ 3 ] = sizeof( DG_FPGA_SENSORS_T ); crc = crc16( fpgaReadCmdBuffer, FPGA_READ_CMD_HDR_LEN ); fpgaReadCmdBuffer[ 4 ] = GET_MSB_OF_WORD( crc ); fpgaReadCmdBuffer[ 5 ] = GET_LSB_OF_WORD( crc ); @@ -793,7 +775,7 @@ // 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 + fpgaReadByteSize + FPGA_CRC_LEN ); + setupDMAForReadResp( FPGA_READ_RSP_HDR_LEN + sizeof( DG_FPGA_SENSORS_T ) + FPGA_CRC_LEN ); // set fpga comm flags for bulk write cmd and follow-up bulk read command fpgaWriteCommandInProgress = TRUE; @@ -861,15 +843,15 @@ // did FPGA ACK the read command? if ( fpgaReadResponseBuffer[ 0 ] == FPGA_READ_CMD_ACK ) { - U32 rspSize = FPGA_READ_RSP_HDR_LEN + fpgaReadByteSize; + U32 rspSize = FPGA_READ_RSP_HDR_LEN + sizeof( DG_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 ) ) { // capture the read values - memcpy( &fpgaSensorReadings, &fpgaReadResponseBuffer[ FPGA_READ_RSP_HDR_LEN ], fpgaReadByteSize ); + memcpy( &fpgaSensorReadings, &fpgaReadResponseBuffer[ FPGA_READ_RSP_HDR_LEN ], sizeof( DG_FPGA_SENSORS_T ) ); result = FPGA_STATE_WRITE_ALL_ACTUATORS; } else // bad CRC @@ -932,21 +914,26 @@ * @brief * The execFPGAClockSpeedTest function verifies the processor clock speed * against the FPGA clock. - * @details Inputs: fpgaHeader + * @details Inputs: fpgaHeader, + * window timer TIME_WINDOWED_COUNT_FPGA_CLOCK_SPEED_ERROR * @details Outputs: none - * @return passed, or failed + * @return: none *************************************************************************/ void execFPGAClockSpeedTest( void ) { + /* DEBUG WARNING + * It may be necessary to comment out the following + * code to prevent the alarm from occurring while + * debugging. + */ -#ifndef DEBUG_ENABLED static U16 currentFPGATimerCount_ms = 0; - static U32 currentTimerCount_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() != DG_MODE_INIT ) { @@ -960,8 +947,7 @@ } currentFPGATimerCount_ms = newFPGATimerCount_ms; - currentTimerCount_ms = newTimerCount_ms; -#endif + currentTimerCount_ms = newTimerCount_ms; } /*********************************************************************//** @@ -1133,22 +1119,6 @@ /*********************************************************************//** * @brief - * The monitorFPGAPowerStatus function monitors the status of the FPGA power source. - * @details Inputs: none - * @details Outputs: none - * @return none - *************************************************************************/ -static void monitorFPGAPowerStatus( void ) -{ - // If the GIO bit returned a 0 it mean the power is out, otherwise the power is not out - BOOL isPowerOut = ( TRUE == (BOOL)gioGetBit( gioPORTA, FPGA_GPIO_POWER_STATUS_PIN ) ? FALSE : TRUE ); - - // TODO check to make sure alarm is not raised when the power is good - checkPersistentAlarm( ALARM_ID_DG_FPGA_POWER_OUT_TIMEOUT, isPowerOut, 0, FPGA_POWER_OUT_TIMEOUT_MS ); -} - -/*********************************************************************//** - * @brief * The setFPGAValveStates function sets the DG valve states with a 16-bit * set of states - one bit per valve, with a 1 meaning "energized" and a 0 * meaning "de-energized". The bit positions for these bit states are as follows: @@ -1329,6 +1299,25 @@ /*********************************************************************//** * @brief + * The getFPGAAcidPumpControlStatus function gets the status of the + * acid pump control status bits. + * bit 7: Park (set in different function) + * bit 6: nSleep + * bit 5: nReset + * bit 4: nEnable + * bit 3: Direction (1=Fwd, 0=Rev) + * bit 0-2: Microstepping resolution + * @details Inputs: none + * @details Outputs: fpgaActuatorSetPoints.fpgaNewCP1Control + * @return Acid pump control status bit + *************************************************************************/ +U08 getFPGAAcidPumpControlStatus( void ) +{ + return fpgaActuatorSetPoints.fpgaNewCP1Control; +} + +/*********************************************************************//** + * @brief * The setFPGABicarbPumpControl function sets the DVT concentrate pump 2 * (bicarb pump) control mode. * bit 7: Park (set in different function) @@ -1338,18 +1327,37 @@ * bit 3: Direction (1=Fwd, 0=Rev) * bit 0-2: Microstepping resolution * @details Inputs: none - * @details Outputs: fpgaActuatorSetPoints.fgpaNewCP2Control + * @details Outputs: fpgaActuatorSetPoints.fpgaNewCP2Control * @param control Concentrate pump control set * @return none *************************************************************************/ void setFPGABicarbPumpControl( U08 control ) { - fpgaActuatorSetPoints.fgpaNewCP2Control &= FPGA_CONC_PUMP_PARK_COMMAND; // preserve msb (park command bit) - fpgaActuatorSetPoints.fgpaNewCP2Control |= control; + fpgaActuatorSetPoints.fpgaNewCP2Control &= FPGA_CONC_PUMP_PARK_COMMAND; // preserve msb (park command bit) + fpgaActuatorSetPoints.fpgaNewCP2Control |= control; } /*********************************************************************//** * @brief + * The getFPGABicarbPumpControlStatus function gets the DVT concentrate pump 2 + * (bicarb pump) control mode. + * bit 7: Park (set in different function) + * bit 6: nSleep + * bit 5: nReset + * bit 4: nEnable + * bit 3: Direction (1=Fwd, 0=Rev) + * bit 0-2: Microstepping resolution + * @details Inputs: none + * @details Outputs: fpgaActuatorSetPoints.fpgaNewCP2Control + * @return Bicarb pump control status bit + *************************************************************************/ +U08 getFPGABicarbPumpControlStatus( void ) +{ + return fpgaActuatorSetPoints.fpgaNewCP2Control; +} + +/*********************************************************************//** + * @brief * The setFPGAAcidPumpParkCmd function sets the DVT concentrate pump 1 * (acid pump) park command bit. * bit 7: Park command bit @@ -1371,13 +1379,13 @@ * bit 7: Park command bit * bit 0-6: Other pump control bits (set in different function) * @details Inputs: none - * @details Outputs: fpgaActuatorSetPoints.fgpaNewCP2Control + * @details Outputs: fpgaActuatorSetPoints.fpgaNewCP2Control * @param Park command bit set * @return none *************************************************************************/ void setFPGABicarbPumpParkCmd( void ) { - fpgaActuatorSetPoints.fgpaNewCP2Control |= FPGA_CONC_PUMP_PARK_COMMAND; // this bit must be cleared after next transmit to prevent continuous park commands + fpgaActuatorSetPoints.fpgaNewCP2Control |= FPGA_CONC_PUMP_PARK_COMMAND; // this bit must be cleared after next transmit to prevent continuous park commands } /*********************************************************************//** @@ -2737,15 +2745,49 @@ *************************************************************************/ BOOL checkFPGACommFailure( void ) { - BOOL status = false; + BOOL status = FALSE; - if ( TRUE == incTimeWindowedCount( TIME_WINDOWED_COUNT_FPGA_COMM_FAILURES ) ) + if ( getMSTimerCount() > MIN_POWER_ON_TIME_FOR_COMM_FAILS ) { - SET_ALARM_WITH_2_U32_DATA( ALARM_ID_DG_FPGA_COMM_TIMEOUT, MAX_FPGA_COMM_FAILURES, (U32)fpgaSensorReadings.fpgaIOErrorCntProcessor ) - status = TRUE; + if ( TRUE == incTimeWindowedCount( TIME_WINDOWED_COUNT_FPGA_COMM_FAILURES ) ) + { + SET_ALARM_WITH_2_U32_DATA( ALARM_ID_DG_FPGA_COMM_TIMEOUT, MAX_FPGA_COMM_FAILURES, (U32)fpgaSensorReadings.fpgaIOErrorCntProcessor ) + status = TRUE; + } } return status; } + +/*********************************************************************//** + * @brief + * The checkFPGACommFailure function increments the FPGA comm failure + * windowed timer if an FE or OE error has occurred 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 checkFPGAFEOEFailure( void ) +{ + BOOL status = FALSE; + BOOL FPGAFEOEError = getSci2FEOEError(); + + if ( TRUE == FPGAFEOEError) + { + 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_DG_FPGA_COMM_TIMEOUT, MAX_FPGA_COMM_FAILURES, (U32)fpgaSensorReadings.fpgaIOErrorCntProcessor ) + status = TRUE; + } + } + } + + return status; +} + /**@}*/