📄 ixhssacccodeletchan.c
字号:
} /* for (byteIndex ... */}/** * @fn void ixHssAccCodeletChannelisedDataSampleReceive ( IxHssAccHssPort hssPortId, unsigned channelIndex, UINT8 *sample) * * @param IxHssAccHssPort hssPortId (in) - the HSS port ID (0 or 1). * @param unsigned channelIndex (in) - the channel (0-31) to receive the * data sample from. * @param UINT8 *sample (out) - a pointer to a data sample of size * CHAN_BYTES_PER_SAMPLE. * * This function handles a data sample received from the specified * port/channel. If the hardware is performing a loopback then the data * sample is verified. If the codelet is performing a loopback then the * data sample is re-transmitted on the same channel. This function also * updates RX statistics. */PRIVATEvoidixHssAccCodeletChannelisedDataSampleReceive ( IxHssAccHssPort hssPortId, unsigned channelIndex, UINT8 *sample){ /* to allow for caching, we request a cache invalidate after rx */ IX_OSAL_CACHE_INVALIDATE ( sample, IX_HSSACC_CODELET_CHAN_BYTES_PER_SAMPLE); /* if the hardware is performing a loopback then verify the data */ if (ixHssAccCodeletHssLoopbackGet () && verify) { ixHssAccCodeletChannelisedDataSampleVerify ( hssPortId, channelIndex, sample); } /* update RX stats */ stats[hssPortId].chan.rxSamples++; stats[hssPortId].chan.rxBytes += IX_HSSACC_CODELET_CHAN_BYTES_PER_SAMPLE;}/** * @fn void ixHssAccCodeletChannelisedDataReceive ( IxHssAccHssPort hssPortId, unsigned rxOffset) * * @param IxHssAccHssPort hssPortId (in) - the HSS port ID (0 or 1). * @param unsigned rxOffset (in) - an offset indicating where within the * receive buffers the NPE is currently receiving data into. * * This function examines the rxOffset parameter to determine if a full * data sample has been received by the NPE or not. If a full data sample * has been received by the NPE then it is handled. */PRIVATEvoidixHssAccCodeletChannelisedDataReceive ( IxHssAccHssPort hssPortId, unsigned rxOffset){ unsigned channelIndex; UINT8 *sample; ClientInfo *pClientInfo = &clientInfo[hssPortId]; /* update rxOffset to allow calculation of the offset difference */ if (rxOffset < (UINT32) pClientInfo->nextRxOffset) { rxOffset += IX_HSSACC_CODELET_CHAN_RX_BUFSIZE_PERCHAN; } /* if we haven't received a full data sample yet then return */ if ((rxOffset - pClientInfo->nextRxOffset) < IX_HSSACC_CODELET_CHAN_BYTES_PER_SAMPLE) { return; } /* save nextRxOffset then update with next offset we will receive to */ pClientInfo->lastRxOffset = pClientInfo->nextRxOffset; pClientInfo->nextRxOffset += IX_HSSACC_CODELET_CHAN_BYTES_PER_SAMPLE; pClientInfo->nextRxOffset %= IX_HSSACC_CODELET_CHAN_RX_BUFSIZE_PERCHAN; /* for each channel */ for (channelIndex = 0; channelIndex < IX_HSSACC_CODELET_CHAN_NUM_CHANS; channelIndex++) { /* get the pointer to the data sample for this offset/channel */ sample = &(*pClientInfo->rxBuffers) [channelIndex][pClientInfo->lastRxOffset]; /* process the received data sample */ ixHssAccCodeletChannelisedDataSampleReceive ( hssPortId, channelIndex, sample); } /* we have received samples for every channel */ pClientInfo->readyToLoopback = TRUE;}/** * @fn void ixHssAccCodeletChanRxCallback ( IxHssAccHssPort hssPortId, unsigned rxOffset, unsigned txOffset, unsigned numHssErrs) * * @param IxHssAccHssPort hssPortId (in) - the HSS port ID (0 or 1). * @param unsigned rxOffset (in) - an offset indicating where within the * receive buffers the NPE is currently receiving data into. * @param unsigned txOffset (in) - an offset indicating from where within * the txPtrList the NPE is either currently transmitting from or will * transmit from next. * @param unsigned numHssErrs (in) - The total number of HSS port errors * since initial port configuration. * * This function is of type IxHssAccChanRxCallback, the prototype of the * clients function to accept notification of channelised rx. * * This function is registered through ixHssAccChanConnect(). It handles * the transmission and receipt of data samples if and when necessary. It * also updates the HSS error count. */PRIVATEvoidixHssAccCodeletChanRxCallback ( IxHssAccHssPort hssPortId, unsigned rxOffset, unsigned txOffset, unsigned numHssErrs){ ClientInfo *pClientInfo = &clientInfo[hssPortId]; Message *pMessage; /* add message to the head of the message queue */ pMessage = &pClientInfo->messageQ[pClientInfo->qHead++]; pClientInfo->qHead %= NUMELEMS(pClientInfo->messageQ); /* fill in the message */ pMessage->type = RxCallback; pMessage->params.rxOffset = rxOffset; pMessage->params.txOffset = txOffset; pMessage->params.numHssErrs = numHssErrs; /* wake up the message processing thread */ (void) ixOsalSemaphorePost (&pClientInfo->messageSem);}/* * Function definition: ixHssAccCodeletChanRxCallbackProcess */PRIVATEvoidixHssAccCodeletChanRxCallbackProcess ( IxHssAccHssPort hssPortId, unsigned rxOffset, unsigned txOffset, unsigned numHssErrs){ /* receive data */ ixHssAccCodeletChannelisedDataReceive (hssPortId, rxOffset); /* transmit data */ ixHssAccCodeletChannelisedDataTransmit (hssPortId, txOffset); /* update error stats */ ixHssAccCodeletNumHssErrorsUpdate (hssPortId, numHssErrs);}/* * Function definition: ixHssAccCodeletChanThreadMain */PRIVATEIX_STATUSixHssAccCodeletChanThreadMain ( void* arg, void** ptrRetObj){ ClientInfo *pClientInfo = (ClientInfo *)arg; Message *pMessage; while (1) { (void) ixOsalSemaphoreWait ( &pClientInfo->messageSem, IX_OSAL_WAIT_FOREVER); pMessage = &pClientInfo->messageQ[pClientInfo->qTail++]; pClientInfo->qTail %= NUMELEMS(pClientInfo->messageQ); switch (pMessage->type) { case RxCallback: ixHssAccCodeletChanRxCallbackProcess ( pClientInfo->hssPortId, pMessage->params.rxOffset, pMessage->params.txOffset, pMessage->params.numHssErrs); break; } } /* while (1) */ return IX_SUCCESS;}/* * Function definition: ixHssAccCodeletChannelisedServiceConfigure */voidixHssAccCodeletChannelisedServiceConfigure ( IxHssAccHssPort hssPortId){ IX_STATUS status; unsigned bytesPerTSTrigger; UINT8 *rxCircular; unsigned numRxBytesPerTS; UINT32 *txPtrList; unsigned numTxPtrLists; unsigned numTxBytesPerBlk; IxHssAccChanRxCallback rxCallback; unsigned channelIndex; unsigned i; ClientInfo *pClientInfo = &clientInfo[hssPortId]; ChannelInfo *pChannelInfo; IxOsalThreadAttr ixHssAccCodeletChanThreadAttr; /* initialise client infor structure for this client */ pClientInfo->hssPortId = hssPortId; pClientInfo->lastTxOffset = -1; pClientInfo->nextRxOffset = 0; /* 1st rxOffset we receive to */ pClientInfo->lastRxOffset = -1; /* initially invalid */ pClientInfo->readyToLoopback = FALSE; /* no samples Rx'ed yet */ for (channelIndex = 0; channelIndex < IX_HSSACC_CODELET_CHAN_NUM_CHANS; channelIndex++) { pChannelInfo = &pClientInfo->channelInfo[channelIndex]; /* not receiving non-idle data yet */ pChannelInfo->receivingNonIdleData = FALSE; /* initialise the tx/rx sample data values (to channel number) */ pChannelInfo->txSampleData = channelIndex + 1; pChannelInfo->rxSampleData = channelIndex + 1; } /****************/ /* START THREAD */ /****************/ /* initialise message queue to empty */ pClientInfo->qHead = 0; pClientInfo->qTail = 0; /* initialise the rx semaphore */ (void) ixOsalSemaphoreInit ( &pClientInfo->messageSem, IX_HSSACC_CODELET_SEM_UNAVAILABLE); /* create the thread for processing callbacks */ /* when running both packetised and channelised services, the */ /* channelised service needs to be serviced in a higher priority */ /* thread (high) than the packetised service (low) */ ixHssAccCodeletChanThreadAttr.name = "HSS Codelet Chan CB"; ixHssAccCodeletChanThreadAttr.stackSize = 10240; ixHssAccCodeletChanThreadAttr.priority = IX_HSSACC_CODELET_THREAD_PRI_HIGH; (void) ixOsalThreadCreate ( &pClientInfo->threadId, /* threadId */ &ixHssAccCodeletChanThreadAttr, /* threadAttr */ (IxOsalVoidFnVoidPtr)ixHssAccCodeletChanThreadMain, /* startRoutine */ pClientInfo); /* arg */ /* start the thread for processing callbacks */ (void) ixOsalThreadStart ( &pClientInfo->threadId); /* threadId */ /********************/ /* ALLOCATE BUFFERS */ /********************/ /* allocate channelised RX buffers */ if (pClientInfo->rxBuffers == 0) { pClientInfo->rxBuffers = IX_OSAL_CACHE_DMA_MALLOC( sizeof (*pClientInfo->rxBuffers)); if (pClientInfo->rxBuffers == 0) { printf("Failed to allocated Rx buffers\n"); return; } } /* to allow for caching, we request a cache flush after memset */ MEMSET_AND_FLUSH (pClientInfo->rxBuffers, 0x00, sizeof (*pClientInfo->rxBuffers)); /* allocate channelised TX buffers */ if (pClientInfo->txBuffers == 0) { pClientInfo->txBuffers = IX_OSAL_CACHE_DMA_MALLOC( sizeof (*pClientInfo->txBuffers)); if (pClientInfo->txBuffers == 0) { printf("Failed to allocated Tx buffers\n"); return; } } /* to allow for caching, we request a cache flush after memset */ MEMSET_AND_FLUSH (pClientInfo->txBuffers, 0x00, sizeof (*pClientInfo->txBuffers)); /* allocate channelised TX pointer lists */ if (pClientInfo->txPointers == 0) { pClientInfo->txPointers = IX_OSAL_CACHE_DMA_MALLOC( sizeof (*pClientInfo->txPointers)); if (pClientInfo->txPointers == 0) { printf("Failed to allocated Tx pointers\n"); return; } } /* to allow for caching, we request a cache flush after memset */ MEMSET_AND_FLUSH (pClientInfo->txPointers, 0x00, sizeof (*pClientInfo->txPointers)); /**********************/ /* CONNECT TO SERVICE */ /**********************/ /* Bytes per timeslot trigger = 8 */ bytesPerTSTrigger = IX_HSSACC_CODELET_CHAN_BYTES_PER_TS_TRIG; /* RX circular buffer = RX buffer */ rxCircular = (UINT8 *)(*pClientInfo->rxBuffers); /* Number of RX bytes per timeslot = 176 (RX buf size per channel) */ numRxBytesPerTS = IX_HSSACC_CODELET_CHAN_RX_BUFSIZE_PERCHAN; /* TX pointer list = TX pointer array */ txPtrList = (UINT32 *)(*pClientInfo->txPointers); /* Number of TX pointer lists = 8 (latency factor) */ numTxPtrLists = IX_HSSACC_CODELET_CHAN_TX_LATENCY_FACTOR; /* Number of TX bytes per block = 44 (bytes per sample) */ numTxBytesPerBlk = IX_HSSACC_CODELET_CHAN_BYTES_PER_SAMPLE; /* Receive callback */ rxCallback = ixHssAccCodeletChanRxCallback; /* connect this client to the Channelised Service */ status = ixHssAccChanConnect ( hssPortId, /* hssPortId */ bytesPerTSTrigger, /* bytesPerTSTrigger */ rxCircular, /* rxCircular */ numRxBytesPerTS, /* numRxBytesPerTS */ txPtrList, /* txPtrList */ numTxPtrLists, /* numTxPtrLists */ numTxBytesPerBlk, /* numTxBytesPerBlk */ rxCallback); /* rxCallback */ /* if there was any problem then update stats */ if (status != IX_SUCCESS) { stats[hssPortId].chan.connectFails++; return; } /*******************/ /* PREPARE TX DATA */ /*******************/ /* prepare data for transmit */ for (i = 1; i <= IX_HSSACC_CODELET_CHAN_TX_LATENCY_FACTOR; i++) { /* by passing in txOffsets from 1 to the tx latency factor, we */ /* can reuse our transmit function to initially fill up the tx */ /* buffer with data */ ixHssAccCodeletChannelisedDataTransmit (hssPortId, i); }}/* * Function definition: ixHssAccCodeletChannelisedServiceStart */voidixHssAccCodeletChannelisedServiceStart ( IxHssAccHssPort hssPortId){ IX_STATUS status; /*****************/ /* START SERVICE */ /*****************/ /* start the Channelised Service for this client */ status = ixHssAccChanPortEnable (hssPortId); /* if there was any problem then update stats */ if (status != IX_SUCCESS) { stats[hssPortId].chan.portEnableFails++; return; }}/* * Function definition: ixHssAccCodeletChannelisedServiceRun */voidixHssAccCodeletChannelisedServiceRun ( IxHssAccHssPort hssPortId){}/* * Function definition: ixHssAccCodeletChannelisedServiceStop */voidixHssAccCodeletChannelisedServiceStop ( IxHssAccHssPort hssPortId){ IX_STATUS status; ClientInfo *pClientInfo = &clientInfo[hssPortId]; /****************/ /* STOP SERVICE */ /****************/ /* stop the Channelised Service for the client */ status = ixHssAccChanPortDisable (hssPortId); /* if there was any problem then update stats */ if (status != IX_SUCCESS) { stats[hssPortId].chan.portDisableFails++; return; } /**********************/ /* DISCONNECT SERVICE */ /**********************/ /* disconnect the Channelised Service for the client */ status = ixHssAccChanDisconnect (hssPortId); /* if there was any problem then update stats */ if (status != IX_SUCCESS) { stats[hssPortId].chan.disconnectFails++; return; } /***************/ /* STOP THREAD */ /***************/ /* wait for thread to finish processing messages */ while (pClientInfo->qTail != pClientInfo->qHead) { /* wait for 50ms */ ixOsalSleep (50); }}/* * Function definition: ixHssAccCodeletChannelisedVerifySet */voidixHssAccCodeletChannelisedVerifySet ( BOOL verifyOn){ verify = verifyOn;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -