Index: firmware/App/Services/NVMessagingDD.c =================================================================== diff -u -r2e65cae607c3ee68326f82d6134b0de3777559f9 -rb925bf251dfd5584a0839cee93ccf8566a0ec2fb --- firmware/App/Services/NVMessagingDD.c (.../NVMessagingDD.c) (revision 2e65cae607c3ee68326f82d6134b0de3777559f9) +++ firmware/App/Services/NVMessagingDD.c (.../NVMessagingDD.c) (revision b925bf251dfd5584a0839cee93ccf8566a0ec2fb) @@ -55,7 +55,7 @@ typedef struct { U32 idx; ///< Index of sensor / pump / concentrates - U08 data[ NUM_OF_BYTES_PER_RECORD_PAYLOAD ]; ///< Data to be sent + U08 data[ NUM_OF_BYTES_PER_RECORD_PAYLOAD ]; ///< Data to be sent } DD_NVM_SEND_RECORD_PAYLOAD_T; // ********** private data ********** @@ -70,6 +70,8 @@ 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 calRecordReceiveStartTime; ///< Time stamp the calibration record was received. +static U32 institRecordReceiveStartTime; ///< Time stamp the institutional record was received. static U32 recordReceiveStartTime; ///< Time stamp the calibration/service was received. static BOOL isPublishRecordRequested[ NUM_OF_NVM_RECORD_TYPES ]; ///< Record state machine publish request flag. @@ -86,7 +88,9 @@ static BOOL sendDDUsageInfoRecord( void ); static BOOL sendDDRecord( MSG_ID_T msgId, U32 idx, U32 length, U08* recordAddress ); -static BOOL receiveDDRecord( MESSAGE_T *message ); +static BOOL receiveDDRecord( MESSAGE_T *message, NVM_RECORD_TYPE_T recordType, U16 recordSize ); +static BOOL receiveCalRecord( MESSAGE_T *message, DD_CAL_REC_TYPE calRecordType, U16 recordSize ); +static BOOL receiveInstitRecord( 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 ); @@ -154,19 +158,27 @@ 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 ) + if( nvmExecreceiveRecordState == NVM_RECEIVE_RECORD_STATE_RECEIVE ) { - // 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 ) ) + if ( TRUE == didTimeout( calRecordReceiveStartTime, RECORD_DATA_RECEIVE_TIMEOUT_MS ) ) { // Exec receive state machine timed out. Schedule a read to update the structure - enqueueRecordJob( NVM_OPERATION_READ, currentRxRecordType ); + enqueueEraseAndWriteSector( NVM_CALIBRATION_RECORD ); + startNewCalRecordAvailableTimer(); + setNewCalibrationRecordAvailable( TRUE ); + PROCESS_RECORD_SPECS_T recordSpec = getProcessRecord( NVM_CALIBRATION_RECORD ); + sendNVEvent( NVM_CALIBRATION_RECORD , 0, 0 ); nvmExecreceiveRecordState = NVM_RECEIVE_RECORD_STATE_IDLE; } + + if ( TRUE == didTimeout( institRecordReceiveStartTime, RECORD_DATA_RECEIVE_TIMEOUT_MS ) ) + { + // Exec receive state machine timed out. Schedule a read to update the structure + enqueueEraseAndWriteSector( NVM_INSTITUTIONAL_RECORD ); + PROCESS_RECORD_SPECS_T recordSpec = getProcessRecord( NVM_INSTITUTIONAL_RECORD ); + sendNVEvent( NVM_INSTITUTIONAL_RECORD , 0, 0 ); + nvmExecreceiveRecordState = NVM_RECEIVE_RECORD_STATE_IDLE; + } } // Check the calibration signal @@ -643,240 +655,95 @@ * @return TRUE if the record is successfully verified and saved, * otherwise FALSE *************************************************************************/ -static BOOL receiveDDRecord( MESSAGE_T *message ) +static BOOL receiveDDRecord( MESSAGE_T *message, NVM_RECORD_TYPE_T recordType, U16 recordSize ) { 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 ) + if (message->hdr.payloadLen == recordSize) { - memcpy(¤tMessage, payloadPtr, sizeof(U32)); - payloadPtr += sizeof(U32); + U08 tempBuffer[ recordSize ]; + memcpy( tempBuffer, message->payload, recordSize ); - memcpy(&totalMessages, payloadPtr, sizeof(U32)); - payloadPtr += sizeof(U32); + // CRC assumed at end of record + U16 *recordCRC = (U16 *)( tempBuffer + ( recordSize - sizeof(U16) ) ); + U16 calcCRC = crc16( tempBuffer, recordSize - sizeof(U16) ); - memcpy(&payloadLength, payloadPtr, sizeof(U32)); - payloadPtr += sizeof(U32); - - status = verifyAndSaveReceivedRecord( job, currentMessage, totalMessages, payloadLength, payloadPtr ); + if ( calcCRC == *recordCRC ) + { + PROCESS_RECORD_SPECS_T recordSpec = getProcessRecord( recordType ); + memcpy( recordSpec.structAddressPtr, tempBuffer, recordSize ); + setNVMRecord( recordType, tempBuffer ); + status = enqueueEraseAndWriteSector( recordType ); + sendNVEvent( recordType, 0, 0 ); + } } 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 ) +static BOOL receiveCalRecord( MESSAGE_T *message, DD_CAL_REC_TYPE calRecordType, U16 recordSize ) { - BOOL status = TRUE; + BOOL status = FALSE; + U08 idx = 0; + MSG_ID_T msgID = (MSG_ID_T)message->hdr.msgID; + U08* payloadPtr = message->payload; + U08 expectedPayloadLen = ( sizeof(U08) + recordSize ); + U08 tempBuffer[ recordSize ]; - // 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 ) ) + if ( message->hdr.payloadLen == expectedPayloadLen ) { - // 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; + memcpy(&idx, payloadPtr, sizeof(U32)); + payloadPtr += sizeof(U08); - // Get the DD main nvm record - PROCESS_RECORD_SPECS_T recordSpec = getProcessRecord( job ); + memcpy( tempBuffer, payloadPtr, recordSize ); - // Offset the pointer to length that we should start writing from - tempRxPtr += recordUpdateAddress; + // CRC assumed at end of record + U16 *recordCRC = (U16 *)( tempBuffer + ( recordSize - sizeof(U16) ) ); + U16 calcCRC = crc16( tempBuffer, recordSize - sizeof(U16) ); - memcpy( tempRxPtr, addressPtr, length ); + if (calcCRC == *recordCRC) + { + nvmExecreceiveRecordState = NVM_RECEIVE_RECORD_STATE_RECEIVE; + status = setNVMCalRecord( calRecordType, &tempBuffer, idx ); - // 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; - } + // It is possible that we receive multiple packets of cal record + // So we write it to flash when we finish receiving all packets or + // a timeout occurs. + calRecordReceiveStartTime = getMSTimerCount(); } } 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 ) +static BOOL receiveInstitRecord( MESSAGE_T *message ) { - NVM_RECORD_TYPE_T job; + BOOL status = FALSE; + U08 idx = 0; + U08* payloadPtr = message->payload; + U08 expectedPayloadLen = sizeof(U08); - switch ( msgID ) + if ( message->hdr.payloadLen >= expectedPayloadLen ) { -// case MSG_ID_DD_NVM_RECV_CAL_PRESSURE_SENSOR: -// case MSG_ID_DD_NVM_RECV_CAL_TEMP_SENSOR: -// case MSG_ID_DD_NVM_RECV_CAL_CONC_PUMP: -// case MSG_ID_DD_NVM_RECV_CAL_D12_PUMP: -// case MSG_ID_DD_NVM_RECV_CAL_D48_PUMP: -// case MSG_ID_DD_NVM_RECV_CAL_ACID_CONCENTRATE: -// case MSG_ID_DD_NVM_RECV_CAL_BICARB_CONCENTRATE: -// case MSG_ID_DD_NVM_RECV_CAL_ACCEL_SENSOR: -// case MSG_ID_DD_NVM_RECV_CAL_BLOOD_LEAK_SENSOR: -// job = NVM_CALIBRATION_RECORD; -// break; + nvmExecreceiveRecordState = NVM_RECEIVE_RECORD_STATE_RECEIVE; - case MSG_ID_UI_DD_NVM_SET_SYSTEM_RECORD: - job = NVM_SYSTEM_RECORD; - break; + memcpy( &idx, payloadPtr, sizeof(U32) ); + payloadPtr += sizeof(U08); - case MSG_ID_UI_DD_NVM_SET_SERVICE_RECORD: - job = NVM_SERVICE_RECORD; - break; + status = setNVMInstitRecord( (DD_CAL_REC_TYPE)idx, payloadPtr ); - case MSG_ID_UI_DD_NVM_SET_INSTITUTIONAL_RECORD: - job = NVM_INSTITUTIONAL_RECORD; - break; - - case MSG_ID_UI_DD_NVM_SET_USAGE_INFO_RECORD: - job = NVM_USAGE_INFO_RECORD; - break; - - default: - // Do nothing for Invalid Input from Dialin - break; + // It is possible that we receive multiple packets of instit record + // So we write it to flash when we finish receiving all packets or + // a timeout occurs. + institRecordReceiveStartTime = getMSTimerCount(); } - return job; + return status; } /*********************************************************************//** * @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_SYSTEM_RECORD_RESPONSE; - break; - - case NVM_SERVICE_RECORD: - msgID = MSG_ID_DD_NVM_SERVICE_RECORD_RESPONSE; - break; - - case NVM_INSTITUTIONAL_RECORD: - msgID = MSG_ID_DD_NVM_INSTITUTIONAL_RECORD_RESPONSE; - break; - - case NVM_USAGE_INFO_RECORD: - msgID = MSG_ID_DD_NVM_USAGE_INFO_RECORD_RESPONSE; - 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, @@ -955,7 +822,7 @@ // System record can be updated only in service mode if ( DD_MODE_SERV == getCurrentOperationMode() ) { - result = receiveDDRecord( message ); + result = receiveDDRecord( message, NVM_SYSTEM_RECORD, sizeof( DD_SYSTEM_RECORD_T ) ); } return result; @@ -978,32 +845,25 @@ // Service record can be updated only in service mode if ( DD_MODE_SERV == getCurrentOperationMode() ) { - result = receiveDDRecord( message ); + result = receiveDDRecord( message, NVM_SERVICE_RECORD, sizeof( DD_SERVICE_RECORD_T ) ); } 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. + * 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 testDDSetNVCalibrationRecord( MESSAGE_T *message ) +BOOL testDDSetNVUsageInfoRecord( MESSAGE_T *message ) { BOOL result = FALSE; - - // Calibration record can be updated only in service mode - if ( DD_MODE_SERV == getCurrentOperationMode() ) - { - result = receiveDDRecord( message ); - } - + result = receiveDDRecord( message, NVM_USAGE_INFO_RECORD, sizeof( DD_USAGE_INFO_RECORD_T ) ); return result; } @@ -1019,26 +879,118 @@ BOOL testDDSetNVInstitutionalRecord( MESSAGE_T *message ) { BOOL result = FALSE; - result = receiveDDRecord( message ); + result = receiveInstitRecord( 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 testDDSetPressureSensorCalRecord( MESSAGE_T *message ) { BOOL result = FALSE; - result = receiveDDRecord( message ); + + if ( DD_MODE_SERV == getCurrentOperationMode() ) + { + result = receiveCalRecord( message, DD_CAL_RECORD_PRESSURE_SENSOR , sizeof( POLYNOMIAL_CAL_PAYLOAD_T ) ); + } return result; } +BOOL testDDSetTempSensorCalRecord( MESSAGE_T *message ) +{ + BOOL result = FALSE; + + if ( DD_MODE_SERV == getCurrentOperationMode() ) + { + result = receiveCalRecord( message, DD_CAL_RECORD_TEMPERATURE_SENSOR , sizeof( POLYNOMIAL_CAL_PAYLOAD_T ) ); + } + + return result; +} + +BOOL testDDSetConcPumpCalRecord( MESSAGE_T *message ) +{ + BOOL result = FALSE; + + if ( DD_MODE_SERV == getCurrentOperationMode() ) + { + result = receiveCalRecord( message, DD_CAL_RECORD_CONCENTRATE_PUMP , sizeof( POLYNOMIAL_CAL_PAYLOAD_T ) ); + } + + return result; +} + +BOOL testDDSetD12PumpCalRecord( MESSAGE_T *message ) +{ + BOOL result = FALSE; + + if ( DD_MODE_SERV == getCurrentOperationMode() ) + { + result = receiveCalRecord( message, DD_CAL_RECORD_D12_PUMP , sizeof( DD_D12_DIALYSATE_PUMP_RECORD_T ) ); + } + + return result; +} + +BOOL testDDSetD48CalRecord( MESSAGE_T *message ) +{ + BOOL result = FALSE; + + if ( DD_MODE_SERV == getCurrentOperationMode() ) + { + result = receiveCalRecord( message, DD_CAL_RECORD_D48_PUMP , sizeof( POLYNOMIAL_CAL_PAYLOAD_T ) ); + } + + return result; +} + +BOOL testDDSetAcidConcCalRecord( MESSAGE_T *message ) +{ + BOOL result = FALSE; + + if ( DD_MODE_SERV == getCurrentOperationMode() ) + { + result = receiveCalRecord( message, DD_CAL_RECORD_ACID_CONCENTRATE , sizeof( DD_ACID_CONCENTRATE_T ) ); + } + + return result; +} + +BOOL testDDSetBicarbConcCalRecord( MESSAGE_T *message ) +{ + BOOL result = FALSE; + + if ( DD_MODE_SERV == getCurrentOperationMode() ) + { + result = receiveCalRecord( message, DD_CAL_RECORD_BICARB_CONCENTRATE , sizeof( DD_BICARB_CONCENTRATE_T ) ); + } + + return result; +} + +BOOL testDDSetAccelSensorCalRecord( MESSAGE_T *message ) +{ + BOOL result = FALSE; + + if ( DD_MODE_SERV == getCurrentOperationMode() ) + { + result = receiveCalRecord( message, DD_CAL_RECORD_ACCELEROMETER_SENSOR , sizeof( DD_ACCEL_SENSOR_CAL_RECORD_T ) ); + } + + return result; +} + +BOOL testDDSetBloodLeakSensorCalRecord( MESSAGE_T *message ) +{ + BOOL result = FALSE; + + if ( DD_MODE_SERV == getCurrentOperationMode() ) + { + result = receiveCalRecord( message, DD_CAL_RECORD_BLLOD_LEAK_SENSOR , sizeof( DD_BLOOD_LEAK_SENSOR_CAL_RECORD_T ) ); + } + + return result; +} + + /*********************************************************************//** * @brief * The testSetNVRecordCRCOverride function overrides the CRC value of @@ -1056,4 +1008,6 @@ return result; } + + /**@}*/