Skip to content
Snippets Groups Projects
Commit 08097382 authored by Rolf Bork's avatar Rolf Bork
Browse files

Simply ran clang on commData3.c.

parent ba4d6a1e
No related branches found
No related tags found
No related merge requests found
/// @file commData3.c /// @file commData3.c
/// @brief This is the generic software for communicating realtime data between CDS applications. /// @brief This is the generic software for communicating realtime data
///between CDS applications.
/// @detail This software supports data communication via: \n /// @detail This software supports data communication via: \n
/// 1) Shared memory, between two processes on the same computer \n /// 1) Shared memory, between two processes on the same computer \n
/// 2) GE Fanuc 5565 Reflected Memory PCIe hardware \n /// 2) GE Fanuc 5565 Reflected Memory PCIe hardware \n
...@@ -8,139 +9,202 @@ ...@@ -8,139 +9,202 @@
/// @copyright Copyright (C) 2014 LIGO Project \n /// @copyright Copyright (C) 2014 LIGO Project \n
///< California Institute of Technology \n ///< California Institute of Technology \n
///< Massachusetts Institute of Technology \n\n ///< Massachusetts Institute of Technology \n\n
/// @license This program is free software: you can redistribute it and/or modify /// @license This program is free software: you can redistribute it and/or
/// modify
///< it under the terms of the GNU General Public License as published by ///< it under the terms of the GNU General Public License as published by
///< the Free Software Foundation, version 3 of the License. \n ///< the Free Software Foundation, version 3 of the License. \n This program
///< This program is distributed in the hope that it will be useful, ///< is distributed in the hope that it will be useful, but WITHOUT ANY
///< but WITHOUT ANY WARRANTY; without even the implied warranty of ///< WARRANTY; without even the implied warranty of MERCHANTABILITY or
///< MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ///< FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
///< GNU General Public License for more details. ///< for more details.
#include "commData3.h" #include "commData3.h"
// #include "isnan.h" // #include "isnan.h"
#include <asm/cacheflush.h> #include <asm/cacheflush.h>
#ifdef COMMDATA_INLINE #ifdef COMMDATA_INLINE
# define INLINE static inline #define INLINE static inline
#else #else
# define INLINE #define INLINE
#endif #endif
/// This function is called from the user application to initialize communications structures /// This function is called from the user application to initialize
/// and pointers. ///communications structures and pointers.
/// @param[in] connects = total number of IPC connections in the application /// @param[in] connects = total number of IPC connections in the application
/// @param[in] rate = Sample rate of the calling application eg 2048 /// @param[in] rate = Sample rate of the calling application eg 2048
/// @param[in,out] ipcInfo[] = Stucture to hold information about each IPC /// @param[in,out] ipcInfo[] = Stucture to hold information about each IPC
INLINE void commData3Init( INLINE void
int connects, // total number of IPC connections in the application commData3Init(
int rate, // Sample rate of the calling application eg 2048, 16384, etc. int connects, // total number of IPC connections in the application
CDS_IPC_INFO ipcInfo[] // IPC information structure int rate, // Sample rate of the calling application eg 2048, 16384, etc.
) CDS_IPC_INFO ipcInfo[] // IPC information structure
)
{ {
int ii; int ii;
unsigned long ipcMemOffset; unsigned long ipcMemOffset;
// printf("size of data block = 0x%x\n", sizeof(CDS_IPC_COMMS)); // printf("size of data block = 0x%x\n", sizeof(CDS_IPC_COMMS));
// printf("Dolphin num = %d \n",cdsPciModules.dolphinCount); // printf("Dolphin num = %d \n",cdsPciModules.dolphinCount);
// printf("\tLocal at 0x%x and 0x%x \n",cdsPciModules.dolphinRead[0],cdsPciModules.dolphinWrite[0]); // printf("\tLocal at 0x%x and 0x%x
// printf("\tRFM at 0x%x and 0x%x \n",cdsPciModules.dolphinRead[1],cdsPciModules.dolphinWrite[1]); // \n",cdsPciModules.dolphinRead[0],cdsPciModules.dolphinWrite[0]);
// printf("\tRFM at 0x%x and 0x%x
// \n",cdsPciModules.dolphinRead[1],cdsPciModules.dolphinWrite[1]);
#ifdef RFM_DELAY #ifdef RFM_DELAY
// printf("Model compiled with RFM DELAY !!\n"); // printf("Model compiled with RFM DELAY !!\n");
#endif #endif
for(ii=0;ii<connects;ii++) for ( ii = 0; ii < connects; ii++ )
{ {
// Set the sendCycle field, used by all send/rcv to determine IPC data block to write/read // Set the sendCycle field, used by all send/rcv to determine IPC data
// All cycle counts sent as part of data sync word are based on max supported rate of // block to write/read
// 65536 cycles/sec, regardless of sender/receiver native cycle rate. // All cycle counts sent as part of data sync word are based on max
ipcInfo[ii].sendCycle = IPC_MAX_RATE / rate; // supported rate of
// Sender always sends data at his native rate. It is the responsiblity of the reciever // 65536 cycles/sec, regardless of sender/receiver native cycle
// to sync to this rate, regardless of the rate of the receiver application. // rate.
if(ipcInfo[ii].mode == IRCV) // RCVR ipcInfo[ ii ].sendCycle = IPC_MAX_RATE / rate;
{ // Sender always sends data at his native rate. It is the responsiblity
if(ipcInfo[ii].sendRate >= rate) // of the reciever to sync to this rate, regardless of the rate of the
{ // receiver application.
ipcInfo[ii].rcvRate = ipcInfo[ii].sendRate / rate; if ( ipcInfo[ ii ].mode == IRCV ) // RCVR
ipcInfo[ii].rcvCycle = 1; {
} else { if ( ipcInfo[ ii ].sendRate >= rate )
ipcInfo[ii].rcvRate = rate / ipcInfo[ii].sendRate; {
ipcInfo[ii].rcvCycle = ipcInfo[ii].rcvRate; ipcInfo[ ii ].rcvRate = ipcInfo[ ii ].sendRate / rate;
} ipcInfo[ ii ].rcvCycle = 1;
} }
// Clear the data point else
ipcInfo[ii].data = 0.0; {
ipcInfo[ii].pIpcDataRead[0] = NULL; ipcInfo[ ii ].rcvRate = rate / ipcInfo[ ii ].sendRate;
ipcInfo[ii].pIpcDataWrite[0] = NULL; ipcInfo[ ii ].rcvCycle = ipcInfo[ ii ].rcvRate;
}
}
// Clear the data point
ipcInfo[ ii ].data = 0.0;
ipcInfo[ ii ].pIpcDataRead[ 0 ] = NULL;
ipcInfo[ ii ].pIpcDataWrite[ 0 ] = NULL;
#ifdef RFM_VIA_PCIE #ifdef RFM_VIA_PCIE
// Save pointers to the IPC communications memory locations. // Save pointers to the IPC communications memory locations.
if(ipcInfo[ii].netType == IRFM0) ipcMemOffset = IPC_PCIE_BASE_OFFSET + RFM0_OFFSET; if ( ipcInfo[ ii ].netType == IRFM0 )
if(ipcInfo[ii].netType == IRFM1) ipcMemOffset = IPC_PCIE_BASE_OFFSET + RFM1_OFFSET; ipcMemOffset = IPC_PCIE_BASE_OFFSET + RFM0_OFFSET;
if((ipcInfo[ii].netType == IRFM0 || ipcInfo[ii].netType == IRFM1) && (ipcInfo[ii].mode == ISND) && (cdsPciModules.dolphinWrite[1])) if ( ipcInfo[ ii ].netType == IRFM1 )
{ ipcMemOffset = IPC_PCIE_BASE_OFFSET + RFM1_OFFSET;
ipcInfo[ii].pIpcDataWrite[0] = (CDS_IPC_COMMS *)((volatile char *)(cdsPciModules.dolphinWrite[1]) + ipcMemOffset); if ( ( ipcInfo[ ii ].netType == IRFM0 ||
ipcInfo[ ii ].netType == IRFM1 ) &&
( ipcInfo[ ii ].mode == ISND ) &&
( cdsPciModules.dolphinWrite[ 1 ] ) )
{
ipcInfo[ ii ].pIpcDataWrite[ 0 ] =
(CDS_IPC_COMMS*)( (volatile char*)( cdsPciModules
.dolphinWrite[ 1 ] ) +
ipcMemOffset );
} }
if((ipcInfo[ii].netType == IRFM0 || ipcInfo[ii].netType == IRFM1) && (ipcInfo[ii].mode == IRCV) && (cdsPciModules.dolphinRead[1])) if ( ( ipcInfo[ ii ].netType == IRFM0 ||
{ ipcInfo[ ii ].netType == IRFM1 ) &&
ipcInfo[ii].pIpcDataRead[0] = (CDS_IPC_COMMS *)((volatile char *)(cdsPciModules.dolphinRead[1]) + ipcMemOffset); ( ipcInfo[ ii ].mode == IRCV ) &&
( cdsPciModules.dolphinRead[ 1 ] ) )
{
ipcInfo[ ii ].pIpcDataRead[ 0 ] =
(CDS_IPC_COMMS*)( (volatile char*)( cdsPciModules
.dolphinRead[ 1 ] ) +
ipcMemOffset );
} }
#else #else
// Use traditional RFM network // Use traditional RFM network
// Save pointers to the IPC communications memory locations. // Save pointers to the IPC communications memory locations.
if(ipcInfo[ii].netType == IRFM0) // VMIC Reflected Memory ******************************* if ( ipcInfo[ ii ].netType ==
IRFM0 ) // VMIC Reflected Memory *******************************
{ {
if(cdsPciModules.rfmCount > 0) { if ( cdsPciModules.rfmCount > 0 )
// Send side will perform direct, individual writes to RFM {
// Rcv side will use DMA, provided by IOP (Performance reasons ie without DMA, each read takes >2usec) // Send side will perform direct, individual writes to RFM
// Rcv side will use DMA, provided by IOP (Performance reasons
// ie without DMA, each read takes >2usec)
#ifdef RFM_DIRECT_READ #ifdef RFM_DIRECT_READ
ipcInfo[ii].pIpcDataRead[0] = (CDS_IPC_COMMS *)(cdsPciModules.pci_rfm[0] + IPC_BASE_OFFSET); ipcInfo[ ii ].pIpcDataRead[ 0 ] =
(CDS_IPC_COMMS*)( cdsPciModules.pci_rfm[ 0 ] +
IPC_BASE_OFFSET );
#else #else
ipcInfo[ii].pIpcDataRead[0] = (CDS_IPC_COMMS *)(cdsPciModules.pci_rfm_dma[0]); ipcInfo[ ii ].pIpcDataRead[ 0 ] =
(CDS_IPC_COMMS*)( cdsPciModules.pci_rfm_dma[ 0 ] );
#endif #endif
if(ipcInfo[ii].mode == ISND) ipcInfo[ii].pIpcDataWrite[0] = (CDS_IPC_COMMS *)(cdsPciModules.pci_rfm[0] + IPC_BASE_OFFSET); if ( ipcInfo[ ii ].mode == ISND )
} ipcInfo[ ii ].pIpcDataWrite[ 0 ] =
(CDS_IPC_COMMS*)( cdsPciModules.pci_rfm[ 0 ] +
IPC_BASE_OFFSET );
}
} }
if(ipcInfo[ii].netType == IRFM1) // VMIC Reflected Memory ******************************* if ( ipcInfo[ ii ].netType ==
IRFM1 ) // VMIC Reflected Memory *******************************
{ {
if(cdsPciModules.rfmCount > 1) { if ( cdsPciModules.rfmCount > 1 )
{
#ifdef RFM_DIRECT_READ #ifdef RFM_DIRECT_READ
ipcInfo[ii].pIpcDataRead[0] = (CDS_IPC_COMMS *)(cdsPciModules.pci_rfm[1] + IPC_BASE_OFFSET); ipcInfo[ ii ].pIpcDataRead[ 0 ] =
(CDS_IPC_COMMS*)( cdsPciModules.pci_rfm[ 1 ] +
IPC_BASE_OFFSET );
#else #else
ipcInfo[ii].pIpcDataRead[0] = (CDS_IPC_COMMS *)(cdsPciModules.pci_rfm_dma[1]); ipcInfo[ ii ].pIpcDataRead[ 0 ] =
(CDS_IPC_COMMS*)( cdsPciModules.pci_rfm_dma[ 1 ] );
#endif #endif
if(ipcInfo[ii].mode == ISND) ipcInfo[ii].pIpcDataWrite[0] = (CDS_IPC_COMMS *)(cdsPciModules.pci_rfm[1] + IPC_BASE_OFFSET); if ( ipcInfo[ ii ].mode == ISND )
} ipcInfo[ ii ].pIpcDataWrite[ 0 ] =
// If there isn't a second card (like in the end stations), default to first card (CDS_IPC_COMMS*)( cdsPciModules.pci_rfm[ 1 ] +
if(cdsPciModules.rfmCount == 1) { IPC_BASE_OFFSET );
}
// If there isn't a second card (like in the end stations), default
// to first card
if ( cdsPciModules.rfmCount == 1 )
{
#ifdef RFM_DIRECT_READ #ifdef RFM_DIRECT_READ
ipcInfo[ii].pIpcDataRead[0] = (CDS_IPC_COMMS *)(cdsPciModules.pci_rfm[0] + IPC_BASE_OFFSET); ipcInfo[ ii ].pIpcDataRead[ 0 ] =
(CDS_IPC_COMMS*)( cdsPciModules.pci_rfm[ 0 ] +
IPC_BASE_OFFSET );
#else #else
ipcInfo[ii].pIpcDataRead[0] = (CDS_IPC_COMMS *)(cdsPciModules.pci_rfm_dma[0]); ipcInfo[ ii ].pIpcDataRead[ 0 ] =
(CDS_IPC_COMMS*)( cdsPciModules.pci_rfm_dma[ 0 ] );
#endif #endif
if(ipcInfo[ii].mode == ISND) ipcInfo[ii].pIpcDataWrite[0] = (CDS_IPC_COMMS *)(cdsPciModules.pci_rfm[0] + IPC_BASE_OFFSET); if ( ipcInfo[ ii ].mode == ISND )
} ipcInfo[ ii ].pIpcDataWrite[ 0 ] =
(CDS_IPC_COMMS*)( cdsPciModules.pci_rfm[ 0 ] +
IPC_BASE_OFFSET );
}
} }
#endif #endif
if(ipcInfo[ii].netType == ISHME) // Computer shared memory ****************************** if ( ipcInfo[ ii ].netType ==
{ ISHME ) // Computer shared memory ******************************
if(ipcInfo[ii].mode == ISND) ipcInfo[ii].pIpcDataWrite[0] = (CDS_IPC_COMMS *)(_ipc_shm + IPC_BASE_OFFSET); {
else ipcInfo[ii].pIpcDataRead[0] = (CDS_IPC_COMMS *)(_ipc_shm + IPC_BASE_OFFSET); if ( ipcInfo[ ii ].mode == ISND )
ipcInfo[ ii ].pIpcDataWrite[ 0 ] =
(CDS_IPC_COMMS*)( _ipc_shm + IPC_BASE_OFFSET );
else
ipcInfo[ ii ].pIpcDataRead[ 0 ] =
(CDS_IPC_COMMS*)( _ipc_shm + IPC_BASE_OFFSET );
} }
// PCIe communications requires one pointer for sending data and a second one for receiving data. // PCIe communications requires one pointer for sending data and a
if((ipcInfo[ii].netType == IPCIE) && (ipcInfo[ii].mode == IRCV) && (cdsPciModules.dolphinRead[0])) // second one for receiving data.
{ if ( ( ipcInfo[ ii ].netType == IPCIE ) &&
ipcInfo[ii].pIpcDataRead[0] = (CDS_IPC_COMMS *)((volatile char *)(cdsPciModules.dolphinRead[0]) + IPC_PCIE_BASE_OFFSET); ( ipcInfo[ ii ].mode == IRCV ) &&
( cdsPciModules.dolphinRead[ 0 ] ) )
{
ipcInfo[ ii ].pIpcDataRead[ 0 ] =
(CDS_IPC_COMMS*)( (volatile char*)( cdsPciModules
.dolphinRead[ 0 ] ) +
IPC_PCIE_BASE_OFFSET );
} }
if((ipcInfo[ii].netType == IPCIE) && (ipcInfo[ii].mode == ISND) && (cdsPciModules.dolphinWrite[0])) if ( ( ipcInfo[ ii ].netType == IPCIE ) &&
{ ( ipcInfo[ ii ].mode == ISND ) &&
ipcInfo[ii].pIpcDataWrite[0] = (CDS_IPC_COMMS *)((volatile char *)(cdsPciModules.dolphinWrite[0]) + IPC_PCIE_BASE_OFFSET); ( cdsPciModules.dolphinWrite[ 0 ] ) )
// printf("Net Type = PCIE SEND IPC at 0x%p *********************************\n",ipcInfo[ii].pIpcData); {
ipcInfo[ ii ].pIpcDataWrite[ 0 ] =
(CDS_IPC_COMMS*)( (volatile char*)( cdsPciModules
.dolphinWrite[ 0 ] ) +
IPC_PCIE_BASE_OFFSET );
// printf("Net Type = PCIE SEND IPC at 0x%p
// *********************************\n",ipcInfo[ii].pIpcData);
} }
#if 0 #if 0
// Following for diags, if desired. Otherwise, leave out as it fills dmesg // Following for diags, if desired. Otherwise, leave out as it fills dmesg
if(ipcInfo[ii].mode == ISND && ipcInfo[ii].netType != ISHME) { if(ipcInfo[ii].mode == ISND && ipcInfo[ii].netType != ISHME) {
printf("IPC Number = %d\n",ipcInfo[ii].ipcNum); printf("IPC Number = %d\n",ipcInfo[ii].ipcNum);
...@@ -150,226 +214,288 @@ unsigned long ipcMemOffset; ...@@ -150,226 +214,288 @@ unsigned long ipcMemOffset;
printf("Send Computer Number = %d\n",ipcInfo[ii].sendNode); printf("Send Computer Number = %d\n",ipcInfo[ii].sendNode);
printf("Send address = %lx\n",(unsigned long)&ipcInfo[ii].pIpcDataWrite[0]->dBlock[0][ipcInfo[ii].ipcNum].data); printf("Send address = %lx\n",(unsigned long)&ipcInfo[ii].pIpcDataWrite[0]->dBlock[0][ipcInfo[ii].ipcNum].data);
} }
#endif #endif
}
// Send connection list to dmesg
for ( ii = 0; ii < connects; ii++ )
{
if ( ipcInfo[ ii ].mode == ISND && ipcInfo[ ii ].netType != ISHME )
{
// printf("IPC Name = %s
// \t%d\t%d\t%lx\t%lx\n",ipcInfo[ii].name,ipcInfo[ii].netType,ipcInfo[ii].ipcNum,
// (unsigned
// long)&ipcInfo[ii].pIpcDataWrite[0]->dBlock[0][ipcInfo[ii].ipcNum].data,
// (unsigned
// long)&ipcInfo[ii].pIpcDataWrite[0]->dBlock[63][ipcInfo[ii].ipcNum].timestamp);
}
} }
// Send connection list to dmesg
for(ii=0;ii<connects;ii++)
{
if(ipcInfo[ii].mode == ISND && ipcInfo[ii].netType != ISHME) {
// printf("IPC Name = %s \t%d\t%d\t%lx\t%lx\n",ipcInfo[ii].name,ipcInfo[ii].netType,ipcInfo[ii].ipcNum,
// (unsigned long)&ipcInfo[ii].pIpcDataWrite[0]->dBlock[0][ipcInfo[ii].ipcNum].data,
// (unsigned long)&ipcInfo[ii].pIpcDataWrite[0]->dBlock[63][ipcInfo[ii].ipcNum].timestamp);
}
}
} }
// ************************************************************************************************* // *************************************************************************************************
/// This function is called from the user application to send data via IPC connections. /// This function is called from the user application to send data via IPC
///connections.
/// @param[in] connects = total number of IPC connections in the application /// @param[in] connects = total number of IPC connections in the application
/// @param[in,out] ipcInfo[] = Stucture to hold information about each IPC /// @param[in,out] ipcInfo[] = Stucture to hold information about each IPC
/// @param[in] timeSec = Present GPS time in GPS seconds /// @param[in] timeSec = Present GPS time in GPS seconds
/// @param[in] cycle = Present cycle of the user application making this call. /// @param[in] cycle = Present cycle of the user application making this
INLINE void commData3Send(int connects, // Total number of IPC connections in the application ///call.
CDS_IPC_INFO ipcInfo[], // IPC information structure INLINE void commData3Send(
int timeSec, // Present GPS Second int connects, // Total number of IPC connections in the application
int cycle) // Application cycle count (0 to FE_CODE_RATE) CDS_IPC_INFO ipcInfo[], // IPC information structure
int timeSec, // Present GPS Second
int cycle ) // Application cycle count (0 to FE_CODE_RATE)
// This routine sends out all IPC data marked as a send (SND) channel in the IPC INFO list. // This routine sends out all IPC data marked as a send (SND) channel in the IPC
// Data is sent at the native rate of the calling application. // INFO list. Data is sent at the native rate of the calling application. Data
// Data sent is of type double, with timestamp and 65536 cycle count combined into long. // sent is of type double, with timestamp and 65536 cycle count combined into
// long.
{ {
unsigned long syncWord; /// \param syncWord Combined GPS timestamp and cycle counter unsigned long
int ipcIndex; /// \param ipcIndex Pointer to next IPC data buffer syncWord; /// \param syncWord Combined GPS timestamp and cycle counter
int dataCycle; /// \param dataCycle Cycle counter 0-65535 int ipcIndex; /// \param ipcIndex Pointer to next IPC data buffer
int ii = 0; /// \param ii Loop counter int dataCycle; /// \param dataCycle Cycle counter 0-65535
int chan; /// \param chan Local ipc number int ii = 0; /// \param ii Loop counter
int sendBlock; /// \param sendBlock Data block data is to be sent to int chan; /// \param chan Local ipc number
int lastPcie = -1; int sendBlock; /// \param sendBlock Data block data is to be sent to
int lastPcie = -1;
#ifdef RFM_DELAY #ifdef RFM_DELAY
// Need to write ahead one extra block // Need to write ahead one extra block
int mycycle = (cycle + 1); int mycycle = ( cycle + 1 );
sendBlock = ((mycycle + 1) * (IPC_MAX_RATE / IPC_RATE)) % IPC_BLOCKS; sendBlock = ( ( mycycle + 1 ) * ( IPC_MAX_RATE / IPC_RATE ) ) % IPC_BLOCKS;
dataCycle = ((mycycle + 1) * ipcInfo[0].sendCycle) % IPC_MAX_RATE; dataCycle = ( ( mycycle + 1 ) * ipcInfo[ 0 ].sendCycle ) % IPC_MAX_RATE;
if(dataCycle == 0 || dataCycle == ipcInfo[0].sendCycle) syncWord = timeSec + 1; if ( dataCycle == 0 || dataCycle == ipcInfo[ 0 ].sendCycle )
else syncWord = timeSec; syncWord = timeSec + 1;
syncWord = (syncWord << 32) + dataCycle; else
syncWord = timeSec;
syncWord = ( syncWord << 32 ) + dataCycle;
#else #else
sendBlock = ((cycle + 1) * (IPC_MAX_RATE / IPC_RATE)) % IPC_BLOCKS; sendBlock = ( ( cycle + 1 ) * ( IPC_MAX_RATE / IPC_RATE ) ) % IPC_BLOCKS;
// Calculate the SYNC word to be sent with all data. // Calculate the SYNC word to be sent with all data.
// Determine the cycle count to be sent with the data // Determine the cycle count to be sent with the data
dataCycle = ((cycle + 1) * ipcInfo[0].sendCycle) % IPC_MAX_RATE; dataCycle = ( ( cycle + 1 ) * ipcInfo[ 0 ].sendCycle ) % IPC_MAX_RATE;
// Since this is write ahead, need to increment the GPS second if // Since this is write ahead, need to increment the GPS second if
// writing to the first block of a new second. // writing to the first block of a new second.
if(dataCycle == 0) syncWord = timeSec + 1; if ( dataCycle == 0 )
else syncWord = timeSec; syncWord = timeSec + 1;
// Combine GPS seconds and cycle counter into long word. else
syncWord = (syncWord << 32) + dataCycle; syncWord = timeSec;
// Combine GPS seconds and cycle counter into long word.
syncWord = ( syncWord << 32 ) + dataCycle;
#endif #endif
// Want to send out RFM signals first to allow maximum time for data delivery. // Want to send out RFM signals first to allow maximum time for data
for(ii=0;ii<connects;ii++) // delivery.
{ for ( ii = 0; ii < connects; ii++ )
// If IPC Sender on RFM Network: {
// RFM network has highest latency, so want to get these signals out first. // If IPC Sender on RFM Network:
if((ipcInfo[ii].mode == ISND) && ((ipcInfo[ii].netType == IRFM0) || (ipcInfo[ii].netType == IRFM1))) // RFM network has highest latency, so want to get these signals out
// first.
if ( ( ipcInfo[ ii ].mode == ISND ) &&
( ( ipcInfo[ ii ].netType == IRFM0 ) ||
( ipcInfo[ ii ].netType == IRFM1 ) ) )
{ {
chan = ipcInfo[ii].ipcNum; chan = ipcInfo[ ii ].ipcNum;
// Determine next block to write in IPC_BLOCKS block buffer // Determine next block to write in IPC_BLOCKS block buffer
ipcIndex = ipcInfo[ii].ipcNum; ipcIndex = ipcInfo[ ii ].ipcNum;
// Don't write to PCI RFM if network error detected by IOP // Don't write to PCI RFM if network error detected by IOP
if(ipcInfo[ii].pIpcDataWrite[0] != NULL) if ( ipcInfo[ ii ].pIpcDataWrite[ 0 ] != NULL )
{ {
// Write Data // Write Data
ipcInfo[ii].pIpcDataWrite[0]->dBlock[sendBlock][ipcIndex].data = ipcInfo[ii].data; ipcInfo[ ii ]
// Write timestamp/cycle counter word .pIpcDataWrite[ 0 ]
ipcInfo[ii].pIpcDataWrite[0]->dBlock[sendBlock][ipcIndex].timestamp = syncWord; ->dBlock[ sendBlock ][ ipcIndex ]
#ifdef RFM_VIA_PCIE .data = ipcInfo[ ii ].data;
lastPcie = ii; // Write timestamp/cycle counter word
#endif ipcInfo[ ii ]
} .pIpcDataWrite[ 0 ]
} ->dBlock[ sendBlock ][ ipcIndex ]
} .timestamp = syncWord;
// Flush out the last PCIe transmission #ifdef RFM_VIA_PCIE
#ifdef RFM_VIA_PCIE lastPcie = ii;
if (lastPcie >= 0) { #endif
clflush_cache_range (&(ipcInfo[lastPcie].pIpcDataWrite[0]->dBlock[sendBlock][ipcInfo[lastPcie].ipcNum].data), 16); }
} }
lastPcie = -1; }
#endif // Flush out the last PCIe transmission
#ifdef RFM_VIA_PCIE
if ( lastPcie >= 0 )
{
clflush_cache_range(
&( ipcInfo[ lastPcie ]
.pIpcDataWrite[ 0 ]
->dBlock[ sendBlock ][ ipcInfo[ lastPcie ].ipcNum ]
.data ),
16 );
}
lastPcie = -1;
#endif
#ifdef RFM_DELAY #ifdef RFM_DELAY
// We don't want to delay SHMEM or PCIe writes, so calc block as usual, // We don't want to delay SHMEM or PCIe writes, so calc block as usual,
// so need to recalc send block and syncWord. // so need to recalc send block and syncWord.
sendBlock = ((cycle + 1) * (IPC_MAX_RATE / IPC_RATE)) % IPC_BLOCKS; sendBlock = ( ( cycle + 1 ) * ( IPC_MAX_RATE / IPC_RATE ) ) % IPC_BLOCKS;
// Calculate the SYNC word to be sent with all data. // Calculate the SYNC word to be sent with all data.
// Determine the cycle count to be sent with the data // Determine the cycle count to be sent with the data
dataCycle = ((cycle + 1) * ipcInfo[0].sendCycle) % IPC_MAX_RATE; dataCycle = ( ( cycle + 1 ) * ipcInfo[ 0 ].sendCycle ) % IPC_MAX_RATE;
// Since this is write ahead, need to increment the GPS second if // Since this is write ahead, need to increment the GPS second if
// writing to the first block of a new second. // writing to the first block of a new second.
if(dataCycle == 0) syncWord = timeSec + 1; if ( dataCycle == 0 )
else syncWord = timeSec; syncWord = timeSec + 1;
// Combine GPS seconds and cycle counter into long word. else
syncWord = (syncWord << 32) + dataCycle; syncWord = timeSec;
// Combine GPS seconds and cycle counter into long word.
syncWord = ( syncWord << 32 ) + dataCycle;
#endif #endif
for(ii=0;ii<connects;ii++) for ( ii = 0; ii < connects; ii++ )
{ {
// If IPC Sender on PCIE Network or via Shared Memory: // If IPC Sender on PCIE Network or via Shared Memory:
if((ipcInfo[ii].mode == ISND) && ((ipcInfo[ii].netType == ISHME) || (ipcInfo[ii].netType == IPCIE))) if ( ( ipcInfo[ ii ].mode == ISND ) &&
( ( ipcInfo[ ii ].netType == ISHME ) ||
( ipcInfo[ ii ].netType == IPCIE ) ) )
{ {
chan = ipcInfo[ii].ipcNum; chan = ipcInfo[ ii ].ipcNum;
// Determine next block to write in IPC_BLOCKS block buffer // Determine next block to write in IPC_BLOCKS block buffer
ipcIndex = ipcInfo[ii].ipcNum; ipcIndex = ipcInfo[ ii ].ipcNum;
// Don't write to PCI RFM if network error detected by IOP // Don't write to PCI RFM if network error detected by IOP
if(ipcInfo[ii].pIpcDataWrite[0] != NULL) if ( ipcInfo[ ii ].pIpcDataWrite[ 0 ] != NULL )
{ {
// Write Data // Write Data
ipcInfo[ii].pIpcDataWrite[0]->dBlock[sendBlock][ipcIndex].data = ipcInfo[ii].data; ipcInfo[ ii ]
// Write timestamp/cycle counter word .pIpcDataWrite[ 0 ]
ipcInfo[ii].pIpcDataWrite[0]->dBlock[sendBlock][ipcIndex].timestamp = syncWord; ->dBlock[ sendBlock ][ ipcIndex ]
if(ipcInfo[ii].netType == IPCIE) { .data = ipcInfo[ ii ].data;
lastPcie = ii; // Write timestamp/cycle counter word
} ipcInfo[ ii ]
} .pIpcDataWrite[ 0 ]
->dBlock[ sendBlock ][ ipcIndex ]
.timestamp = syncWord;
if ( ipcInfo[ ii ].netType == IPCIE )
{
lastPcie = ii;
}
}
} }
} }
// Flush out the last PCIe transmission // Flush out the last PCIe transmission
if (lastPcie >= 0) { if ( lastPcie >= 0 )
clflush_cache_range (&(ipcInfo[lastPcie].pIpcDataWrite[0]->dBlock[sendBlock][ipcInfo[lastPcie].ipcNum].data), 16); {
} clflush_cache_range(
&( ipcInfo[ lastPcie ]
.pIpcDataWrite[ 0 ]
->dBlock[ sendBlock ][ ipcInfo[ lastPcie ].ipcNum ]
.data ),
16 );
}
} }
// ************************************************************************************************* // *************************************************************************************************
/// This function is called from the user application to receive data via IPC connections. /// This function is called from the user application to receive data via
///IPC connections.
/// @param[in] connects = total number of IPC connections in the application /// @param[in] connects = total number of IPC connections in the application
/// @param[in,out] ipcInfo[] = Stucture to hold information about each IPC /// @param[in,out] ipcInfo[] = Stucture to hold information about each IPC
/// @param[in] timeSec = Present GPS time in GPS seconds /// @param[in] timeSec = Present GPS time in GPS seconds
/// @param[in] cycle = Present cycle of the user application making this call. /// @param[in] cycle = Present cycle of the user application making this
INLINE void commData3Receive(int connects, // Total number of IPC connections in the application ///call.
CDS_IPC_INFO ipcInfo[], // IPC information structure INLINE void commData3Receive(
int timeSec, // Present GPS Second int connects, // Total number of IPC connections in the application
int cycle) // Application cycle count (0 to FE_CODE_RATE) CDS_IPC_INFO ipcInfo[], // IPC information structure
int timeSec, // Present GPS Second
int cycle ) // Application cycle count (0 to FE_CODE_RATE)
// This routine receives all IPC data marked as a read (RCV) channel in the IPC INFO list. // This routine receives all IPC data marked as a read (RCV) channel in the IPC
// INFO list.
{ {
unsigned long syncWord; // Combined GPS timestamp and cycle counter word received with data unsigned long syncWord; // Combined GPS timestamp and cycle counter word
unsigned long mySyncWord; // Local version of syncWord for comparison and error detection // received with data
int ipcIndex; // Pointer to next IPC data buffer unsigned long mySyncWord; // Local version of syncWord for comparison and
int cycle65k; // All data sent with 64K cycle count; need to convert local app cycle count to match // error detection
int ii; int ipcIndex; // Pointer to next IPC data buffer
int rcvBlock; // Which of the IPC_BLOCKS IPC data blocks to read from int cycle65k; // All data sent with 64K cycle count; need to convert local
double tmp; // Temp location for data for checking NaN // app cycle count to match
// static unsigned long ptim = 0; // last printing time int ii;
// static unsigned long nskipped = 0; // number of skipped error messages (couldn't print that fast) int rcvBlock; // Which of the IPC_BLOCKS IPC data blocks to read from
double tmp; // Temp location for data for checking NaN
// static unsigned long ptim = 0; // last printing time
// static unsigned long nskipped = 0; // number of skipped error messages
// (couldn't print that fast)
// Determine which block to read, based on present code cycle // Determine which block to read, based on present code cycle
rcvBlock = ((cycle) * (IPC_MAX_RATE / IPC_RATE)) % IPC_BLOCKS; rcvBlock = ( ( cycle ) * ( IPC_MAX_RATE / IPC_RATE ) ) % IPC_BLOCKS;
for(ii=0;ii<connects;ii++) for ( ii = 0; ii < connects; ii++ )
{ {
if(ipcInfo[ii].mode == IRCV) // Zero = Rcv and One = Send if ( ipcInfo[ ii ].mode == IRCV ) // Zero = Rcv and One = Send
{ {
if(!(cycle % ipcInfo[ii].rcvCycle)) // Time to rcv if ( !( cycle % ipcInfo[ ii ].rcvCycle ) ) // Time to rcv
{ {
// Determine which data block to read when RCVR runs faster than sender // Determine which data block to read when RCVR runs faster than
// if(ipcInfo[ii].rcvCycle > 1) ipcIndex = (cycle / ipcInfo[ii].rcvCycle) % 64; // sender if(ipcInfo[ii].rcvCycle > 1) ipcIndex = (cycle /
// ipcInfo[ii].rcvCycle) % 64;
// Data block to read if RCVR runs same speed or slower than sender // Data block to read if RCVR runs same speed or slower than
// else ipcIndex = (cycle * ipcInfo[ii].rcvRate) % 64; // sender else ipcIndex = (cycle * ipcInfo[ii].rcvRate) % 64;
if(ipcInfo[ii].pIpcDataRead[0] != NULL)
{
ipcIndex = ipcInfo[ii].ipcNum; if ( ipcInfo[ ii ].pIpcDataRead[ 0 ] != NULL )
// Read GPS time/cycle count {
tmp = ipcInfo[ii].pIpcDataRead[0]->dBlock[rcvBlock][ipcIndex].data;
syncWord = ipcInfo[ii].pIpcDataRead[0]->dBlock[rcvBlock][ipcIndex].timestamp; ipcIndex = ipcInfo[ ii ].ipcNum;
// Create local 65K cycle count // Read GPS time/cycle count
cycle65k = ((cycle * ipcInfo[ii].sendCycle)); tmp = ipcInfo[ ii ]
mySyncWord = timeSec; .pIpcDataRead[ 0 ]
// Create local GPS time/cycle word for comparison to ipc ->dBlock[ rcvBlock ][ ipcIndex ]
mySyncWord = (mySyncWord << 32) + cycle65k; .data;
// If IPC syncword = local syncword, data is good syncWord = ipcInfo[ ii ]
if(syncWord == mySyncWord) .pIpcDataRead[ 0 ]
{ ->dBlock[ rcvBlock ][ ipcIndex ]
ipcInfo[ii].data = tmp; .timestamp;
// If IPC syncword != local syncword, data is BAD // Create local 65K cycle count
// Set error and leave value same as last good receive cycle65k = ( ( cycle * ipcInfo[ ii ].sendCycle ) );
} else { mySyncWord = timeSec;
ipcInfo[ii].errFlag ++; // Create local GPS time/cycle word for comparison to ipc
} mySyncWord = ( mySyncWord << 32 ) + cycle65k;
} else { // If IPC syncword = local syncword, data is good
ipcInfo[ii].errFlag ++; if ( syncWord == mySyncWord )
} {
} ipcInfo[ ii ].data = tmp;
// Send error per second output // If IPC syncword != local syncword, data is BAD
//if(cycle == 0) // Set error and leave value same as last good receive
//{ }
// if (ipcInfo[ii].errFlag) ipcErrBits |= 1 << (ipcInfo[ii].netType); else
// else ipcErrBits &= ~(1 << (ipcInfo[ii].netType)); {
// ipcInfo[ii].errFlag = 0; ipcInfo[ ii ].errFlag++;
// } }
}
else
{
ipcInfo[ ii ].errFlag++;
}
}
// Send error per second output
// if(cycle == 0)
//{
// if (ipcInfo[ii].errFlag) ipcErrBits |= 1 <<
// (ipcInfo[ii].netType); else ipcErrBits &= ~(1 <<
// (ipcInfo[ii].netType)); ipcInfo[ii].errFlag = 0;
// }
} }
} }
// On cycle 0, set error flags to send back to EPICS // On cycle 0, set error flags to send back to EPICS
if(cycle == 0) if ( cycle == 0 )
{ {
ipcErrBits = ipcErrBits & 0xf0; ipcErrBits = ipcErrBits & 0xf0;
for(ii=0;ii<connects;ii++) for ( ii = 0; ii < connects; ii++ )
{ {
if(ipcInfo[ii].mode == IRCV) // Zero = Rcv and One = Send if ( ipcInfo[ ii ].mode == IRCV ) // Zero = Rcv and One = Send
{ {
ipcInfo[ii].errTotal = ipcInfo[ii].errFlag; ipcInfo[ ii ].errTotal = ipcInfo[ ii ].errFlag;
if (ipcInfo[ii].errFlag) { if ( ipcInfo[ ii ].errFlag )
ipcErrBits |= 1 << (ipcInfo[ii].netType); {
ipcErrBits |= 16 << (ipcInfo[ii].netType);; ipcErrBits |= 1 << ( ipcInfo[ ii ].netType );
} ipcErrBits |= 16 << ( ipcInfo[ ii ].netType );
ipcInfo[ii].errFlag = 0; ;
} }
} ipcInfo[ ii ].errFlag = 0;
} }
}
}
} }
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment