Index: firmware/App/Controllers/BoostPump.c =================================================================== diff -u -r9a14f69c0f0de343b5664b20753142b50bc4e093 -r1fa38184526c2b0c072eb8745c653f772156a824 --- firmware/App/Controllers/BoostPump.c (.../BoostPump.c) (revision 9a14f69c0f0de343b5664b20753142b50bc4e093) +++ firmware/App/Controllers/BoostPump.c (.../BoostPump.c) (revision 1fa38184526c2b0c072eb8745c653f772156a824) @@ -18,7 +18,7 @@ #include "BoostPump.h" #include "Flow.h" #include "FPOperationModes.h" -//#include "NVMgmtDD.h" +//#include "NVMgmt.h" #include "Messaging.h" #include "MessageSupport.h" #include "PersistentAlarm.h" Index: firmware/App/Controllers/ConcentratePumps.h =================================================================== diff -u -r9a14f69c0f0de343b5664b20753142b50bc4e093 -r1fa38184526c2b0c072eb8745c653f772156a824 --- firmware/App/Controllers/ConcentratePumps.h (.../ConcentratePumps.h) (revision 9a14f69c0f0de343b5664b20753142b50bc4e093) +++ firmware/App/Controllers/ConcentratePumps.h (.../ConcentratePumps.h) (revision 1fa38184526c2b0c072eb8745c653f772156a824) @@ -19,7 +19,7 @@ #define __CONCENTRATE_PUMPS_H__ #include "DDCommon.h" -//#include "NVMgmtDD.h" +//#include "NVMgmt.h" /** * @defgroup ConcentratePumps ConcentratePumps Index: firmware/App/Controllers/DialysatePumps.c =================================================================== diff -u -r6d1ea33dbe56d63b13802cacd09c263a5ee7e6e0 -r1fa38184526c2b0c072eb8745c653f772156a824 --- firmware/App/Controllers/DialysatePumps.c (.../DialysatePumps.c) (revision 6d1ea33dbe56d63b13802cacd09c263a5ee7e6e0) +++ firmware/App/Controllers/DialysatePumps.c (.../DialysatePumps.c) (revision 1fa38184526c2b0c072eb8745c653f772156a824) @@ -22,7 +22,7 @@ #include "FpgaDD.h" #include "MessageSupport.h" #include "Messaging.h" -//#include "NVMgmtDD.h" +//#include "NVMgmt.h" #include "OperationModes.h" #include "PersistentAlarm.h" #include "PIControllers.h" Index: firmware/App/Controllers/Heaters.c =================================================================== diff -u -r9a14f69c0f0de343b5664b20753142b50bc4e093 -r1fa38184526c2b0c072eb8745c653f772156a824 --- firmware/App/Controllers/Heaters.c (.../Heaters.c) (revision 9a14f69c0f0de343b5664b20753142b50bc4e093) +++ firmware/App/Controllers/Heaters.c (.../Heaters.c) (revision 1fa38184526c2b0c072eb8745c653f772156a824) @@ -23,7 +23,7 @@ #include "Level.h" #include "MessageSupport.h" #include "Messaging.h" -//#include "NVMgmtDD.h" +//#include "NVMgmt.h" #include "OperationModes.h" #include "PersistentAlarm.h" #include "PIControllers.h" Index: firmware/App/Controllers/ROPump.c =================================================================== diff -u -r9a14f69c0f0de343b5664b20753142b50bc4e093 -r1fa38184526c2b0c072eb8745c653f772156a824 --- firmware/App/Controllers/ROPump.c (.../ROPump.c) (revision 9a14f69c0f0de343b5664b20753142b50bc4e093) +++ firmware/App/Controllers/ROPump.c (.../ROPump.c) (revision 1fa38184526c2b0c072eb8745c653f772156a824) @@ -18,7 +18,7 @@ #include "Flow.h" #include "FPOperationModes.h" -//#include "NVMgmtDD.h" +//#include "NVMgmt.h" #include "Messaging.h" #include "MessageSupport.h" #include "PersistentAlarm.h" Fisheye: Tag 1fa38184526c2b0c072eb8745c653f772156a824 refers to a dead (removed) revision in file `firmware/App/Drivers/NVDriver.c'. Fisheye: No comparison available. Pass `N' to diff? Fisheye: Tag 1fa38184526c2b0c072eb8745c653f772156a824 refers to a dead (removed) revision in file `firmware/App/Drivers/NVDriver.h'. Fisheye: No comparison available. Pass `N' to diff? Index: firmware/App/Drivers/TemperatureSensors.c =================================================================== diff -u -r9a14f69c0f0de343b5664b20753142b50bc4e093 -r1fa38184526c2b0c072eb8745c653f772156a824 --- firmware/App/Drivers/TemperatureSensors.c (.../TemperatureSensors.c) (revision 9a14f69c0f0de343b5664b20753142b50bc4e093) +++ firmware/App/Drivers/TemperatureSensors.c (.../TemperatureSensors.c) (revision 1fa38184526c2b0c072eb8745c653f772156a824) @@ -20,7 +20,7 @@ #include "FpgaDD.h" #include "MessageSupport.h" #include "Messaging.h" -//#include "NVMgmtDD.h" +//#include "NVMgmt.h" #include "OperationModes.h" #include "PersistentAlarm.h" #include "TemperatureSensors.h" Index: firmware/App/Drivers/TemperatureSensors.h =================================================================== diff -u -r9a14f69c0f0de343b5664b20753142b50bc4e093 -r1fa38184526c2b0c072eb8745c653f772156a824 --- firmware/App/Drivers/TemperatureSensors.h (.../TemperatureSensors.h) (revision 9a14f69c0f0de343b5664b20753142b50bc4e093) +++ firmware/App/Drivers/TemperatureSensors.h (.../TemperatureSensors.h) (revision 1fa38184526c2b0c072eb8745c653f772156a824) @@ -19,7 +19,7 @@ #define __TEMPERATURE_SENSORS_H__ #include "DDCommon.h" -//#include "NVMgmtDD.h" +//#include "NVMgmt.h" /** * @defgroup TemperatureSensors TemperatureSensors Index: firmware/App/Modes/ModeInitPOST.c =================================================================== diff -u -r6d1ea33dbe56d63b13802cacd09c263a5ee7e6e0 -r1fa38184526c2b0c072eb8745c653f772156a824 --- firmware/App/Modes/ModeInitPOST.c (.../ModeInitPOST.c) (revision 6d1ea33dbe56d63b13802cacd09c263a5ee7e6e0) +++ firmware/App/Modes/ModeInitPOST.c (.../ModeInitPOST.c) (revision 1fa38184526c2b0c072eb8745c653f772156a824) @@ -15,6 +15,7 @@ * ***************************************************************************/ +#include #include "reg_crc.h" // Used to hold reset reason code at startup before bits get cleared #include "reg_system.h" // Used to access exception status registers for reset reason code at startup @@ -24,7 +25,6 @@ //#include "Integrity.h" #include "Messaging.h" #include "ModeInitPOST.h" -#include "NVMgmtDD.h" #include "OperationModes.h" #include "Pressure.h" #include "SafetyShutdown.h" Index: firmware/App/Modes/ModeStandby.c =================================================================== diff -u -r9a14f69c0f0de343b5664b20753142b50bc4e093 -r1fa38184526c2b0c072eb8745c653f772156a824 --- firmware/App/Modes/ModeStandby.c (.../ModeStandby.c) (revision 9a14f69c0f0de343b5664b20753142b50bc4e093) +++ firmware/App/Modes/ModeStandby.c (.../ModeStandby.c) (revision 1fa38184526c2b0c072eb8745c653f772156a824) @@ -25,7 +25,7 @@ #include "ModeGenDialysate.h" #include "MessageSupport.h" #include "Messaging.h" -//#include "NVMgmtDD.h" +//#include "NVMgmt.h" #include "OperationModes.h" #include "PermeateTank.h" #include "Pressure.h" Index: firmware/App/Services/Messaging.c =================================================================== diff -u -r6d1ea33dbe56d63b13802cacd09c263a5ee7e6e0 -r1fa38184526c2b0c072eb8745c653f772156a824 --- firmware/App/Services/Messaging.c (.../Messaging.c) (revision 6d1ea33dbe56d63b13802cacd09c263a5ee7e6e0) +++ firmware/App/Services/Messaging.c (.../Messaging.c) (revision 1fa38184526c2b0c072eb8745c653f772156a824) @@ -15,7 +15,6 @@ * ***************************************************************************/ - #include // for memcpy() #include "reg_system.h" @@ -47,7 +46,7 @@ #include "ModePreGenPermeateDefeatured.h" #include "ModePostGenDialysate.h" #include "ModeStandby.h" -#include "NVMessaging.h" +#include "NVMessagingDD.h" #include "OperationModes.h" #include "PAL.h" #include "PermeateTank.h" Fisheye: Tag 1fa38184526c2b0c072eb8745c653f772156a824 refers to a dead (removed) revision in file `firmware/App/Services/NVJobQ.c'. Fisheye: No comparison available. Pass `N' to diff? Fisheye: Tag 1fa38184526c2b0c072eb8745c653f772156a824 refers to a dead (removed) revision in file `firmware/App/Services/NVJobQ.h'. Fisheye: No comparison available. Pass `N' to diff? Fisheye: Tag 1fa38184526c2b0c072eb8745c653f772156a824 refers to a dead (removed) revision in file `firmware/App/Services/NVMessaging.c'. Fisheye: No comparison available. Pass `N' to diff? Fisheye: Tag 1fa38184526c2b0c072eb8745c653f772156a824 refers to a dead (removed) revision in file `firmware/App/Services/NVMessaging.h'. Fisheye: No comparison available. Pass `N' to diff? Index: firmware/App/Services/NVMessagingDD.c =================================================================== diff -u --- firmware/App/Services/NVMessagingDD.c (revision 0) +++ firmware/App/Services/NVMessagingDD.c (revision 1fa38184526c2b0c072eb8745c653f772156a824) @@ -0,0 +1,765 @@ +/************************************************************************** +* +* Copyright (c) 2026-2027 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 NVMessagingDD.c +* +* @author (original) Arpita Srivastava +* @date (original) 31-Mar-2026 +* +***************************************************************************/ + +#include // For ceilf function +#include "NVJobQ.h" +#include "NVMessagingDD.h" +#include "NVRecordsDD.h" +#include "OperationModes.h" +#include "TaskGeneral.h" +#include "Timers.h" +#include "Utilities.h" // For crc calculation + +/** + * @addtogroup NVMessagingDD + * @{ + */ + +// ********** private definitions ********** + +#define NEW_CAL_AVAILABLE_SIGNAL_TIMEOUT_MS (1 * MS_PER_SECOND) ///< New calibration available signal timeout in milliseconds. +#define NUM_OF_BYTES_PER_RECORD_PAYLOAD ( MAX_MSG_PAYLOAD_SIZE - ( sizeof( U32 ) * 3 ) ) ///< Number of bytes per calibration payload. +#define RECORD_DATA_SEND_INTERVAL_COUNT (MS_PER_SECOND / (5 * TASK_GENERAL_INTERVAL)) ///< Calibration data send time interval in counts. +#define RECORD_DATA_RECEIVE_TIMEOUT_MS (4 * MS_PER_SECOND) ///< Record data receive all the data packets timeout in ms. +#define RECORD_DATA_MAX_MESSAGE_DFFIRENCE 1 ///< Calibration data receive message different from the previous message. +#define RECORD_DATA_FIRST_RECEIVING_MSG_NUM 1 ///< Calibration data first receiving message number. + +/// NVM send records states +typedef enum NVM_Send_Records_States +{ + NVM_SEND_RECORD_STATE_IDLE = 0, ///< NVM process record idle state. + NVM_SEND_RECORD_STATE_SEND, ///< NVM process record send record state. + NUM_OF_NVM_SEND_RECORD_STATES ///< Number of NVM process records state. +} SEND_RECORD_STATE_T; + +/// NVM receive records states +typedef enum NVM_Receive_Records_States +{ + NVM_RECEIVE_RECORD_STATE_IDLE = 0, ///< NVM receive record idle. + NVM_RECEIVE_RECORD_STATE_RECEIVE, ///< NVM receive record receive. + NUM_OF_NVM_RECEIVE_RECORD_STATES ///< Number of NVM receive record. +} RECEIVE_RECORD_STATE_T; + +/// DD NVM Record Payload +typedef struct +{ + U32 payloadCurrNum; ///< Current Chunk number out of total number number of chunks + U32 payloadTotalNum; ///< Total number of chunks in which data is broken be sent + U32 length; ///< Length of data in the current chunk + U08 data[NUM_OF_BYTES_PER_RECORD_PAYLOAD]; ///< Data to be sent +} DD_NVM_SEND_RECORD_PAYLOAD_T; + +// ********** private data ********** + +static SEND_RECORD_STATE_T nvMExecSendRecordState; ///< NVM exec process record state. +static RECEIVE_RECORD_STATE_T nvmExecreceiveRecordState; ///< NVM exec receive record state. +static U32 newRecordStartTimer; ///< New record availability start timer. +static BOOL isNewCalRecordAvailable; ///< Signal to indicate whether a new NVM data is available. +static NVM_RECORD_TYPE_T recordToPublish; ///< Record type which is being processed currently for sending +static NVM_RECORD_TYPE_T nvPublishRecordType; ///< Used to index over isPublishRecordRequested in the idle state +static NVM_RECORD_TYPE_T currentRxRecordType; ///< Record type which is being processed currently for receiving +static U32 recordPublishMsgCount; ///< Record data publish message counter. +static U32 recordPublishTotalMsgs; ///< Record data total number of messages to be sent. +static U32 recordSendDataIntervalCounter; ///< Record data send to CAN bust interval counter. +static U32 previousRecordMessageNum; ///< Record previous message number. +static U32 recordUpdateAddress; ///< DD record update address for all the write operations. +static U32 recordReceiveStartTime; ///< Time stamp the calibration/service was received. +static BOOL isPublishRecordRequested[ NUM_OF_NVM_RECORD_TYPES ]; ///< Record state machine publish request flag. + +// ********** private function prototypes ********** + +// Process record functions +static SEND_RECORD_STATE_T handleExecSendRecordIdleState( void ); +static SEND_RECORD_STATE_T handleExecSendRecordSendState( void ); +static BOOL sendDDRecord( MSG_ID_T msgId, U32 payloadCurrNum, U32 payloadTotalNum, + U32 length, U08* calRcrdAddress ); +static BOOL receiveDDRecord( MESSAGE_T *message ); +static BOOL verifyAndSaveReceivedRecord( NVM_RECORD_TYPE_T job, U32 currentMessage, + U32 totalMessages, U32 length, U08 *addressPtr ); +static NVM_RECORD_TYPE_T getNVMRecordJobState( MSG_ID_T msgID ); +static MSG_ID_T getNVMRecordResponseMsgId (NVM_RECORD_TYPE_T job ); +static void monitorNewCalSignal( void ); + +/*********************************************************************//** + * @brief + * The initNVMessagingDD function initializes NV messaging related + * states and variables. It resets send and receive states, flags, + * counters, and timing values. + * @details \b Inputs: none + * @details \b Outputs: nvMExecSendRecordState, + * nvmExecreceiveRecordState, newRecordStartTimer, + * isNewCalRecordAvailable, nvPublishRecordType, + * isPublishRecordRequested, recordPublishMsgCount, + * recordPublishTotalMsgs, recordSendDataIntervalCounter, + * previousRecordMessageNum, recordReceiveStartTime + * @return none + *************************************************************************/ +void initNVMessagingDD( void ) +{ + nvMExecSendRecordState = NVM_SEND_RECORD_STATE_IDLE; + nvmExecreceiveRecordState = NVM_RECEIVE_RECORD_STATE_IDLE; + newRecordStartTimer = 0; + isNewCalRecordAvailable = FALSE; + nvPublishRecordType = NVM_SYSTEM_RECORD; + isPublishRecordRequested[ NVM_SYSTEM_RECORD ] = FALSE; + isPublishRecordRequested[ NVM_SERVICE_RECORD ] = FALSE; + isPublishRecordRequested[ NVM_CALIBRATION_RECORD ] = FALSE; + isPublishRecordRequested[ NVM_INSTITUTIONAL_RECORD ] = FALSE; + isPublishRecordRequested[ NVM_USAGE_INFO_RECORD ] = FALSE; + recordPublishMsgCount = 1; + recordPublishTotalMsgs = 1; + recordSendDataIntervalCounter = 0; + previousRecordMessageNum = 0; + recordReceiveStartTime = 0; +} + +/*********************************************************************//** + * @brief + * The execNVMPSendreceiveDDRecord function executes the NV record processing + * state machines. It handles send and receive operations and monitors + * for timeouts and calibration signals. + * @details \b Alarms: ALARM_ID_DD_SOFTWARE_FAULT if invalid send state + * @details \b Inputs: nvMExecSendRecordState, + * nvmExecreceiveRecordState, recordReceiveStartTime + * @details \b Outputs: nvMExecSendRecordState, + * nvmExecreceiveRecordState + * @return none + *************************************************************************/ +void execNVMPSendReceiveRecord( void ) +{ + switch ( nvMExecSendRecordState ) + { + case NVM_SEND_RECORD_STATE_IDLE: + nvMExecSendRecordState = handleExecSendRecordIdleState(); + break; + + case NVM_SEND_RECORD_STATE_SEND: + nvMExecSendRecordState = handleExecSendRecordSendState(); + break; + + default: + SET_ALARM_WITH_2_U32_DATA( ALARM_ID_DD_SOFTWARE_FAULT, SW_FAULT_ID_NVM_INVALID_EXEC_SEND_STATE, ( U32 )nvMExecSendRecordState ); + nvMExecSendRecordState = NVM_SEND_RECORD_STATE_IDLE; + break; + } + + // Check if the exec receive records is not idle + // This section checks the status of the asynchronous state machine that receives + // data from Dialin. + if ( nvmExecreceiveRecordState != NVM_RECEIVE_RECORD_STATE_IDLE ) + { + // Check if the data receiving process has timed out. The exec receive record + // state machine is asynchronous so it is checked in this state machine + if ( TRUE == didTimeout( recordReceiveStartTime, RECORD_DATA_RECEIVE_TIMEOUT_MS ) ) + { + // Exec receive state machine timed out. Schedule a read to update the structure + enqueueRecordJob( NVM_OPERATION_READ, currentRxRecordType ); + nvmExecreceiveRecordState = NVM_RECEIVE_RECORD_STATE_IDLE; + } + } + + // Check the calibration signal + monitorNewCalSignal(); +} + +/*********************************************************************//** + * @brief + * The setNewCalibrationRecordAvailable function updates the flag + * indicating new NV record availability. + * @details \b Inputs: none + * @details \b Outputs: isNewCalRecordAvailable + * @param value Flag value to be updated + * @return none + *************************************************************************/ +void setNewCalibrationRecordAvailable( BOOL isAvailable) +{ + isNewCalRecordAvailable = isAvailable; +} + +/*********************************************************************//** + * @brief + * The getNewCalRecordAvalability function gets the status of new + * calibration record availability. + * @details \b Inputs: isNewCalRecordAvailable + * @details \b Outputs: none + * @return TRUE if new calibration record is available otherwise FALSE + *************************************************************************/ +BOOL getNewCalRecordAvalability( void ) +{ + return isNewCalRecordAvailable; +} + +/*********************************************************************//** + * @brief + * The startNewCalRecordAvailableTimer function starts the time for + * new calibration record availability. + * @details \b Inputs: none + * @details \b Outputs: newRecordStartTimer + * @return none + *************************************************************************/ +void startNewCalRecordAvailableTimer( void ) +{ + newRecordStartTimer = getMSTimerCount(); +} +/*********************************************************************//** + * @brief + * The handleExecSendRecordIdleState function handles the idle state of + * the exec send record state machine. It prepares record data for + * publishing when requested. + * @details \b Inputs: isPublishRecordRequested, + * nvPublishRecordType + * @details \b Outputs: isPublishRecordRequested, + * recordPublishTotalMsgs, recordPublishMsgCount, + * recordSendDataIntervalCounter, nvPublishRecordType, + * recordToPublish + * @return state next state of the state machine + *************************************************************************/ +static SEND_RECORD_STATE_T handleExecSendRecordIdleState( void ) +{ + SEND_RECORD_STATE_T state = NVM_SEND_RECORD_STATE_IDLE; + + if ( TRUE == isPublishRecordRequested[ nvPublishRecordType ] ) + { + recordToPublish = ( NVM_RECORD_TYPE_T )nvPublishRecordType; + + // Set the publish flag to FALSE + isPublishRecordRequested[ recordToPublish ] = FALSE; + + // Get the record specifications to find the size of the job + PROCESS_RECORD_SPECS_T recordSpec = getProcessRecord( recordToPublish ); + + // Calculate the total number of messages required to be sent using ceilf function. This function rounds up the + // value and its result is converted to U32. + recordPublishTotalMsgs = (U32)ceilf( (F32)recordSpec.sizeofRecord / (F32)NUM_OF_BYTES_PER_RECORD_PAYLOAD ); + recordPublishMsgCount = 0; + + // Time interval in between data to be sent. It is set to the interval count so on the first call + // of the send calibration record function, the first packet of data is sent + recordSendDataIntervalCounter = RECORD_DATA_SEND_INTERVAL_COUNT; + + state = NVM_SEND_RECORD_STATE_SEND; + } + + nvPublishRecordType = ( NVM_RECORD_TYPE_T )( nvPublishRecordType + 1 ); + if( nvPublishRecordType >= NUM_OF_NVM_RECORD_TYPES ) + { + nvPublishRecordType = NVM_SYSTEM_RECORD; + } + + return state; +} + +/*********************************************************************//** + * @brief + * The handleExecSendRecordSendState function handles the send state of + * the exec send record state machine. It sends record data in chunks + * based on timing and message count. + * @details \b Inputs: recordPublishTotalMsgs, + * recordPublishMsgCount, recordSendDataIntervalCounter, + * recordToPublish + * @details \b Outputs: recordPublishMsgCount, + * recordSendDataIntervalCounter + * @return state next state of the state machine + *************************************************************************/ +static SEND_RECORD_STATE_T handleExecSendRecordSendState( void ) +{ + SEND_RECORD_STATE_T state = NVM_SEND_RECORD_STATE_SEND; + MSG_ID_T msgId; + + // If the current message number is less than the total, keep sending + if ( recordPublishMsgCount < recordPublishTotalMsgs ) + { + // If it is time to send data + if ( ++recordSendDataIntervalCounter >= RECORD_DATA_SEND_INTERVAL_COUNT ) + { + // Set to default cal data payload length + U32 length = NUM_OF_BYTES_PER_RECORD_PAYLOAD; + + PROCESS_RECORD_SPECS_T recordSpec = getProcessRecord( recordToPublish ); + U08* startPtr = recordSpec.structAddressPtr; + + // If this is the last calibration data payload, calculate the remainder of the bytes to send + if ( ( recordPublishMsgCount + 1 ) == recordPublishTotalMsgs ) + { + length = recordSpec.sizeofRecord - ( recordPublishMsgCount * NUM_OF_BYTES_PER_RECORD_PAYLOAD ); + } + + // Find the new location of the pointer which is the start of the calibration payload to be sent + startPtr += recordPublishMsgCount * NUM_OF_BYTES_PER_RECORD_PAYLOAD; + + // Get th message id of the NVM record response + msgId = getNVMRecordResponseMsgId( recordToPublish ); + + // Send the NVM record + sendDDRecord( msgId, recordPublishMsgCount + 1, recordPublishTotalMsgs, length, startPtr ); + + recordPublishMsgCount++; + recordSendDataIntervalCounter = 0; + } + } + else + { + state = NVM_SEND_RECORD_STATE_IDLE; + } + + return state; +} + +/*********************************************************************//** + * @brief + * The sendDDRecord function sends a DD record payload over communication. + * It prepares the payload and queues it for transmission. + * @details \b Inputs: none + * @details \b Outputs: none + * @param msgId Message Id for response record + * @param payloadCurrNum Current payload number + * @param payloadTotalNum Total number of payloads + * @param length Buffer length to be written + * @param recordAddress Start address of the record data + * @return TRUE if msg successfully queued for transmit, FALSE if not + *************************************************************************/ +static BOOL sendDDRecord( MSG_ID_T msgId, U32 payloadCurrNum, U32 payloadTotalNum, + U32 length, U08* recordAddress ) +{ + BOOL result = FALSE; + U08 payloadLen = 0; + DD_NVM_SEND_RECORD_PAYLOAD_T payload; + + payloadLen = sizeof( U32 ) + sizeof( U32 ) + sizeof( U32 ) + length; + payload.payloadCurrNum = payloadCurrNum; + payload.payloadTotalNum = payloadTotalNum; + payload.length = length; + memcpy( payload.data, recordAddress, length ); + result = sendMessage( msgId, COMM_BUFFER_OUT_DD_CAN_PC, (U08 *)&payload, payloadLen ); + + return result; +} + +/*********************************************************************//** + * @brief + * The receiveDDRecord function processes a received DD record message. + * It extracts payload information and verifies the received data before + * saving it. + * @details \b Inputs: none + * @details \b Outputs: none + * @param message Pointer to received message structure + * @return TRUE if the record is successfully verified and saved, + * otherwise FALSE + *************************************************************************/ +static BOOL receiveDDRecord( MESSAGE_T *message ) +{ + BOOL status = FALSE; + U32 currentMessage; + U32 totalMessages; + U32 payloadLength; + + U08* payloadPtr = message->payload; + U08 minPayloadLen = ( sizeof(currentMessage) + sizeof(totalMessages) + sizeof(payloadLength) ); + MSG_ID_T msgID = (MSG_ID_T)message->hdr.msgID; + NVM_RECORD_TYPE_T job = getNVMRecordJobState( msgID ); + + // To proceed, the payload length should be valid. And, if it is a service job, then DD mode should also be in service. + if ( message->hdr.payloadLen >= minPayloadLen ) + { + memcpy(¤tMessage, payloadPtr, sizeof(U32)); + payloadPtr += sizeof(U32); + + memcpy(&totalMessages, payloadPtr, sizeof(U32)); + payloadPtr += sizeof(U32); + + memcpy(&payloadLength, payloadPtr, sizeof(U32)); + payloadPtr += sizeof(U32); + + status = verifyAndSaveReceivedRecord( job, currentMessage, totalMessages, payloadLength, payloadPtr ); + } + + return status; +} + +/*********************************************************************//** + * @brief + * The verifyAndSaveReceivedRecord function receives the record sent + * from Dialin, assembles it, validates it using CRC, and schedules a + * write to NV memory if valid. + * @details \b Inputs: nvmExecreceiveRecordState, + * @details \b Outputs: nvmExecreceiveRecordState, + * recordReceiveStartTime, previousRecordMessageNum, + * recordUpdateAddress, currentRxRecordType, + * @param job The job that has to be received and written + * @param currentMessage Current message number received from Dialin + * @param totalMessages Total number of messages from Dialin + * @param length Message length in bytes + * @param addressPtr Address to the beginning of received data from Dialin + * @return TRUE if the request was successfully registered + *************************************************************************/ +static BOOL verifyAndSaveReceivedRecord( NVM_RECORD_TYPE_T job, U32 currentMessage, + U32 totalMessages, U32 length, U08 *addressPtr ) +{ + BOOL status = TRUE; + + // If the calibration message number is the first message number and receive exec state is idle, switch to idle + if ( ( RECORD_DATA_FIRST_RECEIVING_MSG_NUM == currentMessage ) && + ( NVM_RECEIVE_RECORD_STATE_IDLE == nvmExecreceiveRecordState ) ) + { + nvmExecreceiveRecordState = NVM_RECEIVE_RECORD_STATE_RECEIVE; + currentRxRecordType = job; + recordReceiveStartTime = getMSTimerCount(); + previousRecordMessageNum = 0; + recordUpdateAddress = 0; + } + + // Check if there is still a message left to be received + if ( ( NVM_RECEIVE_RECORD_STATE_RECEIVE == nvmExecreceiveRecordState ) && + ( currentMessage <= totalMessages ) ) + { + // Check if the current message is different from the previous message by 1 + if ( RECORD_DATA_MAX_MESSAGE_DFFIRENCE == ( currentMessage - previousRecordMessageNum ) ) + { + // Define a pointer that points to the temporary receive record + PROCESS_RECORD_SPECS_T tempRxSpec = getTemporaryRxRecord( job ); + U08* tempRxPtr = tempRxSpec.structAddressPtr; + + // Get the DD main nvm record + PROCESS_RECORD_SPECS_T recordSpec = getProcessRecord( job ); + + // Offset the pointer to length that we should start writing from + tempRxPtr += recordUpdateAddress; + + memcpy( tempRxPtr, addressPtr, length ); + + // Check if the current message is total messages + // and 0 everything out since we are done writing + if ( currentMessage == totalMessages ) + { + U16 calcCRC = crc16 ( tempRxSpec.structAddressPtr, + tempRxSpec.sizeofRecord - sizeof(U16) ); + // Get the CRC of the structure without the last 16 bits which is the CRC as well as the padding values + U16 recordCRC = *(U16*)tempRxSpec.structCRCPtr; + + // Check if calculated CRC matches the Stored CRC + if ( ( calcCRC == recordCRC ) ) + { + _disable_IRQ(); + // Copy the valid temporary record into the main record spec + memcpy(recordSpec.structAddressPtr, tempRxSpec.structAddressPtr, tempRxSpec.sizeofRecord); + _enable_IRQ(); + + // Enqueue an erase and write of the nvm record + status = enqueueEraseAndWriteSector( job ); + + if( NVM_CALIBRATION_RECORD == job ) + { + // Signal that there is a new calibration record available. + // NOTE: as of now, this signal will be sent even after the system record is sent + startNewCalRecordAvailableTimer(); + setNewCalibrationRecordAvailable( TRUE ); + } + + // Update the event of the received record that has been accepted + SEND_EVENT_WITH_2_U32_DATA( recordSpec.nvEvent, 0, 0 ); + + // Done with receiving data, go back to idle + nvmExecreceiveRecordState = NVM_RECEIVE_RECORD_STATE_IDLE; + } + else + { + // CRC match failed, go to idle + nvmExecreceiveRecordState = NVM_RECEIVE_RECORD_STATE_IDLE; + status = FALSE; + } + } + else + { + // Update the length as it has successfully been written + recordUpdateAddress += length; + + // Now the current message is the previous message + previousRecordMessageNum = currentMessage; + } + } + } + + return status; +} + +/*********************************************************************//** + * @brief + * The getNVMRecordJobState function maps the received message ID to + * the corresponding NV record job type. + * @details \b Inputs: none + * @details \b Outputs: none + * @param msgID Message ID received + * @return job corresponding NV record type + *************************************************************************/ +static NVM_RECORD_TYPE_T getNVMRecordJobState( MSG_ID_T msgID ) +{ + NVM_RECORD_TYPE_T job; + + switch ( msgID ) + { + case MSG_ID_DD_NVM_SET_CALIBRATION_RECORD: + job = NVM_CALIBRATION_RECORD; + break; + + case MSG_ID_DD_NVM_SET_SYSTEM_RECORD: + job = NVM_SYSTEM_RECORD; + break; + + case MSG_ID_DD_NVM_SET_SERVICE_RECORD: + job = NVM_SERVICE_RECORD; + break; + + case MSG_ID_DD_NVM_SET_INSTITUTIONAL_RECORD: + job = NVM_INSTITUTIONAL_RECORD; + break; + + case MSG_ID_DD_NVM_SET_USAGE_INFO_RECORD: + job = NVM_USAGE_INFO_RECORD; + break; + + default: + // Do nothing for Invalid Input from Dialin + break; + } + + return job; +} + +/*********************************************************************//** + * @brief + * The getNVMRecordResponseMsgId function maps the NV record type to + * the corresponding response message ID. + * provided + * @details \b Inputs: none + * @details \b Outputs: none + * @param job NV record type + * @return msgID corresponding response message ID + *************************************************************************/ +static MSG_ID_T getNVMRecordResponseMsgId( NVM_RECORD_TYPE_T job ) +{ + MSG_ID_T msgID; + + switch( job ) + { + case NVM_CALIBRATION_RECORD: + msgID = MSG_ID_DD_NVM_SEND_CALIBRATION_RECORD; + break; + + case NVM_SYSTEM_RECORD: + msgID = MSG_ID_DD_NVM_SEND_SYSTEM_RECORD; + break; + + case NVM_SERVICE_RECORD: + msgID = MSG_ID_DD_NVM_SEND_SERVICE_RECORD; + break; + + case NVM_INSTITUTIONAL_RECORD: + msgID = MSG_ID_DD_NVM_SEND_INSTITUTIONAL_RECORD; + break; + + case NVM_USAGE_INFO_RECORD: + msgID = MSG_ID_DD_NVM_SEND_USAGE_INFO_RECORD; + break; + + default: + // Do nothing for Invalid Input from Dialin + break; + } + + + return msgID; +} + +/*********************************************************************//** + * @brief + * The monitorNewCalSignal function monitors the new calibration signal + * and clears it when the timeout has elapsed. + * @details \b Inputs: isNewCalRecordAvailable, + * newRecordStartTimer + * @details \b Outputs: isNewCalRecordAvailable + * @return none + *************************************************************************/ + +static void monitorNewCalSignal( void ) +{ + // Check if new calibration record is available and + // the timer has elapsed + if ( ( TRUE == didTimeout( newRecordStartTimer, NEW_CAL_AVAILABLE_SIGNAL_TIMEOUT_MS ) ) && + ( TRUE == getNewCalRecordAvalability() ) ) + { + // Clear the new calibration record available flag + setNewCalibrationRecordAvailable( FALSE ); + } +} + + +/************************************************************************* + * TEST SUPPORT FUNCTIONS + *************************************************************************/ + + +/*********************************************************************//** + * @brief + * The testDDGetNVRecord function processes a request to publish an NV + * record. It validates the payload and sets the publish request flag + * for the selected record. + * @details \b Inputs: nvMExecSendRecordState + * @details \b Outputs: isPublishRecordRequested, + * recordToPublish + * @param message Pointer to the received message + * @return TRUE if the request is accepted otherwise FALSE + *************************************************************************/ +BOOL testDDGetNVRecord( MESSAGE_T *message ) +{ + BOOL result = FALSE; + NVM_RECORD_TYPE_T job; + + // verify payload length + if ( 1 == message->hdr.payloadLen ) + { + job = ( NVM_RECORD_TYPE_T )message->payload[ 0 ]; + + // Accept the request only if the send exec is in the idle state + if ( ( job < NUM_OF_NVM_RECORD_TYPES ) && + ( NVM_SEND_RECORD_STATE_IDLE == nvMExecSendRecordState ) ) + { + isPublishRecordRequested[ job ] = TRUE; + recordToPublish = job; + result = TRUE; + } + + } + + return result; +} + +/*********************************************************************//** + * @brief + * The testDDSetNVSystemRecord function processes a request to update + * the system record. It allows updates only when the system is in + * service mode. + * @details \b Inputs: none + * @details \b Outputs: none + * @param message Pointer to the received message + * @return TRUE if the record is successfully processed otherwise FALSE + *************************************************************************/ +BOOL testDDSetNVSystemRecord( MESSAGE_T *message ) +{ + BOOL result = FALSE; + + // System record can be updated only in service mode + if ( DD_MODE_SERV == getCurrentOperationMode() ) + { + result = receiveDDRecord( message ); + } + + return result; +} + +/*********************************************************************//** + * @brief + * The testDDSetNVServiceRecord function processes a request to update + * the service record. It allows updates only when the system is in + * service mode. + * @details \b Inputs: none + * @details \b Outputs: none + * @param message Pointer to the received message + * @return TRUE if the record is successfully processed otherwise FALSE + *************************************************************************/ +BOOL testDDSetNVServiceRecord( MESSAGE_T *message ) +{ + BOOL result = FALSE; + + // Service record can be updated only in service mode + if ( DD_MODE_SERV == getCurrentOperationMode() ) + { + result = receiveDDRecord( message ); + } + + return result; +} + +/*********************************************************************//** + * @brief + * The testDDSetNVCalibrationRecord function processes a request to + * update the calibration record. It allows updates only when the + * system is in service mode. + * @details \b Inputs: none + * @details \b Outputs: none + * @param message Pointer to the received message + * @return TRUE if the record is successfully processed otherwise FALSE + *************************************************************************/ +BOOL testDDSetNVCalibrationRecord( MESSAGE_T *message ) +{ + BOOL result = FALSE; + + // Calibration record can be updated only in service mode + if ( DD_MODE_SERV == getCurrentOperationMode() ) + { + result = receiveDDRecord( message ); + } + + return result; +} + +/*********************************************************************//** + * @brief + * The testDDSetNVInstitutionalRecord function processes a request to + * update the institutional record. + * @details \b Inputs: none + * @details \b Outputs: none + * @param message Pointer to the received message + * @return TRUE if the record is successfully processed otherwise FALSE + *************************************************************************/ +BOOL testDDSetNVInstitutionalRecord( MESSAGE_T *message ) +{ + BOOL result = FALSE; + result = receiveDDRecord( message ); + return result; +} + +/*********************************************************************//** + * @brief + * The testDDSetNVUsageInfoRecord function processes a request to + * update the usage information record. + * @details \b Inputs: none + * @details \b Outputs: none + * @param message Pointer to the received message + * @return TRUE if the record is successfully processed otherwise FALSE + *************************************************************************/ +BOOL testDDSetNVUsageInfoRecord( MESSAGE_T *message ) +{ + BOOL result = FALSE; + result = receiveDDRecord( message ); + return result; +} + +/*********************************************************************//** + * @brief + * The testSetNVRecordCRCOverride function overrides the CRC value of + * the selected non-volatile record and schedules it for writing. + * @details \b Inputs: none + * @details \b Outputs: none + * @param job The job whose CRC needs to be overridden + * @param crc The CRC value to be set + * @return TRUE if the job was scheduled successfully otherwise FALSE + *************************************************************************/ +BOOL testSetNVRecordCRCOverride( U32 job, U16 crc ) +{ + BOOL result = FALSE; + result = updateNVRecordCRC( job, crc ); + return result; +} + +/**@}*/ Index: firmware/App/Services/NVMessagingDD.h =================================================================== diff -u --- firmware/App/Services/NVMessagingDD.h (revision 0) +++ firmware/App/Services/NVMessagingDD.h (revision 1fa38184526c2b0c072eb8745c653f772156a824) @@ -0,0 +1,51 @@ +/************************************************************************** +* +* Copyright (c) 2026-2027 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 NVMessagingDD.h +* +* @author (original) Arpita Srivastava +* @date (original) 31-Mar-2026 +* +***************************************************************************/ + +#ifndef _NV_MESSAGING_H_ +#define _NV_MESSAGING_H_ + +#include "Common.h" + +/** + * @defgroup NVMessagingDD NVMessagingDD + * @brief This module handles NV record messaging including sending and + * receiving records over communication interfaces. It manages + * publish requests, record transmission sequencing, and reception + * of record data from external sources. It also provides support + * for signaling new calibration record availability and includes + * test interfaces for setting and getting different NV records + * + * + * @addtogroup NVMessagingDD + * @{ + */ + +// ********** public function prototypes ********** + +void initNVMessagingDD( void ); +void execNVMPSendReceiveRecord( void ); +void setNewCalibrationRecordAvailable( BOOL isAvailable ); +BOOL getNewCalRecordAvalability( void ); +void startNewCalRecordAvailableTimer( void ); + +BOOL testDDGetNVRecord( MESSAGE_T *message ); +BOOL testDDSetNVSystemRecord( MESSAGE_T *message ); +BOOL testDDSetNVServiceRecord( MESSAGE_T *message ); +BOOL testDDSetNVCalibrationRecord( MESSAGE_T *message ); +BOOL testDDSetNVInstitutionalRecord( MESSAGE_T *message ); +BOOL testDDSetNVUsageInfoRecord( MESSAGE_T *message ); + +/**@}*/ + +#endif /* _NV_MESSAGING_H_ */ Fisheye: Tag 1fa38184526c2b0c072eb8745c653f772156a824 refers to a dead (removed) revision in file `firmware/App/Services/NVMgmtDD.c'. Fisheye: No comparison available. Pass `N' to diff? Fisheye: Tag 1fa38184526c2b0c072eb8745c653f772156a824 refers to a dead (removed) revision in file `firmware/App/Services/NVMgmtDD.h'. Fisheye: No comparison available. Pass `N' to diff? Index: firmware/App/Services/NVRecordsDD.c =================================================================== diff -u -r6d1ea33dbe56d63b13802cacd09c263a5ee7e6e0 -r1fa38184526c2b0c072eb8745c653f772156a824 --- firmware/App/Services/NVRecordsDD.c (.../NVRecordsDD.c) (revision 6d1ea33dbe56d63b13802cacd09c263a5ee7e6e0) +++ firmware/App/Services/NVRecordsDD.c (.../NVRecordsDD.c) (revision 1fa38184526c2b0c072eb8745c653f772156a824) @@ -16,7 +16,7 @@ //#include "Common.h" #include "DDDefs.h" #include "NVJobQ.h" -#include "NVMessaging.h" +#include "NVMessagingDD.h" #include "NVRecordsDD.h" #include "Timers.h" #include "Utilities.h" // For crc calculation Index: firmware/App/Services/NVRecordsDD.h =================================================================== diff -u -r6d1ea33dbe56d63b13802cacd09c263a5ee7e6e0 -r1fa38184526c2b0c072eb8745c653f772156a824 --- firmware/App/Services/NVRecordsDD.h (.../NVRecordsDD.h) (revision 6d1ea33dbe56d63b13802cacd09c263a5ee7e6e0) +++ firmware/App/Services/NVRecordsDD.h (.../NVRecordsDD.h) (revision 1fa38184526c2b0c072eb8745c653f772156a824) @@ -242,7 +242,7 @@ typedef struct { BOOL isHDFOnlineFluid; ///< True : HDF Online Fluid feature is available, False if not. - U32 waterRecovey; ///< Low : 0, Medium : 1, High : 2. + U32 waterRecovery; ///< Low : 0, Medium : 1, High : 2. U08 serviceLoc; ///< DD service location. U32 lastServiceEpochDate; ///< DD last service date in epoch. U32 serviceIntervalSeconds; ///< DD service interval in seconds. Index: firmware/App/Tasks/TaskBG.c =================================================================== diff -u -r6d1ea33dbe56d63b13802cacd09c263a5ee7e6e0 -r1fa38184526c2b0c072eb8745c653f772156a824 --- firmware/App/Tasks/TaskBG.c (.../TaskBG.c) (revision 6d1ea33dbe56d63b13802cacd09c263a5ee7e6e0) +++ firmware/App/Tasks/TaskBG.c (.../TaskBG.c) (revision 1fa38184526c2b0c072eb8745c653f772156a824) @@ -15,9 +15,9 @@ * ***************************************************************************/ +#include #include "gio.h" -#include "NVMgmtDD.h" #include "TaskTimer.h" #include "WatchdogMgmt.h" Index: firmware/App/Tasks/TaskGeneral.c =================================================================== diff -u -r6d1ea33dbe56d63b13802cacd09c263a5ee7e6e0 -r1fa38184526c2b0c072eb8745c653f772156a824 --- firmware/App/Tasks/TaskGeneral.c (.../TaskGeneral.c) (revision 6d1ea33dbe56d63b13802cacd09c263a5ee7e6e0) +++ firmware/App/Tasks/TaskGeneral.c (.../TaskGeneral.c) (revision 1fa38184526c2b0c072eb8745c653f772156a824) @@ -15,6 +15,7 @@ * ***************************************************************************/ +#include #include "gio.h" #include "lin.h" @@ -25,7 +26,6 @@ #include "Heaters.h" #include "FPOperationModes.h" #include "Messaging.h" -#include "NVMgmtDD.h" #include "OperationModes.h" #include "PermeateTank.h" #include "RinsePump.h" Index: firmware/source/sys_main.c =================================================================== diff -u -r9a14f69c0f0de343b5664b20753142b50bc4e093 -r1fa38184526c2b0c072eb8745c653f772156a824 --- firmware/source/sys_main.c (.../sys_main.c) (revision 9a14f69c0f0de343b5664b20753142b50bc4e093) +++ firmware/source/sys_main.c (.../sys_main.c) (revision 1fa38184526c2b0c072eb8745c653f772156a824) @@ -47,6 +47,7 @@ /* Include Files */ +#include #include "sys_common.h" /* USER CODE BEGIN (1) */ @@ -87,7 +88,6 @@ #include "ModeGenPermeate.h" #include "ModePreGenPermeate.h" #include "MsgQueues.h" -#include "NVMgmtDD.h" #include "OperationModes.h" #include "PermeateTank.h" #include "Pressure.h" @@ -190,7 +190,7 @@ initWatchdogMgmt(); initInterrupts(); initFPGADD(); - initNVMgmtDD(); + initNVMgmt(); initPressure(); initConductivity(); initValves();