Index: AlarmMgmt.c =================================================================== diff -u --- AlarmMgmt.c (revision 0) +++ AlarmMgmt.c (revision 6d80d69a210f45c733e5307859351f2cd820a8e7) @@ -0,0 +1,393 @@ +/************************************************************************** +* +* Copyright (c) 2024-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 AlarmMgmt.c +* +* @author (last) Sean +* @date (last) 30-Jul-2024 +* +* @author (original) Sean +* @date (original) 30-Jul-2024 +* +***************************************************************************/ + +#include "mibspi.h" + +#define __ALARM_MGMT_C__ + +#include "Messaging.h" +#include "OperationModes.h" +#include "TaskGeneral.h" +#include "Timers.h" + +/** + * @addtogroup AlarmManagement + * @{ + */ + +// ********** private definitions ********** + +// ********** private data ********** + +// *** This declaration will cause a compiler error if ALARM_TABLE does not have same # of alarms as the Alarm_List enumeration. +U08 alarmTableSizeAssertion[ ( ( sizeof( ALARM_TABLE ) / sizeof( ALARM_T ) ) == NUM_OF_ALARM_IDS ? 1 : -1 ) ]; + +// *** This declaration will cause a compiler error if ALARM_RANK_TABLE does not have same # of alarms as the Alarm_List enumeration. +U08 alarmRankTableSizeAssertion[ ( ( sizeof( ALARM_RANK_TABLE ) / sizeof( ALARM_RANK_T ) ) == NUM_OF_ALARM_IDS ? 1 : -1 ) ]; + +static BOOL alarmIsActive[ NUM_OF_ALARM_IDS ]; ///< Table - current state of each alarm +static BOOL alarmIsDetected[ NUM_OF_ALARM_IDS ]; ///< Table - current state of each alarm condition (detected or cleared) + +// ********** private function prototypes ********** + +/*********************************************************************//** + * @brief + * The initAlarmMgmt function initializes the AlarmMgmt module. + * @details Inputs: none + * @details Outputs: AlarmMgmt module initialized. + * @return none + *************************************************************************/ +void initAlarmMgmt( void ) +{ + ALARM_ID_T a; + + // Initialize alarm states and start time stamps + for ( a = ALARM_ID_NO_ALARM; a < NUM_OF_ALARM_IDS; a++ ) + { + alarmIsActive[ a ] = FALSE; + alarmIsDetected[ a ] = FALSE;; + } +} + +/*********************************************************************//** + * @brief + * The getAlarmProperties function gets the alarm properties for a given alarm. + * @details Inputs: none + * @details Outputs: ALARM_TABLE[] + * @param alarm ID of alarm to get properties record for + * @return properties record for given alarm + *************************************************************************/ +ALARM_T getAlarmProperties( ALARM_ID_T alarm ) +{ + ALARM_T result = ALARM_TABLE[ ALARM_ID_NO_ALARM ]; + + if ( alarm < NUM_OF_ALARM_IDS ) + { + result = ALARM_TABLE[ alarm ]; + } + else + { + // TODO - s/w fault + } + + return result; +} + +/*********************************************************************//** + * @brief + * The getAlarmRank function gets the alarm rank for a given alarm index. + * @details Inputs: none + * @details Outputs: ALARM_RANK_TABLE[] + * @param index index to alarm table + * @return Alarm rank record for given index + *************************************************************************/ +ALARM_RANK_T getAlarmRank( U32 index ) +{ + ALARM_RANK_T result = ALARM_RANK_TABLE[ 0 ]; + + if ( index < NUM_OF_ALARM_IDS ) + { + result = ALARM_RANK_TABLE[ index ]; + } + else + { + // TODO - s/w fault + } + + return result; +} + +/*********************************************************************//** + * @brief + * The activateAlarm function activates a given alarm. + * @details Inputs: none + * @details Outputs: alarmIsActive[], alarmStartedAt[], alarmStatus is updated + * @param alarm ID of alarm to activate + * @return none + *************************************************************************/ +void activateAlarm( ALARM_ID_T alarm ) +{ + // Verify valid alarm index + if ( ( alarm > ALARM_ID_NO_ALARM ) && ( alarm < NUM_OF_ALARM_IDS ) ) + { + // No need to do anything if alarm is already active, but if condition was cleared then re-trigger alarm + if ( ( FALSE == alarmIsActive[ alarm ] ) || + ( ( FALSE == alarmIsDetected[ alarm ] ) && ( FALSE == ALARM_TABLE[ alarm ].alarmConditionClearImmed ) ) ) + { + // Activate alarm + alarmIsActive[ alarm ] = TRUE; + alarmIsDetected[ alarm ] = TRUE; + + // If alarm has clear condition immediately property, clear condition now + if ( TRUE == ALARM_TABLE[ alarm ].alarmConditionClearImmed ) + { + clearAlarmCondition( alarm ); + } + } + } + else + { +// SET_ALARM_WITH_2_U32_DATA( ALARM_ID_TD_SOFTWARE_FAULT, SW_FAULT_ID_ALARM_MGMT_INVALID_ALARM_TO_ACTIVATE, alarm ) + } +} + +/*********************************************************************//** + * @brief + * The clearAlarmCondition function clears a given alarm's condition detected + * flag. Also an alarm message is broadcast to the rest of the system. + * @details Inputs: none + * @details Outputs: alarmIsDetected[] + * @param alarm ID of alarm to clear condition for + * @return none + *************************************************************************/ +void clearAlarmCondition( ALARM_ID_T alarm ) +{ + // Verify given alarm + if ( ( alarm > ALARM_ID_NO_ALARM ) && ( alarm < NUM_OF_ALARM_IDS ) ) + { + // Clear alarm condition and broadcast alarm condition clear if not already cleared + if ( TRUE == alarmIsDetected[ alarm ] ) + { + ALARM_ID_DATA_PUBLISH_T data; + + data.alarmID = (U32)alarm; + + alarmIsDetected[ alarm ] = FALSE; + broadcastData( MSG_ID_ALARM_CONDITION_CLEARED, COMM_BUFFER_OUT_CAN_TD_ALARM, (U08*)&data, sizeof( ALARM_ID_DATA_PUBLISH_T ) ); + } + } +} + +/*********************************************************************//** + * @brief + * The clearAlarm function clears a given alarm if it is recoverable. Also + * an alarm message is broadcast to the rest of the system. + * @details Inputs: none + * @details Outputs: AlarmStatusTable[], alarmIsActive[], alarmStartedAt[], + * alarmIsDetected[] + * @param alarm ID of alarm to clear + * @return none + *************************************************************************/ +void clearAlarm( ALARM_ID_T alarm ) +{ + // Verify given alarm + if ( ( alarm > ALARM_ID_NO_ALARM ) && ( alarm < NUM_OF_ALARM_IDS ) ) + { + // Verify alarm can be cleared + if ( FALSE == ALARM_TABLE[ alarm ].alarmNoClear ) + { + // Clear alarm and broadcast alarm clear if not already cleared + if ( TRUE == alarmIsActive[ alarm ] ) + { + ALARM_ID_DATA_PUBLISH_T data; + + data.alarmID = (U32) alarm; + + broadcastData( MSG_ID_ALARM_CLEARED, COMM_BUFFER_OUT_CAN_TD_ALARM, (U08*)&data, sizeof( ALARM_ID_DATA_PUBLISH_T ) ); + alarmIsActive[ alarm ] = FALSE; + clearAlarmCondition( alarm ); + } + } + } + else + { +// SET_ALARM_WITH_2_U32_DATA( ALARM_ID_TD_SOFTWARE_FAULT, SW_FAULT_ID_ALARM_MGMT_INVALID_ALARM_TO_CLEAR, alarm ) + } +} + +/*********************************************************************//** + * @brief + * The setAlarmActive function sets the active flag for a given alarm. + * @details Inputs: none + * @details Outputs: alarmIsActive[] + * @param alarm ID of alarm to set active flag for + * @param active TRUE if setting alarm as active, FALSE if not + * @return none + *************************************************************************/ +void setAlarmActive( ALARM_ID_T alarm, BOOL active ) +{ + alarmIsActive[ alarm ] = active; +} + +/*********************************************************************//** + * @brief + * The setAlarmConditionDetected function sets the condition detected flag + * for a given alarm. + * @details Inputs: none + * @details Outputs: alarmIsDetected[] + * @param alarm ID of alarm to set condition detected flag for + * @param detected TRUE if setting alarm condition as detected, FALSE if not + * @return none + *************************************************************************/ +void setAlarmConditionDetected( ALARM_ID_T alarm, BOOL detected ) +{ + alarmIsDetected[ alarm ] = detected; +} + +/*********************************************************************//** + * @brief + * The isAlarmActive function determines whether a given alarm is currently + * active. + * @details Inputs: alarmIsActive[] + * @details Outputs: none + * @param alarm ID of alarm to check + * @return TRUE if given alarm is active, FALSE if not + *************************************************************************/ +BOOL isAlarmActive( ALARM_ID_T alarm ) +{ + BOOL result = FALSE; + + if ( alarm < NUM_OF_ALARM_IDS ) + { + result = alarmIsActive[ alarm ]; + } + else + { +// SET_ALARM_WITH_2_U32_DATA( ALARM_ID_TD_SOFTWARE_FAULT, SW_FAULT_ID_INVALID_ALARM_ID_REFERENCED, (U32)alarm ); + } + + return result; +} + +/*********************************************************************//** + * @brief + * The isAlarmConditionDetected function determines whether a given alarm + * condition is currently detected. + * @details Inputs: alarmIsDetected[] + * @details Outputs: none + * @param alarm ID of alarm to check + * @return TRUE if given alarm is active, FALSE if not + *************************************************************************/ +BOOL isAlarmConditionDetected( ALARM_ID_T alarm ) +{ + BOOL result = FALSE; + + if ( alarm < NUM_OF_ALARM_IDS ) + { + if ( ( TRUE == alarmIsActive[ alarm ] ) && ( TRUE == alarmIsDetected[ alarm ] ) ) + { + result = TRUE; + } + } + else + { +// SET_ALARM_WITH_2_U32_DATA( ALARM_ID_TD_SOFTWARE_FAULT, SW_FAULT_ID_INVALID_ALARM_ID_REFERENCED, (U32)alarm ); + } + + return result; +} + +/*********************************************************************//** + * @brief +* The isAlarmRecoverable function determines whether a given alarm is +* recoverable. +* @details Inputs: ALARM_TABLE[] +* @details Outputs: none +* @param alarm ID of alarm to check +* @return TRUE if given alarm is recoverable, FALSE if not +*************************************************************************/ +BOOL isAlarmRecoverable( ALARM_ID_T alarm ) +{ + BOOL result = ( TRUE == ALARM_TABLE[ alarm ].alarmNoClear ? FALSE : TRUE ); + + return result; +} + + +/************************************************************************* + * TEST SUPPORT FUNCTIONS + *************************************************************************/ + + +/*********************************************************************//** + * @brief + * The testSetAlarmStateOverride function overrides the state of the + * alarm active state for a given alarm with the alarm management with + * a given active state. + * @details Inputs: none + * @details Outputs: alarm activated or cleared + * @param alarmID ID of alarm to activate or clear + * @param value override state for the given alarm ID (1=activate, 0=clear) + * @return TRUE if override successful, FALSE if not + *************************************************************************/ +BOOL testSetAlarmStateOverride( U32 alarmID, U32 state ) +{ + BOOL result = FALSE; + + if ( alarmID < NUM_OF_ALARM_IDS ) + { + // Verify tester has logged in with HD + if ( TRUE == isTestingActivated() ) + { + if ( TRUE == state ) + { + activateAlarmNoData( (ALARM_ID_T)alarmID ); + } + else + { +#ifdef _TD_ + clearAlarmTD( (ALARM_ID_T)alarmID ); +#endif +#ifdef _DD_ + clearAlarmDD( (ALARM_ID_T)alarmID ); +#endif +#ifdef _RO_ + clearAlarmRO( (ALARM_ID_T)alarmID ); +#endif + } + result = TRUE; + } + } + + return result; +} + +/*********************************************************************//** + * @brief + * The testResetAlarmStateOverride function resets the override of the + * state of the active state for a given alarm with the alarm management. + * @details Inputs: none + * @details Outputs: alarm cleared + * @param alarmID ID of alarm to clear + * @return TRUE if alarm clear successful, FALSE if not + *************************************************************************/ +BOOL testResetAlarmStateOverride( U32 alarmID ) +{ + BOOL result = FALSE; + + if ( alarmID < NUM_OF_ALARM_IDS ) + { + // Verify tester has logged in with HD + if ( TRUE == isTestingActivated() ) + { + result = TRUE; +#ifdef _TD_ + clearAlarmTD( (ALARM_ID_T)alarmID ); +#endif +#ifdef _DD_ + clearAlarmDD( (ALARM_ID_T)alarmID ); +#endif +#ifdef _RO_ + clearAlarmRO( (ALARM_ID_T)alarmID ); +#endif + } + } + + return result; +} + +/**@}*/ Index: AlarmMgmt.h =================================================================== diff -u --- AlarmMgmt.h (revision 0) +++ AlarmMgmt.h (revision 6d80d69a210f45c733e5307859351f2cd820a8e7) @@ -0,0 +1,118 @@ +/************************************************************************** +* +* Copyright (c) 2024-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 AlarmMgmt.h +* +* @author (last) Sean +* @date (last) 30-Jul-2024 +* +* @author (original) Sean +* @date (original) 30-Jul-2024 +* +***************************************************************************/ + +#ifndef __ALARM_MGMT_H__ +#define __ALARM_MGMT_H__ + +#include "TDCommon.h" +#include "AlarmDefs.h" +#include "AlarmMgmtSWFaults.h" + +/** + * @defgroup AlarmManagement AlarmManagement + * @brief Alarm Management service module. Provides general alarm management + * functionality including support functions for triggering and clearing + * specific alarms. + * + * @addtogroup AlarmManagement + * @{ + */ + +#pragma pack(push, 4) +/// Record structure for unsigned integer alarm data. +typedef struct +{ + U32 data; ///< Alarm data of unsigned integer type. +} ALARM_DATA_U32_T; + +/// Record structure for signed integer alarm data. +typedef struct +{ + S32 data; ///< Alarm data of signed integer type. +} ALARM_DATA_S32_T; + +/// Record structure for floating point alarm data. +typedef struct +{ + F32 data; ///< Alarm data of floating point type. +} ALARM_DATA_F32_T; + +/// Record structure for boolean alarm data. +typedef struct +{ + BOOL data; ///< Alarm data of boolean type. +} ALARM_DATA_BOOL_T; + +/// Record structure for alarm data of any supported type. +typedef union +{ + ALARM_DATA_U32_T uInt; ///< Alarm data of unsigned integer type. + ALARM_DATA_S32_T sInt; ///< Alarm data of signed integer type. + ALARM_DATA_F32_T flt; ///< Alarm data of floating point type. + ALARM_DATA_BOOL_T bln; ///< Alarm data of boolean type. +} ALARM_DATAS_T; + +/// Record structure for alarm data including the data type to aid in interpretation. +typedef struct +{ + ALARM_DATA_TYPES_T dataType; ///< The type of alarm data provided. + ALARM_DATAS_T data; ///< The alarm data of specified type. +} ALARM_DATA_T; + +/// Payload record structure for the alarm triggered message. +typedef struct +{ + U32 alarm; ///< ID of alarm that was triggered + U32 almDataType1; ///< Supporting data type #1 + U32 almData1; ///< Supporting data #1 + U32 almDataType2; ///< Supporting data type #2 + U32 almData2; ///< Supporting data #2 + U32 almPriority; ///< Alarm priority + U32 almRank; ///< Alarm rank + BOOL almClrTopOnly; ///< Alarm clear (when on top) should only clear top alarm +} ALARM_TRIGGERED_PAYLOAD_T; + +#pragma pack(pop) + +/// Alarm ID data publish +typedef struct +{ + U32 alarmID; ///< Alarm ID. +} ALARM_ID_DATA_PUBLISH_T; + +// ********** public function prototypes ********** + +void initAlarmMgmt( void ); + +ALARM_T getAlarmProperties( ALARM_ID_T alarm ); +ALARM_RANK_T getAlarmRank( U32 index ); + +void activateAlarm( ALARM_ID_T alarm ); +void clearAlarm( ALARM_ID_T alarm ); +void clearAlarmCondition( ALARM_ID_T alarm ); +void setAlarmActive( ALARM_ID_T alarm, BOOL active ); +void setAlarmConditionDetected( ALARM_ID_T alarm, BOOL detected ); +BOOL isAlarmActive( ALARM_ID_T alarm ); +BOOL isAlarmConditionDetected( ALARM_ID_T alarm ); +BOOL isAlarmRecoverable( ALARM_ID_T alarm ); + +BOOL testSetAlarmStateOverride( U32 alarmID, BOOL value ); +BOOL testResetAlarmStateOverride( U32 alarmID ); + +/**@}*/ + +#endif Index: Comm.c =================================================================== diff -u --- Comm.c (revision 0) +++ Comm.c (revision 6d80d69a210f45c733e5307859351f2cd820a8e7) @@ -0,0 +1,160 @@ +/************************************************************************** +* +* Copyright (c) 2024-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 Comm.c +* +* @author (last) Sean Nash +* @date (last) 30-Jul-2024 +* +* @author (original) Sean Nash +* @date (original) 30-Jul-2024 +* +***************************************************************************/ + +#include "can.h" +#include "sci.h" +#include "sys_dma.h" + +#include "Comm.h" + +/** + * @addtogroup CommInterrupts + * @{ + */ + +// ********** private definitions ********** + +#define DMA_CH_STATUS_BIT(ch) ((U32)1U << (ch)) ///< Macro to get bit mask for status of a given DMA channel. + +// ********** private data ********** + +static volatile BOOL canXmitsInProgress = FALSE; ///< Flag indicates a CAN frame transmit is in progress. + +/*********************************************************************//** + * @brief + * The signalCANXmitsInitiated function sets the CAN transmits in + * progress flag. + * @details Inputs: none + * @details Outputs: canXmitsInProgress + * @return none + *************************************************************************/ +void signalCANXmitsInitiated( void ) +{ + canXmitsInProgress = TRUE; +} + +/*********************************************************************//** + * @brief + * The signalCANXmitsCompleted function resets the CAN transmits in + * progress flag. + * @details Inputs: none + * @details Outputs: canXmitsInProgress + * @return none + *************************************************************************/ +void signalCANXmitsCompleted( void ) +{ + canXmitsInProgress = FALSE; +} + +/*********************************************************************//** + * @brief + * The setSCI2DMAReceiveInterrupt function enables DMA receive interrupts + * for the SCI2 peripheral. + * @details Inputs: none + * @details Outputs: DMA receive interrupt is enabled. + * @return none + *************************************************************************/ +void setSCI2DMAReceiveInterrupt( void ) +{ + scilinREG->SETINT = SCI_DMA_RECEIVE_INT; +} + +/*********************************************************************//** + * @brief + * The setSCI2DMATransmitInterrupt function enables DMA transmit interrupts + * for the SCI2 peripheral. + * @details Inputs: none + * @details Outputs: DMA transmit interrupt is enabled. + * @return none + *************************************************************************/ +void setSCI2DMATransmitInterrupt( void ) +{ + scilinREG->SETINT = SCI_DMA_TRANSMIT_INT; +} + +/*********************************************************************//** + * @brief + * The clearSCI2DMAReceiveInterrupt function disables DMA receive interrupts + * for the SCI2 peripheral. + * @details Inputs: none + * @details Outputs: DMA receive interrupt is disabled. + * @return none + *************************************************************************/ +void clearSCI2DMAReceiveInterrupt( void ) +{ + scilinREG->CLEARINT = SCI_DMA_RECEIVE_INT; +} + +/*********************************************************************//** + * @brief + * The clearSCI2DMATransmitInterrupt function disables DMA transmit interrupts + * for the SCI2 peripheral. + * @details Inputs: none + * @details Outputs: DMA transmit interrupt is disabled. + * @return none + *************************************************************************/ +void clearSCI2DMATransmitInterrupt( void ) +{ + scilinREG->CLEARINT = SCI_DMA_TRANSMIT_INT; +} + +/*********************************************************************//** + * @brief + * The clearSCI1CommErrors function clears framing and/or overrun error flags \ + * for the SCI1 peripheral. + * @details Inputs: none + * @details Outputs: SCI1 error flags cleared. + * @return none + *************************************************************************/ +void clearSCI1CommErrors( void ) +{ + sciReceiveByte( sciREG ); + sciREG->FLR |= ( SCI_FE_INT | SCI_OE_INT ); +} + +/*********************************************************************//** + * @brief + * The isSCI2DMATransmitInProgress function determines whether a DMA transmit + * is in progress on the SCI2 peripheral. + * @details Inputs: status registers + * @details Outputs: none + * @return TRUE if a transmit is in progress, FALSE if not + *************************************************************************/ +BOOL isSCI2DMATransmitInProgress( void ) +{ + BOOL transmitterBusy = ( ( scilinREG->FLR & (U32)SCI_TX_INT ) == 0U ? TRUE : FALSE ); + BOOL dmaTransmitterBusy = ( ( dmaREG->PEND & DMA_CH_STATUS_BIT(DMA_CH2) ) != 0U ? TRUE : FALSE ); + + return ( ( transmitterBusy == TRUE ) || ( dmaTransmitterBusy == TRUE ) ? TRUE : FALSE ); +} + +/*********************************************************************//** + * @brief + * The isCAN1TransmitInProgress function determines whether a transmit + * is in progress on the CAN1 peripheral. + * @details Inputs: status registers + * @details Outputs: none + * @return TRUE if a transmit is in progress, FALSE if not + *************************************************************************/ +BOOL isCAN1TransmitInProgress( void ) +{ + BOOL result = ( ( TRUE == canXmitsInProgress ) || ( canREG1->TXRQx[ 0 ] != 0 ) || ( canREG1->TXRQx[ 1 ] != 0 ) ? TRUE : FALSE ); + + return result; +} + +/**@}*/ Index: Comm.h =================================================================== diff -u --- Comm.h (revision 0) +++ Comm.h (revision 6d80d69a210f45c733e5307859351f2cd820a8e7) @@ -0,0 +1,52 @@ +/************************************************************************** +* +* Copyright (c) 2024-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 Comm.h +* +* @author (last) Sean Nash +* @date (last) 30-Jul-2024 +* +* @author (original) Sean Nash +* @date (original) 30-Jul-2024 +* +***************************************************************************/ + +#ifndef __COMM_H__ +#define __COMM_H__ + +#include "../TDCommon.h" + +/** + * @defgroup CommInterrupts CommInterrupts + * @brief The communication module provides low level comm signal, + * status, and some interrupt handling functions. + * + * @addtogroup CommInterrupts + * @{ + */ + +// ********** public definitions ********** + +#define SCI_DMA_TRANSMIT_INT 0x00010000 ///< Bit mask for setting/clearing serial DMA transmit interrupts. +#define SCI_DMA_RECEIVE_INT 0x00060000 ///< Bit mask for setting/clearing serial DMA receive interrupts. + +// ********** public function prototypes ********** + +void signalCANXmitsInitiated( void ); +void signalCANXmitsCompleted( void ); + +void setSCI2DMAReceiveInterrupt( void ); +void setSCI2DMATransmitInterrupt( void ); +void clearSCI2DMAReceiveInterrupt( void ); +void clearSCI2DMATransmitInterrupt( void ); +BOOL isSCI2DMATransmitInProgress( void ); + +BOOL isCAN1TransmitInProgress( void ); + +/**@}*/ + +#endif Index: Common.h =================================================================== diff -u --- Common.h (revision 0) +++ Common.h (revision 6d80d69a210f45c733e5307859351f2cd820a8e7) @@ -0,0 +1,512 @@ +/************************************************************************** +* +* Copyright (c) 2024-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 Common.h +* +* @author (last) Sean +* @date (last) 30-Jul-2024 +* +* @author (original) Sean +* @date (original) 30-Jul-2024 +* +***************************************************************************/ + +#ifndef __COMMON_H__ +#define __COMMON_H__ + +#include "hal_stdtypes.h" + +/** + * @defgroup CommonHeader CommonHeader + * @brief Provides commonly used definitions and macros. + * + * @addtogroup CommonHeader + * @{ + */ + +// ********** public definitions ********** + +// **** Types **** + +typedef float F32; ///< 32-bit floating point type +typedef double F64; ///< 64-bit floating point type +typedef long long S64; ///< 64-bit signed integer type +typedef unsigned int U32; ///< 32-bit unsigned integer type +typedef int S32; ///< 32-bit signed integer type +typedef unsigned short U16; ///< 16-bit unsigned integer type +typedef short S16; ///< 16-bit signed integer type +typedef unsigned char U08; ///< 8-bit unsigned integer type +typedef unsigned int BOOL; ///< 32-bit boolean type +typedef unsigned char BYTE; ///< 8-bit byte type + +/// List of pin signal states. +typedef enum Pin_Signal_States +{ + PIN_SIGNAL_LOW = 0, ///< Low signal level + PIN_SIGNAL_HIGH, ///< High signal level + NUM_OF_PIN_SIGNAL_STATES ///< Number of pin signal states +} PIN_SIGNAL_STATE_T; + +/// List of self-test status. +typedef enum Self_Test_Status +{ + SELF_TEST_STATUS_IN_PROGRESS = 0, ///< Self test is in progress + SELF_TEST_STATUS_PASSED, ///< Self test has passed + SELF_TEST_STATUS_FAILED, ///< Self test has failed + NUM_OF_SELF_TEST_STATUS ///< Number of self-test status +} SELF_TEST_STATUS_T; + +/// List of 2-way states. +typedef enum Two_Way_States +{ + STATE_CLOSED = 0, ///< Closed state + STATE_OPEN, ///< Open state + NUM_OF_OPN_CLS_STATES ///< Number of 2-way states +} OPN_CLS_STATE_T; + +/// List of motor directions. +typedef enum Motor_Directions +{ + MOTOR_DIR_FORWARD = 0, ///< Motor direction is forward + MOTOR_DIR_REVERSE, ///< Motor direction is reverse + NUM_OF_MOTOR_DIRECTIONS ///< Number of motor directions +} MOTOR_DIR_T; + +/// List of pump control modes. +typedef enum Pump_Control_Modes +{ + PUMP_CONTROL_MODE_CLOSED_LOOP = 0, ///< Pump controlled based on set point and feedback + PUMP_CONTROL_MODE_OPEN_LOOP, ///< Pump controlled to set PWM duty cycle + NUM_OF_PUMP_CONTROL_MODES ///< Number of pump control modes +} PUMP_CONTROL_MODE_T; + +// **** Common Definitions **** + +#define NEARLY_INFINITY 1.0E20 ///< Value that is nearly infinity. +#define NEARLY_ZERO 0.00000001F ///< Value that is nearly zero. Used for floating point zero comparisons (e.g. divide by zero checks) +#define HEX_64_K 0x10000 ///< 64K (65536 in decimal) +#define HEX_32_BIT_FULL_SCALE 0xFFFFFFFF ///< 32-bit full scale value +#define MASK_OFF_MSB 0x00FF ///< Bits to mask off the most significant byte of a 2-byte word +#define MASK_OFF_LSB 0xFF00 ///< Bits to mask off the least significant byte of a 2-byte word +#define MASK_OFF_MSW 0x0000FFFF ///< Bits to mask off the most significant 2-byte word of a 4-byte word +#define MASK_OFF_LSW 0xFFFF0000 ///< Bits to mask off the least significant 2-byte word of a 4-byte word +#define MASK_OFF_U32_MSB 0x00FFFFFF ///< Bits to mask off the most significant byte word of a 4-byte word +#define MASK_OFF_U32_LSB 0xFFFFFF00 ///< Bits to mask off the least significant byte of a 4-byte word +#define MASK_OFF_U32_MSBS 0x000000FF ///< Bits to mask off all but the least significant byte of a 4-byte word +#define SHIFT_8_BITS_FOR_BYTE_SHIFT 8 ///< Number of bits to shift in order to shift a byte +#define SHIFT_16_BITS_FOR_WORD_SHIFT 16 ///< Number of bits to shift in order to shift 2 bytes +#define SHIFT_24_BITS 24 ///< Number of bits to shift in order to shift 3 bytes +#define MASK_OFF_NIBBLE_LSB 0xF0 ///< Bits to mask off the least significant nibble of a byte +#define MASK_OFF_NIBBLE_MSB 0x0F ///< Bits to mask off the most significant nibble of a byte +#define MAX_DOUBLE_DIGIT_DECIMAL 99U ///< Maximum value for a decimal byte +#define MAX_SINGLE_DIGIT_DECIMAL 9U ///< Maximum value for a decimal nibble +#define SHIFT_BITS_BY_4 4U ///< Number of bits to shift in order to shift a nibble +#define SHIFT_BITS_BY_31 31 ///< Shift bits by 31 +#define SHIFT_BITS_BY_7 7 ///< Shift bits by 7 +#define SHIFT_BITS_BY_23 23 ///< Shift bits by 23 +#define FLOAT_TO_INT_ROUNDUP_OFFSET 0.5F ///< Offset to add to a floating point value for rounding rounding when converting to integer +#define ML_PER_LITER 1000 ///< Number of milliliters in a liter +#define MA_PER_AMP 1000 ///< Number of milliamps in an amp +#define MS_PER_SECOND 1000 ///< Number of milliseconds in a second +#define US_PER_SECOND 1000000 ///< Number of microseconds in a second +#define SEC_PER_MIN 60 ///< Number of seconds in a minute +#define FRACTION_TO_PERCENT_FACTOR 100.0F ///< Percentage factor (100) +#define MIN_PER_HOUR 60 ///< Number of minutes in an hour +#define PI 3.1415927F ///< PI +#define SECONDS_IN_A_DAY 86400 ///< Number of seconds in a day +#define BITS_8_FULL_SCALE 256 ///< Full scale range for 8 bit ADC or DAC +#define BITS_10_FULL_SCALE 1024 ///< Full scale range for 10 bit ADC or DAC +#define BITS_11_FULL_SCALE 2048 ///< Full scale range for 11 bit ADC or DAC +#define BITS_12_FULL_SCALE 4096 ///< Full scale range for 12 bit ADC or DAC +#define BITS_14_FULL_SCALE 16384 ///< Full scale range for 14 bit ADC or DAC +#define BITS_16_FULL_SCALE 65536 ///< Full scale range for 16 bit ADC or DAC +#define BITS_24_FULL_SCALE 16777216 ///< Full scale range for 24 bit ADC or DAC +#define HALF 0.5F ///< Half + +#define ASCII_CODE_LETTER_A 0x41 ///< ASCII code in hex for letter A. +#define ASCII_CODE_LETTER_B 0x42 ///< ASCII code in hex for letter B. +#define ASCII_CODE_LETTER_C 0x43 ///< ASCII code in hex for letter C. +#define ASCII_CODE_LETTER_D 0x44 ///< ASCII code in hex for letter D. +#define ASCII_CODE_LETTER_E 0x45 ///< ASCII code in hex for letter E. +#define ASCII_CODE_LETTER_F 0x46 ///< ASCII code in hex for letter F. +#define ASCII_CODE_LETTER_G 0x47 ///< ASCII code in hex for letter G. +#define ASCII_CODE_LETTER_H 0x48 ///< ASCII code in hex for letter H. +#define ASCII_CODE_LETTER_I 0x49 ///< ASCII code in hex for letter I. +#define ASCII_CODE_LETTER_J 0x4A ///< ASCII code in hex for letter J. +#define ASCII_CODE_LETTER_K 0x4B ///< ASCII code in hex for letter K. +#define ASCII_CODE_LETTER_L 0x4C ///< ASCII code in hex for letter L. +#define ASCII_CODE_LETTER_M 0x4D ///< ASCII code in hex for letter M. +#define ASCII_CODE_LETTER_N 0x4E ///< ASCII code in hex for letter N. +#define ASCII_CODE_LETTER_O 0x4F ///< ASCII code in hex for letter O. +#define ASCII_CODE_LETTER_P 0x50 ///< ASCII code in hex for letter P. +#define ASCII_CODE_LETTER_Q 0x51 ///< ASCII code in hex for letter Q. +#define ASCII_CODE_LETTER_R 0x52 ///< ASCII code in hex for letter R. +#define ASCII_CODE_LETTER_S 0x53 ///< ASCII code in hex for letter S. +#define ASCII_CODE_LETTER_T 0x54 ///< ASCII code in hex for letter T. +#define ASCII_CODE_LETTER_U 0x55 ///< ASCII code in hex for letter U. +#define ASCII_CODE_LETTER_V 0x56 ///< ASCII code in hex for letter V. +#define ASCII_CODE_LETTER_W 0x57 ///< ASCII code in hex for letter W. +#define ASCII_CODE_LETTER_X 0x58 ///< ASCII code in hex for letter X. +#define ASCII_CODE_LETTER_Y 0x59 ///< ASCII code in hex for letter Y. +#define ASCII_CODE_LETTER_Z 0x5A ///< ASCII code in hex for letter Z. + +#define ASCII_CODE_NUMBER_ZERO 0x30 ///< ASCII code in hex for number zero. +#define ASCII_CODE_NUMBER_ONE 0x31 ///< ASCII code in hex for number one. +#define ASCII_CODE_NUMBER_TWO 0x32 ///< ASCII code in hex for number two. +#define ASCII_CODE_NUMBER_THREE 0x33 ///< ASCII code in hex for number three. +#define ASCII_CODE_NUMBER_FOUR 0x34 ///< ASCII code in hex for number four. +#define ASCII_CODE_NUMBER_FIVE 0x35 ///< ASCII code in hex for number five. +#define ASCII_CODE_NUMBER_SIX 0x36 ///< ASCII code in hex for number six. +#define ASCII_CODE_NUMBER_SEVEN 0x37 ///< ASCII code in hex for number seven. +#define ASCII_CODE_NUMBER_EIGHT 0x38 ///< ASCII code in hex for number eight. +#define ASCII_CODE_NUMBER_NINE 0x39 ///< ASCII code in hex for number nine. + +// **** Common Macros **** + +#define FLOAT_TO_INT_WITH_ROUND(f) ((f) < 0.0F ? (S32)((f) - FLOAT_TO_INT_ROUNDUP_OFFSET) : (S32)((f) + FLOAT_TO_INT_ROUNDUP_OFFSET)) ///< Macro converts a floating point value to an integer +#define CAP(v, u) ((v) > (u) ? (u) : (v)) ///< Macro caps a value to a maximum +#define RANGE(v, l, u) ((v) > (u) ? (u) : ((v) < (l) ? (l) : (v))) ///< Macro enforces a range on a value +#define INC_WRAP(v, l, u) ((v) >= (u) ? (l) : ((v) + 1)) ///< Macro increments a value and wraps to a minimum when a maximum is reached +#define DEC_WRAP(v, l, u) ((v) <= (l) ? (u) : ((v) - 1)) ///< Macro decrements a value and wraps to a maximum when a minimum is reached +#define INC_CAP(v, u) ((v) >= (u) ? (u) : ((v) + 1)) ///< Macro increments a value but does not allow to exceed a maximum +#define MAX(a, b) ((a) < (b) ? (b) : (a)) ///< Macro enforces a maximum on a value +#define MIN(a, b) ((a) > (b) ? (b) : (a)) ///< Macro enforces a minimum on a value +#define GET_LSB_OF_WORD(w) ((U08)((w) & MASK_OFF_MSB)) ///< Macro returns the least signficant byte of a 2-byte word +#define GET_MSB_OF_WORD(w) ((U08)(((w) >> SHIFT_8_BITS_FOR_BYTE_SHIFT) & MASK_OFF_MSB)) ///< Macro returns the most signficant byte of a 2-byte word +#define GET_LSW_OF_LONG(l) ((U16)((l) & MASK_OFF_MSW)) ///< Macro returns the least signficant 2-byte word of a 4-byte word +#define GET_MSW_OF_LONG(l) ((U16)(((l) >> SHIFT_16_BITS_FOR_WORD_SHIFT) & MASK_OFF_MSW)) ///< Macro returns the most signficant 2-byte word of a 4-byte word +#define MAKE_WORD_OF_BYTES(h, l) ((((U16)(h) << SHIFT_8_BITS_FOR_BYTE_SHIFT) & MASK_OFF_LSB) | ((U16)(l) & MASK_OFF_MSB)) ///< Macro merges two bytes into a 2-byte word +#define MAKE_LONG_OF_WORDS(h, l) ((((U32)(h) << SHIFT_16_BITS_FOR_WORD_SHIFT) & MASK_OFF_LSW) | ((U32)(l) & MASK_OFF_MSW)) ///< Macro merges two 2-byte words into a 4-byte word +#define GET_TOGGLE(v, l, h) ((v) == (l) ? (h) : (l)) ///< Macro toggles a value +#define BIT_BY_POS(p) (1U << (p)) ///< Macro returns a bit mask for a bit of given position +#define RAD2DEG(r) ((r) * 180.0F / PI) ///< Macro converts radians to degrees + +/// Macro to set a specific alarm with 1 piece of unsigned 32-bit alarm data. +#define SET_ALARM_WITH_1_U32_DATA(a,d1) { \ + ALARM_DATA_T dat1; \ + dat1.dataType = ALARM_DATA_TYPE_U32; \ + dat1.data.uInt.data = (U32)(d1); \ + activateAlarm1Data( a, dat1 ); \ +} + +/// Macro to set a specific alarm with 1 piece of floating point alarm data. +#define SET_ALARM_WITH_1_F32_DATA(a,d1) { \ + ALARM_DATA_T dat1; \ + dat1.dataType = ALARM_DATA_TYPE_F32; \ + dat1.data.flt.data = (F32)(d1); \ + activateAlarm1Data( a, dat1 ); \ +} + +/// Macro to set a specific alarm with 2 pieces of unsigned 32-bit alarm data. +#define SET_ALARM_WITH_2_U32_DATA(a,d1,d2) { \ + ALARM_DATA_T dat1; \ + ALARM_DATA_T dat2; \ + dat1.dataType = ALARM_DATA_TYPE_U32; \ + dat1.data.uInt.data = (U32)(d1); \ + dat2.dataType = ALARM_DATA_TYPE_U32; \ + dat2.data.uInt.data = (U32)(d2); \ + activateAlarm2Data( a, dat1, dat2, FALSE ); \ +} + +/// Macro to set a specific alarm with 2 pieces of floating point alarm data. +#define SET_ALARM_WITH_2_F32_DATA(a,d1,d2) { \ + ALARM_DATA_T dat1; \ + ALARM_DATA_T dat2; \ + dat1.dataType = ALARM_DATA_TYPE_F32; \ + dat1.data.flt.data = (F32)(d1); \ + dat2.dataType = ALARM_DATA_TYPE_F32; \ + dat2.data.flt.data = (F32)(d2); \ + activateAlarm2Data( a, dat1, dat2, FALSE ); \ +} + +/// Record structure for unsigned integer event data. +typedef struct +{ + U32 data; ///< Event data of unsigned integer type. +} EVENT_DATA_U32_T; + +/// Record structure for signed integer event data. +typedef struct +{ + S32 data; ///< Event data of signed integer type. +} EVENT_DATA_S32_T; + +/// Record structure for floating point event data. +typedef struct +{ + F32 data; ///< Event data of floating point type. +} EVENT_DATA_F32_T; + +/// Record structure for boolean event data. +typedef struct +{ + BOOL data; ///< Event data of boolean type. +} EVENT_DATA_BOOL_T; + +/// Record structure for event data of any supported type. +typedef union +{ + EVENT_DATA_U32_T uInt; ///< Event data of unsigned integer type. + EVENT_DATA_S32_T sInt; ///< Event data of signed integer type. + EVENT_DATA_F32_T flt; ///< Event data of floating point type. + EVENT_DATA_BOOL_T bln; ///< Event data of boolean type. +} EVENT_DATAS_T; + +/// Event data types list. +typedef enum Event_Data_Types +{ + EVENT_DATA_TYPE_NONE = 0, ///< No data given. + EVENT_DATA_TYPE_U32 = 1, ///< Event data is unsigned 32-bit integer type. + EVENT_DATA_TYPE_S32 = 2, ///< Event data is signed 32-bit integer type. + EVENT_DATA_TYPE_F32 = 3, ///< Event data is 32-bit floating point type. + EVENT_DATA_TYPE_BOOL = 4, ///< Event data is 32-bit boolean type. + NUM_OF_EVENT_DATA_TYPES ///< Total number of event data types. +} EVENT_DATA_TYPES_T; + +/// Record structure for event data including the data type to aid in interpretation. +typedef struct +{ + EVENT_DATA_TYPES_T dataType; ///< The type of event data provided. + EVENT_DATAS_T data; ///< The event data of specified type. +} EVENT_DATA_T; + +/// Payload record structure for event messages. +typedef struct +{ + U32 event; ///< Event ID + U32 dataType1; ///< Data type for data field 1 + EVENT_DATAS_T data1; ///< data field 1 + U32 dataType2; ///< Data type for data field 2 + EVENT_DATAS_T data2; ///< Data field 2 +} EVENT_PAYLOAD_T; + +/// Macro to set a specific alarm with 2 pieces of unsigned 32-bit alarm data. +#define SEND_EVENT_WITH_2_U32_DATA(e,d1,d2) { \ + EVENT_DATA_T dat1; \ + EVENT_DATA_T dat2; \ + dat1.dataType = EVENT_DATA_TYPE_U32; \ + dat1.data.uInt.data = (U32)(d1); \ + dat2.dataType = EVENT_DATA_TYPE_U32; \ + dat2.data.uInt.data = (U32)(d2); \ + sendEvent( e, dat1, dat2 ); \ +} + +/// Macro to set a specific alarm with 2 pieces of floating point alarm data. +#define SEND_EVENT_WITH_2_F32_DATA(e,d1,d2) { \ + EVENT_DATA_T dat1; \ + EVENT_DATA_T dat2; \ + dat1.dataType = EVENT_DATA_TYPE_F32; \ + dat1.data.flt.data = (F32)(d1); \ + dat2.dataType = EVENT_DATA_TYPE_F32; \ + dat2.data.flt.data = (F32)(d2); \ + sendEvent( e, dat1, dat2 ); \ +} + +// **** Common Data **** + +#ifndef _RELEASE_ +/// Hardware configuration +typedef enum Hardware_Configurations +{ + HW_CONFIG_BETA = 1, ///< Hardware configuration beta + HW_CONFIG_DVT, ///< Hardware configuration DVT + NUM_OF_HW_CONFIGS, ///< Number of hardware configurations +} HARDWARE_CONFIG_T; +#endif + +/// Heaters data structure. +typedef struct +{ + F32 mainPrimayHeaterDC; ///< Main primary heater DC + F32 smallPrimaryHeaterDC; ///< Small primary heater DC + F32 trimmerHeaterDC; ///< Trimmer heater DC + F32 primaryTargetTemp; ///< Primary heater target temperature + F32 trimmerTargetTemp; ///< Trimmer heater target temperature + U32 primaryHeaterState; ///< Primary heater state + U32 trimmerHeaterState; ///< Trimmer heater state + F32 primaryEfficiency; ///< Primary heater efficiency + F32 primaryCalcTargetTemp; ///< Primary heater calculated target temperature + F32 trimmerCalcCurrentTemp; ///< Trimmer heater calculated current temperature + U32 trimmerUseLastDC; ///< Trimmer heater use last duty cycle + F32 previsouFlow; ///< Trimmer heater previous flow L/min + U32 controlCounter; ///< Trimmer heater control count +} HEATERS_DATA_T; + +/// Temperature sensors data structure. +typedef struct +{ + F32 inletPrimaryHeater; ///< Inlet primary heater temperature sensor + F32 heatDisinfect; ///< Heat Disinfect temperature sensor + F32 outletPrimaryHeater; ///< Outlet primary heater temperature sensor + F32 conductivitySensor1; ///< Conductivity sensor 1 temperature sensor + F32 conductivitySensor2; ///< Conductivity sensor 2 temperature sensor + F32 outletRedundant; ///< Outlet redundant temperature sensor + F32 inletDialysate; ///< Inlet dialysate temperature sensor + F32 primaryHeaterThermocouple; ///< Primary heaters thermocouple sensor + F32 trimmerHeaterThermocouple; ///< Trimmer heater thermocouple sensor + F32 priamyHeaterColdjunction; ///< Primary heaters cold junction temperature sensor + F32 trimmerHeaterColdjunction; ///< Trimmer heater cold junction temperature sensor + F32 primaryHeaterInternal; ///< Primary heaters internal temperature (calculated from thermocouple and cold junction) + F32 trimmerHeaterInternal; ///< Trimmer heater internal temperature (calculated from thermocouple and cold junction) + F32 fpgaBoard; ///< FPGA board temperature sensor + F32 loadCellA1B1; ///< Load cell A1/B1 temperature sensor + F32 loadCellA2B2; ///< Load cell A2/B2 temperature sensor + F32 internalTHDORTD; ///< THDo RTD channel temperature sensor + F32 internalTDIRTD; ///< TDI RTD channel temperature sensor + F32 interalTHDRTD; ///< THd RTD channel temperature sensor + F32 internalCondSnsrTemp; ///< Conductivity Sensor internal temperature sensor + F32 baroTempSensor; ///< Barometric temperature sensor + F32 dialysateInletMovingAvg; ///< Dialysate inlet moving average + F32 redundantOutletMovingAvg; ///< Redundant outlet moving average +} TEMPERATURE_SENSORS_DATA_T; + +/// Dialysate heating parameters +typedef struct +{ + F32 trimmerTargetTemperature; ///< Trimmer Target temperature. + U32 timeReservoirCycleMS; ///< Reservoir cycle time in milliseconds. + F32 timeReservoirFillMS; ///< Reservoir fill time in milliseconds. + U32 timeReservoirWait2SwitchMS; ///< Wait to switch active reservoir time in milliseconds. + F32 dialysateFlowLPM; ///< Dialysate flow rate in L/min. + BOOL usePriTargetTempEquation; ///< Use primary heater target temperature estimation equation or not. +} DG_CMD_DIALYSATE_HEATING_PARAMS_T; + +/// Loadcell measurements struct. +typedef struct +{ + F32 loadCellA1inGram; ///< Loadcell A1 measurement in gram + F32 loadCellA2inGram; ///< Loadcell A2 measurement in gram + F32 loadCellB1inGram; ///< Loadcell B1 measurement in gram + F32 loadCellB2inGram; ///< Loadcell B2 measurement in gram +} LOAD_CELL_DATA_T; + +/// Flow meters data struct. +typedef struct +{ + F32 ROFlowRateLPM; ///< RO flow rate in L/min. + F32 ROFlowRateWithCPsLPM; ///< RO flow rate with concentrate pumps in L/min. + F32 dialysateFlowRateLPM; ///< Dialysate flow rate L/min. + F32 RORawFlowRateLPM; ///< Raw RO flow rate in L/min. + F32 dialysateRawFlowRateLPM; ///< Raw dialysate flow rate in L/min. +} FLOW_SENSORS_DATA_T; + +/// DG switch reservoirs command structure +typedef struct +{ + U32 reservoirID; ///< DG reservoir ID. + BOOL useLastTrimmerHeaterDC; ///< Use last trimmer heater duty cycle flag. +} DG_SWITCH_RSRVRS_CMD_T; + +/// DG change valve settings command structure +typedef struct +{ + U32 valveSettingCmd; ///< DG valve setting command. +} DG_VALVE_SETTING_CMD_REQUEST_T; + +/// DG fill command structure +typedef struct +{ + U32 fillToVolMl; ///< fill to volume in mL. + U32 cmd; ///< DG cmd. + F32 targetFlowRateLPM; ///< target flow rate in LPM. +} DG_FILL_CMD_T; + +/// DG start stop command structure +typedef struct +{ + BOOL start; ///< DG start stop cmd. + U32 acidType; ///< Acid type. + U32 bicarbType; ///< Bicarb type. +} DG_START_STOP_TX_CMD_REQUEST_T; + +/// DG start stop trimmer heater command structure +typedef struct +{ + BOOL start; ///< DG start stop trimmer heater. +} DG_START_STOP_TRIMMER_HEATER_CMD_T; + +/// DG flush mode start stop command structure +typedef struct +{ + BOOL start; ///< DG start stop flush mode. +} DG_FLUSH_MODE_CMD_T; + +/// DG heat disinfect mode start stop command structure +typedef struct +{ + BOOL start; ///< DG start stop heat disinfection mode. +} DG_HEAT_DISINFECTION_MODE_CMD_T; + +/// DG chemical disinfect mode start stop command structure +typedef struct +{ + BOOL start; ///< DG start stop chem disinfection mode. +} DG_CHEM_DISINFECTION_MODE_CMD_T; + +/// DG sample water command structure. +typedef struct +{ + U32 cmd; ///< DG sample water command. +} DG_SAMPLE_WATER_CMD_REQUEST_T; + +#pragma pack(push, 1) +/// DG usage info structure. +typedef struct +{ + F32 roWaterGenTotalL; ///< Total RO water generated in liters. (Cannot be reset) + F32 roWaterGenSinceLastServiceL; ///< RO water generated since last treatment in liters. + U32 lastBasicFlushCompleteDateEpoch; ///< Last basic flush complete date in epoch. + U32 lastChemDisStartDateEpoch; ///< Last chemical disinfect start date in epoch. + U32 lastChemDisCompleteDateEpoch; ///< Last chemical disinfect complete date in epoch. + U32 lastChemDisFlushCompleteDateEpoch; ///< Last chemical disinfect flush complete date in epoch. + U32 lastHeatDisCompleteDateEpoch; ///< Last heat disinfect complete date in epoch. + U32 lastHeatActiveCoolCompleteDateEpoch; ///< Last heat disinfect active cool complete date in epoch. + U32 lastFilterFlushCompleteDateEpoch; ///< Last filter flush complete date in epoch. + U32 lastResetTimeEpoch; ///< Last time the record was reset in epoch. + U16 crc; ///< CRC for the DG usage info structure. +} DG_USAGE_INFO_RECORD_T; + +/// DG service record structure +typedef struct +{ + U08 serviceLoc; ///< DG service location. + U32 lastServiceEpochDate; ///< DG last service date in epoch. + U32 serviceIntervalSeconds; ///< DG service interval in seconds. + U32 lastResetTimeEpoch; ///< Last time the record was reset in epoch. + U16 crc; ///< CRC for the DG service record structure. +} DG_SERVICE_RECORD_T; +#pragma pack(pop) + +// **** VectorCAST Definitions **** + +#ifdef _VECTORCAST_ + #define _enable_IRQ() + #define _disable_IRQ() + #define _enable_FIQ() +#endif + +// include alarm mgmt header so any module can trigger an alarm +#include "AlarmMgmt.h" +#ifdef _TD_ +#include "AlarmMgmtTD.h" +#endif +#ifdef _DD_ +#include "AlarmMgmtDD.h" +#endif +#ifdef _RD_ +#include "AlarmMgmtRO.h" +#endif + +// include Message definitions header for access to system message IDs +#include "MsgDefs.h" + +// include test support definitions and macros +#include "TestSupport.h" + +/**@}*/ + +#endif Index: FPGA.c =================================================================== diff -u --- FPGA.c (revision 0) +++ FPGA.c (revision 6d80d69a210f45c733e5307859351f2cd820a8e7) @@ -0,0 +1,836 @@ +/************************************************************************** +* +* 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) Sean Nash +* @date (last) 10-Sep-2023 +* +* @author (original) Dara Navaei +* @date (original) 05-Nov-2019 +* +***************************************************************************/ + +#include // For memset(), memcpy() + +#include "sci.h" +#include "sys_dma.h" + +#include "Comm.h" +#include "Compatible.h" +#include "FPGA.h" +#ifdef _TD_ +#include "FpgaTD.h" +#endif +#ifdef _DD_ +#include "FpgaDD.h" +#endif +#ifdef _RO_ +#include "FpgaRO.h" +#endif +#include "Messaging.h" +#include "OperationModes.h" +#include "PersistentAlarm.h" +#include "Timers.h" +#include "Utilities.h" + +/** + * @addtogroup FPGA + * @{ + */ + +// ********** private definitions ********** + +/// Enumeration of FPGA states. +typedef enum FPGA_States +{ + FPGA_STATE_START = 0, ///< Start state for the FPGA. + FPGA_STATE_READ_HEADER, ///< Read header command state for the FPGA. + 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_FAILED, ///< Failed state for the FPGA. + NUM_OF_FPGA_STATES ///< Number of FPGA states. +} FPGA_STATE_T; + +#define FPGA_PAGE_SIZE 256 ///< FPGA register pages are 256 bytes. + +#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_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. +#define FPGA_WRITE_RSP_BUFFER_LEN 8 ///< FPGA write command response buffer byte length. +#define FPGA_READ_RSP_BUFFER_LEN (FPGA_PAGE_SIZE+8) ///< FPGA read command response buffer byte length. + +#define FPGA_WRITE_CMD_CODE 0x55 ///< FPGA write command code. +#define FPGA_READ_CMD_CODE 0x5A ///< FPGA read command code. +#define FPGA_WRITE_CMD_ACK 0xA5 ///< FPGA write command ACK code. +#define FPGA_READ_CMD_ACK 0xAA ///< FPGA read command ACK code. +#define FPGA_CMD_NAK 0xEE ///< FPGA command NAK code. + +#define FPGA_CRC_LEN 2 ///< FPGA CRC byte length. +#define FPGA_WRITE_CMD_HDR_LEN 4 ///< FPGA write command header byte length. +#define FPGA_READ_CMD_HDR_LEN 4 ///< FPGA read command header byte length. +#define FPGA_WRITE_RSP_HDR_LEN 3 ///< FPGA write command response header byte length. +#define FPGA_READ_RSP_HDR_LEN 3 ///< FPGA read command response header byte length. + +#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 FPGA_INPUT_VOLTAGE_SCALE 3.0F ///< FPGA source and aux voltage. +#define FPGA_PVN_VOLTAGE_SCALE 1.0F ///< FPGA pvn voltage. + +#define FPGA_ADC1_AUTO_READ_ENABLE 0x01 ///< Auto-read enable bit for ADC1 control register. + +#define FPGA_AIRTRAP_LEVEL_LOW_MASK 0x0008 ///< Bit mask for air trap lower level sensor. +#define FPGA_AIRTRAP_LEVEL_HIGH_MASK 0x0004 ///< Bit mask for air trap upper level sensor. + +#define FPGA_FLUID_LEAK_STATE_MASK 0x0040 ///< Bit mask for fluid leak detector. + +#define FPGA_BLOOD_LEAK_STATUS_MASK 0x1000 ///< Bit mask for blood leak detector. +#define FPGA_BLOOD_LEAK_ST_BIT_INDEX 12 ///< Bit index for the blood leak self test status bit. +#define FPGA_BLOOD_LEAK_ZERO_STATE_MASK 0x2000 ///< Bit mask for blood leak detector zero. +#define FPAG_BLOOD_LEAK_ZERO_BIT_INDEX 13 ///< Bit index for the blood leak zero status bit. +#define FPGA_BLOOD_LEAK_ZERO_CMD 0x02 ///< Bit for blood leak detector zero command. +#define FPGA_BLOOD_LEAK_SELF_TEST_CMD 0x01 ///< Bit for blood leak detector self test command. + +#define FPGA_ADA_BUBBLE_STATUS_MASK 0x0001 ///< Bit mask for arterial air bubble detector input status. +#define FPGA_ADV_BUBBLE_STATUS_MASK 0x0002 ///< Bit mask for venous air bubble detector input status. +#define FPGA_ADA_BUBBLE_SELF_TEST_CMD 0x04 ///< Bit for arterial air bubble detector self-test command. +#define FPGA_ADV_BUBBLE_SELF_TEST_CMD 0x08 ///< Bit for venous air bubble detector self-test command. + +#define FPGA_PBO_TEMP_DIVISOR 2047.0F ///< Used in conversion of PBo temperature reading to deg C. +#define FPGA_PBO_TEMP_GAIN 200.0F ///< Used in conversion of PBo temperature reading to deg C. +#define FPGA_PBO_TEMP_OFFSET 50.0F ///< Used in conversion of PBo temperature reading to deg C. + +#define FPGA_ALARM_AUDIO_VOLUME_SHIFT 3 ///< Shift alarm audio volume 3 bits to left before writing to register. +#define FPGA_ALARM_AUDIO_DIVIDE_SHIFT 6 ///< Shift alarm audio volume divider 6 bits to left before writing to register. + +#define FPGA_BACKUP_ALARM_AUDIO_CONVERT 0.4F ///< Converts backup (piezo) alarm audio ADC volts to amps. + +#define FRONT_DOOR_SWITCH_MASK 0x0010 ///< Front door switch bit mask. Bit 4 of the GPIO register. +#define PUMP_TRACK_SWITCH_MASK 0x0020 ///< Pump track switch bit mask. Bit 5 of the GPIO register. + +#define FPGA_VALVES_MIN_PWM_MODE_COUNT 2500 ///< FPGA valves minimum PWM in PWM mode in counts. + +// ********** private data ********** + +// FPGA state +static FPGA_STATE_T fpgaState = FPGA_STATE_START; ///< Current FPGA state. + +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. +static BOOL fpgaReadCommandInProgress = FALSE; ///< Flag indicating an FPGA read command is in progress. +static BOOL fpgaBulkWriteAndReadInProgress = FALSE; ///< Flag indicating an FPGA bulk write and read command are in progress. +static BOOL fpgaWriteCommandResponseReceived = FALSE; ///< Flag indicating a response to an FPGA write command has been received. +static BOOL fpgaReadCommandResponseReceived = FALSE; ///< Flag indicating a response to an FPGA read command has been received. + +// FPGA comm buffers +static U08 fpgaWriteCmdBuffer[ FPGA_WRITE_CMD_BUFFER_LEN ]; ///< FPGA write command buffer. Holds the next FPGA write command to be transmitted. +static U08 fpgaReadCmdBuffer[ FPGA_READ_CMD_BUFFER_LEN ]; ///< FPGA read command buffer. Holds the next FPGA read command to be transmitted. +static U08 fpgaWriteResponseBuffer[ FPGA_WRITE_RSP_BUFFER_LEN ]; ///< FPGA write command response buffer. Memory reserved to capture the response to the last FPGA write command. +static U08 fpgaReadResponseBuffer[ FPGA_READ_RSP_BUFFER_LEN ]; ///< FPGA read command response buffer. Memory reserved to capture the response to the last FPGA read command. + +// DMA control records +static g_dmaCTRL fpgaDMAWriteControlRecord; ///< DMA record for controlling a DMA write command transmission from buffer. +static g_dmaCTRL fpgaDMAWriteRespControlRecord; ///< DMA record for controlling a DMA write command reception to buffer. +static g_dmaCTRL fpgaDMAReadControlRecord; ///< DMA record for controlling a DMA read command transmission from buffer. +static g_dmaCTRL fpgaDMAReadRespControlRecord; ///< DMA record for controlling a DMA read command reception to buffer. + +// FPGA data +static U08* fpgaHeaderPtr; ///< Record of last received FPGA header data. +static U08* fpgaSensorReadingsPtr; ///< Record of last received FPGA priority sensor data. +static U08* fpgaActuatorSetPointsPtr; ///< Record of next transmitted FPGA priority actuator data. +static U32 fpgaHeaderSize; ///< FPGA header record byte size. +static U32 fpgaSensorReadingsSize; ///< FPGA sensor readings record byte size. +static U32 fpgaActuatorSetPointsSize; ///< FPGA actuator set points record byte size. + +// ********** private function prototypes ********** + +static FPGA_STATE_T handleFPGAReadHeaderState( void ); +static FPGA_STATE_T handleFPGAReceiveHeaderState( void ); +static FPGA_STATE_T handleFPGAWriteAllActuatorsState( void ); +static FPGA_STATE_T handleFPGAReceiveAllSensorsState( void ); + +static void resetFPGACommFlags( void ); +static void setupDMAForWriteCmd( U32 bytes2Transmit ); +static void startDMAWriteCmd( void ); +static void setupDMAForWriteResp( U32 bytes2Receive ); +static void startDMAReceiptOfWriteResp( void ); +static void setupDMAForReadCmd( U32 bytes2Transmit ); +static void startDMAReadCmd( void ); +static void setupDMAForReadResp( U32 bytes2Receive ); +static void startDMAReceiptOfReadResp( void ); + +static void consumeUnexpectedData( void ); +static void monitorFPGAPowerStatus( void ); + +/*********************************************************************//** + * @brief + * The initFPGA function initializes the FPGA module. + * @details Inputs: none + * @details Outputs: FPGA module initialized. + * @return none + *************************************************************************/ +void initFPGA( U08* hdr, U08* sen, U08* act, U32 hdrSize, U32 senSize, U32 actSize ) +{ + // Initialize fpga data structure pointers + fpgaHeaderPtr = hdr; + fpgaSensorReadingsPtr = sen; + fpgaActuatorSetPointsPtr = act; + fpgaHeaderSize = hdrSize; + fpgaSensorReadingsSize = senSize; + fpgaActuatorSetPointsSize = actSize; + + // Enable interrupt notifications for FPGA serial port + sciEnableNotification( scilinREG, SCI_OE_INT | SCI_FE_INT ); + + // Assign DMA channels to h/w DMA requests + dmaReqAssign( DMA_CH0, SCI2_RECEIVE_DMA_REQUEST ); + dmaReqAssign( DMA_CH2, SCI2_TRANSMIT_DMA_REQUEST ); + // Set DMA channel priorities + dmaSetPriority( DMA_CH0, HIGHPRIORITY ); + dmaSetPriority( DMA_CH2, LOWPRIORITY ); + // Enable DMA block transfer complete interrupts + dmaEnableInterrupt( DMA_CH0, BTC ); + dmaEnableInterrupt( DMA_CH2, BTC ); + + // Initialize FPGA DMA Write Control Record + fpgaDMAWriteControlRecord.PORTASGN = 4; // Port B (only choice per datasheet) + fpgaDMAWriteControlRecord.SADD = (U32)fpgaWriteCmdBuffer; // Transfer source address + fpgaDMAWriteControlRecord.DADD = (U32)(&(scilinREG->TD)); // Dest. is SCI2 xmit register + fpgaDMAWriteControlRecord.CHCTRL = 0; // No chaining + fpgaDMAWriteControlRecord.ELCNT = 1; // Frame is 1 element + fpgaDMAWriteControlRecord.FRCNT = 0; // Block is TBD frames - will be populated later when known + fpgaDMAWriteControlRecord.RDSIZE = ACCESS_8_BIT; // Element size is 1 byte + fpgaDMAWriteControlRecord.WRSIZE = ACCESS_8_BIT; // + fpgaDMAWriteControlRecord.TTYPE = FRAME_TRANSFER; // Transfer type is block transfer + fpgaDMAWriteControlRecord.ADDMODERD = ADDR_INC1; // Source addressing mode is post-increment + fpgaDMAWriteControlRecord.ADDMODEWR = ADDR_FIXED; // Dest. addressing mode is fixed + fpgaDMAWriteControlRecord.AUTOINIT = AUTOINIT_OFF; // Auto-init off + fpgaDMAWriteControlRecord.ELSOFFSET = 0; // Not used + fpgaDMAWriteControlRecord.ELDOFFSET = 0; // Not used + fpgaDMAWriteControlRecord.FRSOFFSET = 0; // Not used + fpgaDMAWriteControlRecord.FRDOFFSET = 0; // Not used + + // Initialize FPGA DMA Write Response Control Record + fpgaDMAWriteRespControlRecord.PORTASGN = 4; // Port B (only choice per datasheet) + fpgaDMAWriteRespControlRecord.SADD = (U32)(&(scilinREG->RD));// Source is SCI2 recv register + fpgaDMAWriteRespControlRecord.DADD = (U32)fpgaWriteResponseBuffer; // Transfer destination address + fpgaDMAWriteRespControlRecord.CHCTRL = 0; // No chaining + fpgaDMAWriteRespControlRecord.ELCNT = 1; // Frame is 1 element + fpgaDMAWriteRespControlRecord.FRCNT = 0; // Block is TBD frames - will be populated later when known + fpgaDMAWriteRespControlRecord.RDSIZE = ACCESS_8_BIT; // Element size is 1 byte + fpgaDMAWriteRespControlRecord.WRSIZE = ACCESS_8_BIT; // + fpgaDMAWriteRespControlRecord.TTYPE = FRAME_TRANSFER; // Transfer type is block transfer + fpgaDMAWriteRespControlRecord.ADDMODERD = ADDR_FIXED; // Source addressing mode is fixed + fpgaDMAWriteRespControlRecord.ADDMODEWR = ADDR_INC1; // Dest. addressing mode is post-increment + fpgaDMAWriteRespControlRecord.AUTOINIT = AUTOINIT_OFF; // Auto-init off + fpgaDMAWriteRespControlRecord.ELDOFFSET = 0; // Not used + fpgaDMAWriteRespControlRecord.ELSOFFSET = 0; // Not used + fpgaDMAWriteRespControlRecord.FRDOFFSET = 0; // Not used + fpgaDMAWriteRespControlRecord.FRSOFFSET = 0; // Not used + + // Initialize FPGA DMA Read Control Record + fpgaDMAReadControlRecord.PORTASGN = 4; // Port B (only choice per datasheet) + fpgaDMAReadControlRecord.SADD = (U32)fpgaReadCmdBuffer; // Transfer source address + fpgaDMAReadControlRecord.DADD = (U32)(&(scilinREG->TD)); // Dest. is SCI2 xmit register + fpgaDMAReadControlRecord.CHCTRL = 0; // No chaining + fpgaDMAReadControlRecord.ELCNT = 1; // Frame is 1 element + fpgaDMAReadControlRecord.FRCNT = 0; // Block is TBD frames - will be populated later when known + fpgaDMAReadControlRecord.RDSIZE = ACCESS_8_BIT; // Element size is 1 byte + fpgaDMAReadControlRecord.WRSIZE = ACCESS_8_BIT; // + fpgaDMAReadControlRecord.TTYPE = FRAME_TRANSFER; // Transfer type is block transfer + fpgaDMAReadControlRecord.ADDMODERD = ADDR_INC1; // Source addressing mode is post-increment + fpgaDMAReadControlRecord.ADDMODEWR = ADDR_FIXED; // Dest. addressing mode is fixed + fpgaDMAReadControlRecord.AUTOINIT = AUTOINIT_OFF; // Auto-init off + fpgaDMAReadControlRecord.ELSOFFSET = 0; // Not used + fpgaDMAReadControlRecord.ELDOFFSET = 0; // Not used + fpgaDMAReadControlRecord.FRSOFFSET = 0; // Not used + fpgaDMAReadControlRecord.FRDOFFSET = 0; // Not used + + // Initialize FPGA DMA Read Response Control Record + fpgaDMAReadRespControlRecord.PORTASGN = 4; // Port B (only choice per datasheet) + fpgaDMAReadRespControlRecord.SADD = (U32)(&(scilinREG->RD)); // Source is SCI2 recv register + fpgaDMAReadRespControlRecord.DADD = (U32)fpgaReadResponseBuffer; // Transfer destination address + fpgaDMAReadRespControlRecord.CHCTRL = 0; // No chaining + fpgaDMAReadRespControlRecord.ELCNT = 1; // Frame is 1 element + fpgaDMAReadRespControlRecord.FRCNT = 0; // Block is TBD frames - will be populated later when known + fpgaDMAReadRespControlRecord.RDSIZE = ACCESS_8_BIT; // Element size is 1 byte + fpgaDMAReadRespControlRecord.WRSIZE = ACCESS_8_BIT; // + fpgaDMAReadRespControlRecord.TTYPE = FRAME_TRANSFER; // Transfer type is block transfer + fpgaDMAReadRespControlRecord.ADDMODERD = ADDR_FIXED; // Source addressing mode is fixed + fpgaDMAReadRespControlRecord.ADDMODEWR = ADDR_INC1; // Dest. addressing mode is post-increment + fpgaDMAReadRespControlRecord.AUTOINIT = AUTOINIT_OFF; // Auto-init off + fpgaDMAReadRespControlRecord.ELDOFFSET = 0; // Not used + fpgaDMAReadRespControlRecord.ELSOFFSET = 0; // Not used + fpgaDMAReadRespControlRecord.FRDOFFSET = 0; // Not used + fpgaDMAReadRespControlRecord.FRSOFFSET = 0; // Not used + + // There should not be any data pending yet + consumeUnexpectedData(); +} + +/*********************************************************************//** + * @brief + * The resetFPGACommFlags function resets the various fpga comm flags and + * counters. + * @details Inputs: none + * @details Outputs: fpga comm flags & counters reset + * @return none + *************************************************************************/ +static void resetFPGACommFlags( void ) +{ + fpgaWriteCommandResponseReceived = FALSE; + fpgaReadCommandResponseReceived = FALSE; + fpgaWriteCommandInProgress = FALSE; + fpgaReadCommandInProgress = FALSE; + fpgaBulkWriteAndReadInProgress = FALSE; + fpgaTransmitCounter = 0; + fpgaReceiptCounter = 0; +} + +/*********************************************************************//** + * @brief + * The signalFPGAReceiptCompleted function increments a counter to indicate + * that another DMA receipt from the FPGA has completed. + * @details Inputs: none + * @details Outputs: fpgaReceiptCounter + * @return none + *************************************************************************/ +void signalFPGAReceiptCompleted( void ) +{ + fpgaReceiptCounter++; + // Did FPGA Ack last command? + if ( TRUE == fpgaWriteCommandInProgress ) + { + fpgaWriteCommandInProgress = FALSE; + fpgaWriteCommandResponseReceived = TRUE; + } + else if ( TRUE == fpgaReadCommandInProgress ) + { + fpgaReadCommandInProgress = FALSE; + fpgaReadCommandResponseReceived = TRUE; + } + + // See if we want to follow up with a bulk read command + if ( TRUE == fpgaBulkWriteAndReadInProgress ) + { + fpgaBulkWriteAndReadInProgress = FALSE; + fpgaReadCommandInProgress = TRUE; + // Initiate bulk read command + startDMAReceiptOfReadResp(); + startDMAReadCmd(); + } +} + +/*********************************************************************//** + * @brief + * The signalFPGATransmitCompleted function increments a counter to indicate + * that another DMA transmit to the FPGA has completed. + * @details Inputs: none + * @details Outputs: fpgaReceiptCounter + * @return none + *************************************************************************/ +void signalFPGATransmitCompleted( void ) +{ + fpgaTransmitCounter++; +} + +/*********************************************************************//** + * @brief + * The execFPGA function manages incoming data exchanges with the FPGA. + * @details Inputs: fpgaState + * @details Outputs: fpgaState + * @return none + *************************************************************************/ +void execFPGAIn( void ) +{ + + // Check if FE or OE error has occurred + checkFPGAFEOEFailure(); + + // FPGA incoming state machine + switch ( fpgaState ) + { + case FPGA_STATE_START: + fpgaState = FPGA_STATE_READ_HEADER; + break; + + case FPGA_STATE_RCV_HEADER: + fpgaState = handleFPGAReceiveHeaderState(); + break; + + case FPGA_STATE_RCV_ALL_SENSORS: + fpgaState = handleFPGAReceiveAllSensorsState(); + break; + + case FPGA_STATE_FAILED: + // Do nothing - we will be stuck here + break; + + default: + if ( fpgaState >= NUM_OF_FPGA_STATES ) + { +// SET_ALARM_WITH_2_U32_DATA( ALARM_ID_TD_SOFTWARE_FAULT, SW_FAULT_ID_FPGA_INVALID_IN_STATE, fpgaState ) + } + else + { + // Ok, some states handled in the outgoing state machine + } + break; + } + + // Reset comm flags after processing incoming responses + resetFPGACommFlags(); + + // Monitor the power status + monitorFPGAPowerStatus(); +} + +/*********************************************************************//** + * @brief + * The execFPGAOut function manages outgoing data exchanges with the FPGA. + * @details Inputs: fpgaState + * @details Outputs: fpgaState + * @return none + *************************************************************************/ +void execFPGAOut( void ) +{ + + // FPGA outgoing state machine + switch ( fpgaState ) + { + case FPGA_STATE_READ_HEADER: + fpgaState = handleFPGAReadHeaderState(); + break; + + case FPGA_STATE_WRITE_ALL_ACTUATORS: + fpgaState = handleFPGAWriteAllActuatorsState(); + break; + + case FPGA_STATE_FAILED: + // Do nothing - we will be stuck here + break; + + default: + if ( fpgaState >= NUM_OF_FPGA_STATES ) + { +// SET_ALARM_WITH_2_U32_DATA( ALARM_ID_TD_SOFTWARE_FAULT, SW_FAULT_ID_FPGA_INVALID_OUT_STATE, fpgaState ) + } + else + { + // Ok, some states handled in the incoming state machine + } + break; + } +} + +/*********************************************************************//** + * @brief + * The handleFPGAReadHeaderState function handles the FPGA state where + * the read header registers command is sent to the FPGA. + * @details Inputs: none + * @details Outputs: read command sent to FPGA + * @return next FPGA state + *************************************************************************/ +static FPGA_STATE_T handleFPGAReadHeaderState( void ) +{ + FPGA_STATE_T result = FPGA_STATE_RCV_HEADER; + U16 crc; + + // Construct read command to read 3 registers starting at address 0 + fpgaReadCmdBuffer[ 0 ] = FPGA_READ_CMD_CODE; + fpgaReadCmdBuffer[ 1 ] = GET_LSB_OF_WORD( FPGA_HEADER_START_ADDR ); + fpgaReadCmdBuffer[ 2 ] = GET_MSB_OF_WORD( FPGA_HEADER_START_ADDR ); + fpgaReadCmdBuffer[ 3 ] = fpgaHeaderSize; + crc = crc16( fpgaReadCmdBuffer, FPGA_READ_CMD_HDR_LEN ); + fpgaReadCmdBuffer[ 4 ] = GET_MSB_OF_WORD( crc ); + fpgaReadCmdBuffer[ 5 ] = GET_LSB_OF_WORD( crc ); + // Prep DMA for sending the read cmd and receiving the response + fpgaReadCommandInProgress = TRUE; + setupDMAForReadResp( FPGA_READ_RSP_HDR_LEN + fpgaHeaderSize + FPGA_CRC_LEN ); + setupDMAForReadCmd( FPGA_READ_CMD_HDR_LEN + FPGA_CRC_LEN ); + startDMAReceiptOfReadResp(); + startDMAReadCmd(); + + return result; +} + +/*********************************************************************//** + * @brief + * The handleFPGAReceiveHeaderState function handles the FPGA state + * where the header registers read response should be ready to take in. + * @details Inputs: none + * @details Outputs: header register values updated + * @return next FPGA state + *************************************************************************/ +static FPGA_STATE_T handleFPGAReceiveHeaderState( void ) +{ + FPGA_STATE_T result = FPGA_STATE_READ_HEADER; + + // Did we get an FPGA response? + if ( TRUE == fpgaReadCommandResponseReceived ) + { + // Did FPGA Ack the read command? + if ( fpgaReadResponseBuffer[ 0 ] == FPGA_READ_CMD_ACK ) + { + U32 rspSize = FPGA_READ_RSP_HDR_LEN + fpgaHeaderSize; + 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( fpgaHeaderPtr, &fpgaReadResponseBuffer[ FPGA_READ_RSP_HDR_LEN ], fpgaHeaderSize ); + result = FPGA_STATE_WRITE_ALL_ACTUATORS; + } + else + { + checkFPGACommFailure(); + } + } + else // Header read was NAK'd + { + checkFPGACommFailure(); + } + } + else // No response to read command + { + checkFPGACommFailure(); + } + + // Should not be any data received at this time + consumeUnexpectedData(); + + return result; +} + +/*********************************************************************//** + * @brief + * The handleFPGAWriteAllActuatorsState function handles the FPGA state + * where the bulk write command is sent to the FPGA. + * @details Inputs: actuator set points + * @details Outputs: actuator set points sent to FPGA + * @return next FPGA state + *************************************************************************/ +static FPGA_STATE_T handleFPGAWriteAllActuatorsState( void ) +{ + FPGA_STATE_T result = FPGA_STATE_RCV_ALL_SENSORS; + U16 crc; + + // Construct bulk write command to write actuator data registers starting at address 3 (TODO - change address later) + fpgaWriteCmdBuffer[ 0 ] = FPGA_WRITE_CMD_CODE; + fpgaWriteCmdBuffer[ 1 ] = GET_LSB_OF_WORD( FPGA_BULK_WRITE_START_ADDR ); + fpgaWriteCmdBuffer[ 2 ] = GET_MSB_OF_WORD( FPGA_BULK_WRITE_START_ADDR ); + fpgaWriteCmdBuffer[ 3 ] = fpgaActuatorSetPointsSize; + memcpy( &( fpgaWriteCmdBuffer[ FPGA_WRITE_CMD_HDR_LEN ] ), fpgaActuatorSetPointsPtr, fpgaActuatorSetPointsSize ); + crc = crc16( fpgaWriteCmdBuffer, FPGA_WRITE_CMD_HDR_LEN + fpgaActuatorSetPointsSize ); + fpgaWriteCmdBuffer[ FPGA_WRITE_CMD_HDR_LEN + fpgaActuatorSetPointsSize ] = GET_MSB_OF_WORD( crc ); + fpgaWriteCmdBuffer[ FPGA_WRITE_CMD_HDR_LEN + fpgaActuatorSetPointsSize + 1 ] = GET_LSB_OF_WORD( crc ); + + // 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 ] = fpgaSensorReadingsSize; + crc = crc16( fpgaReadCmdBuffer, FPGA_READ_CMD_HDR_LEN ); + fpgaReadCmdBuffer[ 4 ] = GET_MSB_OF_WORD( crc ); + fpgaReadCmdBuffer[ 5 ] = GET_LSB_OF_WORD( crc ); + + // Prep DMA for sending the bulk write cmd and receiving its response + setupDMAForWriteCmd( FPGA_WRITE_CMD_HDR_LEN + fpgaActuatorSetPointsSize + 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 + fpgaSensorReadingsSize + FPGA_CRC_LEN ); + + // Set fpga comm flags for bulk write cmd and follow-up bulk read command + fpgaWriteCommandInProgress = TRUE; + fpgaBulkWriteAndReadInProgress = TRUE; + // Initiate bulk write command and its receipt - read will follow + startDMAReceiptOfWriteResp(); + startDMAWriteCmd(); + + return result; +} + +/*********************************************************************//** + * @brief + * The handleFPGAReceiveAllSensorsState function handles the FPGA state + * where the bulk read response should be ready to parse. + * @details Inputs: none + * @details Outputs: sensor values updated + * @return next FPGA state + *************************************************************************/ +static FPGA_STATE_T handleFPGAReceiveAllSensorsState( void ) +{ + FPGA_STATE_T result = FPGA_STATE_WRITE_ALL_ACTUATORS; + + // check bulk write command success + if ( TRUE == fpgaWriteCommandResponseReceived ) + { + // 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 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 ) + { + // if bulk read command is ACK'd, collect the readings + if ( TRUE == fpgaReadCommandResponseReceived ) + { + // did FPGA ACK the read command? + if ( fpgaReadResponseBuffer[ 0 ] == FPGA_READ_CMD_ACK ) + { + U32 rspSize = FPGA_READ_RSP_HDR_LEN + fpgaSensorReadingsSize; + 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( fpgaSensorReadingsPtr, &fpgaReadResponseBuffer[ FPGA_READ_RSP_HDR_LEN ], fpgaSensorReadingsSize ); + result = FPGA_STATE_WRITE_ALL_ACTUATORS; + } + else // bad CRC + { + checkFPGACommFailure(); + } + } + else // read command was NAK'd + { + checkFPGACommFailure(); + } + } + else // no response to read command + { + checkFPGACommFailure(); + } + } + + // There should not be any data received at this time + consumeUnexpectedData(); + + return result; +} + +/*********************************************************************//** + * @brief + * The consumeUnexpectedData function checks to see if a byte is sitting in + * the SCI2 received data register. + * @details Inputs: fpgaHeader + * @details Outputs: none + * @return fpgaDiag + *************************************************************************/ +static void consumeUnexpectedData( void ) +{ + // Clear any errors + sciRxError( scilinREG ); + + // If a byte is pending read, read it + if ( sciIsRxReady( scilinREG ) != 0 ) + { + sciReceiveByte( scilinREG ); + } +} + +/*********************************************************************//** + * @brief + * The monitorFPGAPowerStatus function monitors the status of the FPGA power source. + * @details Inputs: none + * @details Outputs: none + * @return none + *************************************************************************/ +static void monitorFPGAPowerStatus( void ) +{ + // TODO Figure out the status of the power source from FPGA from NOE and Kai. +} + +/*********************************************************************//** + * @brief + * The setupDMAForWriteCmd function sets the byte count for the next DMA + * write command to the FPGA. + * @details Inputs: none + * @details Outputs: number of bytes for next FPGA write command is set + * @param bytes2Transmit number of bytes to be transmitted via DMA to the FPGA + * @return none + *************************************************************************/ +static void setupDMAForWriteCmd( U32 bytes2Transmit ) +{ + // Verify # of bytes does not exceed buffer length + if ( bytes2Transmit <= FPGA_WRITE_CMD_BUFFER_LEN ) + { + fpgaDMAWriteControlRecord.FRCNT = bytes2Transmit; + } + else + { +// SET_ALARM_WITH_2_U32_DATA( ALARM_ID_TD_SOFTWARE_FAULT, SW_FAULT_ID_FPGA_WRITE_CMD_TOO_MUCH_DATA, bytes2Transmit ) + } +} + +/*********************************************************************//** + * @brief + * The startDMAWriteCmd function initiates the DMA transmit for the next + * DMA write command to the FPGA. + * @details Inputs: none + * @details Outputs: DMA write command to FPGA is initiated + * @return none + *************************************************************************/ +static void startDMAWriteCmd( void ) +{ + dmaSetCtrlPacket( DMA_CH2, fpgaDMAWriteControlRecord ); + dmaSetChEnable( DMA_CH2, DMA_HW ); + setSCI2DMATransmitInterrupt(); +} + +/*********************************************************************//** + * @brief + * The setupDMAForWriteResp function sets the expected byte count for the + * next DMA write command response from the FPGA. + * @details Inputs: none + * @details Outputs: number of expected bytes for next FPGA write command response is set + * @param bytes2Receive number of bytes expected to be transmitted via DMA from the FPGA + * @return none + *************************************************************************/ +static void setupDMAForWriteResp( U32 bytes2Receive ) +{ + // Verify # of bytes does not exceed buffer length + if ( bytes2Receive <= FPGA_WRITE_RSP_BUFFER_LEN ) + { + fpgaDMAWriteRespControlRecord.FRCNT = bytes2Receive; + } + else + { +// SET_ALARM_WITH_2_U32_DATA( ALARM_ID_TD_SOFTWARE_FAULT, SW_FAULT_ID_FPGA_WRITE_RSP_TOO_MUCH_DATA, bytes2Receive ) + } +} + +/*********************************************************************//** + * @brief + * The startDMAReceiptOfWriteResp function initiates readiness of the DMA + * receiver for the next DMA write command response from the FPGA. + * @details Inputs: none + * @details Outputs: DMA write command response is ready to be received from the FPGA + * @return none + *************************************************************************/ +static void startDMAReceiptOfWriteResp( void ) +{ + dmaSetCtrlPacket( DMA_CH0, fpgaDMAWriteRespControlRecord ); + dmaSetChEnable( DMA_CH0, DMA_HW ); + setSCI2DMAReceiveInterrupt(); +} + +/*********************************************************************//** + * @brief + * The setupDMAForReadCmd function sets the byte count for the next DMA + * read command to the FPGA. + * @details Inputs: none + * @details Outputs: number of bytes for next FPGA read command is set + * @param bytes2Transmit number of bytes to be transmitted via DMA to the FPGA + * @return none + *************************************************************************/ +static void setupDMAForReadCmd( U32 bytes2Transmit ) +{ + // Verify # of bytes does not exceed buffer length + if ( bytes2Transmit <= FPGA_READ_CMD_BUFFER_LEN ) + { + fpgaDMAReadControlRecord.FRCNT = bytes2Transmit; + } + else + { +// SET_ALARM_WITH_2_U32_DATA( ALARM_ID_TD_SOFTWARE_FAULT, SW_FAULT_ID_FPGA_READ_CMD_TOO_MUCH_DATA, bytes2Transmit ) + } +} + +/*********************************************************************//** + * @brief + * The startDMAReadCmd function initiates the DMA transmit for the next + * DMA read command to the FPGA. + * @details Inputs: none + * @details Outputs: DMA read command to FPGA is initiated + * @return none + *************************************************************************/ +static void startDMAReadCmd( void ) +{ + dmaSetCtrlPacket( DMA_CH2, fpgaDMAReadControlRecord ); + dmaSetChEnable( DMA_CH2, DMA_HW ); + setSCI2DMATransmitInterrupt(); +} + +/*********************************************************************//** + * @brief + * The setupDMAForReadResp function sets the expected byte count for the + * next DMA read command response from the FPGA. + * @details Inputs: none + * @details Outputs: number of expected bytes for next FPGA read command response is set + * @param bytes2Receive number of expected bytes to be transmitted via DMA from the FPGA + * @return none + *************************************************************************/ +static void setupDMAForReadResp( U32 bytes2Receive ) +{ + // Verify # of bytes does not exceed buffer length + if ( bytes2Receive <= FPGA_READ_RSP_BUFFER_LEN ) + { + fpgaDMAReadRespControlRecord.FRCNT = bytes2Receive; + } + else + { +// SET_ALARM_WITH_2_U32_DATA( ALARM_ID_TD_SOFTWARE_FAULT, SW_FAULT_ID_FPGA_READ_RSP_TOO_MUCH_DATA, bytes2Receive ) + } +} + +/*********************************************************************//** + * @brief + * The startDMAReceiptOfReadResp function initiates readiness of the DMA + * receiver for the next DMA read command response from the FPGA. + * @details Inputs: none + * @details Outputs: DMA read command response is ready to be received from the FPGA + * @return none + *************************************************************************/ +static void startDMAReceiptOfReadResp( void ) +{ + dmaSetCtrlPacket( DMA_CH0, fpgaDMAReadRespControlRecord ); + dmaSetChEnable( DMA_CH0, DMA_HW ); + setSCI2DMAReceiveInterrupt(); +} + +/**@}*/ Index: FPGA.h =================================================================== diff -u --- FPGA.h (revision 0) +++ FPGA.h (revision 6d80d69a210f45c733e5307859351f2cd820a8e7) @@ -0,0 +1,54 @@ +/************************************************************************** +* +* 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.h +* +* @author (last) Sean Nash +* @date (last) 05-Sep-2023 +* +* @author (original) Dara Navaei +* @date (original) 05-Nov-2019 +* +***************************************************************************/ + +#ifndef __FPGA_H__ +#define __FPGA_H__ + +#include "TDCommon.h" +#include "Interrupts.h" + + +/** + * @defgroup FPGA FPGA + * @brief FPGA service module. + * The FPGA module manages communication between the HD and the FPGA via UART. + * This module is driven by the Priority Task via calls to two FPGA executive functions: + * 1) an incoming executive manages the states of the state machine that deal with responses and data received from the FPGA + * 2) an outgoing executive manages transmission of write and read commands to the FPGA. + * This module first reads the header record that includes the FPGA ID and revision and + * verifies the FPGA ID to check FPGA communication. It then initializes and configures the ADCs and + * various other sensors that are interfaced via the FPGA. Then, it essentially enters an infinite loop + * where a bulk write command updates actuator set points and a bulk read command retrieves the latest sensor readings. + * + * @addtogroup FPGA + * @{ + */ + +// ********** public definitions ********** + +// ********** public function prototypes ********** + +void initFPGA( U08* hdr, U08* sen, U08* act, U32 hdrSize, U32 senSize, U32 actSize ); +void execFPGAIn( void ); +void execFPGAOut( void ); + +void signalFPGAReceiptCompleted( void ); +void signalFPGATransmitCompleted( void ); + +/**@}*/ + +#endif Index: FlashDrvr/CGT.CCS.h =================================================================== diff -u --- FlashDrvr/CGT.CCS.h (revision 0) +++ FlashDrvr/CGT.CCS.h (revision 6d80d69a210f45c733e5307859351f2cd820a8e7) @@ -0,0 +1,54 @@ +/********************************************************************************************************************** + * COPYRIGHT + * ------------------------------------------------------------------------------------------------------------------- + * \verbatim + * + * � Copyright 2009-2012 Texas Instruments Incorporated. All rights reserved. + * + * \endverbatim + * ------------------------------------------------------------------------------------------------------------------- + * FILE DESCRIPTION + * ------------------------------------------------------------------------------------------------------------------- + * + * Project: Hercules� ARM� Safety MCUs - F021 Flash API + * Version: v2.01.01 Build(000830) + * Build Date: 2014-10-21 + * + * File: CGT.CCS.h + * + * Description: TI CCS compiler specific info used by the F021 API. + *--------------------------------------------------------------------------------------------------------------------- + * Author: John R Hall + *--------------------------------------------------------------------------------------------------------------------- + * + *********************************************************************************************************************/ + + +#ifndef CGT_CCS_H_ +#define CGT_CCS_H_ + +#if defined(__big_endian__) /* is big endian compile */ +#if !defined(_BIG_ENDIAN) + #define _BIG_ENDIAN /* FAPI generic define for big endian */ +#endif +#elif defined(__little_endian__) /* is little endian compile */ +#if !defined(_LITTLE_ENDIAN) + #define _LITTLE_ENDIAN /* FAPI generic define for little endian */ +#endif +#endif + +/* Defines the method to indicate packed enums */ +#if defined(__TI_GNU_ATTRIBUTE_SUPPORT__) && (__TI_GNU_ATTRIBUTE_SUPPORT__==1) +/* --gcc option enabled so we can specify this */ +#define ATTRIBUTE_PACKED __attribute__((packed)) +#else +/* --gcc option not enabled so we cannot specify this */ +#define ATTRIBUTE_PACKED +#endif + + +#endif /* CGT_CCS_H_ */ + +/********************************************************************************************************************** + * END OF FILE: CGT.CCS.h + *********************************************************************************************************************/ Index: FlashDrvr/CGT.gcc.h =================================================================== diff -u --- FlashDrvr/CGT.gcc.h (revision 0) +++ FlashDrvr/CGT.gcc.h (revision 6d80d69a210f45c733e5307859351f2cd820a8e7) @@ -0,0 +1,48 @@ +/********************************************************************************************************************** + * COPYRIGHT + * ------------------------------------------------------------------------------------------------------------------- + * \verbatim + * + * � Copyright 2009-2012 Texas Instruments Incorporated. All rights reserved. + * + * \endverbatim + * ------------------------------------------------------------------------------------------------------------------- + * FILE DESCRIPTION + * ------------------------------------------------------------------------------------------------------------------- + * + * Project: Hercules� ARM� Safety MCUs - F021 Flash API + * Version: v2.01.01 Build(000830) + * Build Date: 2014-10-21 + * + * File: CGT.gcc.h + * + * Description: gcc compiler specific info used by the F021 API. + *--------------------------------------------------------------------------------------------------------------------- + * Author: John R Hall + *--------------------------------------------------------------------------------------------------------------------- + * + *********************************************************************************************************************/ + + +#ifndef CGT_GCC_H_ +#define CGT_GCC_H_ + +#if (__BYTE_ORDER__ == __ORDER_BIG_ENDIAN__) /* is big endian compile */ +#if !defined(_BIG_ENDIAN) + #define _BIG_ENDIAN /* FAPI generic define for big endian */ +#endif +#endif +#if (__BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__) /* is little endian compile */ +#if !defined(_LITTLE_ENDIAN) + #define _LITTLE_ENDIAN /* FAPI generic define for little endian */ +#endif +#endif + +/* Defines the method to indicate packed enums */ +#define ATTRIBUTE_PACKED __attribute__((packed)) + +#endif /* CGT_GCC_H_ */ + +/********************************************************************************************************************** + * END OF FILE: CGT.GCC.h + *********************************************************************************************************************/ Index: FlashDrvr/Compatibility.h =================================================================== diff -u --- FlashDrvr/Compatibility.h (revision 0) +++ FlashDrvr/Compatibility.h (revision 6d80d69a210f45c733e5307859351f2cd820a8e7) @@ -0,0 +1,54 @@ +/********************************************************************************************************************** + * COPYRIGHT + * ------------------------------------------------------------------------------------------------------------------- + * \verbatim + * + * � Copyright 2009-2012 Texas Instruments Incorporated. All rights reserved. + * + * \endverbatim + * ------------------------------------------------------------------------------------------------------------------- + * FILE DESCRIPTION + * ------------------------------------------------------------------------------------------------------------------- + * + * Project: Hercules� ARM� Safety MCUs - F021 Flash API + * Version: v2.01.01 Build(000830) + * Build Date: 2014-10-21 + * + * File: Compatibility.h + * + * Description: A set of macro defines to provide backwards compatibility to v1.x API. + *--------------------------------------------------------------------------------------------------------------------- + * Author: John R Hall + *--------------------------------------------------------------------------------------------------------------------- + * + *********************************************************************************************************************/ + + +#ifndef COMPATIBILITY_H_ +#define COMPATIBILITY_H_ + +/*LDRA_NOANALYSIS*/ +/* This header file is intended for backwards compatibility only and is not meant to be MISRA-C compliant */ + +/* Define to provide backwards compatibility with Fapi_initializeFlashApi() */ +#define Fapi_initializeAPI(mControlRegister,mFrequency) (Fapi_initializeFlashBanks((mFrequency))) + +/* Define to provide backwards compatibility with Fapi_getFsmStatus() */ +#define Fapi_getFsmStatus() (FAPI_GET_FSM_STATUS) + +/* Define to provide backwards compatibility with Fapi_issueFsmSuspendCommand() */ +#define Fapi_issueFsmSuspendCommand() (FAPI_SUSPEND_FSM) + +/* Define to provide backwards compatibility with Fapi_writeEwaitValue() */ +#define Fapi_writeEwaitValue(mEwait) (FAPI_WRITE_EWAIT((mEwait))) + +/* Define to provide backwards compatibility with Fapi_checkFsmForReady() */ +#define Fapi_checkFsmForReady() (FAPI_CHECK_FSM_READY_BUSY) + + +#endif +/*LDRA_ANALYSIS*/ + +/********************************************************************************************************************** + * END OF FILE: Compatibility.h + *********************************************************************************************************************/ Index: FlashDrvr/Constants.h =================================================================== diff -u --- FlashDrvr/Constants.h (revision 0) +++ FlashDrvr/Constants.h (revision 6d80d69a210f45c733e5307859351f2cd820a8e7) @@ -0,0 +1,67 @@ +/********************************************************************************************************************** + * COPYRIGHT + * ------------------------------------------------------------------------------------------------------------------- + * \verbatim + * + * � Copyright 2009-2012 Texas Instruments Incorporated. All rights reserved. + * + * \endverbatim + * ------------------------------------------------------------------------------------------------------------------- + * FILE DESCRIPTION + * ------------------------------------------------------------------------------------------------------------------- + * + * Project: Hercules� ARM� Safety MCUs - F021 Flash API + * Version: v2.01.01 Build(000830) + * Build Date: 2014-10-21 + * + * File: Constants.h + * + * Description: A set of Constant Values used by the Flash Memory Controller. + *--------------------------------------------------------------------------------------------------------------------- + * Author: John R Hall + *--------------------------------------------------------------------------------------------------------------------- + * + *********************************************************************************************************************/ + + +#ifndef CONSTANTS_H_ +#define CONSTANTS_H_ + +/* Specifies the bit mask for determining all address bits exclusive of the offest + imposed by the memory map register */ +#define F021_PROGRAM_ADDRESS_MASK 0x07FFFFFFU + +/* Specifies the Offset to the TI OTP */ +#define F021_PROGRAM_TIOTP_OFFSET 0xF0080000U + +/* FMC memory map defines */ +#define F021_FLASH_MAP_BEGIN 0x00000000U +#define F021_FLASH_MAP_END 0x00FFFFFFU +#define F021_OTP_MAP_BEGIN 0xF0000000U +#define F021_OTP_MAP_END 0xF000FFFFU +#define F021_OTPECC_MAP_BEGIN 0xF0040000U +#define F021_OTPECC_MAP_END 0xF0041FFFU +#define F021_EEPROMECC_MAP_BEGIN 0xF0100000U +#define F021_EEPROMECC_MAP_END 0xF01FFFFFU +#define F021_EEPROM_MAP_BEGIN 0xF0200000U +#define F021_EEPROM_MAP_END 0xF03FFFFFU +#define F021_FLASHECC_MAP_BEGIN 0xF0400000U +#define F021_FLASHECC_MAP_END 0xF04FFFFFU + +#define F021_CPU0_REGISTER_ADDRESS 0xFFF87000U + +/* Specific TI OTP Offsets */ +#define F021_TIOTP_PER_BANK_SIZE 0x2000U +#define F021_TIOTP_SETTINGS_BASE 0x150U +#define F021_TIOTP_BANK_SECTOR_OFFSET 0x158U + +/* Define to map the direct access to the TI OTP memory */ +#define F021_TIOTP_BASE_ADDRESS ((Fapi_TiOtpBytesType *)(F021_PROGRAM_TIOTP_OFFSET + F021_TIOTP_SETTINGS_BASE)) + +#define F021_MINIMUM_HCLK_FREQUENCY 10U + +#endif /* CONSTANTS_H_ */ + +/********************************************************************************************************************** + * END OF FILE: Constants.h + *********************************************************************************************************************/ Index: FlashDrvr/F021.h =================================================================== diff -u --- FlashDrvr/F021.h (revision 0) +++ FlashDrvr/F021.h (revision 6d80d69a210f45c733e5307859351f2cd820a8e7) @@ -0,0 +1,52 @@ +/********************************************************************************************************************** + * COPYRIGHT + * ------------------------------------------------------------------------------------------------------------------- + * \verbatim + * + * � Copyright 2009-2012 Texas Instruments Incorporated. All rights reserved. + * + * \endverbatim + * ------------------------------------------------------------------------------------------------------------------- + * FILE DESCRIPTION + * ------------------------------------------------------------------------------------------------------------------- + * + * Project: Hercules� ARM� Safety MCUs - F021 Flash API + * Version: v2.01.01 Build(000830) + * Build Date: 2014-10-21 + * + * File: F021.h + * + * Description: Main include file for F021 devices. + *--------------------------------------------------------------------------------------------------------------------- + * Author: John R Hall + *--------------------------------------------------------------------------------------------------------------------- + * + *********************************************************************************************************************/ + + +#ifndef F021_H_ +#define F021_H_ + +#if !defined(F021) + #define F021 +#endif + +#if !defined(_FMC) + #define _FMC +#endif + +/********************************************************************************************************************** + * INCLUDES + *********************************************************************************************************************/ +#include "Types.h" +#include "Helpers.h" +#include "Constants.h" +#include "Registers.h" +#include "FapiFunctions.h" +#include "Compatibility.h" + +#endif /*F021_H_*/ + +/********************************************************************************************************************** + * END OF FILE: F021.h + *********************************************************************************************************************/ Index: FlashDrvr/F021_API_CortexR4_LE_L2FMC_V3D16_NDS.lib =================================================================== diff -u Binary files differ Index: FlashDrvr/FapiFunctions.h =================================================================== diff -u --- FlashDrvr/FapiFunctions.h (revision 0) +++ FlashDrvr/FapiFunctions.h (revision 6d80d69a210f45c733e5307859351f2cd820a8e7) @@ -0,0 +1,185 @@ +/********************************************************************************************************************** + * COPYRIGHT + * ------------------------------------------------------------------------------------------------------------------- + * \verbatim + * + * � Copyright 2009-2012 Texas Instruments Incorporated. All rights reserved. + * + * \endverbatim + * ------------------------------------------------------------------------------------------------------------------- + * FILE DESCRIPTION + * ------------------------------------------------------------------------------------------------------------------- + * + * Project: Hercules� ARM� Safety MCUs - F021 Flash API + * Version: v2.01.01 Build(000830) + * Build Date: 2014-10-21 + * + * File: FapiFunctions.h + * + * Description: All the FAPI function extern definitions. + *--------------------------------------------------------------------------------------------------------------------- + * Author: John R Hall + *--------------------------------------------------------------------------------------------------------------------- + * + *********************************************************************************************************************/ + + +#ifndef FAPI_FUNCTIONS_H_ +#define FAPI_FUNCTIONS_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +/* Flash C API functions*/ + +/* Flash State Machine commands */ +extern Fapi_StatusType Fapi_enableMainBankSectors(uint16_t u16SectorsEnables); + +extern Fapi_StatusType Fapi_enableEepromBankSectors( + uint32_t u32SectorsEnables_31_0, + uint32_t u32SectorsEnables_63_32 + ); + +extern Fapi_StatusType Fapi_enableFsmDoneEvent(void); + +extern Fapi_StatusType Fapi_disableFsmDoneEvent(void); + +extern Fapi_StatusType Fapi_initializeFlashBanks(uint32_t u32HclkFrequency); + +extern Fapi_StatusType Fapi_setActiveFlashBank(Fapi_FlashBankType oNewFlashBank); + +extern Fapi_StatusType Fapi_enableBanksForOtpWrite(uint8_t u8Banks); + +extern Fapi_StatusType Fapi_disableBanksForOtpWrite(void); + +/* Functions only available on devices with L2FMC Flash controllers */ +#if defined(_L2FMC) + +extern Fapi_StatusType Fapi_enableAutoEccCalculation(void); +extern Fapi_StatusType Fapi_disableAutoEccCalculation(void); + +#endif /* defined(_L2FMC) */ + +extern void Fapi_flushPipeline(void); + +extern uint32_t* Fapi_remapEccAddress(uint32_t u32EccAddress); + +extern uint32_t Fapi_remapMainAddress(uint32_t u32MainAddress); + +extern boolean_t Fapi_isAddressEcc(uint32_t u32Address); + +extern boolean_t Fapi_isAddressEEPROM(uint32_t u32Address); + +/* Async Commands */ +extern Fapi_StatusType Fapi_issueAsyncCommandWithAddress( + Fapi_FlashStateCommandsType oCommand, + uint32_t* pu32StartAddress + ); + +extern Fapi_StatusType Fapi_issueAsyncCommand(Fapi_FlashStateCommandsType oCommand); + +/* Info Commands */ +extern Fapi_LibraryInfoType Fapi_getLibraryInfo(void); +extern Fapi_DeviceInfoType Fapi_getDeviceInfo(void); +extern Fapi_StatusType Fapi_getBankSectors( + Fapi_FlashBankType oBank, + Fapi_FlashBankSectorsType* poFlashBankSectors + ); +extern uint32_t Fapi_getNumberOfBankSectors( uint32_t u32Bank); +/* Read commands */ +extern Fapi_StatusType Fapi_doBlankCheck( + uint32_t* pu32StartAddress, + uint32_t u32Length, + Fapi_FlashStatusWordType* poFlashStatusWord + ); + +extern Fapi_StatusType Fapi_doMarginRead( + uint32_t* pu32StartAddress, + uint32_t* pu32ReadBuffer, + uint32_t u32Length, + Fapi_FlashReadMarginModeType oReadMode + ); + +extern Fapi_StatusType Fapi_doVerify( + uint32_t* pu32StartAddress, + uint32_t u32Length, + uint32_t* pu32CheckValueBuffer, + Fapi_FlashStatusWordType* poFlashStatusWord + ); + +extern uint32_t Fapi_calculatePsa( + uint32_t* pu32StartAddress, + uint32_t u32Length, + uint32_t u32PsaSeed, + Fapi_FlashReadMarginModeType oReadMode + ); + +extern Fapi_StatusType Fapi_doPsaVerify( + uint32_t* pu32StartAddress, + uint32_t u32Length, + uint32_t u32PsaValue, + Fapi_FlashStatusWordType* poFlashStatusWord + ); + +extern Fapi_StatusType Fapi_doBlankCheckByByte( + uint8_t* pu8StartAddress, + uint32_t u32Length, + Fapi_FlashStatusWordType* poFlashStatusWord + ); + +extern Fapi_StatusType Fapi_doMarginReadByByte( + uint8_t* pu8StartAddress, + uint8_t* pu8ReadBuffer, + uint32_t u32Length, + Fapi_FlashReadMarginModeType oReadMode + ); + +extern Fapi_StatusType Fapi_doVerifyByByte( + uint8_t* pu8StartAddress, + uint32_t u32Length, + uint8_t* pu8CheckValueBuffer, + Fapi_FlashStatusWordType* poFlashStatusWord + ); + +/* Programming Commands */ +extern Fapi_StatusType Fapi_issueProgrammingCommand( + uint32_t* pu32StartAddress, + uint8_t* pu8DataBuffer, + uint8_t u8DataBufferSizeInBytes, + uint8_t* pu8EccBuffer, + uint8_t u8EccBufferSizeInBytes, + Fapi_FlashProgrammingCommandsType oMode + ); + +extern Fapi_StatusType Fapi_issueProgrammingCommandForEccAddresses( + uint32_t* pu32StartAddress, + uint8_t* pu8EccBuffer, + uint8_t u8EccBufferSizeInBytes + ); + +/* Utility Commands */ +extern Fapi_StatusType Fapi_waitDelay(volatile uint32_t u32WaitDelay); + +extern uint32_t Fapi_calculateFletcherChecksum( + uint32_t u32Address, + uint32_t u32Length + ); + +extern uint8_t Fapi_calculateEcc( + uint32_t u32Address, + uint64_t u64Data + ); + +/* User Defined Functions */ +extern Fapi_StatusType Fapi_serviceWatchdogTimer(void); + +#ifdef __cplusplus +} +#endif + +#endif /*FAPI_FUNCTIONS_H_*/ + +/********************************************************************************************************************** + * END OF FILE: FapiFunctions.h + *********************************************************************************************************************/ Index: FlashDrvr/Fapi_UserDefinedFunctions.c =================================================================== diff -u --- FlashDrvr/Fapi_UserDefinedFunctions.c (revision 0) +++ FlashDrvr/Fapi_UserDefinedFunctions.c (revision 6d80d69a210f45c733e5307859351f2cd820a8e7) @@ -0,0 +1,78 @@ +/********************************************************************************************************************** + * FILE DESCRIPTION + * ------------------------------------------------------------------------------------------------------------------- + * + * Project: Hercules� ARM� Safety MCUs - F021 Flash API + * Version: v2.00.00 Build(000776) - Alpha + * Build Date: 2012-12-25 + * + * + * Description: Contains all user defined callback functions used by the F021 Flash API. + *--------------------------------------------------------------------------------------------------------------------- + * Author: John R Hall + *--------------------------------------------------------------------------------------------------------------------- + * + *********************************************************************************************************************/ + +/* +* Copyright (C) 2009-2018 Texas Instruments Incorporated - www.ti.com +* +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions +* are met: +* +* Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* +* Redistributions in binary form must reproduce the above copyright +* notice, this list of conditions and the following disclaimer in the +* documentation and/or other materials provided with the +* distribution. +* +* Neither the name of Texas Instruments Incorporated nor the names of +* its contributors may be used to endorse or promote products derived +* from this software without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +* +*/ + + +/********************************************************************************************************************** + * INCLUDES + *********************************************************************************************************************/ +#include "F021.h" + +/********************************************************************************************************************** + * Fapi_serviceWatchdogTimer + *********************************************************************************************************************/ +/*! Callback function to service watchdog timer. Used by the Blank, Read, and Verify fuctions. + * + * \param [in] none + * \param [out] none + * \return Fapi_StatusType + * \retval Fapi_Status_Success + * \note TI FEE API. + *********************************************************************************************************************/ +Fapi_StatusType Fapi_serviceWatchdogTimer(void) +{ + /* User to add their own watchdog servicing code here */ + + return(Fapi_Status_Success); +} + +/********************************************************************************************************************** + * END OF FILE: Fapi_UserDefinedFunctions.c + *********************************************************************************************************************/ + Index: FlashDrvr/Helpers.h =================================================================== diff -u --- FlashDrvr/Helpers.h (revision 0) +++ FlashDrvr/Helpers.h (revision 6d80d69a210f45c733e5307859351f2cd820a8e7) @@ -0,0 +1,83 @@ +/********************************************************************************************************************** + * COPYRIGHT + * ------------------------------------------------------------------------------------------------------------------- + * \verbatim + * + * � Copyright 2009-2012 Texas Instruments Incorporated. All rights reserved. + * + * \endverbatim + * ------------------------------------------------------------------------------------------------------------------- + * FILE DESCRIPTION + * ------------------------------------------------------------------------------------------------------------------- + * + * Project: Hercules� ARM� Safety MCUs - F021 Flash API + * Version: v2.01.01 Build(000830) + * Build Date: 2014-10-21 + * + * File: Helpers.h + * + * Description: These helper Macros are to facilitate common operations. + *--------------------------------------------------------------------------------------------------------------------- + * Author: John R Hall + *--------------------------------------------------------------------------------------------------------------------- + * + *********************************************************************************************************************/ + + +#ifndef HELPERS_H_ +#define HELPERS_H_ + +/* Quick Register referencing macro */ +#define REGISTER(mRegister) (* (volatile uint32_t* )(mRegister)) + +/* Macro allowing a write to a locked FSM register */ +#define FAPI_WRITE_LOCKED_FSM_REGISTER(mRegister,mValue) \ + do { \ + FLASH_CONTROL_REGISTER->FsmWrEna.FSM_WR_ENA_BITS.WR_ENA = 0x5U; \ + (mRegister) = (mValue); \ + FLASH_CONTROL_REGISTER->FsmWrEna.FSM_WR_ENA_BITS.WR_ENA = 0x2U; \ + } while(0) + + + +/* These are helper functions to handle generic Big Endian/Little Endian code bases */ +#if defined(_LITTLE_ENDIAN) + #define EI16(idx) ((idx) ^ 1) + #define EI8(idx) ((idx) ^ 3) +#else + #define EI16(idx) (idx) + #define EI8(idx) (idx) +#endif + +/* These are helper functions to handle generic Big Endian/Little Endian code bases */ +#if defined(_L2FMC) && defined(_BIG_ENDIAN) +#define L2EI16(idx) ((idx) ^ 1) +#define L2EI8(idx) ((idx) ^ 3) +#else +#define L2EI16 EI16 +#define L2EI8 EI8 +#endif + +/* Macro that reads the FMSTAT register and indicates if the FSM is Ready or Busy */ +#define FAPI_CHECK_FSM_READY_BUSY \ + (FLASH_CONTROL_REGISTER->FmStat.FMSTAT_BITS.BUSY ? Fapi_Status_FsmBusy : Fapi_Status_FsmReady) + +/* Macro that clears the FSM_DONE event */ +#define FAPI_CLEAR_FSM_DONE_EVENT (FLASH_CONTROL_REGISTER->FedAcStatus.FEDACSTATUS_BITS.FSM_DONE = 1U) + +/* Macro that returns the value in the FMStat Register */ +#define FAPI_GET_FSM_STATUS (FLASH_CONTROL_REGISTER->FmStat.u32Register) + +/* Macro that issues a Suspend command to the FSM */ +#define FAPI_SUSPEND_FSM \ + FAPI_WRITE_LOCKED_FSM_REGISTER(FLASH_CONTROL_REGISTER->FsmExecute.FSM_EXECUTE_BITS.SUSPEND_NOW, 0x5U) + +/* Macro to set the EWAIT value */ +#define FAPI_WRITE_EWAIT(_mEwait) \ + FAPI_WRITE_LOCKED_FSM_REGISTER(FLASH_CONTROL_REGISTER->EepromConfig.EEPROM_CONFIG_BITS.EWAIT,(_mEwait)) + +#endif /* HELPERS_H_ */ + +/********************************************************************************************************************** + * END OF FILE: Helpers.h + *********************************************************************************************************************/ Index: FlashDrvr/Registers.h =================================================================== diff -u --- FlashDrvr/Registers.h (revision 0) +++ FlashDrvr/Registers.h (revision 6d80d69a210f45c733e5307859351f2cd820a8e7) @@ -0,0 +1,92 @@ +/********************************************************************************************************************** + * COPYRIGHT + * ------------------------------------------------------------------------------------------------------------------- + * \verbatim + * + * � Copyright 2009-2012 Texas Instruments Incorporated. All rights reserved. + * + * \endverbatim + * ------------------------------------------------------------------------------------------------------------------- + * FILE DESCRIPTION + * ------------------------------------------------------------------------------------------------------------------- + * + * Project: Hercules� ARM� Safety MCUs - F021 Flash API + * Version: v2.01.01 Build(000830) + * Build Date: 2014-10-21 + * + * File: Registers.h + * + * Description: A complete mapping of the F021 Flash Registers facilitating named access to the F021 Flash Registers. + * This file will select the appropriate definitions based on selected compile Endianness. + *--------------------------------------------------------------------------------------------------------------------- + * Author: John R Hall + *--------------------------------------------------------------------------------------------------------------------- + * + *********************************************************************************************************************/ + + +#ifndef REGISTERS_H_ +#define REGISTERS_H_ + +/********************************************************************************************************************** + * INCLUDES + *********************************************************************************************************************/ +/*LDRA_NOANALYSIS*/ +/*LDRA_INSPECTED 42 S MR: 3.5 "Necessary for FMC register definitions" */ +/*LDRA_INSPECTED 74 S MR: 18.4 "Necessary for FMC register definitions" */ +#if defined(_LITTLE_ENDIAN) + #include "Registers_FMC_LE.h" +#else + #include "Registers_FMC_BE.h" +#endif +/*LDRA_ANALYSIS*/ + +/* Certain non released devices did not contain this information in the FMC */ +#if defined(_BIG_ENDIAN) && defined(__TI_TMS470_V7M3__) + #define WIDTH_MAIN_BANK 0x10U; + #define WIDTH_MAIN_ECC 0x2U; + #define WIDTH_EEPROM_BANK 0x10U; + #define WIDTH_EEPROM_ECC 0x2U; +#else + /* Macro to get the width of the Data on Main Banks */ + #define WIDTH_MAIN_BANK ((uint8_t)(( (uint32_t)FLASH_CONTROL_REGISTER->FcfgBank.FCFG_BANK_BITS.MAIN_BANK_WIDTH \ + & (uint32_t)0x1C0U) >> 3U)) + /* Macro to get the width of the ECC on Main Banks */ + #define WIDTH_MAIN_ECC ((uint8_t)(( (uint32_t)FLASH_CONTROL_REGISTER->FcfgBank.FCFG_BANK_BITS.MAIN_BANK_WIDTH \ + & (uint32_t)0x038U) >> 3U)) + /* Macro to get the width of the Data on EEPROM Bank */ + #define WIDTH_EEPROM_BANK ((uint8_t)(( (uint32_t)FLASH_CONTROL_REGISTER->FcfgBank.FCFG_BANK_BITS.EE_BANK_WIDTH \ + & (uint32_t)0x0C0U) >> 3U)) + /* Macro to get the width of the ECC on EEPROM Bank */ + #define WIDTH_EEPROM_ECC ((uint8_t)(( (uint32_t)FLASH_CONTROL_REGISTER->FcfgBank.FCFG_BANK_BITS.EE_BANK_WIDTH \ + & (uint32_t)0x018U) >> 3U)) +#endif + +/* Typedef pointer to Fapi_FmcRegistersType */ +typedef Fapi_FmcRegistersType* pFapi_FmcRegistersType; + +/* Typedef byte pointer to FWPWRITEx Registers */ +typedef volatile uint8_t FwpWriteByteAccessorType; +/* Typedef dword pointer to FWPWRITEx Registers */ +typedef volatile uint32_t FwpWriteDWordAccessorType; + +/* Offset from FMC base address to the start of the FWPWRITEx registers */ +#define FWP_WRITE_OFFSET 0x120U +/* Macro that creates a byte accessor pointer to the FWPWRITEx registers */ +#define FWPWRITE_BYTE_ACCESSOR_ADDRESS ((FwpWriteByteAccessorType*)(F021_CPU0_REGISTER_ADDRESS + 0x120U)) +/* Macro that creates a byte accessor pointer to the FWPWRITE_ECC register */ +#define FWPWRITE_ECC_BYTE_ACCESSOR_ADDRESS ((FwpWriteByteAccessorType*)(F021_CPU0_REGISTER_ADDRESS + 0x140U)) +/* Macro that creates a dword accessor pointer to the FWPWRITEx registers */ +#define FWPWRITE_DWORD_ACCESSOR_ADDRESS ((FwpWriteDWordAccessorType*)(F021_CPU0_REGISTER_ADDRESS + 0x120U)) + +/* Macro that creates an object pointer to the start of the FMC registers */ +#define FLASH_CONTROL_REGISTER ((pFapi_FmcRegistersType)(F021_CPU0_REGISTER_ADDRESS)) + +/* Macro that defines the base address for the FMC registers structure */ +#define F021_CPU0_BASE_ADDRESS ((Fapi_FmcRegistersType*)F021_CPU0_REGISTER_ADDRESS) + +#endif /* REGISTERS_H_ */ + +/********************************************************************************************************************** + * END OF FILE: Registers.h + *********************************************************************************************************************/ Index: FlashDrvr/Registers_FMC_LE.h =================================================================== diff -u --- FlashDrvr/Registers_FMC_LE.h (revision 0) +++ FlashDrvr/Registers_FMC_LE.h (revision 6d80d69a210f45c733e5307859351f2cd820a8e7) @@ -0,0 +1,1592 @@ +/********************************************************************************************************************** + * COPYRIGHT + * ------------------------------------------------------------------------------------------------------------------- + * \verbatim + * + * � Copyright 2009-2012 Texas Instruments Incorporated. All rights reserved. + * + * \endverbatim + * ------------------------------------------------------------------------------------------------------------------- + * FILE DESCRIPTION + * ------------------------------------------------------------------------------------------------------------------- + * + * Project: Hercules� ARM� Safety MCUs - F021 Flash API + * Version: v2.01.01 Build(000830) + * Build Date: 2014-10-21 + * + * File: Registers_FMC_LE.h + * + * Description: A complete mapping of the F021 Flash Registers facilitating named access to the F021 Flash Registers. + * This file is for Little Endian devices. + *--------------------------------------------------------------------------------------------------------------------- + * Author: John R Hall + *--------------------------------------------------------------------------------------------------------------------- + * + *********************************************************************************************************************/ + + +#ifndef REGISTERS_LE_H_ +#define REGISTERS_LE_H_ + +/* Flash Configuration Registers */ + +/*! + Structure describing the Flash Wrapper registers allowing register and bit + level accesses. +*/ +#if defined(_L2FMC) +typedef volatile struct FMC_REGISTERS +{ + /*! + Defines whole and bit level accesses to the Read Control Register - 0x00 + */ + + union FRDCNTL + { + uint32_t u32Register; /* Read Control Register, bits 31:0 */ + struct + { + uint32_t PFUENA :1;/*!< Read Mode, bit 0 */ + uint32_t PFUENB :1;/*!< Address Setup Wait State Enable, bit 4 */ + uint32_t _FRDCNTL_Reserved_07_02 :6;/*!< Reserved, bits 7:5 */ + uint32_t RWAIT :4;/*!< Random Read Wait State, bits 11:8 */ + uint32_t _FRDCNTL_Reserved_31_12 :20;/*!< Reserved, bits 31:12 */ + } FRDCNTRL_BITS; + } FrdCntl; + + uint32_t _Reserved_04; /* Reserved Address Locations 0x04 */ + + /*! + Defines whole and bit level accesses to the Error Correction Control Register1 - 0x08 + */ + union FEDACCTRL1 + { + uint32_t u32Register; /* Error Correction Control Register1, bits 31:0 */ + struct + { + uint32_t _FEDACCTRL1_Reserved_03_00 :4;/* !< Reserved bit 03:00 */ + uint32_t EZCV :1;/*!< Zero Condition Valid, bit 4 */ + uint32_t EOCV :1;/*!< One Condition Valid, bit 5 */ + uint32_t _FEDACCTRL1_Reserved_31_06 :26;/*!< Reserved, bits 31:06 */ + + } FEDACCTRL1_BITS; + } FedAcCtrl1; + + + uint32_t _Reserved_0C; /* Reserved Address Locations 0x0C */ + + uint32_t _Reserved_10; /* Reserved Address Locations 0x10 */ + + /*! + Defines whole and bit level accesses to the Port A Error and Status Register - 0x14 + */ + union FEDAC_PASTATUS + { + uint32_t u32Register; /* Port A Error and Status Register, bits 31:0 */ + struct + { + uint32_t _FEDACPASTATUS_Reserved_09_00 :10; /* !< Reserved bits 09:00 */ + uint32_t ADD_PAR_ERR :1;/*!< Address Parity Error , bits 10 */ + uint32_t ADD_TAG_ERR :1;/*!< Address Tag Register Error Status Flag, bit 11 */ + uint32_t _FEDACPASTATUS_Reserved_13_12 :2; /*!< Reserved bits 13:12 */ + uint32_t MCMD_PAR_ERR :1;/*!< Parity error in MCmd while Mcmd=Idle or in MRespAccept, bit 14 */ + uint32_t ACC_TOUT :1;/*!< Crossbar access timeout/ Internal address parity error, bit 15 */ + uint32_t _FEDACPASTATUS_Reserved_31_16 :16 ;/*!< Reserved bits 31:17 */ + } FEDAC_PASTATUS_BITS; + } FedacPAStatus; + + /*! + Defines whole and bit level accesses to the Port B Error and Status Register - 0x18 + */ + union FEDAC_PBSTATUS + { + uint32_t u32Register; /* Port B Error and Status Register, bits 31:0 */ + struct + { + uint32_t _FEDACPBSTATUS_Reserved_09_00 :10; /*!< Reserved bits 09:00 */ + uint32_t ADD_PAR_ERR :1;/*!< Address Parity Error , bits 10 */ + uint32_t ADD_TAG_ERR :1;/*!< Address Tag Register Error Status Flag, bit 11 */ + uint32_t _FEDACPBSTATUS_Reserved_13_12 :2; /*!< Reserved bits 13:12 */ + uint32_t MCMD_PAR_ERR :1;/*!< Parity error in MCmd while Mcmd=Idle or in MRespAccept, bit 14 */ + uint32_t ACC_TOUT :1;/*!< Crossbar access timeout/ Internal address parity error, bit 15 */ + uint32_t _FEDACPBSTATUS_Reserved_31_16 :16 ;/*!< Reserved bits 31:17 */ + } FEDAC_PBSTATUS_BITS; + } FedacPBStatus; + + /*! + Defines whole and bit level accesses to the Global Error and Status Register - 0x1C + */ + union FEDAC_GBLSTATUS + { + uint32_t u32Register; /* Global Error and Status Register ,bits 31:0 */ + struct + { + uint32_t _FEDACGLBSTATUS_Reserved_12_00 :13; /*!< Reserved bits 12:00 */ + uint32_t IMPLICIT_UNC_ERR :1;/*!< UnCorrectable error during implicit two reads from OTP, bit 13 */ + uint32_t IMPLICIT_COR_ERR :1;/*!< Correctable error during implicit two reads from OTP, bit 14 */ + uint32_t RCR_ERR :1;/*!< L2FMC_Config_out port correction, bit 15 */ + uint32_t _FEDACGLBSTATUS_Reserved_23_16 :8; /*!< Reserved bits 23:16 */ + uint32_t FSM_DONE :1;/*!< FSM done event, bit 24 */ + uint32_t RVF_EVT :1;/*!< FSM Command Read_Verify failed error event, bit 25 */ + uint32_t _FEDACGLBSTATUS_Reserved_31_26 :6 ;/*!< Reserved bits 31:26 */ + } FEDAC_GLBSTATUS_BITS; + } FedacGblStatus; + + uint32_t _Reserved_20; /* Reserved Address Locations 0x20 */ + + /*! + Defines whole and bit level accesses to the Error Detection Sector Disable Register - 0x24 + */ + union FEDACSDIS + { + uint32_t u32Register; /* Error Detection Sector Disable Register, bits 31:0 */ + struct + { + uint32_t SectorID0 :6;/*!< Sector ID0 , bits 05:00 */ + uint32_t _FEDACSDIS_Reserved_07_06 :2;/*!< Reserved bits, 07:06 */ + uint32_t SectorID0_inverse :6;/*!< Sector ID0 Inverse, bits 13:08 */ + uint32_t _FEDACSDIS_Reserved_15_14 :2;/*!< Reserved bits, 15:14 */ + uint32_t SectorID1 :6;/*!< Sector ID1 , bits 21:16 */ + uint32_t _FEDACSDIS_Reserved_23_22 :2;/*!< Reserved bits, 23:22 */ + uint32_t SectorID1_inverse :6;/*!< Sector ID1 Inverse, bits 29:24 */ + uint32_t _FEDACSDIS_Reserved_31_30 :2;/*!< Reserved bits, 31:30 */ + } FEDACSDIS_BITS; + } FedAcsDis; + + /*! + Defines whole and bit level accesses to the Primary Address Tag Register - 0x28 + */ + union FPRIM_ADD_TAG + { + uint32_t u32Register; /* Primary Address Tag Register, bits 31:0 */ + struct + { + uint32_t RET_ZERO :5;/*!< This field always returns 0000, bits 4:0 */ + uint32_t PRIM_ADD_TAG :27;/*!< Primary Address Tag Register, bits 31:5 */ + } FPRIM_ADD_TAG_BITS; + } FprimAddTag; + + /*! + Defines whole and bit level accesses to the Redundant Address Tag Register - 0x2C + */ + union FDUP_ADD_TAG + { + uint32_t u32Register; /* Duplicate Address Tag Register, bits 31:0 */ + struct + { + uint32_t RET_ZERO :5;/*!< This field always returns 0000, bits 4:0 */ + uint32_t DUP_ADD_TAG :27;/*!< Duplicate Address Tag Register, bits 31:5 */ + } FDUP_ADD_TAG_BITS; + } FdupAddTag; + + /*! + Defines whole and bit level accesses to the Bank Sector Enable Register - 0x30 + */ + union FBPROT + { + uint32_t u32Register; /* Bank Protection Register, bits 31:0 */ + struct + { + uint32_t PROTL1DIS :1; /*!< Level 1 Protection Disabled, bit 0 */ + uint32_t _FBPROT_Reserved_31_01 :31;/*!< Reserved, bits 31:1 */ + } FBPROT_BITS; + } Fbprot; + + /*! + Defines whole and bit level accesses to the Bank Protection Register - 0x34 + */ + union FBSE + { + uint32_t u32Register; /* Bank Protection Register, bits 31:0 */ + struct + { + uint32_t BSE :16;/*!< Bank Sector Enable, bits 15:0 */ + uint32_t _FBSE_Reserved_31_16 :16;/*!< Reserved, bits 31:16 */ + } FBSE_BITS; + } Fbse; + + /*! + Defines whole and bit level accesses to the Bank Busy Register - 0x38 + */ + union FBBUSY + { + uint32_t u32Register; /* Bank Busy Register, bits 31:0 */ + struct + { + uint32_t BUSY :8; /*!< Bank Busy, bits 7:0 */ + uint32_t _FBBUSY_Reserved_31_08 :24;/*!< Reserved, bits 31:8 */ + } FBPROT_BITS; + } Fbbusy; + + /*! + Defines whole and bit level accesses to the Bank Access Control Register - 0x3C + */ + union FBAC + { + uint32_t u32Register; /* Bank Access Control Register, bits 31:0 */ + struct + { + uint32_t VREADS :8;/*!< VREAD Setup, bits 7:0 */ + uint32_t _FBAC_Reserved_15_08 :8;/*!< Reserved, bits 15:8 */ + uint32_t OTPPROTDIS :8;/*!< OTP Sector Protection Disable, bits 23:16 */ + uint32_t _FBAC_Reserved_31_24 :8;/*!< Reserved, bits 31:24 */ + } FBAC_BITS; + } Fbac; + + /*! + Defines whole and bit level accesses to the Bank Power mode Register - 0x40 + */ + union FBFALLBACK + { + uint32_t u32Register; /* Bank Fallback Power Register, bits 31:0 */ + struct + { + uint32_t BANKPWR0 :2;/*!< Bank 0 Fallback Power Mode, bits 15:14 */ + uint32_t BANKPWR1 :2;/*!< Bank 1 Fallback Power Mode, bits 15:14 */ + uint32_t BANKPWR2 :2;/*!< Bank 2 Fallback Power Mode, bits 15:14 */ + uint32_t BANKPWR3 :2;/*!< Bank 3 Fallback Power Mode, bits 15:14 */ + uint32_t BANKPWR4 :2;/*!< Bank 4 Fallback Power Mode, bits 15:14 */ + uint32_t BANKPWR5 :2;/*!< Bank 5 Fallback Power Mode, bits 15:14 */ + uint32_t BANKPWR6 :2;/*!< Bank 6 Fallback Power Mode, bits 15:14 */ + uint32_t BANKPWR7 :2;/*!< Bank 7 Fallback Power Mode, bits 15:14 */ + uint32_t _FBAC_Reserved_31_16 :16;/*!< Reserved, bits 31:16 */ + } FBFALLBACK_BITS; + } Fbfallback; + + /*! + Defines whole and bit level accesses to the Bank/Pump Ready Register - 0x44 + */ + union FBPRDY + { + uint32_t u32Register; /* Bank/Pump Ready Register, bits 31:0 */ + struct + { + uint32_t BANKRDY :8;/*!< Bank Ready, bits 7:0 */ + uint32_t _FBPRDY_Reserved_14_08 :7;/*!< Reserved, bits 14:8 */ + uint32_t PUMPRDY :1;/*!< Pump Ready, bit 15 */ + uint32_t BANKBUSY :8;/*!< Bank Busy with FSM, SW_INTF, CPU or PMT, bits 23:16 */ + uint32_t _FBPRDY_Reserved_31_24 :8;/*!< Reserved, bits 31:24 */ + } FBPRDY_BITS; + } Fbprdy; + + /*! + Defines whole and bit level accesses to the Pump Access Control Register 1 - 0x48 + */ + union FPAC1 + { + uint32_t u32Register; /* Flash Pump Access Control Register 1, bits 31:0 */ + struct + { + uint32_t PUMPPWR :1; /*!< Flash Charge Pump Fallback Power Mode, bit 0 */ + uint32_t _FPAC1_Reserved_15_01 :15;/*!< Reserved, bits 15:1 */ + uint32_t PSBEEP :12;/*!< Pump Sleep, bits 27:16 */ + uint32_t _FPAC1_Reserved_31_28 :4; /*!< Reserved, bits 31:28 */ + } FPAC1_BITS; + } Fpac1; + + + uint32_t _Reserved_4C; /* Reserved Address Locations 0x4C */ + + /*! + Defines whole and bit level accesses to the Module Access Control Register - 0x50 + */ + union FMAC + { + uint32_t u32Register; /* Module Access Control Register, bits 31:0 */ + struct + { + uint32_t BANK :3; /*!< Bank Enable, bits 2:0 */ + uint32_t _FMAC_Reserved_31_03 :29; /*!< Reserved, bits 31:3 */ + } FMAC_BITS; + } Fmac; + + /*! + Defines whole and bit level accesses to the Module Status Register - 0x54 + */ + union FMSTAT + { + uint32_t u32Register; /* Module Status Register, bits 31:0 */ + struct + { + uint32_t SLOCK :1; /*!< Sector Lock Status, bit 0 */ + uint32_t PSUSP :1; /*!< Program Suspend, bit 1 */ + uint32_t ESUSP :1; /*!< Erase Suspend, bit 2 */ + uint32_t VOLSTAT :1; /*!< Core Voltage Status, bit 3 */ + uint32_t CSTAT :1; /*!< Command Status, bit 4 */ + uint32_t INVDAT :1; /*!< Invalid Data, bit 5 */ + uint32_t PGM :1; /*!< Program Active, bit 6 */ + uint32_t ERS :1; /*!< Erase Active, bit 7 */ + uint32_t BUSY :1; /*!< Busy, bit 8 */ + uint32_t CV :1; /*!< Compact Verify, bit 9 */ + uint32_t EV :1; /*!< Erase verify, bit 10 */ + uint32_t PCV :1; /*!< Precondidition verify, bit 11 */ + uint32_t PGV :1; /*!< Program verify, bit 12 */ + uint32_t DBT :1; /*!< Disturbance Test Fail, bit 13 */ + uint32_t ILA :1; /*!< Illegal Address, bit 14 */ + uint32_t RVF :1; /*!< Read Verify Failure, bit 15 */ + uint32_t RDVER :1; /*!< Read Verify command currently underway, bit 16 */ + uint32_t RVSUSP :1; /*!< Read Verify Suspend, bit 17 */ + uint32_t _FMSTAT_Reserved_31_18 :14;/*!< Reserved, bits 31:18 */ + } FMSTAT_BITS; + } FmStat; + + /*! + Defines whole and bit level accesses to the EEPROM Emulation Data MSW Register - 0x58 + */ + union FEMU_DMSW + { + uint32_t u32Register; /* EEPROM Emulation Data MSW Register, bits 31:0 */ + } FemuDmsw; + + /*! + Defines whole and bit level accesses to the EEPROM Emulation Data LSW Register - 0x5C + */ + union FEMU_DLSW + { + uint32_t u32Register; /* EEPROM Emulation Data LSW Register, bits 31:0 */ + } FemuDlsw; + + /*! + Defines whole and bit level accesses to the EEPROM Emulation ECC Register - 0x60 + */ + union FEMU_ECC + { + uint32_t u32Register; /* EEPROM Emulation ECC Register, bits 31:0 */ + struct + { + uint32_t EMU_ECC :8; /*!< EEPROM Emulation ECC, bits 7:0 */ + uint32_t _FEMU_ECC_Reserved_31_08 :24;/*!< Reserved, bits 31:8 */ + } FEMU_ECC_BITS; + } FemuEcc; + + uint32_t _Reserved_64; /* Reserved Address Locations 0x64 */ + + /*! + Defines whole and bit level accesses to the EEPROM Emulation Address Register - 0x68 + */ + union FEMU_ADDR + { + uint32_t u32Register; /* EEPROM Emulation Address, bits 31:0 */ + struct + { + uint32_t _FEMU_ADDR_Reserved_02_00 :3;/*!< Reserved, bits 02:00 */ + uint32_t EMU_ADDR :29;/*!< EEPROM Emulation Address, bits 31:03 */ + } FEMU_ADDR_BITS; + } FemuAddr; + + /*! + Defines whole and bit level accesses to the Diagnostic Control Register - 0x6C + */ + union FDIAGCTRL + { + uint32_t u32Register; /* Diagnostic Control Register, bits 31:0 */ + struct + { + uint32_t DIAGMODE :3;/*!< Diagnostic Mode, bits 2:0 */ + uint32_t _FDIAGCTRL_Reserved_07_03 :5;/*!< Reserved, bits 7:3 */ + uint32_t DIAG_BUF_SEL :3;/*!< Diagnostic Buffer Select, bits 10:8 */ + uint32_t _FDIAGCTRL_Reserved_15_11 :5;/*!< Reserved, bits 15:11 */ + uint32_t DIAG_EN_KEY :4;/*!< Diagnostic Enable Key, bits 19:16 */ + uint32_t _FDIAGCTRL_Reserved_23_20 :4;/*!< Reserved, bits 23:20 */ + uint32_t DIAG_TRIG :1;/*!< Diagnostic Trigger, bit 24 */ + uint32_t _FDIAGCTRL_Reserved_31_25 :7;/*!< Reserved, bits 31:25 */ + } FDIAGCTRL_BITS; + } FdiagCtrl; + + uint32_t _Reserved_70; /* Reserved Address Locations 0x70 */ + + /*! + Defines whole and bit level accesses to the Uncorrected Raw Data High Register - 0x70 + */ + union FRAW_ADDR + { + uint32_t u32Register; /* Uncorrected Raw Data High, bits 31:0 */ + struct + { + uint32_t _FRAW_ADDR_Reserved_04_00 :5;/*!< Reserved, bits 04:00 */ + uint32_t RAW_ADDR :27;/*!< EEPROM Emulation Address, bits 31:05 */ + } FRAW_ADDR_BITS; + } FrawAddr; + + uint32_t _Reserved_78; /* Reserved Address Locations 0x78 */ + + /*! + Defines whole and bit level accesses to the Parity Override Register - 0x7C + */ + union FPAR_OVR + { + uint32_t u32Register; /* Parity Override, bits 31:0 */ + struct + { + uint32_t DAT_INV_PAR :8; /*!< Data Odd Parity, bits 7:0 */ + uint32_t _FPAR_OVR_Reserved_08 :1; /*!< Reserved , bit 8 */ + uint32_t PAR_OVR_KEY :3; /*!< Parity Override Key, bits 11:9 */ + uint32_t BUS_PAR_DIS :4; /*!< Disable bus parity, bits 15:12 */ + uint32_t BNK_INV_PAR :1; /*!< Buffer Invert Parity, bit 16 */ + uint32_t _FPAR_OVR_Reserved_31_17 :15;/*!< Reserved, bits 31:17 */ + } FPAR_OVR_BITS; + } FparOvr; + + + uint32_t _Reserved_80_B0[13];/* Reserved Address Locations 0x80 - 0xB0 */ + + /*! + Defines whole and bit level accesses to the Reset Config and JSM Key Valid Register - 0xB4 + */ + union RCR_JSM_VALID + { + uint32_t u32Register; /* Uncorrected Raw Data High, bits 31:0 */ + struct + { + uint32_t RCR_VALID :1;/*!< RCR Key Valid, bits 0 */ + uint32_t JSM_VALID :1;/*!< JSM Key Valid, bits 1 */ + uint32_t _RCR_JSM_VALID_Reserved_31_02 :30;/*!< Reserved , bits 31:02 */ + } RCR_JSM_VALID_BITS; + } RcrJsmValid; + + /*! + Defines whole and bit level accesses to the Crossbar access time threshold Register - 0xB8 + */ + union ACC_THRESHOLD + { + uint32_t u32Register; /* Uncorrected Raw Data High, bits 31:0 */ + struct + { + uint32_t ACC_THRESH_CNT :12;/*!< Crossbar access time threshold count, bits 11:00 */ + uint32_t _ACC_THRESHOLD_Reserved_31_12 :20;/*!< Reserved , bits 31:12 */ + } ACC_THRESHOLD_BITS; + } AccThreshold; + + uint32_t _Reserved_BC;/* Reserved Address Locations 0xBC */ + + /*! + Defines whole and bit level accesses to the EEPROM Error Detection Sector Disable Register - 0xC0 + */ + union FEDACSDIS2 + { + uint32_t u32Register; /* Error Detection Sector Disable Register, bits 31:0 */ + struct + { + uint32_t SectorID2 :6;/*!< Sector ID2 , bits 05:00 */ + uint32_t _FEDACSDIS_Reserved_07_06 :2;/*!< Reserved bits, 07:06 */ + uint32_t SectorID2_inverse :6;/*!< Sector ID2 Inverse, bits 13:08 */ + uint32_t _FEDACSDIS_Reserved_15_14 :2;/*!< Reserved bits, 15:14 */ + uint32_t SectorID3 :6;/*!< Sector ID3 , bits 21:16 */ + uint32_t _FEDACSDIS_Reserved_23_22 :2;/*!< Reserved bits, 23:22 */ + uint32_t SectorID3_inverse :6;/*!< Sector ID3 Inverse, bits 29:24 */ + uint32_t _FEDACSDIS_Reserved_31_30 :2;/*!< Reserved bits, 31:30 */ + } FEDACSDIS_BITS; + } FedAcsDis2; + + uint32_t _Reserved_C4_CC[3];/* Reserved Address Locations 0xC4-0xCC */ + + /*! + Defines whole and bit level accesses to the RCR Lower word - 0xD0 + */ + union RCRVALUE0 + { + uint32_t u32Register; /* RCR Lower word, bits 31:0 */ + } RcrValue0; + + /*! + Defines whole and bit level accesses to the RCR Upper word - 0xD4 + */ + union RCRVALUE1 + { + uint32_t u32Register; /* RCR Upper word, bits 31:0 */ + } RcrValue1; + + uint32_t _Reserved_D8_DC[2];/* Reserved Address Locations 0xD8-0xDC */ + + /*! + Defines whole and bit level accesses to the JSM Key0 - 0xE0 + */ + union JSMKEY0 + { + uint32_t u32Register; /* Bank Addr Register, bits 31:0 */ + } JSMKey0; + + /*! + Defines whole and bit level accesses to the JSM Key1 - 0xE4 + */ + union JSMKEY1 + { + uint32_t u32Register; /* Bank Addr Register, bits 31:0 */ + } JSMKey1; + + + /*! + Defines whole and bit level accesses to the JSM Key2 - 0xE8 + */ + union JSMKEY2 + { + uint32_t u32Register; /* Bank Addr Register, bits 31:0 */ + } JSMKey2; + + + /*! + Defines whole and bit level accesses to the JSM Key3 - 0xEC + */ + union JSMKEY3 + { + uint32_t u32Register; /* Bank Addr Register, bits 31:0 */ + } JSMKey3; + + uint32_t _Reserved_F0_10C[8];/* Reserved Address Locations 0xF0 - 0x10C */ + + + /*! + Defines whole and bit level accesses to the Bank Addr Register - 0x110 + */ + union FADDR + { + uint32_t u32Register; /* Bank Addr Register, bits 31:0 */ + } Faddr; + + uint32_t _Reserved_114_118[2]; /* Reserved Address Locations 0x114-0x118 */ + + union FTCTRL + { + uint32_t u32Register; /* Error Detection Sector Disable Register, bits 31:0 */ + struct + { + uint32_t Reserved_23_00 :24; + uint32_t AutoCalc_EN :1;/*!< Sector ID3 Inverse, bits 29:24 */ + uint32_t Reserved_31_30 :7;/*!< Reserved bits, 31:30 */ + } FTCTRL_BITS; + } Ftctrl; + + /*! + Defines whole and bit level accesses to the FWPWRITE0 Register - 0x120 + */ + union FWPWRITE0 + { + uint32_t u32Register; /* FWPWRITE0 Register, bits 31:0 */ + } Fwpwrite0; + + /*! + Defines whole and bit level accesses to the FWPWRITE1 Register - 0x124 + */ + union FWPWRITE1 + { + uint32_t u32Register; /* FWPWRITE1 Register, bits 31:0 */ + } Fwpwrite1; + + /*! + Defines whole and bit level accesses to the FWPWRITE2 Register - 0x128 + */ + union FWPWRITE2 + { + uint32_t u32Register; /* FWPWRITE2 Register, bits 31:0 */ + } Fwpwrite2; + + /*! + Defines whole and bit level accesses to the FWPWRITE3 Register - 0x12C + */ + union FWPWRITE3 + { + uint32_t u32Register; /* FWPWRITE3 Register, bits 31:0 */ + } Fwpwrite3; + + /*! + Defines whole and bit level accesses to the FWPWRITE4 Register - 0x130 + */ + union FWPWRITE4 + { + uint32_t u32Register; /* FWPWRITE4 Register, bits 31:0 */ + } Fwpwrite4; + + /*! + Defines whole and bit level accesses to the FWPWRITE5 Register - 0x134 + */ + union FWPWRITE5 + { + uint32_t u32Register; /* FWPWRITE5 Register, bits 31:0 */ + } Fwpwrite5; + + /*! + Defines whole and bit level accesses to the FWPWRITE6 Register - 0x138 + */ + union FWPWRITE6 + { + uint32_t u32Register; /* FWPWRITE6 Register, bits 31:0 */ + } Fwpwrite6; + + /*! + Defines whole and bit level accesses to the FWPWRITE7 Register - 0x13C + */ + union FWPWRITE7 + { + uint32_t u32Register; /* FWPWRITE7 Register, bits 31:0 */ + } Fwpwrite7; + + /*! + Defines whole and bit level accesses to the FWPWRITE_ECC Register - 0x140 + */ + union FWPWRITE_ECC + { + uint32_t u32Register; /* FWPWRITE_ECC Register, bits 31:0 */ + struct + { + uint32_t WPDATA_287_256; /*!< WPDATA[287:256], bits 31:0 */ + } FWPWRITE_ECC_BITS; + struct + { + uint32_t u8Bytes31_24:8; + uint32_t u8Bytes23_16:8; + uint32_t u8Bytes15_08:8; + uint32_t u8Bytes07_00:8; + } FWPWRITE_ECC_BYTES; + } FwpwriteEcc; + + uint32_t _Reserved_144_208[50]; /* Reserved Address Locations 0x144-0x208 */ + + /*! + Defines whole and bit level accesses to the FSM Command Register - 0x20C + */ + union FSM_COMMAND + { + uint32_t u32Register; /* FSM Command, bits 31:0 */ + struct + { + uint32_t FSMCMD :6; /*!< Flash State Machine Command, bits 5:0 */ + uint32_t _FSM_COMMAND_Reserved_31_06 :26;/*!< Reserved, bits 31:6 */ + } FSM_COMMAND_BITS; + } FsmCommand; + + uint32_t _Reserved_210_284[30]; /* Reserved Address Locations 0x210-0x284 */ + + /*! + Defines whole and bit level accesses to the FSM Register Write Enable- 0x288 + */ + union FSM_WR_ENA + { + uint32_t u32Register; /* FSM Register Write Enable, bits 31:0 */ + struct + { + uint32_t WR_ENA :3; /*!< FSM Write Enable, bits 2:0 */ + uint32_t _FSM_WR_ENA_Reserved_31_03 :29;/*!< Reserved, bits 31:3 */ + } FSM_WR_ENA_BITS; + } FsmWrEna; + + uint32_t _Reserved_28C_2A0[6]; /* Reserved Address Locations 0x28C-0x2A0 */ + + /*! + Defines whole and bit level accesses to the FSM Sector Register - 0x2A4 + */ + union FSM_SECTOR + { + uint32_t u32Register; /* FSM Sector, bits 31:0 */ + struct + { + uint32_t SEC_OUT :4; /*!< Sector from Address decoder, bits 3:0 */ + uint32_t SECTOR :4; /*!< Current sector used by FSM, bits 7:4 */ + uint32_t FLEE_SECT_ETXN :8; /*!< FLEE Sector Extension bits, bits 15:8 */ + uint32_t SECT_ERASED :16;/*!< Sectors Erased, bits 31:16 */ + } FSM_SECTOR_BITS; + } FsmSector; + + uint32_t _Reserved_2A8_2B0[3]; /* Reserved Address Locations 0x2A8-0x2B0 */ + + + /*! + Defines whole and bit level accesses to the FSM Command Execute Register - 0x2B4 + */ + union FSM_EXECUTE + { + uint32_t u32Register; /* FSM Command Execute, bits 31:0 */ + struct + { + uint32_t FSMEXECUTE :5; /*!< FSM Command Execute, bits 4:0 */ + uint32_t _FSM_EXECUTE_Reserved_15_05 :11;/*!< Reserved, bits 15:5 */ + uint32_t SUSPEND_NOW :4; /*!< FSM Command Suspend, bits 19:16 */ + uint32_t _FSM_EXECUTE_Reserved_31_20 :12;/*!< Reserved, bits 31:20 */ + } FSM_EXECUTE_BITS; + } FsmExecute; + + /*! + Defines whole and bit level accesses to the EEPROM Emulation configuration Register - 0x2B8 + */ + union EEPROM_CONFIG + { + uint32_t u32Register; /* EEPROM Emulation configuration, bits 31:0 */ + struct + { + uint32_t _EEPROM_CONFIG_Reserved_15_00 :16;/*!< Reserved, bits 15:0 */ + uint32_t EWAIT :4; /*!< EEPROM Wait state Counter, bits 19:16 */ + uint32_t _EEPROM_CONFIG_Reserved_31_20 :12;/*!< Reserved, bits 31:20 */ + } EEPROM_CONFIG_BITS; + } EepromConfig; + + uint32_t _Reserved_2BC; /* Reserved Address Locations 0x2BC */ + + /*! + Defines whole and bit level accesses to the FSM Sector1 Register - 0x2C0 + */ + union FSM_SECTOR_1 + { + uint32_t u32Register; /* FSM Sector1, bits 31:0 */ + } FsmSector1; + + /*! + Defines whole and bit level accesses to the FSM Sector2 Register - 0x2C4 + */ + union FSM_SECTOR_2 + { + uint32_t u32Register; /* FSM Sector1, bits 31:0 */ + } FsmSector2; + + uint32_t _Reserved_2C8_3FC[78];/* Reserved Address Locations 0x2C8 - 0x3FC */ + + + /*! + Defines whole and bit level accesses to the FCFG BANK Register - 0x400 + */ + union FCFG_BANK_1 + { + uint32_t u32Register; /* Flash Bank configuration, bits 31:0 */ + struct + { + uint32_t _FCFG_BANK_Reserved_3_0 :4; /*!< Reserved bits 3:0 */ + uint32_t MAIN_BANK_WIDTH :12;/*!< MAIN_BANK_WIDTH, bits 15:4 */ + uint32_t _FCFG_BANK_Reserved_19_16 :4; /*!< Reserved bits 19:16 */ + uint32_t EE_BANK_WIDTH :12;/*!< EE_BANK_WIDTH, bits 31:20 */ + } FCFG_BANK_BITS; + } FcfgBank; + + }Fapi_FmcRegistersType; +#else +typedef volatile struct FMC_REGISTERS +{ + /*! + Defines whole and bit level accesses to the Read Control Register - 0x00 + */ + union FRDCNTL + { + uint32_t u32Register; /* Read Control Register, bits 31:0 */ + struct + { + uint32_t ENPIPE :1;/*!< Read Mode, bit 0 */ + uint32_t _FRDCNTL_Reserved_03_01 :3;/*!< Reserved, bits 3:1 */ + uint32_t ASWSTEN :1;/*!< Address Setup Wait State Enable, bit 4 */ + uint32_t _FRDCNTL_Reserved_07_05 :3;/*!< Reserved, bits 7:5 */ + uint32_t RWAIT :4;/*!< Random Read Wait State, bits 11:8 */ + uint32_t _FRDCNTL_Reserved_31_12 :20;/*!< Reserved, bits 31:12 */ + } FRDCNTRL_BITS; + } FrdCntl; + + uint32_t _Reserved_04; /* Reserved Address Locations 0x04 */ + + /*! + Defines whole and bit level accesses to the Error Correction Control Register1 - 0x08 + */ + union FEDACCTRL1 + { + uint32_t u32Register; /* Error Correction Control Register1, bits 31:0 */ + struct + { + uint32_t EDACEN :4;/*!< Error Detection and Correction Enable, bits 3:0 */ + uint32_t EZCV :1;/*!< Zero Condition Valid, bit 4 */ + uint32_t EOCV :1;/*!< One Condition Valid, bit 5 */ + uint32_t _FEDACCTRL1_Reserved_07_06 :2;/*!< Reserved, bits 7:6 */ + uint32_t EPEN :1;/*!< Error Profiling Enable, bit 8 */ + uint32_t EZFEN :1;/*!< Error on Zero Fail Enable, bit 9 */ + uint32_t EOFEN :1;/*!< Error on One Fail Enable, bit 10 */ + uint32_t _FEDACCTRL1_Reserved_15_11 :5;/*!< Reserved, bits 15:11 */ + uint32_t EDACMODE :4;/*!< Error Correction Mode, bits 19:16 */ + uint32_t _FEDACCTRL1_Reserved_23_20 :4;/*!< Reserved, bits 23:20 */ + uint32_t SUSP_IGNR :1;/*!< Suspend Ignore, bit 24 */ + uint32_t _FEDACCTRL1_Reserved_31_25 :7;/*!< Reserved, bits 31:25 */ + } FEDACCTRL1_BITS; + } FedAcCtrl1; + + /*! + Defines whole and bit level accesses to the Error Correction Control Register2 - 0x0C + */ + union FEDACCTRL2 + { + uint32_t u32Register; /* Error Correction Control Register2, bits 31:0 */ + struct + { + uint32_t SEC_THRESHOLD :16;/*!< Single Error Correction Threshold, bits 15:0 */ + uint32_t _FEDACCTRL2_Reserved_31_16 :16;/*!< Reserved, bits 31:16 */ + } FEDACCTRL2_BITS; + } FedAcCtrl2; + + /*! + Defines whole and bit level accesses to the Error Correction Counter Register - 0x10 + */ + union FCOR_ERR_CNT + { + uint32_t u32Register; /* Error Correction Counter Register, bits 31:0 */ + struct + { + uint32_t FERRCNT :16;/*!< Correctable Error Counter, bits 15:0 */ + uint32_t _FCOR_ERR_CNT_Reserved_31_16 :16;/*!< Reserved, bits 31:16 */ + } FCOR_ERR_CNT_BITS; + } FcorErrCnt; + + /*! + Defines whole and bit level accesses to the Correctable Error Address Register - 0x14 + */ + union FCOR_ERR_ADD + { + uint32_t u32Register; /* Correctable Error Address Register, bits 31:0 */ + struct + { + uint32_t B_OFF :3;/*!< Byte Offset, bits 2:0 */ + uint32_t COR_ERR_ADD :29;/*!< Correctable Error Address, bits 31:3 */ + } FCOR_ERR_ADD_BITS; + } FcorErrAdd; + + /*! + Defines whole and bit level accesses to the Correctable Error Position Register - 0x18 + */ + union FCOR_ERR_POS + { + uint32_t u32Register; /* Correctable Error Position Register, bits 31:0 */ + struct + { + uint32_t ERR_POS :8; /*!< Single Error Position, bits 7:0 */ + uint32_t TYPE :1; /*!< Error Type, bit 8 */ + uint32_t BUS2 :1; /*!< Bus 2 error position, bit 9 */ + uint32_t _FCOR_ERR_POS_Reserved_31_10 :22;/*!< Reserved, bits 31:10 */ + } FCOR_ERR_POS_BITS; + } FcorErrPos; + + /*! + Defines whole and bit level accesses to the Error Status Register - 0x1C + */ + union FEDACSTATUS + { + uint32_t u32Register; /* Error Status Register, bits 31:0 */ + struct + { + uint32_t ERR_PRF_FLG :1;/*!< Error Profiling Status Flag, bit 0 */ + uint32_t ERR_ZERO_FLG :1;/*!< Error On Zero Fail Status Flag, bit 1 */ + uint32_t ERR_ONE_FLG :1;/*!< Error On One Fail Status Flag, bit 2 */ + uint32_t D_COR_ERR :1;/*!< Diagnostic Correctable Error Status Flag, bit 3 */ + uint32_t _FEDACSTATUS_Reserved_7_4 :4;/*!< Reserved, bits 7:4 */ + uint32_t B1_UNC_ERR :1;/*!< Bus1 Uncorrectable Error Flag, bit 8 */ + uint32_t _FEDACSTATUS_Reserved_9 :1;/*!< Reserved, bit 9 */ + uint32_t ADD_PAR_ERR :1;/*!< Address Parity Error, bit 10 */ + uint32_t ADD_TAG_ERR :1;/*!< Address Tag Register Error Status Flag, bit 11 */ + uint32_t D_UNC_ERR :1;/*!< Diagnostic Un-correctable Error Status Flag, bit 12 */ + uint32_t _FEDACSTATUS_Reserved_15_13 :3;/*!< Reserved, bits 15:13 */ + uint32_t B2_COR_ERR :1;/*!< Bus2 Correctable Error, bit 16 */ + uint32_t B2_UNC_ERR :1;/*!< Bus2 Uncorrectable Error, bit 17 */ + uint32_t ECC_B2_MAL_ERR :1;/*!< Bus2 ECC Malfunction Status Flag, bit 18 */ + uint32_t COMB2_MAL_G :1;/*!< Bus2 Compare Malfunction Flag, bit 19 */ + uint32_t _FEDACSTATUS_Reserved_23_20 :4;/*!< Reserved, bits 23:20 */ + uint32_t FSM_DONE :1;/*!< FSM is Finished, bit 24 */ + uint32_t _FEDACSTATUS_Reserved_31_25 :7;/*!< Reserved, bits 31:25 */ + } FEDACSTATUS_BITS; + } FedAcStatus; + + /*! + Defines whole and bit level accesses to the Un-correctable Error Address Register - 0x20 + */ + union FUNC_ERR_ADD + { + uint32_t u32Register; /* Error Status Register, bits 31:0 */ + struct + { + uint32_t B_OFF :3;/*!< Byte Offset, bits 2:0 */ + uint32_t UNC_ERR_ADD :29;/*!< Un-correctable Error Address, bits 31:3 */ + } FUNC_ERR_ADD_BITS; + } FuncErrAdd; + + /*! + Defines whole and bit level accesses to the Error Detection Sector Disable Register - 0x24 + */ + union FEDACSDIS + { + uint32_t u32Register; /* Error Detection Sector Disable Register, bits 31:0 */ + struct + { + uint32_t SectorID0 :4;/*!< Sector ID0 , bits 3:0 */ + uint32_t _FEDACSDIS_Reserved_04 :1;/*!< Reserved, bit 4 */ + uint32_t BankID0 :3;/*!< Bank ID0 , bits 7:5 */ + uint32_t SectorID0_inverse :4;/*!< Sector ID0 Inverse, bits 11:8 */ + uint32_t _FEDACSDIS_Reserved_12 :1;/*!< Reserved, bit 12 */ + uint32_t BankID0_inverse :3;/*!< Bank ID0 Inverse, bits 15:13 */ + uint32_t SectorID1 :4;/*!< Sector ID1 , bits 19:16 */ + uint32_t _FEDACSDIS_Reserved_20 :1;/*!< Reserved, bit 20 */ + uint32_t BankID1 :3;/*!< Bank ID1 , bits 23:21 */ + uint32_t SectorID1_inverse :4;/*!< Sector ID1 Inverse, bits 27:24 */ + uint32_t _FEDACSDIS_Reserved_28 :1;/*!< Reserved, bit 28 */ + uint32_t BankID1_inverse :3;/*!< Bank ID1 Inverse, bits 31:29 */ + } FEDACSDIS_BITS; + } FedAcsDis; + + /*! + Defines whole and bit level accesses to the Primary Address Tag Register - 0x28 + */ + union FPRIM_ADD_TAG + { + uint32_t u32Register; /* Primary Address Tag Register, bits 31:0 */ + struct + { + uint32_t RET_ZERO :4;/*!< This field always returns 0000, bits 3:0 */ + uint32_t PRIM_ADD_TAG :28;/*!< Primary Address Tag Register, bits 31:4 */ + } FPRIM_ADD_TAG_BITS; + } FprimAddTag; + + /*! + Defines whole and bit level accesses to the Redundant Address Tag Register - 0x2C + */ + union FDUP_ADD_TAG + { + uint32_t u32Register; /* Duplicate Address Tag Register, bits 31:0 */ + struct + { + uint32_t RET_ZERO :4;/*!< This field always returns 0000, bits 3:0 */ + uint32_t DUP_ADD_TAG :28;/*!< Primary Address Tag Register, bits 31:4 */ + } FDUP_ADD_TAG_BITS; + } FdupAddTag; + + /*! + Defines whole and bit level accesses to the Bank Sector Enable Register - 0x30 + */ + union FBPROT + { + uint32_t u32Register; /* Bank Protection Register, bits 31:0 */ + struct + { + uint32_t PROTL1DIS :1; /*!< Level 1 Protection Disabled, bit 0 */ + uint32_t _FBPROT_Reserved_31_01 :31;/*!< Reserved, bits 31:1 */ + } FBPROT_BITS; + } Fbprot; + + /*! + Defines whole and bit level accesses to the Bank Protection Register - 0x34 + */ + union FBSE + { + uint32_t u32Register; /* Bank Protection Register, bits 31:0 */ + struct + { + uint32_t BSE :16;/*!< Bank Sector Enable, bits 15:0 */ + uint32_t _FBSE_Reserved_31_16 :16;/*!< Reserved, bits 31:16 */ + } FBSE_BITS; + } Fbse; + + /*! + Defines whole and bit level accesses to the Bank Busy Register - 0x38 + */ + union FBBUSY + { + uint32_t u32Register; /* Bank Busy Register, bits 31:0 */ + struct + { + uint32_t BUSY :8; /*!< Bank Busy, bits 7:0 */ + uint32_t _FBBUSY_Reserved_31_08 :24;/*!< Reserved, bits 31:8 */ + } FBPROT_BITS; + } Fbbusy; + + /*! + Defines whole and bit level accesses to the Bank Access Control Register - 0x3C + */ + union FBAC + { + uint32_t u32Register; /* Bank Access Control Register, bits 31:0 */ + struct + { + uint32_t VREADS :8;/*!< VREAD Setup, bits 7:0 */ + uint32_t BAGP :8;/*!< Bank Active Grace Period, bits 15:8 */ + uint32_t OTPPROTDIS :8;/*!< OTP Sector Protection Disable, bits 23:16 */ + uint32_t _FBAC_Reserved_31_24 :8;/*!< Reserved, bits 31:24 */ + } FBAC_BITS; + } Fbac; + + /*! + Defines whole and bit level accesses to the Bank Fallback Power Register - 0x40 + */ + union FBFALLBACK + { + uint32_t u32Register; /* Bank Fallback Power Register, bits 31:0 */ + struct + { + uint32_t BANKPWR0 :2;/*!< Bank 0 Fallback Power Mode, bits 1:0 */ + uint32_t BANKPWR1 :2;/*!< Bank 1 Fallback Power Mode, bits 3:2 */ + uint32_t BANKPWR2 :2;/*!< Bank 2 Fallback Power Mode, bits 5:4 */ + uint32_t BANKPWR3 :2;/*!< Bank 3 Fallback Power Mode, bits 7:6 */ + uint32_t BANKPWR4 :2;/*!< Bank 4 Fallback Power Mode, bits 9:8 */ + uint32_t BANKPWR5 :2;/*!< Bank 5 Fallback Power Mode, bits 11:10 */ + uint32_t BANKPWR6 :2;/*!< Bank 6 Fallback Power Mode, bits 13:12 */ + uint32_t BANKPWR7 :2;/*!< Bank 7 Fallback Power Mode, bits 15:14 */ + uint32_t REG_PWRSAV :4;/*!< Power saving clocking control, bits 19:16 */ + uint32_t _FBAC_Reserved_23_20 :4;/*!< Reserved, bits 23:20 */ + uint32_t FSM_PWRSAV :4;/*!< Power saving clocking control, bits 27:24 */ + uint32_t _FBAC_Reserved_31_28 :4;/*!< Reserved, bits 31:28 */ + } FBFALLBACK_BITS; + } Fbfallback; + + /*! + Defines whole and bit level accesses to the Bank/Pump Ready Register - 0x44 + */ + union FBPRDY + { + uint32_t u32Register; /* Bank/Pump Ready Register, bits 31:0 */ + struct + { + uint32_t BANKRDY :8;/*!< Bank Ready, bits 7:0 */ + uint32_t _FBPRDY_Reserved_14_08 :7;/*!< Reserved, bits 14:8 */ + uint32_t PUMPRDY :1;/*!< Pump Ready, bit 15 */ + uint32_t BANKBUSY :8;/*!< Bank Busy with FSM, SW_INTF, CPU or PMT, bits 23:16 */ + uint32_t _FBPRDY_Reserved_31_24 :8;/*!< Reserved, bits 31:24 */ + } FBPRDY_BITS; + } Fbprdy; + + /*! + Defines whole and bit level accesses to the Pump Access Control Register 1 - 0x48 + */ + union FPAC1 + { + uint32_t u32Register; /* Flash Pump Access Control Register 1, bits 31:0 */ + struct + { + uint32_t PUMPPWR :1; /*!< Flash Charge Pump Fallback Power Mode, bit 0 */ + uint32_t _FPAC1_Reserved_15_01 :15;/*!< Reserved, bits 15:1 */ + uint32_t PSLEEP :11;/*!< Pump Sleep, bits 26:16 */ + uint32_t _FPAC1_Reserved_31_27 :5; /*!< Reserved, bits 31:27 */ + } FPAC1_BITS; + } Fpac1; + + /*! + Defines whole and bit level accesses to the Pump Access Control Register 2 - 0x4C + */ + union FPAC2 + { + uint32_t u32Register; /* Flash Pump Access Control Register 2, bits 31:0 */ + struct + { + uint32_t PAGP :16;/*!< Pump Active Grace Period, bits 15:0 */ + uint32_t _FPAC2_Reserved_31_16 :16;/*!< Reserved, bits 31:16 */ + } FPAC2_BITS; + } Fpac2; + + /*! + Defines whole and bit level accesses to the Module Access Control Register - 0x50 + */ + union FMAC + { + uint32_t u32Register; /* Module Access Control Register, bits 31:0 */ + struct + { + uint32_t BANK :3; /*!< Bank Enable, bits 2:0 */ + uint32_t _FMAC_Reserved_31_03 :29;/*!< Reserved, bits 31:3 */ + } FMAC_BITS; + } Fmac; + + /*! + Defines whole and bit level accesses to the Module Status Register - 0x54 + */ + union FMSTAT + { + uint32_t u32Register; /* Module Status Register, bits 31:0 */ + struct + { + uint32_t SLOCK :1; /*!< Sector Lock Status, bit 0 */ + uint32_t PSUSP :1; /*!< Program Suspend, bit 1 */ + uint32_t ESUSP :1; /*!< Erase Suspend, bit 2 */ + uint32_t VOLSTAT :1; /*!< Core Voltage Status, bit 3 */ + uint32_t CSTAT :1; /*!< Command Status, bit 4 */ + uint32_t INVDAT :1; /*!< Invalid Data, bit 5 */ + uint32_t PGM :1; /*!< Program Active, bit 6 */ + uint32_t ERS :1; /*!< Erase Active, bit 7 */ + uint32_t BUSY :1; /*!< Busy, bit 8 */ + uint32_t CV :1; /*!< Compact Verify, bit 9 */ + uint32_t EV :1; /*!< Erase verify, bit 10 */ + uint32_t PCV :1; /*!< Precondidition verify, bit 11 */ + uint32_t PGV :1; /*!< Program verify, bit 12 */ + uint32_t DBT :1; /*!< Disturbance Test Fail, bit 13 */ + uint32_t ILA :1; /*!< Illegal Address, bit 14 */ + uint32_t RVF :1; /*!< Read Verify Failure, bit 15 */ + uint32_t RDVER :1; /*!< Read Verify command currently underway, bit 16 */ + uint32_t RVSUSP :1; /*!< Read Verify Suspend, bit 17 */ + uint32_t _FMSTAT_Reserved_31_18 :14;/*!< Reserved, bits 31:18 */ + } FMSTAT_BITS; + } FmStat; + + /*! + Defines whole and bit level accesses to the EEPROM Emulation Data MSW Register - 0x58 + */ + union FEMU_DMSW + { + uint32_t u32Register; /* EEPROM Emulation Data MSW Register, bits 31:0 */ + } FemuDmsw; + + /*! + Defines whole and bit level accesses to the EEPROM Emulation Data LSW Register - 0x5C + */ + union FEMU_DLSW + { + uint32_t u32Register; /* EEPROM Emulation Data LSW Register, bits 31:0 */ + } FemuDlsw; + + /*! + Defines whole and bit level accesses to the EEPROM Emulation ECC Register - 0x60 + */ + union FEMU_ECC + { + uint32_t u32Register; /* EEPROM Emulation ECC Register, bits 31:0 */ + struct + { + uint32_t EMU_ECC :8; /*!< EEPROM Emulation ECC, bits 7:0 */ + uint32_t _FEMU_ECC_Reserved_31_08 :24;/*!< Reserved, bits 31:8 */ + } FEMU_ECC_BITS; + } FemuEcc; + + uint32_t _Reserved_64; /* Reserved Address Locations 0x64 */ + + /*! + Defines whole and bit level accesses to the EEPROM Emulation Address Register - 0x68 + */ + union FEMU_ADDR + { + uint32_t u32Register; /* EEPROM Emulation Address, bits 31:0 */ + struct + { + uint32_t EMU_ADDR :22;/*!< EEPROM Emulation Address, bits 21:0 */ + uint32_t _FEMU_ADDR_Reserved_31_22 :10;/*!< Reserved, bits 31:22 */ + } FEMU_ADDR_BITS; + } FemuAddr; + + /*! + Defines whole and bit level accesses to the Diagnostic Control Register - 0x6C + */ + union FDIAGCTRL + { + uint32_t u32Register; /* Diagnostic Control Register, bits 31:0 */ + struct + { + uint32_t DIAGMODE :3;/*!< Diagnostic Mode, bits 2:0 */ + uint32_t _FDIAGCTRL_Reserved_07_03 :5;/*!< Reserved, bits 7:3 */ + uint32_t DIAG_BUF_SEL :2;/*!< Diagnostic Buffer Select, bits 9:8 */ + uint32_t _FDIAGCTRL_Reserved_11_10 :2;/*!< Reserved, bits 11:10 */ + uint32_t DIAG_ECC_SEL :3;/*!< Diagnostic SECDED Select, bits 14-12 */ + uint32_t _FDIAGCTRL_Reserved_15 :1;/*!< Reserved, bit 15 */ + uint32_t DIAG_EN_KEY :4;/*!< Diagnostic Enable Key, bits 19:16 */ + uint32_t _FDIAGCTRL_Reserved_23_20 :4;/*!< Reserved, bits 23:20 */ + uint32_t DIAG_TRIG :1;/*!< Diagnostic Trigger, bit 24 */ + uint32_t _FDIAGCTRL_Reserved_31_25 :7;/*!< Reserved, bits 31:25 */ + } FDIAGCTRL_BITS; + } FdiagCtrl; + + /*! + Defines whole and bit level accesses to the Uncorrected Raw Data High Register - 0x70 + */ + union FRAW_DATAH + { + uint32_t u32Register; /* Uncorrected Raw Data High, bits 31:0 */ + } FrawDatah; + + /*! + Defines whole and bit level accesses to the Uncorrected Raw Data Low Register - 0x74 + */ + union FRAW_DATAL + { + uint32_t u32Register; /* Uncorrected Raw Data Low, bits 31:0 */ + } FrawDatal; + + /*! + Defines whole and bit level accesses to the Uncorrected Raw ECC Register - 0x78 + */ + union FRAW_ECC + { + uint32_t u32Register; /* Uncorrected Raw ECC, bits 31:0 */ + struct + { + uint32_t RAW_ECC :8; /*!< Uncorrected Raw ECC, bits 7:0 */ + uint32_t _FRAW_ECC_Reserved_31_08 :24;/*!< Reserved, bits 31:8 */ + } FRAW_ECC_BITS; + } FrawEcc; + + /*! + Defines whole and bit level accesses to the Parity Override Register - 0x7C + */ + union FPAR_OVR + { + uint32_t u32Register; /* Parity Override, bits 31:0 */ + struct + { + uint32_t DAT_INV_PAR :8; /*!< Data Odd Parity, bits 7:0 */ + uint32_t ADD_INV_PAR :1; /*!< Address Odd Parity, bit 8 */ + uint32_t PAR_OVR_KEY :3; /*!< Parity Override Key, bits 11:9 */ + uint32_t BUS_PAR_DIS :4; /*!< Disable bus parity, bits 15:12 */ + uint32_t BNK_INV_PAR :1; /*!< Buffer Invert Parity, bit 16 */ + uint32_t _FPAR_OVR_Reserved_31_17 :15;/*!< Reserved, bits 31:17 */ + } FPAR_OVR_BITS; + } FparOvr; + + uint32_t _Reserved_80_BC[16];/* Reserved Address Locations 0x80 - 0xBC */ + + /*! + Defines whole and bit level accesses to the Error Detection Sector Disable2 Register - 0xC0 + */ + union FEDACSDIS2 + { + uint32_t u32Register; /* Error Detection Sector Disable Register, bits 31:0 */ + struct + { + uint32_t SectorID2 :4;/*!< Sector ID2 , bits 3:0 */ + uint32_t _FEDACSDIS2_Reserved_4 :1;/*!< Reserved, bit 4 */ + uint32_t BankID2 :3;/*!< Bank ID2 , bits 7:5 */ + uint32_t SectorID2_inverse :4;/*!< Sector ID2 Inverse, bits 11:8 */ + uint32_t _FEDACSDIS2_Reserved_12 :1;/*!< Reserved, bit 12 */ + uint32_t BankID2_inverse :3;/*!< Bank ID2 Inverse, bits 15:13 */ + uint32_t SectorID3 :4;/*!< Sector ID3 , bits 19:16 */ + uint32_t _FEDACSDIS2_Reserved_20 :1;/*!< Reserved, bit 20 */ + uint32_t BankID3 :3;/*!< Bank ID3 , bits 23:21 */ + uint32_t SectorID3_inverse :4;/*!< Sector ID3 Inverse, bits 27:24 */ + uint32_t _FEDACSDIS2_Reserved_28 :1;/*!< Reserved, bit 28 */ + uint32_t BankID3_inverse :3;/*!< Bank ID3 Inverse, bits 31:29 */ + } FEDACSDIS2_BITS; + } FedAcsDis2; + + uint32_t _Reserved_C4_10C[19];/* Reserved Address Locations 0xC4 - 0x10C */ + + /*! + Defines whole and bit level accesses to the Bank Addr Register - 0x110 + */ + union FADDR + { + uint32_t u32Register; /* Bank Addr Register, bits 31:0 */ + } Faddr; + + uint32_t _Reserved_114_118[2]; /* Reserved Address Locations 0x114-0x118 */ + + union FTCTRL + { + uint32_t u32Register; /* Error Detection Sector Disable Register, bits 31:0 */ + struct + { + uint32_t Reserved_00 :1;/*!< Reserved bit, 00 */ + uint32_t Test_EN :1;/*!< Test Enable bit 1 */ + uint32_t Reserved_23_02 :14;/*!< Reserved bits, 23:02 */ + uint32_t WKData_Blk_Clr :1;/*!< Block clearing of FWPWRTITE, bit 16 */ + uint32_t Reserved_23_17 :7;/*!< Reserved bits, 23:17 */ + uint32_t AutoCalc_EN :1;/*!< Auto Calc Enable bit 24 */ + uint32_t Reserved_31_25 :7;/*!< Reserved bits, 31:25 */ + } FTCTRL_BITS; + } Ftctrl; + + + + /*! + Defines whole and bit level accesses to the FWPWRITE0 Register - 0x120 + */ + union FWPWRITE0 + { + uint32_t u32Register; /* FWPWRITE0 Register, bits 31:0 */ + } Fwpwrite0; + + /*! + Defines whole and bit level accesses to the FWPWRITE1 Register - 0x124 + */ + union FWPWRITE1 + { + uint32_t u32Register; /* FWPWRITE1 Register, bits 31:0 */ + } Fwpwrite1; + + /*! + Defines whole and bit level accesses to the FWPWRITE2 Register - 0x128 + */ + union FWPWRITE2 + { + uint32_t u32Register; /* FWPWRITE2 Register, bits 31:0 */ + } Fwpwrite2; + + /*! + Defines whole and bit level accesses to the FWPWRITE3 Register - 0x12C + */ + union FWPWRITE3 + { + uint32_t u32Register; /* FWPWRITE3 Register, bits 31:0 */ + } Fwpwrite3; + + /*! + Defines whole and bit level accesses to the FWPWRITE4 Register - 0x130 + */ + union FWPWRITE4 + { + uint32_t u32Register; /* FWPWRITE4 Register, bits 31:0 */ + } Fwpwrite4; + + /*! + Defines whole and bit level accesses to the FWPWRITE5 Register - 0x134 + */ + union FWPWRITE5 + { + uint32_t u32Register; /* FWPWRITE5 Register, bits 31:0 */ + } Fwpwrite5; + + /*! + Defines whole and bit level accesses to the FWPWRITE6 Register - 0x138 + */ + union FWPWRITE6 + { + uint32_t u32Register; /* FWPWRITE6 Register, bits 31:0 */ + } Fwpwrite6; + + /*! + Defines whole and bit level accesses to the FWPWRITE7 Register - 0x13C + */ + union FWPWRITE7 + { + uint32_t u32Register; /* FWPWRITE7 Register, bits 31:0 */ + } Fwpwrite7; + + /*! + Defines whole and bit level accesses to the FWPWRITE_ECC Register - 0x140 + */ + union FWPWRITE_ECC + { + uint32_t u32Register; /* FWPWRITE_ECC Register, bits 31:0 */ + struct + { + uint32_t WPDATA_287_256; /*!< WPDATA[287:256], bits 31:0 */ + } FWPWRITE_ECC_BITS; + struct + { + uint32_t u8Bytes31_24:8; + uint32_t u8Bytes23_16:8; + uint32_t u8Bytes15_08:8; + uint32_t u8Bytes07_00:8; + } FWPWRITE_ECC_BYTES; + } FwpwriteEcc; + + uint32_t _Reserved_144_208[50]; /* Reserved Address Locations 0x144-0x208 */ + + /*! + Defines whole and bit level accesses to the FSM Command Register - 0x20C + */ + union FSM_COMMAND + { + uint32_t u32Register; /* FSM Command, bits 31:0 */ + struct + { + uint32_t FSMCMD :6; /*!< Flash State Machine Command, bits 5:0 */ + uint32_t _FSM_COMMAND_Reserved_31_06 :26;/*!< Reserved, bits 31:6 */ + } FSM_COMMAND_BITS; + } FsmCommand; + + uint32_t _Reserved_210_284[30]; /* Reserved Address Locations 0x210-0x284 */ + + /*! + Defines whole and bit level accesses to the FSM Register Write Enable- 0x288 + */ + union FSM_WR_ENA + { + uint32_t u32Register; /* FSM Register Write Enable, bits 31:0 */ + struct + { + uint32_t WR_ENA :3; /*!< FSM Write Enable, bits 2:0 */ + uint32_t _FSM_WR_ENA_Reserved_31_03 :29;/*!< Reserved, bits 31:3 */ + } FSM_WR_ENA_BITS; + } FsmWrEna; + + uint32_t _Reserved_28C_2A0[6]; /* Reserved Address Locations 0x28C-0x2A0 */ + + /*! + Defines whole and bit level accesses to the FSM Sector Register - 0x2A4 + */ + union FSM_SECTOR + { + uint32_t u32Register; /* FSM Sector, bits 31:0 */ + struct + { + uint32_t _FSM_SECTOR_Reserved_15_0 :8; /*!< Reserved, bits 15:8 */ + uint32_t SECT_ERASED :16;/*!< Sectors Erased, bits 31:16 */ + } FSM_SECTOR_BITS; + } FsmSector; + + uint32_t _Reserved_2A8_2B0[3]; /* Reserved Address Locations 0x2A8-0x2B0 */ + + /*! + Defines whole and bit level accesses to the FSM Command Execute Register - 0x2B4 + */ + union FSM_EXECUTE + { + uint32_t u32Register; /* FSM Command Execute, bits 31:0 */ + struct + { + uint32_t FSMEXECUTE :5; /*!< FSM Command Execute, bits 4:0 */ + uint32_t _FSM_EXECUTE_Reserved_15_05 :11; /*!< Reserved, bits 15:5 */ + uint32_t SUSPEND_NOW :4; /*!< FSM Command Suspend, bits 19:16 */ + uint32_t _FSM_EXECUTE_Reserved_31_20 :12; /*!< Reserved, bits 31:20 */ + } FSM_EXECUTE_BITS; + } FsmExecute; + + /*! + Defines whole and bit level accesses to the EEPROM Emulation configuration Register - 0x2B8 + */ + union EEPROM_CONFIG + { + uint32_t u32Register; /* EEPROM Emulation configuration, bits 31:0 */ + struct + { + uint32_t AUTOSTART_GRACE :8; /*!< Auto-suspend Startup Grace Period, bits 7:0 */ + uint32_t AUTOSUSP_EN :1; /*!< Auto-suspend Enable, bit 8 */ + uint32_t _EEPROM_CONFIG_Reserved_15_09 :7; /*!< Reserved, bits 15:9 */ + uint32_t EWAIT :4; /*!< EEPROM Wait state Counter, bits 19:16 */ + uint32_t _EEPROM_CONFIG_Reserved_31_20 :12; /*!< Reserved, bits 31:20 */ + } EEPROM_CONFIG_BITS; + } EepromConfig; + + uint32_t _Reserved_2BC; /* Reserved Address Locations 0x2BC */ + + /*! + Defines whole and bit level accesses to the FSM Sector1 Register - 0x2C0 + */ + union FSM_SECTOR_1 + { + uint32_t u32Register; /* FSM Sector1, bits 31:0 */ + } FsmSector1; + + /*! + Defines whole and bit level accesses to the FSM Sector2 Register - 0x2C4 + */ + union FSM_SECTOR_2 + { + uint32_t u32Register; /* FSM Sector1, bits 31:0 */ + } FsmSector2; + + uint32_t _Reserved_2C8_304[16];/* Reserved Address Locations 0x2C8 - 0x304 */ + + /*! + Defines whole and bit level accesses to the EEPROM Error Correction Control Register1 - 0x308 + */ + union EE_CTRL1 + { + uint32_t u32Register; /* EEPROM Error Correction Control Register1, bits 31:0 */ + struct + { + uint32_t EE_EDACEN :4;/*!< Error Detection and Correction Enable, bits 3:0 */ + uint32_t EE_ALL0_OK :1;/*!< Zero Condition Valid, bit 4 */ + uint32_t EE_ALL1_OK :1;/*!< One Condition Valid, bit 5 */ + uint32_t _EE_CTRL1_Reserved_07_06 :2;/*!< Reserved, bits 7:6 */ + uint32_t EE_PEN :1;/*!< Error Profiling Enable, bit 8 */ + uint32_t EE_EZFEN :1;/*!< Error on Zero Fail Enable, bit 9 */ + uint32_t EE_EOFEN :1;/*!< Error on One Fail Enable, bit 10 */ + uint32_t _EE_CTRL1_Reserved_15_11 :5;/*!< Reserved, bits 15:11 */ + uint32_t EE_EDACMODE :4;/*!< Error Correction Mode, bits 19:16 */ + uint32_t _EE_CTRL1_Reserved_31_20 :12;/*!< Reserved, bits 31:20 */ + } EE_CTRL1_BITS; + } EeCtrl1; + + /*! + Defines whole and bit level accesses to the EEPROM Error Correction Control Register2 - 0x30C + */ + union EE_CTRL2 + { + uint32_t u32Register; /* EEPROM Error Correction Control Register2, bits 31:0 */ + struct + { + uint32_t EE_SEC_THRESHOLD :16;/*!< EEPROM Single Error Correction Threshold, bits 15:0 */ + uint32_t _EE_CTRL2_Reserved_31_16 :16;/*!< Reserved, bits 31:16 */ + } EE_CTRL2_BITS; + } EeCtrl2; + + /*! + Defines whole and bit level accesses to the EEPROM Error Correction Counter Register - 0x310 + */ + union EE_COR_ERR_CNT + { + uint32_t u32Register; /* EEPROM Error Correction Counter Register, bits 31:0 */ + struct + { + uint32_t EE_ERRCNT :16;/*!< Correctable Error Counter, bits 15:0 */ + uint32_t _EE_COR_ERR_CNT_Reserved_31_16 :16;/*!< Reserved, bits 31:16 */ + } EE_COR_ERR_CNT_BITS; + } EeCorErrCnt; + + /*! + Defines whole and bit level accesses to the EEPROM Correctable Error Address Register - 0x314 + */ + union EE_COR_ERR_ADD + { + uint32_t u32Register; /* Correctable Error Address Register, bits 31:0 */ + struct + { + uint32_t B_OFF :3;/*!< Byte Offset, bits 2:0 */ + uint32_t COR_ERR_ADD :29;/*!< Correctable Error Address, bits 31:3 */ + } EE_COR_ERR_ADD_BITS; + } EeCorErrAdd; + + /*! + Defines whole and bit level accesses to the EEPROM Correctable Error Position Register - 0x318 + */ + union EE_COR_ERR_POS + { + uint32_t u32Register; /* EEPROM Correctable Error Position Register, bits 31:0 */ + struct + { + uint32_t EE_ERR_POS :8; /*!< Single Error Position, bits 7:0 */ + uint32_t TYPE :1; /*!< Error Type, bit 8 */ + uint32_t _EE_COR_ERR_POS_Reserved_31_9 :22;/*!< Reserved, bits 31:9 */ + } EE_COR_ERR_POS_BITS; + } EeCorErrPos; + + /*! + Defines whole and bit level accesses to the EEPROM Error Status Register - 0x31C + */ + union EE_STATUS + { + uint32_t u32Register; /* EEPROM Error Status Register, bits 31:0 */ + struct + { + uint32_t EE_ERR_PRF_FLG :1;/*!< Error Profiling Status Flag, bit 0 */ + uint32_t EE_ERR_ZERO_FLG :1;/*!< Error On Zero Fail Status Flag, bit 1 */ + uint32_t EE_ERR_ONE_FLG :1;/*!< Error On One Fail Status Flag, bit 2 */ + uint32_t EE_D_COR_ERR :1;/*!< Diagnostic Correctable Error Status Flag, bit 3 */ + uint32_t EE_CME :1;/*!< EE ECC Malfunction Status Flag, bit 4 */ + uint32_t _EE_STATUS_Reserved_5 :1;/*!< Reserved, bit 5 */ + uint32_t EE_CMG :1;/*!< EE Compare Malfunction Flag, bit 6 */ + uint32_t _EE_STATUS_Reserved_7 :1;/*!< Reserved, bit 7 */ + uint32_t EE_UNC_ERR :1;/*!< Multiple bit ECC or Parity Error Status Flag, bit 8 */ + uint32_t _EE_STATUS_Reserved_11_9 :3;/*!< Reserved, bits 11:9 */ + uint32_t EE_D_UNC_ERR :1;/*!< Diagnostic Un-correctable Error Status Flag, bit 12 */ + uint32_t _EE_STATUS_Reserved_31_13 :19;/*!< Reserved, bits 31:13 */ + } EE_STATUS_BITS; + } EeStatus; + + /*! + Defines whole and bit level accesses to the Un-correctable Error Address Register - 0x320 + */ + union EE_UNC_ERR_ADD + { + uint32_t u32Register; /* Error Status Register, bits 31:0 */ + struct + { + uint32_t B_OFF :3;/*!< Byte Offset, bits 2:0 */ + uint32_t UNC_ERR_ADD :29;/*!< Un-correctable Error Address, bits 31:3 */ + } EE_UNC_ERR_ADD_BITS; + } EeUncErrAdd; + + uint32_t _Reserved_324_3FC[55];/* Reserved Address Locations 0x324 - 0x3FC */ + + /*! + Defines whole and bit level accesses to the FCFG BANK Register - 0x400 + */ + union FCFG_BANK_1 + { + uint32_t u32Register; /* Flash Bank configuration, bits 31:0 */ + struct + { + uint32_t _FCFG_BANK_Reserved_3_0 :4; /*!< Reserved bits 3:0 */ + uint32_t MAIN_BANK_WIDTH :12;/*!< MAIN_BANK_WIDTH, bits 15:4 */ + uint32_t _FCFG_BANK_Reserved_19_16 :4; /*!< Reserved bits 19:16 */ + uint32_t EE_BANK_WIDTH :12;/*!< EE_BANK_WIDTH, bits 31:20 */ + } FCFG_BANK_BITS; + } FcfgBank; + +} Fapi_FmcRegistersType; +#endif + +#endif /* REGISTERS_LE_H_ */ + +/********************************************************************************************************************** + * END OF FILE: Registers_FMC_LE.h + *********************************************************************************************************************/ Index: FlashDrvr/Types.h =================================================================== diff -u --- FlashDrvr/Types.h (revision 0) +++ FlashDrvr/Types.h (revision 6d80d69a210f45c733e5307859351f2cd820a8e7) @@ -0,0 +1,569 @@ +/********************************************************************************************************************** + * COPYRIGHT + * ------------------------------------------------------------------------------------------------------------------- + * \verbatim + * + * � Copyright 2009-2012 Texas Instruments Incorporated. All rights reserved. + * + * \endverbatim + * ------------------------------------------------------------------------------------------------------------------- + * FILE DESCRIPTION + * ------------------------------------------------------------------------------------------------------------------- + * + * Project: Hercules� ARM� Safety MCUs - F021 Flash API + * Version: v2.01.01 Build(000830) + * Build Date: 2014-10-21 + * + * File: Types.h + * + * Description: Types used by the F021 API. + *--------------------------------------------------------------------------------------------------------------------- + * Author: John R Hall + *--------------------------------------------------------------------------------------------------------------------- + * + *********************************************************************************************************************/ + + +#ifndef TYPES_H_ +#define TYPES_H_ + +/********************************************************************************************************************** + * INCLUDES + *********************************************************************************************************************/ +/*LDRA_NOANALYSIS*/ +#include +#include +/*LDRA_ANALYSIS*/ + +#if defined(__TI_COMPILER_VERSION__) /* TI CCS Compiler */ +#include "CGT.CCS.h" +#elif defined(__ICCARM__) /* IAR EWARM Compiler */ +#include "CGT.IAR.h" +#elif defined(__ghs__) /* GreenHills Compiler */ +#include "CGT.GHS.h" +#elif defined(__ARMCC_VERSION) /* ARM Compiler */ +#include "CGT.ARM.h" +#elif defined(__GNUC__) /* gcc Compiler */ +#include "CGT.gcc.h" +#else +#error "A valid code generation compiler type was not determined!" +#endif + +#if !defined(_LITTLE_ENDIAN) && !defined(_BIG_ENDIAN) +#error "Target Endianess is not defined" +#endif + + +/*****************************************************************************/ +/* GLOBAL DEFINITIONS */ +/*****************************************************************************/ +#if !defined(HIGH_BYTE_FIRST) +#define HIGH_BYTE_FIRST 0U +#endif + +#if !defined(LOW_BYTE_FIRST) +#define LOW_BYTE_FIRST 1U +#endif + +#if !defined(CPU_BYTE_ORDER) +#if defined(_LITTLE_ENDIAN) + #define CPU_BYTE_ORDER (LOW_BYTE_FIRST) +#else + #define CPU_BYTE_ORDER (HIGH_BYTE_FIRST) +#endif +#endif + +#if !defined(false) +#define false 0U +#endif +#if !defined(true) +#define true 1U +#endif + +/*****************************************************************************/ +/* TYPE DEFINITIONS */ +/*****************************************************************************/ +typedef unsigned char boolean_t; + +/*! + \brief This is used to indicate which Cpu is being used. +*/ +typedef enum +{ + Fapi_MasterCpu, + Fapi_SlaveCpu0 +} ATTRIBUTE_PACKED Fapi_CpuSelectorType; + +/*! + \brief This is used to indicate what type of Cpu is being used. +*/ +typedef enum +{ + ARM7 = 0U, /* ARM7 core, Legacy placeholder */ + M3 = 1U, /* ARM Cortex M3 core */ + R4 = 2U, /* ARM Cortex R4 core without ECC logic */ + R4F = 3U, /* ARM Cortex R4, R4F, and R5 cores with ECC logic*/ + C28 = 4U, /* TI C28x core */ + Undefined1 = 5U, /* To Be Determined. Future core placeholder */ + Undefined2 = 6U, /* To Be Determined. Future core placeholder */ + Undefined3 = 7U /* To Be Determined. Future core placeholder */ +} ATTRIBUTE_PACKED Fapi_CpuType; + +/*! + \brief This is used to indicate what type of Family is being used. +*/ +typedef enum +{ + Family_FMC = 0x00, + Family_L2FMC = 0x10, + Family_Sonata = 0x20, + Family_Stellaris = 0x30, + Family_Future = 0x40 +} ATTRIBUTE_PACKED Fapi_FamilyType; + +/*! + \brief This is used to indicate what type of Address is being used. +*/ +typedef enum +{ + Fapi_Flash, + Fapi_FlashEcc, + Fapi_Otp, + Fapi_OtpEcc, + Fapi_Undefined +} ATTRIBUTE_PACKED Fapi_AddressMemoryType; + +/*! + \brief This is used to return the information from the engineering row in the TI OTP. +*/ +typedef struct +{ + uint32_t u32AsicId; + uint8_t u8Revision; + uint32_t u32LotNumber; + uint16_t u16FlowCheck; + uint16_t u16WaferNumber; + uint16_t u16XCoordinate; + uint16_t u16YCoordinate; +} ATTRIBUTE_PACKED Fapi_EngineeringRowType; + +typedef struct +{ + uint32_t au32StatusWord[4]; +} ATTRIBUTE_PACKED Fapi_FlashStatusWordType; + +/*! + \brief This contains all the possible modes used in the Fapi_IssueAsyncProgrammingCommand(). +*/ +typedef enum +{ + Fapi_AutoEccGeneration, /* This is the default mode for the command and will auto generate the ECC for the + provided data buffer */ + Fapi_DataOnly, /* Command will only process the data buffer */ + Fapi_EccOnly, /* Command will only process the ecc buffer */ + Fapi_DataAndEcc /* Command will process data and ecc buffers */ +} ATTRIBUTE_PACKED Fapi_FlashProgrammingCommandsType; + +/*! + \brief This is used to indicate which Flash bank is being used. +*/ +typedef enum +{ + Fapi_FlashBank0=0, + Fapi_FlashBank1=1, + Fapi_FlashBank2=2, + Fapi_FlashBank3=3, + Fapi_FlashBank4=4, + Fapi_FlashBank5=5, + Fapi_FlashBank6=6, + Fapi_FlashBank7=7 +} ATTRIBUTE_PACKED Fapi_FlashBankType; + +/*! + \brief This is used to indicate what F021 Bank Technology the bank is +*/ +typedef enum +{ + Fapi_FLEP=0, + Fapi_FLEE=1, + Fapi_FLES=2, + Fapi_FLHV=3 +} ATTRIBUTE_PACKED Fapi_FlashBankTechType; + +/*! + \brief This is used to indicate which Flash sector is being used. +*/ +typedef enum +{ + Fapi_FlashSector0, + Fapi_FlashSector1, + Fapi_FlashSector2, + Fapi_FlashSector3, + Fapi_FlashSector4, + Fapi_FlashSector5, + Fapi_FlashSector6, + Fapi_FlashSector7, + Fapi_FlashSector8, + Fapi_FlashSector9, + Fapi_FlashSector10, + Fapi_FlashSector11, + Fapi_FlashSector12, + Fapi_FlashSector13, + Fapi_FlashSector14, + Fapi_FlashSector15, + Fapi_FlashSector16, + Fapi_FlashSector17, + Fapi_FlashSector18, + Fapi_FlashSector19, + Fapi_FlashSector20, + Fapi_FlashSector21, + Fapi_FlashSector22, + Fapi_FlashSector23, + Fapi_FlashSector24, + Fapi_FlashSector25, + Fapi_FlashSector26, + Fapi_FlashSector27, + Fapi_FlashSector28, + Fapi_FlashSector29, + Fapi_FlashSector30, + Fapi_FlashSector31, + Fapi_FlashSector32, + Fapi_FlashSector33, + Fapi_FlashSector34, + Fapi_FlashSector35, + Fapi_FlashSector36, + Fapi_FlashSector37, + Fapi_FlashSector38, + Fapi_FlashSector39, + Fapi_FlashSector40, + Fapi_FlashSector41, + Fapi_FlashSector42, + Fapi_FlashSector43, + Fapi_FlashSector44, + Fapi_FlashSector45, + Fapi_FlashSector46, + Fapi_FlashSector47, + Fapi_FlashSector48, + Fapi_FlashSector49, + Fapi_FlashSector50, + Fapi_FlashSector51, + Fapi_FlashSector52, + Fapi_FlashSector53, + Fapi_FlashSector54, + Fapi_FlashSector55, + Fapi_FlashSector56, + Fapi_FlashSector57, + Fapi_FlashSector58, + Fapi_FlashSector59, + Fapi_FlashSector60, + Fapi_FlashSector61, + Fapi_FlashSector62, + Fapi_FlashSector63 +} ATTRIBUTE_PACKED Fapi_FlashSectorType; + +/*! + \brief This contains all the possible Flash State Machine commands. +*/ +typedef enum +{ + Fapi_ProgramData = 0x0002, + Fapi_EraseSector = 0x0006, + Fapi_EraseBank = 0x0008, + Fapi_ValidateSector = 0x000E, + Fapi_ClearStatus = 0x0010, + Fapi_ProgramResume = 0x0014, + Fapi_EraseResume = 0x0016, + Fapi_ClearMore = 0x0018 +} ATTRIBUTE_PACKED Fapi_FlashStateCommandsType; + +/*LDRA_INSPECTED 495 S MR: 6.3 "This does have a size indicated. LDRA is incorrect" */ +typedef uint32_t Fapi_FlashStatusType; + +/*! + \brief This contains all the possible Flash State Machine commands. +*/ +typedef enum +{ + Fapi_NormalRead = 0x0, + Fapi_RM0 = 0x1, + Fapi_RM1 = 0x2 +} ATTRIBUTE_PACKED Fapi_FlashReadMarginModeType; + +/*! + \brief This is the master type containing all possible returned status codes. +*/ +typedef enum +{ + Fapi_Status_Success=0, /* Function completed successfully */ + Fapi_Status_FsmBusy, /* FSM is Busy */ + Fapi_Status_FsmReady, /* FSM is Ready */ + Fapi_Error_Fail, /* Generic Function Fail code */ + Fapi_Error_NullPointer, /* One of the pointer parameters is a null pointer */ + Fapi_Error_InvalidCommand, /* Command used is invalid for the function called */ + Fapi_Error_InvalidEccAddress, /* Returned if the ECC Address given to a function is invalid for that function */ + Fapi_Error_OtpChecksumMismatch, /* Returned if OTP checksum does not match expected value */ + Fapi_Error_InvalidHclkValue, /* Returned if FClk is above max FClk value - FClk is a calculated from HClk and + RWAIT/EWAIT */ + Fapi_Error_InvalidBank, /* Returned if the specified bank does not exist */ + Fapi_Error_InvalidAddress, /* Returned if the specified Address does not exist in Flash or OTP */ + Fapi_Error_InvalidReadMode, /* Returned if the specified read mode does not exist */ + Fapi_Error_AsyncIncorrectDataBufferLength, /* Returned if Data buffer size specified exceeds Data bank width */ + Fapi_Error_AsyncIncorrectEccBufferLength, /* Returned if ECC buffer size specified exceeds ECC bank width */ + Fapi_Error_AsyncDataEccBufferLengthMismatch, /* Returned if Data buffer size either is not 64bit aligned or Data + length exceeds amount ECC supplied */ + Fapi_Error_FeatureNotAvailable /* FMC feature is not available on this device */ +} ATTRIBUTE_PACKED Fapi_StatusType; + +/*LDRA_NOANALYSIS*/ +/*LDRA_INSPECTED 42 S MR: 3.5 "Necessary for FMC register definitions" */ +/*LDRA_INSPECTED 74 S MR: 18.4 "Necessary for FMC register definitions" */ +#if defined(_LITTLE_ENDIAN) +typedef union +{ + volatile struct + { +#if defined (_C28X) + uint16_t ChecksumLength:16; /* 0x150 bits 15:0 */ + uint16_t OtpVersion:16; /* 0x150 bits 31:16 */ + uint32_t OtpChecksum; /* 0x154 bits 31:0 */ + uint16_t NumberOfBanks:16; /* 0x158 bits 15:0 */ + uint16_t NumberOfSectors:16; /* 0x158 bits 31:16 */ + uint16_t MemorySize:16; /* 0x15C bits 15:0 */ + uint16_t Package:16; /* 0x15C bits 31:16 */ + uint16_t SiliconRevision:8; /* 0x160 bits 7:0 */ + uint16_t AsicNumber_23_8:8; /* 0x160 bits 31:8 */ + uint16_t AsicNumber_31_24:16; /* 0x160 bits 31:8 */ + uint32_t LotNumber; /* 0x164 bits 31:0 */ + uint16_t WaferNumber:16; /* 0x168 bits 15:0 */ + uint16_t Flowbits:16; /* 0x168 bits 31:16 */ + uint16_t YCoordinate:16; /* 0x16C bits 15:0 */ + uint16_t XCoordinate:16; /* 0x16C bits 31:16 */ + uint16_t EVSU:8; /* 0x170 bits 7:0 */ + uint16_t PVSU:8; /* 0x170 bits 15:8 */ + uint16_t ESU:8; /* 0x170 bits 23:16 */ + uint16_t PSU:8; /* 0x170 bits 31:24 */ + uint16_t CVSU:12; /* 0x174 bits 11:0 */ + uint16_t Add_EXEZSU:4; /* 0x174 bits 15:12 */ + uint16_t PVAcc:8; /* 0x174 bits 23:16 */ + uint16_t RVSU:8; /* 0x174 bits 31:24 */ + uint16_t PVH2:8; /* 0x178 bits 7:0 */ + uint16_t PVH:8; /* 0x178 bits 15:8 */ + uint16_t RH:8; /* 0x178 bits 23:16 */ + uint16_t PH:8; /* 0x178 bits 31:24 */ + uint16_t SmFrequency:12; /* 0x17C bits 11:0 */ + uint16_t VSTAT:4; /* 0x17C bits 15:12 */ + uint16_t Sequence:8; /* 0x17C bits 23:16 */ + uint16_t EH:8; /* 0x17C bits 31:24 */ + uint16_t VHV_EStep:16; /* 0x180 bits 15:0 */ + uint16_t VHV_EStart:16; /* 0x180 bits 31:16 */ + uint16_t MAX_PP:16; /* 0x184 bits 15:0 */ + uint16_t OtpReserved1:16; /* 0x184 bits 31:16 */ + uint16_t PROG_PW:16; /* 0x188 bits 15:0 */ + uint16_t MAX_EP:16; /* 0x188 bits 31:16 */ + uint32_t ERA_PW; /* 0x18C bits 31:0 */ + uint16_t VHV_E:16; /* 0x190 bits 15:0 */ + uint16_t VHV_P:16; /* 0x190 bits 31:16 */ + uint16_t VINH:8; /* 0x194 bits 7:0 */ + uint16_t VCG:8; /* 0x194 bits 15:8 */ + uint16_t VHV_PV:16; /* 0x194 bits 31:16 */ + uint16_t OtpReserved2:8; /* 0x198 bits 7:0 */ + uint16_t VRead:8; /* 0x198 bits 15:8 */ + uint16_t VWL_P:8; /* 0x198 bits 23:16 */ + uint16_t VSL_P:8; /* 0x198 bits 31:24 */ + uint32_t ApiChecksum; /* 0x19C bits 15:0 */ + uint32_t OtpReserved3; /* 0x1A0 bits 31:0 */ + uint32_t OtpReserved4; /* 0x1A4 bits 31:0 */ + uint32_t OtpReserved5; /* 0x1A8 bits 31:0 */ + uint32_t OtpReserved6; /* 0x1AC bits 31:0 */ +#else + uint32_t ChecksumLength:16; /* 0x150 bits 15:0 */ + uint32_t OtpVersion:16; /* 0x150 bits 31:16 */ + uint32_t OtpChecksum; /* 0x154 bits 31:0 */ + uint32_t NumberOfBanks:16; /* 0x158 bits 15:0 */ + uint32_t NumberOfSectors:16; /* 0x158 bits 31:16 */ + uint32_t MemorySize:16; /* 0x15C bits 15:0 */ + uint32_t Package:16; /* 0x15C bits 31:16 */ + uint32_t SiliconRevision:8; /* 0x160 bits 7:0 */ + uint32_t AsicNumber:24; /* 0x160 bits 31:8 */ + uint32_t LotNumber; /* 0x164 bits 31:0 */ + uint32_t WaferNumber:16; /* 0x168 bits 15:0 */ + uint32_t Flowbits:16; /* 0x168 bits 31:16 */ + uint32_t YCoordinate:16; /* 0x16C bits 15:0 */ + uint32_t XCoordinate:16; /* 0x16C bits 31:16 */ + uint32_t EVSU:8; /* 0x170 bits 7:0 */ + uint32_t PVSU:8; /* 0x170 bits 15:8 */ + uint32_t ESU:8; /* 0x170 bits 23:16 */ + uint32_t PSU:8; /* 0x170 bits 31:24 */ + uint32_t CVSU:12; /* 0x174 bits 11:0 */ + uint32_t Add_EXEZSU:4; /* 0x174 bits 15:12 */ + uint32_t PVAcc:8; /* 0x174 bits 23:16 */ + uint32_t RVSU:8; /* 0x174 bits 31:24 */ + uint32_t PVH2:8; /* 0x178 bits 7:0 */ + uint32_t PVH:8; /* 0x178 bits 15:8 */ + uint32_t RH:8; /* 0x178 bits 23:16 */ + uint32_t PH:8; /* 0x178 bits 31:24 */ + uint32_t SmFrequency:12; /* 0x17C bits 11:0 */ + uint32_t VSTAT:4; /* 0x17C bits 15:12 */ + uint32_t Sequence:8; /* 0x17C bits 23:16 */ + uint32_t EH:8; /* 0x17C bits 31:24 */ + uint32_t VHV_EStep:16; /* 0x180 bits 15:0 */ + uint32_t VHV_EStart:16; /* 0x180 bits 31:16 */ + uint32_t MAX_PP:16; /* 0x184 bits 15:0 */ + uint32_t OtpReserved1:16; /* 0x184 bits 31:16 */ + uint32_t PROG_PW:16; /* 0x188 bits 15:0 */ + uint32_t MAX_EP:16; /* 0x188 bits 31:16 */ + uint32_t ERA_PW; /* 0x18C bits 31:0 */ + uint32_t VHV_E:16; /* 0x190 bits 15:0 */ + uint32_t VHV_P:16; /* 0x190 bits 31:16 */ + uint32_t VINH:8; /* 0x194 bits 7:0 */ + uint32_t VCG:8; /* 0x194 bits 15:8 */ + uint32_t VHV_PV:16; /* 0x194 bits 31:16 */ + uint32_t OtpReserved2:8; /* 0x198 bits 7:0 */ + uint32_t VRead:8; /* 0x198 bits 15:8 */ + uint32_t VWL_P:8; /* 0x198 bits 23:16 */ + uint32_t VSL_P:8; /* 0x198 bits 31:24 */ + uint32_t ApiChecksum:32; /* 0x19C bits 31:0 */ + uint32_t OtpReserved3:32; /* 0x1A0 bits 31:0 */ + uint32_t OtpReserved4:32; /* 0x1A4 bits 31:0 */ + uint32_t OtpReserved5:32; /* 0x1A8 bits 31:0 */ + uint32_t OtpReserved6:32; /* 0x1AC bits 31:0 */ +#endif + } OTP_VALUE; + volatile uint8_t au8OtpWord[0x60]; + volatile uint16_t au16OtpWord[0x30]; + volatile uint32_t au32OtpWord[0x18]; +}Fapi_TiOtpBytesType; +#else +typedef union +{ + volatile struct + { + uint32_t OtpVersion:16; /* 0x150 bits 31:16 */ + uint32_t ChecksumLength:16; /* 0x150 bits 15:0 */ + uint32_t OtpChecksum; /* 0x154 bits 31:0 */ + uint32_t NumberOfSectors:16; /* 0x158 bits 31:16 */ + uint32_t NumberOfBanks:16; /* 0x158 bits 15:0 */ + uint32_t Package:16; /* 0x15C bits 31:16 */ + uint32_t MemorySize:16; /* 0x15C bits 15:0 */ + uint32_t AsicNumber:24; /* 0x160 bits 31:8 */ + uint32_t SiliconRevision:8; /* 0x160 bits 7:0 */ + uint32_t LotNumber; /* 0x164 bits 31:0 */ + uint32_t Flowbits:16; /* 0x168 bits 31:16 */ + uint32_t WaferNumber:16; /* 0x168 bits 15:0 */ + uint32_t XCoordinate:16; /* 0x16C bits 31:16 */ + uint32_t YCoordinate:16; /* 0x16C bits 15:0 */ + uint32_t PSU:8; /* 0x170 bits 31:24 */ + uint32_t ESU:8; /* 0x170 bits 23:16 */ + uint32_t PVSU:8; /* 0x170 bits 15:8 */ + uint32_t EVSU:8; /* 0x170 bits 7:0 */ + uint32_t RVSU:8; /* 0x174 bits 31:24 */ + uint32_t PVAcc:8; /* 0x174 bits 23:16 */ + uint32_t Add_EXEZSU:4; /* 0x174 bits 15:12 */ + uint32_t CVSU:12; /* 0x174 bits 11:0 */ + uint32_t PH:8; /* 0x178 bits 31:24 */ + uint32_t RH:8; /* 0x178 bits 23:16 */ + uint32_t PVH:8; /* 0x178 bits 15:8 */ + uint32_t PVH2:8; /* 0x178 bits 7:0 */ + uint32_t EH:8; /* 0x17C bits 31:24 */ + uint32_t Sequence:8; /* 0x17C bits 23:16 */ + uint32_t VSTAT:4; /* 0x17C bits 15:12 */ + uint32_t SmFrequency:12; /* 0x17C bits 11:0 */ + uint32_t VHV_EStart:16; /* 0x180 bits 31:16 */ + uint32_t VHV_EStep:16; /* 0x180 bits 15:0 */ + uint32_t OtpReserved1:16; /* 0x184 bits 31:16 */ + uint32_t MAX_PP:16; /* 0x184 bits 15:0 */ + uint32_t MAX_EP:16; /* 0x188 bits 31:16 */ + uint32_t PROG_PW:16; /* 0x188 bits 15:0 */ + uint32_t ERA_PW; /* 0x18C bits 31:0 */ + uint32_t VHV_P:16; /* 0x190 bits 31:16 */ + uint32_t VHV_E:16; /* 0x190 bits 15:0 */ + uint32_t VHV_PV:16; /* 0x194 bits 31:16 */ + uint32_t VCG:8; /* 0x194 bits 15:8 */ + uint32_t VINH:8; /* 0x194 bits 7:0 */ + uint32_t VSL_P:8; /* 0x198 bits 31:24 */ + uint32_t VWL_P:8; /* 0x198 bits 23:16 */ + uint32_t VRead:8; /* 0x198 bits 15:8 */ + uint32_t OtpReserved2:8; /* 0x198 bits 7:0 */ + uint32_t ApiChecksum:32; /* 0x19C bits 31:0 */ + uint32_t OtpReserved3:32; /* 0x1A0 bits 31:0 */ + uint32_t OtpReserved4:32; /* 0x1A4 bits 31:0 */ + uint32_t OtpReserved5:32; /* 0x1A8 bits 31:0 */ + uint32_t OtpReserved6:32; /* 0x1AC bits 31:0 */ + } OTP_VALUE; + volatile uint8_t au8OtpWord[0x60]; + volatile uint16_t au16OtpWord[0x30]; + volatile uint32_t au32OtpWord[0x18]; +}Fapi_TiOtpBytesType; +#endif +/*LDRA_ANALYSIS*/ + +typedef struct TI_OTP_TYPE +{ + Fapi_TiOtpBytesType aOtpBank[8]; +}Fapi_TiOtpType; + +/*! + \brief +*/ +typedef enum +{ + Alpha_Internal, /* For internal TI use only. Not intended to be used by customers */ + Alpha, /* Early Engineering release. May not be functionally complete */ + Beta_Internal, /* For internal TI use only. Not intended to be used by customers */ + Beta, /* Functionally complete, to be used for testing and validation */ + Production /* Fully validated, functionally complete, ready for production use */ +} ATTRIBUTE_PACKED Fapi_ApiProductionStatusType; + +typedef struct +{ + uint8_t u8ApiMajorVersion; + uint8_t u8ApiMinorVersion; + uint8_t u8ApiRevision; + Fapi_ApiProductionStatusType oApiProductionStatus; + uint32_t u32ApiBuildNumber; + uint8_t u8ApiTechnologyType; + uint8_t u8ApiTechnologyRevision; + uint8_t u8ApiEndianness; + uint32_t u32ApiCompilerVersion; +}Fapi_LibraryInfoType; + +typedef struct +{ +#if defined(_LITTLE_ENDIAN) + uint16_t u16NumberOfBanks; + uint16_t u16Reserved; + uint16_t u16DeviceMemorySize; + uint16_t u16DevicePackage; + uint32_t u32AsicId; + uint32_t u32LotNumber; + uint16_t u16WaferNumber; + uint16_t u16FlowCheck; + uint16_t u16WaferYCoordinate; + uint16_t u16WaferXCoordinate; +#else + uint16_t u16Reserved; + uint16_t u16NumberOfBanks; + uint16_t u16DevicePackage; + uint16_t u16DeviceMemorySize; + uint32_t u32AsicId; + uint32_t u32LotNumber; + uint16_t u16FlowCheck; + uint16_t u16WaferNumber; + uint16_t u16WaferXCoordinate; + uint16_t u16WaferYCoordinate; +#endif +}Fapi_DeviceInfoType; + +typedef struct +{ + Fapi_FlashBankTechType oFlashBankTech; + uint32_t u32NumberOfSectors; + uint32_t u32BankStartAddress; + uint16_t au16SectorSizes[16]; +}Fapi_FlashBankSectorsType; + +#endif /* TYPES_H_*/ + +/********************************************************************************************************************** + * END OF FILE: Types.h + *********************************************************************************************************************/ Index: MessageSupport.c =================================================================== diff -u --- MessageSupport.c (revision 0) +++ MessageSupport.c (revision 6d80d69a210f45c733e5307859351f2cd820a8e7) @@ -0,0 +1,62 @@ +/************************************************************************** +* +* Copyright (c) 2024-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 MessageSupport.c +* +* @author (last) Sean +* @date (last) 30-Jul-2024 +* +* @author (original) Sean +* @date (original) 30-Jul-2024 +* +***************************************************************************/ + +#include +#include "Utilities.h" + +/** + * @addtogroup MessageSupport + * @{ + */ + +// ********** private function prototypes ********** + + +/*********************************************************************//** + * @brief + * The broadcastData function queues a broadcast message for transmission. + * @details Inputs: none + * @details Outputs: broadcast data msg constructed and queued + * @param msgID message ID of the data is broadcast + * @param buffer comm buffer ID + * @param dataPtr pointer to the start of the buffer + * @param length length of the data buffer + * @return TRUE if msg successfully queued for transmit, FALSE if not + *************************************************************************/ +BOOL broadcastData( MSG_ID_T msgID, COMM_BUFFER_T buffer, U08* dataPtr, U32 length ) +{ + BOOL result; + MESSAGE_T msg; + U08 *payloadPtr = msg.payload; + + // create a message record + blankMessage( &msg ); + msg.hdr.msgID = msgID; + msg.hdr.payloadLen = length; + + if ( ( length > 0 ) && ( dataPtr != 0 ) ) + { + memcpy( payloadPtr, dataPtr, length ); + } + + // serialize the message (w/ sync, CRC, and appropriate CAN padding) and add serialized message data to appropriate comm buffer + result = serializeMessage( msg, buffer, ACK_NOT_REQUIRED ); + + return result; +} + +/**@}*/ Index: MessageSupport.h =================================================================== diff -u --- MessageSupport.h (revision 0) +++ MessageSupport.h (revision 6d80d69a210f45c733e5307859351f2cd820a8e7) @@ -0,0 +1,35 @@ +/************************************************************************** +* +* Copyright (c) 2024-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 MessageSupport.h +* +* @author (last) Sean +* @date (last) 30-Jul-2024 +* +* @author (original) Sean +* @date (original) 30-Jul-2024 +* +***************************************************************************/ + +#ifndef __MESSAGESUPPORT_H__ +#define __MESSAGESUPPORT_H__ + +#include "CommBuffers.h" + +/** + * @defgroup MessageSupport MessageSupport + * @brief Provides commonly used function for messaging + * + * @addtogroup MessageSupport + * @{ + */ + +// ********** public function prototypes ********** + +BOOL broadcastData( MSG_ID_T msgID, COMM_BUFFER_T buffer, U08* dataPtr, U32 length ); + +#endif Index: PersistentAlarm.c =================================================================== diff -u --- PersistentAlarm.c (revision 0) +++ PersistentAlarm.c (revision 6d80d69a210f45c733e5307859351f2cd820a8e7) @@ -0,0 +1,410 @@ +/************************************************************************** +* +* Copyright (c) 2024-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 PersistentAlarm.c +* +* @author (last) Sean +* @date (last) 30-Jul-2024 +* +* @author (original) Sean +* @date (original) 30-Jul-2024 +* +***************************************************************************/ + +#include "Common.h" +#include "PersistentAlarm.h" +#include "Timers.h" + +/** + * @addtogroup PersistentAlarm + * @{ + */ + +// ********** private definitions ********** + +#define NUM_OF_FPGA_ALARMS_PER_GROUP 2 ///< Number of FPGA alarms per group. +#define FPGA_READ_ALARM_INDEX 0 ///< FPGA read alarm index number. +#define FPGA_ERROR_ALARM_INDEX 1 ///< FPGA error alarm index number. + +/// FPGA persistent alarm types +typedef enum +{ + FPGA_READ_ERROR = 0, ///< FPGA read error type. + FPGA_ERROR_ERROR, ///< FPGA error error type. + NUM_OF_FPGA_ERROR_TYPES ///< Number of FPGA error types. +} FPGA_ERROR_TYPE_T; + +/// Persistent alarm structure +typedef struct +{ + ALARM_ID_T alarm; ///< Alarm ID. + U32 persistentClearPeriod; ///< Persistent count limit before clear alarm. + U32 persistentTriggerPeriod; ///< Persistent count limit before trigger alarm. + U32 errorClearedStartTime; ///< Error cleared start time. + U32 errorOccurredStartTime; ///< Error occurred start time. + BOOL alarmActive; ///< State of alarm last time alarm checked. +} PERSISTENT_ALARM_DATA_T; + +/// FPGA persistent alarm data structure +typedef struct +{ + U32 fpagErrorClearedStartTime; ///< FPGA error cleared start time. + U32 fpgaErrorOccurredStartTime; ///< FPGA error occurred start time. + U32 fpgaPreviousCount; ///< FPGA previous read count. + BOOL fpgaIsConditionClear; ///< FPGA is persistent condition clear. +} FPGA_ALARM_DATA_T; + +/// FPGA persistent alarm structure +typedef struct +{ + ALARM_ID_T fpgaAlarm; ///< FPGA read alarm. + U32 fpgaPersistentClearPeriod; ///< FPGA persistent count limit before clear alarm. + U32 fpgaPersistentTriggerPeriod; ///< FPGA persistent count limit before trigger alarm. + FPGA_ALARM_DATA_T fpgaAlarmData[ NUM_OF_FPGA_ERROR_TYPES ]; ///< FPGA persistent alarm data. +} FPGA_PERSISTENT_ALARM_GROUP_T; + +// ********** private data ********** + +static PERSISTENT_ALARM_DATA_T persistentAlarms[ NUM_OF_ALARM_IDS ]; ///< Array of persistent alarm structure. +static FPGA_PERSISTENT_ALARM_GROUP_T fpgaPersistentAlarmGroup[ NUM_OF_FPGA_SENSOR_GROUPS ]; ///< FPGA persistent alarm group. + +// ********** private function prototypes ********** + +static BOOL isFPGAPersistentAlarmTriggered( FPGA_PERSISTENT_ALARM_GROUP_T* alarmGroup, U32 fpgaCount, FPGA_ERROR_TYPE_T errorType ); + +/*********************************************************************//** + * @brief + * The initPersistentAlarm function initializes the PersistentAlarm module + * when the alarm count lower than maximum persistent alarm allowed. + * @details Inputs: none + * @details Outputs: PersistentAlarm module initialized + * @param alarmId Alarm id + * @param persistentClearPeriod Persistent period limit before clear alarm (in ms) + * @param persistentTriggerPeriod Persistent period limit before trigger alarm (in ms) + * @return none + *************************************************************************/ +void initPersistentAlarm( ALARM_ID_T alarmId, U32 persistentClearPeriod, U32 persistentTriggerPeriod ) +{ + if ( alarmId < NUM_OF_ALARM_IDS ) + { + persistentAlarms[ alarmId ].persistentClearPeriod = persistentClearPeriod; + persistentAlarms[ alarmId ].persistentTriggerPeriod = persistentTriggerPeriod; + persistentAlarms[ alarmId ].errorClearedStartTime = 0U; + persistentAlarms[ alarmId ].errorOccurredStartTime = 0U; + persistentAlarms[ alarmId ].alarmActive = FALSE; + } + else + { +#ifdef _DD_ +// SET_ALARM_WITH_2_U32_DATA( ALARM_ID_DD_SOFTWARE_FAULT, SW_FAULT_ID_PERSISTENT_ALARM_INVALID_INDEX, alarmId ); +#else +// SET_ALARM_WITH_2_U32_DATA( ALARM_ID_TD_SOFTWARE_FAULT, SW_FAULT_ID_PERSISTENT_ALARM_INVALID_INDEX, alarmId ); +#endif + } +} + +/*********************************************************************//** + * @brief + * The initFPGAPersistentAlarm function initializes the FPGA persistent alarm + * when the alarm count lower than maximum persistent alarm allowed and the FPGA + * sensor group is less than the maximum allowed sensor group. + * @details Inputs: none + * @details Outputs: fpgaPersistentAlarmGroup + * @param group which is the FPGA persistent alarm group + * @param alarmId Alarm id + * @param persistentClearPeriod Persistent period limit before clear alarm (in ms) + * @param persistentTriggerPeriod Persistent period limit before trigger alarm (in ms) + * @return none + *************************************************************************/ +void initFPGAPersistentAlarm( FPGA_PERSISTENT_ALARMS_GROUP_T group, ALARM_ID_T alarmIndex, U32 persistentClearPeriod, U32 persistentTriggerPeriod ) +{ +// if ( ( group < NUM_OF_FPGA_SENSOR_GROUPS ) && ( alarmIndex < NUM_OF_ALARM_IDS ) ) +// { +// fpgaPersistentAlarmGroup[ group ].fpgaAlarm = alarmIndex; +// fpgaPersistentAlarmGroup[ group ].fpgaPersistentClearPeriod = persistentClearPeriod; +// fpgaPersistentAlarmGroup[ group ].fpgaPersistentTriggerPeriod = persistentTriggerPeriod; +// +// fpgaPersistentAlarmGroup[ group ].fpgaAlarmData[ FPGA_READ_ALARM_INDEX ].fpgaIsConditionClear = TRUE; +// fpgaPersistentAlarmGroup[ group ].fpgaAlarmData[ FPGA_READ_ALARM_INDEX ].fpagErrorClearedStartTime = 0; +// fpgaPersistentAlarmGroup[ group ].fpgaAlarmData[ FPGA_READ_ALARM_INDEX ].fpgaErrorOccurredStartTime = 0; +// fpgaPersistentAlarmGroup[ group ].fpgaAlarmData[ FPGA_READ_ALARM_INDEX ].fpgaPreviousCount = 0; +// +// fpgaPersistentAlarmGroup[ group ].fpgaAlarmData[ FPGA_ERROR_ALARM_INDEX ].fpgaIsConditionClear = TRUE; +// fpgaPersistentAlarmGroup[ group ].fpgaAlarmData[ FPGA_ERROR_ALARM_INDEX ].fpagErrorClearedStartTime = 0; +// fpgaPersistentAlarmGroup[ group ].fpgaAlarmData[ FPGA_ERROR_ALARM_INDEX ].fpgaErrorOccurredStartTime = 0; +// fpgaPersistentAlarmGroup[ group ].fpgaAlarmData[ FPGA_ERROR_ALARM_INDEX ].fpgaPreviousCount = 0; +// } +} + +/*********************************************************************//** + * @brief + * The isPersistentAlarmTriggered function checks if the error condition has + * persisted for given time limit. + * @details Inputs: persistentAlarms[] + * @details Outputs: none + * @param alarmId Alarm id + * @param isErrorOccurred Flag indicates error condition is occurring or not + * @return TRUE if error condition persisted over given time limit, FALSE if not + *************************************************************************/ +BOOL isPersistentAlarmTriggered( ALARM_ID_T alarmId, BOOL const isErrorOccurred ) +{ + BOOL isAlarmTriggered = FALSE; + + if ( alarmId < NUM_OF_ALARM_IDS ) + { + BOOL alarmIsActive = isAlarmActive( alarmId ); + + // Reset persistence if alarm was just cleared + if ( ( FALSE == alarmIsActive ) && ( TRUE == persistentAlarms[ alarmId ].alarmActive ) ) + { + persistentAlarms[ alarmId ].errorOccurredStartTime = 0; + } + persistentAlarms[ alarmId ].alarmActive = alarmIsActive; // remember latest alarm state for next time + + // Update start time when error occurs for the first time + if ( ( TRUE == isErrorOccurred ) && ( 0 == persistentAlarms[ alarmId ].errorOccurredStartTime ) ) + { + persistentAlarms[ alarmId ].errorOccurredStartTime = getMSTimerCount(); + } + + if ( TRUE == isErrorOccurred ) + { + isAlarmTriggered = didTimeout( persistentAlarms[ alarmId ].errorOccurredStartTime, persistentAlarms[ alarmId ].persistentTriggerPeriod ); + } + else + { + persistentAlarms[ alarmId ].errorOccurredStartTime = 0; + } + } + else + { +#ifdef _DD_ +// SET_ALARM_WITH_2_U32_DATA( ALARM_ID_DD_SOFTWARE_FAULT, SW_FAULT_ID_PERSISTENT_ALARM_INVALID_INDEX, alarmId ); +#else +// SET_ALARM_WITH_2_U32_DATA( ALARM_ID_TD_SOFTWARE_FAULT, SW_FAULT_ID_PERSISTENT_ALARM_INVALID_INDEX, alarmId ); +#endif + } + + return isAlarmTriggered; +} + +/*********************************************************************//** + * @brief + * The isPersistentAlarmConditionCleared function checks if the error condition has + * been cleared for given time limit. + * @details Inputs: persistentAlarms[] + * @details Outputs: none + * @param alarmId Alarm id + * @param isErrorOccurred Flag indicates error condition is occurring or not + * @return TRUE if error condition has been cleared over given time limit, FALSE if not + *************************************************************************/ +BOOL isPersistentAlarmConditionCleared( ALARM_ID_T alarmId, BOOL const isErrorOccurred ) +{ + BOOL isErrorConditionCleared = FALSE; + + if ( alarmId < NUM_OF_ALARM_IDS ) + { + // Update start time when error condition clears for the first time + if ( ( FALSE == isErrorOccurred ) && ( 0 == persistentAlarms[ alarmId ].errorClearedStartTime ) ) + { + persistentAlarms[ alarmId ].errorClearedStartTime = getMSTimerCount(); + } + + if ( FALSE == isErrorOccurred ) + { + isErrorConditionCleared = didTimeout( persistentAlarms[ alarmId ].errorClearedStartTime, persistentAlarms[ alarmId ].persistentClearPeriod ); + } + else + { + persistentAlarms[ alarmId ].errorClearedStartTime = 0; + } + } + else + { +#ifdef _DD_ +// SET_ALARM_WITH_2_U32_DATA( ALARM_ID_DD_SOFTWARE_FAULT, SW_FAULT_ID_PERSISTENT_ALARM_INVALID_INDEX, alarmId ) +#endif +#ifdef _TD_ +// SET_ALARM_WITH_2_U32_DATA( ALARM_ID_TD_SOFTWARE_FAULT, SW_FAULT_ID_PERSISTENT_ALARM_INVALID_INDEX, alarmId ) +#endif + } + + return isErrorConditionCleared; +} + +/*********************************************************************//** + * @brief + * The checkPersistentAlarm function triggers/clears an alarm if an alarm condition + * has persisted/cleared over given time limit. + * @details Inputs: none + * @details Outputs: checks whether an alarm is triggered or an alarm condition is cleared + * @param alarmID ID of alarm to check + * @param isErrorOccured Flag indicates alarm condition is active or not + * @param data alarm data + * @param limit alarm condition limit + * @return TRUE if given alarm is active, FALSE if not + *************************************************************************/ +BOOL checkPersistentAlarm( ALARM_ID_T alarm, BOOL isErrorOccured, F32 data, F32 limit ) +{ + BOOL status = FALSE; + + if ( TRUE == isPersistentAlarmTriggered( alarm, isErrorOccured ) ) + { + SET_ALARM_WITH_2_F32_DATA( alarm, data, limit ); + } + + if ( TRUE == isPersistentAlarmConditionCleared( alarm, isErrorOccured ) ) + { + clearAlarmCondition( alarm ); + status = TRUE; + } + + return status; +} + +/*********************************************************************//** + * @brief + * The resetPersistentAlarmTimer function resets the start time for error + * condition clear start time and error start time. + * @details Inputs: none + * @details Outputs: reset condition clear start time and error occur start time + * @param alarmId Alarm id of the alarm to reset timer + * @return none + *************************************************************************/ +void resetPersistentAlarmTimer( ALARM_ID_T alarmId ) +{ + persistentAlarms[ alarmId ].errorOccurredStartTime = 0; + persistentAlarms[ alarmId ].errorClearedStartTime = 0; +} + +/*********************************************************************//** + * @brief + * The checkFPGAPersistentAlarms function checks the FPGA persistent alarm + * status of the provided FPGA persistent alarm group. + * @details Inputs: fpgaPersistentAlarmGroup + * @details Outputs: fpgaPersistentAlarmGroup + * @param alarmGroup which is the alarm group of the persistent alarm + * (i.e. 2-wire temperature sensor) + * @param readCount which is the FPGA read count of the sensor group + * @return none + *************************************************************************/ +void checkFPGAPersistentAlarms( FPGA_PERSISTENT_ALARMS_GROUP_T group, U32 readCount ) +{ + if ( group < NUM_OF_FPGA_SENSOR_GROUPS ) + { + FPGA_ERROR_TYPE_T type = FPGA_READ_ERROR; + BOOL isReadPersTrgrd = isFPGAPersistentAlarmTriggered( &fpgaPersistentAlarmGroup[ group ], readCount, type ); + + if ( TRUE == isReadPersTrgrd ) + { + SET_ALARM_WITH_2_U32_DATA( fpgaPersistentAlarmGroup[ group ].fpgaAlarm, type, group ) + } + } + else + { +#ifdef _DD_ +// SET_ALARM_WITH_2_U32_DATA( ALARM_ID_DD_SOFTWARE_FAULT, SW_FAULT_ID_INVALID_FPGA_SENSOR_GROUP_SELECTED, (U32)group ) +#endif +#ifdef _TD_ +// SET_ALARM_WITH_2_U32_DATA( ALARM_ID_TD_SOFTWARE_FAULT, SW_FAULT_ID_INVALID_FPGA_SENSOR_GROUP_SELECTED, (U32)group ) +#endif + } +} + +/*********************************************************************//** + * @brief + * The checkFPGAPersistentErrorCountAlarm function checks the FPGA persistent + * error count alarm status of the provided FPGA persistent alarm group. + * @details Inputs: fpgaPersistentAlarmGroup + * @details Outputs: none + * @param alarmGroup which is the alarm group of the persistent alarm + * (i.e. 2-wire temperature sensor) + * @param errorCount which is the FPGA error count of the sensor group + * @return none + *************************************************************************/ +void checkFPGAPersistentErrorCountAlarm( FPGA_PERSISTENT_ALARMS_GROUP_T group, U32 errorCount ) +{ + if ( group < NUM_OF_FPGA_SENSOR_GROUPS ) + { + BOOL isErrorPersTrgrd = isFPGAPersistentAlarmTriggered( &fpgaPersistentAlarmGroup[ group ], errorCount, FPGA_ERROR_ERROR ); + + if ( TRUE == isErrorPersTrgrd ) + { + SET_ALARM_WITH_2_U32_DATA( fpgaPersistentAlarmGroup[ group ].fpgaAlarm, FPGA_ERROR_ERROR, group ) + } + } + else + { +#ifdef _DD_ +// SET_ALARM_WITH_2_U32_DATA( ALARM_ID_DD_SOFTWARE_FAULT, SW_FAULT_ID_INVALID_FPGA_SENSOR_GROUP_SELECTED, (U32)group ) +#endif +#ifdef _TD_ +// SET_ALARM_WITH_2_U32_DATA( ALARM_ID_TD_SOFTWARE_FAULT, SW_FAULT_ID_INVALID_FPGA_SENSOR_GROUP_SELECTED, (U32)group ) +#endif + } +} + +/*********************************************************************//** + * @brief + * The isFPGAPersistentAlarmTriggered function checks whether persistent alarm + * has been triggered or not. + * @details Inputs: alarmGroup + * @details Outputs: alarmGroup + * @param alarmGroup which is the alarm group of the persistent alarm + * (i.e. 2-wire temperature sensor) + * @param fpgaCount which is the FPGA count of the sensor group + * @param errorType which is the FPGA error type (i.e. read or error count) + * @return TRUE if the persistent alarm is triggered otherwise, FALSE + *************************************************************************/ +static BOOL isFPGAPersistentAlarmTriggered( FPGA_PERSISTENT_ALARM_GROUP_T* alarmGroup, U32 fpgaCount, FPGA_ERROR_TYPE_T errorType ) +{ + BOOL isPersistentTriggered = FALSE; + BOOL hasErrorOccured = FALSE; + + switch ( errorType ) + { + case FPGA_READ_ERROR: + hasErrorOccured = ( fpgaCount == alarmGroup->fpgaAlarmData[ errorType ].fpgaPreviousCount ? TRUE : FALSE ); + break; + + case FPGA_ERROR_ERROR: + hasErrorOccured = ( alarmGroup->fpgaAlarmData[ errorType ].fpgaPreviousCount != fpgaCount ? TRUE : FALSE ); + break; + + default: +#ifdef _DD_ +// SET_ALARM_WITH_2_U32_DATA( ALARM_ID_DD_SOFTWARE_FAULT, SW_FAULT_ID_INVALID_FPGA_ERROR_GROUP_SELECTED, errorType ) +#endif +#ifdef _TD_ +// SET_ALARM_WITH_2_U32_DATA( ALARM_ID_TD_SOFTWARE_FAULT, SW_FAULT_ID_INVALID_FPGA_ERROR_GROUP_SELECTED, errorType ) +#endif + break; + } + + if ( TRUE == hasErrorOccured ) + { + if ( TRUE == alarmGroup->fpgaAlarmData[ errorType ].fpgaIsConditionClear ) + { + alarmGroup->fpgaAlarmData[ errorType ].fpgaIsConditionClear = FALSE; + alarmGroup->fpgaAlarmData[ errorType ].fpgaErrorOccurredStartTime = getMSTimerCount(); + } + else if ( TRUE == didTimeout( alarmGroup->fpgaAlarmData[ errorType ].fpgaErrorOccurredStartTime, alarmGroup->fpgaPersistentTriggerPeriod ) ) + { + isPersistentTriggered = TRUE; + } + } + else + { + alarmGroup->fpgaAlarmData[ errorType ].fpgaIsConditionClear = TRUE; + } + + alarmGroup->fpgaAlarmData[ errorType ].fpgaPreviousCount = fpgaCount; + + return isPersistentTriggered; +} + +/**@}*/ Index: PersistentAlarm.h =================================================================== diff -u --- PersistentAlarm.h (revision 0) +++ PersistentAlarm.h (revision 6d80d69a210f45c733e5307859351f2cd820a8e7) @@ -0,0 +1,81 @@ +/************************************************************************** +* +* Copyright (c) 2024-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 PersistentAlarm.h +* +* @author (last) Sean +* @date (last) 30-Jul-2024 +* +* @author (original) Sean +* @date (original) 30-Jul-2024 +* +***************************************************************************/ + +#ifndef __PERSISTENTALARM_H__ +#define __PERSISTENTALARM_H__ + +#include "Common.h" + +/** + * @defgroup PersistentAlarm PersistentAlarm + * @brief Persistent alarm monitor module. + * Check for persistent error and return indication on whether alarm is triggered or alarm condition is cleared. + * + * @addtogroup PersistentAlarm + * @{ + */ + +// ********** public definitions ********** + +#ifdef _DD_ +/// FPGA persistent alarm groups data structure +typedef enum +{ + FPGA_PERS_ERROR_TWO_WIRE_ADC_TEMP_SENSORS = 0, ///< Two wire ADC temperature sensors. + FPGA_PERS_ERROR_THD_ADC_TEMP_SENSORS, ///< THd ADC temperature sensors. + FPGA_PERS_ERROR_TDI_ADC_TEMP_SENSORS, ///< TDi ADC temperature sensors. + FPGA_PERS_ERROR_TRO_ADC_TEMP_SENSORS, ///< TRo ADC temperature sensors. + FPGA_PERS_ERROR_CPI_CPO_COND_SENSORS, ///< CPi/CPo conductivity sensors. + FPGA_PERS_ERROR_CD1_CD2_COND_SENSORS, ///< CD1/CD2 conductivity sensors. + FPGA_PERS_ERROR_BARO_SENSOR, ///< Barometric sensor. + FPGA_PERS_ERROR_LOAD_CELL_A1_B1_SENSORS, ///< Load cell A1/B1 sensors. + FPGA_PERS_ERROR_LOAD_CELL_A2_B2_SENSORS, ///< Load cell A2/B2 sensors. + FPGA_PERS_ERROR_MAIN_PRIMARY_HEATER_VOLTAGE_ADC, ///< Main primary heater voltage ADC. + NUM_OF_FPGA_SENSOR_GROUPS ///< Number of FPGA sensor groups. +} FPGA_PERSISTENT_ALARMS_GROUP_T; +#endif + +#ifdef _TD_ +/// FPGA persistent alarm groups data structure +typedef enum +{ + FPGA_PERS_ERROR_OCCLUSION_PRESSURE_SENSOR = 0, ///< FPGA persistent error occlusion pressure sensor. + FPGA_PERS_ERROR_ARTERIAL_PRESSURE_SENSOR, ///< FPGA persistent error arterial pressure sensor. + FPGA_PERS_ERROR_VENOUS_PRESSURE_SESNOR, ///< FPGA persistent error venous pressure sensor. + FPGA_PERS_ERROR_SYRINGE_PUMP_ADC, ///< FPGA persistent error syringe pump ADC. + NUM_OF_FPGA_SENSOR_GROUPS ///< Number of FPGA sensor groups. +} FPGA_PERSISTENT_ALARMS_GROUP_T; +#endif + +// ********** public function prototypes ********** + +// Persistent period resolution is in ms +void initPersistentAlarm( ALARM_ID_T alarmIndex, U32 persistentClearPeriod, U32 persistentTriggerPeriod ); + +void initFPGAPersistentAlarm( FPGA_PERSISTENT_ALARMS_GROUP_T group, ALARM_ID_T alarmIndex, U32 persistentClearPeriod, U32 persistentTriggerPeriod ); + +BOOL isPersistentAlarmTriggered( ALARM_ID_T alarmIndex, BOOL const isErrorOccurred ); +BOOL isPersistentAlarmConditionCleared( ALARM_ID_T alarmIndex, BOOL const isErrorOccurred ); +BOOL checkPersistentAlarm( ALARM_ID_T alarm, BOOL isErrorOccured, F32 data, F32 limit ); +void resetPersistentAlarmTimer( ALARM_ID_T alarmId ); + +void checkFPGAPersistentAlarms( FPGA_PERSISTENT_ALARMS_GROUP_T group, U32 readCount ); +void checkFPGAPersistentErrorCountAlarm( FPGA_PERSISTENT_ALARMS_GROUP_T group, U32 errorCount ); + +/**@}*/ + +#endif Index: SystemComm.c =================================================================== diff -u --- SystemComm.c (revision 0) +++ SystemComm.c (revision 6d80d69a210f45c733e5307859351f2cd820a8e7) @@ -0,0 +1,787 @@ +/************************************************************************** +* +* Copyright (c) 2024-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 SystemComm.c +* +* @author (last) Sean +* @date (last) 30-Jul-2024 +* +* @author (original) Sean +* @date (original) 30-Jul-2024 +* +***************************************************************************/ + +#include +#include // For memcpy() + +#include "can.h" +#include "sci.h" +#include "sys_dma.h" + +#include "Comm.h" +#include "Interrupts.h" +#include "OperationModes.h" +#include "SystemComm.h" +#ifdef _TD_ +#include "SystemCommTD.h" +#endif +#ifdef _DD_ +#include "SystemCommDD.h" +#endif +#ifdef _RO_ +#include "SystemCommRO.h" +#endif +#include "Timers.h" +#include "Utilities.h" + +/** + * @addtogroup SystemComm + * @{ + */ + +// ********** private definitions ********** + +#define CAN_XMIT_PACKET_TIMEOUT_MS 200 ///< If transmitted CAN frame does not cause a transmit complete interrupt within this time, re-send or move on +#define MAX_XMIT_RETRIES 5 ///< Maximum number of retries on no transmit complete interrupt timeout + +#define MSG_NOT_ACKED_TIMEOUT_MS 250 ///< Maximum time for a Denali message that requires ACK to be ACK'd + +#define MSG_NOT_ACKED_MAX_RETRIES 10 ///< Maximum number of times a message that requires ACK that was not ACK'd can be re-sent before alarm +#define PENDING_ACK_LIST_SIZE 25 ///< Maximum number of Denali messages that can be pending ACK at any given time + +#define PENDING_ACK_LIST_OVERRIDE_UI_CHANNEL 1 ///< Value for determining UI channel when Pending ACKs are overriden. +#define PENDING_ACK_LIST_OVERRIDE_DG_CHANNEL 2 ///< Value for determining DG channel when Pending ACKs are overriden. + +#pragma pack(push, 1) + +/// Record for transmitted message that is pending acknowledgment from receiver. +typedef struct +{ + BOOL used; ///< Used. + U16 seqNo; ///< Message sequence number. + U16 retries; ///< Number of retries. + U32 timeStamp; ///< Time stamp. + COMM_BUFFER_T channel; ///< Channel ID. + U32 msgSize; ///< Message size. + U08 msg[ MAX_ACK_MSG_SIZE ]; ///< Message. +} PENDING_ACK_RECORD_T; + +#pragma pack(pop) + +// ********** private data ********** + +static U08 lastCANPacketSent[ CAN_MESSAGE_PAYLOAD_SIZE ]; ///< Keep last packet sent on CAN bus in case we need to re-send. +static CAN_MESSAGE_BOX_T lastCANPacketSentChannel = (CAN_MESSAGE_BOX_T)0; ///< Keep channel last packet was sent on CAN bus in case we need to re-send. +static U32 lastCANPacketSentTimeStamp = 0; ///< Keep time last packet sent on CAN bus so we can timeout on transmission attempt. +static U32 canXmitRetryCtr = 0; ///< Counter for CAN transmit retries. + +static volatile PENDING_ACK_RECORD_T pendingAckList[ PENDING_ACK_LIST_SIZE ]; ///< List of outgoing messages that are awaiting an ACK +static OVERRIDE_U32_T pendingACKOverride = { 0, 0, 0, 0 }; ///< Pending ACK override data structure. + +// ********** private function prototypes ********** + +static COMM_BUFFER_T findNextHighestPriorityCANPacketToTransmit( void ); +static U32 transmitNextCANPacket( void ); + +static void processIncomingData( void ); +static S32 parseMessageFromBuffer( U08 *data, U32 len ); +static void consumeBufferPaddingBeforeSync( COMM_BUFFER_T buffer ); +static void processReceivedMessages( void ); + +static void checkTooManyBadMsgCRCs( void ); + +static BOOL matchACKtoPendingACKList( S16 seqNo ); +static void checkPendingACKList( void ); + +/*********************************************************************//** + * @brief + * The initSystemComm function initializes the SystemComm module. + * @details Inputs: none + * @details Outputs: SystemComm module initialized. + * @return none + *************************************************************************/ +void initSystemComm( void ) +{ + U32 i; + + // Initialize pending ACK list + for ( i = 0; i < PENDING_ACK_LIST_SIZE; i++ ) + { + pendingAckList[ i ].used = FALSE; + } +} + +/*********************************************************************//** + * @brief + * The execSystemCommRx function manages received data from other sub-systems. + * @details Inputs: none + * @details Outputs: Incoming messages parsed and processed. + * @return none + *************************************************************************/ +void execSystemCommRx( void ) +{ + // Parse messages from comm buffers and queue them + processIncomingData(); + + // Process received messages in the queue + processReceivedMessages(); + + // Check for sub-system comm timeouts + checkForCommTimeouts(); + + // Check ACK list for messages that need to be re-sent because they have not been ACK'd + checkPendingACKList(); + + if ( TRUE == hasDialinCheckInExpired() ) + { + // It has been a while since the user logged in but not activity has been received from Dialin so set the tester's status to log out + setTesterStatusToLoggedOut(); + } +} + +/*********************************************************************//** + * @brief + * The execSystemCommTx function manages data to be transmitted to other + * sub-systems. + * @details Inputs: none + * @details Outputs: Outgoing messages transmitted. + * @return none + *************************************************************************/ +void execSystemCommTx( void ) +{ + // Do not transmit if no other nodes on CAN bus + if ( FALSE == isOnlyCANNode() ) + { + // If CAN transmitter is idle, start transmitting any pending packets + if ( FALSE == isCAN1TransmitInProgress() ) + { + transmitNextCANPacket(); + } + else + { + // Generally, transmitter should not be busy at time of this function call - check timeout just in case so we do not get stuck waiting forever + if ( TRUE == didTimeout( lastCANPacketSentTimeStamp, CAN_XMIT_PACKET_TIMEOUT_MS ) ) + { + // Assume last packet was not successfully transmitted. Re-send last packet. + if ( ++canXmitRetryCtr <= MAX_XMIT_RETRIES ) + { + // Ensure we have a previous CAN packet/channel to resend - canTransmit() channel param MUST be valid + if ( ( lastCANPacketSentChannel > COMM_BUFFER_NOT_USED ) && ( lastCANPacketSentChannel < NUM_OF_COMM_BUFFERS ) ) + { + canTransmit( canREG1, lastCANPacketSentChannel, lastCANPacketSent ); + } + } + // We must be only node on CAN bus - nobody is ACKing our transmitted frames + else + { + setOnlyCANNode( TRUE ); // Set only CAN node flag + canXmitRetryCtr = MAX_XMIT_RETRIES; + signalCANXmitsCompleted(); // Clear pending xmit flag + clearCANXmitBuffers(); // Clear xmit buffers - nothing is going out right now + } // end - are we retrying xmit or are we alone on CAN bus + } // end - pending xmit timeout? + } // end - transmit in progress or not + } // end - DG not alone on CAN bus +} + +/*********************************************************************//** + * @brief + * The handleCANMsgInterrupt function handles a CAN message interrupt. + * This may have occurred because a CAN packet transmission has completed + * or because a CAN packet has been received. The appropriate handler is + * called. + * @details Inputs: none + * @details Outputs: message interrupt handled + * @param srcCANBox which CAN message box triggered this interrupt + * @return none + *************************************************************************/ +void handleCANMsgInterrupt( CAN_MESSAGE_BOX_T srcCANBox ) +{ + // Message interrupt is for a transmit message box? + if ( TRUE == isCANBoxForXmit( srcCANBox ) ) + { + U32 bytesXmitted; + + bytesXmitted = transmitNextCANPacket(); + + // If nothing more to send, signal that transmitter is available + if ( 0 == bytesXmitted ) + { + signalCANXmitsCompleted(); + } + } + else if ( TRUE == isCANBoxForRecv( srcCANBox ) ) + { + U08 data[ CAN_MESSAGE_PAYLOAD_SIZE ]; + + // Get CAN packet received on given CAN message box + if ( FALSE != canIsRxMessageArrived( canREG1, srcCANBox ) ) + { + U32 result = canGetData( canREG1, srcCANBox, data ); + + // If packet retrieved, add to buffer + if ( result != 0 ) + { + // Add CAN packet to appropriate comm buffer based on the message box it came in on (s/b same #) + addToCommBuffer( srcCANBox, data, CAN_MESSAGE_PAYLOAD_SIZE ); + } + } + } + else + { + // Should not get here - not an active message box +// SET_ALARM_WITH_2_U32_DATA( ALARM_ID_TD_SOFTWARE_FAULT, SW_FAULT_ID_INVALID_CAN_MESSAGE_BOX, srcCANBox ) + } +} + +/*********************************************************************//** + * @brief + * The isCANBoxForXmit function determines whether a given CAN message box + * is configured for transmit. + * @details Inputs: CAN_OUT_BUFFERS[] + * @details Outputs: none + * @param srcCANBox which CAN message box to check + * @return TRUE if the given CAN message box is configured for transmit, FALSE if not. + *************************************************************************/ +BOOL isCANBoxForXmit( CAN_MESSAGE_BOX_T srcCANBox ) +{ + BOOL result = FALSE; + U32 i; + + for ( i = 0; i < NUM_OF_CAN_OUT_BUFFERS; i++ ) + { + if ( getOutBufferID( i ) == srcCANBox ) + { + result = TRUE; + break; + } + } + + return result; +} + +/*********************************************************************//** + * @brief + * The isCANBoxForRecv function determines whether a given CAN message box + * is configured for receiving. + * @details Inputs: CAN_IN_BUFFERS[] + * @details Outputs: none + * @param srcCANBox which CAN message box to check + * @return TRUE if the given CAN message box is configured for receiving, FALSE if not. + *************************************************************************/ +BOOL isCANBoxForRecv( CAN_MESSAGE_BOX_T srcCANBox ) +{ + BOOL result = FALSE; + U32 i; + + for ( i = 0; i < NUM_OF_CAN_IN_BUFFERS; i++ ) + { + if ( getInBufferID( i ) == srcCANBox ) + { + result = TRUE; + break; + } + } + + return result; +} + + +/************************************************************************* +********************** TRANSMIT SUPPORT FUNCTIONS ************************ +*************************************************************************/ + + +/*********************************************************************//** + * @brief + * The findNextHighestPriorityCANPacketToTransmit function gets the next + * 8 byte packet and initiates a CAN transmit on the appropriate CAN channel. + * @details Inputs: Output CAN Comm Buffer(s) + * @details Outputs: none + * @return buffer with highest priority CAN packet to transmit, + * COMM_BUFFER_NOT_USED if not CAN packets pending transmit found + *************************************************************************/ +static COMM_BUFFER_T findNextHighestPriorityCANPacketToTransmit( void ) +{ + COMM_BUFFER_T result = COMM_BUFFER_NOT_USED; + U32 i; + + // Search for next priority CAN packet to transmit + for ( i = 0; i < NUM_OF_CAN_OUT_BUFFERS; i++ ) + { + if ( numberOfBytesInCommBuffer( getOutBufferID( i ) ) >= CAN_MESSAGE_PAYLOAD_SIZE ) + { + result = getOutBufferID( i ); + break; // Found highest priority packet to transmit - we are done + } + } + + return result; +} + +/*********************************************************************//** + * @brief + * The transmitNextCANPacket function gets the next 8 byte packet and initiates + * a CAN transmit on the appropriate CAN channel. + * @details Inputs: Output CAN Comm Buffers + * @details Outputs: CAN packet transmit initiated. + * @return number of bytes transmitted + *************************************************************************/ +static U32 transmitNextCANPacket( void ) +{ + U32 result = 0; + COMM_BUFFER_T buffer = findNextHighestPriorityCANPacketToTransmit(); + + // If a buffer is found with a packet to transmit, get packet from buffer and transmit it + if ( buffer != COMM_BUFFER_NOT_USED ) + { + U08 data[ CAN_MESSAGE_PAYLOAD_SIZE ]; + U32 dataSize = getFromCommBuffer( buffer, data, CAN_MESSAGE_PAYLOAD_SIZE ); + CAN_MESSAGE_BOX_T mBox = buffer; // CAN message boxes and comm buffers are aligned + + // If there is another CAN packet to send, send it + if ( dataSize == CAN_MESSAGE_PAYLOAD_SIZE ) + { + // We are transmitting another packet - signal transmitter is busy + signalCANXmitsInitiated(); + // Remember packet data being transmitted here in case transmission fails and we need to re-send + memcpy( lastCANPacketSent, data, CAN_MESSAGE_PAYLOAD_SIZE ); + lastCANPacketSentChannel = mBox; + lastCANPacketSentTimeStamp = getMSTimerCount(); + if ( 0 != canTransmit( canREG1, mBox, data ) ) + { + result = CAN_MESSAGE_PAYLOAD_SIZE; + } + else + { + signalCANXmitsCompleted(); +// SET_ALARM_WITH_2_U32_DATA( ALARM_ID_TD_SOFTWARE_FAULT, SW_FAULT_ID_SYSTEM_CMMM_CAN_TRANSMIT_REJECTED, (U32)mBox ) + } + } + else + { +// SET_ALARM_WITH_2_U32_DATA( ALARM_ID_TD_SOFTWARE_FAULT, SW_FAULT_ID_SYSTEM_COMM_INVALID_FRAME_SIZE, ((U32)buffer << 16) | dataSize ) + } + } + + return result; +} + + +/************************************************************************* +********************** RECEIVE SUPPORT FUNCTIONS ************************* +*************************************************************************/ + + +/*********************************************************************//** + * @brief + * The processIncomingData function parses out messages from the Input + * Comm Buffers and adds them to the Received Message Queue. + * @details Inputs: none + * @details Outputs: rcvMsg, dgIsCommunicating, + * timeOfLastDGCheckIn, timeOfLastUICheckIn, uiDidCommunicate + * @return none + *************************************************************************/ +static void processIncomingData( void ) +{ + U08 data[ 512 ]; // Message work space + U32 i; + BOOL badCRCDetected = FALSE; + + // Queue any received messages + for ( i = 0; i < NUM_OF_CAN_IN_BUFFERS; i++ ) + { + BOOL messagesInBuffer = TRUE; // Assume true at first to get into while loop + + while ( TRUE == messagesInBuffer ) + { + U32 numOfBytesInBuffer; + + // Assume false so we do not get stuck in loop. Set to true only if we find another complete message in buffer + messagesInBuffer = FALSE; + + // Since messages can have 8-byte alignment padding left unconsumed by last get, get padding out of buffer + consumeBufferPaddingBeforeSync( getInBufferID( i ) ); + // Do we have enough bytes in buffer for smallest message? + numOfBytesInBuffer = numberOfBytesInCommBuffer( getInBufferID( i ) ); + if ( numOfBytesInBuffer >= MESSAGE_OVERHEAD_SIZE ) + { // Peek at minimum of all bytes available or max message size (+1 for sync byte) + U32 bytesPeeked = peekFromCommBuffer( getInBufferID( i ), data, MIN( numOfBytesInBuffer, sizeof( MESSAGE_WRAPPER_T ) + 1 ) ); + S32 msgSize = parseMessageFromBuffer( data, bytesPeeked ); + + setOnlyCANNode( FALSE ); // Since we are getting a message, this indicates we are not the only node on the CAN bus + canXmitRetryCtr = 0; + + if ( msgSize > 0 ) // Valid, complete message found? + { + MESSAGE_WRAPPER_T rcvMsg; + U08 *dataPtr = data+1; // Skip over sync byte + + // Consume message (+sync byte) + msgSize = getFromCommBuffer( getInBufferID( i ), data, msgSize + 1 ); + // Convert received message data to a message and add to message queue + messagesInBuffer = TRUE; // Keep processing this buffer + // Blank the new message record + blankMessageInWrapper( &rcvMsg ); + // Copy message header portion of message data to the new message + memcpy( &(rcvMsg.msg.hdr), dataPtr, sizeof( MESSAGE_HEADER_T ) ); + dataPtr += sizeof( MESSAGE_HEADER_T ); + // Copy message payload portion of message data to the new message + memcpy( &(rcvMsg.msg.payload), dataPtr, rcvMsg.msg.hdr.payloadLen ); + dataPtr += rcvMsg.msg.hdr.payloadLen; + // Copy CRC portion of message data to the new message + rcvMsg.crc = *dataPtr; + // Add new message to queue for later processing + addToMsgQueue( MSG_Q_IN, &rcvMsg ); +#ifdef _TD_ + // If message from DG broadcast channel, update DG comm status + if ( COMM_BUFFER_IN_CAN_DD_BROADCAST == getInBufferID( i ) ) + { + checkInFromDG(); + } + // If message from UI channel, mark UI communication so HD can begin transmitting + if ( ( COMM_BUFFER_IN_CAN_UI_2_TD == getInBufferID( i ) ) || ( COMM_BUFFER_IN_CAN_UI_BROADCAST == getInBufferID( i ) ) ) + { + checkInFromUI(); + } +#endif + } + else if ( -1 == msgSize ) // Candidate message with bad CRC found? + { + badCRCDetected = TRUE; + getFromCommBuffer( getInBufferID( i ), data, 1 ); // Consume sync byte so we can re-sync + messagesInBuffer = TRUE; // Keep processing this buffer + } // Looks like there is a complete message in the comm buffer + } // Enough data left in comm buffer to possibly be a complete message + } // While loop to get all complete messages for each comm buffer + } // For loop to check all comm buffers for messages + + // If any bad CRCs detected, see if too many + if ( TRUE == badCRCDetected ) + { + checkTooManyBadMsgCRCs(); + } +} + +/*********************************************************************//** + * @brief + * The consumeBufferPaddingBeforeSync function removes any bytes in a given + * buffer that lie before a sync byte. + * @details Inputs: none + * @details Outputs: Any padding at front of buffer is consumed. + * @param buffer the comm buffer to process + * @return none + *************************************************************************/ +static void consumeBufferPaddingBeforeSync( COMM_BUFFER_T buffer ) +{ + U08 data; + U32 numOfBytesInBuffer = numberOfBytesInCommBuffer( buffer ); + + // Consume bytes out of buffer 1 at a time until we find the sync byte or it is empty + while ( numOfBytesInBuffer > 0 ) + { + peekFromCommBuffer( buffer, &data, 1 ); + if ( MESSAGE_SYNC_BYTE == data ) + { + break; // We found a sync - we are done + } + else // Not a sync byte, so consume it + { + getFromCommBuffer( buffer, &data, 1 ); + numOfBytesInBuffer = numberOfBytesInCommBuffer( buffer ); + } + } +} + +/*********************************************************************//** + * @brief + * The parseMessageFromBuffer function looks for a complete message in a + * given buffer. If a message is found, its size is returned. + * @details Inputs: none + * @details Outputs: none + * @param data pointer to byte array to search for a message + * @param len number of bytes in the data to search + * @return size of message if found, zero if no complete message found, + * -1 if message found but CRC fails. + *************************************************************************/ +static S32 parseMessageFromBuffer( U08 *data, U32 len ) +{ + U32 i; + U32 payloadSize; + U32 msgSize; + S32 result = 0; + + for ( i = 0; i < len; i++ ) + { + // Find sync byte + if ( MESSAGE_SYNC_BYTE == data[ i ] ) + { + U32 pos = i + 1; // Skip past sync byte implemented + U32 remSize = len - pos; + + // If a minimum sized msg would fit in remaining, continue + if ( remSize >= MESSAGE_OVERHEAD_SIZE ) + { + payloadSize = data[ pos + sizeof(MESSAGE_HEADER_T) - sizeof(U08) ]; + msgSize = MESSAGE_OVERHEAD_SIZE + payloadSize; + // We now know the size of the message - we can now know if full message is contained in buffer + if ( msgSize <= remSize ) + { // Check CRC to make sure it is a valid message + if ( data[i+msgSize] == crc8( &data[pos], msgSize - 1 ) ) + { + result = msgSize; // We found a complete, valid message of this size + } + else // CRC failed + { + result = -1; // We found a complete, invalid message + } + } + } + break; + } + } + + return result; +} + +/*********************************************************************//** + * @brief + * The processReceivedMessages function processes any messages in the + * received message queues. + * @details Inputs: Received Message Queues + * @details Outputs: Message(s) processed. + * @return none + *************************************************************************/ +static void processReceivedMessages( void ) +{ + BOOL isThereMsgRcvd = TRUE; // Assume TRUE at first to get into while loop + MESSAGE_WRAPPER_T message; + + while ( TRUE == isThereMsgRcvd ) + { + // See if any messages received + isThereMsgRcvd = getFromMsgQueue( MSG_Q_IN, &message ); + if ( TRUE == isThereMsgRcvd ) + { // CRC should be good because we checked it during parsing before adding to queue - but check it again for good measure + if ( message.crc == crc8( (U08*)(&message), sizeof(MESSAGE_HEADER_T) + message.msg.hdr.payloadLen ) ) + { + // If ACK, mark pending message ACK'd + if ( MSG_ID_ACK_MESSAGE_THAT_REQUIRES_ACK == message.msg.hdr.msgID ) + { + matchACKtoPendingACKList( message.msg.hdr.seqNo ); + } + else + { + // If received message requires ACK, queue one up + if ( message.msg.hdr.seqNo < 0 ) + { + sendACKMsg( &message.msg ); + } + // Process the received message + processReceivedMessage( &message.msg ); + } + } + else // CRC failed + { + checkTooManyBadMsgCRCs(); + } + } + } +} + +/*********************************************************************//** + * @brief + * The checkTooManyBadMsgCRCs function checks for too many bad message CRCs + * within a set period of time. Assumed function is being called when a new + * bad CRC is detected so a new bad CRC will be added to the list. + * @details Inputs: badCRCTimeStamps[], badCRCListIdx, badCRCListCount + * @details Outputs: possibly a "too many bad CRCs" alarm + * @return none + *************************************************************************/ +static void checkTooManyBadMsgCRCs( void ) +{ + if ( TRUE == incTimeWindowedCount( TIME_WINDOWED_COUNT_BAD_MSG_CRC ) ) + { + SET_ALARM_WITH_1_U32_DATA( ALARM_ID_HD_COMM_TOO_MANY_BAD_CRCS, (U32)ALARM_SOURCE_HD ); + } +} + +/*********************************************************************//** + * @brief + * The addMsgToPendingACKList function adds a given message to the pending + * ACK list. Messages in this list will require receipt of an ACK message + * for this particular message within a limited time. + * @details Inputs: pendingAckList[] + * @details Outputs: pendingAckList[] + * @param msg pointer to msg within the message data + * @param msgData pointer to message data to add to pending ACK list + * @param len number of bytes of message data + * @return TRUE if message added successfully, FALSE if not + *************************************************************************/ +BOOL addMsgToPendingACKList( MESSAGE_T *msg, COMM_BUFFER_T channel, U08 *msgData, U32 len ) +{ + BOOL result = FALSE; + U32 i; + + // Find first open slot in pending ACK list and add given msg data to it + for ( i = 0; i < PENDING_ACK_LIST_SIZE; i++ ) + { + _disable_IRQ(); // Slot selection needs interrupt protection + if ( FALSE == pendingAckList[ i ].used ) + { + S16 seqNo = msg->hdr.seqNo * -1; // Remove ACK bit from seq # + + pendingAckList[ i ].used = TRUE; + _enable_IRQ(); + pendingAckList[ i ].seqNo = seqNo; + pendingAckList[ i ].channel = channel; + pendingAckList[ i ].timeStamp = getMSTimerCount(); + pendingAckList[ i ].retries = MSG_NOT_ACKED_MAX_RETRIES; + pendingAckList[ i ].msgSize = len; + memcpy( (U08*)pendingAckList[ i ].msg, msgData, len ); + result = TRUE; + break; + } + else + { + _enable_IRQ(); + } + } + + return result; +} + +/*********************************************************************//** + * @brief + * The matchACKtoPendingACKList function searches the pending ACK list to + * see if the sequence # from a received ACK msg matches any. If found, + * the list entry is removed. + * @details Inputs: pendingAckList[] + * @details Outputs: pendingAckList[] + * @param seqNo sequence # to match to an entry in the list + * @return TRUE if a match was found, FALSE if not + *************************************************************************/ +static BOOL matchACKtoPendingACKList( S16 seqNo ) +{ + BOOL result = FALSE; + U32 i; + + // Find match + for ( i = 0; i < PENDING_ACK_LIST_SIZE; i++ ) + { + if ( ( TRUE == pendingAckList[ i ].used ) && ( pendingAckList[ i ].seqNo == seqNo ) ) + { + result = TRUE; + // Remove message pending ACK from list + if ( ( ( getU32OverrideValue( &pendingACKOverride ) != PENDING_ACK_LIST_OVERRIDE_UI_CHANNEL ) || ( pendingAckList[ i ].channel != COMM_BUFFER_OUT_CAN_TD_2_UI ) ) && + ( ( getU32OverrideValue( &pendingACKOverride ) != PENDING_ACK_LIST_OVERRIDE_DG_CHANNEL ) || ( pendingAckList[ i ].channel != COMM_BUFFER_OUT_CAN_TD_2_DD ) ) ) + { + pendingAckList[ i ].used = FALSE; + } + break; + } + } + + return result; +} + +/*********************************************************************//** + * @brief + * The checkPendingACKList function searches the pending ACK list to + * see if any have expired. Any such messages will be queued for retransmission + * and if max retries reached a fault is triggered. + * @details Inputs: pendingAckList[] + * @details Outputs: pendingAckList[] + * @return none + *************************************************************************/ +static void checkPendingACKList( void ) +{ + U32 i; + + // Find expired messages pending ACK + for ( i = 0; i < PENDING_ACK_LIST_SIZE; i++ ) + { // Pending ACK expired? + if ( ( TRUE == pendingAckList[ i ].used ) && ( TRUE == didTimeout( pendingAckList[ i ].timeStamp, MSG_NOT_ACKED_TIMEOUT_MS ) ) ) + { // If retries left, reset and resend pending message + if ( pendingAckList[ i ].retries > 0 ) + { // Re-queue message for transmit + pendingAckList[ i ].retries--; + pendingAckList[ i ].timeStamp = getMSTimerCount(); + addToCommBuffer( pendingAckList[ i ].channel, (U08*)pendingAckList[ i ].msg, pendingAckList[ i ].msgSize ); + } + // If no retries left, alarm + else + { + U16 msgID; + + memcpy( &msgID, (U08*)&pendingAckList[ i ].msg[ sizeof( U08 ) + sizeof( U16) ], sizeof( U16 ) ); + + if ( pendingAckList[ i ].channel != COMM_BUFFER_OUT_CAN_TD_2_DD ) + { +// SET_ALARM_WITH_1_U32_DATA( ALARM_ID_HD_CAN_MESSAGE_NOT_ACKED_BY_UI, (U32)msgID ); + } + else + { +// SET_ALARM_WITH_1_U32_DATA( ALARM_ID_HD_CAN_MESSAGE_NOT_ACKED_BY_DD, (U32)msgID ); + } + pendingAckList[ i ].used = FALSE; // Take pending message off of list + } + } + } +} + + +/************************************************************************* + * TEST SUPPORT FUNCTIONS + *************************************************************************/ + + +/*********************************************************************//** + * @brief + * The testSetPendingACKOverride function overrides the + * pendingACKOverride variable. + * @details Inputs: none + * @details Outputs: pendingACKOverride + * @param value override for pendingACKOverride + * @return TRUE if override successful, FALSE if not + *************************************************************************/ +BOOL testSetPendingACKOverride( U32 value ) +{ + BOOL result = FALSE; + + if ( TRUE == isTestingActivated() ) + { + result = TRUE; + pendingACKOverride.ovData = value; + pendingACKOverride.override = OVERRIDE_KEY; + } + + return result; +} + +/*********************************************************************//** + * @brief + * The testResetPendingACKOverride function resets the override + * of the pendingACKOverride variable. + * @details Inputs: none + * @details Outputs: pendingACKOverride + * @return TRUE if override reset successful, FALSE if not + *************************************************************************/ +BOOL testResetPendingACKOverride( void ) +{ + BOOL result = FALSE; + + if ( TRUE == isTestingActivated() ) + { + result = TRUE; + pendingACKOverride.override = OVERRIDE_RESET; + pendingACKOverride.ovData = pendingACKOverride.ovInitData; + } + + return result; +} +/**@}*/ Index: SystemComm.h =================================================================== diff -u --- SystemComm.h (revision 0) +++ SystemComm.h (revision 6d80d69a210f45c733e5307859351f2cd820a8e7) @@ -0,0 +1,60 @@ +/************************************************************************** +* +* Copyright (c) 2024-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 SystemComm.h +* +* @author (last) Sean +* @date (last) 30-Jul-2024 +* +* @author (original) Sean +* @date (original) 30-Jul-2024 +* +***************************************************************************/ + +#ifndef __SYSTEM_COMM_H__ +#define __SYSTEM_COMM_H__ + +#include "TDCommon.h" +#include "CommBuffers.h" +#include "MsgQueues.h" + +/** + * @defgroup SystemComm SystemComm + * @brief System communication module. Manages incoming and outgoing CAN frames. + * + * @addtogroup SystemComm + * @{ + */ + +// ********** public definitions ********** + +#define MESSAGE_SYNC_BYTE 0xA5 ///< Denali message syncronization byte. + +#define CAN_MESSAGE_PAYLOAD_SIZE 8 ///< CAN frame payload size (in bytes). + +#define MSG_ACK_BIT 0x8000 ///< ACK bit in sequence number that indicates an ACK is required. +#define MAX_MSG_SEQ_NO 0x7FFF ///< Maximum sequence number for Denali message (then wraps to 1). +#define MIN_MSG_SEQ_NO 0x0001 ///< Minimum sequence number for Denali message. +#define MAX_ACK_MSG_SIZE ( sizeof( MESSAGE_WRAPPER_T ) + 1 + CAN_MESSAGE_PAYLOAD_SIZE ) ///< Maximum size (in bytes) of Denali message including full (wrapped) message + sync + any CAN padding) + +typedef COMM_BUFFER_T CAN_MESSAGE_BOX_T; ///< The CAN comm buffers align with the active CAN message boxes + +// ********** public function prototypes ********** + +void initSystemComm( void ); +void execSystemCommRx( void ); +void execSystemCommTx( void ); +void handleCANMsgInterrupt( CAN_MESSAGE_BOX_T srcCANBox ); +BOOL isCANBoxForXmit( CAN_MESSAGE_BOX_T srcCANBox ); +BOOL isCANBoxForRecv( CAN_MESSAGE_BOX_T srcCANBox ); +BOOL addMsgToPendingACKList( MESSAGE_T *msg, COMM_BUFFER_T channel, U08 *msgData, U32 len ); +BOOL testSetPendingACKOverride( U32 value ); +BOOL testResetPendingACKOverride( void ); + +/**@}*/ + +#endif Index: TestSupport.c =================================================================== diff -u --- TestSupport.c (revision 0) +++ TestSupport.c (revision 6d80d69a210f45c733e5307859351f2cd820a8e7) @@ -0,0 +1,386 @@ +/************************************************************************** +* +* Copyright (c) 2024-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 TestSupport.c +* +* @author (last) Sean +* @date (last) 30-Jul-2024 +* +* @author (original) Sean +* @date (original) 30-Jul-2024 +* +***************************************************************************/ + +#include +#include "Common.h" +#include "Timers.h" + +/** + * @addtogroup TestSupport + * @{ + */ + +// ********** private definitions ********** + +#define TEST_CONFIG_ENABLE_KEY 0xDABA36B2 ///< Release software configuration enable key. +#define TEST_CONFIG_DISABLE_KEY 0x00000000 ///< Release software configuration disable key. +#define DIALIN_CHECK_IN_TIMEOUT_MS ( 8 * MIN_PER_HOUR * SEC_PER_MIN * MS_PER_SECOND ) ///< Dialin check in timeout in milliseconds. + +// ********** private data ********** + +static U32 testConfig[ NUM_OF_TEST_CONFIGS ]; ///< Release software configuration. +static U32 dialinCheckInTimeStamp; ///< Dialin checkin time stamp. +static BOOL signalRecoverFromFaultMode; ///< Boolean flag to allow the user to recover from fault mode in test configurations. + +// ********** private function prototypes ********** + + +/*********************************************************************//** + * @brief + * The getU08OverrideValue function extracts the appropriate U08 + * value from a given U32 override record according to the record state. + * @details Inputs: none + * @details Outputs: none + * @param ovU32 pointer to a floating point override record + * @return overridden U08 point value from the record + *************************************************************************/ +U08 getU08OverrideValue( OVERRIDE_U32_T *ovU32 ) +{ + U08 result = (U08)( ovU32->data & MASK_OFF_U32_MSBS ); + + if ( OVERRIDE_KEY == ovU32->override ) + { + result = (U08)( ovU32->ovData & MASK_OFF_U32_MSBS ); + } + + return result; +} + +/*********************************************************************//** + * @brief + * The getU16OverrideValue function extracts the appropriate U16 + * value from a given U32 override record according to the record state. + * @details Inputs: none + * @details Outputs: none + * @param ovU32 pointer to a floating point override record + * @return overridden U16 point value from the record + *************************************************************************/ +U16 getU16OverrideValue( OVERRIDE_U32_T *ovU32 ) +{ + U16 result = (U16)( ovU32->data & MASK_OFF_MSW ); + + if ( OVERRIDE_KEY == ovU32->override ) + { + result = (U16)( ovU32->ovData & MASK_OFF_MSW ); + } + + return result; +} + +/*********************************************************************//** + * @brief + * The getS32OverrideValue function extracts the appropriate signed integer + * value from a given signed integer override record according to the + * record state. + * @details Inputs: none + * @details Outputs: none + * @param ovS32 pointer to an unsigned integer override record + * @return either the real or overridden signed integer value from the record + *************************************************************************/ +S32 getS32OverrideValue( OVERRIDE_S32_T *ovS32 ) +{ + S32 result = ovS32->data; + + if ( OVERRIDE_KEY == ovS32->override ) + { + result = ovS32->ovData; + } + + return result; +} + +/*********************************************************************//** + * @brief + * The getU32OverrideValue function extracts the appropriate unsigned integer + * value from a given unsigned integer override record according to the + * record state. + * @details Inputs: none + * @details Outputs: none + * @param ovU32 pointer to an unsigned integer override record + * @return either the real or overridden unsigned integer value from the record + *************************************************************************/ +U32 getU32OverrideValue( OVERRIDE_U32_T *ovU32 ) +{ + U32 result = ovU32->data; + + if ( OVERRIDE_KEY == ovU32->override ) + { + result = ovU32->ovData; + } + + return result; +} + +/*********************************************************************//** + * @brief + * The getF32OverrideValue function extracts the appropriate floating point + * value from a given float override record according to the record state. + * @details Inputs: none + * @details Outputs: none + * @param ovF32 pointer to a floating point override record + * @return either the real or overridden floating point value from the record + *************************************************************************/ +F32 getF32OverrideValue( OVERRIDE_F32_T *ovF32 ) +{ + F32 result = ovF32->data; + + if ( OVERRIDE_KEY == ovF32->override ) + { + result = ovF32->ovData; + } + + return result; +} + +// ********** Release software configurations functions ********** + +/*********************************************************************//** + * @brief + * The initTestConfigs function initializes the test software configurations. + * @details Inputs: none + * @details Outputs: signalRecoverFromFaultMode + * @return none + *************************************************************************/ +void initTestConfigs( void ) +{ + resetAllTestConfigs(); + signalRecoverFromFaultMode = FALSE; +} + +/*********************************************************************//** + * @brief + * The setTestConfig function sets the test configuration. + * Must be logged into HD/DG. + * @details Inputs: none + * @details Outputs: testConfig + * @param config which is the configuration to set + * @return TRUE if the set configuration was successful otherwise, FALSE + *************************************************************************/ +BOOL setTestConfig( TEST_CONFIG_T config ) +{ + BOOL status = FALSE; + + if ( ( config < NUM_OF_TEST_CONFIGS ) && ( TRUE == isTestingActivated() ) ) + { + testConfig[ config ] = TEST_CONFIG_ENABLE_KEY; + status = TRUE; + } + else + { +#ifdef _DD_ +// SET_ALARM_WITH_2_U32_DATA( ALARM_ID_DD_SOFTWARE_FAULT, SW_FAULT_ID_DG_INVALID_TEST_CONFIG_SELECTED, config ) +#endif +#ifdef _TD_ +// SET_ALARM_WITH_2_U32_DATA( ALARM_ID_TD_SOFTWARE_FAULT, SW_FAULT_ID_HD_INVALID_TEST_CONFIG_SELECTED, config ) +#endif + } + + return status; +} + +/*********************************************************************//** + * @brief + * The resetTestConfig function resets the test configuration. + * Must be logged into HD/DG. + * @details Inputs: none + * @details Outputs: testConfig + * @param config which is the configuration to reset + * @return TRUE if the reset configuration was successful otherwise, FALSE + *************************************************************************/ +BOOL resetTestConfig( TEST_CONFIG_T config ) +{ + BOOL status = FALSE; + + if ( ( config < NUM_OF_TEST_CONFIGS ) && ( TRUE == isTestingActivated() ) ) + { + testConfig[ config ] = TEST_CONFIG_DISABLE_KEY; + status = TRUE; + } + else + { +#ifdef _DD_ +// SET_ALARM_WITH_2_U32_DATA( ALARM_ID_DD_SOFTWARE_FAULT, SW_FAULT_ID_DG_INVALID_TEST_CONFIG_SELECTED, config ) +#endif +#ifdef _TD_ +// SET_ALARM_WITH_2_U32_DATA( ALARM_ID_TD_SOFTWARE_FAULT, SW_FAULT_ID_HD_INVALID_TEST_CONFIG_SELECTED, config ) +#endif + } + + return status; +} + +/*********************************************************************//** + * @brief + * The getTestConfigStatus function gets the status of the provided test + * configuration. Must be logged into HD/DG. + * @details Inputs: testConfig + * @details Outputs: none + * @param config the test configuration + * @return TRUE if the test configuration is enabled otherwise, FALSE + *************************************************************************/ +BOOL getTestConfigStatus( TEST_CONFIG_T config ) +{ + BOOL status = FALSE; + + if ( ( TEST_CONFIG_ENABLE_KEY == testConfig[ config ] ) && ( TRUE == isTestingActivated() ) ) + { + status = TRUE; + } + + return status; +} + +/*********************************************************************//** + * @brief + * The sendTestConfigStatusToDialin function sends the test configuration + * status to dialin. + * @details Inputs: none + * @details Outputs: testConfig + * @return TRUE if the serialization is successful otherwise, FALSE + *************************************************************************/ +BOOL sendTestConfigStatusToDialin( void ) +{ + BOOL result = FALSE; + MESSAGE_T msg; + TEST_CONFIG_T config; + U32 configStatus = 0; + U08 *payloadPtr = msg.payload; + + if ( TRUE == isTestingActivated() ) + { + // Create a message record + blankMessage( &msg ); +#ifdef _DD_ + msg.hdr.msgID = MSG_ID_DG_SEND_TEST_CONFIGURATION; +#endif +#ifdef _TD_ + msg.hdr.msgID = MSG_ID_HD_SEND_TEST_CONFIGURATION; +#endif + msg.hdr.payloadLen = sizeof( testConfig ); + + for ( config = TEST_CONFIG_FIRST; config < NUM_OF_TEST_CONFIGS; ++config ) + { + configStatus = (U32)getTestConfigStatus( config ); + + memcpy( payloadPtr, &configStatus, sizeof( U32 ) ); + payloadPtr += sizeof( U32 ); + } + + // Serialize the message (w/ sync, CRC, and appropriate CAN padding) and add serialized message data to appropriate comm buffer + result = serializeMessage( msg, COMM_BUFFER_OUT_CAN_PC, ACK_NOT_REQUIRED ); + } + + return result; +} + +/*********************************************************************//** + * @brief + * The resetAllTestConfigs function resets all of the test configurations. + * Must be logged into HD/DG. + * @details Inputs: none + * @details Outputs: testConfig + * @return TRUE if the reset was successful otherwise, FALSE + *************************************************************************/ +BOOL resetAllTestConfigs( void ) +{ + BOOL status = FALSE; + + if ( TRUE == isTestingActivated() ) + { + TEST_CONFIG_T config; + + for ( config = TEST_CONFIG_FIRST; config < NUM_OF_TEST_CONFIGS; ++config ) + { + testConfig[ config ] = TEST_CONFIG_DISABLE_KEY; + } + + status = TRUE; + } + + return status; +} + +/*********************************************************************//** + * @brief + * The setDialinCheckInTimeStamp function set the dialin check in timestamp. + * @details Inputs: none + * @details Outputs: dialinCheckInTimeStamp + * @return none + *************************************************************************/ +void setDialinCheckInTimeStamp( void ) +{ + dialinCheckInTimeStamp = getMSTimerCount(); +} + +/*********************************************************************//** + * @brief + * The hasDialinCheckInExpired function checks whether the check in from + * dialin has expired or not. + * @details Inputs: none + * @details Outputs: dialinCheckInTimeStamp + * @return TRUE if the check in has been expired otherwise, FALSE + *************************************************************************/ +BOOL hasDialinCheckInExpired( void ) +{ + BOOL status = FALSE; + + if ( ( TRUE == didTimeout( dialinCheckInTimeStamp, DIALIN_CHECK_IN_TIMEOUT_MS ) ) && ( TRUE == isTestingActivated() ) ) + { + // If the dialin check in has timed out and tester has logged in check for the expiration value + status = TRUE; + } + + return status; +} + +/*********************************************************************//** + * @brief + * The setRecoverFromFaultModeSignal function sets the recover from fault + * mode signal upon receiving it from the user. + * @details Inputs: none + * @details Outputs: signalRecoverFromFaultMode + * @return none + *************************************************************************/ +void setRecoverFromFaultModeSignal( void ) +{ + if ( TRUE == isTestingActivated() ) + { + signalRecoverFromFaultMode = TRUE; + } +} + +/*********************************************************************//** + * @brief + * The hasRecoverFromFaultModeBeenSet function returns the status of the + * recover from fault mode signal + * @details Inputs: none + * @details Outputs: signalRecoverFromFaultMode + * @return TRUE is the user is logged in and the signal is TRUE, otherwise FLASE + *************************************************************************/ +BOOL hasRecoverFromFaultModeBeenSet( void ) +{ + BOOL status = FALSE; + + if ( TRUE == isTestingActivated() ) + { + status = signalRecoverFromFaultMode; + } + + return status; +} + +/**@}*/ Index: TestSupport.h =================================================================== diff -u --- TestSupport.h (revision 0) +++ TestSupport.h (revision 6d80d69a210f45c733e5307859351f2cd820a8e7) @@ -0,0 +1,146 @@ +/************************************************************************** +* +* Copyright (c) 2024-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 TestSupport.h +* +* @author (last) Sean +* @date (last) 30-Jul-2024 +* +* @author (original) Sean +* @date (original) 30-Jul-2024 +* +***************************************************************************/ + +#ifndef __TEST_SUPPORT_H__ +#define __TEST_SUPPORT_H__ + +/** + * @defgroup TestSupport TestSupport + * @brief Test support header file. Contains the structures and macros for override operations. + * + * @addtogroup TestSupport + * @{ + */ + +// ***************************** OVERRIDE DEFINITIONS & MACROS ************************************* + +#define OVERRIDE_KEY 0xCCC33C33 ///< Override key +#define OVERRIDE_RESET 0x00000000 ///< Override reset + +#ifdef _DD_ +/// DG test software configurations +typedef enum test_Config_enums +{ + TEST_CONFIG_MIX_WITH_WATER = 0, ///< Test configuration mix with water. + TEST_CONFIG_FIRST = TEST_CONFIG_MIX_WITH_WATER, ///< Test configuration first configuration. + TEST_CONFIG_DISABLE_INLET_WATER_TEMP_CHECK, ///< Test configuration disable inlet water temperature check. + TEST_CONFIG_RECOVER_TREATMENT, ///< Test configuration recover treatment. + NUM_OF_TEST_CONFIGS ///< Number of test configuration. +} TEST_CONFIG_T; +#else +/// HD test software configurations +typedef enum test_Config +{ + TEST_CONFIG_USE_WET_CARTRIDGE = 0, ///< Test configuration use wet cartridge. + TEST_CONFIG_FIRST = TEST_CONFIG_USE_WET_CARTRIDGE, ///< Test configuration first configuration. + TEST_CONFIG_USE_WORN_CARTRIDGE, ///< Test configuration use worn cartridge. + TEST_CONFIG_EXPEDITE_PRE_TREATMENT, ///< Test configuration expedite pre-treatment. + TEST_CONFIG_SKIP_BLOOD_PRIME, ///< Test configuration skip blood prime. + TEST_CONFIG_SKIP_DISINFECT_AND_SERVICE_TX_BLOCKERS, ///< Test configuration skip disinfect and service treatment blockers. + TEST_CONFIG_DISABLE_WET_SELFTEST_DISPLACEMENT_ALARM, ///< Test configuration disable wet self test displacement alarm. + TEST_CONFIG_RECOVER_TREATMENT, ///< Test configuration recover treatment. + TEST_CONFIG_ENABLE_ONE_MINUTE_TREATMENT, ///< Test configuration enable one minute treatment. + TEST_CONFIG_DISABLE_BLOOD_LEAK_ALARM, ///< Test configuration disable blood leak alarm. + NUM_OF_TEST_CONFIGS ///< Number of test configuration. +} TEST_CONFIG_T; +#endif + +#pragma pack(push,1) + +/// Test configuration payload +typedef struct +{ + BOOL reset; ///< Test configuration reset. + U32 config; ///< Test configuration. +} TEST_CONFIG_PAYLOAD_T ; + +/// Test override payload type union. +typedef union +{ + U32 u32; ///< U32 + F32 f32; ///< F32 +} TEST_OVERRIDE_PAYLOAD_TYPE_T; + +/// Test override payload type structure. +typedef struct +{ + BOOL reset; ///< Reset (bool) + TEST_OVERRIDE_PAYLOAD_TYPE_T state; ///< Test override payload +} TEST_OVERRIDE_PAYLOAD_T; + +/// Test override array payload structure. +typedef struct +{ + BOOL reset; ///< Reset (bool) + TEST_OVERRIDE_PAYLOAD_TYPE_T state; ///< Test override array payload + U32 index; ///< Index +} TEST_OVERRIDE_ARRAY_PAYLOAD_T; + +#pragma pack(pop) + +/// Override U32 structure. +typedef struct +{ + U32 data; ///< Data + U32 ovInitData; ///< Override init data + U32 ovData; ///< Override data + U32 override; ///< Override +} OVERRIDE_U32_T; + +/// Override S32 structure. +typedef struct +{ + S32 data; ///< Data + S32 ovInitData; ///< Override init data + S32 ovData; ///< Override data + U32 override; ///< Override +} OVERRIDE_S32_T; + +/// Override F32 structure. +typedef struct +{ + F32 data; ///< Data + F32 ovInitData; ///< Override init data + F32 ovData; ///< Overrode data + U32 override; ///< Override +} OVERRIDE_F32_T; + +// ********** public function prototypes ********** + +U08 getU08OverrideValue( OVERRIDE_U32_T *ovU32 ); +U16 getU16OverrideValue( OVERRIDE_U32_T *ovU32 ); +U32 getU32OverrideValue( OVERRIDE_U32_T *ovU32 ); +S32 getS32OverrideValue( OVERRIDE_S32_T *ovS32 ); +F32 getF32OverrideValue( OVERRIDE_F32_T *ovF32 ); + +// Test configuration functions + +void initTestConfigs( void ); +BOOL setTestConfig( TEST_CONFIG_T config ); +BOOL resetTestConfig( TEST_CONFIG_T config ); +BOOL getTestConfigStatus( TEST_CONFIG_T config ); +BOOL sendTestConfigStatusToDialin( void ); +BOOL resetAllTestConfigs( void ); + +void setDialinCheckInTimeStamp( void ); +BOOL hasDialinCheckInExpired( void ); +void setRecoverFromFaultModeSignal( void ); +BOOL hasRecoverFromFaultModeBeenSet( void ); + +/**@}*/ + +#endif Index: Timers.c =================================================================== diff -u --- Timers.c (revision 0) +++ Timers.c (revision 6d80d69a210f45c733e5307859351f2cd820a8e7) @@ -0,0 +1,158 @@ +/************************************************************************** +* +* Copyright (c) 2024-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 Timers.c +* +* @author (last) Sean +* @date (last) 30-Jul-2024 +* +* @author (original) Sean +* @date (original) 30-Jul-2024 +* +***************************************************************************/ + +#include "Timers.h" + +/** + * @addtogroup Timers + * @{ + */ + +// ********** private definitions ********** + +// ********** private data ********** + +static volatile U32 msTimerCount = 0; ///< 1ms timer counter incremented by TaskTimer.c. + +/*********************************************************************//** + * @brief + * The initTimers function initializes the Timers module. + * @details Inputs: msTimerCount + * @details Outputs: msTimerCount + * @return none + *************************************************************************/ +void initTimers( void ) +{ + msTimerCount = 0; +} + +/*********************************************************************//** + * @brief + * The incMSTimerCount function increments the ms timer count. + * @details Inputs: msTimerCount + * @details Outputs: msTimerCount + * @return none + *************************************************************************/ +void incMSTimerCount( void ) +{ + msTimerCount++; +} + +/*********************************************************************//** + * @brief + * The getMSTimerCount function returns the current ms timer count. + * @details Inputs: msTimerCount + * @details Outputs: none + * @return msTimerCount as a U32 + *************************************************************************/ +U32 getMSTimerCount( void ) +{ + return msTimerCount; +} + +/*********************************************************************//** + * @brief + * The didTimeout function determines whether a timeout has occurred between + * a given start count and a given timeout period (in ms). + * @details Inputs: msTimerCount + * @details Outputs: none + * @param startMSCount the ms count at the start of the timeout period + * @param timeoutPeriod the period for the timeout (in ms) + * @return TRUE if a timeout has occurred, FALSE if not + *************************************************************************/ +BOOL didTimeout( U32 startMSCount, U32 timeoutPeriod ) +{ + BOOL result = FALSE; + U32 currMSCount = msTimerCount; + + // no wrap + if ( currMSCount >= startMSCount ) + { + if ( ( currMSCount - startMSCount ) >= timeoutPeriod ) + { + result = TRUE; + } + } + // counter wrapped + else + { + U32 deltaMSCount = ( 0xFFFFFFFF - startMSCount ) + currMSCount + 1; + + if ( deltaMSCount >= timeoutPeriod ) + { + result = TRUE; + } + } + + return result; +} + +/*********************************************************************//** + * @brief + * The calcTimeSince function calculates the time (in ms) from a given start + * time until now. + * @details Inputs: msTimerCount + * @details Outputs: none + * @param startMSCount the ms count at the start of the period + * @return ms since given start time + *************************************************************************/ +U32 calcTimeSince( U32 startMSCount ) +{ + U32 result; + U32 currMSCount = msTimerCount; + + // no wrap + if ( currMSCount >= startMSCount ) + { + result = currMSCount - startMSCount; + } + else + { + result = ( 0xFFFFFFFF - startMSCount ) + currMSCount + 1; + } + + return result; +} + +/*********************************************************************//** + * @brief + * The calcTimeBetween function calculates the time (in ms) from a given start + * time until a given end time. + * @details Inputs: none + * @details Outputs: none + * @param startMSCount the ms count at the start of the period + * @param endMSCount the ms count at the end of the period + * @return ms between two given times + *************************************************************************/ +U32 calcTimeBetween( U32 startMSCount, U32 endMSCount ) +{ + U32 result; + + // no wrap + if ( endMSCount >= startMSCount ) + { + result = endMSCount - startMSCount; + } + else + { + result = ( 0xFFFFFFFF - startMSCount ) + endMSCount + 1; + } + + return result; +} + +/**@}*/ Index: Timers.h =================================================================== diff -u --- Timers.h (revision 0) +++ Timers.h (revision 6d80d69a210f45c733e5307859351f2cd820a8e7) @@ -0,0 +1,43 @@ +/************************************************************************** +* +* Copyright (c) 2024-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 Timers.h +* +* @author (last) Sean +* @date (last) 30-Jul-2024 +* +* @author (original) Sean +* @date (original) 30-Jul-2024 +* +***************************************************************************/ + +#ifndef __TIMERS_H__ +#define __TIMERS_H__ + +#include "Common.h" + +/** + * @defgroup Timers Timers + * @brief Timers service module. Provides timer utility functions based on + * a 1ms timer counter incremented by TaskTimer.c. + * + * @addtogroup Timers + * @{ + */ + +// ********** public function prototypes ********** + +void initTimers( void ); +void incMSTimerCount( void ); +U32 getMSTimerCount( void ); +BOOL didTimeout( U32 startMSCount, U32 timeoutPeriod ); +U32 calcTimeSince( U32 startMSCount ); +U32 calcTimeBetween( U32 startMSCount, U32 endMSCount ); + +/**@}*/ + +#endif Index: Utilities.c =================================================================== diff -u --- Utilities.c (revision 0) +++ Utilities.c (revision 6d80d69a210f45c733e5307859351f2cd820a8e7) @@ -0,0 +1,746 @@ +/************************************************************************** +* +* Copyright (c) 2024-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 Utilities.c +* +* @author (last) Sean +* @date (last) 30-Jul-2024 +* +* @author (original) Sean +* @date (original) 30-Jul-2024 +* +***************************************************************************/ + +#include // For memcpy + +#include "Common.h" +//#include "FPGA.h" +#include "Timers.h" +#include "Utilities.h" + +/** + * @addtogroup Utilities + * @{ + */ + +// ********** private definitions ********** + +#define INITIAL_CRC16_VAL 0xFFFF ///< Seed for 16-bit CRC function. +#define INITIAL_CRC08_VAL 0x00 ///< Seed for 8-bit CRC function. +#define HEX_LETTER_TO_NUMBER_CONV 0x37 ///< Hex letter (i.e. A) to number conversion. +#define STR_TO_HEX_CONV_MAX_BYTES 8 ///< String to hex conversion maximum allowed bytes. + +#define SEMAPHORE_IN_USE_TIMEOUT_MS ( 10 * MS_PER_SECOND ) ///< Taken semaphore timeout in milliseconds. + +// ********** private data ********** + +/// Semaphore data structure +typedef struct +{ + U32 semaphoreStartTimeMS; ///< Semaphore start time in milliseconds. + volatile BOOL isSemaphoreTaken; ///< Flag to indicate whether the semaphore is taken or not. +} SEMAPHORE_STATUS_T; + +/// CRC-32 look-up table. +const U32 CRC32_TABLE[] = +{ + 0x00000000, 0x1EDC6F41, 0x3DB8DE82, 0x2364B1C3, 0x7B71BD04, 0x65ADD245, 0x46C96386, 0x58150CC7, + 0xF6E37A08, 0xE83F1549, 0xCB5BA48A, 0xD587CBCB, 0x8D92C70C, 0x934EA84D, 0xB02A198E, 0xAEF676CF, + 0xF31A9B51, 0xEDC6F410, 0xCEA245D3, 0xD07E2A92, 0x886B2655, 0x96B74914, 0xB5D3F8D7, 0xAB0F9796, + 0x05F9E159, 0x1B258E18, 0x38413FDB, 0x269D509A, 0x7E885C5D, 0x6054331C, 0x433082DF, 0x5DECED9E, + 0xF8E959E3, 0xE63536A2, 0xC5518761, 0xDB8DE820, 0x8398E4E7, 0x9D448BA6, 0xBE203A65, 0xA0FC5524, + 0x0E0A23EB, 0x10D64CAA, 0x33B2FD69, 0x2D6E9228, 0x757B9EEF, 0x6BA7F1AE, 0x48C3406D, 0x561F2F2C, + 0x0BF3C2B2, 0x152FADF3, 0x364B1C30, 0x28977371, 0x70827FB6, 0x6E5E10F7, 0x4D3AA134, 0x53E6CE75, + 0xFD10B8BA, 0xE3CCD7FB, 0xC0A86638, 0xDE740979, 0x866105BE, 0x98BD6AFF, 0xBBD9DB3C, 0xA505B47D, + 0xEF0EDC87, 0xF1D2B3C6, 0xD2B60205, 0xCC6A6D44, 0x947F6183, 0x8AA30EC2, 0xA9C7BF01, 0xB71BD040, + 0x19EDA68F, 0x0731C9CE, 0x2455780D, 0x3A89174C, 0x629C1B8B, 0x7C4074CA, 0x5F24C509, 0x41F8AA48, + 0x1C1447D6, 0x02C82897, 0x21AC9954, 0x3F70F615, 0x6765FAD2, 0x79B99593, 0x5ADD2450, 0x44014B11, + 0xEAF73DDE, 0xF42B529F, 0xD74FE35C, 0xC9938C1D, 0x918680DA, 0x8F5AEF9B, 0xAC3E5E58, 0xB2E23119, + 0x17E78564, 0x093BEA25, 0x2A5F5BE6, 0x348334A7, 0x6C963860, 0x724A5721, 0x512EE6E2, 0x4FF289A3, + 0xE104FF6C, 0xFFD8902D, 0xDCBC21EE, 0xC2604EAF, 0x9A754268, 0x84A92D29, 0xA7CD9CEA, 0xB911F3AB, + 0xE4FD1E35, 0xFA217174, 0xD945C0B7, 0xC799AFF6, 0x9F8CA331, 0x8150CC70, 0xA2347DB3, 0xBCE812F2, + 0x121E643D, 0x0CC20B7C, 0x2FA6BABF, 0x317AD5FE, 0x696FD939, 0x77B3B678, 0x54D707BB, 0x4A0B68FA, + 0xC0C1D64F, 0xDE1DB90E, 0xFD7908CD, 0xE3A5678C, 0xBBB06B4B, 0xA56C040A, 0x8608B5C9, 0x98D4DA88, + 0x3622AC47, 0x28FEC306, 0x0B9A72C5, 0x15461D84, 0x4D531143, 0x538F7E02, 0x70EBCFC1, 0x6E37A080, + 0x33DB4D1E, 0x2D07225F, 0x0E63939C, 0x10BFFCDD, 0x48AAF01A, 0x56769F5B, 0x75122E98, 0x6BCE41D9, + 0xC5383716, 0xDBE45857, 0xF880E994, 0xE65C86D5, 0xBE498A12, 0xA095E553, 0x83F15490, 0x9D2D3BD1, + 0x38288FAC, 0x26F4E0ED, 0x0590512E, 0x1B4C3E6F, 0x435932A8, 0x5D855DE9, 0x7EE1EC2A, 0x603D836B, + 0xCECBF5A4, 0xD0179AE5, 0xF3732B26, 0xEDAF4467, 0xB5BA48A0, 0xAB6627E1, 0x88029622, 0x96DEF963, + 0xCB3214FD, 0xD5EE7BBC, 0xF68ACA7F, 0xE856A53E, 0xB043A9F9, 0xAE9FC6B8, 0x8DFB777B, 0x9327183A, + 0x3DD16EF5, 0x230D01B4, 0x0069B077, 0x1EB5DF36, 0x46A0D3F1, 0x587CBCB0, 0x7B180D73, 0x65C46232, + 0x2FCF0AC8, 0x31136589, 0x1277D44A, 0x0CABBB0B, 0x54BEB7CC, 0x4A62D88D, 0x6906694E, 0x77DA060F, + 0xD92C70C0, 0xC7F01F81, 0xE494AE42, 0xFA48C103, 0xA25DCDC4, 0xBC81A285, 0x9FE51346, 0x81397C07, + 0xDCD59199, 0xC209FED8, 0xE16D4F1B, 0xFFB1205A, 0xA7A42C9D, 0xB97843DC, 0x9A1CF21F, 0x84C09D5E, + 0x2A36EB91, 0x34EA84D0, 0x178E3513, 0x09525A52, 0x51475695, 0x4F9B39D4, 0x6CFF8817, 0x7223E756, + 0xD726532B, 0xC9FA3C6A, 0xEA9E8DA9, 0xF442E2E8, 0xAC57EE2F, 0xB28B816E, 0x91EF30AD, 0x8F335FEC, + 0x21C52923, 0x3F194662, 0x1C7DF7A1, 0x02A198E0, 0x5AB49427, 0x4468FB66, 0x670C4AA5, 0x79D025E4, + 0x243CC87A, 0x3AE0A73B, 0x198416F8, 0x075879B9, 0x5F4D757E, 0x41911A3F, 0x62F5ABFC, 0x7C29C4BD, + 0xD2DFB272, 0xCC03DD33, 0xEF676CF0, 0xF1BB03B1, 0xA9AE0F76, 0xB7726037, 0x9416D1F4, 0x8ACABEB5, +}; + +/// CRC-16 look-up table. +const U16 CRC16_TABLE[] = +{ + 0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50a5, 0x60c6, 0x70e7, + 0x8108, 0x9129, 0xa14a, 0xb16b, 0xc18c, 0xd1ad, 0xe1ce, 0xf1ef, + 0x1231, 0x0210, 0x3273, 0x2252, 0x52b5, 0x4294, 0x72f7, 0x62d6, + 0x9339, 0x8318, 0xb37b, 0xa35a, 0xd3bd, 0xc39c, 0xf3ff, 0xe3de, + 0x2462, 0x3443, 0x0420, 0x1401, 0x64e6, 0x74c7, 0x44a4, 0x5485, + 0xa56a, 0xb54b, 0x8528, 0x9509, 0xe5ee, 0xf5cf, 0xc5ac, 0xd58d, + 0x3653, 0x2672, 0x1611, 0x0630, 0x76d7, 0x66f6, 0x5695, 0x46b4, + 0xb75b, 0xa77a, 0x9719, 0x8738, 0xf7df, 0xe7fe, 0xd79d, 0xc7bc, + 0x48c4, 0x58e5, 0x6886, 0x78a7, 0x0840, 0x1861, 0x2802, 0x3823, + 0xc9cc, 0xd9ed, 0xe98e, 0xf9af, 0x8948, 0x9969, 0xa90a, 0xb92b, + 0x5af5, 0x4ad4, 0x7ab7, 0x6a96, 0x1a71, 0x0a50, 0x3a33, 0x2a12, + 0xdbfd, 0xcbdc, 0xfbbf, 0xeb9e, 0x9b79, 0x8b58, 0xbb3b, 0xab1a, + 0x6ca6, 0x7c87, 0x4ce4, 0x5cc5, 0x2c22, 0x3c03, 0x0c60, 0x1c41, + 0xedae, 0xfd8f, 0xcdec, 0xddcd, 0xad2a, 0xbd0b, 0x8d68, 0x9d49, + 0x7e97, 0x6eb6, 0x5ed5, 0x4ef4, 0x3e13, 0x2e32, 0x1e51, 0x0e70, + 0xff9f, 0xefbe, 0xdfdd, 0xcffc, 0xbf1b, 0xaf3a, 0x9f59, 0x8f78, + 0x9188, 0x81a9, 0xb1ca, 0xa1eb, 0xd10c, 0xc12d, 0xf14e, 0xe16f, + 0x1080, 0x00a1, 0x30c2, 0x20e3, 0x5004, 0x4025, 0x7046, 0x6067, + 0x83b9, 0x9398, 0xa3fb, 0xb3da, 0xc33d, 0xd31c, 0xe37f, 0xf35e, + 0x02b1, 0x1290, 0x22f3, 0x32d2, 0x4235, 0x5214, 0x6277, 0x7256, + 0xb5ea, 0xa5cb, 0x95a8, 0x8589, 0xf56e, 0xe54f, 0xd52c, 0xc50d, + 0x34e2, 0x24c3, 0x14a0, 0x0481, 0x7466, 0x6447, 0x5424, 0x4405, + 0xa7db, 0xb7fa, 0x8799, 0x97b8, 0xe75f, 0xf77e, 0xc71d, 0xd73c, + 0x26d3, 0x36f2, 0x0691, 0x16b0, 0x6657, 0x7676, 0x4615, 0x5634, + 0xd94c, 0xc96d, 0xf90e, 0xe92f, 0x99c8, 0x89e9, 0xb98a, 0xa9ab, + 0x5844, 0x4865, 0x7806, 0x6827, 0x18c0, 0x08e1, 0x3882, 0x28a3, + 0xcb7d, 0xdb5c, 0xeb3f, 0xfb1e, 0x8bf9, 0x9bd8, 0xabbb, 0xbb9a, + 0x4a75, 0x5a54, 0x6a37, 0x7a16, 0x0af1, 0x1ad0, 0x2ab3, 0x3a92, + 0xfd2e, 0xed0f, 0xdd6c, 0xcd4d, 0xbdaa, 0xad8b, 0x9de8, 0x8dc9, + 0x7c26, 0x6c07, 0x5c64, 0x4c45, 0x3ca2, 0x2c83, 0x1ce0, 0x0cc1, + 0xef1f, 0xff3e, 0xcf5d, 0xdf7c, 0xaf9b, 0xbfba, 0x8fd9, 0x9ff8, + 0x6e17, 0x7e36, 0x4e55, 0x5e74, 0x2e93, 0x3eb2, 0x0ed1, 0x1ef0 +}; + +/// CRC-8 look-up table. +const U08 CRC8_TABLE[] = { + 0, 49, 98, 83, 196, 245, 166, 151, 185, 136, 219, 234, 125, 76, 31, 46, + 67, 114, 33, 16, 135, 182, 229, 212, 250, 203, 152, 169, 62, 15, 92, 109, + 134, 183, 228, 213, 66, 115, 32, 17, 63, 14, 93, 108, 251, 202, 153, 168, + 197, 244, 167, 150, 1, 48, 99, 82, 124, 77, 30, 47, 184, 137, 218, 235, + 61, 12, 95, 110, 249, 200, 155, 170, 132, 181, 230, 215, 64, 113, 34, 19, + 126, 79, 28, 45, 186, 139, 216, 233, 199, 246, 165, 148, 3, 50, 97, 80, + 187, 138, 217, 232, 127, 78, 29, 44, 2, 51, 96, 81, 198, 247, 164, 149, + 248, 201, 154, 171, 60, 13, 94, 111, 65, 112, 35, 18, 133, 180, 231, 214, + 122, 75, 24, 41, 190, 143, 220, 237, 195, 242, 161, 144, 7, 54, 101, 84, + 57, 8, 91, 106, 253, 204, 159, 174, 128, 177, 226, 211, 68, 117, 38, 23, + 252, 205, 158, 175, 56, 9, 90, 107, 69, 116, 39, 22, 129, 176, 227, 210, + 191, 142, 221, 236, 123, 74, 25, 40, 6, 55, 100, 85, 194, 243, 160, 145, + 71, 118, 37, 20, 131, 178, 225, 208, 254, 207, 156, 173, 58, 11, 88, 105, + 4, 53, 102, 87, 192, 241, 162, 147, 189, 140, 223, 238, 121, 72, 27, 42, + 193, 240, 163, 146, 5, 52, 103, 86, 120, 73, 26, 43, 188, 141, 222, 239, + 130, 179, 224, 209, 70, 119, 36, 21, 59, 10, 89, 104, 255, 206, 157, 172 +}; + +// variables for time windowed counts (counts # of instances in a specific window of time) +static BOOL timeWindowedCountsInitialized[ NUM_OF_TIME_WINDOWED_COUNTS ]; ///< Initialized flags for time windowed counts +static U32 timeWindowedCountsMaxCount[ NUM_OF_TIME_WINDOWED_COUNTS ]; ///< Max. counts for time windowed counts +static U32 timeWindowedCountsWindowMs[ NUM_OF_TIME_WINDOWED_COUNTS ]; ///< Time windows (in ms) for time windowed counts +static U32 timeWindowedCounts[ NUM_OF_TIME_WINDOWED_COUNTS ][ MAX_TIME_WINDOWED_COUNT ]; ///< Time stamps for instances for time windowed counts +static U32 timeWindowedCountIndexes[ NUM_OF_TIME_WINDOWED_COUNTS ]; ///< List indexes for time windowed counts +static U32 timeWindowedCountCounts[ NUM_OF_TIME_WINDOWED_COUNTS ]; ///< Current counts for time windowed counts +static SEMAPHORE_STATUS_T sempahoreStatus[ NUM_OF_SEMAPHORES ]; + +/*********************************************************************//** + * @brief + * The crc32 function calculates a 32-bit CRC for a given range of bytes + * in memory. Poly = 0x1EDC6F41. Not reflected. Initial value = 0x00000000. + * @details Inputs: CRC32_TABLE[] + * @details Outputs: none + * @param initialValue initial CRC seed value + * @param address pointer to start address of memory range to calculate CRC for + * @param len number of bytes in the memory range to calculate CRC for + * @return CRC as a U32 + *************************************************************************/ +U32 crc32( U32 const initialValue, const U08 *address, U32 len ) +{ + U32 crc = initialValue; + + while ( len-- > 0 ) + { + crc = ( crc << SHIFT_8_BITS_FOR_BYTE_SHIFT ) ^ CRC32_TABLE[ *address ^ ( crc >> SHIFT_24_BITS ) ]; + address++; + } + + return crc; +} + +/*********************************************************************//** + * @brief + * The crc16 function calculates a 16-bit CRC for a given range of bytes + * in memory. Poly = 0x1021. Not reflected. Initial value = 0xFFFF. + * @details Inputs: CRC16_TABLE[] + * @details Outputs: none + * @param address pointer to start address of memory range to calculate CRC for + * @param len number of bytes in the memory range to calculate CRC for + * @return CRC as a U16 + *************************************************************************/ +U16 crc16( const U08 *address, U32 len ) +{ + U16 crc = INITIAL_CRC16_VAL; + + while ( len-- > 0 ) + { + crc = ( crc << SHIFT_8_BITS_FOR_BYTE_SHIFT ) ^ CRC16_TABLE[ *address ^ ( ( crc >> SHIFT_8_BITS_FOR_BYTE_SHIFT ) & MASK_OFF_MSB ) ]; + address++; + } + + return crc; +} + +/*********************************************************************//** + * @brief + * The crc8 function calculates a 8-bit CRC for a given range of bytes + * in memory. + * @details Inputs: CRC8_TABLE[] + * @details Outputs: none + * @param address pointer to start address of memory range to calculate CRC for + * @param len number of bytes in the memory range to calculate CRC for + * @return CRC as a U08 + *************************************************************************/ +U08 crc8( const U08 *address, U32 len ) +{ + U08 crc = INITIAL_CRC08_VAL; + + while ( len-- > 0 ) + { + crc = CRC8_TABLE[ (*address) ^ crc ]; + address++; + } + + return crc; +} + +/*********************************************************************//** + * @brief + * The crc4 function calculates a 4-bit CRC for a given range of bytes + * in memory. + * @details Inputs: none + * @details Outputs: none + * @param buffer pointer to start address of memory range to calculate CRC for + * @param byteCount number of bytes in the memory range to calculate CRC for + * @return CRC as a U08 + *************************************************************************/ +U08 crc4( U16* buffer, U32 byteCount ) +{ + U32 count; + U08 nBit; + U32 nRem = 0; + + for ( count = 0; count < byteCount; count++ ) + { + if ( 1 == ( count % 2 ) ) + { + nRem ^= (U16)( buffer[ count >> 1 ] & MASK_OFF_MSB ); + } + else + { + nRem ^= (U16)( buffer[ count >> 1 ] >> SHIFT_8_BITS_FOR_BYTE_SHIFT ); + } + + for ( nBit = SHIFT_8_BITS_FOR_BYTE_SHIFT; nBit > 0; nBit-- ) + { + if ( nRem & 0x8000 ) + { + nRem = ( nRem << 1 ) ^ 0x3000; + } + else + { + nRem = ( nRem << 1 ); + } + } + } + + nRem = ( 0x000F & ( nRem >> 12 ) ); + + return ( nRem ^ 0x00 ); +} + +/*********************************************************************//** + * @brief + * The u32DiffWithWrap function calculates the difference between two given + * unsigned 32-bit numbers. If the second (ending) number is less than the + * first (starting) number, then the difference is calculated with a wrap past + * 32-bit full scale to zero. + * @details Inputs: none + * @details Outputs: none + * @param start first number to compute difference for + * @param end second number to compute difference for + * @return the difference between the two given numbers + *************************************************************************/ +U32 u32DiffWithWrap( U32 start, U32 end ) +{ + U32 result = ( end >= start ? end - start : ( HEX_32_BIT_FULL_SCALE - start ) + end + 1 ); + + return result; +} + +/*********************************************************************//** + * @brief + * The u16BiDiffWithWrap function calculates the difference between two given + * unsigned 16-bit numbers. This version of function returns a signed value + * to allow for a negative difference. + * @details Inputs: none + * @details Outputs: none + * @param start first number to compute difference for + * @param end second number to compute difference for + * @return the difference between the two given numbers + *************************************************************************/ +S32 u32BiDiffWithWrap( U32 start, U32 end ) +{ + S32 result; + + U32 incDelta = ( end >= start ? end - start : ( HEX_32_BIT_FULL_SCALE - start ) + end + 1 ); + U32 decDelta = HEX_32_BIT_FULL_SCALE - incDelta + 1; + + if ( incDelta < decDelta ) + { + result = (S32)incDelta; + } + else + { + result = (S32)decDelta * -1; + } + + return result; +} + +/*********************************************************************//** + * @brief + * The u16DiffWithWrap function calculates the difference between two given + * unsigned 16-bit numbers. If the second (ending) number is less than the + * first (starting) number, then the difference is calculated with a wrap past + * 16-bit full scale to zero. + * @details Inputs: none + * @details Outputs: none + * @param start first number to compute difference for + * @param end second number to compute difference for + * @return the difference between the two given numbers + *************************************************************************/ +U16 u16DiffWithWrap( U16 start, U16 end ) +{ + U16 result = ( end >= start ? end - start : ( HEX_64_K - start ) + end ); + + return result; +} + +/*********************************************************************//** + * @brief + * The u16BiDiffWithWrap function calculates the difference between two given + * unsigned 16-bit numbers. This version of function returns a signed value + * to allow for a negative difference. + * @details Inputs: none + * @details Outputs: none + * @param start first number to compute difference for + * @param end second number to compute difference for + * @return the difference between the two given numbers + *************************************************************************/ +S16 u16BiDiffWithWrap( U16 start, U16 end ) +{ + S16 result; + + U16 incDelta = ( end >= start ? end - start : ( HEX_64_K - start ) + end ); + U16 decDelta = HEX_64_K - incDelta; + + if ( incDelta < decDelta ) + { + result = (S16)incDelta; + } + else + { + result = (S16)decDelta * -1; + } + + return result; +} + +/*********************************************************************//** + * @brief + * The initTimeWindowedCount function initializes a given time windowed count. + * @details Inputs: timeWindowedCountsMaxCount, timeWindowedCountsInitialized + * @details Outputs: timeWindowedCountsMaxCount, timeWindowedCountsInitialized, alarm if + * software fault occurred + * @param cnt ID of the time windowed count to initialize + * @param maxCnt maximum number of instances in the time window for this count + * @param winMs number of ms in the time window for this count + * @return none + *************************************************************************/ +void initTimeWindowedCount( TIME_WINDOWED_COUNT_T cnt, U32 maxCnt, U32 winMs ) +{ + if ( ( cnt < NUM_OF_TIME_WINDOWED_COUNTS ) && ( maxCnt <= MAX_TIME_WINDOWED_COUNT ) ) + { + U32 i; + + // initialize a time windowed count + timeWindowedCountsMaxCount[ cnt ] = maxCnt; + timeWindowedCountsWindowMs[ cnt ] = winMs; + timeWindowedCountIndexes[ cnt ] = 0; + timeWindowedCountCounts[ cnt ] = 0; + for ( i = 0; i < MAX_TIME_WINDOWED_COUNT; i++ ) + { + timeWindowedCounts[ cnt ][ i ] = 0; + } + timeWindowedCountsInitialized[ cnt ] = TRUE; + } + else + { + if ( cnt < NUM_OF_TIME_WINDOWED_COUNTS ) + { + timeWindowedCountsInitialized[ cnt ] = FALSE; +#ifdef _DD_ +// SET_ALARM_WITH_2_U32_DATA( ALARM_ID_DD_SOFTWARE_FAULT, SW_FAULT_ID_UTIL_INVALID_WIN_MAX_COUNT, maxCnt ) +#else +// SET_ALARM_WITH_2_U32_DATA( ALARM_ID_TD_SOFTWARE_FAULT, SW_FAULT_ID_UTIL_INVALID_WIN_MAX_COUNT, maxCnt ) +#endif + } + else + { +#ifdef _DD_ +// SET_ALARM_WITH_2_U32_DATA( ALARM_ID_DD_SOFTWARE_FAULT, SW_FAULT_ID_UTIL_INVALID_WIN_COUNT, cnt ) +#else +// SET_ALARM_WITH_2_U32_DATA( ALARM_ID_TD_SOFTWARE_FAULT, SW_FAULT_ID_UTIL_INVALID_WIN_COUNT, cnt ) +#endif + } + } +} + +/*********************************************************************//** + * @brief + * The incTimeWindowedCount function adds a new instance to a given time + * windowed count. Must call initTimeWindowedCount() prior to calling this + * function for a given time windowed count. + * *Note - thread protection not provided - assumed function will be called + * by one task for a given time windowed count. + * @details Inputs: timeWindowedCounts, timeWindowedCountIndexes, timeWindowedCountCounts + * @details Outputs: timeWindowedCounts, timeWindowedCountIndexes, timeWindowedCountCounts, + * alarm if a software fault occurred + * @param cnt ID of the time windowed count to add an instance to + * @return TRUE if this instances brings the count to the maximum within + * this counts time window, otherwise FALSE + *************************************************************************/ +BOOL incTimeWindowedCount( TIME_WINDOWED_COUNT_T cnt ) +{ + BOOL result = FALSE; + U32 timeInMS; + + if ( ( cnt < NUM_OF_TIME_WINDOWED_COUNTS ) && ( TRUE == timeWindowedCountsInitialized[ cnt ] ) ) + { + // Replace timestamp of oldest instance in list with this new one + timeWindowedCounts[ cnt ][ timeWindowedCountIndexes[ cnt ] ] = getMSTimerCount(); + // move index to next position in list (may wrap) + timeWindowedCountIndexes[ cnt ] = INC_WRAP( timeWindowedCountIndexes[ cnt ], 0, timeWindowedCountsMaxCount[ cnt ] - 1 ); + // update list count + timeWindowedCountCounts[ cnt ] = INC_CAP( timeWindowedCountCounts[ cnt ], timeWindowedCountsMaxCount[ cnt ] ); + // check if too many instances within time window + timeInMS = calcTimeSince( timeWindowedCounts[ cnt ][ timeWindowedCountIndexes[ cnt ] ] ); + if ( ( timeWindowedCountCounts[ cnt ] >= timeWindowedCountsMaxCount[ cnt ] ) && ( timeInMS <= timeWindowedCountsWindowMs[ cnt ] ) ) + { + result = TRUE; + } + } + else + { +#ifdef _DD_ +// SET_ALARM_WITH_2_U32_DATA ( ALARM_ID_DD_SOFTWARE_FAULT, SW_FAULT_ID_UTIL_TIME_WINDOWED_COUNT_ERROR, cnt ); +#else +// SET_ALARM_WITH_2_U32_DATA ( ALARM_ID_TD_SOFTWARE_FAULT, SW_FAULT_ID_UTIL_TIME_WINDOWED_COUNT_ERROR, cnt ); +#endif + } + + return result; +} + +/*********************************************************************//** + * @brief + * The getCriticalData function gets the value for a given critical data + * record. The integrity of the critical data is checked first. If the + * critical data record fails the integrity check, a fault is triggered. + * @details Inputs: none + * @details Outputs: alarm if HD critical error occurred + * @param data Ptr to a critical data record + * @return The data from a critical data record + *************************************************************************/ +CRITICAL_DATAS_T getCriticalData( CRITICAL_DATA_T *data ) +{ + CRITICAL_DATAS_T result; + CRITICAL_DATA_T d; + + _disable_IRQ(); + d = *data; + _enable_IRQ(); + + result = d.data; + // verify data integrity + if ( ( ~d.data.uInt != d.comp ) || + ( isCriticalDataInRange( &d ) != TRUE ) || + ( data->typ >= NUM_OF_CRITICAL_DATA_TYPES ) ) + { + result.uInt = 0; +#ifdef _DD_ + SET_ALARM_WITH_2_U32_DATA( ALARM_ID_DG_CRITICAL_DATA_ERROR, (U32)&data[0], 0 ) +#else + SET_ALARM_WITH_2_U32_DATA( ALARM_ID_HD_CRITICAL_DATA_ERROR, (U32)&data[0], 0 ) +#endif + } + + return result; +} + +/*********************************************************************//** + * @brief + * The isCriticalDataInRange function determines whether a critical data + * value is within the range set for that critical data. + * @details Inputs: none + * @details Outputs: none + * @param data Ptr to a critical data record + * @return TRUE if given data is in range, FALSE if not + *************************************************************************/ +BOOL isCriticalDataInRange( CRITICAL_DATA_T *data ) +{ + BOOL result = FALSE; + + if ( CRITICAL_DATA_TYPE_F32 == data->typ ) + { + if ( ( data->data.sFlt >= data->minimum.sFlt ) && ( data->data.sFlt <= data->maximum.sFlt ) ) + { + result = TRUE; + } + } + else if ( CRITICAL_DATA_TYPE_S32 == data->typ ) + { + if ( ( data->data.sInt >= data->minimum.sInt ) && ( data->data.sInt <= data->maximum.sInt ) ) + { + result = TRUE; + } + } + else + { + if ( ( data->data.uInt >= data->minimum.uInt ) && ( data->data.uInt <= data->maximum.uInt ) ) + { + result = TRUE; + } + } + + return result; +} + +/*********************************************************************//** + * @brief + * The setCriticalData function sets the value for a given critical data + * record. + * @details Inputs: none + * @details Outputs: alarm if HD critical error occurred + * @param data Ptr to a critical data record + * @param value a value to set + * @return TRUE if set was successful, FALSE if not (out of range) + *************************************************************************/ +BOOL setCriticalData( CRITICAL_DATA_T *data, CRITICAL_DATAS_T value ) +{ + BOOL result = FALSE; + + if ( data->typ < NUM_OF_CRITICAL_DATA_TYPES ) + { + CRITICAL_DATA_T tmp = *data; + + // test set on temporary data record so it can have its range pre-checked + tmp.data = value; + if ( TRUE == isCriticalDataInRange( &tmp ) ) + { + _disable_IRQ(); + data->data = value; + data->comp = ~data->data.uInt; + _enable_IRQ(); + result = TRUE; + } + } + else + { +#ifdef _DD_ + SET_ALARM_WITH_2_U32_DATA( ALARM_ID_DG_CRITICAL_DATA_ERROR, (U32)&data[0], 1 ) +#else + SET_ALARM_WITH_2_U32_DATA( ALARM_ID_HD_CRITICAL_DATA_ERROR, (U32)&data[0], 1 ) +#endif + } + + return result; +} + +/*********************************************************************//** + * @brief + * The resetCriticalData function resets a critical data record. + * @details Inputs: none + * @details Outputs: Given critical data record is reset to unset w/ default value. + * @param data Ptr to a critical data record + * @return none + *************************************************************************/ +void resetCriticalData( CRITICAL_DATA_T *data ) +{ + _disable_IRQ(); + data->data.uInt = data->defValue.uInt; + data->comp = ~data->data.uInt; + _enable_IRQ(); +} + +/*********************************************************************//** + * @brief + * The hexStrToDec function convert hex string to decimal value. + * @details Inputs: none + * @details Outputs: none + * @param valuePtr pointer to hex string to convert + * @param convValuePtr pointer to the provided buffer to write the converted + * values back + * @param size size of the hex string to convert + * @return TRUE if the characters were accepted, otherwise FALSE + *************************************************************************/ +BOOL hexStrToDec( U08 const * const valuePtr, U32* convValuePtr, U08 size ) +{ + U08 ii; + U08 value; + U32 result = 0; + BOOL status = TRUE; + + if ( size <= STR_TO_HEX_CONV_MAX_BYTES ) + { + // If the provided size is less than the maximum allowed, loop through the list for conversion + for ( ii = 0; ii < size; ++ii ) + { + value = valuePtr[ ii ]; + + switch( value ) + { + case ASCII_CODE_NUMBER_ZERO: + case ASCII_CODE_NUMBER_ONE: + case ASCII_CODE_NUMBER_TWO: + case ASCII_CODE_NUMBER_THREE: + case ASCII_CODE_NUMBER_FOUR: + case ASCII_CODE_NUMBER_FIVE: + case ASCII_CODE_NUMBER_SIX: + case ASCII_CODE_NUMBER_SEVEN: + case ASCII_CODE_NUMBER_EIGHT: + case ASCII_CODE_NUMBER_NINE: + // If the hex string is a number, subtract the number from hex zero to get a number + // Shift the results by a nibble and add the calculated number. + // For instance, if the value = 0x36 - 0x30 = the value becomes 6 + value = ( value - ASCII_CODE_NUMBER_ZERO ); + result = ( result << SHIFT_BITS_BY_4 ) | value; + break; + + case ASCII_CODE_LETTER_A: + case ASCII_CODE_LETTER_B: + case ASCII_CODE_LETTER_C: + case ASCII_CODE_LETTER_D: + case ASCII_CODE_LETTER_E: + case ASCII_CODE_LETTER_F: + // If the value is from A-F for the hex values, subtract the value from 0x37. + // This converts the letters from A to F to 10 to 15. + // For instance if the read value is 0x43 ( Hex C ) - 0x37 = 12 (decimal) + value = ( value - HEX_LETTER_TO_NUMBER_CONV ); + result = ( result << SHIFT_BITS_BY_4 ) | value; + break; + + default: + status = FALSE; + // Do nothing since the character is not accepted. + break; + } + } + + // Set the processed value to the provided buffer, but only if + // the conversion was successful + if (TRUE == status) + { + *convValuePtr = result; + } + } + + return status; +} + +/*********************************************************************//** + * @brief + * The initSemaphores function initializes the semaphores + * @details Inputs: none + * @details Outputs: sempahoreStatus + * @return none + *************************************************************************/ +void initSemaphores( void ) +{ + U08 i; + + for ( i = 0; i < NUM_OF_SEMAPHORES; i++ ) + { + memset( &sempahoreStatus[ i ], 0x0, sizeof( SEMAPHORE_STATUS_T ) ); + } +} + +/*********************************************************************//** + * @brief + * The getSemaphore function gets a semaphore for the requested semaphore. + * @details Inputs: none + * @details Outputs: sempahoreStatus + * @param s which is the semaphore to be taken + * @return TRUE if semaphore is available and now it is taken otherwise, FALSE + *************************************************************************/ +BOOL getSemaphore( SEMAPHORE_T s ) +{ + BOOL result = FALSE; + + _disable_IRQ(); + if ( FALSE == sempahoreStatus[ s ].isSemaphoreTaken ) + { + sempahoreStatus[ s ].semaphoreStartTimeMS = getMSTimerCount(); + sempahoreStatus[ s ].isSemaphoreTaken = TRUE; + result = TRUE; + } + else if ( TRUE == didTimeout( sempahoreStatus[ s ].semaphoreStartTimeMS, SEMAPHORE_IN_USE_TIMEOUT_MS ) ) + { +#ifdef _DD_ +// SET_ALARM_WITH_2_U32_DATA( ALARM_ID_DD_SOFTWARE_FAULT, SW_FAULT_ID_SEMAPHORE_IN_USE_TIMEOUT, (U32)s ) +#endif +#ifdef _TD_ +// SET_ALARM_WITH_2_U32_DATA( ALARM_ID_TD_SOFTWARE_FAULT, SW_FAULT_ID_SEMAPHORE_IN_USE_TIMEOUT, (U32)s ) +#endif + } + _enable_IRQ(); + + return result; +} + +/*********************************************************************//** + * @brief + * The releaseSemaphore function releases a semaphore that was previously taken + * for a job. + * @details Inputs: none + * @details Outputs: sempahoreStatus + * @param s which is the semaphore to be released + * @return none + *************************************************************************/ +void releaseSemaphore( SEMAPHORE_T s ) +{ + if ( TRUE == sempahoreStatus[ s ].isSemaphoreTaken ) + { + sempahoreStatus[ s ].isSemaphoreTaken = FALSE; + } +} + +/*********************************************************************//** + * @brief + * The isSemaphoreReleased function returns the status of a taken semaphore + * @details Inputs: none + * @details Outputs: sempahoreStatus + * @param s which is the semaphore to check + * @return status of the semaphore + *************************************************************************/ +BOOL isSemaphoreReleased( SEMAPHORE_T s ) +{ + return ( TRUE == sempahoreStatus[ s ].isSemaphoreTaken ? FALSE : TRUE ); +} + +/**@}*/ Index: Utilities.h =================================================================== diff -u --- Utilities.h (revision 0) +++ Utilities.h (revision 6d80d69a210f45c733e5307859351f2cd820a8e7) @@ -0,0 +1,120 @@ +/************************************************************************** +* +* Copyright (c) 2024-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 Utilities.h +* +* @author (last) Sean +* @date (last) 30-Jul-2024 +* +* @author (original) Sean +* @date (original) 30-Jul-2024 +* +***************************************************************************/ + +#ifndef __UTILITIES_H__ +#define __UTILITIES_H__ + +/** + * @defgroup Utilities Utilities + * @brief Utilities module contains various utility functions. + * + * @addtogroup Utilities + * @{ + */ + +// ********** public definitions ********** + +// ******* Time Windowed Count Definitions ********* +#define MAX_TIME_WINDOWED_COUNT 10 ///< Maximum number of counts that a time windowed count can count to + +/// Enumeration of time-windowed counts. +typedef enum TimeWindowedCounts +{ + TIME_WINDOWED_COUNT_BAD_MSG_CRC = 0, ///< Bad message CRC + TIME_WINDOWED_COUNT_CAN_WARNING, ///< CAN warning + TIME_WINDOWED_COUNT_CAN_OFF, ///< CAN off + TIME_WINDOWED_COUNT_CAN_PARITY, ///< CAN parity error + TIME_WINDOWED_COUNT_FPGA_CLOCK_SPEED_ERROR, ///< FPGA clock speed error +#ifdef _TD_ + TIME_WINDOWED_COUNT_BP_COMMUTATION_ERROR, ///< Blood pump commutation error + TIME_WINDOWED_COUNT_DIP_COMMUTATION_ERROR, ///< Dialysate inlet pump commutation error + TIME_WINDOWED_COUNT_DOP_COMMUTATION_ERROR, ///< Dialysate outlet pump commutation error + TIME_WINDOWED_COUNT_FPGA_COMM_FAILURES, ///< FPGA communication failure (NAK, CRC, timeout) + TIME_WINDOWED_COUNT_SYRINGE_PUMP_OFF_ERROR, ///< Syringe pump off movement error + TIME_WINDOWED_COUNT_BATT_COMM_ERROR, ///< Battery communication error +#endif +#ifdef _DD_ + TIME_WINDOWED_COUNT_FPGA_CONDUCTIVITY_SENSOR_ERROR, ///< FPGA Conductivity sensor error + TIME_WINDOWED_COUNT_FPGA_TEMPERATURE_SENSOR_ERROR, ///< FPGA Temperature sensor error + TIME_WINDOWED_COUNT_FPGA_COMM_FAILURES, ///< FPGA communication failure (NAK, CRC, timeout) + TIME_WINDOWED_COUNT_FPGA_DRAIN_PUMP_HALL_SENSOR_ERROR, ///< FPGA Drain pump hall sensor failure +#endif + NUM_OF_TIME_WINDOWED_COUNTS ///< Number of pressure sensors +} TIME_WINDOWED_COUNT_T; + +// ******* Critical Data Definitions ********* +/// Critical data types list. +typedef enum Critical_Data_Types +{ + CRITICAL_DATA_TYPE_U32 = 0, ///< Critical data is unsigned 32-bit integer type + CRITICAL_DATA_TYPE_S32, ///< Critical data is signed 32-bit integer type + CRITICAL_DATA_TYPE_F32, ///< Critical data is 32-bit floating point type + NUM_OF_CRITICAL_DATA_TYPES ///< Total number of critical data types +} CRITICAL_DATA_TYPES_T; + +/// Semaphore items +typedef enum Semaphores +{ + SEMAPHORE_RTC = 0, ///< Semaphore RTC + NUM_OF_SEMAPHORES, ///< Number of semaphores +} SEMAPHORE_T; + +/// Record structure for alarm data of any supported type. +typedef union +{ + U32 uInt; ///< critical data of unsigned integer type + S32 sInt; ///< critical data of signed integer type + F32 sFlt; ///< critical data of floating point type +} CRITICAL_DATAS_T; + +/// critical integer data structure. +typedef struct +{ + CRITICAL_DATA_TYPES_T typ; ///< Type of data + CRITICAL_DATAS_T minimum; ///< Minimum value for valid data + CRITICAL_DATAS_T maximum; ///< Maximum value for valid data + CRITICAL_DATAS_T defValue; ///< Default value + CRITICAL_DATAS_T data; ///< Data value + U32 comp; ///< One's compliment of value +} CRITICAL_DATA_T; + +// ********** public function prototypes ********** + +U32 crc32( U32 const initialValue, const U08 *address, U32 len ); +U16 crc16( const U08 *address, U32 len ); +U08 crc8( const U08 *address, U32 len ); +U08 crc4( U16* buffer, U32 byteCount ); +U32 u32DiffWithWrap( U32 start, U32 end ); +S32 u32BiDiffWithWrap( U32 start, U32 end ); +U16 u16DiffWithWrap( U16 start, U16 end ); +S16 u16BiDiffWithWrap( U16 start, U16 end ); +void initTimeWindowedCount( TIME_WINDOWED_COUNT_T cnt, U32 maxCnt, U32 winMs ); +BOOL incTimeWindowedCount( TIME_WINDOWED_COUNT_T cnt ); +CRITICAL_DATAS_T getCriticalData( CRITICAL_DATA_T *data ); +BOOL setCriticalData( CRITICAL_DATA_T *data, CRITICAL_DATAS_T value ); +BOOL isCriticalDataInRange( CRITICAL_DATA_T *data ); +void resetCriticalData( CRITICAL_DATA_T *data ); +BOOL hexStrToDec( U08 const * const valuePtr, U32* convValueAddress, U08 size ); + +void initSemaphores( void ); +BOOL getSemaphore( SEMAPHORE_T s ); +void releaseSemaphore( SEMAPHORE_T s ); +BOOL isSemaphoreReleased( SEMAPHORE_T s ); + +/**@}*/ + +#endif Index: WatchdogMgmt.c =================================================================== diff -u --- WatchdogMgmt.c (revision 0) +++ WatchdogMgmt.c (revision 6d80d69a210f45c733e5307859351f2cd820a8e7) @@ -0,0 +1,452 @@ +/************************************************************************** +* +* Copyright (c) 2024-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 WatchdogMgmt.c +* +* @author (last) Sean +* @date (last) 30-Jul-2024 +* +* @author (original) Sean +* @date (original) 30-Jul-2024 +* +***************************************************************************/ + +#ifdef _TD_ +//#include "CPLD.h" +#endif +//#include "FPGA.h" +//#include "InternalADC.h" +#include "Messaging.h" +#include "OperationModes.h" +#include "Timers.h" +#include "WatchdogMgmt.h" + +/** + * @addtogroup WatchdogMgmt + * @{ + */ + +// ********** private definitions ********** + +#define MIN_WATCHDOG_PET_INTERVAL_MS 45 ///< Minimum watchdog pet interval (in ms). +#define WATCHDOG_POST_TIMEOUT_MS 500 ///< Watchdog POST test timeout (in ms). +#define WATCHDOG_RECOVERY_TIME_MS 500 ///< After watchdog POST test, wait this long (in ms) before moving on. + +#define MAX_24V_LEVEL_ON_WATCHDOG_EXPIRED 5.0F ///< Maximum voltage on 24V line when watchdog is expired. // TODO - check w/ Systems. Takes time for V to bleed off. Had to raise to 5V. +#define MIN_24V_LEVEL_ON_WATCHDOG_RECOVER 22.6F ///< Minimum voltage on 24V line when watchdog is recovered. +#define MIN_BACKUP_ALARM_CURRENT_MA 200.0F ///< Minimum backup alarm audio current (in mA) detected when watchdog is expired. +#define MAX_BACKUP_ALARM_CURRENT_MA 10.0F ///< Maximum backup alarm audio current (in mA) detected when watchdog is recovered. + +#define MAX_SAFETY_SHUTDOWN_MISMATCH_MS 100 ///< Maximum time (in ms) that safety shutdown cmd vs. feedback can be mismatched. + +/// Enumeration of watchdog self-test states. +typedef enum Watchdog_Self_Test_States +{ + WATCHDOG_SELF_TEST_STATE_START = 0, ///< Watchdog self-test start state + WATCHDOG_SELF_TEST_STATE_IN_PROGRESS, ///< Watchdog self-test in progress state + WATCHDOG_SELF_TEST_STATE_RECOVER, ///< Watchdog self-test recovery state + WATCHDOG_SELF_TEST_STATE_COMPLETE, ///< Watchdog self-test completed state + NUM_OF_WATCHDOG_SELF_TEST_STATES ///< Number of watchdog self-test states +} WATCHDOG_SELF_TEST_STATE_T; + +// ********** private data ********** + +static U32 lastWatchdogPetTime; ///< Timestamp (ms counter) since last watchdog pet. +static OVERRIDE_U32_T watchdogTaskCheckedIn[ NUM_OF_TASKS ]; ///< Array of flags indicating whether individual tasks have checked in with watchdog manager. +static WATCHDOG_SELF_TEST_STATE_T watchdogSelfTestState; ///< Current watchdog self-test state. +static SELF_TEST_STATUS_T watchdogSelfTestStatus; ///< Watchdog self-test state status. +static U32 watchdogSelfTestTimerCount; ///< Watchdog self-test state timer counter. +static U32 safetyShutdownFeedbackMismatchTS; ///< Persistence timestamp for safety shutdown cmd vs. feedback mismatch. + +// ********** private function prototypes ********** + +static void resetWDTaskCheckIns( void ); +static BOOL haveAllTasksCheckedIn( void ); +static void petWatchdog( void ); +static BOOL hasTaskGeneralCheckedIn( U32 task ); + +/*********************************************************************//** + * @brief + * The initWatchdogMgmt function initializes the watchdog mgmt. module. + * @details Inputs: none + * @details Outputs: Watchdog mgmt. module initialized. + * @return none + *************************************************************************/ +void initWatchdogMgmt( void ) +{ + U32 i; + + lastWatchdogPetTime = 0; + watchdogSelfTestState = WATCHDOG_SELF_TEST_STATE_START; + watchdogSelfTestStatus = SELF_TEST_STATUS_IN_PROGRESS; + watchdogSelfTestTimerCount = 0; + safetyShutdownFeedbackMismatchTS = getMSTimerCount(); + + // Initialize task check-ins to false + for ( i = 0; i < NUM_OF_TASKS; i++ ) + { + watchdogTaskCheckedIn[ i ].data = FALSE; + watchdogTaskCheckedIn[ i ].ovData = FALSE; + watchdogTaskCheckedIn[ i ].ovInitData = FALSE; + watchdogTaskCheckedIn[ i ].override = OVERRIDE_RESET; + } +} + +/*********************************************************************//** + * @brief + * The execWatchdogMgmt function executes thewatchdog mgmt. service. + * @details Inputs: watchdogTaskCheckedIn[] + * @details Outputs: watchdogTaskCheckedIn[] + * @return none + *************************************************************************/ +void execWatchdogMgmt( void ) +{ + BOOL allTasksCheckedIn; +// PIN_SIGNAL_STATE_T safetyShutdownFeedbackSignal = getWatchdogExpired(); +// PIN_SIGNAL_STATE_T safetyShutdownSoftwareCmd = ( TRUE == isSafetyShutdownActivated() ? PIN_SIGNAL_LOW : PIN_SIGNAL_HIGH ); + + // Called by background task, so give bg task credit for checking in + checkInWithWatchdogMgmt( TASK_BG ); + + // Check to see if all monitored tasks have checked in + allTasksCheckedIn = haveAllTasksCheckedIn(); + + // If all monitored tasks checked in, pet watchdog and clear the slate + if ( ( TRUE == allTasksCheckedIn ) && ( TRUE == didTimeout( lastWatchdogPetTime, MIN_WATCHDOG_PET_INTERVAL_MS ) ) ) + { + petWatchdog(); + resetWDTaskCheckIns(); + } + // Check to see if watchdog has expired or safety shutdown feedback does not match s/w command (only after POST completed) +// if ( ( safetyShutdownSoftwareCmd != safetyShutdownFeedbackSignal ) && ( getCurrentOperationMode() != MODE_INIT ) ) +// { +// if ( ( PIN_SIGNAL_LOW == safetyShutdownFeedbackSignal ) || ( TRUE == didTimeout( safetyShutdownFeedbackMismatchTS, MAX_SAFETY_SHUTDOWN_MISMATCH_MS ) ) ) + { + /* DEBUG WARNING + * It may be necessary to comment out the following + * line to prevent the alarm from occurring while + * debugging. + */ +#ifdef _TD_ + activateAlarmNoData( ALARM_ID_TD_WATCHDOG_EXPIRED ); +#endif +#ifdef _DD_ + activateAlarmNoData( ALARM_ID_DD_WATCHDOG_EXPIRED ); +#endif +#ifdef _RO_ + //activateAlarmNoData( ALARM_ID_RO_WATCHDOG_EXPIRED ); +#endif + } +// } +// else +// { +// safetyShutdownFeedbackMismatchTS = getMSTimerCount(); +// } +} + +/*********************************************************************//** + * @brief + * The checkInWithWatchdogMgmt function checks a given task in with the + * watchdog mgmt. service. + * @details Inputs: none + * @details Outputs: task is checked in with the watchdog mgmt.. + * @param task the task that is checking in with the watchdog mgmt + * @return none + *************************************************************************/ +void checkInWithWatchdogMgmt( TASK_T task ) +{ + if ( task < NUM_OF_TASKS ) + { + watchdogTaskCheckedIn[ task ].data = TRUE; + } +} + +/*********************************************************************//** + * @brief + * The execWatchdogTest function executes the watchdog test. + * This function should be called periodically until a pass or fail + * result is returned. + * @details Inputs: watchdogSelfTestState + * @details Outputs: watchdogSelfTestState + * @return in progress, passed, or failed + *************************************************************************/ +SELF_TEST_STATUS_T execWatchdogTest( void ) +{ + SELF_TEST_STATUS_T result = SELF_TEST_STATUS_IN_PROGRESS; + + switch ( watchdogSelfTestState ) + { + case WATCHDOG_SELF_TEST_STATE_START: + watchdogSelfTestState = WATCHDOG_SELF_TEST_STATE_IN_PROGRESS; + watchdogSelfTestTimerCount = getMSTimerCount(); + // No break here so we pass through directly to in progress processing + + case WATCHDOG_SELF_TEST_STATE_IN_PROGRESS: + while ( FALSE == didTimeout( watchdogSelfTestTimerCount, WATCHDOG_POST_TIMEOUT_MS ) ) + { + // Waiting here for w.d. test period to prevent this task from checking in - watchdog should expire + } +// if ( PIN_SIGNAL_LOW == getWatchdogExpired() ) +// { +// F32 v24 = getIntADCVoltageConverted( INT_ADC_24V_ACTUATORS ); +// F32 audioCurrent = getFPGABackupAlarmAudioCurrent(); +// +// // Verify 24V is down when w.d. expired +// if ( v24 > MAX_24V_LEVEL_ON_WATCHDOG_EXPIRED ) +// { +// SET_ALARM_WITH_2_F32_DATA( ALARM_ID_HD_WATCHDOG_POST_TEST_FAILED, 2.0F, v24 ); +// watchdogSelfTestStatus = SELF_TEST_STATUS_FAILED; +// } +// // Verify backup alarm audio is on when w.d. expired +// else if ( audioCurrent < MIN_BACKUP_ALARM_CURRENT_MA ) +// { +//#ifndef _RELEASE_ +// if ( getSoftwareConfigStatus( SW_CONFIG_DISABLE_ALARM_AUDIO ) != SW_CONFIG_ENABLE_VALUE ) +//#endif +// { +// SET_ALARM_WITH_2_F32_DATA( ALARM_ID_HD_WATCHDOG_POST_TEST_FAILED, 3.0F, audioCurrent ); +// watchdogSelfTestStatus = SELF_TEST_STATUS_FAILED; +// } +// } +// } +// else +// { +// SET_ALARM_WITH_1_U32_DATA( ALARM_ID_HD_WATCHDOG_POST_TEST_FAILED, 1 ); +// watchdogSelfTestStatus = SELF_TEST_STATUS_FAILED; +// } +// watchdogSelfTestTimerCount = getMSTimerCount(); +// watchdogSelfTestState = WATCHDOG_SELF_TEST_STATE_RECOVER; + break; + + case WATCHDOG_SELF_TEST_STATE_RECOVER: + if ( TRUE == didTimeout( watchdogSelfTestTimerCount, WATCHDOG_RECOVERY_TIME_MS ) ) + { // Verify watchdog expired signal no longer active +// if ( PIN_SIGNAL_HIGH == getCPLDWatchdogExpired() ) +// { +// F32 v24 = getIntADCVoltageConverted( INT_ADC_24V_ACTUATORS ); +// F32 audioCurrent = getFPGABackupAlarmAudioCurrent(); +// +// // Verify 24V is down when w.d. recovered +// if ( v24 < MIN_24V_LEVEL_ON_WATCHDOG_RECOVER ) +// { +// SET_ALARM_WITH_2_F32_DATA( ALARM_ID_HD_WATCHDOG_POST_TEST_FAILED, 4.0F, v24 ); +// watchdogSelfTestStatus = SELF_TEST_STATUS_FAILED; +// } +// // Verify backup alarm audio is on when w.d. recovered +// else if ( audioCurrent > MAX_BACKUP_ALARM_CURRENT_MA ) +// { +//#ifndef _RELEASE_ +// if ( getSoftwareConfigStatus( SW_CONFIG_DISABLE_ALARM_AUDIO ) != SW_CONFIG_ENABLE_VALUE ) +//#endif +// { +// SET_ALARM_WITH_2_F32_DATA( ALARM_ID_HD_WATCHDOG_POST_TEST_FAILED, 5.0F, audioCurrent ); +// watchdogSelfTestStatus = SELF_TEST_STATUS_FAILED; +// } +// } +// else +// { +// watchdogSelfTestStatus = SELF_TEST_STATUS_PASSED; +// } +// } +// else +// { +// SET_ALARM_WITH_1_U32_DATA( ALARM_ID_HD_WATCHDOG_POST_TEST_FAILED, 6 ); +// watchdogSelfTestStatus = SELF_TEST_STATUS_FAILED; +// } +// result = watchdogSelfTestStatus; +// watchdogSelfTestState = WATCHDOG_SELF_TEST_STATE_COMPLETE; + } + break; + + case WATCHDOG_SELF_TEST_STATE_COMPLETE: + // If we get called in this state, assume we are doing self-test again + watchdogSelfTestStatus = SELF_TEST_STATUS_IN_PROGRESS; + watchdogSelfTestState = WATCHDOG_SELF_TEST_STATE_START; + break; + + default: + result = SELF_TEST_STATUS_FAILED; +// SET_ALARM_WITH_2_U32_DATA( ALARM_ID_TD_SOFTWARE_FAULT, SW_FAULT_ID_WATCHDOG_INVALID_SELF_TEST_STATE, watchdogSelfTestState ) + break; + } + + return result; +} + +/*********************************************************************//** + * @brief + * The resetWatchdogPOSTState function resets the watchdog POST state. + * @details Inputs: none + * @details Outputs: watchdogSelfTestState + * @return none + *************************************************************************/ +void resetWatchdogPOSTState( void ) +{ + watchdogSelfTestState = WATCHDOG_SELF_TEST_STATE_START; +} + +/*********************************************************************//** + * @brief + * The resetWDTaskCheckIns function resets the task check-ins with the watchdog. + * @details Inputs: none + * @details Outputs: watchdogTaskCheckedIn[] array reset to all false. + * @return none + *************************************************************************/ +static void resetWDTaskCheckIns( void ) +{ + U32 i; + + // Initialize task check-ins to false + for ( i = 0; i < NUM_OF_TASKS; i++ ) + { + watchdogTaskCheckedIn[ i ].data = FALSE; + } +} + +/*********************************************************************//** + * @brief + * The haveAllTasksCheckedIn function determines whether all tasks have + * checked in with watchdog mgmt. + * @details Inputs: watchdogTaskCheckedIn[] + * @details Outputs: none + * @return TRUE if all tasks have checked in since last watchdog pet, FALSE if not. + *************************************************************************/ +static BOOL haveAllTasksCheckedIn( void ) +{ + BOOL result = TRUE; + U32 i; + + // Check that each task has checked in + for ( i = 0; i < NUM_OF_TASKS; i++ ) + { + if ( FALSE == hasTaskGeneralCheckedIn( i ) ) + { + result = FALSE; + break; + } + } + + return result; +} + +/*********************************************************************//** + * @brief + * The hasTaskGeneralCheckedIn function gets the check-in state of a given + * task. + * @details Inputs: watchdogTaskCheckedIn[] + * @details Outputs: none + * @param task ID of task to check + * @return TRUE if given task has checked in, FALSE if not + *************************************************************************/ +BOOL hasTaskGeneralCheckedIn( U32 task ) +{ + BOOL result = FALSE; + + if ( task < NUM_OF_TASKS ) + { + if ( OVERRIDE_KEY == watchdogTaskCheckedIn[ task ].override ) + { + result = (BOOL)watchdogTaskCheckedIn[ task ].ovData; + } + else + { + result = (BOOL)watchdogTaskCheckedIn[ task ].data; + } + } + else + { +#ifdef _TD_ + //SET_ALARM_WITH_2_U32_DATA( ALARM_ID_TD_SOFTWARE_FAULT, TBD, task ) +#endif +#ifdef _DD_ + //SET_ALARM_WITH_2_U32_DATA( ALARM_ID_DD_SOFTWARE_FAULT, TBD, task ) +#endif +#ifdef _RO_ + //SET_ALARM_WITH_2_U32_DATA( ALARM_ID_RO_SOFTWARE_FAULT, TBD, task ) +#endif + } + + return result; +} + +/*********************************************************************//** + * @brief + * The petWatchdog function pets the watchdog by pulsing the CPLD WD pet + * signal. + * @details Inputs: none + * @details Outputs: CPLD WD pet signal is pulsed + * @return none + *************************************************************************/ +static void petWatchdog( void ) +{ + // Pulse the watchdog signal +// toggleCPLDWatchdog(); + + // Remember when we last pet the watchdog + lastWatchdogPetTime = getMSTimerCount(); +} + + +/************************************************************************* + * TEST SUPPORT FUNCTIONS + *************************************************************************/ + + +/*********************************************************************//** + * @brief + * The testSetWatchdogTaskCheckInOverride function overrides the state of the + * task check-in with the watchdog management with a given check-in state. + * @details Inputs: none + * @details Outputs: watchdogTaskCheckedIn[] + * @param task ID of task to override check-in state for + * @param value override state for the given task ID + * @return TRUE if override successful, FALSE if not + *************************************************************************/ +BOOL testSetWatchdogTaskCheckInOverride( U32 task, BOOL value ) +{ + BOOL result = FALSE; + + if ( task < NUM_OF_TASKS ) + { + if ( TRUE == isTestingActivated() ) + { + result = TRUE; + watchdogTaskCheckedIn[ task ].ovData = value; + watchdogTaskCheckedIn[ task ].override = OVERRIDE_KEY; + } + } + + return result; +} + +/*********************************************************************//** + * @brief + * The testResetWatchdogTaskCheckInOverride function resets the override of the + * state of the check-in with the watchdog management. + * @details Inputs: none + * @details Outputs: watchdogTaskCheckedIn[] + * @param task ID of task to override check-in state for + * @return TRUE if override reset successful, FALSE if not + *************************************************************************/ +BOOL testResetWatchdogTaskCheckInOverride( U32 task ) +{ + BOOL result = FALSE; + + if ( task < NUM_OF_TASKS ) + { + if ( TRUE == isTestingActivated() ) + { + result = TRUE; + watchdogTaskCheckedIn[ task ].override = OVERRIDE_RESET; + watchdogTaskCheckedIn[ task ].ovData = watchdogTaskCheckedIn[ task ].ovInitData; + } + } + + return result; +} + +/**@}*/ Index: WatchdogMgmt.h =================================================================== diff -u --- WatchdogMgmt.h (revision 0) +++ WatchdogMgmt.h (revision 6d80d69a210f45c733e5307859351f2cd820a8e7) @@ -0,0 +1,57 @@ +/************************************************************************** +* +* Copyright (c) 2024-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 WatchdogMgmt.h +* +* @author (last) Sean +* @date (last) 30-Jul-2024 +* +* @author (original) Sean +* @date (original) 30-Jul-2024 +* +***************************************************************************/ + +#ifndef __WATCHDOG_MGMT_H__ +#define __WATCHDOG_MGMT_H__ + +#include "../TDCommon.h" + +/** + * @defgroup WatchdogMgmt WatchdogMgmt + * @brief The watchdog management module provides functions for checking in + * with and petting the watchdog. + * + * @addtogroup WatchdogMgmt + * @{ + */ + +// ********** public definitions ********** + +/// Enumeration of tasks that must check in with the watchdog manager. +typedef enum Tasks +{ + TASK_BG = 0, ///< Background task + TASK_GENERAL, ///< General task + TASK_PRIORITY, ///< Priority task + TASK_TIMER, ///< Timer task + NUM_OF_TASKS ///< Number of tasks +} TASK_T; + +// ********** public function prototypes ********** + +void initWatchdogMgmt( void ); +void execWatchdogMgmt( void ); +void checkInWithWatchdogMgmt( TASK_T task ); +SELF_TEST_STATUS_T execWatchdogTest( void ); +void resetWatchdogPOSTState( void ); + +BOOL testSetWatchdogTaskCheckInOverride( U32 task, BOOL value ); +BOOL testResetWatchdogTaskCheckInOverride( U32 task ); + +/**@}*/ + +#endif Index: irqDispatch_a.asm =================================================================== diff -u --- irqDispatch_a.asm (revision 0) +++ irqDispatch_a.asm (revision 6d80d69a210f45c733e5307859351f2cd820a8e7) @@ -0,0 +1,74 @@ +;------------------------------------------------------------------------------- +; irqDispatch_a.asm +; +; (c) Texas Instruments 2009-2012, All rights reserved. +; + + ; Export Symbols + .def _irqDispatch + + ; Import Symbols + .ref C_irqDispatch + + ; The following should be placed in the .text section + .text + + ; Function: _irqDispatch + .align 4 + .armfunc _irqDispatch + + ; Use ARM mode assembly + .arm + + ; Note: This implementation is for ARMv7-R (Cortex-R4) in ARM mode only. + +_irqDispatch: .asmfunc + ; TI ASM Step 1: + SUB LR, LR, #4 ; construct the return address + SRSDB #31! ; Save LR_irq and SPSR_irq to System mode stack + + ; TI ASM Step 2: + CPS #31 ; Switch to System mode + + ; TI ASM Step 3: + PUSH {R0-R3, R12} ; Store AAPCS registers + + .if __TI_VFPV3D16_SUPPORT__ = 1 ; If VFPV3D16 is used + FMRX R12, FPSCR + STMFD SP!, {R12} + FMRX R12, FPEXC + STMFD SP!, {R12} + FSTMDBD SP!, {D0-D7} + .endif + + ; TI ASM Step 4 + ; Align stack to a 64 Bit boundary + AND R3, SP, #4 ; Calculate Stack adjustment to 64bit boundary + SUB SP, SP, R3 ; Adjust System Stack + PUSH {R3, LR} ; Put Stack adjustment and System Mode LR on Stack + + ; TI ASM Step 5 + BL C_irqDispatch ; Call Second Level IRQ Dispatcher C routine + + ; TI ASM Step 6 + ; Undo stack alignment + POP {R3, LR} ; Get Stack adjustment and System Mode LR from Stack + ADD SP, SP, R3 ; Undo System Stack adjustment + + ; TI ASM Step 7 + .if __TI_VFPV3D16_SUPPORT__ = 1 ; If VFPV3D16 is used + FLDMIAD SP!, {D0-D7} + LDMFD SP!, {R12} + FMXR FPEXC, R12 + LDMFD SP!, {R12} + FMXR FPSCR, R12 + .endif + + POP {R0-R3, R12} ; Restore AAPCS registers + + ; TI ASM Step 7 + RFEIA SP! ; Return using RFE from System mode stack + .endasmfunc + + .end +;------------------------------------------------------------------------------- Index: irqDispatch_c.c =================================================================== diff -u --- irqDispatch_c.c (revision 0) +++ irqDispatch_c.c (revision 6d80d69a210f45c733e5307859351f2cd820a8e7) @@ -0,0 +1,223 @@ +/************************************************************************** +* +* Copyright (c) 2020-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 irqDispatch_c.c +* +* @author (last) Sean Nash +* @date (last) 15-Jun-2020 +* +* @author (original) Sean +* @date (original) 17-Feb-2020 +* +***************************************************************************/ + +#if defined(__TI_VIM_128CH__) +#include "sys_common.h" +#include "sys_vim.h" +#elif defined(__TI_VIM_96CH__) +#include "sys_common.h" +#include "sys_vim.h" +#else +#error File irqDispatcher.c requires either __TI_VIM_96CH__ or __TI_VIM_128CH__ to be defined. +#endif + + +/** @typedef vimRAM_t + * @brief Vim Ram Definition + * + * This type is used to access the VIM RAM. + */ + +typedef volatile struct vimRam +{ + t_isrFuncPTR ISR[VIM_CHANNELS + 1]; +} vimRAM_t; + + +/** @var vimRAM_t * const vimRAM + * @brief vimRAM definition + * + * This variable is used to access the VIM RAM. + */ + +static const vimRAM_t * const vimRAM = ((vimRAM_t *)0xFFF82000U); + + +/** @var sint32 s32NestingLevel; + * @brief Variable to store the current level of nesting + * + */ + +static sint32 s32NestingLevel = 0; + + +/** @def MAX_NESTING_LEVEL + * @brief Defines max nesting deep + * + */ + +#define MAX_NESTING_LEVEL 12 + + +/** @fn void C_irqDispatch(void) + * @brief Second Level IRQ Dispatcher C routine + * @note This implementation is limited to the use of the first 96 interrupt priority's. + * + */ + +/* Ensure that the function is coded with ARM mode instructions. */ +#pragma CODE_STATE(C_irqDispatch, 32); +/* Inform the Compiler that the function is called externally, and thus should not be removed. */ +#pragma FUNC_EXT_CALLED(C_irqDispatch); +void C_irqDispatch(void) +{ + /* TI C Step 1 */ + uint32 u32IrqIndex = vimREG->IRQINDEX; /* Read IRQ Index Offset Vector */ + + /* TI C Step 2 */ + t_isrFuncPTR irq_func_pnt = vimRAM->ISR[u32IrqIndex]; /* Read IRQ Interrupt Vector */ + /** Note: + * Do not use the IRQVECREG to readout the vector address, as this could change between Step 1 and 2. + * As an alternative you could read out the vector from the constant table which was used to initialize the VIM RAM. + * This method should be faster than reading the vector address from the VIM RAM, as Flash accesses are faster than peripheral accesses. + */ + + /* IRQIVEC is zero if no interrupt is pending */ + if (0U == u32IrqIndex) + { + /* Phantom Interrupt */ + + /** @todo + * Add custom fault handler, if necessary. + */ + + // while(1); + // TODO - understand why we might get here and decide what we want to do + } + else + { + /* Increment Nesting Level indicator */ + s32NestingLevel++; + + /* If Nesting Level indicator is less than the max level, enable IRQ to allow further preemption */ + if ((MAX_NESTING_LEVEL) > s32NestingLevel) + { + /* TI C Step 3 */ + /* Save VIM REQENASET[0,1,2] Registers for later restore */ + uint32 SaveREQMASKSET0 = vimREG->REQMASKSET0; + uint32 SaveREQMASKSET1 = vimREG->REQMASKSET1; + uint32 SaveREQMASKSET2 = vimREG->REQMASKSET2; +#if defined(__TI_VIM_128CH__) + uint32 SaveREQMASKSET3 = vimREG->REQMASKSET3; +#endif + + /* TI C Step 4 */ + /* Mask out lower priority IRQ's and the current IRQ itself, keep FIQ's enabled */ + if (96U < u32IrqIndex) /* 96-...*/ + { +#if defined(__TI_VIM_128CH__) + /* REG->REQMASKCLR0 = ( 0xFFFFFFFCU & (~vimREG->FIRQPR0)); Higher priority */ + /* REG->REQMASKCLR1 = ( 0xFFFFFFFFU & (~vimREG->FIRQPR1)); Higher priority */ + /* REG->REQMASKCLR2 = ( 0xFFFFFFFFU & (~vimREG->FIRQPR2)); Higher priority */ + vimREG->REQMASKCLR3 = ((0xFFFFFFFFU << (u32IrqIndex - 97U)) & (~vimREG->FIRQPR3)); + vimREG->REQMASKCLR3; /* Readback Mask to ensure that the previous write was finished before enabling interrupts again */ +#elif defined(__TI_VIM_96CH__) + /** @todo + * Add custom fault handler, if necessary. + */ + while (1); /* Fault */ +#else +#error File irqDispatcher.c requires either __TI_VIM_96CH__ or __TI_VIM_128CH__ to be defined. +#endif + } + else if (64U < u32IrqIndex) /* 64-96 */ + { + /* REG->REQMASKCLR0 = ( 0xFFFFFFFCU & (~vimREG->FIRQPR0)); Higher priority */ + /* REG->REQMASKCLR1 = ( 0xFFFFFFFFU & (~vimREG->FIRQPR1)); Higher priority */ + vimREG->REQMASKCLR2 = ((0xFFFFFFFFU << (u32IrqIndex - 65U)) & (~vimREG->FIRQPR2)); +#if defined(__TI_VIM_128CH__) + vimREG->REQMASKCLR3 = ( 0xFFFFFFFFU & (~vimREG->FIRQPR3)); + vimREG->REQMASKCLR3; /* Readback Mask to ensure that the previous write was finished before enabling interrupts again */ +#elif defined(__TI_VIM_96CH__) + vimREG->REQMASKCLR2; /* Readback Mask to ensure that the previous write was finished before enabling interrupts again */ +#else +#error File irqDispatcher.c requires either __TI_VIM_96CH__ or __TI_VIM_128CH__ to be defined. +#endif + } + else if (32U < u32IrqIndex) /* 32-63 */ + { + /* REG->REQMASKCLR0 = ( 0xFFFFFFFCU & (~vimREG->FIRQPR0)); Higher priority */ + vimREG->REQMASKCLR1 = ((0xFFFFFFFFU << (u32IrqIndex - 33U)) & (~vimREG->FIRQPR1)); + vimREG->REQMASKCLR2 = ( 0xFFFFFFFFU & (~vimREG->FIRQPR2)); +#if defined(__TI_VIM_128CH__) + vimREG->REQMASKCLR3 = ( 0xFFFFFFFFU & (~vimREG->FIRQPR3)); + vimREG->REQMASKCLR3; /* Readback Mask to ensure that the previous write was finished before enabling interrupts again */ +#elif defined(__TI_VIM_96CH__) + vimREG->REQMASKCLR2; /* Readback Mask to ensure that the previous write was finished before enabling interrupts again */ +#else +#error File irqDispatcher.c requires either __TI_VIM_96CH__ or __TI_VIM_128CH__ to be defined. +#endif + } + else if ( 2U < u32IrqIndex) /* 2-31 */ + { + + vimREG->REQMASKCLR0 = ((0xFFFFFFFFU << (u32IrqIndex - 1U)) & (~vimREG->FIRQPR0)); + vimREG->REQMASKCLR1 = ( 0xFFFFFFFFU & (~vimREG->FIRQPR1)); + vimREG->REQMASKCLR2 = ( 0xFFFFFFFFU & (~vimREG->FIRQPR2)); +#if defined(__TI_VIM_128CH__) + vimREG->REQMASKCLR3 = ( 0xFFFFFFFFU & (~vimREG->FIRQPR3)); + vimREG->REQMASKCLR3; /* Readback Mask to ensure that the previous write was finished before enabling interrupts again */ +#elif defined(__TI_VIM_96CH__) + vimREG->REQMASKCLR2; /* Readback Mask to ensure that the previous write was finished before enabling interrupts again */ +#else +#error File irqDispatcher.c requires either __TI_VIM_96CH__ or __TI_VIM_128CH__ to be defined. +#endif + } + else /* if (0U < u32IrqIndex) */ /* 0 and 1 */ + { + /* Vectors 0 and 1 are tied to FIQ and this code is thus dead for IRQ. */ + + /** @todo + * Add custom fault handler, if necessary. + */ + + while (1); /* Fault */ + } + + /* TI C Step 5 */ + _enable_IRQ(); /* Enable IRQ, to allow preemption of IRQ routine */ + + /* TI C Step 6 */ + (*irq_func_pnt)(); /* Execute interrupt routine */ + + /* TI C Step 7 */ + _disable_IRQ(); /* Disable IRQ, to protect the remainder of the dispatcher from preemption */ + + /* TI C Step 8 */ + /* Restore VIM REQENASET[0,1,2] Registers */ + vimREG->REQMASKSET0 = SaveREQMASKSET0; + vimREG->REQMASKSET1 = SaveREQMASKSET1; + vimREG->REQMASKSET2 = SaveREQMASKSET2; +#if defined(__TI_VIM_128CH__) + vimREG->REQMASKSET3 = SaveREQMASKSET3; +#endif + } + else + { + /* Do not enable IRQ, because max nesting level was reached */ + (*irq_func_pnt)(); /* Execute interrupt routine */ + } + + if (0 < s32NestingLevel) + { + s32NestingLevel--; + } + } + + /* TI C Step 9 */ + return; /* Return to First Level IRQ Dispatcher Assembly routine */ +}