/* Copyright 2013 The MathWorks, Inc. */ /* * File: xilcomms_rtiostream.c * */ /* include module header file */ #include "xilcomms_wrapper.h" /* include rtIOStream interface to use */ #include "rtiostream.h" /* include Target-side rtIOStream utility APIs */ #include "rtiostream_utils.h" /* rx/tx buffer sizes info */ #include "rx_tx_buffer_sizes.h" /* need UNUSED_PARAMETER */ #include "xil_common.h" /* call xilProcessMsg */ #include "xil_interface_lib_common.h" /* store stream handle */ static int streamID; /* error codes */ static const boolean_T XILCOMMS_SUCCESS = 1; static const boolean_T XILCOMMS_FAILURE = 0; #define APPLICATION_ID_SIZE (sizeof(MemUnit_T)) #define APPLICATION_ID_IDX 0 #define PAYLOAD_SIZE_IDX (APPLICATION_ID_IDX + APPLICATION_ID_SIZE) #define PAYLOAD_IDX (PAYLOAD_SIZE_IDX + WRITE_DATA_AVAIL_SIZE) /* allocate the buffers */ static MemUnit_T xilCommsBuffer[COMMSERVICE_RX_BUFFER_MEMUNIT_SIZE]; static IOUnit_T xilWriteBuffer[XIL_TX_BUFFER_MEMUNIT_SIZE]; #ifdef CODE_INSTRUMENTATION_ENABLED static IOUnit_T codeInstrWriteBuffer[CODE_INSTR_TX_BUFFER_MEMUNIT_SIZE]; #endif /* Returns pointer to corresponding buffer for application * given its id. Returns NULL for invalid application ids. */ static IOUnit_T* getApplicationBufferPtr( const uint8_T appId){ switch(appId) { case XIL_APPLICATION_ID: return &xilWriteBuffer[APPLICATION_ID_IDX]; #ifdef CODE_INSTRUMENTATION_ENABLED case CODE_INSTR_APPLICATION_ID: return &codeInstrWriteBuffer[APPLICATION_ID_IDX]; #endif default: return NULL; } } /* provide access to XIL send buffer */ EXTERN_C boolean_T xilCommsAllocXILBuffer( void* const pRTIOStreamCS, void** ppBuf, const size_t dataSize){ /* buffer is already statically allocated */ *ppBuf = NULL; UNUSED_PARAMETER(pRTIOStreamCS); UNUSED_PARAMETER(dataSize); /* nothing to do as buffer is already statically allocated */ return XILCOMMS_SUCCESS; } /* return pointer to XIL buffer data */ EXTERN_C IOUnit_T * xilCommsGetXILBufferDataPtr( void* const pBuf){ /* buffer is already statically allocated */ UNUSED_PARAMETER(pBuf); return &xilWriteBuffer[PAYLOAD_IDX]; } #ifdef CODE_INSTRUMENTATION_ENABLED /* provide access to code instrumentation send buffer */ boolean_T xilCommsAllocCodeInstrBuffer( void* const pRTIOStreamCS, void** ppBuf, const size_t dataSize){ /* buffer is already statically allocated */ *ppBuf = NULL; UNUSED_PARAMETER(pRTIOStreamCS); UNUSED_PARAMETER(dataSize); /* nothing to do as buffer is already statically allocated */ return XILCOMMS_SUCCESS; } /* return pointer to code instrumentation buffer data */ EXTERN_C IOUnit_T * xilCommsGetCodeInstrBufferDataPtr( void* const pBuf){ /* buffer is already statically allocated */ UNUSED_PARAMETER(pBuf); return &codeInstrWriteBuffer[PAYLOAD_IDX]; } #endif /* open rtiostream */ boolean_T xilCommsCreate( void** const ppRTIOStreamCS, const int argc, void * argv[]){ UNUSED_PARAMETER(ppRTIOStreamCS); streamID = rtIOStreamOpen(argc, argv); if (streamID == RTIOSTREAM_ERROR) { return XILCOMMS_FAILURE; } return XILCOMMS_SUCCESS; } /* close rtiostream */ boolean_T xilCommsDestroy(void* const pRTIOStreamCSVoid) { UNUSED_PARAMETER(pRTIOStreamCSVoid); return(rtIOStreamClose(streamID) == RTIOSTREAM_NO_ERROR); } /* call rtIOStreamBlockingSend to send data*/ EXTERN_C boolean_T xilCommsEnqueue( void* const pRTIOStreamCSVoid, void* const pBuf, const uint8_T appId, const uint16_T dataSize) { int rtIOStreamErrorStatus; MemUnit_T appIdMemUnit = (MemUnit_T)appId; uint32_T writeDataAvail = (uint32_T)dataSize; uint32_T transferSize = writeDataAvail + BUFFER_HEADER_SIZE; /* write size and application id before sending the buffer */ #ifdef HOST_WORD_ADDRESSABLE_TESTING /* writeDataAvail is in terms of IOUnit_T (uint8_T) - convert to MemUnit_T's * assume that writeDataAvail divides exactly */ uint32_T writeDataAvailMemUnits = writeDataAvail / MEM_UNIT_BYTES; #else uint32_T writeDataAvailMemUnits = writeDataAvail; #endif /* get the pointer for the application buffer of the given app id */ IOUnit_T* appBuffer = getApplicationBufferPtr(appId); if (appBuffer == NULL) { /* early return */ return XILCOMMS_FAILURE; } UNUSED_PARAMETER(pRTIOStreamCSVoid); UNUSED_PARAMETER(pBuf); memcpy((void *) &appBuffer[APPLICATION_ID_IDX], &appIdMemUnit, sizeof(appIdMemUnit)); memcpy((void *) &appBuffer[PAYLOAD_SIZE_IDX], &writeDataAvailMemUnits, sizeof(writeDataAvailMemUnits)); /* Blocks until all requested outgoing data is sent */ rtIOStreamErrorStatus = rtIOStreamBlockingSend(streamID, (const void *) appBuffer, transferSize); if (rtIOStreamErrorStatus == RTIOSTREAM_ERROR) return XILCOMMS_FAILURE; return XILCOMMS_SUCCESS; } #define RECV_BUFFER_DATA_IDX 0 boolean_T xilCommsRun(void* const pRTIOStreamCSVoid) { int rtIOStreamErrorStatus; uint32_T dataSize; MemUnit_T appId; UNUSED_PARAMETER(pRTIOStreamCSVoid); /* receive app id */ rtIOStreamErrorStatus = rtIOStreamBlockingRecv(streamID, (void *) &appId, sizeof(appId)); if (rtIOStreamErrorStatus == RTIOSTREAM_ERROR) return XILCOMMS_FAILURE; /* receive size of data contained in the buffer */ rtIOStreamErrorStatus = rtIOStreamBlockingRecv(streamID, (void *) &dataSize, sizeof(dataSize)); if (rtIOStreamErrorStatus == RTIOSTREAM_ERROR) return XILCOMMS_FAILURE; #ifdef HOST_WORD_ADDRESSABLE_TESTING /* dataSize is in terms of MemUnit_T - convert to IOUnit_T (uint8_T). Note * that dataSize will not overflow since the host already divided dataSize * by memUnit_T before transmission, so this multiplication should be safe * and won't overflow. */ dataSize *= MEM_UNIT_BYTES; #endif /* receive the data */ rtIOStreamErrorStatus = rtIOStreamBlockingRecv(streamID, (void *) &xilCommsBuffer[RECV_BUFFER_DATA_IDX], dataSize); if (rtIOStreamErrorStatus == RTIOSTREAM_ERROR) return XILCOMMS_FAILURE; /* dispatch buffer to owning application */ switch(appId) { case XIL_APPLICATION_ID: xilProcessMsg(&(xilCommsBuffer[RECV_BUFFER_DATA_IDX]), (uint16_T)dataSize); break; default: return XILCOMMS_FAILURE; } return XILCOMMS_SUCCESS; }