/************************************************************************* $Archive: /PACS/OnBoard/DpuRec.c $ $Revision: 1.11 $ $Date: 2009/04/23 13:51:12 $ $Author: amazy $ $Log: DpuRec.c,v $ Revision 1.11 2009/04/23 13:51:12 amazy 6.029 * * 60 3/14/06 4:31p Pacs Egse * Version 6.001 * Cleaned and commented *************************************************************************/ #ifdef SIMULATOR #include "virtuosoSim.h" #else // SIMULATOR #include "v_macro.h" #include "node1.h" #include "k_struct.h" #endif #include "seq_msg.h" #include "constant.h" #include "params.h" #include "error.h" #include "links.h" #include "crc.h" #include "u_res.h" #include "l_memory.h" //**************************************************************** // ENUMERATION //**************************************************************** // define the IDs of all the params that can be accessed from the DPU through a write command // Actually, in this file, we will only use NB_PARAMS. The individual IDs are usefull only // for ground programmers. #undef PARAM #define PARAM(ParamId, variable, length) ParamId, enum { #include "par_list.h" NB_PARAMS }; //**************************************************************** // GLOBAL VARIABLES //**************************************************************** int gDumpPacketBuffer[MAXIMUM_SIZE_OF_DUMP_PACKET]; // buffer used to store results of dump commands //**************************************************************** // LOCAL VARIABLES //**************************************************************** static int ReceptionBuffer[512]; // buffer used to store the messages received from the DPU // Initialize the array containing the address of each of the parameters that can be accessed // by the DPU through a write command. #undef PARAM #define PARAM(ParamId, variable, length) &(variable), static void* apParametersAddress[] = { #include "par_list.h" }; // Initialize the array containing the size of each of the parameters that can be accessed // by the DPU through a write command. #undef PARAM #define PARAM(ParamId, variable, length) length, static int apParametersSize[] = { #include "par_list.h" }; //**************************************************************** // LOCAL STRUCTURES //**************************************************************** /* STRUCT : ReadWriteCommandParam ****************************** AUTHOR : AMazy USE : This structure is used to pass arguments to a "memcpy" function. Since this memcpy function shall be executed in a critical section, it can have only one parameter (void*) so, we will pass a pointer to this structure. */ typedef struct { void* pSrcBuffer; void* pDestBuffer; int Size; } ReadWriteCommandParam; //**************************************************************** // MACRO //**************************************************************** //macro to signal an error in DPU Receiver Task #define SetError(newError) \ {\ SetGlobalError(newError);\ LOCK_WRITE_RES_PARAMS;\ SET_BITS(gpDpuRec->TaskStatus, K_BMASK_TASK_STATUS_ERROR_STATUS | K_BMASK_TASK_STATUS_ERROR_CODE, K_BMASK_TASK_STATUS_TASK_IN_ERROR + newError); \ UNLOCK_WRITE_RES_PARAMS;\ } //**************************************************************** // FUNCTION DECLARATION //**************************************************************** void InitializeDpuRec(); void DpuRec(); int MemcpyInCriticalSection(void* p_arg); //**************************************************************** // FUNCTION IMPLEMENTATION //**************************************************************** /* FUNCTION : void InitializeDpuRec() ********************************** AUTHOR : AMazy USE : Initialize the Dpu Receiver Task */ void InitializeDpuRec() { SequencerMsg msg; // temporary message used to send the first command to the sequencer LOCK_WRITE_RES_PARAMS; // initialize task status. gpDpuRec->TaskStatus = K_BMASK_TASK_STATUS_ALIVE | K_BMASK_TASK_STATUS_NO_ERROR_IN_TASK | K_BMASK_TASK_STATUS_LINK_NOT_CONNECTED; gpDpuRec->PacketCounter = 0; UNLOCK_WRITE_RES_PARAMS; // initialize CRC stuffs InitCrcTable(); // wait a certain time to be sure that the other tasks are ready to receive messages KS_TaskSleep(DPU_RECEIVER_START_UP_SLEEP_PERIOD); // first thing we do is to wait for the link1355 to be initialize by the other side (DPU) // It is a blocking operation since, if we can not communicate with the DPU, there is no // need to start doing something else. LOCK_READ_RES_PARAMS; do { UNLOCK_READ_RES_PARAMS; KS_TaskSleep(1000); LOCK_READ_RES_PARAMS; } while (!IS(gpDpuRec->TaskStatus, K_BMASK_TASK_STATUS_LINK_STATUS, K_BMASK_TASK_STATUS_LINK_CONNECTED)); UNLOCK_READ_RES_PARAMS; // send the command START_HK to test that the main tasks are working properly msg.Type = SINGLE_COMMAND_AVAILABLE; msg.Content.Cmd.Id = DMC_START_HK; msg.Content.Cmd.Param.Uint = 0; msg.SID = 0; KS_FIFOPut(SEQUENCER_FIFO, &msg); } /* TASK : void DpuRec() ******************** AUTHOR : AMazy */ void DpuRec() { SequencerMsg seqMsg; // used to send messages to the Sequencer DpuSenderMsg dpuSendMsg; // used to send messages to the DPU Sender InitializeDpuRec(); while (1) { // receive a packet from DPU Link1355Read(CHANNEL_DPU, 512, &(ReceptionBuffer[0])); gpDpuRec->PacketCounter++; // look at message header. switch(ReceptionBuffer[0] & 0xFFFF0000) { case TRIGGER_CMD : { // forward the command to the Sequencer seqMsg.Type = SINGLE_COMMAND_AVAILABLE; seqMsg.SID = ReceptionBuffer[1] & 0x0000FFFF; seqMsg.Content.Cmd.Id = (ReceptionBuffer[1] >> 16) & 0x0000FFFF; seqMsg.Content.Cmd.Param.Int = ReceptionBuffer[2]; KS_FIFOPut(SEQUENCER_FIFO, &seqMsg); };break; case DUMP_CMD : { int memID; int address; int length; ReadWriteCommandParam param; //if a sequence is running, all commands but the DMC_ABORT_SEQUENCE must be rejected if (IS(gpSequencer->TaskStatus, K_BMASK_TASK_STATUS_SEQ_EXECUTION_STATUS, K_BMASK_TASK_STATUS_SEQ_RUNNING)) { dpuSendMsg.Header = DUMP_NACK; dpuSendMsg.Field1.ErrorCode = COULD_NOT_EXECUTE_COMMAND; dpuSendMsg.Field2.Parameter = 0; KS_FIFOPut(DPUSENDER_FIFO, &dpuSendMsg); break; } //address is the 24 LSBits of ReceptionBuffer[0] and length is ReceptionBuffer[1] param.pDestBuffer = (void*)gDumpPacketBuffer; length = ReceptionBuffer[1] & 0x0000FFFF; memID = ReceptionBuffer[0] & 0x00001F00; address = ((ReceptionBuffer[0] & 0x000000FF) << 16) + ((ReceptionBuffer[1] >> 16) & 0x0000FFFF); if (memID == 0x00001100) // DRAM { int packetCount = 0; //check address and length if (address > (K_DMSIZE_DRAM-1)) { dpuSendMsg.Header = DUMP_NACK; dpuSendMsg.Field1.ErrorCode = INVALID_ADDRESS; dpuSendMsg.Field2.Parameter = address; KS_FIFOPut(DPUSENDER_FIFO, &dpuSendMsg); length = 0; //nothing to copy since parameters were invalid } else if ((address + length -1) > (K_DMSIZE_DRAM-1)) { dpuSendMsg.Header = DUMP_NACK; dpuSendMsg.Field1.ErrorCode = INVALID_LENGTH; dpuSendMsg.Field2.Parameter = length; KS_FIFOPut(DPUSENDER_FIFO, &dpuSendMsg); length = 0; //nothing to copy since parameters were invalid } while (length > 249) { if (KS_SemaTestWT(SEMA_DUMP_BUFFER_AVAILABLE, 1000) == RC_TIME) { SetError(ERR_DPU_RECEIVER_TIME_OUT_ON_DUMP_BUFFER); length = 0; // so, the execution of the program continues } else { param.pSrcBuffer = (int*)address + 249*packetCount; param.Size = 249; #ifndef SIMULATOR KS_CriticalSection(MemcpyInCriticalSection, (void*)¶m); #endif //SIMULATOR //send the packet to the DPU (through the DPU Sender) dpuSendMsg.Header = DUMP_ACK_INTERMED; dpuSendMsg.Field1.MemId = memID + (((int)param.pSrcBuffer & 0x00FF0000) >> 16); dpuSendMsg.Field2.Address = ((int)param.pSrcBuffer & 0x0000FFFF) << 16; dpuSendMsg.Field3.LengthSAU = 249; dpuSendMsg.Field4.Checksum = GetChecksum(gDumpPacketBuffer, param.Size); dpuSendMsg.Field5.LengthWords = 249; KS_FIFOPut(DPUSENDER_FIFO, &dpuSendMsg); packetCount++; length-=249; } } if (length > 0) { if (KS_SemaTestWT(SEMA_DUMP_BUFFER_AVAILABLE, 1000) == RC_TIME) { SetError(ERR_DPU_RECEIVER_TIME_OUT_ON_DUMP_BUFFER); } else { param.pSrcBuffer = (int*)address + 249*packetCount; param.Size = length; #ifndef SIMULATOR KS_CriticalSection(MemcpyInCriticalSection, (void*)¶m); #endif //SIMULATOR //send the packet to the DPU (through the DPU Sender) dpuSendMsg.Header = DUMP_ACK; dpuSendMsg.Field1.MemId = memID + (((int)param.pSrcBuffer & 0x00FF0000) >> 16); dpuSendMsg.Field2.Address = ((int)param.pSrcBuffer & 0x0000FFFF) << 16; dpuSendMsg.Field3.LengthSAU = length; dpuSendMsg.Field4.Checksum = GetChecksum(gDumpPacketBuffer, param.Size); dpuSendMsg.Field5.LengthWords = length; KS_FIFOPut(DPUSENDER_FIFO, &dpuSendMsg); } } } else if ((memID == 0x00000100) || (memID == 0x00000300) || (memID == 0x00000000)) // PRAM || EEPROM || PROM { int packetCount = 0; switch (memID) { case 0x00000100 : //PRAM { //check address and length if (address > (K_PMSIZE_PRAM-1)) { dpuSendMsg.Header = DUMP_NACK; dpuSendMsg.Field1.ErrorCode = INVALID_ADDRESS; dpuSendMsg.Field2.Parameter = address; KS_FIFOPut(DPUSENDER_FIFO, &dpuSendMsg); length = 0; //nothing to copy since parameters were invalid } else if ((address + length -1) > (K_PMSIZE_PRAM-1)) { dpuSendMsg.Header = DUMP_NACK; dpuSendMsg.Field1.ErrorCode = INVALID_LENGTH; dpuSendMsg.Field2.Parameter = length; KS_FIFOPut(DPUSENDER_FIFO, &dpuSendMsg); length = 0; //nothing to copy since parameters were invalid } //apply offset //no offset };break; case 0x00000300 : //EEPROM { //check address and length if (address < K_PMADDR_BASE_EEPROM) { dpuSendMsg.Header = DUMP_NACK; dpuSendMsg.Field1.ErrorCode = INVALID_ADDRESS; dpuSendMsg.Field2.Parameter = address; KS_FIFOPut(DPUSENDER_FIFO, &dpuSendMsg); length = 0; //nothing to copy since parameters were invalid } else if (address > (K_PMADDR_BASE_EEPROM + K_PMSIZE_EEPROM - 1)) { dpuSendMsg.Header = DUMP_NACK; dpuSendMsg.Field1.ErrorCode = INVALID_ADDRESS; dpuSendMsg.Field2.Parameter = address; KS_FIFOPut(DPUSENDER_FIFO, &dpuSendMsg); length = 0; //nothing to copy since parameters were invalid } else if ((address + length -1) > (K_PMADDR_BASE_EEPROM + K_PMSIZE_EEPROM - 1)) { dpuSendMsg.Header = DUMP_NACK; dpuSendMsg.Field1.ErrorCode = INVALID_LENGTH; dpuSendMsg.Field2.Parameter = length; KS_FIFOPut(DPUSENDER_FIFO, &dpuSendMsg); length = 0; //nothing to copy since parameters were invalid } //apply offset address += K_PMADDR_BASE_EEPROM; };break; case 0x00000000 : //PROM { //check address and length if (address < K_PMADDR_BASE_MIRR_ROM) { dpuSendMsg.Header = DUMP_NACK; dpuSendMsg.Field1.ErrorCode = INVALID_ADDRESS; dpuSendMsg.Field2.Parameter = address; KS_FIFOPut(DPUSENDER_FIFO, &dpuSendMsg); length = 0; //nothing to copy since parameters were invalid } else if (address > (K_PMADDR_BASE_MIRR_ROM + K_PMSIZE_PROM -1)) { dpuSendMsg.Header = DUMP_NACK; dpuSendMsg.Field1.ErrorCode = INVALID_ADDRESS; dpuSendMsg.Field2.Parameter = address; KS_FIFOPut(DPUSENDER_FIFO, &dpuSendMsg); length = 0; //nothing to copy since parameters were invalid } else if ((address + length -1) > (K_PMADDR_BASE_MIRR_ROM + K_PMSIZE_PROM -1)) { dpuSendMsg.Header = DUMP_NACK; dpuSendMsg.Field1.ErrorCode = INVALID_LENGTH; dpuSendMsg.Field2.Parameter = length; KS_FIFOPut(DPUSENDER_FIFO, &dpuSendMsg); length = 0; //nothing to copy since parameters were invalid } //apply offset address += K_PMADDR_BASE_MIRR_ROM; };break; } while (length > 166) { if (KS_SemaTestWT(SEMA_DUMP_BUFFER_AVAILABLE, 1000) == RC_TIME) { SetError(ERR_DPU_RECEIVER_TIME_OUT_ON_DUMP_BUFFER); length = 0; // so, the execution of the program continues } else { param.pSrcBuffer = (int*)address + 166*packetCount; param.Size = 166; #ifndef SIMULATOR MEM_CopyPMToDM((T_UNSIGNED_32)param.pSrcBuffer, (T_UNSIGNED_32)param.pDestBuffer, param.Size*3); #endif //SIMULATOR //send the packet to the DPU (through the DPU Sender) dpuSendMsg.Header = DUMP_ACK_INTERMED; dpuSendMsg.Field1.MemId = memID + (((int)param.pSrcBuffer & 0x00FF0000) >> 16); dpuSendMsg.Field2.Address = ((int)param.pSrcBuffer & 0x0000FFFF) << 16; dpuSendMsg.Field3.LengthSAU = 166; dpuSendMsg.Field4.Checksum = GetChecksum(gDumpPacketBuffer, param.Size); dpuSendMsg.Field5.LengthWords = 249; KS_FIFOPut(DPUSENDER_FIFO, &dpuSendMsg); packetCount++; length-=166; } } if (length > 0) { if (KS_SemaTestWT(SEMA_DUMP_BUFFER_AVAILABLE, 1000) == RC_TIME) { SetError(ERR_DPU_RECEIVER_TIME_OUT_ON_DUMP_BUFFER); } else { param.pSrcBuffer = (int*)address + 166*packetCount; param.Size = length; #ifndef SIMULATOR MEM_CopyPMToDM((T_UNSIGNED_32)param.pSrcBuffer, (T_UNSIGNED_32)param.pDestBuffer, param.Size*3); #endif //SIMULATOR //send the packet to the DPU (through the DPU Sender) dpuSendMsg.Header = DUMP_ACK; dpuSendMsg.Field1.MemId = memID + (((int)param.pSrcBuffer & 0x00FF0000) >> 16); dpuSendMsg.Field2.Address = ((int)param.pSrcBuffer & 0x0000FFFF) << 16; dpuSendMsg.Field3.LengthSAU = length; dpuSendMsg.Field4.Checksum = GetChecksum(gDumpPacketBuffer, param.Size); dpuSendMsg.Field5.LengthWords = (length*3+1)/2; KS_FIFOPut(DPUSENDER_FIFO, &dpuSendMsg); } } } else { dpuSendMsg.Header = DUMP_NACK; dpuSendMsg.Field1.ErrorCode = INVALID_MEMORY_ID; dpuSendMsg.Field2.Parameter = memID >> 8; KS_FIFOPut(DPUSENDER_FIFO, &dpuSendMsg); } };break; case LOAD_CMD : { int memID; int address; int length; int checksumReceived; int checksumAfterCopy; int checksumInPacket; ReadWriteCommandParam param; //if a sequence is running, all commands but the DMC_ABORT_SEQUENCE must be rejected if (IS(gpSequencer->TaskStatus, K_BMASK_TASK_STATUS_SEQ_EXECUTION_STATUS, K_BMASK_TASK_STATUS_SEQ_RUNNING)) { dpuSendMsg.Header = LOAD_NACK; dpuSendMsg.Field1.ErrorCode = COULD_NOT_EXECUTE_COMMAND; dpuSendMsg.Field2.Parameter = 0; KS_FIFOPut(DPUSENDER_FIFO, &dpuSendMsg); break; } //address is the 24 LSBits of ReceptionBuffer[0] and length is ReceptionBuffer[1] param.pSrcBuffer = (void*)&(ReceptionBuffer[2]); length = ReceptionBuffer[1] & 0x0000FFFF; memID = ReceptionBuffer[0] & 0x00001F00; address = ((ReceptionBuffer[0] & 0x000000FF) << 16) + ((ReceptionBuffer[1] >> 16) & 0x0000FFFF); if (memID == 0x00001100) // DRAM { //check address and length if (address > (K_DMSIZE_DRAM-1)) { dpuSendMsg.Header = LOAD_NACK; dpuSendMsg.Field1.ErrorCode = INVALID_ADDRESS; dpuSendMsg.Field2.Parameter = address; KS_FIFOPut(DPUSENDER_FIFO, &dpuSendMsg); length = 0; //nothing to copy since parameters were invalid } else if ((address + length -1) > (K_DMSIZE_DRAM-1)) { dpuSendMsg.Header = LOAD_NACK; dpuSendMsg.Field1.ErrorCode = INVALID_LENGTH; dpuSendMsg.Field2.Parameter = length; KS_FIFOPut(DPUSENDER_FIFO, &dpuSendMsg); length = 0; //nothing to copy since parameters were invalid } // if address is valid, perform the copy param.pDestBuffer = (int*)address; param.Size = length; checksumReceived = GetChecksum((int*)(param.pSrcBuffer), param.Size); checksumInPacket = (ReceptionBuffer[2 + param.Size] >> 16) & 0x0000FFFF; // compare the checksum received and the checksum computed on the received data if (checksumInPacket != checksumReceived) { dpuSendMsg.Header = LOAD_NACK; dpuSendMsg.Field1.ErrorCode = INVALID_CHECKSUM_RECEIVED; dpuSendMsg.Field2.Parameter = checksumReceived; KS_FIFOPut(DPUSENDER_FIFO, &dpuSendMsg); } else { KS_CriticalSection(MemcpyInCriticalSection, (void*)¶m); checksumAfterCopy = GetChecksum((int*)(param.pDestBuffer), param.Size); if (checksumReceived != checksumAfterCopy) { // send nack to DPU dpuSendMsg.Header = LOAD_NACK; dpuSendMsg.Field1.ErrorCode = INVALID_CHECKSUM_AFTER_COPY; dpuSendMsg.Field2.Parameter = checksumAfterCopy; KS_FIFOPut(DPUSENDER_FIFO, &dpuSendMsg); } else { // send ack to DPU dpuSendMsg.Header = LOAD_ACK; KS_FIFOPut(DPUSENDER_FIFO, &dpuSendMsg); } } } else // PRAM or other memory area { // send nack to DPU dpuSendMsg.Header = LOAD_NACK; dpuSendMsg.Field1.ErrorCode = INVALID_MEMORY_ID; dpuSendMsg.Field2.Parameter = memID >> 8; KS_FIFOPut(DPUSENDER_FIFO, &dpuSendMsg); } };break; case CHECK_CMD : { int memID; int address; int length; ReadWriteCommandParam param; //if a sequence is running, all commands but the DMC_ABORT_SEQUENCE must be rejected // if we are currently writing in EEPROM, we should also reject the check commands if ((IS(gpSequencer->TaskStatus, K_BMASK_TASK_STATUS_SEQ_EXECUTION_STATUS, K_BMASK_TASK_STATUS_SEQ_RUNNING)) || gParameters.CopyInEepromInProgress) { dpuSendMsg.Header = CHECK_NACK; dpuSendMsg.Field1.ErrorCode = COULD_NOT_EXECUTE_COMMAND; dpuSendMsg.Field2.Parameter = 0; KS_FIFOPut(DPUSENDER_FIFO, &dpuSendMsg); break; } //address is the 24 LSBits of ReceptionBuffer[0] and length is ReceptionBuffer[1] param.pSrcBuffer = (void*)&(ReceptionBuffer[2]); length = ReceptionBuffer[1] & 0x0000FFFF; memID = ReceptionBuffer[0] & 0x00001F00; address = ((ReceptionBuffer[0] & 0x000000FF) << 16) + ((ReceptionBuffer[1] >> 16) & 0x0000FFFF); if (memID == 0x00001100) // DRAM { if (address > (K_DMSIZE_DRAM-1)) { dpuSendMsg.Header = CHECK_NACK; dpuSendMsg.Field1.ErrorCode = INVALID_ADDRESS; dpuSendMsg.Field2.Parameter = address; KS_FIFOPut(DPUSENDER_FIFO, &dpuSendMsg); length = 0; //nothing to copy since parameters were invalid } else if ((address + length -1) > (K_DMSIZE_DRAM-1)) { dpuSendMsg.Header = CHECK_NACK; dpuSendMsg.Field1.ErrorCode = INVALID_LENGTH; dpuSendMsg.Field2.Parameter = length; KS_FIFOPut(DPUSENDER_FIFO, &dpuSendMsg); length = 0; //nothing to copy since parameters were invalid } // if address is valid, Compute the checksum // and send the packet to the DPU (through the DPU Sender) dpuSendMsg.Header = CHECK_ACK; dpuSendMsg.Field1.MemId = ReceptionBuffer[0] & 0x0000FFFF; dpuSendMsg.Field2.Address = ReceptionBuffer[1] & 0xFFFF0000; dpuSendMsg.Field3.LengthSAU = length; dpuSendMsg.Field4.Checksum = GetChecksum((int*)address, length); KS_FIFOPut(DPUSENDER_FIFO, &dpuSendMsg); } else if (memID == 0x00000100) //PRAM { //check address and length if (address > (K_PMSIZE_PRAM-1)) { dpuSendMsg.Header = CHECK_NACK; dpuSendMsg.Field1.ErrorCode = INVALID_ADDRESS; dpuSendMsg.Field2.Parameter = address; KS_FIFOPut(DPUSENDER_FIFO, &dpuSendMsg); length = 0; //nothing to copy since parameters were invalid } else if ((address + length -1) > (K_PMSIZE_PRAM-1)) { dpuSendMsg.Header = CHECK_NACK; dpuSendMsg.Field1.ErrorCode = INVALID_LENGTH; dpuSendMsg.Field2.Parameter = length; KS_FIFOPut(DPUSENDER_FIFO, &dpuSendMsg); length = 0; //nothing to copy since parameters were invalid } else { // if address is valid, Compute the checksum // and send the packet to the DPU (through the DPU Sender) dpuSendMsg.Header = CHECK_ACK; dpuSendMsg.Field1.MemId = ReceptionBuffer[0] & 0x0000FFFF; dpuSendMsg.Field2.Address = ReceptionBuffer[1] & 0xFFFF0000; dpuSendMsg.Field3.LengthSAU = length; dpuSendMsg.Field4.Checksum = GetChecksumInPram((int*)address, length); KS_FIFOPut(DPUSENDER_FIFO, &dpuSendMsg); } } else if (memID == 0x00000300) //EEPROM { //check address and length if (address > (K_PMSIZE_EEPROM - 1)) { dpuSendMsg.Header = DUMP_NACK; dpuSendMsg.Field1.ErrorCode = INVALID_ADDRESS; dpuSendMsg.Field2.Parameter = address; KS_FIFOPut(DPUSENDER_FIFO, &dpuSendMsg); break; } else if ((address + length -1) > (K_PMSIZE_EEPROM - 1)) { dpuSendMsg.Header = DUMP_NACK; dpuSendMsg.Field1.ErrorCode = INVALID_LENGTH; dpuSendMsg.Field2.Parameter = length; KS_FIFOPut(DPUSENDER_FIFO, &dpuSendMsg); break; } //apply offset address += K_PMADDR_BASE_EEPROM; // if address is valid, Compute the checksum // and send the packet to the DPU (through the DPU Sender) dpuSendMsg.Header = CHECK_ACK; dpuSendMsg.Field1.MemId = ReceptionBuffer[0] & 0x0000FFFF; dpuSendMsg.Field2.Address = ReceptionBuffer[1] & 0xFFFF0000; dpuSendMsg.Field3.LengthSAU = length; dpuSendMsg.Field4.Checksum = GetChecksumInPram((int*)address, length); KS_FIFOPut(DPUSENDER_FIFO, &dpuSendMsg); } else { // send nack to DPU dpuSendMsg.Header = CHECK_NACK; dpuSendMsg.Field1.ErrorCode = INVALID_MEMORY_ID; dpuSendMsg.Field2.Parameter = memID >> 8; KS_FIFOPut(DPUSENDER_FIFO, &dpuSendMsg); } };break; case WRITE_CMD : { ReadWriteCommandParam param; int paramID; int checksumReceived; int checksumAfterCopy; int checksumInPacket; //if a sequence is running, all commands but the DMC_ABORT_SEQUENCE must be rejected if (IS(gpSequencer->TaskStatus, K_BMASK_TASK_STATUS_SEQ_EXECUTION_STATUS, K_BMASK_TASK_STATUS_SEQ_RUNNING)) { dpuSendMsg.Header = WRITE_NACK; dpuSendMsg.Field1.ErrorCode = COULD_NOT_EXECUTE_COMMAND; dpuSendMsg.Field2.Parameter = 0; KS_FIFOPut(DPUSENDER_FIFO, &dpuSendMsg); break; } //paramId is the 16 MSBits of ReceptionBuffer[1] and length is the 16 LSB of ReceptionBuffer[1] paramID = (ReceptionBuffer[1] >> 16) & 0x0000FFFF; param.Size = ReceptionBuffer[1] & 0x0000FFFF; if (paramID >= NB_PARAMS) { // send nack to DPU dpuSendMsg.Header = WRITE_NACK; dpuSendMsg.Field1.ErrorCode = INVALID_PARAMETER_ID; dpuSendMsg.Field2.Parameter = paramID; KS_FIFOPut(DPUSENDER_FIFO, &dpuSendMsg); } else if (param.Size > apParametersSize[paramID]) { // send nack to DPU dpuSendMsg.Header = WRITE_NACK; dpuSendMsg.Field1.ErrorCode = INVALID_LENGTH; dpuSendMsg.Field2.Parameter = param.Size; KS_FIFOPut(DPUSENDER_FIFO, &dpuSendMsg); } else { param.pDestBuffer = apParametersAddress[paramID]; // extract address of destination buffer param.pSrcBuffer = (void*)&(ReceptionBuffer[2]); // source buffer is the message received from DPU (without header) checksumReceived = GetChecksum(&(ReceptionBuffer[2]), param.Size); checksumInPacket = (ReceptionBuffer[2 + param.Size] >> 16) & 0x0000FFFF; // compare the checksum received and the checksum computed on the received data if (checksumInPacket != checksumReceived) { dpuSendMsg.Header = WRITE_NACK; dpuSendMsg.Field1.ErrorCode = INVALID_CHECKSUM_RECEIVED; dpuSendMsg.Field2.Parameter = checksumReceived; KS_FIFOPut(DPUSENDER_FIFO, &dpuSendMsg); } else { // make the copy KS_CriticalSection(MemcpyInCriticalSection, (void*)¶m); checksumAfterCopy = GetChecksum((int*)(param.pDestBuffer), param.Size); // compare checksums if (checksumAfterCopy != checksumReceived) { // send nack to DPU dpuSendMsg.Header = WRITE_NACK; dpuSendMsg.Field1.ErrorCode = INVALID_CHECKSUM_AFTER_COPY; dpuSendMsg.Field2.Parameter = checksumAfterCopy; KS_FIFOPut(DPUSENDER_FIFO, &dpuSendMsg); } else { // send ack to DPU dpuSendMsg.Header = WRITE_ACK; KS_FIFOPut(DPUSENDER_FIFO, &dpuSendMsg); } } } };break; default : SetError(ERR_DPU_RECEIVER_UNKNOWN_MSG_TYPE); // send nack to DPU dpuSendMsg.Header = NACK_UNKNOWN_COMMAND; dpuSendMsg.Field1.ErrorCode = INVALID_COMMAND; dpuSendMsg.Field2.Parameter = (ReceptionBuffer[0] & 0xFFFF0000) >> 16; KS_FIFOPut(DPUSENDER_FIFO, &dpuSendMsg); }; } } /* FUNCTION : int MemcpyInCriticalSection(void* p_arg) *************************************************** AUTHOR : Amazy USE : Executes a memcpy inside a critical section. This function is called when executing a read/write command received from the DPU. Since this action must be performed inside a critical section (to prevent from other task modifying the memory in the same time), it must be included in a separate function PARAMS : ReadWriteCommandParam* p_arg : contains all the information mandatory to perform the copy */ int MemcpyInCriticalSection(void* p_arg) { ReadWriteCommandParam* p_param = (ReadWriteCommandParam*)p_arg; MEMCPY(p_param->pDestBuffer, p_param->pSrcBuffer, p_param->Size); return 0; }