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
/// @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
/// 1) Shared memory, between two processes on the same computer \n
/// 2) GE Fanuc 5565 Reflected Memory PCIe hardware \n
......@@ -8,139 +9,202 @@
/// @copyright Copyright (C) 2014 LIGO Project \n
///< California Institute of Technology \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
///< the Free Software Foundation, version 3 of the License. \n
///< This program is distributed in the hope that it will be useful,
///< but WITHOUT ANY WARRANTY; without even the implied warranty of
///< MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
///< GNU General Public License for more details.
///< the Free Software Foundation, version 3 of the License. \n This program
///< is distributed in the hope that it will be useful, but WITHOUT ANY
///< WARRANTY; without even the implied warranty of MERCHANTABILITY or
///< FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
///< for more details.
#include "commData3.h"
// #include "isnan.h"
#include <asm/cacheflush.h>
#ifdef COMMDATA_INLINE
# define INLINE static inline
#define INLINE static inline
#else
# define INLINE
#define INLINE
#endif
/// This function is called from the user application to initialize communications structures
/// and pointers.
/// This function is called from the user application to initialize
///communications structures and pointers.
/// @param[in] connects = total number of IPC connections in the application
/// @param[in] rate = Sample rate of the calling application eg 2048
/// @param[in,out] ipcInfo[] = Stucture to hold information about each IPC
INLINE void commData3Init(
int connects, // total number of IPC connections in the application
int rate, // Sample rate of the calling application eg 2048, 16384, etc.
CDS_IPC_INFO ipcInfo[] // IPC information structure
)
INLINE void
commData3Init(
int connects, // total number of IPC connections in the application
int rate, // Sample rate of the calling application eg 2048, 16384, etc.
CDS_IPC_INFO ipcInfo[] // IPC information structure
)
{
int ii;
unsigned long ipcMemOffset;
int ii;
unsigned long ipcMemOffset;
// printf("size of data block = 0x%x\n", sizeof(CDS_IPC_COMMS));
// printf("Dolphin num = %d \n",cdsPciModules.dolphinCount);
// printf("\tLocal at 0x%x and 0x%x \n",cdsPciModules.dolphinRead[0],cdsPciModules.dolphinWrite[0]);
// printf("\tRFM at 0x%x and 0x%x \n",cdsPciModules.dolphinRead[1],cdsPciModules.dolphinWrite[1]);
// printf("\tLocal at 0x%x and 0x%x
// \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
// printf("Model compiled with RFM DELAY !!\n");
#endif
for(ii=0;ii<connects;ii++)
{
// Set the sendCycle field, used by all send/rcv to determine IPC data block to write/read
// All cycle counts sent as part of data sync word are based on max supported rate of
// 65536 cycles/sec, regardless of sender/receiver native cycle rate.
ipcInfo[ii].sendCycle = IPC_MAX_RATE / rate;
// Sender always sends data at his native rate. It is the responsiblity of the reciever
// to sync to this rate, regardless of the rate of the receiver application.
if(ipcInfo[ii].mode == IRCV) // RCVR
{
if(ipcInfo[ii].sendRate >= rate)
{
ipcInfo[ii].rcvRate = ipcInfo[ii].sendRate / rate;
ipcInfo[ii].rcvCycle = 1;
} else {
ipcInfo[ii].rcvRate = rate / ipcInfo[ii].sendRate;
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;
for ( ii = 0; ii < connects; ii++ )
{
// Set the sendCycle field, used by all send/rcv to determine IPC data
// block to write/read
// All cycle counts sent as part of data sync word are based on max
// supported rate of
// 65536 cycles/sec, regardless of sender/receiver native cycle
// rate.
ipcInfo[ ii ].sendCycle = IPC_MAX_RATE / rate;
// Sender always sends data at his native rate. It is the responsiblity
// of the reciever to sync to this rate, regardless of the rate of the
// receiver application.
if ( ipcInfo[ ii ].mode == IRCV ) // RCVR
{
if ( ipcInfo[ ii ].sendRate >= rate )
{
ipcInfo[ ii ].rcvRate = ipcInfo[ ii ].sendRate / rate;
ipcInfo[ ii ].rcvCycle = 1;
}
else
{
ipcInfo[ ii ].rcvRate = rate / ipcInfo[ ii ].sendRate;
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
// Save pointers to the IPC communications memory locations.
if(ipcInfo[ii].netType == IRFM0) ipcMemOffset = IPC_PCIE_BASE_OFFSET + RFM0_OFFSET;
if(ipcInfo[ii].netType == IRFM1) ipcMemOffset = IPC_PCIE_BASE_OFFSET + RFM1_OFFSET;
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);
// Save pointers to the IPC communications memory locations.
if ( ipcInfo[ ii ].netType == IRFM0 )
ipcMemOffset = IPC_PCIE_BASE_OFFSET + RFM0_OFFSET;
if ( ipcInfo[ ii ].netType == IRFM1 )
ipcMemOffset = IPC_PCIE_BASE_OFFSET + RFM1_OFFSET;
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]))
{
ipcInfo[ii].pIpcDataRead[0] = (CDS_IPC_COMMS *)((volatile char *)(cdsPciModules.dolphinRead[1]) + ipcMemOffset);
if ( ( ipcInfo[ ii ].netType == IRFM0 ||
ipcInfo[ ii ].netType == IRFM1 ) &&
( ipcInfo[ ii ].mode == IRCV ) &&
( cdsPciModules.dolphinRead[ 1 ] ) )
{
ipcInfo[ ii ].pIpcDataRead[ 0 ] =
(CDS_IPC_COMMS*)( (volatile char*)( cdsPciModules
.dolphinRead[ 1 ] ) +
ipcMemOffset );
}
#else
// Use traditional RFM network
// Use traditional RFM network
// 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) {
// 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)
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)
#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
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
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
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
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
if(ipcInfo[ii].mode == ISND) ipcInfo[ii].pIpcDataWrite[0] = (CDS_IPC_COMMS *)(cdsPciModules.pci_rfm[1] + IPC_BASE_OFFSET);
}
// If there isn't a second card (like in the end stations), default to first card
if(cdsPciModules.rfmCount == 1) {
if ( ipcInfo[ ii ].mode == ISND )
ipcInfo[ ii ].pIpcDataWrite[ 0 ] =
(CDS_IPC_COMMS*)( cdsPciModules.pci_rfm[ 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
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
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
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
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 ].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 );
}
// PCIe communications requires one pointer for sending data and a second one for receiving data.
if((ipcInfo[ii].netType == IPCIE) && (ipcInfo[ii].mode == IRCV) && (cdsPciModules.dolphinRead[0]))
{
ipcInfo[ii].pIpcDataRead[0] = (CDS_IPC_COMMS *)((volatile char *)(cdsPciModules.dolphinRead[0]) + IPC_PCIE_BASE_OFFSET);
// PCIe communications requires one pointer for sending data and a
// second one for receiving data.
if ( ( ipcInfo[ ii ].netType == IPCIE ) &&
( 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]))
{
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 ( ( ipcInfo[ ii ].netType == IPCIE ) &&
( ipcInfo[ ii ].mode == ISND ) &&
( cdsPciModules.dolphinWrite[ 0 ] ) )
{
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
if(ipcInfo[ii].mode == ISND && ipcInfo[ii].netType != ISHME) {
printf("IPC Number = %d\n",ipcInfo[ii].ipcNum);
......@@ -150,226 +214,288 @@ unsigned long ipcMemOffset;
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);
}
#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,out] ipcInfo[] = Stucture to hold information about each IPC
/// @param[in] timeSec = Present GPS time in GPS seconds
/// @param[in] cycle = Present cycle of the user application making this call.
INLINE void commData3Send(int connects, // Total number of IPC connections in the application
CDS_IPC_INFO ipcInfo[], // IPC information structure
int timeSec, // Present GPS Second
int cycle) // Application cycle count (0 to FE_CODE_RATE)
/// @param[in] cycle = Present cycle of the user application making this
///call.
INLINE void commData3Send(
int connects, // Total number of IPC connections in the application
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.
// Data is sent at the native rate of the calling application.
// Data sent is of type double, with timestamp and 65536 cycle count combined into long.
// This routine sends out all IPC data marked as a send (SND) channel in the IPC
// INFO list. Data is sent at the native rate of the calling application. Data
// 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
int ipcIndex; /// \param ipcIndex Pointer to next IPC data buffer
int dataCycle; /// \param dataCycle Cycle counter 0-65535
int ii = 0; /// \param ii Loop counter
int chan; /// \param chan Local ipc number
int sendBlock; /// \param sendBlock Data block data is to be sent to
int lastPcie = -1;
unsigned long
syncWord; /// \param syncWord Combined GPS timestamp and cycle counter
int ipcIndex; /// \param ipcIndex Pointer to next IPC data buffer
int dataCycle; /// \param dataCycle Cycle counter 0-65535
int ii = 0; /// \param ii Loop counter
int chan; /// \param chan Local ipc number
int sendBlock; /// \param sendBlock Data block data is to be sent to
int lastPcie = -1;
#ifdef RFM_DELAY
// Need to write ahead one extra block
int mycycle = (cycle + 1);
sendBlock = ((mycycle + 1) * (IPC_MAX_RATE / IPC_RATE)) % IPC_BLOCKS;
dataCycle = ((mycycle + 1) * ipcInfo[0].sendCycle) % IPC_MAX_RATE;
if(dataCycle == 0 || dataCycle == ipcInfo[0].sendCycle) syncWord = timeSec + 1;
else syncWord = timeSec;
syncWord = (syncWord << 32) + dataCycle;
// Need to write ahead one extra block
int mycycle = ( cycle + 1 );
sendBlock = ( ( mycycle + 1 ) * ( IPC_MAX_RATE / IPC_RATE ) ) % IPC_BLOCKS;
dataCycle = ( ( mycycle + 1 ) * ipcInfo[ 0 ].sendCycle ) % IPC_MAX_RATE;
if ( dataCycle == 0 || dataCycle == ipcInfo[ 0 ].sendCycle )
syncWord = timeSec + 1;
else
syncWord = timeSec;
syncWord = ( syncWord << 32 ) + dataCycle;
#else
sendBlock = ((cycle + 1) * (IPC_MAX_RATE / IPC_RATE)) % IPC_BLOCKS;
// Calculate the SYNC word to be sent with all data.
// Determine the cycle count to be sent with the data
dataCycle = ((cycle + 1) * ipcInfo[0].sendCycle) % IPC_MAX_RATE;
// Since this is write ahead, need to increment the GPS second if
// writing to the first block of a new second.
if(dataCycle == 0) syncWord = timeSec + 1;
else syncWord = timeSec;
// Combine GPS seconds and cycle counter into long word.
syncWord = (syncWord << 32) + dataCycle;
sendBlock = ( ( cycle + 1 ) * ( IPC_MAX_RATE / IPC_RATE ) ) % IPC_BLOCKS;
// Calculate the SYNC word to be sent with all data.
// Determine the cycle count to be sent with the data
dataCycle = ( ( cycle + 1 ) * ipcInfo[ 0 ].sendCycle ) % IPC_MAX_RATE;
// Since this is write ahead, need to increment the GPS second if
// writing to the first block of a new second.
if ( dataCycle == 0 )
syncWord = timeSec + 1;
else
syncWord = timeSec;
// Combine GPS seconds and cycle counter into long word.
syncWord = ( syncWord << 32 ) + dataCycle;
#endif
// Want to send out RFM signals first to allow maximum time for data 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((ipcInfo[ii].mode == ISND) && ((ipcInfo[ii].netType == IRFM0) || (ipcInfo[ii].netType == IRFM1)))
// Want to send out RFM signals first to allow maximum time for data
// 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 ( ( ipcInfo[ ii ].mode == ISND ) &&
( ( ipcInfo[ ii ].netType == IRFM0 ) ||
( ipcInfo[ ii ].netType == IRFM1 ) ) )
{
chan = ipcInfo[ii].ipcNum;
// Determine next block to write in IPC_BLOCKS block buffer
ipcIndex = ipcInfo[ii].ipcNum;
// Don't write to PCI RFM if network error detected by IOP
if(ipcInfo[ii].pIpcDataWrite[0] != NULL)
{
// Write Data
ipcInfo[ii].pIpcDataWrite[0]->dBlock[sendBlock][ipcIndex].data = ipcInfo[ii].data;
// Write timestamp/cycle counter word
ipcInfo[ii].pIpcDataWrite[0]->dBlock[sendBlock][ipcIndex].timestamp = syncWord;
#ifdef RFM_VIA_PCIE
lastPcie = ii;
#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
chan = ipcInfo[ ii ].ipcNum;
// Determine next block to write in IPC_BLOCKS block buffer
ipcIndex = ipcInfo[ ii ].ipcNum;
// Don't write to PCI RFM if network error detected by IOP
if ( ipcInfo[ ii ].pIpcDataWrite[ 0 ] != NULL )
{
// Write Data
ipcInfo[ ii ]
.pIpcDataWrite[ 0 ]
->dBlock[ sendBlock ][ ipcIndex ]
.data = ipcInfo[ ii ].data;
// Write timestamp/cycle counter word
ipcInfo[ ii ]
.pIpcDataWrite[ 0 ]
->dBlock[ sendBlock ][ ipcIndex ]
.timestamp = syncWord;
#ifdef RFM_VIA_PCIE
lastPcie = ii;
#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
// We don't want to delay SHMEM or PCIe writes, so calc block as usual,
// so need to recalc send block and syncWord.
sendBlock = ((cycle + 1) * (IPC_MAX_RATE / IPC_RATE)) % IPC_BLOCKS;
// Calculate the SYNC word to be sent with all data.
// Determine the cycle count to be sent with the data
dataCycle = ((cycle + 1) * ipcInfo[0].sendCycle) % IPC_MAX_RATE;
// Since this is write ahead, need to increment the GPS second if
// writing to the first block of a new second.
if(dataCycle == 0) syncWord = timeSec + 1;
else syncWord = timeSec;
// Combine GPS seconds and cycle counter into long word.
syncWord = (syncWord << 32) + dataCycle;
// We don't want to delay SHMEM or PCIe writes, so calc block as usual,
// so need to recalc send block and syncWord.
sendBlock = ( ( cycle + 1 ) * ( IPC_MAX_RATE / IPC_RATE ) ) % IPC_BLOCKS;
// Calculate the SYNC word to be sent with all data.
// Determine the cycle count to be sent with the data
dataCycle = ( ( cycle + 1 ) * ipcInfo[ 0 ].sendCycle ) % IPC_MAX_RATE;
// Since this is write ahead, need to increment the GPS second if
// writing to the first block of a new second.
if ( dataCycle == 0 )
syncWord = timeSec + 1;
else
syncWord = timeSec;
// Combine GPS seconds and cycle counter into long word.
syncWord = ( syncWord << 32 ) + dataCycle;
#endif
for(ii=0;ii<connects;ii++)
{
// If IPC Sender on PCIE Network or via Shared Memory:
if((ipcInfo[ii].mode == ISND) && ((ipcInfo[ii].netType == ISHME) || (ipcInfo[ii].netType == IPCIE)))
for ( ii = 0; ii < connects; ii++ )
{
// If IPC Sender on PCIE Network or via Shared Memory:
if ( ( ipcInfo[ ii ].mode == ISND ) &&
( ( ipcInfo[ ii ].netType == ISHME ) ||
( ipcInfo[ ii ].netType == IPCIE ) ) )
{
chan = ipcInfo[ii].ipcNum;
// Determine next block to write in IPC_BLOCKS block buffer
ipcIndex = ipcInfo[ii].ipcNum;
// Don't write to PCI RFM if network error detected by IOP
if(ipcInfo[ii].pIpcDataWrite[0] != NULL)
{
// Write Data
ipcInfo[ii].pIpcDataWrite[0]->dBlock[sendBlock][ipcIndex].data = ipcInfo[ii].data;
// Write timestamp/cycle counter word
ipcInfo[ii].pIpcDataWrite[0]->dBlock[sendBlock][ipcIndex].timestamp = syncWord;
if(ipcInfo[ii].netType == IPCIE) {
lastPcie = ii;
}
}
chan = ipcInfo[ ii ].ipcNum;
// Determine next block to write in IPC_BLOCKS block buffer
ipcIndex = ipcInfo[ ii ].ipcNum;
// Don't write to PCI RFM if network error detected by IOP
if ( ipcInfo[ ii ].pIpcDataWrite[ 0 ] != NULL )
{
// Write Data
ipcInfo[ ii ]
.pIpcDataWrite[ 0 ]
->dBlock[ sendBlock ][ ipcIndex ]
.data = ipcInfo[ ii ].data;
// 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
if (lastPcie >= 0) {
clflush_cache_range (&(ipcInfo[lastPcie].pIpcDataWrite[0]->dBlock[sendBlock][ipcInfo[lastPcie].ipcNum].data), 16);
}
}
// Flush out the last PCIe transmission
if ( lastPcie >= 0 )
{
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,out] ipcInfo[] = Stucture to hold information about each IPC
/// @param[in] timeSec = Present GPS time in GPS seconds
/// @param[in] cycle = Present cycle of the user application making this call.
INLINE void commData3Receive(int connects, // Total number of IPC connections in the application
CDS_IPC_INFO ipcInfo[], // IPC information structure
int timeSec, // Present GPS Second
int cycle) // Application cycle count (0 to FE_CODE_RATE)
/// @param[in] cycle = Present cycle of the user application making this
///call.
INLINE void commData3Receive(
int connects, // Total number of IPC connections in the application
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 mySyncWord; // Local version of syncWord for comparison and error detection
int ipcIndex; // Pointer to next IPC data buffer
int cycle65k; // All data sent with 64K cycle count; need to convert local app cycle count to match
int ii;
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)
unsigned long syncWord; // Combined GPS timestamp and cycle counter word
// received with data
unsigned long mySyncWord; // Local version of syncWord for comparison and
// error detection
int ipcIndex; // Pointer to next IPC data buffer
int cycle65k; // All data sent with 64K cycle count; need to convert local
// app cycle count to match
int ii;
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
rcvBlock = ((cycle) * (IPC_MAX_RATE / IPC_RATE)) % IPC_BLOCKS;
for(ii=0;ii<connects;ii++)
{
if(ipcInfo[ii].mode == IRCV) // Zero = Rcv and One = Send
// Determine which block to read, based on present code cycle
rcvBlock = ( ( cycle ) * ( IPC_MAX_RATE / IPC_RATE ) ) % IPC_BLOCKS;
for ( ii = 0; ii < connects; ii++ )
{
if ( ipcInfo[ ii ].mode == IRCV ) // Zero = Rcv and One = Send
{
if(!(cycle % ipcInfo[ii].rcvCycle)) // Time to rcv
{
// Determine which data block to read when RCVR runs faster than sender
// if(ipcInfo[ii].rcvCycle > 1) ipcIndex = (cycle / ipcInfo[ii].rcvCycle) % 64;
if ( !( cycle % ipcInfo[ ii ].rcvCycle ) ) // Time to rcv
{
// Determine which data block to read when RCVR runs faster than
// 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
// else ipcIndex = (cycle * ipcInfo[ii].rcvRate) % 64;
if(ipcInfo[ii].pIpcDataRead[0] != NULL)
{
// Data block to read if RCVR runs same speed or slower than
// sender else ipcIndex = (cycle * ipcInfo[ii].rcvRate) % 64;
ipcIndex = ipcInfo[ii].ipcNum;
// Read GPS time/cycle count
tmp = ipcInfo[ii].pIpcDataRead[0]->dBlock[rcvBlock][ipcIndex].data;
syncWord = ipcInfo[ii].pIpcDataRead[0]->dBlock[rcvBlock][ipcIndex].timestamp;
// Create local 65K cycle count
cycle65k = ((cycle * ipcInfo[ii].sendCycle));
mySyncWord = timeSec;
// Create local GPS time/cycle word for comparison to ipc
mySyncWord = (mySyncWord << 32) + cycle65k;
// If IPC syncword = local syncword, data is good
if(syncWord == mySyncWord)
{
ipcInfo[ii].data = tmp;
// If IPC syncword != local syncword, data is BAD
// Set error and leave value same as last good receive
} else {
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;
// }
if ( ipcInfo[ ii ].pIpcDataRead[ 0 ] != NULL )
{
ipcIndex = ipcInfo[ ii ].ipcNum;
// Read GPS time/cycle count
tmp = ipcInfo[ ii ]
.pIpcDataRead[ 0 ]
->dBlock[ rcvBlock ][ ipcIndex ]
.data;
syncWord = ipcInfo[ ii ]
.pIpcDataRead[ 0 ]
->dBlock[ rcvBlock ][ ipcIndex ]
.timestamp;
// Create local 65K cycle count
cycle65k = ( ( cycle * ipcInfo[ ii ].sendCycle ) );
mySyncWord = timeSec;
// Create local GPS time/cycle word for comparison to ipc
mySyncWord = ( mySyncWord << 32 ) + cycle65k;
// If IPC syncword = local syncword, data is good
if ( syncWord == mySyncWord )
{
ipcInfo[ ii ].data = tmp;
// If IPC syncword != local syncword, data is BAD
// Set error and leave value same as last good receive
}
else
{
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
if(cycle == 0)
{
ipcErrBits = ipcErrBits & 0xf0;
for(ii=0;ii<connects;ii++)
{
if(ipcInfo[ii].mode == IRCV) // Zero = Rcv and One = Send
{
ipcInfo[ii].errTotal = ipcInfo[ii].errFlag;
if (ipcInfo[ii].errFlag) {
ipcErrBits |= 1 << (ipcInfo[ii].netType);
ipcErrBits |= 16 << (ipcInfo[ii].netType);;
}
ipcInfo[ii].errFlag = 0;
}
}
}
}
// On cycle 0, set error flags to send back to EPICS
if ( cycle == 0 )
{
ipcErrBits = ipcErrBits & 0xf0;
for ( ii = 0; ii < connects; ii++ )
{
if ( ipcInfo[ ii ].mode == IRCV ) // Zero = Rcv and One = Send
{
ipcInfo[ ii ].errTotal = ipcInfo[ ii ].errFlag;
if ( ipcInfo[ ii ].errFlag )
{
ipcErrBits |= 1 << ( ipcInfo[ ii ].netType );
ipcErrBits |= 16 << ( ipcInfo[ ii ].netType );
;
}
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