Line 13... |
Line 13... |
* Symbols are in four flavors, idle, control, data and error. They are abstract
|
* Symbols are in four flavors, idle, control, data and error. They are abstract
|
* and should be serialized by any implementation to be sent on a transmission
|
* and should be serialized by any implementation to be sent on a transmission
|
* channel. Error symbols are never generated by the stack and are used if the
|
* channel. Error symbols are never generated by the stack and are used if the
|
* symbol decoder encounters an error that the stack should be notified of.
|
* symbol decoder encounters an error that the stack should be notified of.
|
*
|
*
|
* Symbols are inserted into the stack by calling RIO_portAddSymbol() and symbols to
|
* Symbols are inserted into the stack from the lower-half by calling
|
* transmit are fetched from the stack using RIO_portGetSymbol(). These two
|
* RIOSTACK_portAddSymbol() and symbols to transmit are fetched from the stack
|
* functions are the low-level interface towards a physical transmission channel.
|
* using RIOSTACK_portGetSymbol(). These two functions are the low-level interface
|
* The function RIO_portSetStatus() is used to indicate to the stack that initial
|
* towards a physical transmission channel.
|
|
* The function RIOSTACK_portSetStatus() is used to indicate to the stack that initial
|
* training of the symbol codec has been completed and that the transmission port
|
* training of the symbol codec has been completed and that the transmission port
|
* is ready to accept other symbols than idle. The procedure is to set the port
|
* is ready to accept other symbols than idle. The procedure is to set the port
|
* status to initialized once idle symbols are successfully received.
|
* status to initialized once idle symbols are successfully received.
|
*
|
*
|
* On the high-level interface are rio_sendXXX() functions used to create and
|
* On the upper-half interface are the RIOSTACK_setOutboundPacket() function used to
|
* insert packets into the outbound transmission queue. The RIO_eventPoll()
|
* insert packets into the outbound transmission queue and RIOSTACK_getInboundPacket()
|
* function is used to check if any packet is available for reading in the
|
* is used to get packet from the inbound reception queue. The
|
* inbound reception queue. These packets are then accessed using
|
* RIOSTACK_getInboundQueueLength() function is used to check if any packet is available
|
* rio_receiveXXX() functions.
|
* for reading in the inbound reception queue.
|
*
|
*
|
* -----------------
|
* -----------------
|
* | OS dependent |
|
* | OS dependent |
|
* | (your code) |
|
* | (your code) |
|
* -----------------
|
* -----------------
|
Line 53... |
Line 54... |
*
|
*
|
* The symbol codec maps a RapidIO symbol to the physical transmission media.
|
* The symbol codec maps a RapidIO symbol to the physical transmission media.
|
*
|
*
|
* Some typical patterns to handle this stack are:
|
* Some typical patterns to handle this stack are:
|
* Initialization:
|
* Initialization:
|
* RIO_open(...);
|
* RIOSTACK_open(...);
|
* RIO_portSetTimeout(...);
|
* RIOSTACK_portSetTimeout(...);
|
* ...
|
* ...
|
* <Symbol transcoder is successfully decoding symbols from the link>
|
* <Symbol transcoder is successfully decoding symbols from the link>
|
* RIO_portSetStatus(1);
|
* RIOSTACK_portSetStatus(1);
|
*
|
*
|
* Bottom-half traffic handling:
|
* Bottom-half traffic handling:
|
* RIO_portSetTime(...);
|
* RIOSTACK_portSetTime(...);
|
* <get symbol from decoder>
|
* <get symbol from decoder>
|
* RIO_portAddSymbol(...);
|
* RIOSTACK_portAddSymbol(...);
|
* s = RIO_portGetSymbol(...);
|
* s = RIOSTACK_portGetSymbol(...);
|
* <send symbol to encoder>
|
* <send symbol to encoder>
|
*
|
*
|
* Receiving packets:
|
* Receiving packets:
|
* switch(RIO_eventPoll(...))
|
* if(RIOSTACK_getInboundQueueLength(...) > 0)
|
* {
|
* {
|
* case RIO_EVENT_DOORBELL:
|
* RIOSTACK_getInboundPacket(...);
|
* RIO_receiveDoorbell(...);
|
* <process the new packet>
|
* ...
|
|
* }
|
* }
|
* RIO_packetRemove();
|
|
*
|
*
|
* Transmitting packets:
|
* Transmitting packets:
|
* if(RIO_sendAvailable(...))
|
* <create a new packet>
|
|
* if(RIOSTACK_getOutboundQueueAvailable(...) > 0)
|
* {
|
* {
|
* RIO_sendDoorbell(...);
|
* RIOSTACK_setOutboundPacket(...);
|
* }
|
* }
|
* ...
|
|
*
|
*
|
* More details about the usage can be found in the module tests in the end of
|
* More details about the usage can be found in the module tests in test_riostack.c.
|
* this file.
|
|
*
|
*
|
* To Do:
|
* To Do:
|
* -
|
* - Optimize the packing of stype0 and stype1 into control symbols.
|
*
|
*
|
* Author(s):
|
* Author(s):
|
* - Magnus Rosenius, magro732@opencores.org
|
* - Magnus Rosenius, magro732@opencores.org
|
*
|
*
|
*******************************************************************************
|
*******************************************************************************
|
*
|
*
|
* Copyright (C) 2013 Authors and OPENCORES.ORG
|
* Copyright (C) 2015 Authors and OPENCORES.ORG
|
*
|
*
|
* This source file may be used and distributed without
|
* This source file may be used and distributed without
|
* restriction provided that this copyright statement is not
|
* restriction provided that this copyright statement is not
|
* removed from the file and that any derivative work contains
|
* removed from the file and that any derivative work contains
|
* the original copyright notice and the associated disclaimer.
|
* the original copyright notice and the associated disclaimer.
|
Line 118... |
Line 116... |
* Public License along with this source; if not, download it
|
* Public License along with this source; if not, download it
|
* from http://www.opencores.org/lgpl.shtml
|
* from http://www.opencores.org/lgpl.shtml
|
*
|
*
|
*******************************************************************************/
|
*******************************************************************************/
|
|
|
|
|
/**
|
/**
|
* \file riostack.c
|
* \file riostack.c
|
*/
|
*/
|
|
|
/*******************************************************************************
|
/*******************************************************************************
|
Line 137... |
Line 136... |
|
|
|
|
/* lint --estring(960,17.4) It is not possible to implement a rio stack without some
|
/* lint --estring(960,17.4) It is not possible to implement a rio stack without some
|
* pointer arithmetic */
|
* pointer arithmetic */
|
|
|
|
|
/*******************************************************************************
|
/*******************************************************************************
|
* Local macro definitions
|
* Local macro definitions
|
*******************************************************************************/
|
*******************************************************************************/
|
|
|
/* Macro to update 5-bit ackId counters. */
|
/* Macro to update 5-bit ackId counters. */
|
Line 244... |
Line 244... |
#define LINK_RESPONSE_PORT_STATUS_ERROR 2u
|
#define LINK_RESPONSE_PORT_STATUS_ERROR 2u
|
#define LINK_RESPONSE_PORT_STATUS_RETRY_STOPPED 4u
|
#define LINK_RESPONSE_PORT_STATUS_RETRY_STOPPED 4u
|
#define LINK_RESPONSE_PORT_STATUS_ERROR_STOPPED 5u
|
#define LINK_RESPONSE_PORT_STATUS_ERROR_STOPPED 5u
|
#define LINK_RESPONSE_PORT_STATUS_OK 16u
|
#define LINK_RESPONSE_PORT_STATUS_OK 16u
|
|
|
|
|
|
|
/*******************************************************************************
|
/*******************************************************************************
|
* Local typedefs
|
* Local typedefs
|
*******************************************************************************/
|
*******************************************************************************/
|
|
|
|
|
|
|
/*******************************************************************************
|
/*******************************************************************************
|
* Global declarations
|
* Global declarations
|
*******************************************************************************/
|
*******************************************************************************/
|
|
|
|
|
|
|
/*******************************************************************************
|
/*******************************************************************************
|
* Local declarations
|
* Local declarations
|
*******************************************************************************/
|
*******************************************************************************/
|
|
|
|
|
|
|
/*******************************************************************************
|
/*******************************************************************************
|
* Local function prototypes
|
* Local function prototypes
|
*******************************************************************************/
|
*******************************************************************************/
|
|
|
/* Helper functions for protocol events. */
|
/* Helper functions for protocol events. */
|
Line 272... |
Line 280... |
static void handleEndOfPacket(RioStack_t *stack);
|
static void handleEndOfPacket(RioStack_t *stack);
|
static void handleLinkRequest(RioStack_t *stack, uint8_t cmd);
|
static void handleLinkRequest(RioStack_t *stack, uint8_t cmd);
|
static void handleNewPacketStart(RioStack_t *stack);
|
static void handleNewPacketStart(RioStack_t *stack);
|
static void handleNewPacketEnd(RioStack_t *stack);
|
static void handleNewPacketEnd(RioStack_t *stack);
|
|
|
/* I/O logical layer maintenance packet functions. */
|
|
static void sendMaintenanceReadRequest( RioStack_t *stack, const uint16_t destid, const uint16_t srcid, const uint8_t tid,
|
|
const uint8_t hopCount, const uint32_t offset);
|
|
static void receiveMaintenanceReadRequest( RioStack_t *stack, uint16_t *destid, uint16_t *srcid, uint8_t *tid,
|
|
uint8_t *hopCount, uint32_t *offset);
|
|
static void sendMaintenanceReadResponse( RioStack_t *stack, const uint16_t destid, const uint16_t srcid, const uint8_t tid,
|
|
const uint8_t hopCount, const uint32_t data);
|
|
static void receiveMaintenanceReadResponse( RioStack_t *stack, uint16_t *destid, uint16_t *srcid, uint8_t *tid,
|
|
uint8_t *hopCount, uint32_t *data);
|
|
static void sendMaintenanceWriteRequest( RioStack_t *stack, const uint16_t destid, const uint16_t srcid, const uint8_t tid,
|
|
const uint8_t hopCount, const uint32_t offset, const uint32_t data );
|
|
static void receiveMaintenanceWriteRequest( RioStack_t *stack, uint16_t *destid, uint16_t *srcid, uint8_t *tid,
|
|
uint8_t *hopCount, uint32_t *offset, uint32_t *data );
|
|
static void sendMaintenanceWriteResponse( RioStack_t *stack, const uint16_t destid, const uint16_t srcid, const uint8_t tid,
|
|
const uint8_t hopCount);
|
|
static void receiveMaintenanceWriteResponse( RioStack_t *stack, uint16_t *destid, uint16_t *srcid, uint8_t *tid,
|
|
uint8_t *hopCount);
|
|
|
|
/* I/O logical layer packet functions. */
|
|
static void sendNwrite( RioStack_t *stack, const uint16_t destid, const uint16_t srcid, const uint8_t tid,
|
|
const uint32_t address, const uint16_t bufferSize, const uint8_t *buffer,
|
|
const uint8_t ack);
|
|
static uint16_t receiveNwrite( RioStack_t *stack, uint16_t *destid, uint16_t *srcid, uint8_t *tid,
|
|
uint32_t *address, const uint16_t dataLength, uint8_t *data );
|
|
static void sendNread( RioStack_t *stack, const uint16_t destid, const uint16_t srcid, const uint8_t tid,
|
|
const uint32_t address, const uint16_t dataLength);
|
|
static void receiveNread( RioStack_t *stack, uint16_t *destid, uint16_t *srcid, uint8_t *tid,
|
|
uint32_t *address, uint16_t *dataLength);
|
|
static void sendResponseDonePayload( RioStack_t *stack, const uint16_t destid, const uint16_t srcid, const uint8_t tid,
|
|
const uint32_t address, const uint16_t bufferSize, const uint8_t *buffer);
|
|
static uint16_t receiveResponseDonePayload( RioStack_t *stack, uint16_t *destid, uint16_t *srcid, uint8_t *tid,
|
|
const uint32_t address, const uint16_t dataLength, uint8_t *data );
|
|
static void sendResponse( RioStack_t *stack, const uint16_t destid, const uint16_t srcid, const uint8_t tid,
|
|
const uint8_t status);
|
|
static void receiveResponse( RioStack_t *stack, uint16_t *destid, uint16_t *srcid, uint8_t *tid);
|
|
|
|
/* Message passing logical layer packet functions. */
|
|
static void sendDoorbell( RioStack_t *stack, const uint16_t destid, const uint16_t srcid, const uint8_t tid,
|
|
const uint16_t info );
|
|
static void receiveDoorbell( RioStack_t *stack, uint16_t *destid, uint16_t *srcid, uint8_t *tid,
|
|
uint16_t *info);
|
|
static void sendMessage( RioStack_t *stack, const uint16_t destid, const uint16_t srcid, const uint8_t mailbox,
|
|
const uint16_t bufferSize, const uint8_t* bufferData);
|
|
static uint16_t receiveMessage( RioStack_t *stack, uint16_t *destid, uint16_t *srcid, uint8_t *mailbox,
|
|
const uint16_t dataLength, uint8_t *data );
|
|
static void sendMessageResponse( RioStack_t *stack, const uint16_t destid, const uint16_t srcid, const uint8_t mailbox,
|
|
const uint8_t status);
|
|
static void receiveMessageResponse( RioStack_t *stack, uint16_t *destid, uint16_t *srcid, uint8_t *mailbox);
|
|
|
|
/* Functions to help transfer data bytes to and from a packet payload. */
|
|
static uint16_t getPacketPayload(uint32_t *packet, const uint16_t payloadOffset, const uint16_t dataOffset,
|
|
const uint16_t dataSize, uint8_t *data);
|
|
static uint16_t setPacketPayload(uint32_t *packet, const uint16_t payloadOffset, const uint16_t dataOffset,
|
|
const uint16_t dataSize, const uint8_t *data);
|
|
|
|
/* Functions to help in conversions between rdsize/wrsize and size/offset. */
|
|
static uint16_t rdsizeGet(const uint32_t address, const uint16_t size);
|
|
static uint16_t wrsizeGet(const uint32_t address, const uint16_t size);
|
|
static void rdsizeToOffset(uint8_t wrsize, uint8_t wdptr, uint8_t *offset, uint16_t *size);
|
|
static void wrsizeToOffset(uint8_t wrsize, uint8_t wdptr, uint8_t *offset, uint16_t *size);
|
|
|
|
/**
|
/**
|
* \brief Create a control symbol.
|
* \brief Create a control symbol.
|
*
|
*
|
* \param[in] stype0 The stype0 value.
|
* \param[in] stype0 The stype0 value.
|
* \param[in] parameter0 The parameter0 value.
|
* \param[in] parameter0 The parameter0 value.
|
* \param[in] parameter1 The parameter1 value.
|
* \param[in] parameter1 The parameter1 value.
|
* \param[in] stype1 The stype1 value.
|
* \param[in] stype1 The stype1 value.
|
* \param[in] cmd The cmd value.
|
* \param[in] cmd The cmd value.
|
* \param[out] None
|
|
* \return The control symbol that were created from the input parameters.
|
* \return The control symbol that were created from the input parameters.
|
*
|
*
|
* This function creates a control symbol with the specified arguments and
|
* This function creates a control symbol with the specified arguments and
|
* calculates a CRC-5 checksum according to the standard specification.
|
* calculates a CRC-5 checksum according to the standard specification.
|
*/
|
*/
|
static RioSymbol CreateControlSymbol( const uint8_t stype0,
|
static RioSymbol_t CreateControlSymbol(const uint8_t stype0,
|
const uint8_t parameter0, const uint8_t parameter1,
|
const uint8_t parameter0, const uint8_t parameter1,
|
const uint8_t stype1, const uint8_t cmd);
|
const uint8_t stype1, const uint8_t cmd);
|
|
|
/**
|
/**
|
* \brief Function to calculate ITU-CRC5, polynom=0x15.
|
* \brief Function to calculate ITU-CRC5, polynom=0x15.
|
Line 361... |
Line 307... |
* \return A new CRC-5 value.
|
* \return A new CRC-5 value.
|
*/
|
*/
|
static uint8_t Crc5( const uint32_t data, const uint8_t crc);
|
static uint8_t Crc5( const uint32_t data, const uint8_t crc);
|
|
|
/**
|
/**
|
* \brief Function to calculate CITT-CRC16, polynom=0x1021.
|
|
*
|
|
* \param[in] data The data to calculate CRC-16 on.
|
|
* \param[in] crc The crc to initiate the result with.
|
|
* \param[out] None
|
|
* \return A new CRC-16 value.
|
|
*
|
|
* This function calculates and returns a new CRC-16 value based on
|
|
* new data and a previous CRC-16 value.
|
|
*/
|
|
static uint16_t Crc16( const uint16_t data, const uint16_t crc);
|
|
|
|
/**
|
|
* \brief Function to calculate CITT-CRC16, polynom=0x1021.
|
|
*
|
|
* \param[in] data The data to calculate CRC-16 on.
|
|
* \param[in] crc The crc to initiate the result with.
|
|
* \param[out] None
|
|
* \return A new CRC-16 value.
|
|
*
|
|
* This function calculates and returns a new CRC-16 value based on
|
|
* new data and a previous CRC-16 value.
|
|
*/
|
|
static uint16_t Crc32( const uint32_t data, uint16_t crc);
|
|
|
|
/**
|
|
* \brief Create a queue with a specified size and a buffer attached to it.
|
* \brief Create a queue with a specified size and a buffer attached to it.
|
*
|
*
|
* \param[in] The number of entries in the queue.
|
* \param[in] size The number of entries in the queue.
|
* \param[in] A pointer to the buffer to store the content in.
|
* \param[in] buffer A pointer to the buffer to store the content in.
|
* \return A queue with the specified size and where new data will be stored
|
* \return A queue with the specified size and where new data will be stored
|
* to the specified buffer.
|
* to the specified buffer.
|
*/
|
*/
|
static Queue_t QueueCreate( const uint8_t size, uint32_t *buffer);
|
static Queue_t QueueCreate( const uint8_t size, uint32_t *buffer);
|
|
|
Line 410... |
Line 330... |
* \brief Get if the queue is empty or not.
|
* \brief Get if the queue is empty or not.
|
*
|
*
|
* \param[in] q The queue to operate on.
|
* \param[in] q The queue to operate on.
|
* \return Non-zero if the queue is empty.
|
* \return Non-zero if the queue is empty.
|
*/
|
*/
|
static bool_t QueueEmpty( const Queue_t q);
|
static int QueueEmpty(const Queue_t q);
|
|
|
/**
|
/**
|
* \brief Get the length of a queue.
|
* \brief Get the length of a queue.
|
*
|
*
|
* \param[in] q The queue to operate on.
|
* \param[in] q The queue to operate on.
|
Line 442... |
Line 362... |
* \brief Check if the readout window is empty.
|
* \brief Check if the readout window is empty.
|
*
|
*
|
* \param[in] q The queue to operate on.
|
* \param[in] q The queue to operate on.
|
* \return If the readout window is empty.
|
* \return If the readout window is empty.
|
*/
|
*/
|
static bool_t QueueWindowEmpty( const Queue_t q);
|
static int QueueWindowEmpty(const Queue_t q);
|
|
|
/**
|
/**
|
* \brief Reset the window to none.
|
* \brief Reset the window to none.
|
*
|
*
|
* \param[in] q The queue to operate on.
|
* \param[in] q The queue to operate on.
|
Line 478... |
Line 398... |
* \param[in] content The content to set at the specified index in the newest queue element.
|
* \param[in] content The content to set at the specified index in the newest queue element.
|
*/
|
*/
|
static void QueueSetContent( Queue_t q, const uint32_t index, const uint32_t content);
|
static void QueueSetContent( Queue_t q, const uint32_t index, const uint32_t content);
|
|
|
/**
|
/**
|
* \brief Get the size of the newest element.
|
|
*
|
|
* \param[in] q The queue to operate on.
|
|
* \return The size of the currently pending element.
|
|
*/
|
|
static uint32_t QueueGetBackSize( Queue_t q);
|
|
|
|
/**
|
|
* \brief Get a pointer to the buffer of the newest element.
|
* \brief Get a pointer to the buffer of the newest element.
|
*
|
*
|
* \param[in] q The queue to operate on.
|
* \param[in] q The queue to operate on.
|
* \return A pointer to the content.
|
* \return A pointer to the content.
|
*/
|
*/
|
Line 498... |
Line 410... |
/**
|
/**
|
* \brief Get the size of the oldest element.
|
* \brief Get the size of the oldest element.
|
* \param[in] q The queue to operate on.
|
* \param[in] q The queue to operate on.
|
* \return The size of the element.
|
* \return The size of the element.
|
*/
|
*/
|
static uint32_t QueueGetFrontSize( Queue_t q );
|
static uint32_t QueueGetSize(Queue_t q );
|
|
|
/**
|
/**
|
* \brief Get the content of the oldest element at specified index.
|
* \brief Get the content of the oldest element at specified index.
|
* \param[in] q The queue to operate on.
|
* \param[in] q The queue to operate on.
|
* \param[in] index The index into the element to get the content from.
|
* \param[in] index The index into the element to get the content from.
|
Line 522... |
Line 434... |
|
|
/*******************************************************************************
|
/*******************************************************************************
|
* Global functions
|
* Global functions
|
*******************************************************************************/
|
*******************************************************************************/
|
|
|
|
void RIOSTACK_open(RioStack_t *stack, void *private,
|
void RIO_open( RioStack_t *stack, const RioStackObserver_t *observer, const void *private,
|
|
const uint32_t rxPacketBufferSize, uint32_t *rxPacketBuffer,
|
const uint32_t rxPacketBufferSize, uint32_t *rxPacketBuffer,
|
const uint32_t txPacketBufferSize, uint32_t *txPacketBuffer,
|
const uint32_t txPacketBufferSize, uint32_t *txPacketBuffer)
|
const uint16_t configDeviceVendorId, const uint16_t configDeviceId, const uint32_t configDeviceRevisionId,
|
|
const uint16_t configAssyVendorId, const uint16_t configAssyId, const uint16_t configAssyRevisionId,
|
|
const uint16_t configBaseDeviceId )
|
|
{
|
{
|
/* Port time and timeout limit. */
|
/* Port time and timeout limit. */
|
stack->portTime = 0u;
|
stack->portTime = 0u;
|
stack->portTimeout = 1000u;
|
stack->portTimeout = 1000u;
|
|
|
Line 542... |
Line 450... |
stack->rxCrc = 0xffffu;
|
stack->rxCrc = 0xffffu;
|
stack->rxStatusReceived = 0u;
|
stack->rxStatusReceived = 0u;
|
stack->rxAckId = 0u;
|
stack->rxAckId = 0u;
|
stack->rxAckIdAcked = 0u;
|
stack->rxAckIdAcked = 0u;
|
stack->rxErrorCause = PACKET_NOT_ACCEPTED_CAUSE_RESERVED;
|
stack->rxErrorCause = PACKET_NOT_ACCEPTED_CAUSE_RESERVED;
|
stack->rxQueue = QueueCreate((uint8_t) (rxPacketBufferSize/RIO_BUFFER_SIZE), rxPacketBuffer);
|
stack->rxQueue = QueueCreate((uint8_t) (rxPacketBufferSize/RIOSTACK_BUFFER_SIZE), rxPacketBuffer);
|
|
|
/* Setup the transmitter. */
|
/* Setup the transmitter. */
|
stack->txState = TX_STATE_UNINITIALIZED;
|
stack->txState = TX_STATE_UNINITIALIZED;
|
stack->txCounter = 0u;
|
stack->txCounter = 0u;
|
stack->txStatusCounter = 0u;
|
stack->txStatusCounter = 0u;
|
stack->txFrameState = TX_FRAME_START;
|
stack->txFrameState = TX_FRAME_START;
|
stack->txAckId = 0u;
|
stack->txAckId = 0u;
|
stack->txAckIdWindow = 0u;
|
stack->txAckIdWindow = 0u;
|
stack->txQueue = QueueCreate((uint8_t) (txPacketBufferSize/RIO_BUFFER_SIZE), txPacketBuffer);
|
stack->txQueue = QueueCreate((uint8_t) (txPacketBufferSize/RIOSTACK_BUFFER_SIZE), txPacketBuffer);
|
|
|
/* Set our own device address to use in the packets. */
|
|
stack->deviceIdentity = configDeviceId;
|
|
stack->deviceVendorIdentity = configDeviceVendorId;
|
|
stack->deviceRev = configDeviceRevisionId;
|
|
stack->assyIdentity = configAssyId;
|
|
stack->assyVendorIdentity = configAssyVendorId;
|
|
stack->assyRev = configAssyRevisionId;
|
|
stack->baseDeviceId = configBaseDeviceId;
|
|
|
|
/* Initialize the host base lock CSR. */
|
|
stack->hostBaseDeviceIdLock = 0xfffffffful;
|
|
stack->componentTag = 0ul;
|
|
|
|
/* Bits that are updated by the configuration procedure. */
|
|
stack->host = 0u;
|
|
stack->masterEnable = 0u;
|
|
stack->discovered = 0u;
|
|
|
|
/* Setup status counters for inbound direction. */
|
/* Setup status counters for inbound direction. */
|
stack->statusInboundPacketComplete = 0ul;
|
stack->statusInboundPacketComplete = 0ul;
|
stack->statusInboundPacketRetry = 0ul;
|
stack->statusInboundPacketRetry = 0ul;
|
stack->statusInboundErrorControlCrc = 0ul;
|
stack->statusInboundErrorControlCrc = 0ul;
|
Line 583... |
Line 473... |
stack->statusInboundErrorGeneral = 0ul;
|
stack->statusInboundErrorGeneral = 0ul;
|
stack->statusInboundErrorPacketUnsupported = 0ul;
|
stack->statusInboundErrorPacketUnsupported = 0ul;
|
|
|
/* Setup status counters for outbound direction. */
|
/* Setup status counters for outbound direction. */
|
stack->statusOutboundPacketComplete = 0ul;
|
stack->statusOutboundPacketComplete = 0ul;
|
|
stack->statusOutboundLinkLatencyMax = 0ul;
|
stack->statusOutboundPacketRetry = 0ul;
|
stack->statusOutboundPacketRetry = 0ul;
|
stack->statusOutboundErrorTimeout = 0ul;
|
stack->statusOutboundErrorTimeout = 0ul;
|
stack->statusOutboundErrorPacketAccepted = 0ul;
|
stack->statusOutboundErrorPacketAccepted = 0ul;
|
stack->statusOutboundErrorPacketRetry = 0ul;
|
stack->statusOutboundErrorPacketRetry = 0ul;
|
|
|
Line 596... |
Line 487... |
stack->statusPartnerErrorPacketAckId = 0ul;
|
stack->statusPartnerErrorPacketAckId = 0ul;
|
stack->statusPartnerErrorPacketCrc = 0ul;
|
stack->statusPartnerErrorPacketCrc = 0ul;
|
stack->statusPartnerErrorIllegalCharacter = 0ul;
|
stack->statusPartnerErrorIllegalCharacter = 0ul;
|
stack->statusPartnerErrorGeneral = 0ul;
|
stack->statusPartnerErrorGeneral = 0ul;
|
|
|
/* Set callback structure. */
|
|
stack->observer = observer;
|
|
|
|
/* Set pointer to user private data. */
|
/* Set pointer to user private data. */
|
stack->private = private;
|
stack->private = private;
|
}
|
}
|
|
|
|
|
|
|
/*******************************************************************************************
|
/*******************************************************************************************
|
* Stack status functions.
|
* Stack status and queue access functions.
|
* Note that status counters are access directly in the stack-structure.
|
* Note that status counters are accessed directly in the stack-structure.
|
*******************************************************************************************/
|
*******************************************************************************************/
|
|
|
RioStatusType RIO_getStatus( RioStack_t *stack )
|
int RIOSTACK_getStatus(RioStack_t *stack)
|
{
|
{
|
RioStatusType status;
|
return !(((stack->rxState == RX_STATE_UNINITIALIZED) || (stack->rxState == RX_STATE_PORT_INITIALIZED)) &&
|
|
((stack->txState == TX_STATE_UNINITIALIZED) || (stack->txState == TX_STATE_PORT_INITIALIZED)));
|
|
}
|
|
|
|
|
/* Check if both receiver and transmitter is up and running. */
|
|
if((stack->rxState == RX_STATE_LINK_INITIALIZED) &&
|
|
(stack->txState == TX_STATE_LINK_INITIALIZED))
|
|
{
|
|
/* Both receiver and transmitter is up. */
|
|
|
|
/* Check if it is allowed to act as a master on the bus. */
|
void RIOSTACK_clearOutboundQueue(RioStack_t *stack)
|
if(stack->masterEnable)
|
|
{
|
{
|
/* Allowed to act as master. */
|
while(!QueueEmpty(stack->txQueue))
|
status = RIO_STATUS_OPERATIONAL;
|
|
}
|
|
else
|
|
{
|
{
|
/* Not allowed to act as master. */
|
stack->txQueue = QueueDequeue(stack->txQueue);
|
/* The enumeration process has not been completed yet. */
|
|
status = RIO_STATUS_ENUMERATION;
|
|
}
|
|
}
|
}
|
else
|
|
{
|
|
/* The link is not up yet. */
|
|
status = RIO_STATUS_UNINITIALIZED;
|
|
}
|
}
|
|
|
return status;
|
|
}
|
|
|
|
|
|
uint8_t RIO_outboundQueueLength( RioStack_t *stack )
|
uint8_t RIOSTACK_getOutboundQueueLength(RioStack_t *stack)
|
{
|
{
|
return QueueLength(stack->txQueue);
|
return QueueLength(stack->txQueue);
|
}
|
}
|
|
|
|
|
uint8_t RIO_inboundQueueLength( RioStack_t *stack )
|
|
|
uint8_t RIOSTACK_getOutboundQueueAvailable(RioStack_t *stack)
|
{
|
{
|
return QueueLength(stack->rxQueue);
|
return QueueAvailable(stack->txQueue);
|
}
|
}
|
|
|
|
|
/*******************************************************************************************
|
|
* Packet reception functions.
|
|
*******************************************************************************************/
|
|
|
|
RioEventType RIO_eventPoll( RioStack_t *stack )
|
|
{
|
|
RioEventType event;
|
|
uint32_t *packet;
|
|
uint32_t ftype;
|
|
uint32_t transaction;
|
|
|
|
|
|
/* Check if there are any new packets in the inbound queue. */
|
void RIOSTACK_setOutboundPacket(RioStack_t *stack, RioPacket_t *packet)
|
if(!QueueEmpty(stack->rxQueue))
|
|
{
|
{
|
/* There are new pending packets. */
|
uint32_t *src, *dst;
|
|
uint32_t size;
|
|
uint32_t i;
|
|
|
/* Get the packet and its ftype. */
|
|
packet = QueueGetFrontBuffer(stack->rxQueue);
|
|
ftype = FTYPE_GET(packet);
|
|
transaction = TRANSACTION_GET(packet);
|
|
|
|
/* Check the type of packets, i.e. read the ftype. */
|
ASSERT((QueueAvailable(stack->txQueue) > 0u),
|
switch(ftype)
|
"Transmission queue packet overflow.");
|
{
|
|
case FTYPE_REQUEST:
|
|
/* Request class. */
|
|
|
|
/* Check transaction type. */
|
src = &packet->payload[0];
|
switch(transaction)
|
dst = QueueGetBackBuffer(stack->txQueue);
|
|
size = packet->size;
|
|
for(i = 0; i < size; i++)
|
{
|
{
|
case TRANSACTION_REQUEST_NREAD:
|
dst[i] = src[i];
|
/* Supported NREAD request. */
|
}
|
event = RIO_EVENT_NREAD;
|
|
break;
|
|
|
|
default:
|
QueueSetSize(stack->txQueue, size);
|
/* Unsupported request transaction. */
|
stack->txQueue = QueueEnqueue(stack->txQueue);
|
/* REMARK: Throw these away for now. */
|
|
stack->statusInboundErrorPacketUnsupported++;
|
|
stack->rxQueue = QueueDequeue(stack->rxQueue);
|
|
event = RIO_EVENT_NONE;
|
|
break;
|
|
}
|
}
|
break;
|
|
|
|
case FTYPE_WRITE:
|
|
/* Write class. */
|
|
|
|
/* Check transaction type. */
|
|
switch(transaction)
|
|
{
|
|
case TRANSACTION_WRITE_NWRITE:
|
|
/* NWRITE transaction. */
|
|
if(QueueGetFrontSize(stack->rxQueue) >= 6ul)
|
|
{
|
|
/* Supported NWRITE request. */
|
|
event = RIO_EVENT_NWRITE;
|
|
}
|
|
else
|
|
{
|
|
/* Unsupported size. */
|
|
/* REMARK: Throw these away for now. */
|
|
stack->statusInboundErrorPacketUnsupported++;
|
|
stack->rxQueue = QueueDequeue(stack->rxQueue);
|
|
event = RIO_EVENT_NONE;
|
|
}
|
|
break;
|
|
|
|
case TRANSACTION_WRITE_NWRITER:
|
void RIOSTACK_clearInboundQueue(RioStack_t *stack)
|
/* NWRITE_R transaction. */
|
|
if(QueueGetFrontSize(stack->rxQueue) >= 6ul)
|
|
{
|
{
|
/* Supported NWRITE_R request. */
|
while(!QueueEmpty(stack->rxQueue))
|
event = RIO_EVENT_NWRITE_R;
|
|
}
|
|
else
|
|
{
|
{
|
/* Unsupported size. */
|
|
/* REMARK: Throw these away for now. */
|
|
stack->statusInboundErrorPacketUnsupported++;
|
|
stack->rxQueue = QueueDequeue(stack->rxQueue);
|
stack->rxQueue = QueueDequeue(stack->rxQueue);
|
event = RIO_EVENT_NONE;
|
|
}
|
}
|
break;
|
|
|
|
default:
|
|
/* Unsupported write transaction. */
|
|
/* REMARK: Throw these away for now. */
|
|
stack->statusInboundErrorPacketUnsupported++;
|
|
stack->rxQueue = QueueDequeue(stack->rxQueue);
|
|
event = RIO_EVENT_NONE;
|
|
break;
|
|
}
|
}
|
break;
|
|
|
|
case FTYPE_MAINTENANCE:
|
|
/* Maintenance class. */
|
|
|
|
/* Check transaction type. */
|
|
/* Normally, only responses could be received here unless the stack is compiled as transparent.
|
|
Maintenance requests are answered by the portAddSymbol() function. */
|
|
switch(transaction)
|
|
{
|
|
case TRANSACTION_MAINT_READ_REQUEST:
|
|
/* Maintenance read request transaction. */
|
|
if(QueueGetFrontSize(stack->rxQueue) == MAINTENANCE_TRANSACTION_READ_REQUEST_SIZE)
|
|
{
|
|
/* Supported maintenance read response. */
|
|
event = RIO_EVENT_MAINT_READ_REQUEST;
|
|
}
|
|
else
|
|
{
|
|
/* Unsupported maintenance read request. */
|
|
/* REMARK: Throw these away for now. */
|
|
stack->statusInboundErrorPacketUnsupported++;
|
|
stack->rxQueue = QueueDequeue(stack->rxQueue);
|
|
event = RIO_EVENT_NONE;
|
|
}
|
|
break;
|
|
|
|
case TRANSACTION_MAINT_WRITE_REQUEST:
|
uint8_t RIOSTACK_getInboundQueueLength(RioStack_t *stack)
|
/* Maintenance write request transaction. */
|
|
if(QueueGetFrontSize(stack->rxQueue) == MAINTENANCE_TRANSACTION_WRITE_REQUEST_SIZE)
|
|
{
|
|
/* Supported maintenance write request. */
|
|
event = RIO_EVENT_MAINT_WRITE_REQUEST;
|
|
}
|
|
else
|
|
{
|
{
|
/* Unsupported maintenance write response. */
|
return QueueLength(stack->rxQueue);
|
/* REMARK: Throw these away for now. */
|
|
stack->statusInboundErrorPacketUnsupported++;
|
|
stack->rxQueue = QueueDequeue(stack->rxQueue);
|
|
event = RIO_EVENT_NONE;
|
|
}
|
}
|
break;
|
|
|
|
case TRANSACTION_MAINT_READ_RESPONSE:
|
|
/* Maintenance read response transaction. */
|
|
if(QueueGetFrontSize(stack->rxQueue) == MAINTENANCE_TRANSACTION_READ_RESPONSE_SIZE)
|
|
{
|
|
/* Supported maintenance read response. */
|
|
event = RIO_EVENT_MAINT_READ_RESPONSE;
|
|
}
|
|
else
|
|
{
|
|
/* Unsupported maintenance read response. */
|
|
/* REMARK: Throw these away for now. */
|
|
stack->statusInboundErrorPacketUnsupported++;
|
|
stack->rxQueue = QueueDequeue(stack->rxQueue);
|
|
event = RIO_EVENT_NONE;
|
|
}
|
|
break;
|
|
|
|
case TRANSACTION_MAINT_WRITE_RESPONSE:
|
|
/* Maintenance write response transaction. */
|
uint8_t RIOSTACK_getInboundQueueAvailable(RioStack_t *stack)
|
if(QueueGetFrontSize(stack->rxQueue) == MAINTENANCE_TRANSACTION_WRITE_RESPONSE_SIZE)
|
|
{
|
|
/* Supported maintenance write response. */
|
|
event = RIO_EVENT_MAINT_WRITE_RESPONSE;
|
|
}
|
|
else
|
|
{
|
{
|
/* Unsupported maintenance write response. */
|
return QueueAvailable(stack->rxQueue);
|
/* REMARK: Throw these away for now. */
|
|
stack->statusInboundErrorPacketUnsupported++;
|
|
stack->rxQueue = QueueDequeue(stack->rxQueue);
|
|
event = RIO_EVENT_NONE;
|
|
}
|
}
|
break;
|
|
|
|
default:
|
|
/* Unsupported maintenance transaction. */
|
|
/* REMARK: Throw these away for now. */
|
|
stack->statusInboundErrorPacketUnsupported++;
|
|
stack->rxQueue = QueueDequeue(stack->rxQueue);
|
|
event = RIO_EVENT_NONE;
|
|
break;
|
|
}
|
|
break;
|
|
|
|
case FTYPE_DOORBELL:
|
|
/* Doorbell class. */
|
|
|
|
/* Check size of message. */
|
void RIOSTACK_getInboundPacket(RioStack_t *stack, RioPacket_t *packet)
|
if(QueueGetFrontSize(stack->rxQueue) == 3ul)
|
|
{
|
|
/* Supported doorbell. */
|
|
event = RIO_EVENT_DOORBELL;
|
|
}
|
|
else
|
|
{
|
{
|
/* Unsupported doorbell request. */
|
uint32_t *src, *dst;
|
/* REMARK: Throw these away for now. */
|
uint32_t size;
|
stack->statusInboundErrorPacketUnsupported++;
|
uint32_t i;
|
stack->rxQueue = QueueDequeue(stack->rxQueue);
|
|
event = RIO_EVENT_NONE;
|
|
}
|
|
break;
|
|
|
|
case FTYPE_MESSAGE:
|
|
/* Message class. */
|
|
|
|
/* Check msglen to see if this packet continues. */
|
ASSERT(!QueueEmpty(stack->rxQueue), "Reading from empty reception queue.");
|
if(MSGLEN_GET(packet) == 0ul)
|
|
|
src = QueueGetFrontBuffer(stack->rxQueue);
|
|
dst = &packet->payload[0];
|
|
size = QueueGetSize(stack->rxQueue);
|
|
for(i = 0; i < size; i++)
|
{
|
{
|
/* Single-packet message. */
|
dst[i] = src[i];
|
event = RIO_EVENT_MESSAGE;
|
|
}
|
}
|
else
|
|
{
|
packet->size = size;
|
/* Unsupported message type. */
|
|
/* REMARK: Throw these away for now. */
|
|
stack->statusInboundErrorPacketUnsupported++;
|
|
stack->rxQueue = QueueDequeue(stack->rxQueue);
|
stack->rxQueue = QueueDequeue(stack->rxQueue);
|
event = RIO_EVENT_NONE;
|
|
}
|
}
|
break;
|
|
|
|
case FTYPE_RESPONSE:
|
|
/* Response class. */
|
|
|
|
/* Check transaction field. */
|
|
switch(transaction)
|
|
{
|
|
case TRANSACTION_RESPONSE_NO_PAYLOAD:
|
|
/* Response transaction without payload. */
|
|
|
|
/* Check status field. */
|
/*******************************************************************************************
|
switch(QueueGetFrontContent(stack->rxQueue, 1ul) & 0x00000f00ul)
|
* Packet port functions.
|
|
*******************************************************************************************/
|
|
|
|
void RIOSTACK_portSetTime(RioStack_t *stack, const uint32_t time)
|
{
|
{
|
case 0x00000000:
|
stack->portTime = time;
|
event = RIO_EVENT_RESPONSE_DONE;
|
|
break;
|
|
case 0x00000300:
|
|
event = RIO_EVENT_RESPONSE_RETRY;
|
|
break;
|
|
case 0x00000700:
|
|
event = RIO_EVENT_RESPONSE_ERROR;
|
|
break;
|
|
default:
|
|
/* Unsupported response status. */
|
|
/* REMARK: Throw these away for now. */
|
|
stack->statusInboundErrorPacketUnsupported++;
|
|
stack->rxQueue = QueueDequeue(stack->rxQueue);
|
|
event = RIO_EVENT_NONE;
|
|
break;
|
|
}
|
}
|
break;
|
|
|
|
case TRANSACTION_RESPONSE_MESSAGE_RESPONSE:
|
|
/* Message response transaction. */
|
|
|
|
/* Check status field. */
|
|
switch(QueueGetFrontContent(stack->rxQueue, 1ul) & 0x00000f00ul)
|
void RIOSTACK_portSetTimeout(RioStack_t *stack, const uint32_t time)
|
{
|
{
|
case 0x00000000:
|
stack->portTimeout = time;
|
event = RIO_EVENT_MESSAGE_RESPONSE_DONE;
|
|
break;
|
|
case 0x00000300:
|
|
event = RIO_EVENT_MESSAGE_RESPONSE_RETRY;
|
|
break;
|
|
case 0x00000700:
|
|
event = RIO_EVENT_MESSAGE_RESPONSE_ERROR;
|
|
break;
|
|
default:
|
|
/* Unsupported message response status. */
|
|
/* REMARK: Throw these away for now. */
|
|
stack->statusInboundErrorPacketUnsupported++;
|
|
stack->rxQueue = QueueDequeue(stack->rxQueue);
|
|
event = RIO_EVENT_NONE;
|
|
break;
|
|
}
|
}
|
break;
|
|
|
|
case TRANSACTION_RESPONSE_WITH_PAYLOAD:
|
|
/* Response with payload transaction. */
|
|
|
|
/* Check status field. */
|
|
switch(QueueGetFrontContent(stack->rxQueue, 1ul) & 0x00000f00ul)
|
|
{
|
|
case 0x00000000:
|
|
event = RIO_EVENT_RESPONSE_DONE_PAYLOAD;
|
|
break;
|
|
case 0x00000300:
|
|
event = RIO_EVENT_RESPONSE_RETRY;
|
|
break;
|
|
case 0x00000700:
|
|
event = RIO_EVENT_RESPONSE_ERROR;
|
|
break;
|
|
default:
|
|
/* Unsupported response with payload status. */
|
|
/* REMARK: Throw these away for now. */
|
|
stack->statusInboundErrorPacketUnsupported++;
|
|
stack->rxQueue = QueueDequeue(stack->rxQueue);
|
|
event = RIO_EVENT_NONE;
|
|
break;
|
|
}
|
|
break;
|
|
|
|
default:
|
void RIOSTACK_portSetStatus(RioStack_t *stack, const uint8_t initialized)
|
/* Unsupported response transaction. */
|
{
|
/* REMARK: Throw these away for now. */
|
/* REMARK: Clean the queues here as well??? */
|
stack->statusInboundErrorPacketUnsupported++;
|
if (initialized)
|
stack->rxQueue = QueueDequeue(stack->rxQueue);
|
{
|
event = RIO_EVENT_NONE;
|
stack->rxState = RX_STATE_PORT_INITIALIZED;
|
break;
|
stack->rxCounter = 0u;
|
}
|
stack->rxCrc = 0xffffu;
|
break;
|
stack->rxStatusReceived = 0;
|
|
stack->rxAckId = 0u;
|
|
stack->rxAckIdAcked = 0u;
|
|
stack->rxErrorCause = PACKET_NOT_ACCEPTED_CAUSE_RESERVED;
|
|
|
default:
|
stack->txState = TX_STATE_PORT_INITIALIZED;
|
/* Unsupported class. */
|
stack->txCounter = 0u;
|
/* REMARK: Throw these away for now. */
|
stack->txStatusCounter = 0u;
|
stack->statusInboundErrorPacketUnsupported++;
|
stack->txFrameState = TX_FRAME_START;
|
stack->rxQueue = QueueDequeue(stack->rxQueue);
|
stack->txAckId = 0u;
|
event = RIO_EVENT_NONE;
|
stack->txAckIdWindow = 0u;
|
break;
|
|
}
|
|
}
|
}
|
else
|
else
|
{
|
{
|
/* No pending events available. */
|
stack->rxState = RX_STATE_UNINITIALIZED;
|
event = RIO_EVENT_NONE;
|
stack->txState = TX_STATE_UNINITIALIZED;
|
}
|
}
|
|
|
return event;
|
|
}
|
}
|
|
|
|
|
void RIO_packetRemove( RioStack_t *stack )
|
|
{
|
|
ASSERT(!QueueEmpty(stack->rxQueue), "Reading from empty reception queue.");
|
|
|
|
stack->rxQueue = QueueDequeue(stack->rxQueue);
|
|
}
|
|
|
|
|
|
bool_t RIO_sendAvailable( RioStack_t *stack, const uint16_t size )
|
void RIOSTACK_portAddSymbol(RioStack_t *stack, const RioSymbol_t s)
|
{
|
{
|
/* Return if there are buffers available and if the requested size is less
|
uint8_t stype0;
|
than or equal to the maximum payload that fits into one packet. */
|
uint8_t parameter0;
|
return (bool_t) (stack->masterEnable && (size <= 256u) && (QueueAvailable(stack->txQueue) > 0u));
|
uint8_t parameter1;
|
}
|
uint8_t stype1;
|
|
|
|
|
uint32_t RIO_packetGet( RioStack_t *stack, uint32_t length, uint32_t *dest)
|
switch(stack->rxState)
|
{
|
{
|
uint32_t i;
|
case RX_STATE_PORT_INITIALIZED:
|
uint32_t size;
|
/******************************************************************************
|
uint32_t *src;
|
* PORT_INITIALIZED
|
|
* This state is entered to initialize the link. Only status-control-symbols
|
|
* are accepted in this state. When 7 error-free, i.e. with CRC5 correct, status
|
|
* control symbols has been received, change state to linkInitialized.
|
|
******************************************************************************/
|
|
|
|
/* Check the type of symbol. */
|
|
if(s.type == RIOSTACK_SYMBOL_TYPE_CONTROL)
|
|
{
|
|
/* This is a control symbol. */
|
|
|
ASSERT(!QueueEmpty(stack->rxQueue), "Reading from empty reception queue.");
|
/* Check that the control symbol contains no errors. */
|
|
if(Crc5(s.data, 0x1fu) == (s.data & 0x1ful))
|
|
{
|
|
/* Error-free control symbol. */
|
|
|
/* Get the size and a pointer to the raw packet. */
|
/* Check if the symbol is a status symbol. */
|
size = QueueGetFrontSize(stack->rxQueue);
|
stype0 = STYPE0_GET(s.data);
|
src = QueueGetFrontBuffer(stack->rxQueue);
|
if(stype0 == STYPE0_STATUS)
|
|
{
|
|
/* Status symbol received. */
|
|
|
ASSERT((length >= size), "Too short destination packet.");
|
/* Indicate an error-free status has been received. */
|
|
stack->rxStatusReceived = 1;
|
|
|
/* Copy the packet to the destination packet pointer. */
|
/* Check if enough status control symbols has been received. */
|
for(i = 0; i < size; i++)
|
if(stack->rxCounter == 7u)
|
{
|
{
|
dest[i] = src[i];
|
/* Enough correct status control symbols has been received without
|
}
|
errors in between. */
|
|
|
/* Remove the packet from the queue. */
|
/* Setup the transmitter with the content of the symbol. */
|
stack->rxQueue = QueueDequeue(stack->rxQueue);
|
stack->txAckId = PARAMETER0_GET(s.data);
|
|
stack->txAckIdWindow = stack->txAckId;
|
|
stack->txBufferStatus = PARAMETER1_GET(s.data);
|
|
|
/* Return the size of the copied packet. */
|
/* Set the transmitter in its normal operational mode. */
|
return size;
|
stack->rxState = RX_STATE_LINK_INITIALIZED;
|
|
stack->rxCounter = 0u;
|
}
|
}
|
|
else
|
|
|
void RIO_packetSet( RioStack_t *stack, uint32_t length, uint32_t *src)
|
|
{
|
{
|
uint32_t i;
|
/* Count the number of consequitive error-free status control symbols
|
uint32_t *dest;
|
that has been received. */
|
|
stack->rxCounter++;
|
|
}
|
ASSERT((QueueAvailable(stack->txQueue) > 0), "Writing to full transmission queue.");
|
}
|
ASSERT((length < RIO_PACKET_SIZE), "Writing a too large packet.");
|
else
|
|
|
/* Set the size of the new packet. */
|
|
QueueSetSize(stack->txQueue, length);
|
|
|
|
/* Get a pointer to the destination packet in the transmission queue. */
|
|
dest = QueueGetBackBuffer(stack->txQueue);
|
|
|
|
/* Copy the packet into the transmission queue. */
|
|
for(i = 0; i < length; i++)
|
|
{
|
{
|
dest[i] = src[i];
|
/* The received symbol is not a status symbol. */
|
|
/* Discard it. */
|
}
|
}
|
|
}
|
/* Make sure the ackId field of the copied packet is reset. */
|
else
|
/* Unless this is done, the ackId field of the transmitted packet may be corrupted. */
|
{
|
dest[0] &= 0x03ffffff;
|
/* CRC error in control symbol. */
|
|
/* Restart counting error-free status-control-symbols. */
|
/* Enqueue the new packet. */
|
stack->rxCounter = 0u;
|
stack->txQueue = QueueEnqueue(stack->txQueue);
|
}
|
|
}
|
|
else
|
|
{
|
|
/* Not a control symbol. */
|
|
/* Discard the symbol. */
|
}
|
}
|
|
|
/*******************************************************************************************
|
break;
|
* Configuration-space access methods.
|
|
*******************************************************************************************/
|
case RX_STATE_LINK_INITIALIZED:
|
|
/******************************************************************************
|
|
* LINK_INITIALIZED
|
|
* The normal state. Accept packets and forward them.
|
|
******************************************************************************/
|
|
|
uint32_t RIO_readConfig( RioStack_t *stack, const uint32_t offset )
|
/* Check the type of symbol. */
|
|
switch(s.type)
|
{
|
{
|
uint32_t data;
|
case RIOSTACK_SYMBOL_TYPE_CONTROL:
|
|
/**************************************************************************
|
|
* This is a control symbol.
|
|
**************************************************************************/
|
|
|
/* Check the area of the access. */
|
/* Check if the CRC is correct. */
|
if(offset < 0x10000ul)
|
if(Crc5(s.data, 0x1fu) == (s.data & (uint8_t)0x1ful))
|
{
|
{
|
/* Access is in not in implementation-defined space. */
|
/* The CRC is correct. */
|
|
|
|
/* Get the content of the control symbol. */
|
|
stype0 = STYPE0_GET(s.data);
|
|
parameter0 = PARAMETER0_GET(s.data);
|
|
parameter1 = PARAMETER1_GET(s.data);
|
|
stype1 = STYPE1_GET(s.data);
|
|
|
/* Check offset and return. */
|
/**********************************************************************************
|
switch(offset)
|
* Check the stype0 part of the symbol.
|
|
* Note that errors in this should trigger OUTPUT_ERROR_STOPPED.
|
|
**********************************************************************************/
|
|
switch(stype0)
|
{
|
{
|
case DEVICE_IDENTITY_CAR:
|
case STYPE0_STATUS:
|
data = (uint32_t)stack->deviceIdentity << 16;
|
/* A status containing the current ackId and the buffer status has been
|
data |= stack->deviceVendorIdentity;
|
received. */
|
break;
|
handleStatus(stack, parameter0, parameter1);
|
case DEVICE_INFORMATION_CAR:
|
|
data = stack->deviceRev;
|
|
break;
|
|
case ASSEMBLY_IDENTITY_CAR:
|
|
data = (uint32_t)stack->assyIdentity << 16;
|
|
data |= stack->assyVendorIdentity;
|
|
break;
|
|
case ASSEMBLY_INFORMATION_CAR:
|
|
data = (uint32_t)stack->assyRev << 16;
|
|
data |= EXTENDED_FEATURES_OFFSET;
|
|
break;
|
|
case PROCESSING_ELEMENT_FEATURES_CAR:
|
|
/* Indicate processor with extended features
|
|
and 34-bit address support. */
|
|
/* Supports common transport large systems. */
|
|
data = 0x20000019ul;
|
|
break;
|
|
case SOURCE_OPERATIONS_CAR:
|
|
/* Supporting doorbells and data messages. */
|
|
data = 0x00000c00ul;
|
|
break;
|
break;
|
case DESTINATION_OPERATIONS_CAR:
|
|
/* Supporting doorbells and data messages. */
|
case STYPE0_PACKET_ACCEPTED:
|
data = 0x00000c00ul;
|
/* A packet has been accepted by the link partner. */
|
|
handlePacketAccepted(stack, parameter0, parameter1);
|
break;
|
break;
|
case PROCESSING_ELEMENT_LOGICAL_LAYER_CONTROL_CSR:
|
|
/* Supports 34-bit addresses. */
|
case STYPE0_PACKET_RETRY:
|
data = 0x00000001ul;
|
/* The link partner wants us to initiate a restart of the received ackId. */
|
|
handlePacketRetry(stack, parameter0, parameter1);
|
break;
|
break;
|
case BASE_DEVICE_ID_CSR:
|
|
data = stack->baseDeviceId;
|
case STYPE0_PACKET_NOT_ACCEPTED:
|
|
/* The link partner indicates that a packet has been rejected. */
|
|
handlePacketNotAccepted(stack, parameter0, parameter1);
|
break;
|
break;
|
case HOST_BASE_DEVICE_ID_LOCK_CSR:
|
|
data = stack->hostBaseDeviceIdLock & (uint32_t)0x0000fffful;
|
case STYPE0_LINK_RESPONSE:
|
|
/* The link partner has sent a response to a link-request. */
|
|
handleLinkResponse(stack, parameter0, parameter1);
|
break;
|
break;
|
case COMPONENT_TAG_CSR:
|
|
data = stack->componentTag;
|
case STYPE0_VC_STATUS:
|
|
case STYPE0_RESERVED:
|
|
case STYPE0_IMPLEMENTATION_DEFINED:
|
|
default:
|
|
/* Unsupported symbol received. */
|
|
/* Discard them. */
|
break;
|
break;
|
case LP_SERIAL_REGISTER_BLOCK_HEADER(EXTENDED_FEATURES_OFFSET):
|
}
|
/* Indicate Generic end point device and no more extended features. */
|
|
data = 0x00000001ul;
|
/**********************************************************************************
|
|
* Check the stype1 part of the symbol.
|
|
* Note that errors in this should trigger INPUT_ERROR_STOPPED.
|
|
**********************************************************************************/
|
|
switch(stype1)
|
|
{
|
|
case STYPE1_START_OF_PACKET:
|
|
/* Start of a new packet. */
|
|
handleStartOfPacket(stack);
|
break;
|
break;
|
case PORT_LINK_TIMEOUT_CONTROL_CSR(EXTENDED_FEATURES_OFFSET):
|
|
/* REMARK: Implement this... */
|
case STYPE1_END_OF_PACKET:
|
data = 0x00000000ul;
|
/* Ending a packet. */
|
|
handleEndOfPacket(stack);
|
break;
|
break;
|
case PORT_RESPONSE_TIMEOUT_CONTROL_CSR(EXTENDED_FEATURES_OFFSET):
|
|
/* REMARK: Implement this... */
|
case STYPE1_STOMP:
|
data = 0x00000000ul;
|
/* Cancel the currently received frame. */
|
|
stack->rxCounter = 0;
|
break;
|
break;
|
case PORT_GENERAL_CONTROL_CSR(EXTENDED_FEATURES_OFFSET):
|
|
/* Return the host, master enable bit and the discovered bit. */
|
case STYPE1_RESTART_FROM_RETRY:
|
data = ((uint32_t) stack->host) << 31;
|
/* Cancel the currently received frame when in this state. */
|
data |= ((uint32_t) stack->masterEnable) << 30;
|
stack->rxCounter = 0;
|
data |= ((uint32_t) stack->discovered) << 29;
|
|
break;
|
break;
|
case PORT_N_LOCAL_ACKID_CSR(EXTENDED_FEATURES_OFFSET, 0u):
|
|
data = ((uint32_t) stack->rxAckId) << 24;
|
case STYPE1_LINK_REQUEST:
|
data |= ((uint32_t) stack->txAckId) << 8;
|
/* A link-request has been received. */
|
data |= ((uint32_t) stack->txAckIdWindow);
|
handleLinkRequest(stack, CMD_GET(s.data));
|
break;
|
break;
|
case PORT_N_ERROR_AND_STATUS_CSR(EXTENDED_FEATURES_OFFSET, 0u):
|
|
/* Indicate the port status here. */
|
case STYPE1_NOP:
|
if((stack->txState == TX_STATE_LINK_INITIALIZED) &&
|
/* No operation symbol. */
|
(stack->rxState == RX_STATE_LINK_INITIALIZED))
|
/* Discard these. */
|
{
|
|
/* Port ok. */
|
|
data = 0x00000002ul;
|
|
}
|
|
else
|
|
{
|
|
/* Port not ok. */
|
|
data = 0x00000001ul;
|
|
}
|
|
break;
|
break;
|
|
|
|
case STYPE1_MULTICAST_EVENT:
|
|
case STYPE1_RESERVED:
|
default:
|
default:
|
data = 0x00000000ul;
|
/* Unsupported symbol received. */
|
|
/* Discard them. */
|
break;
|
break;
|
}
|
}
|
}
|
}
|
else
|
else
|
{
|
{
|
/* Access is in implementation-defined space. */
|
/* The control symbol CRC is incorrect. */
|
|
/* Corrupted control symbol. Discard the symbol and enter the input-error-stopped state. */
|
/* Check if there are any registered callback. */
|
stack->txState = TX_STATE_SEND_PACKET_NOT_ACCEPTED;
|
if((stack->observer != NULL) &&
|
stack->rxState = RX_STATE_INPUT_ERROR_STOPPED;
|
(stack->observer->configRead != NULL))
|
stack->rxErrorCause = PACKET_NOT_ACCEPTED_CAUSE_CONTROL_CRC;
|
{
|
stack->statusInboundErrorControlCrc++;
|
/* Call the observer callback to handle the access. */
|
|
data = stack->observer->configRead(stack, offset - 0x00010000ul);
|
|
}
|
|
else
|
|
{
|
|
data = 0x00000000ul;
|
|
}
|
|
}
|
|
|
|
return data;
|
|
}
|
}
|
|
break;
|
|
|
|
case RIOSTACK_SYMBOL_TYPE_DATA:
|
|
/**************************************************************************
|
|
* This is a data symbol.
|
|
**************************************************************************/
|
|
|
void RIO_writeConfig( RioStack_t *stack, const uint32_t offset, const uint32_t data)
|
/* Check if a packet has been started and that it is not too long. */
|
{
|
if ((stack->rxCounter >= 1u) && (stack->rxCounter <= RIOPACKET_SIZE_MAX))
|
/* Check the area of the access. */
|
|
if(offset < 0x00010000ul)
|
|
{
|
{
|
/* Access is not in implementation-defined space. */
|
/* A packet has been started. */
|
|
|
/* Check offset and execute request. */
|
/* Check if the ackId is correct on the first part of the packet. */
|
switch(offset)
|
if ((stack->rxCounter > 1u) ||
|
|
((stack->rxCounter == 1u) && (((uint8_t)(s.data >> 27)) == stack->rxAckId)))
|
{
|
{
|
case BASE_DEVICE_ID_CSR:
|
/* The ackId is the expected one. */
|
stack->baseDeviceId = (uint16_t) data;
|
|
break;
|
/* Check if this is the first symbol of a packet. */
|
case HOST_BASE_DEVICE_ID_LOCK_CSR:
|
if (stack->rxCounter == 1u)
|
if (stack->hostBaseDeviceIdLock == 0xfffffffful)
|
|
{
|
{
|
stack->hostBaseDeviceIdLock = (uint16_t)data;
|
/* This is the first symbol of the packet. */
|
|
/* Start to calculate the CRC of the packet. */
|
|
/* Note that the ackId should not be included in the CRC calculation. */
|
|
stack->rxCrc = RIOPACKET_Crc32(s.data & (uint32_t)0x03fffffful, 0xffffu);
|
}
|
}
|
else
|
else
|
{
|
{
|
if ((stack->hostBaseDeviceIdLock & (uint32_t)0x0000fffful) ==
|
/* This is not the first symbol. */
|
(data & (uint32_t)0x0000fffful))
|
/* Continue to calculate the CRC of the packet. */
|
{
|
stack->rxCrc = RIOPACKET_Crc32(s.data, stack->rxCrc);
|
stack->hostBaseDeviceIdLock = 0xfffffffful;
|
}
|
|
|
|
/* Save the new data in the packet queue and update the reception counter. */
|
|
QueueSetContent(stack->rxQueue, (uint32_t)stack->rxCounter - (uint32_t)1ul, s.data);
|
|
stack->rxCounter++;
|
}
|
}
|
else
|
else
|
{
|
{
|
/* Ignore the write. */
|
/* The ackId is not correct. */
|
|
/* Packet error. Enter input-error-stopped state. */
|
|
stack->txState = TX_STATE_SEND_PACKET_NOT_ACCEPTED;
|
|
stack->rxState = RX_STATE_INPUT_ERROR_STOPPED;
|
|
stack->rxErrorCause = PACKET_NOT_ACCEPTED_CAUSE_UNEXPECTED_ACKID;
|
|
stack->statusInboundErrorPacketAckId++;
|
}
|
}
|
}
|
}
|
break;
|
else
|
case COMPONENT_TAG_CSR:
|
|
stack->componentTag = data;
|
|
break;
|
|
case PORT_LINK_TIMEOUT_CONTROL_CSR(EXTENDED_FEATURES_OFFSET):
|
|
/* REMARK: Implement this... */
|
|
break;
|
|
case PORT_RESPONSE_TIMEOUT_CONTROL_CSR(EXTENDED_FEATURES_OFFSET):
|
|
/* REMARK: Implement this... */
|
|
break;
|
|
case PORT_GENERAL_CONTROL_CSR(EXTENDED_FEATURES_OFFSET):
|
|
/* Return host, master enable bit and discovered bit. */
|
|
stack->host = (uint8_t)(data >> 31) & 1u;
|
|
stack->masterEnable = (uint8_t)(data >> 30) & 1u;
|
|
stack->discovered = (uint8_t)(data >> 29) & 1u;
|
|
break;
|
|
case PORT_N_LOCAL_ACKID_CSR(EXTENDED_FEATURES_OFFSET, 0u):
|
|
if(data & 0x80000000)
|
|
{
|
|
while(!QueueEmpty(stack->txQueue))
|
|
{
|
{
|
stack->txQueue = QueueDequeue(stack->txQueue);
|
/* No packet has been started or the packet is too long. */
|
}
|
/* Packet error. Enter input-error-stopped state. */
|
|
stack->txState = TX_STATE_SEND_PACKET_NOT_ACCEPTED;
|
|
stack->rxState = RX_STATE_INPUT_ERROR_STOPPED;
|
|
stack->rxErrorCause = PACKET_NOT_ACCEPTED_CAUSE_GENERAL;
|
|
stack->statusInboundErrorGeneral++;
|
}
|
}
|
stack->rxAckId = (uint8_t) ((data >> 24) & 0x1f);
|
|
stack->txAckId = (uint8_t) ((data >> 8) & 0x1f);
|
|
stack->txAckIdWindow = (uint8_t) (data & 0x1f);
|
|
break;
|
|
default:
|
|
break;
|
break;
|
}
|
|
}
|
|
else
|
|
{
|
|
/* Access is in implementation-defined space. */
|
|
|
|
/* Check if there are any registered callback. */
|
case RIOSTACK_SYMBOL_TYPE_ERROR:
|
if((stack->observer != NULL) &&
|
/**************************************************************************
|
(stack->observer->configWrite != NULL))
|
* The decoder has received a erronous symbol.
|
{
|
**************************************************************************/
|
/* Call the observer callback to handle the access. */
|
|
stack->observer->configWrite(stack, offset - 0x00010000ul, data);
|
|
}
|
|
else
|
|
{
|
|
/* Dont do anything. */
|
|
}
|
|
}
|
|
}
|
|
|
|
|
/* Idle symbol error. Place the receiver in input-error-stopped state. */
|
|
stack->txState = TX_STATE_SEND_PACKET_NOT_ACCEPTED;
|
|
stack->rxState = RX_STATE_INPUT_ERROR_STOPPED;
|
|
stack->rxErrorCause = PACKET_NOT_ACCEPTED_CAUSE_ILLEGAL_CHARACTER;
|
|
stack->statusInboundErrorIllegalCharacter++;
|
|
break;
|
|
|
/*******************************************************************************************
|
case RIOSTACK_SYMBOL_TYPE_IDLE:
|
* Logical I/O MAINTENANCE-READ functions.
|
default:
|
*******************************************************************************************/
|
/**************************************************************************
|
|
* Idle symbol or unsupported symbol.
|
|
**************************************************************************/
|
|
|
#ifdef RIO_TRANSPARENT
|
/* Discard these for now. */
|
void RIO_sendMaintenanceReadRequest( RioStack_t *stack, const uint16_t destid, const uint16_t srcid, const uint8_t tid,
|
break;
|
const uint8_t hopCount, const uint32_t offset)
|
|
{
|
|
sendMaintenanceReadRequest(stack, destid, srcid, tid, hopCount, offset);
|
|
}
|
|
#else
|
|
void RIO_sendMaintenanceReadRequest( RioStack_t *stack, const uint16_t destid, const uint8_t tid,
|
|
const uint8_t hopCount, const uint32_t offset)
|
|
{
|
|
sendMaintenanceReadRequest(stack, destid, stack->baseDeviceId, tid, hopCount, offset);
|
|
}
|
}
|
#endif
|
break;
|
|
|
#ifdef RIO_TRANSPARENT
|
case RX_STATE_INPUT_RETRY_STOPPED:
|
void RIO_receiveMaintenanceReadRequest( RioStack_t *stack, uint16_t *destid, uint16_t *srcid, uint8_t *tid,
|
/******************************************************************************
|
uint8_t *hopCount, uint32_t *offset)
|
* INPUT_RETRY_STOPPED
|
{
|
* This state is entered when no more buffers was available and a packet was
|
receiveMaintenanceReadRequest( stack, destid, srcid, tid, hopCount, offset);
|
* received. When in this state, all packets should be discarded until a
|
}
|
* RESTART-FROM-RETRY symbol is received. See section 5.9.1.4 of the standard.
|
#else
|
* Note that it is only the input side of the port that are affected, not the
|
void RIO_receiveMaintenanceReadRequest( RioStack_t *stack, uint16_t *srcid, uint8_t *tid,
|
* output side. Packets may still be transmitted and acknowledges should be
|
uint8_t *hopCount, uint32_t *offset)
|
* accepted.
|
{
|
******************************************************************************/
|
receiveMaintenanceReadRequest( stack, srcid, srcid, tid, hopCount, offset);
|
|
}
|
|
#endif
|
|
|
|
#ifdef RIO_TRANSPARENT
|
/* Check the type of symbol. */
|
void RIO_sendMaintenanceReadResponse( RioStack_t *stack, const uint16_t destid, const uint16_t srcid, const uint8_t tid,
|
switch(s.type)
|
const uint8_t hopCount, const uint32_t data)
|
|
{
|
|
sendMaintenanceReadResponse(stack, destid, srcid, tid, hopCount, data);
|
|
}
|
|
#else
|
|
void RIO_sendMaintenanceReadResponse( RioStack_t *stack, const uint16_t destid, const uint8_t tid,
|
|
const uint8_t hopCount, const uint32_t data)
|
|
{
|
{
|
sendMaintenanceReadResponse(stack, destid, stack->baseDeviceId, tid, hopCount, data);
|
case RIOSTACK_SYMBOL_TYPE_CONTROL:
|
}
|
/* This is a control symbol. */
|
#endif
|
|
|
|
#ifdef RIO_TRANSPARENT
|
/* Check if the CRC is correct. */
|
void RIO_receiveMaintenanceReadResponse( RioStack_t *stack, uint16_t *destid, uint16_t *srcid, uint8_t *tid,
|
if(Crc5(s.data, 0x1fu) == (s.data & (uint8_t)0x1ful))
|
uint8_t *hopCount, uint32_t *data)
|
|
{
|
|
receiveMaintenanceReadResponse(stack, destid, srcid, tid, hopCount, data);
|
|
}
|
|
#else
|
|
void RIO_receiveMaintenanceReadResponse( RioStack_t *stack, uint16_t *srcid, uint8_t *tid,
|
|
uint8_t *hopCount, uint32_t *data)
|
|
{
|
{
|
receiveMaintenanceReadResponse(stack, srcid, srcid, tid, hopCount, data);
|
/* The CRC is correct. */
|
}
|
|
#endif
|
|
|
|
/*******************************************************************************************
|
/* Get the content of the control symbol. */
|
* Logical I/O MAINTENANCE-WRITE functions.
|
stype0 = STYPE0_GET(s.data);
|
*******************************************************************************************/
|
parameter0 = PARAMETER0_GET(s.data);
|
|
parameter1 = PARAMETER1_GET(s.data);
|
|
stype1 = STYPE1_GET(s.data);
|
|
|
#ifdef RIO_TRANSPARENT
|
/* Check the stype0 part of the symbol. */
|
void RIO_sendMaintenanceWriteRequest( RioStack_t *stack, const uint16_t destid, const uint16_t srcid, const uint8_t tid,
|
switch(stype0)
|
const uint8_t hopCount, const uint32_t offset, const uint32_t data )
|
|
{
|
|
sendMaintenanceWriteRequest(stack, destid, srcid, tid, hopCount, offset, data);
|
|
}
|
|
#else
|
|
void RIO_sendMaintenanceWriteRequest( RioStack_t *stack, const uint16_t destid, const uint8_t tid,
|
|
const uint8_t hopCount, const uint32_t offset, const uint32_t data )
|
|
{
|
{
|
sendMaintenanceWriteRequest(stack, destid, stack->baseDeviceId, tid, hopCount, offset, data);
|
case STYPE0_STATUS:
|
}
|
/* A status containing the current ackId and the buffer status has been
|
#endif
|
received. */
|
|
handleStatus(stack, parameter0, parameter1);
|
|
break;
|
|
|
#ifdef RIO_TRANSPARENT
|
case STYPE0_PACKET_ACCEPTED:
|
void RIO_receiveMaintenanceWriteRequest( RioStack_t *stack, uint16_t *destid, uint16_t *srcid, uint8_t *tid,
|
/* A packet has been accepted by the link partner. */
|
uint8_t *hopCount, uint32_t *offset, uint32_t *data )
|
handlePacketAccepted(stack, parameter0, parameter1);
|
{
|
break;
|
receiveMaintenanceWriteRequest(stack, destid, srcid, tid, hopCount, offset, data);
|
|
}
|
|
#else
|
|
void RIO_receiveMaintenanceWriteRequest( RioStack_t *stack, uint16_t *srcid, uint8_t *tid,
|
|
uint8_t *hopCount, uint32_t *offset, uint32_t *data )
|
|
{
|
|
receiveMaintenanceWriteRequest(stack, srcid, srcid, tid, hopCount, offset, data);
|
|
}
|
|
#endif
|
|
|
|
#ifdef RIO_TRANSPARENT
|
|
void RIO_sendMaintenanceWriteResponse( RioStack_t *stack, const uint16_t destid, const uint16_t srcid, const uint8_t tid,
|
|
const uint8_t hopCount)
|
|
{
|
|
sendMaintenanceWriteResponse(stack, destid, srcid, tid, hopCount);
|
|
}
|
|
#else
|
|
void RIO_sendMaintenanceWriteResponse( RioStack_t *stack, const uint16_t destid, const uint8_t tid,
|
|
const uint8_t hopCount)
|
|
{
|
|
sendMaintenanceWriteResponse(stack, destid, stack->baseDeviceId, tid, hopCount);
|
|
}
|
|
#endif
|
|
|
|
#ifdef RIO_TRANSPARENT
|
case STYPE0_PACKET_RETRY:
|
void RIO_receiveMaintenanceWriteResponse( RioStack_t *stack, uint16_t *destid, uint16_t *srcid, uint8_t *tid,
|
/* The link partner wants us to initiate a restart of the received ackId. */
|
uint8_t *hopCount)
|
handlePacketRetry(stack, parameter0, parameter1);
|
{
|
break;
|
receiveMaintenanceWriteResponse(stack, destid, srcid, tid, hopCount);
|
|
}
|
|
#else
|
|
void RIO_receiveMaintenanceWriteResponse( RioStack_t *stack, uint16_t *srcid, uint8_t *tid,
|
|
uint8_t *hopCount)
|
|
{
|
|
receiveMaintenanceWriteResponse(stack, srcid, srcid, tid, hopCount);
|
|
}
|
|
#endif
|
|
|
|
/*******************************************************************************************
|
case STYPE0_PACKET_NOT_ACCEPTED:
|
* Logical I/O NWRITE/NWRITER functions.
|
/* The link partner indicates that a packet has been rejected. */
|
*******************************************************************************************/
|
handlePacketNotAccepted(stack, parameter0, parameter1);
|
|
break;
|
|
|
#ifdef RIO_TRANSPARENT
|
case STYPE0_LINK_RESPONSE:
|
void RIO_sendNwrite( RioStack_t *stack, const uint16_t destid, const uint16_t srcid,
|
/* The link partner has sent a response to a link-request. */
|
const uint32_t address, const uint16_t size, const uint8_t *data)
|
handleLinkResponse(stack, parameter0, parameter1);
|
{
|
break;
|
sendNwrite(stack, destid, srcid, 0, address, size, data, 0u);
|
|
}
|
|
#else
|
|
void RIO_sendNwrite( RioStack_t *stack, const uint16_t destid,
|
|
const uint32_t address, const uint16_t size, const uint8_t *data)
|
|
{
|
|
sendNwrite(stack, destid, stack->baseDeviceId, 0, address, size, data, 0u);
|
|
}
|
|
#endif
|
|
|
|
#ifdef RIO_TRANSPARENT
|
case STYPE0_VC_STATUS:
|
void RIO_sendNwriteR( RioStack_t *stack, const uint16_t destid, const uint16_t srcid, const uint8_t tid,
|
case STYPE0_RESERVED:
|
const uint32_t address, const uint16_t size, const uint8_t *data)
|
case STYPE0_IMPLEMENTATION_DEFINED:
|
{
|
default:
|
sendNwrite(stack, destid, srcid, tid, address, size, data, 1u);
|
/* Unsupported symbol received. */
|
}
|
/* Discard them. */
|
#else
|
break;
|
void RIO_sendNwriteR( RioStack_t *stack, const uint16_t destid, const uint8_t tid,
|
|
const uint32_t address, const uint16_t size, const uint8_t *data)
|
|
{
|
|
sendNwrite(stack, destid, stack->baseDeviceId, tid, address, size, data, 1u);
|
|
}
|
}
|
#endif
|
|
|
|
#ifdef RIO_TRANSPARENT
|
/* Check the stype1 part of the symbol. */
|
uint16_t RIO_receiveNwrite( RioStack_t *stack, uint16_t *destid, uint16_t *srcid, uint8_t *tid,
|
switch(stype1)
|
uint32_t *address, const uint16_t dataLength, uint8_t *data )
|
|
{
|
|
return receiveNwrite(stack, destid, srcid, tid, address, dataLength, data);
|
|
}
|
|
#else
|
|
uint16_t RIO_receiveNwrite( RioStack_t *stack, uint16_t *srcid, uint8_t *tid,
|
|
uint32_t *address, const uint16_t dataLength, uint8_t *data )
|
|
{
|
{
|
return receiveNwrite(stack, srcid, srcid, tid, address, dataLength, data);
|
case STYPE1_START_OF_PACKET:
|
}
|
/* Starting new frames are ignored in this state. */
|
#endif
|
break;
|
|
|
/*******************************************************************************************
|
case STYPE1_END_OF_PACKET:
|
* Logical I/O NREAD functions.
|
/* Ending new frames are ignored in this state. */
|
*******************************************************************************************/
|
break;
|
|
|
#ifdef RIO_TRANSPARENT
|
case STYPE1_STOMP:
|
void RIO_sendNread( RioStack_t *stack, const uint16_t destid, const uint16_t srcid, const uint8_t tid,
|
/* Restarting frames are ignored in this state. */
|
const uint32_t address, const uint16_t dataLength)
|
break;
|
{
|
|
sendNread(stack, destid, srcid, tid, address, dataLength);
|
|
}
|
|
#else
|
|
void RIO_sendNread( RioStack_t *stack, const uint16_t destid, const uint8_t tid,
|
|
const uint32_t address, const uint16_t dataLength)
|
|
{
|
|
sendNread(stack, destid, stack->baseDeviceId, tid, address, dataLength);
|
|
}
|
|
#endif
|
|
|
|
#ifdef RIO_TRANSPARENT
|
case STYPE1_RESTART_FROM_RETRY:
|
void RIO_receiveNread( RioStack_t *stack, uint16_t *destid, uint16_t *srcid, uint8_t *tid,
|
/* The link partner has confirmed our packet-retry-symbol. */
|
uint32_t *address, uint16_t *dataLength)
|
/* Go back to the normal state and reset the frame reception. */
|
{
|
stack->rxState = RX_STATE_LINK_INITIALIZED;
|
receiveNread( stack, destid, srcid, tid, address, dataLength);
|
stack->rxCounter = 0u;
|
}
|
break;
|
#else
|
|
void RIO_receiveNread( RioStack_t *stack, uint16_t *srcid, uint8_t *tid,
|
|
uint32_t *address, uint16_t *dataLength)
|
|
{
|
|
receiveNread( stack, srcid, srcid, tid, address, dataLength);
|
|
}
|
|
#endif
|
|
|
|
/*******************************************************************************************
|
case STYPE1_LINK_REQUEST:
|
* Logical I/O RESPONSE-DONE-PAYLOAD, RESPONSE-DONE, RESPONSE-RETRY and RESPONSE-ERROR
|
/* A link-request has been received. */
|
* functions.
|
handleLinkRequest(stack, CMD_GET(s.data));
|
*******************************************************************************************/
|
stack->rxState = RX_STATE_LINK_INITIALIZED;
|
|
break;
|
|
|
|
case STYPE1_NOP:
|
|
/* No operation symbol. */
|
|
/* Discard these. */
|
|
break;
|
|
|
#ifdef RIO_TRANSPARENT
|
case STYPE1_MULTICAST_EVENT:
|
void RIO_sendResponseDonePayload( RioStack_t *stack, const uint16_t destid, const uint16_t srcid, const uint8_t tid,
|
case STYPE1_RESERVED:
|
const uint32_t address, const uint16_t bufferSize, const uint8_t *buffer)
|
default:
|
{
|
/* Unsupported symbol received. */
|
sendResponseDonePayload(stack, destid, srcid, tid, address, bufferSize, buffer);
|
/* Discard them. */
|
}
|
break;
|
#else
|
|
void RIO_sendResponseDonePayload( RioStack_t *stack, const uint16_t destid, const uint8_t tid,
|
|
const uint32_t address, const uint16_t bufferSize, const uint8_t *buffer)
|
|
{
|
|
sendResponseDonePayload(stack, destid, stack->baseDeviceId, tid, address, bufferSize, buffer);
|
|
}
|
}
|
#endif
|
|
|
|
#ifdef RIO_TRANSPARENT
|
|
uint16_t RIO_receiveResponseDonePayload( RioStack_t *stack, uint16_t *destid, uint16_t *srcid, uint8_t *tid,
|
|
const uint32_t address, const uint16_t dataLength, uint8_t *data )
|
|
{
|
|
return receiveResponseDonePayload(stack, destid, srcid, tid, address, dataLength, data);
|
|
}
|
}
|
#else
|
else
|
uint16_t RIO_receiveResponseDonePayload( RioStack_t *stack, uint16_t *srcid, uint8_t *tid,
|
|
const uint32_t address, const uint16_t dataLength, uint8_t *data )
|
|
{
|
{
|
return receiveResponseDonePayload(stack, srcid, srcid, tid, address, dataLength, data);
|
/* The control symbol CRC is incorrect. */
|
|
/* Corrupted control symbol. Discard the symbol and enter the input-error-stopped state. */
|
|
stack->txState = TX_STATE_SEND_PACKET_NOT_ACCEPTED;
|
|
stack->rxState = RX_STATE_INPUT_ERROR_STOPPED;
|
|
stack->rxErrorCause = PACKET_NOT_ACCEPTED_CAUSE_CONTROL_CRC;
|
|
stack->statusInboundErrorControlCrc++;
|
}
|
}
|
#endif
|
break;
|
|
|
#ifdef RIO_TRANSPARENT
|
case RIOSTACK_SYMBOL_TYPE_ERROR:
|
void RIO_sendResponseDone( RioStack_t *stack, const uint16_t destid, const uint16_t srcid, const uint8_t tid)
|
/* Idle symbol error. Place the receiver in input-error-stopped state. */
|
{
|
stack->txState = TX_STATE_SEND_PACKET_NOT_ACCEPTED;
|
sendResponse(stack, destid, srcid, tid, 0x0u);
|
stack->rxState = RX_STATE_INPUT_ERROR_STOPPED;
|
}
|
stack->rxErrorCause = PACKET_NOT_ACCEPTED_CAUSE_ILLEGAL_CHARACTER;
|
#else
|
stack->statusInboundErrorIllegalCharacter++;
|
void RIO_sendResponseDone( RioStack_t *stack, const uint16_t destid, const uint8_t tid)
|
break;
|
{
|
|
sendResponse(stack, destid, stack->baseDeviceId, tid, 0x0u);
|
case RIOSTACK_SYMBOL_TYPE_DATA:
|
|
case RIOSTACK_SYMBOL_TYPE_IDLE:
|
|
default:
|
|
/* Data or idle symbol. */
|
|
/* Discard these in this state. */
|
|
break;
|
}
|
}
|
#endif
|
break;
|
|
|
|
case RX_STATE_INPUT_ERROR_STOPPED:
|
|
/******************************************************************************
|
|
* INPUT_ERROR_STOPPED
|
|
* This state is entered when an error situation has occurred. When in this
|
|
* state, all symbols should be discarded until a link-request-symbols has
|
|
* been received. See section 5.13.2.6 in part 6 of the standard.
|
|
* Note that it is only the input side of the port that are affected, not the
|
|
* output side. Packets may still be transmitted and acknowledges should be
|
|
* accepted.
|
|
******************************************************************************/
|
|
|
#ifdef RIO_TRANSPARENT
|
/* Check the type of symbol. */
|
void RIO_receiveResponseDone( RioStack_t *stack, uint16_t *destid, uint16_t *srcid, uint8_t *tid)
|
switch(s.type)
|
{
|
{
|
receiveResponse(stack, destid, srcid, tid);
|
case RIOSTACK_SYMBOL_TYPE_CONTROL:
|
}
|
/* This is a control symbol. */
|
#else
|
|
void RIO_receiveResponseDone( RioStack_t *stack, uint16_t *srcid, uint8_t *tid)
|
/* Check if the CRC is correct. */
|
|
if(Crc5(s.data, 0x1fu) == (s.data & (uint8_t)0x1ful))
|
{
|
{
|
receiveResponse(stack, srcid, srcid, tid);
|
/* The CRC is correct. */
|
}
|
|
#endif
|
|
|
|
|
/* Get the content of the control symbol. */
|
|
stype0 = STYPE0_GET(s.data);
|
|
parameter0 = PARAMETER0_GET(s.data);
|
|
parameter1 = PARAMETER1_GET(s.data);
|
|
stype1 = STYPE1_GET(s.data);
|
|
|
#ifdef RIO_TRANSPARENT
|
/* Check the stype0 part of the symbol. */
|
void RIO_sendResponseRetry( RioStack_t *stack, const uint16_t destid, const uint16_t srcid, const uint8_t tid )
|
switch(stype0)
|
{
|
|
sendResponse(stack, destid, srcid, tid, 0x3u);
|
|
}
|
|
#else
|
|
void RIO_sendResponseRetry( RioStack_t *stack, const uint16_t destid, const uint8_t tid )
|
|
{
|
{
|
sendResponse(stack, destid, stack->baseDeviceId, tid, 0x3u);
|
case STYPE0_STATUS:
|
}
|
/* A status containing the current ackId and the buffer status has been
|
#endif
|
received. */
|
|
handleStatus(stack, parameter0, parameter1);
|
|
break;
|
|
|
|
case STYPE0_PACKET_ACCEPTED:
|
|
/* A packet has been accepted by the link partner. */
|
|
handlePacketAccepted(stack, parameter0, parameter1);
|
|
break;
|
|
|
#ifdef RIO_TRANSPARENT
|
case STYPE0_PACKET_RETRY:
|
void RIO_receiveResponseRetry( RioStack_t *stack, uint16_t *destid, uint16_t *srcid, uint8_t *tid)
|
/* The link partner wants us to initiate a restart of the received ackId. */
|
{
|
handlePacketRetry(stack, parameter0, parameter1);
|
receiveResponse(stack, destid, srcid, tid);
|
break;
|
}
|
|
#else
|
|
void RIO_receiveResponseRetry( RioStack_t *stack, uint16_t *srcid, uint8_t *tid)
|
|
{
|
|
receiveResponse(stack, srcid, srcid, tid);
|
|
}
|
|
#endif
|
|
|
|
|
case STYPE0_PACKET_NOT_ACCEPTED:
|
|
/* The link partner indicates that a packet has been rejected. */
|
|
handlePacketNotAccepted(stack, parameter0, parameter1);
|
|
break;
|
|
|
#ifdef RIO_TRANSPARENT
|
case STYPE0_LINK_RESPONSE:
|
void RIO_sendResponseError( RioStack_t *stack, const uint16_t destid, const uint16_t srcid, const uint8_t tid)
|
/* The link partner has sent a response to a link-request. */
|
{
|
handleLinkResponse(stack, parameter0, parameter1);
|
sendResponse(stack, destid, srcid, tid, 0x7u);
|
break;
|
|
|
|
case STYPE0_VC_STATUS:
|
|
case STYPE0_RESERVED:
|
|
case STYPE0_IMPLEMENTATION_DEFINED:
|
|
default:
|
|
/* Unsupported symbol received. */
|
|
/* Discard them. */
|
|
break;
|
}
|
}
|
#else
|
|
void RIO_sendResponseError( RioStack_t *stack, const uint16_t destid, const uint8_t tid)
|
/* Check the stype1 part of the symbol. */
|
|
switch(stype1)
|
{
|
{
|
sendResponse(stack, destid, stack->baseDeviceId, tid, 0x7u);
|
case STYPE1_START_OF_PACKET:
|
}
|
/* Starting new frames are ignored in this state. */
|
#endif
|
break;
|
|
|
|
case STYPE1_END_OF_PACKET:
|
|
/* Ending new frames are ignored in this state. */
|
|
break;
|
|
|
#ifdef RIO_TRANSPARENT
|
case STYPE1_STOMP:
|
void RIO_receiveResponseError( RioStack_t *stack, uint16_t *destid, uint16_t *srcid, uint8_t *tid)
|
/* Restarting frames are ignored in this state. */
|
{
|
break;
|
receiveResponse(stack, destid, srcid, tid);
|
|
}
|
|
#else
|
|
void RIO_receiveResponseError( RioStack_t *stack, uint16_t *srcid, uint8_t *tid)
|
|
{
|
|
receiveResponse(stack, srcid, srcid, tid);
|
|
}
|
|
#endif
|
|
|
|
|
case STYPE1_RESTART_FROM_RETRY:
|
|
/* Restart-from-retry are ignored in this state. */
|
|
break;
|
|
|
|
case STYPE1_LINK_REQUEST:
|
|
/* This is the symbol we have been waiting for. */
|
|
/* Force the transmitter to send a link-response and go back into the normal
|
|
operational state. */
|
|
/* The transmitter will always send a status as the first symbol after this. */
|
|
handleLinkRequest(stack, CMD_GET(s.data));
|
|
stack->rxState = RX_STATE_LINK_INITIALIZED;
|
|
break;
|
|
|
/*******************************************************************************************
|
case STYPE1_NOP:
|
* Logical message passing DOORBELL and MESSAGE functions.
|
/* No operation symbol. */
|
*******************************************************************************************/
|
/* Discard these. */
|
|
break;
|
|
|
#ifdef RIO_TRANSPARENT
|
case STYPE1_MULTICAST_EVENT:
|
void RIO_sendDoorbell( RioStack_t *stack, const uint16_t destid, const uint16_t srcid, const uint8_t tid,
|
case STYPE1_RESERVED:
|
const uint16_t info )
|
default:
|
{
|
/* Unsupported symbol received. */
|
sendDoorbell(stack, destid, srcid, tid, info);
|
/* Discard them. */
|
}
|
break;
|
#else
|
|
void RIO_sendDoorbell( RioStack_t *stack, const uint16_t destid, const uint8_t tid,
|
|
const uint16_t info )
|
|
{
|
|
sendDoorbell(stack, destid, stack->baseDeviceId, tid, info);
|
|
}
|
}
|
#endif
|
|
|
|
#ifdef RIO_TRANSPARENT
|
|
void RIO_receiveDoorbell( RioStack_t *stack, uint16_t *destid, uint16_t *srcid, uint8_t *tid,
|
|
uint16_t *info)
|
|
{
|
|
receiveDoorbell(stack, destid, srcid, tid, info);
|
|
}
|
}
|
#else
|
else
|
void RIO_receiveDoorbell( RioStack_t *stack, uint16_t *srcid, uint8_t *tid,
|
|
uint16_t *info)
|
|
{
|
{
|
receiveDoorbell(stack, srcid, srcid, tid, info);
|
/* The CRC is incorrect. */
|
|
/* Discard these in this state. */
|
}
|
}
|
#endif
|
break;
|
|
|
#ifdef RIO_TRANSPARENT
|
case RIOSTACK_SYMBOL_TYPE_DATA:
|
void RIO_sendMessage( RioStack_t *stack, const uint16_t destid, const uint16_t srcid, const uint8_t mailbox,
|
case RIOSTACK_SYMBOL_TYPE_IDLE:
|
const uint16_t bufferSize, const uint8_t* bufferData)
|
case RIOSTACK_SYMBOL_TYPE_ERROR:
|
{
|
default:
|
sendMessage(stack, destid, srcid, mailbox, bufferSize, bufferData);
|
/* Data, idle or error symbol. */
|
}
|
/* Discard these in this state. */
|
#else
|
break;
|
void RIO_sendMessage( RioStack_t *stack, const uint16_t destid, const uint8_t mailbox,
|
|
const uint16_t bufferSize, const uint8_t* bufferData)
|
|
{
|
|
sendMessage(stack, destid, stack->baseDeviceId, mailbox, bufferSize, bufferData);
|
|
}
|
}
|
#endif
|
break;
|
|
|
#ifdef RIO_TRANSPARENT
|
case RX_STATE_UNINITIALIZED:
|
uint16_t RIO_receiveMessage( RioStack_t *stack, uint16_t *destid, uint16_t *srcid, uint8_t *mailbox,
|
default:
|
const uint16_t dataLength, uint8_t *data )
|
/******************************************************************************
|
{
|
* Wait for the port to be initialized.
|
return receiveMessage(stack, destid, srcid, mailbox, dataLength, data);
|
******************************************************************************/
|
|
|
|
/* Discard all incoming symbols. */
|
|
break;
|
}
|
}
|
#else
|
|
uint16_t RIO_receiveMessage( RioStack_t *stack, uint16_t *srcid, uint8_t *mailbox,
|
|
const uint16_t dataLength, uint8_t *data )
|
|
{
|
|
return receiveMessage(stack, srcid, srcid, mailbox, dataLength, data);
|
|
}
|
}
|
#endif
|
|
|
|
/*******************************************************************************************
|
|
* Logical message passing MESSAGE-RESPONSE functions.
|
|
*******************************************************************************************/
|
|
|
|
#ifdef RIO_TRANSPARENT
|
|
void RIO_sendMessageResponseDone( RioStack_t *stack, const uint16_t destid, const uint16_t srcid, const uint8_t mailbox)
|
RioSymbol_t RIOSTACK_portGetSymbol(RioStack_t *stack )
|
{
|
|
sendMessageResponse(stack, destid, srcid, mailbox, 0x0u);
|
|
}
|
|
#else
|
|
void RIO_sendMessageResponseDone( RioStack_t *stack, const uint16_t destid, const uint8_t mailbox)
|
|
{
|
{
|
sendMessageResponse(stack, destid, stack->baseDeviceId, mailbox, 0x0u);
|
RioSymbol_t s;
|
}
|
|
#endif
|
|
|
|
|
|
#ifdef RIO_TRANSPARENT
|
switch(stack->txState)
|
void RIO_receiveMessageResponseDone( RioStack_t *stack, uint16_t *destid, uint16_t *srcid, uint8_t *mailbox)
|
|
{
|
|
receiveMessageResponse(stack, destid, srcid, mailbox);
|
|
}
|
|
#else
|
|
void RIO_receiveMessageResponseDone( RioStack_t *stack, uint16_t *srcid, uint8_t *mailbox)
|
|
{
|
{
|
receiveMessageResponse(stack, srcid, srcid, mailbox);
|
case TX_STATE_PORT_INITIALIZED:
|
}
|
/******************************************************************************
|
#endif
|
* PORT_INITIALIZED
|
|
* This state is entered to initialize the link. Send status-control-symbols
|
|
* once in a while until the receiver has received enough error-free status-
|
|
* control-symbols and we have transmitted enough status-control-symbols. Once
|
|
* an error-free status-control-symbol has been received, the statuses are
|
|
* transmitted more frequently to decrease the time for the link to be
|
|
* initialized.
|
|
******************************************************************************/
|
|
|
#ifdef RIO_TRANSPARENT
|
/* Check if an idle symbol or a status control symbol should be sent. */
|
void RIO_sendMessageResponseRetry( RioStack_t *stack, const uint16_t destid, const uint16_t srcid, const uint8_t mailbox)
|
if(((stack->rxStatusReceived == 0) && (stack->txCounter == 255u)) ||
|
{
|
((stack->rxStatusReceived == 1) && (stack->txCounter >= 15u)))
|
sendMessageResponse(stack, destid, srcid, mailbox, 0x3u);
|
|
}
|
|
#else
|
|
void RIO_sendMessageResponseRetry( RioStack_t *stack, const uint16_t destid, const uint8_t mailbox)
|
|
{
|
{
|
sendMessageResponse(stack, destid, stack->baseDeviceId, mailbox, 0x3u);
|
/* A control symbol should be sent. */
|
}
|
|
#endif
|
|
|
|
|
/* Create a new status symbol and reset the transmission counter. */
|
|
stack->txCounter = 0u;
|
|
s = CreateControlSymbol(STYPE0_STATUS, stack->rxAckId, QueueAvailable(stack->rxQueue),
|
|
STYPE1_NOP, 0u);
|
|
|
#ifdef RIO_TRANSPARENT
|
/* Check if the receiver has received any error-free status and that we
|
void RIO_receiveMessageResponseRetry( RioStack_t *stack, uint16_t *destid, uint16_t *srcid, uint8_t *mailbox)
|
have sent at least 15 status control symbols. */
|
|
if((stack->rxStatusReceived == 1) && (stack->txStatusCounter < 15u))
|
{
|
{
|
receiveMessageResponse(stack, destid, srcid, mailbox);
|
/* Has not sent enough status control symbols. */
|
|
stack->txStatusCounter++;
|
}
|
}
|
#else
|
else
|
void RIO_receiveMessageResponseRetry( RioStack_t *stack, uint16_t *srcid, uint8_t *mailbox)
|
|
{
|
{
|
receiveMessageResponse(stack, srcid, srcid, mailbox);
|
/* Has sent enough status control symbols. */
|
|
/* Dont do anything. */
|
}
|
}
|
#endif
|
|
|
|
|
|
#ifdef RIO_TRANSPARENT
|
|
void RIO_sendMessageResponseError( RioStack_t *stack, const uint16_t destid, const uint16_t srcid, const uint8_t mailbox)
|
|
{
|
|
sendMessageResponse(stack, destid, srcid, mailbox, 0x7u);
|
|
}
|
}
|
#else
|
else
|
void RIO_sendMessageResponseError( RioStack_t *stack, const uint16_t destid, const uint8_t mailbox)
|
|
{
|
{
|
sendMessageResponse(stack, destid, stack->baseDeviceId, mailbox, 0x7u);
|
/* Idle symbol should be sent. */
|
|
s.type = RIOSTACK_SYMBOL_TYPE_IDLE;
|
|
stack->txCounter++;
|
}
|
}
|
#endif
|
|
|
|
|
|
#ifdef RIO_TRANSPARENT
|
/* Check if we are ready to set the transmitter in a link initialized state. */
|
void RIO_receiveMessageResponseError( RioStack_t *stack, uint16_t *destid, uint16_t *srcid, uint8_t *mailbox)
|
if ((stack->rxState == RX_STATE_LINK_INITIALIZED) && (stack->txStatusCounter == 15u))
|
{
|
{
|
receiveMessageResponse(stack, destid, srcid, mailbox);
|
/* Ready to go to link initialized. */
|
|
stack->txState = TX_STATE_LINK_INITIALIZED;
|
|
stack->txFrameState = TX_FRAME_START;
|
|
stack->txStatusCounter = 0u;
|
}
|
}
|
#else
|
else
|
void RIO_receiveMessageResponseError( RioStack_t *stack, uint16_t *srcid, uint8_t *mailbox)
|
|
{
|
{
|
receiveMessageResponse(stack, srcid, srcid, mailbox);
|
/* Not ready to go to link initialized. */
|
|
/* Dont do anything. */
|
}
|
}
|
#endif
|
|
|
|
|
break;
|
|
|
|
case TX_STATE_LINK_INITIALIZED:
|
|
/******************************************************************************
|
|
* LINK_INITIALIZED
|
|
* The normal state. Accept packets and forward them. Send acknowledges when
|
|
* the receiver has received complete packets.
|
|
******************************************************************************/
|
|
|
void RIO_portSetStatus( RioStack_t *stack, const uint8_t initialized)
|
/* Check if the receiver wants to acknowledge a packet. */
|
{
|
if(stack->rxAckId == stack->rxAckIdAcked)
|
/* REMARK: Clean the queues here as well??? */
|
|
if (initialized)
|
|
{
|
{
|
stack->rxState = RX_STATE_PORT_INITIALIZED;
|
/* The receiver does not want to acknowledge a packet. */
|
stack->rxCounter = 0u;
|
|
stack->rxCrc = 0xffffu;
|
|
stack->rxStatusReceived = 0;
|
|
stack->rxAckId = 0u;
|
|
stack->rxAckIdAcked = 0u;
|
|
stack->rxErrorCause = PACKET_NOT_ACCEPTED_CAUSE_RESERVED;
|
|
|
|
stack->txState = TX_STATE_PORT_INITIALIZED;
|
/* Check if there are any outstanding packets and if it has timed out. */
|
stack->txCounter = 0u;
|
if((stack->txAckId == stack->txAckIdWindow) ||
|
stack->txStatusCounter = 0u;
|
((stack->portTime - stack->txFrameTimeout[stack->txAckId]) < stack->portTimeout))
|
stack->txFrameState = TX_FRAME_START;
|
|
stack->txAckId = 0u;
|
|
stack->txAckIdWindow = 0u;
|
|
}
|
|
else
|
|
{
|
{
|
stack->rxState = RX_STATE_UNINITIALIZED;
|
/* There are no outstanding packets or there has been no timeout. */
|
stack->txState = TX_STATE_UNINITIALIZED;
|
|
}
|
|
}
|
|
|
|
|
/* Check if a packet is ongoing. */
|
|
if(stack->txFrameState == TX_FRAME_BODY)
|
|
{
|
|
/* A packet transmission is ongoing. */
|
|
|
void RIO_portSetTime( RioStack_t *stack, const uint32_t time)
|
/* Check if the packet has been completly sent. */
|
|
if(stack->txCounter != QueueGetSize(stack->txQueue))
|
{
|
{
|
stack->portTime = time;
|
/* The packet has not been completly sent. */
|
}
|
|
|
|
|
/* Create a new data symbol to transmit. */
|
|
s.type = RIOSTACK_SYMBOL_TYPE_DATA;
|
|
s.data = QueueGetFrontContent(stack->txQueue, (uint32_t)stack->txCounter);
|
|
|
void RIO_portSetTimeout( RioStack_t *stack, const uint32_t time)
|
/* Check if this is the first symbol in a packet. */
|
|
if (stack->txCounter == 0u)
|
{
|
{
|
stack->portTimeout = time;
|
/* Place the correct ackId in the right place. */
|
|
s.data |= (uint32_t)stack->txAckIdWindow << 27;
|
|
}
|
|
else
|
|
{
|
|
/* Dont do anything. */
|
}
|
}
|
|
|
|
/* Update the transmission counter. */
|
|
stack->txCounter++;
|
|
|
void RIO_portAddSymbol( RioStack_t *stack, const RioSymbol s)
|
/* A status control symbol was not sent. Update the status counter. */
|
|
stack->txStatusCounter++;
|
|
}
|
|
else
|
{
|
{
|
uint8_t stype0;
|
/* The packet has been sent. */
|
uint8_t parameter0;
|
|
uint8_t parameter1;
|
|
uint8_t stype1;
|
|
|
|
|
/* Save the timeout time and update to the next ackId. */
|
|
stack->txFrameTimeout[stack->txAckIdWindow] = stack->portTime;
|
|
stack->txAckIdWindow = ACKID_INC(stack->txAckIdWindow);
|
|
stack->txQueue = QueueWindowNext(stack->txQueue);
|
|
|
switch(stack->rxState)
|
/* Check if there are more packets pending to be sent. */
|
|
/* Also check that there are buffer available at the receiver and that not too many
|
|
packets are outstanding. */
|
|
if(!QueueWindowEmpty(stack->txQueue) && (stack->txBufferStatus > 0) &&
|
|
(((stack->txAckIdWindow - stack->txAckId) & 0x1f) != 31))
|
{
|
{
|
case RX_STATE_PORT_INITIALIZED:
|
/* More pending packets. */
|
/******************************************************************************
|
/* Create a control symbol to signal that the new packet has started. */
|
* PORT_INITIALIZED
|
s = CreateControlSymbol(STYPE0_STATUS, stack->rxAckId, QueueAvailable(stack->rxQueue),
|
* This state is entered to initialize the link. Only status-control-symbols
|
STYPE1_START_OF_PACKET, 0u);
|
* are accepted in this state. When 7 error-free, i.e. with CRC5 correct, status
|
|
* control symbols has been received, change state to linkInitialized.
|
|
******************************************************************************/
|
|
|
|
/* Check the type of symbol. */
|
/* Restart transmission counter. */
|
if(s.type == RIO_SYMBOL_TYPE_CONTROL)
|
stack->txCounter = 0;
|
|
}
|
|
else
|
{
|
{
|
/* This is a control symbol. */
|
/* No more pending packets. */
|
|
/* Create a control symbol to signal that the packet has ended. */
|
|
s = CreateControlSymbol(STYPE0_STATUS, stack->rxAckId, QueueAvailable(stack->rxQueue),
|
|
STYPE1_END_OF_PACKET, 0u);
|
|
|
/* Check that the control symbol contains no errors. */
|
/* Go back to wait for a new frame. */
|
if(Crc5(s.data, 0x1fu) == (s.data & 0x1ful))
|
stack->txFrameState = TX_FRAME_START;
|
{
|
}
|
/* Error-free control symbol. */
|
|
|
|
/* Check if the symbol is a status symbol. */
|
/* A status control symbol has been sent. Reset the status counter. */
|
stype0 = STYPE0_GET(s.data);
|
stack->txStatusCounter = 0u;
|
if(stype0 == STYPE0_STATUS)
|
}
|
|
}
|
|
else
|
{
|
{
|
/* Status symbol received. */
|
/* No packet is being sent. */
|
|
|
/* Indicate an error-free status has been received. */
|
/* Check if there are any pending packets to start sending. */
|
stack->rxStatusReceived = 1;
|
/* Also check that there are buffer available at the receiver and that not too many
|
|
packets are outstanding. */
|
|
if(!QueueWindowEmpty(stack->txQueue) && (stack->txBufferStatus > 0) &&
|
|
(((stack->txAckIdWindow - stack->txAckId) & 0x1f) != 31))
|
|
{
|
|
/* There is a pending packet to send. */
|
|
/* Send a start-of-packet control symbol to start to send the packet. */
|
|
s = CreateControlSymbol(STYPE0_STATUS, stack->rxAckId, QueueAvailable(stack->rxQueue),
|
|
STYPE1_START_OF_PACKET, 0u);
|
|
stack->txFrameState = TX_FRAME_BODY;
|
|
stack->txCounter = 0u;
|
|
|
/* Check if enough status control symbols has been received. */
|
/* A status control symbol has been sent. Reset the status counter. */
|
if(stack->rxCounter == 7u)
|
stack->txStatusCounter = 0u;
|
|
}
|
|
else
|
{
|
{
|
/* Enough correct status control symbols has been received without
|
/* There are no pending packets to send. */
|
errors in between. */
|
|
|
|
/* Setup the transmitter with the content of the symbol. */
|
/* Check if a status control symbol must be transmitted. */
|
stack->txAckId = PARAMETER0_GET(s.data);
|
if(stack->txStatusCounter < 255u)
|
stack->txAckIdWindow = stack->txAckId;
|
{
|
stack->txBufferStatus = PARAMETER1_GET(s.data);
|
/* Not required to send a status control symbol. */
|
|
|
/* Set the transmitter in its normal operational mode. */
|
/* Send an idle-symbol. */
|
stack->rxState = RX_STATE_LINK_INITIALIZED;
|
s.type = RIOSTACK_SYMBOL_TYPE_IDLE;
|
stack->rxCounter = 0u;
|
stack->txStatusCounter++;
|
DEBUG_STATE("rx:normal");
|
|
}
|
}
|
else
|
else
|
{
|
{
|
/* Count the number of consequitive error-free status control symbols
|
/* Must send a status control symbol. */
|
that has been received. */
|
|
stack->rxCounter++;
|
/* Create a status control symbol. */
|
|
s = CreateControlSymbol(STYPE0_STATUS, stack->rxAckId, QueueAvailable(stack->rxQueue),
|
|
STYPE1_NOP, 0u);
|
|
|
|
/* A status control symbol has been sent. Reset the status counter. */
|
|
stack->txStatusCounter = 0u;
|
}
|
}
|
}
|
}
|
else
|
|
{
|
|
/* The received symbol is not a status symbol. */
|
|
/* Discard it. */
|
|
}
|
}
|
}
|
}
|
else
|
else
|
{
|
{
|
/* CRC error in control symbol. */
|
/* There has been a timeout. */
|
/* Restart counting error-free status-control-symbols. */
|
/* A packet has been sent but no packet-accepted has been received. */
|
stack->rxCounter = 0u;
|
/* Send link-request-symbol (input-status). */
|
|
s = CreateControlSymbol(STYPE0_STATUS, stack->rxAckId, QueueAvailable(stack->rxQueue),
|
|
STYPE1_LINK_REQUEST, LINK_REQUEST_INPUT_STATUS);
|
|
|
|
/* Save the time when this was transmitted. */
|
|
stack->txFrameTimeout[stack->txAckId] = stack->portTime;
|
|
|
|
/* Remember that this symbol has been transmitted. */
|
|
stack->txCounter = 1;
|
|
|
|
/* Go into the output error stopped state. */
|
|
stack->txState = TX_STATE_OUTPUT_ERROR_STOPPED;
|
|
stack->statusOutboundErrorTimeout++;
|
}
|
}
|
}
|
}
|
else
|
else
|
{
|
{
|
/* Not a control symbol. */
|
/* The receiver wants us to send an acknowledgement. */
|
/* Discard the symbol. */
|
s = CreateControlSymbol(STYPE0_PACKET_ACCEPTED, stack->rxAckIdAcked, QueueAvailable(stack->rxQueue),
|
}
|
STYPE1_NOP, 0u);
|
|
stack->rxAckIdAcked = ACKID_INC(stack->rxAckIdAcked);
|
|
|
|
/* A status control symbol was not sent. Update the status counter. */
|
|
stack->txStatusCounter++;
|
|
}
|
break;
|
break;
|
|
|
case RX_STATE_LINK_INITIALIZED:
|
case TX_STATE_SEND_PACKET_RETRY:
|
/******************************************************************************
|
/******************************************************************************
|
* LINK_INITIALIZED
|
* SEND_PACKET_RETRY
|
* The normal state. Accept packets and forward them.
|
* This state is set by the receiver to force a packet-retry-symbol to be
|
|
* transmitted.
|
******************************************************************************/
|
******************************************************************************/
|
|
|
/* Check the type of symbol. */
|
/* Check if the receiver wants to acknowledge a packet. */
|
switch(s.type)
|
/* This must be done first or we will get an error for a missmatching
|
|
ackId in the link-partner. */
|
|
if(stack->rxAckId == stack->rxAckIdAcked)
|
{
|
{
|
case RIO_SYMBOL_TYPE_CONTROL:
|
/* No pending acknowledge. */
|
/**************************************************************************
|
|
* This is a control symbol.
|
|
**************************************************************************/
|
|
|
|
/* Check if the CRC is correct. */
|
/* Send a packet-retry symbol to tell the link partner to retry the last frame. */
|
if(Crc5(s.data, 0x1fu) == (s.data & (uint8_t)0x1ful))
|
s = CreateControlSymbol(STYPE0_PACKET_RETRY, stack->rxAckId, QueueAvailable(stack->rxQueue),
|
{
|
STYPE1_NOP, 0u);
|
/* The CRC is correct. */
|
|
|
|
/* Get the content of the control symbol. */
|
/* Proceed with normal transmission. */
|
stype0 = STYPE0_GET(s.data);
|
stack->txState = TX_STATE_LINK_INITIALIZED;
|
parameter0 = PARAMETER0_GET(s.data);
|
|
parameter1 = PARAMETER1_GET(s.data);
|
|
stype1 = STYPE1_GET(s.data);
|
|
|
|
/**********************************************************************************
|
/* A status control symbol was not sent. Update the status counter. */
|
* Check the stype0 part of the symbol.
|
stack->txStatusCounter++;
|
* Note that errors in this should trigger OUTPUT_ERROR_STOPPED.
|
}
|
**********************************************************************************/
|
else
|
switch(stype0)
|
|
{
|
{
|
case STYPE0_STATUS:
|
|
/* A status containing the current ackId and the buffer status has been
|
|
received. */
|
|
handleStatus(stack, parameter0, parameter1);
|
|
break;
|
|
|
|
case STYPE0_PACKET_ACCEPTED:
|
|
/* A packet has been accepted by the link partner. */
|
|
handlePacketAccepted(stack, parameter0, parameter1);
|
|
break;
|
|
|
|
case STYPE0_PACKET_RETRY:
|
|
/* The link partner wants us to initiate a restart of the received ackId. */
|
|
handlePacketRetry(stack, parameter0, parameter1);
|
|
break;
|
|
|
|
case STYPE0_PACKET_NOT_ACCEPTED:
|
/* The receiver wants us to send an acknowledgement. */
|
/* The link partner indicates that a packet has been rejected. */
|
s = CreateControlSymbol(STYPE0_PACKET_ACCEPTED, stack->rxAckIdAcked, QueueAvailable(stack->rxQueue),
|
handlePacketNotAccepted(stack, parameter0, parameter1);
|
STYPE1_NOP, 0u);
|
break;
|
stack->rxAckIdAcked = ACKID_INC(stack->rxAckIdAcked);
|
|
|
case STYPE0_LINK_RESPONSE:
|
|
/* The link partner has sent a response to a link-request. */
|
|
handleLinkResponse(stack, parameter0, parameter1);
|
|
break;
|
|
|
|
case STYPE0_VC_STATUS:
|
/* A status control symbol was not sent. Update the status counter. */
|
case STYPE0_RESERVED:
|
stack->txStatusCounter++;
|
case STYPE0_IMPLEMENTATION_DEFINED:
|
|
default:
|
|
/* Unsupported symbol received. */
|
|
/* Discard them. */
|
|
break;
|
|
}
|
}
|
|
|
/**********************************************************************************
|
|
* Check the stype1 part of the symbol.
|
|
* Note that errors in this should trigger INPUT_ERROR_STOPPED.
|
|
**********************************************************************************/
|
|
switch(stype1)
|
|
{
|
|
case STYPE1_START_OF_PACKET:
|
|
/* Start of a new packet. */
|
|
handleStartOfPacket(stack);
|
|
break;
|
break;
|
|
|
case STYPE1_END_OF_PACKET:
|
case TX_STATE_SEND_PACKET_NOT_ACCEPTED:
|
/* Ending a packet. */
|
/******************************************************************************
|
handleEndOfPacket(stack);
|
* SEND_PACKET_NOT_ACCEPTED
|
break;
|
* This state is set by the receiver to force a packet-not-accepted-symbol to be
|
|
* transmitted.
|
|
******************************************************************************/
|
|
|
case STYPE1_STOMP:
|
/* Send a packet-not-accepted symbol to indicate an error on the link. */
|
/* Cancel the currently received frame. */
|
s = CreateControlSymbol(STYPE0_PACKET_NOT_ACCEPTED, 0, stack->rxErrorCause,
|
stack->rxCounter = 0;
|
STYPE1_NOP, 0u);
|
break;
|
|
|
|
case STYPE1_RESTART_FROM_RETRY:
|
/* Proceed with normal transmission. */
|
/* Cancel the currently received frame when in this state. */
|
stack->txState = TX_STATE_LINK_INITIALIZED;
|
stack->rxCounter = 0;
|
|
break;
|
|
|
|
case STYPE1_LINK_REQUEST:
|
/* A status control symbol was not sent. Update the status counter. */
|
/* A link-request has been received. */
|
stack->txStatusCounter++;
|
handleLinkRequest(stack, CMD_GET(s.data));
|
|
break;
|
break;
|
|
|
case STYPE1_NOP:
|
case TX_STATE_SEND_LINK_RESPONSE:
|
/* No operation symbol. */
|
/******************************************************************************
|
/* Discard these. */
|
* SEND_LINK_RESPONSE
|
break;
|
* This state is set by the receiver to force a link-response-symbol to be
|
|
* transmitted.
|
|
******************************************************************************/
|
|
|
case STYPE1_MULTICAST_EVENT:
|
/* Check the state of the receiver. */
|
case STYPE1_RESERVED:
|
/* REMARK: If a link-request gives this response and a link-request also makes the receiver
|
default:
|
enter the normal operational state, none of these states except the normal state will ever
|
/* Unsupported symbol received. */
|
be used... */
|
/* Discard them. */
|
if((stack->rxState == RX_STATE_LINK_INITIALIZED) || (stack->rxState == RX_STATE_PORT_INITIALIZED))
|
break;
|
|
}
|
|
}
|
|
else
|
|
{
|
{
|
/* The control symbol CRC is incorrect. */
|
/* Normal state. */
|
/* Corrupted control symbol. Discard the symbol and enter the input-error-stopped state. */
|
s = CreateControlSymbol(STYPE0_LINK_RESPONSE, stack->rxAckId, LINK_RESPONSE_PORT_STATUS_OK,
|
stack->txState = TX_STATE_SEND_PACKET_NOT_ACCEPTED;
|
STYPE1_NOP, 0u);
|
stack->rxState = RX_STATE_INPUT_ERROR_STOPPED;
|
|
stack->rxErrorCause = PACKET_NOT_ACCEPTED_CAUSE_CONTROL_CRC;
|
|
stack->statusInboundErrorControlCrc++;
|
|
DEBUG_STATE("rx:error-stopped");
|
|
}
|
}
|
break;
|
else if(stack->rxState == RX_STATE_INPUT_RETRY_STOPPED)
|
|
|
case RIO_SYMBOL_TYPE_DATA:
|
|
/**************************************************************************
|
|
* This is a data symbol.
|
|
**************************************************************************/
|
|
|
|
/* Check if a packet has been started and that it is not too long. */
|
|
if ((stack->rxCounter >= 1u) && (stack->rxCounter <= RIO_PACKET_SIZE))
|
|
{
|
|
/* A packet has been started. */
|
|
|
|
/* Check if the ackId is correct on the first part of the packet. */
|
|
if ((stack->rxCounter > 1u) ||
|
|
((stack->rxCounter == 1u) && (((uint8_t)(s.data >> 27)) == stack->rxAckId)))
|
|
{
|
{
|
/* The ackId is the expected one. */
|
/* Input-retry-stopped state. */
|
|
s = CreateControlSymbol(STYPE0_LINK_RESPONSE, stack->rxAckId, LINK_RESPONSE_PORT_STATUS_RETRY_STOPPED,
|
/* Check if this is the first symbol of a packet. */
|
STYPE1_NOP, 0u);
|
if (stack->rxCounter == 1u)
|
}
|
|
else if(stack->rxState == RX_STATE_INPUT_ERROR_STOPPED)
|
{
|
{
|
/* This is the first symbol of the packet. */
|
/* Input-error-stopped state. */
|
/* Start to calculate the CRC of the packet. */
|
s = CreateControlSymbol(STYPE0_LINK_RESPONSE, stack->rxAckId, LINK_RESPONSE_PORT_STATUS_ERROR_STOPPED,
|
/* Note that the ackId should not be included in the CRC calculation. */
|
STYPE1_NOP, 0u);
|
stack->rxCrc = Crc32(s.data & (uint32_t)0x03fffffful, 0xffffu);
|
|
}
|
}
|
else
|
else
|
{
|
{
|
/* This is not the first symbol. */
|
/* Not in the defined states. */
|
/* Continue to calculate the CRC of the packet. */
|
s = CreateControlSymbol(STYPE0_LINK_RESPONSE, stack->rxAckId, LINK_RESPONSE_PORT_STATUS_ERROR,
|
stack->rxCrc = Crc32(s.data, stack->rxCrc);
|
STYPE1_NOP, 0u);
|
}
|
}
|
|
|
/* Save the new data in the packet queue and update the reception counter. */
|
/* Proceed with normal transmission. */
|
QueueSetContent(stack->rxQueue, (uint32_t)stack->rxCounter - (uint32_t)1ul, s.data);
|
stack->txState = TX_STATE_LINK_INITIALIZED;
|
stack->rxCounter++;
|
|
}
|
|
else
|
|
{
|
|
DEBUG_FRAMING_RX("error=%u %u", stack->rxAckId, s.data>>27);
|
|
|
|
/* The ackId is not correct. */
|
/* Force a status to be transmitted the next time to comply to the input-error-stopped
|
/* Packet error. Enter input-error-stopped state. */
|
state rules. */
|
stack->txState = TX_STATE_SEND_PACKET_NOT_ACCEPTED;
|
stack->txStatusCounter = 255;
|
stack->rxState = RX_STATE_INPUT_ERROR_STOPPED;
|
|
stack->rxErrorCause = PACKET_NOT_ACCEPTED_CAUSE_UNEXPECTED_ACKID;
|
|
stack->statusInboundErrorPacketAckId++;
|
|
DEBUG_STATE("rx:error-stopped");
|
|
}
|
|
}
|
|
else
|
|
{
|
|
/* No packet has been started or the packet is too long. */
|
|
/* Packet error. Enter input-error-stopped state. */
|
|
stack->txState = TX_STATE_SEND_PACKET_NOT_ACCEPTED;
|
|
stack->rxState = RX_STATE_INPUT_ERROR_STOPPED;
|
|
stack->rxErrorCause = PACKET_NOT_ACCEPTED_CAUSE_GENERAL;
|
|
stack->statusInboundErrorGeneral++;
|
|
DEBUG_STATE("rx:error-stopped");
|
|
}
|
|
break;
|
break;
|
|
|
case RIO_SYMBOL_TYPE_ERROR:
|
case TX_STATE_OUTPUT_RETRY_STOPPED:
|
/**************************************************************************
|
/******************************************************************************
|
* The decoder has received a erronous symbol.
|
* OUTPUT_RETRY_STOPPED
|
**************************************************************************/
|
* This state is entered when the link-partner has transmitted a
|
|
* packet-retry-symbol. The packet-retry-symbol is acknowledged by sending a
|
|
* restart-from-retry-symbol.
|
|
* This state follows 5.9.1.5 in part 6.
|
|
******************************************************************************/
|
|
|
/* Idle symbol error. Place the receiver in input-error-stopped state. */
|
/* Send a restart-from-retry symbol to acknowledge. */
|
stack->txState = TX_STATE_SEND_PACKET_NOT_ACCEPTED;
|
s = CreateControlSymbol(STYPE0_STATUS, stack->rxAckId, QueueAvailable(stack->rxQueue),
|
stack->rxState = RX_STATE_INPUT_ERROR_STOPPED;
|
STYPE1_RESTART_FROM_RETRY, 0u);
|
stack->rxErrorCause = PACKET_NOT_ACCEPTED_CAUSE_ILLEGAL_CHARACTER;
|
|
stack->statusInboundErrorIllegalCharacter++;
|
|
DEBUG_STATE("rx:error-stopped");
|
|
break;
|
|
|
|
case RIO_SYMBOL_TYPE_IDLE:
|
/* Restart the current frame and proceed with normal operation. */
|
default:
|
stack->txFrameState = TX_FRAME_START;
|
/**************************************************************************
|
stack->txState = TX_STATE_LINK_INITIALIZED;
|
* Idle symbol or unsupported symbol.
|
stack->txCounter = 0;
|
**************************************************************************/
|
|
|
|
/* Discard these for now. */
|
/* Discard all packets that has not received a matching packet-accepted. */
|
break;
|
stack->txAckIdWindow = stack->txAckId;
|
}
|
stack->txQueue = QueueWindowReset(stack->txQueue);
|
|
|
|
/* A status control symbol was sent. Reset the status counter. */
|
|
stack->txStatusCounter = 0;
|
break;
|
break;
|
|
|
case RX_STATE_INPUT_RETRY_STOPPED:
|
case TX_STATE_OUTPUT_ERROR_STOPPED:
|
/******************************************************************************
|
/******************************************************************************
|
* INPUT_RETRY_STOPPED
|
* OUTPUT_ERROR_STOPPED
|
* This state is entered when no more buffers was available and a packet was
|
* This state is entered when the link partner has encountered any problem
|
* received. When in this state, all packets should be discarded until a
|
* which is indicated by sending a packet-not-accepted symbol or if a packet
|
* RESTART-FROM-RETRY symbol is received. See section 5.9.1.4 of the standard.
|
* timeout has expired. The error condition is acknowledged by sending a
|
* Note that it is only the input side of the port that are affected, not the
|
* link-request-symbol and then wait for a link-response reply.
|
* output side. Packets may still be transmitted and acknowledges should be
|
* This state follows 5.13.2.7 in part 6.
|
* accepted.
|
|
******************************************************************************/
|
******************************************************************************/
|
|
|
/* Check the type of symbol. */
|
/* Check if a link-request-symbol has been transmitted. */
|
switch(s.type)
|
if(stack->txCounter == 0)
|
{
|
{
|
case RIO_SYMBOL_TYPE_CONTROL:
|
/* A link-request-symbol has not been transmitted. */
|
/* This is a control symbol. */
|
|
|
|
/* Check if the CRC is correct. */
|
/* Send link-request-symbol (input-status). */
|
if(Crc5(s.data, 0x1fu) == (s.data & (uint8_t)0x1ful))
|
s = CreateControlSymbol(STYPE0_STATUS, stack->rxAckId, QueueAvailable(stack->rxQueue),
|
{
|
STYPE1_LINK_REQUEST, LINK_REQUEST_INPUT_STATUS);
|
/* The CRC is correct. */
|
|
|
|
/* Get the content of the control symbol. */
|
|
stype0 = STYPE0_GET(s.data);
|
|
parameter0 = PARAMETER0_GET(s.data);
|
|
parameter1 = PARAMETER1_GET(s.data);
|
|
stype1 = STYPE1_GET(s.data);
|
|
|
|
/* Check the stype0 part of the symbol. */
|
|
switch(stype0)
|
|
{
|
|
case STYPE0_STATUS:
|
|
/* A status containing the current ackId and the buffer status has been
|
|
received. */
|
|
handleStatus(stack, parameter0, parameter1);
|
|
break;
|
|
|
|
case STYPE0_PACKET_ACCEPTED:
|
|
/* A packet has been accepted by the link partner. */
|
|
handlePacketAccepted(stack, parameter0, parameter1);
|
|
break;
|
|
|
|
case STYPE0_PACKET_RETRY:
|
|
/* The link partner wants us to initiate a restart of the received ackId. */
|
|
handlePacketRetry(stack, parameter0, parameter1);
|
|
break;
|
|
|
|
case STYPE0_PACKET_NOT_ACCEPTED:
|
|
/* The link partner indicates that a packet has been rejected. */
|
|
handlePacketNotAccepted(stack, parameter0, parameter1);
|
|
break;
|
|
|
|
case STYPE0_LINK_RESPONSE:
|
|
/* The link partner has sent a response to a link-request. */
|
|
handleLinkResponse(stack, parameter0, parameter1);
|
|
break;
|
|
|
|
case STYPE0_VC_STATUS:
|
|
case STYPE0_RESERVED:
|
|
case STYPE0_IMPLEMENTATION_DEFINED:
|
|
default:
|
|
/* Unsupported symbol received. */
|
|
/* Discard them. */
|
|
break;
|
|
}
|
|
|
|
/* Check the stype1 part of the symbol. */
|
|
switch(stype1)
|
|
{
|
|
case STYPE1_START_OF_PACKET:
|
|
/* Starting new frames are ignored in this state. */
|
|
break;
|
|
|
|
case STYPE1_END_OF_PACKET:
|
|
/* Ending new frames are ignored in this state. */
|
|
break;
|
|
|
|
case STYPE1_STOMP:
|
|
/* Restarting frames are ignored in this state. */
|
|
break;
|
|
|
|
case STYPE1_RESTART_FROM_RETRY:
|
|
/* The link partner has confirmed our packet-retry-symbol. */
|
|
/* Go back to the normal state and reset the frame reception. */
|
|
stack->rxState = RX_STATE_LINK_INITIALIZED;
|
|
stack->rxCounter = 0u;
|
|
DEBUG_STATE("rx:normal(restart)");
|
|
break;
|
|
|
|
case STYPE1_LINK_REQUEST:
|
|
/* A link-request has been received. */
|
|
handleLinkRequest(stack, CMD_GET(s.data));
|
|
stack->rxState = RX_STATE_LINK_INITIALIZED;
|
|
DEBUG_STATE("rx:normal(link-req)");
|
|
break;
|
|
|
|
case STYPE1_NOP:
|
|
/* No operation symbol. */
|
|
/* Discard these. */
|
|
break;
|
|
|
|
case STYPE1_MULTICAST_EVENT:
|
|
case STYPE1_RESERVED:
|
|
default:
|
|
/* Unsupported symbol received. */
|
|
/* Discard them. */
|
|
break;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
/* The control symbol CRC is incorrect. */
|
|
/* Corrupted control symbol. Discard the symbol and enter the input-error-stopped state. */
|
|
stack->txState = TX_STATE_SEND_PACKET_NOT_ACCEPTED;
|
|
stack->rxState = RX_STATE_INPUT_ERROR_STOPPED;
|
|
stack->rxErrorCause = PACKET_NOT_ACCEPTED_CAUSE_CONTROL_CRC;
|
|
stack->statusInboundErrorControlCrc++;
|
|
DEBUG_STATE("rx:error-stopped");
|
|
}
|
|
break;
|
|
|
|
case RIO_SYMBOL_TYPE_ERROR:
|
|
/* Idle symbol error. Place the receiver in input-error-stopped state. */
|
|
stack->txState = TX_STATE_SEND_PACKET_NOT_ACCEPTED;
|
|
stack->rxState = RX_STATE_INPUT_ERROR_STOPPED;
|
|
stack->rxErrorCause = PACKET_NOT_ACCEPTED_CAUSE_ILLEGAL_CHARACTER;
|
|
stack->statusInboundErrorIllegalCharacter++;
|
|
DEBUG_STATE("rx:error-stopped");
|
|
break;
|
|
|
|
case RIO_SYMBOL_TYPE_DATA:
|
|
case RIO_SYMBOL_TYPE_IDLE:
|
|
default:
|
|
/* Data or idle symbol. */
|
|
/* Discard these in this state. */
|
|
break;
|
|
}
|
|
break;
|
|
|
|
case RX_STATE_INPUT_ERROR_STOPPED:
|
|
/******************************************************************************
|
|
* INPUT_ERROR_STOPPED
|
|
* This state is entered when an error situation has occurred. When in this
|
|
* state, all symbols should be discarded until a link-request-symbols has
|
|
* been received. See section 5.13.2.6 in part 6 of the standard.
|
|
* Note that it is only the input side of the port that are affected, not the
|
|
* output side. Packets may still be transmitted and acknowledges should be
|
|
* accepted.
|
|
******************************************************************************/
|
|
|
|
/* Check the type of symbol. */
|
|
switch(s.type)
|
|
{
|
|
case RIO_SYMBOL_TYPE_CONTROL:
|
|
/* This is a control symbol. */
|
|
|
|
/* Check if the CRC is correct. */
|
|
if(Crc5(s.data, 0x1fu) == (s.data & (uint8_t)0x1ful))
|
|
{
|
|
/* The CRC is correct. */
|
|
|
|
/* Get the content of the control symbol. */
|
|
stype0 = STYPE0_GET(s.data);
|
|
parameter0 = PARAMETER0_GET(s.data);
|
|
parameter1 = PARAMETER1_GET(s.data);
|
|
stype1 = STYPE1_GET(s.data);
|
|
|
|
/* Check the stype0 part of the symbol. */
|
|
switch(stype0)
|
|
{
|
|
case STYPE0_STATUS:
|
|
/* A status containing the current ackId and the buffer status has been
|
|
received. */
|
|
handleStatus(stack, parameter0, parameter1);
|
|
break;
|
|
|
|
case STYPE0_PACKET_ACCEPTED:
|
|
/* A packet has been accepted by the link partner. */
|
|
handlePacketAccepted(stack, parameter0, parameter1);
|
|
break;
|
|
|
|
case STYPE0_PACKET_RETRY:
|
|
/* The link partner wants us to initiate a restart of the received ackId. */
|
|
handlePacketRetry(stack, parameter0, parameter1);
|
|
break;
|
|
|
|
case STYPE0_PACKET_NOT_ACCEPTED:
|
|
/* The link partner indicates that a packet has been rejected. */
|
|
handlePacketNotAccepted(stack, parameter0, parameter1);
|
|
break;
|
|
|
|
case STYPE0_LINK_RESPONSE:
|
|
/* The link partner has sent a response to a link-request. */
|
|
handleLinkResponse(stack, parameter0, parameter1);
|
|
break;
|
|
|
|
case STYPE0_VC_STATUS:
|
|
case STYPE0_RESERVED:
|
|
case STYPE0_IMPLEMENTATION_DEFINED:
|
|
default:
|
|
/* Unsupported symbol received. */
|
|
/* Discard them. */
|
|
break;
|
|
}
|
|
|
|
/* Check the stype1 part of the symbol. */
|
|
switch(stype1)
|
|
{
|
|
case STYPE1_START_OF_PACKET:
|
|
/* Starting new frames are ignored in this state. */
|
|
break;
|
|
|
|
case STYPE1_END_OF_PACKET:
|
|
/* Ending new frames are ignored in this state. */
|
|
break;
|
|
|
|
case STYPE1_STOMP:
|
|
/* Restarting frames are ignored in this state. */
|
|
break;
|
|
|
|
case STYPE1_RESTART_FROM_RETRY:
|
|
/* Restart-from-retry are ignored in this state. */
|
|
break;
|
|
|
|
case STYPE1_LINK_REQUEST:
|
|
/* This is the symbol we have been waiting for. */
|
|
/* Force the transmitter to send a link-response and go back into the normal
|
|
operational state. */
|
|
/* The transmitter will always send a status as the first symbol after this. */
|
|
handleLinkRequest(stack, CMD_GET(s.data));
|
|
stack->rxState = RX_STATE_LINK_INITIALIZED;
|
|
DEBUG_STATE("rx:normal(link-req)");
|
|
break;
|
|
|
|
case STYPE1_NOP:
|
|
/* No operation symbol. */
|
|
/* Discard these. */
|
|
break;
|
|
|
|
case STYPE1_MULTICAST_EVENT:
|
|
case STYPE1_RESERVED:
|
|
default:
|
|
/* Unsupported symbol received. */
|
|
/* Discard them. */
|
|
break;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
/* The CRC is incorrect. */
|
|
/* Discard these in this state. */
|
|
}
|
|
break;
|
|
|
|
case RIO_SYMBOL_TYPE_DATA:
|
|
case RIO_SYMBOL_TYPE_IDLE:
|
|
case RIO_SYMBOL_TYPE_ERROR:
|
|
default:
|
|
/* Data, idle or error symbol. */
|
|
/* Discard these in this state. */
|
|
break;
|
|
}
|
|
break;
|
|
|
|
case RX_STATE_UNINITIALIZED:
|
|
default:
|
|
/******************************************************************************
|
|
* Wait for the port to be initialized.
|
|
******************************************************************************/
|
|
|
|
/* Discard all incoming symbols. */
|
|
break;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
RioSymbol RIO_portGetSymbol( RioStack_t *stack )
|
|
{
|
|
RioSymbol s;
|
|
|
|
|
|
switch(stack->txState)
|
|
{
|
|
case TX_STATE_PORT_INITIALIZED:
|
|
/******************************************************************************
|
|
* PORT_INITIALIZED
|
|
* This state is entered to initialize the link. Send status-control-symbols
|
|
* once in a while until the receiver has received enough error-free status-
|
|
* control-symbols and we have transmitted enough status-control-symbols. Once
|
|
* an error-free status-control-symbol has been received, the statuses are
|
|
* transmitted more frequently to decrease the time for the link to be
|
|
* initialized.
|
|
******************************************************************************/
|
|
|
|
/* Check if an idle symbol or a status control symbol should be sent. */
|
|
if(((stack->rxStatusReceived == 0) && (stack->txCounter == 255u)) ||
|
|
((stack->rxStatusReceived == 1) && (stack->txCounter >= 15u)))
|
|
{
|
|
/* A control symbol should be sent. */
|
|
|
|
/* Create a new status symbol and reset the transmission counter. */
|
|
stack->txCounter = 0u;
|
|
s = CreateControlSymbol(STYPE0_STATUS, stack->rxAckId, QueueAvailable(stack->rxQueue),
|
|
STYPE1_NOP, 0u);
|
|
|
|
/* Check if the receiver has received any error-free status and that we
|
|
have sent at least 15 status control symbols. */
|
|
if((stack->rxStatusReceived == 1) && (stack->txStatusCounter < 15u))
|
|
{
|
|
/* Has not sent enough status control symbols. */
|
|
stack->txStatusCounter++;
|
|
}
|
|
else
|
|
{
|
|
/* Has sent enough status control symbols. */
|
|
/* Dont do anything. */
|
|
}
|
|
}
|
|
else
|
|
{
|
|
/* Idle symbol should be sent. */
|
|
s.type = RIO_SYMBOL_TYPE_IDLE;
|
|
stack->txCounter++;
|
|
}
|
|
|
|
/* Check if we are ready to set the transmitter in a link initialized state. */
|
|
if ((stack->rxState == RX_STATE_LINK_INITIALIZED) && (stack->txStatusCounter == 15u))
|
|
{
|
|
/* Ready to go to link initialized. */
|
|
stack->txState = TX_STATE_LINK_INITIALIZED;
|
|
stack->txFrameState = TX_FRAME_START;
|
|
stack->txStatusCounter = 0u;
|
|
DEBUG_STATE("tx:normal");
|
|
}
|
|
else
|
|
{
|
|
/* Not ready to go to link initialized. */
|
|
/* Dont do anything. */
|
|
}
|
|
|
|
break;
|
|
|
|
case TX_STATE_LINK_INITIALIZED:
|
|
/******************************************************************************
|
|
* LINK_INITIALIZED
|
|
* The normal state. Accept packets and forward them. Send acknowledges when
|
|
* the receiver has received complete packets.
|
|
******************************************************************************/
|
|
|
|
/* Check if the receiver wants to acknowledge a packet. */
|
|
if(stack->rxAckId == stack->rxAckIdAcked)
|
|
{
|
|
/* The receiver does not want to acknowledge a packet. */
|
|
|
|
/* Check if there are any outstanding packets and if it has timed out. */
|
|
if((stack->txAckId == stack->txAckIdWindow) ||
|
|
((stack->portTime - stack->txFrameTimeout[stack->txAckId]) < stack->portTimeout))
|
|
{
|
|
/* There are no outstanding packets or there has been no timeout. */
|
|
|
|
/* Check if a packet is ongoing. */
|
|
if(stack->txFrameState == TX_FRAME_BODY)
|
|
{
|
|
/* A packet transmission is ongoing. */
|
|
|
|
/* Check if the packet has been completly sent. */
|
|
if(stack->txCounter != QueueGetFrontSize(stack->txQueue))
|
|
{
|
|
/* The packet has not been completly sent. */
|
|
|
|
/* Create a new data symbol to transmit. */
|
|
s.type = RIO_SYMBOL_TYPE_DATA;
|
|
s.data = QueueGetFrontContent(stack->txQueue, (uint32_t)stack->txCounter);
|
|
|
|
/* Check if this is the first symbol in a packet. */
|
|
if (stack->txCounter == 0u)
|
|
{
|
|
/* Place the correct ackId in the right place. */
|
|
s.data |= (uint32_t)stack->txAckIdWindow << 27;
|
|
}
|
|
else
|
|
{
|
|
/* Dont do anything. */
|
|
}
|
|
|
|
/* Update the transmission counter. */
|
|
stack->txCounter++;
|
|
|
|
/* A status control symbol was not sent. Update the status counter. */
|
|
stack->txStatusCounter++;
|
|
}
|
|
else
|
|
{
|
|
/* The packet has been sent. */
|
|
|
|
/* Save the timeout time and update to the next ackId. */
|
|
stack->txFrameTimeout[stack->txAckIdWindow] = stack->portTime;
|
|
stack->txAckIdWindow = ACKID_INC(stack->txAckIdWindow);
|
|
stack->txQueue = QueueWindowNext(stack->txQueue);
|
|
|
|
/* Check if there are more packets pending to be sent. */
|
|
/* Also check that there are buffer available at the receiver and that not too many
|
|
packets are outstanding. */
|
|
if(!QueueWindowEmpty(stack->txQueue) && (stack->txBufferStatus > 0) &&
|
|
(((stack->txAckIdWindow - stack->txAckId) & 0x1f) != 31))
|
|
{
|
|
/* More pending packets. */
|
|
DEBUG_FRAMING_TX("cont=%i", stack->txAckIdWindow);
|
|
/* Create a control symbol to signal that the new packet has started. */
|
|
s = CreateControlSymbol(STYPE0_STATUS, stack->rxAckId, QueueAvailable(stack->rxQueue),
|
|
STYPE1_START_OF_PACKET, 0u);
|
|
|
|
/* Restart transmission counter. */
|
|
stack->txCounter = 0;
|
|
}
|
|
else
|
|
{
|
|
/* No more pending packets. */
|
|
DEBUG_FRAMING_TX("end=%i", stack->txAckIdWindow);
|
|
/* Create a control symbol to signal that the packet has ended. */
|
|
s = CreateControlSymbol(STYPE0_STATUS, stack->rxAckId, QueueAvailable(stack->rxQueue),
|
|
STYPE1_END_OF_PACKET, 0u);
|
|
|
|
/* Go back to wait for a new frame. */
|
|
stack->txFrameState = TX_FRAME_START;
|
|
}
|
|
|
|
/* A status control symbol has been sent. Reset the status counter. */
|
|
stack->txStatusCounter = 0u;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
/* No packet is being sent. */
|
|
|
|
/* Check if there are any pending packets to start sending. */
|
|
/* Also check that there are buffer available at the receiver and that not too many
|
|
packets are outstanding. */
|
|
if(!QueueWindowEmpty(stack->txQueue) && (stack->txBufferStatus > 0) &&
|
|
(((stack->txAckIdWindow - stack->txAckId) & 0x1f) != 31))
|
|
{
|
|
/* There is a pending packet to send. */
|
|
DEBUG_FRAMING_TX("start=%i", stack->txAckIdWindow);
|
|
/* Send a start-of-packet control symbol to start to send the packet. */
|
|
s = CreateControlSymbol(STYPE0_STATUS, stack->rxAckId, QueueAvailable(stack->rxQueue),
|
|
STYPE1_START_OF_PACKET, 0u);
|
|
stack->txFrameState = TX_FRAME_BODY;
|
|
stack->txCounter = 0u;
|
|
|
|
/* A status control symbol has been sent. Reset the status counter. */
|
|
stack->txStatusCounter = 0u;
|
|
}
|
|
else
|
|
{
|
|
/* There are no pending packets to send. */
|
|
|
|
/* Check if a status control symbol must be transmitted. */
|
|
if(stack->txStatusCounter < 255u)
|
|
{
|
|
/* Not required to send a status control symbol. */
|
|
|
|
/* Send an idle-symbol. */
|
|
s.type = RIO_SYMBOL_TYPE_IDLE;
|
|
stack->txStatusCounter++;
|
|
}
|
|
else
|
|
{
|
|
/* Must send a status control symbol. */
|
|
|
|
/* Create a status control symbol. */
|
|
s = CreateControlSymbol(STYPE0_STATUS, stack->rxAckId, QueueAvailable(stack->rxQueue),
|
|
STYPE1_NOP, 0u);
|
|
|
|
/* A status control symbol has been sent. Reset the status counter. */
|
|
stack->txStatusCounter = 0u;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
/* There has been a timeout. */
|
|
/* A packet has been sent but no packet-accepted has been received. */
|
|
DEBUG_FRAMING_TX("timeout=%i", stack->txAckId);
|
|
/* Send link-request-symbol (input-status). */
|
|
s = CreateControlSymbol(STYPE0_STATUS, stack->rxAckId, QueueAvailable(stack->rxQueue),
|
|
STYPE1_LINK_REQUEST, LINK_REQUEST_INPUT_STATUS);
|
|
|
|
/* Save the time when this was transmitted. */
|
|
stack->txFrameTimeout[stack->txAckId] = stack->portTime;
|
|
|
|
/* Remember that this symbol has been transmitted. */
|
|
stack->txCounter = 1;
|
|
|
|
/* Go into the output error stopped state. */
|
|
stack->txState = TX_STATE_OUTPUT_ERROR_STOPPED;
|
|
stack->statusOutboundErrorTimeout++;
|
|
DEBUG_STATE("tx:error-stopped");
|
|
}
|
|
}
|
|
else
|
|
{
|
|
/* The receiver wants us to send an acknowledgement. */
|
|
s = CreateControlSymbol(STYPE0_PACKET_ACCEPTED, stack->rxAckIdAcked, QueueAvailable(stack->rxQueue),
|
|
STYPE1_NOP, 0u);
|
|
stack->rxAckIdAcked = ACKID_INC(stack->rxAckIdAcked);
|
|
|
|
/* A status control symbol was not sent. Update the status counter. */
|
|
stack->txStatusCounter++;
|
|
}
|
|
break;
|
|
|
|
case TX_STATE_SEND_PACKET_RETRY:
|
|
/******************************************************************************
|
|
* SEND_PACKET_RETRY
|
|
* This state is set by the receiver to force a packet-retry-symbol to be
|
|
* transmitted.
|
|
******************************************************************************/
|
|
|
|
/* Check if the receiver wants to acknowledge a packet. */
|
|
/* This must be done first or we will get an error for a missmatching
|
|
ackId in the link-partner. */
|
|
if(stack->rxAckId == stack->rxAckIdAcked)
|
|
{
|
|
/* No pending acknowledge. */
|
|
|
|
/* Send a packet-retry symbol to tell the link partner to retry the last frame. */
|
|
s = CreateControlSymbol(STYPE0_PACKET_RETRY, stack->rxAckId, QueueAvailable(stack->rxQueue),
|
|
STYPE1_NOP, 0u);
|
|
|
|
/* Proceed with normal transmission. */
|
|
stack->txState = TX_STATE_LINK_INITIALIZED;
|
|
|
|
/* A status control symbol was not sent. Update the status counter. */
|
|
stack->txStatusCounter++;
|
|
}
|
|
else
|
|
{
|
|
|
|
/* The receiver wants us to send an acknowledgement. */
|
|
s = CreateControlSymbol(STYPE0_PACKET_ACCEPTED, stack->rxAckIdAcked, QueueAvailable(stack->rxQueue),
|
|
STYPE1_NOP, 0u);
|
|
stack->rxAckIdAcked = ACKID_INC(stack->rxAckIdAcked);
|
|
|
|
/* A status control symbol was not sent. Update the status counter. */
|
|
stack->txStatusCounter++;
|
|
}
|
|
break;
|
|
|
|
case TX_STATE_SEND_PACKET_NOT_ACCEPTED:
|
|
/******************************************************************************
|
|
* SEND_PACKET_NOT_ACCEPTED
|
|
* This state is set by the receiver to force a packet-not-accepted-symbol to be
|
|
* transmitted.
|
|
******************************************************************************/
|
|
|
|
/* Send a packet-not-accepted symbol to indicate an error on the link. */
|
|
s = CreateControlSymbol(STYPE0_PACKET_NOT_ACCEPTED, 0, stack->rxErrorCause,
|
|
STYPE1_NOP, 0u);
|
|
|
|
/* Proceed with normal transmission. */
|
|
stack->txState = TX_STATE_LINK_INITIALIZED;
|
|
|
|
/* A status control symbol was not sent. Update the status counter. */
|
|
stack->txStatusCounter++;
|
|
break;
|
|
|
|
case TX_STATE_SEND_LINK_RESPONSE:
|
|
/******************************************************************************
|
|
* SEND_LINK_RESPONSE
|
|
* This state is set by the receiver to force a link-response-symbol to be
|
|
* transmitted.
|
|
******************************************************************************/
|
|
|
|
DEBUG_FRAMING_RX("link-res:%u", stack->rxAckId);
|
|
|
|
/* Check the state of the receiver. */
|
|
/* REMARK: If a link-request gives this response and a link-request also makes the receiver
|
|
enter the normal operational state, none of these states except the normal state will ever
|
|
be used... */
|
|
if((stack->rxState == RX_STATE_LINK_INITIALIZED) || (stack->rxState == RX_STATE_PORT_INITIALIZED))
|
|
{
|
|
/* Normal state. */
|
|
s = CreateControlSymbol(STYPE0_LINK_RESPONSE, stack->rxAckId, LINK_RESPONSE_PORT_STATUS_OK,
|
|
STYPE1_NOP, 0u);
|
|
}
|
|
else if(stack->rxState == RX_STATE_INPUT_RETRY_STOPPED)
|
|
{
|
|
/* Input-retry-stopped state. */
|
|
s = CreateControlSymbol(STYPE0_LINK_RESPONSE, stack->rxAckId, LINK_RESPONSE_PORT_STATUS_RETRY_STOPPED,
|
|
STYPE1_NOP, 0u);
|
|
}
|
|
else if(stack->rxState == RX_STATE_INPUT_ERROR_STOPPED)
|
|
{
|
|
/* Input-error-stopped state. */
|
|
s = CreateControlSymbol(STYPE0_LINK_RESPONSE, stack->rxAckId, LINK_RESPONSE_PORT_STATUS_ERROR_STOPPED,
|
|
STYPE1_NOP, 0u);
|
|
}
|
|
else
|
|
{
|
|
/* Not in the defined states. */
|
|
s = CreateControlSymbol(STYPE0_LINK_RESPONSE, stack->rxAckId, LINK_RESPONSE_PORT_STATUS_ERROR,
|
|
STYPE1_NOP, 0u);
|
|
}
|
|
|
|
/* Proceed with normal transmission. */
|
|
stack->txState = TX_STATE_LINK_INITIALIZED;
|
|
|
|
/* Force a status to be transmitted the next time to comply to the input-error-stopped
|
|
state rules. */
|
|
stack->txStatusCounter = 255;
|
|
break;
|
|
|
|
case TX_STATE_OUTPUT_RETRY_STOPPED:
|
|
/******************************************************************************
|
|
* OUTPUT_RETRY_STOPPED
|
|
* This state is entered when the link-partner has transmitted a
|
|
* packet-retry-symbol. The packet-retry-symbol is acknowledged by sending a
|
|
* restart-from-retry-symbol.
|
|
* This state follows 5.9.1.5 in part 6.
|
|
******************************************************************************/
|
|
|
|
/* Send a restart-from-retry symbol to acknowledge. */
|
|
s = CreateControlSymbol(STYPE0_STATUS, stack->rxAckId, QueueAvailable(stack->rxQueue),
|
|
STYPE1_RESTART_FROM_RETRY, 0u);
|
|
|
|
/* Restart the current frame and proceed with normal operation. */
|
|
stack->txFrameState = TX_FRAME_START;
|
|
stack->txState = TX_STATE_LINK_INITIALIZED;
|
|
stack->txCounter = 0;
|
|
DEBUG_STATE("tx:normal");
|
|
|
|
/* Discard all packets that has not received a matching packet-accepted. */
|
|
stack->txAckIdWindow = stack->txAckId;
|
|
stack->txQueue = QueueWindowReset(stack->txQueue);
|
|
|
|
/* A status control symbol was sent. Reset the status counter. */
|
|
stack->txStatusCounter = 0;
|
|
break;
|
|
|
|
case TX_STATE_OUTPUT_ERROR_STOPPED:
|
|
/******************************************************************************
|
|
* OUTPUT_ERROR_STOPPED
|
|
* This state is entered when the link partner has encountered any problem
|
|
* which is indicated by sending a packet-not-accepted symbol or if a packet
|
|
* timeout has expired. The error condition is acknowledged by sending a
|
|
* link-request-symbol and then wait for a link-response reply.
|
|
* This state follows 5.13.2.7 in part 6.
|
|
******************************************************************************/
|
|
|
|
/* Check if a link-request-symbol has been transmitted. */
|
|
if(stack->txCounter == 0)
|
|
{
|
|
/* A link-request-symbol has not been transmitted. */
|
|
|
|
/* Send link-request-symbol (input-status). */
|
|
s = CreateControlSymbol(STYPE0_STATUS, stack->rxAckId, QueueAvailable(stack->rxQueue),
|
|
STYPE1_LINK_REQUEST, LINK_REQUEST_INPUT_STATUS);
|
|
|
|
/* Save the time when this was transmitted. */
|
|
stack->txFrameTimeout[stack->txAckId] = stack->portTime;
|
|
|
|
/* Remember that this symbol has been transmitted. */
|
|
stack->txCounter = 1;
|
|
}
|
|
else
|
|
{
|
|
/* A link-request-symbol has been transmitted. */
|
|
|
|
/* Check if the link partner reply has timed out. */
|
|
if((stack->portTime - stack->txFrameTimeout[stack->txAckId]) < stack->portTimeout)
|
|
{
|
|
/* No timeout. */
|
|
|
|
/* A link-request-symbol has been transmitted. */
|
|
/* Send only idle-symbols until the link-response is received. */
|
|
s.type = RIO_SYMBOL_TYPE_IDLE;
|
|
}
|
|
else
|
|
{
|
|
/* Link response timeout. */
|
|
|
|
/* Check if the link-partner has not responded for too many times. */
|
|
if(stack->txCounter < 5)
|
|
{
|
|
/* Not too many timeouts. */
|
|
/* Retry and send a new link-request. */
|
|
|
|
/* Send link-request-symbol (input-status). */
|
|
s = CreateControlSymbol(STYPE0_STATUS, stack->rxAckId, QueueAvailable(stack->rxQueue),
|
|
STYPE1_LINK_REQUEST, LINK_REQUEST_INPUT_STATUS);
|
|
|
|
/* Save the time when this was transmitted. */
|
|
stack->txFrameTimeout[stack->txAckId] = stack->portTime;
|
|
|
|
/* Increment the number of times we have retransmitted the link-request. */
|
|
stack->txCounter++;
|
|
}
|
|
else
|
|
{
|
|
/* The link partner has not answered for too many times. */
|
|
/* Give up and set the state to uninitialized. */
|
|
stack->txState = TX_STATE_UNINITIALIZED;
|
|
s.type = RIO_SYMBOL_TYPE_IDLE;
|
|
ASSERT0("No link-response received, giving up.");
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
|
|
case TX_STATE_UNINITIALIZED:
|
|
default:
|
|
/******************************************************************************
|
|
* Wait for the port to be initialized.
|
|
******************************************************************************/
|
|
|
|
/* Send only idle symbols. */
|
|
s.type = RIO_SYMBOL_TYPE_IDLE;
|
|
break;
|
|
}
|
|
|
|
/* Return the created symbol. */
|
|
return s;
|
|
}
|
|
|
|
/*******************************************************************************
|
|
* Deprecated functions
|
|
*******************************************************************************/
|
|
|
|
uint8_t RIO_packetTid( RioStack_t *stack )
|
|
{
|
|
ASSERT(!QueueEmpty(stack->rxQueue) , "Reading from empty reception queue.");
|
|
|
|
return (uint8_t) (QueueGetFrontContent(stack->rxQueue, 1ul) & 0xfful);
|
|
}
|
|
|
|
|
|
uint16_t RIO_packetDestination( RioStack_t *stack )
|
|
{
|
|
ASSERT(!QueueEmpty(stack->rxQueue), "Reading from empty reception queue.");
|
|
|
|
return (uint16_t) (QueueGetFrontContent(stack->rxQueue, 0ul));
|
|
}
|
|
|
|
|
|
uint16_t RIO_packetSource( RioStack_t *stack )
|
|
{
|
|
ASSERT(!QueueEmpty(stack->rxQueue), "Reading from empty reception queue.");
|
|
|
|
return (uint16_t) (QueueGetFrontContent(stack->rxQueue, 1ul) >> 16);
|
|
}
|
|
|
|
|
|
uint8_t RIO_readMaintenanceReadRequestHop( RioStack_t *stack )
|
|
{
|
|
ASSERT(!QueueEmpty(stack->rxQueue), "Reading from empty reception queue.");
|
|
|
|
return (QueueGetFrontContent(stack->rxQueue, 2ul) >> 24);
|
|
}
|
|
|
|
uint32_t RIO_readMaintenanceReadRequestOffset( RioStack_t *stack )
|
|
{
|
|
ASSERT(!QueueEmpty(stack->rxQueue), "Reading from empty reception queue.");
|
|
|
|
return (QueueGetFrontContent(stack->rxQueue, 2ul) & 0x00fffffcul);
|
|
}
|
|
|
|
uint8_t RIO_readMaintenanceReadResponseHop( RioStack_t *stack )
|
|
{
|
|
ASSERT(!QueueEmpty(stack->rxQueue), "Reading from empty reception queue.");
|
|
|
|
return (QueueGetFrontContent(stack->rxQueue, 2ul) >> 24);
|
|
}
|
|
|
|
uint32_t RIO_readMaintenanceReadResponse( RioStack_t *stack )
|
|
{
|
|
uint32_t readData;
|
|
|
|
|
|
ASSERT(!QueueEmpty(stack->rxQueue), "Reading from empty reception queue.");
|
|
|
|
/* There is no way of knowing where the data is positioned. */
|
|
/* Bit-or the two words together since one of the words are zero. */
|
|
readData = QueueGetFrontContent(stack->rxQueue, 3ul);
|
|
readData |= QueueGetFrontContent(stack->rxQueue, 4ul);
|
|
return readData;
|
|
}
|
|
|
|
uint8_t RIO_readMaintenanceWriteRequestHop( RioStack_t *stack )
|
|
{
|
|
ASSERT(!QueueEmpty(stack->rxQueue), "Reading from empty reception queue.");
|
|
|
|
return (QueueGetFrontContent(stack->rxQueue, 2ul) >> 24);
|
|
}
|
|
|
|
uint32_t RIO_readMaintenanceWriteRequestOffset( RioStack_t *stack )
|
|
{
|
|
ASSERT(!QueueEmpty(stack->rxQueue), "Reading from empty reception queue.");
|
|
|
|
return (QueueGetFrontContent(stack->rxQueue, 2ul) & 0x00fffffcul);
|
|
}
|
|
|
|
uint32_t RIO_readMaintenanceWriteRequestData( RioStack_t *stack )
|
|
{
|
|
ASSERT(!QueueEmpty(stack->rxQueue), "Reading from empty reception queue.");
|
|
|
|
return (QueueGetFrontContent(stack->rxQueue, 3ul) | QueueGetFrontContent(stack->rxQueue, 4ul));
|
|
}
|
|
|
|
uint8_t RIO_readMaintenanceWriteResponseHop( RioStack_t *stack )
|
|
{
|
|
return (uint8_t) (QueueGetFrontContent(stack->rxQueue, 2ul) >> 24);
|
|
}
|
|
|
|
|
|
|
|
void RIO_sendNwrite8( RioStack_t *stack, const uint16_t destid, const uint32_t address,
|
|
const uint8_t data)
|
|
{
|
|
sendNwrite(stack, destid, stack->baseDeviceId, 0, address, 1, &data, 0u);
|
|
}
|
|
|
|
|
|
void RIO_sendNwriteR8( RioStack_t *stack, const uint16_t destid, const uint8_t tid, const uint32_t address,
|
|
const uint8_t data)
|
|
{
|
|
sendNwrite(stack, destid, stack->baseDeviceId, tid, address, 1, &data, 1u);
|
|
}
|
|
|
|
|
|
uint32_t RIO_readNwriteAddress8( RioStack_t *stack )
|
|
{
|
|
uint32_t address;
|
|
|
|
|
|
ASSERT(!QueueEmpty(stack->rxQueue), "Reading from empty reception queue.");
|
|
|
|
/* Assemble the address from the wrsize field and the address itself to get a byte address. */
|
|
address = (QueueGetFrontContent(stack->rxQueue, 1ul) >> 8) & (uint32_t)0x00000003ul;
|
|
address |= QueueGetFrontContent(stack->rxQueue, 2ul) & (uint32_t)0xfffffffcul;
|
|
|
|
return address;
|
|
}
|
|
|
|
|
|
uint8_t RIO_readNwriteSize8( RioStack_t *stack )
|
|
{
|
|
uint8_t wrsize;
|
|
uint8_t n;
|
|
|
|
|
|
ASSERT(!QueueEmpty(stack->rxQueue), "Reading from empty reception queue.");
|
|
|
|
/* Get the wrsize field from the packet and check its value. */
|
|
wrsize = (uint8_t) ((QueueGetFrontContent(stack->rxQueue, 1ul) >> 8) & (uint32_t)0xful);
|
|
switch(wrsize)
|
|
{
|
|
case 0:
|
|
/* Reading one byte. */
|
|
n = 1u;
|
|
break;
|
|
case 1:
|
|
/* Reading one byte. */
|
|
n = 1u;
|
|
break;
|
|
case 2:
|
|
/* Reading one byte. */
|
|
n = 1u;
|
|
break;
|
|
case 3:
|
|
/* Reading one byte. */
|
|
n = 1u;
|
|
break;
|
|
default:
|
|
/* Unsupported. */
|
|
n = 0u;
|
|
break;
|
|
}
|
|
|
|
return n;
|
|
}
|
|
|
|
|
|
uint8_t RIO_readNwritePayload8( RioStack_t *stack )
|
|
{
|
|
uint8_t returnValue;
|
|
uint32_t readData;
|
|
|
|
|
|
ASSERT(!QueueEmpty(stack->rxQueue), "Reading from empty reception queue.");
|
|
|
|
/* Since there is no way of knowing where the byte will be placed,
|
|
OR all bytes in the payload and return it. */
|
|
readData = QueueGetFrontContent(stack->rxQueue, 3ul);
|
|
returnValue = (uint8_t) (readData >> 24);
|
|
returnValue |= (uint8_t) (readData >> 16);
|
|
returnValue |= (uint8_t) (readData >> 8);
|
|
returnValue |= (uint8_t) (readData);
|
|
readData = QueueGetFrontContent(stack->rxQueue, 4ul);
|
|
returnValue |= (uint8_t) (readData >> 24);
|
|
returnValue |= (uint8_t) (readData >> 16);
|
|
returnValue |= (uint8_t) (readData >> 8);
|
|
returnValue |= (uint8_t) (readData);
|
|
|
|
return returnValue;
|
|
}
|
|
|
|
void RIO_sendNread8( RioStack_t *stack, const uint16_t destid, const uint8_t tid, const uint32_t address)
|
|
{
|
|
uint32_t content;
|
|
uint16_t crc = 0xffffu;
|
|
|
|
|
|
ASSERT((QueueAvailable(stack->txQueue) > 0u), "Transmission queue packet overflow.");
|
|
|
|
/* ackId(4:0)|0|vc|crf|prio(1:0)|tt(1:0)|ftype(3:0)|destinationId(15:0) */
|
|
/* ackId is set when the packet is transmitted. */
|
|
content = ((uint32_t) 0x0012ul) << 16;
|
|
content |= (uint32_t) destid;
|
|
crc = Crc32(content, crc);
|
|
QueueSetContent(stack->txQueue, 0ul, content);
|
|
|
|
/* sourceId(15:0)|transaction(3:0)|rdsize(3:0)|srcTID(7:0) */
|
|
content = ((uint32_t) stack->baseDeviceId) << 16;
|
|
content |= ((uint32_t) 0x4ul) << 12;
|
|
content |= (address & (uint32_t)0x00000003ul) << 8;
|
|
content |= (uint32_t) tid;
|
|
crc = Crc32(content, crc);
|
|
QueueSetContent(stack->txQueue, 1ul, content);
|
|
|
|
/* address(28:0)|wdptr|xamsbs(1:0) */
|
|
/* xamsbs cannot be used if the address is a word. */
|
|
content = address & (uint32_t)0xfffffffcul;
|
|
crc = Crc32(content, crc);
|
|
QueueSetContent(stack->txQueue, 2ul, content);
|
|
|
|
/* crc(15:0)|pad(15:0) */
|
|
content = ((uint32_t) crc) << 16;
|
|
QueueSetContent(stack->txQueue, 3ul, content);
|
|
|
|
/* Set the size of the packet and place it in the queue. */
|
|
QueueSetSize(stack->txQueue, 4ul);
|
|
stack->txQueue = QueueEnqueue(stack->txQueue);
|
|
}
|
|
|
|
|
|
uint32_t RIO_readNreadAddress8( RioStack_t *stack )
|
|
{
|
|
uint32_t address;
|
|
|
|
|
|
ASSERT(!QueueEmpty(stack->rxQueue), "Reading from empty reception queue.");
|
|
|
|
/* Assemble the address from the rdsize field and the address itself to get a byte address. */
|
|
address = (QueueGetFrontContent(stack->rxQueue, 1ul) >> 8) & (uint32_t)0x00000003ul;
|
|
address |= QueueGetFrontContent(stack->rxQueue, 2ul) & (uint32_t)0xfffffffcul;
|
|
|
|
return address;
|
|
}
|
|
|
|
|
|
uint8_t RIO_readNreadSize8( RioStack_t *stack )
|
|
{
|
|
uint8_t rdsize;
|
|
uint8_t n;
|
|
|
|
|
|
ASSERT(!QueueEmpty(stack->rxQueue), "Reading from empty reception queue.");
|
|
|
|
/* Get the rdsize field from the packet and check its value. */
|
|
rdsize = (uint8_t) ((QueueGetFrontContent(stack->rxQueue, 1ul) >> 8) & (uint32_t)0xful);
|
|
switch(rdsize)
|
|
{
|
|
case 0:
|
|
/* Reading one byte. */
|
|
n = 1u;
|
|
break;
|
|
case 1:
|
|
/* Reading one byte. */
|
|
n = 1u;
|
|
break;
|
|
case 2:
|
|
/* Reading one byte. */
|
|
n = 1u;
|
|
break;
|
|
case 3:
|
|
/* Reading one byte. */
|
|
n = 1u;
|
|
break;
|
|
default:
|
|
/* Unsupported. */
|
|
n = 0u;
|
|
break;
|
|
}
|
|
|
|
return n;
|
|
}
|
|
|
|
|
|
void RIO_sendMessage8( RioStack_t *stack, const uint16_t destid, const uint8_t mailbox, const uint16_t size, const uint8_t* data)
|
|
{
|
|
uint32_t content;
|
|
uint16_t crc = 0xffffu;
|
|
uint32_t packetIndex;
|
|
uint32_t dataIndex;
|
|
|
|
|
|
ASSERT((QueueAvailable(stack->txQueue) > 0u), "Transmission queue packet overflow.");
|
|
ASSERT((size <= 256), "Packet sizes over 256 are currently unsupported.");
|
|
|
|
/* ackId(4:0)|0|vc|crf|prio(1:0)|tt(1:0)|ftype(3:0)|destinationId(15:0) */
|
|
/* ackId is set when the packet is transmitted. */
|
|
content = ((uint32_t) 0x001bul) << 16;
|
|
content |= (uint32_t) destid;
|
|
crc = Crc32(content, crc);
|
|
QueueSetContent(stack->txQueue, 0ul, content);
|
|
|
|
/* sourceId(15:0)|msglen(3:0)|ssize(3:0)|letter(1:0|mbox(1:0)|xmbox(3:0) */
|
|
content = ((uint32_t) stack->baseDeviceId) << 16;
|
|
if(size <= 8u)
|
|
{
|
|
content |= ((uint32_t) 0x09ul) << 8;
|
|
}
|
|
else if(size <= 16u)
|
|
{
|
|
content |= ((uint32_t) 0x0aul) << 8;
|
|
}
|
|
else if(size <= 32u)
|
|
{
|
|
content |= ((uint32_t) 0x0bul) << 8;
|
|
}
|
|
else if(size <= 64u)
|
|
{
|
|
content |= ((uint32_t) 0x0cul) << 8;
|
|
}
|
|
else if(size <= 128u)
|
|
{
|
|
content |= ((uint32_t) 0x0dul) << 8;
|
|
}
|
|
else
|
|
{
|
|
content |= ((uint32_t) 0x0eul) << 8;
|
|
}
|
|
content |= ((uint32_t)mailbox & (uint32_t)0xfu) << 4;
|
|
content |= ((uint32_t)mailbox) >> 4;
|
|
crc = Crc32(content, crc);
|
|
QueueSetContent(stack->txQueue, 1ul, content);
|
|
|
|
/* double-word0...double-wordN */
|
|
dataIndex = 0;
|
|
packetIndex = 8;
|
|
while(dataIndex < size)
|
|
{
|
|
content <<= 8;
|
|
if(packetIndex == 80)
|
|
{
|
|
content |= crc >> 8;
|
|
}
|
|
else if(packetIndex == 81)
|
|
{
|
|
content |= crc & 0xff;
|
|
}
|
|
else
|
|
{
|
|
content |= data[dataIndex++];
|
|
}
|
|
|
|
if((packetIndex & 0x3) == 3)
|
|
{
|
|
crc = Crc32(content, crc);
|
|
QueueSetContent(stack->txQueue, packetIndex>>2, content);
|
|
}
|
|
|
|
packetIndex++;
|
|
}
|
|
|
|
/* Pad the data to an even double word. */
|
|
while((dataIndex & 0x7) != 0)
|
|
{
|
|
content <<= 8;
|
|
dataIndex++;
|
|
|
|
if((packetIndex & 0x3) == 3)
|
|
{
|
|
crc = Crc32(content, crc);
|
|
QueueSetContent(stack->txQueue, packetIndex>>2, content);
|
|
}
|
|
|
|
packetIndex++;
|
|
}
|
|
|
|
/* Check where the CRC should be placed. */
|
|
if((packetIndex & 0x3) == 0)
|
|
{
|
|
/* crc(15:0)|pad(15:0) */
|
|
content = ((uint32_t) crc) << 16;
|
|
}
|
|
else
|
|
{
|
|
/* double-wordN-LSB|crc(15:0) */
|
|
content &= 0x0000ffff;
|
|
crc = Crc16(content, crc);
|
|
content <<= 16;
|
|
content |= crc;
|
|
}
|
|
|
|
/* Set the crc. */
|
|
QueueSetContent(stack->txQueue, packetIndex>>2, content);
|
|
|
|
/* Set the size of the packet and place it in the queue. */
|
|
QueueSetSize(stack->txQueue, 1+(packetIndex>>2));
|
|
stack->txQueue = QueueEnqueue(stack->txQueue);
|
|
}
|
|
|
|
|
|
uint8_t RIO_readMessageMbox( RioStack_t *stack )
|
|
{
|
|
ASSERT(!QueueEmpty(stack->rxQueue), "Reading from empty reception queue." );
|
|
|
|
return (uint8_t) ((QueueGetFrontContent(stack->rxQueue, 1ul) >> 4) & (uint32_t)0xful);
|
|
}
|
|
|
|
|
|
uint16_t RIO_readMessageSize8( RioStack_t *stack )
|
|
{
|
|
ASSERT(!QueueEmpty(stack->rxQueue), "Reading from empty reception queue.");
|
|
|
|
return (uint16_t) (4ul*(QueueGetFrontSize(stack->rxQueue) - 3ul));
|
|
}
|
|
|
|
|
|
/*lint -save -e613 */
|
|
void RIO_readMessagePayload8( RioStack_t *stack, uint8_t* buffer )
|
|
{
|
|
uint32_t size;
|
|
uint32_t dataIndex;
|
|
uint32_t packetIndex;
|
|
uint32_t content = 0;;
|
|
|
|
|
|
ASSERT((buffer != NULL), "Buffer is not allocated.");
|
|
ASSERT(!QueueEmpty(stack->rxQueue), "Reading from empty reception queue.");
|
|
|
|
/* Move bytes from inbound packet queue into the user buffer. */
|
|
/* Long messages contain a CRC in byte 80-81, this is removed when the buffer
|
|
is copied. */
|
|
size = QueueGetFrontSize(stack->rxQueue);
|
|
dataIndex = 0;
|
|
packetIndex = 8;
|
|
while((packetIndex>>2) < size)
|
|
{
|
|
/* Check if a new word should be read from the inbound queue. */
|
|
if((packetIndex & 0x3) == 0)
|
|
{
|
|
/* Get a new word. */
|
|
content = QueueGetFrontContent(stack->rxQueue, packetIndex>>2);
|
|
}
|
|
else
|
|
{
|
|
/* Update the current word. Remove the MSB, it has already be moved
|
|
to the user buffer. */
|
|
content <<= 8;
|
|
}
|
|
|
|
/* Check if the current byte is CRC. */
|
|
if((packetIndex != 80) && (packetIndex != 81))
|
|
{
|
|
/* Not CRC. */
|
|
/* Move the byte to the user buffer. */
|
|
buffer[dataIndex++] = (content >> 24);
|
|
}
|
|
|
|
/* Increment to the next position in the packet. */
|
|
packetIndex++;
|
|
}
|
|
}
|
|
/*lint -restore */
|
|
|
|
uint16_t RIO_readDoorbellInfo( RioStack_t *stack )
|
|
{
|
|
ASSERT(!QueueEmpty(stack->rxQueue), "Reading from empty reception queue.");
|
|
|
|
return (uint16_t) (QueueGetFrontContent(stack->rxQueue, 2ul) >> 16);
|
|
}
|
|
|
|
|
|
void RIO_sendResponseDone8( RioStack_t *stack, const uint16_t destid, const uint8_t tid, const uint32_t address, const uint8_t data)
|
|
{
|
|
uint32_t content;
|
|
uint16_t crc = 0xffffu;
|
|
|
|
|
|
ASSERT((QueueAvailable(stack->txQueue) > 0u), "Transmission queue packet overflow.");
|
|
|
|
/* ackId(4:0)|0|vc|crf|prio(1:0)|tt(1:0)|ftype(3:0)|destinationId(15:0) */
|
|
/* ackId is set when the packet is transmitted. */
|
|
content = 0x001dul << 16;
|
|
content |= (uint32_t) destid;
|
|
crc = Crc32(content, crc);
|
|
QueueSetContent(stack->txQueue, 0ul, content);
|
|
|
|
/* sourceId(15:0)|transaction(3:0)|status(3:0)|targetTID(7:0) */
|
|
content = ((uint32_t) stack->baseDeviceId) << 16;
|
|
content |= (uint32_t)0x80ul << 8;
|
|
content |= (uint32_t) tid;
|
|
crc = Crc32(content, crc);
|
|
QueueSetContent(stack->txQueue, 1ul, content);
|
|
|
|
/* double-word 0 */
|
|
switch(address & 0x7ul)
|
|
{
|
|
case 0:
|
|
/* MSB byte. */
|
|
content = ((uint32_t) data) << 24;
|
|
crc = Crc32(content, crc);
|
|
QueueSetContent(stack->txQueue, 2ul, content);
|
|
content = 0x00000000ul;
|
|
crc = Crc32(content, crc);
|
|
QueueSetContent(stack->txQueue, 3ul, content);
|
|
break;
|
|
case 1:
|
|
content = ((uint32_t) data) << 16;
|
|
crc = Crc32(content, crc);
|
|
QueueSetContent(stack->txQueue, 2ul, content);
|
|
content = 0x00000000ul;
|
|
crc = Crc32(content, crc);
|
|
QueueSetContent(stack->txQueue, 3ul, content);
|
|
break;
|
|
case 2:
|
|
content = ((uint32_t) data) << 8;
|
|
crc = Crc32(content, crc);
|
|
QueueSetContent(stack->txQueue, 2ul, content);
|
|
content = 0x00000000ul;
|
|
crc = Crc32(content, crc);
|
|
QueueSetContent(stack->txQueue, 3ul, content);
|
|
break;
|
|
case 3:
|
|
content = ((uint32_t) data);
|
|
crc = Crc32(content, crc);
|
|
QueueSetContent(stack->txQueue, 2ul, content);
|
|
content = 0x00000000ul;
|
|
crc = Crc32(content, crc);
|
|
QueueSetContent(stack->txQueue, 3ul, content);
|
|
break;
|
|
case 4:
|
|
content = 0x00000000ul;
|
|
crc = Crc32(content, crc);
|
|
QueueSetContent(stack->txQueue, 2ul, content);
|
|
content = ((uint32_t) data) << 24;
|
|
crc = Crc32(content, crc);
|
|
QueueSetContent(stack->txQueue, 3ul, content);
|
|
break;
|
|
case 5:
|
|
content = 0x00000000ul;
|
|
crc = Crc32(content, crc);
|
|
QueueSetContent(stack->txQueue, 2ul, content);
|
|
content = ((uint32_t) data) << 16;
|
|
crc = Crc32(content, crc);
|
|
QueueSetContent(stack->txQueue, 3ul, content);
|
|
break;
|
|
case 6:
|
|
content = 0x00000000ul;
|
|
crc = Crc32(content, crc);
|
|
QueueSetContent(stack->txQueue, 2ul, content);
|
|
content = ((uint32_t) data) << 8;
|
|
crc = Crc32(content, crc);
|
|
QueueSetContent(stack->txQueue, 3ul, content);
|
|
break;
|
|
default:
|
|
/* LSB byte. */
|
|
content = 0x00000000ul;
|
|
crc = Crc32(content, crc);
|
|
QueueSetContent(stack->txQueue, 2ul, content);
|
|
content = ((uint32_t) data);
|
|
crc = Crc32(content, crc);
|
|
QueueSetContent(stack->txQueue, 3ul, content);
|
|
break;
|
|
}
|
|
|
|
/* crc(15:0)|pad(15:0) */
|
|
content = ((uint32_t) crc) << 16;
|
|
QueueSetContent(stack->txQueue, 4ul, content);
|
|
|
|
/* Set the size of the packet and place it in the queue. */
|
|
QueueSetSize(stack->txQueue, 5ul);
|
|
stack->txQueue = QueueEnqueue(stack->txQueue);
|
|
}
|
|
|
|
|
|
uint8_t RIO_readResponseDone8( RioStack_t *stack )
|
|
{
|
|
uint8_t returnValue;
|
|
uint32_t readData;
|
|
|
|
|
|
ASSERT(!QueueEmpty(stack->rxQueue), "Reading from empty reception queue.");
|
|
|
|
/* Since there is no way of knowing where the byte will be placed,
|
|
OR all bytes in the reply and return it. */
|
|
readData = QueueGetFrontContent(stack->rxQueue, 2ul);
|
|
returnValue = (uint8_t) (readData >> 24);
|
|
returnValue |= (uint8_t) (readData >> 16);
|
|
returnValue |= (uint8_t) (readData >> 8);
|
|
returnValue |= (uint8_t) (readData);
|
|
readData = QueueGetFrontContent(stack->rxQueue, 3ul);
|
|
returnValue |= (uint8_t) (readData >> 24);
|
|
returnValue |= (uint8_t) (readData >> 16);
|
|
returnValue |= (uint8_t) (readData >> 8);
|
|
returnValue |= (uint8_t) (readData);
|
|
|
|
return returnValue;
|
|
}
|
|
|
|
|
|
|
|
/*******************************************************************************
|
|
* Local functions
|
|
*******************************************************************************/
|
|
|
|
|
|
static void handleStatus(RioStack_t *stack, const uint8_t ackId, const uint8_t bufferStatus)
|
|
{
|
|
/* Update the buffer status of the link partner. */
|
|
(void) ackId;
|
|
stack->txBufferStatus = bufferStatus;
|
|
}
|
|
|
|
|
|
static void handlePacketAccepted(RioStack_t *stack, const uint8_t ackId, const uint8_t bufferStatus)
|
|
{
|
|
/* Check if an acknowledge is expected and that it is for a transmitted packet. */
|
|
if((stack->txAckId != stack->txAckIdWindow) && (ackId == stack->txAckId))
|
|
{
|
|
DEBUG_FRAMING_TX("ack=%i", ackId);
|
|
/* Acknowledge for a recently transmitted packet received. */
|
|
/* Remove the packet from the outbound queue and restart the transmission for
|
|
a new packet. */
|
|
stack->txQueue = QueueDequeue(stack->txQueue);
|
|
stack->txAckId = ACKID_INC(stack->txAckId);
|
|
stack->statusOutboundPacketComplete++;
|
|
}
|
|
else
|
|
{
|
|
DEBUG_FRAMING_TX("*ack=%i", ackId);
|
|
/* Acknowledge for an unexpected ackId or not waiting for an acknowledge. */
|
|
/* Link protocol violation. Discard the symbol and enter the output-error-stopped state. */
|
|
stack->txState = TX_STATE_OUTPUT_ERROR_STOPPED;
|
|
stack->txCounter = 0u;
|
|
stack->statusOutboundErrorPacketAccepted++;
|
|
DEBUG_STATE("tx:error-stopped");
|
|
}
|
|
|
|
/* Update the buffer status of the link partner. */
|
|
stack->txBufferStatus = bufferStatus;
|
|
}
|
|
|
|
|
|
static void handlePacketRetry(RioStack_t *stack, const uint8_t ackId, const uint8_t bufferStatus)
|
|
{
|
|
/* Check if the retried packet ackId is acceptable. */
|
|
if(ackId == stack->txAckId)
|
|
{
|
|
DEBUG_FRAMING_TX("retry=%u", ackId);
|
|
/* The request for retry is for the current packet. */
|
|
/* Force the transmitter to send a RESTART-FROM-RETRY symbol. */
|
|
stack->txState = TX_STATE_OUTPUT_RETRY_STOPPED;
|
|
stack->statusOutboundPacketRetry++;
|
|
DEBUG_STATE("tx:retry-stopped");
|
|
}
|
|
else
|
|
{
|
|
DEBUG_FRAMING_TX("*retry=%u %u", ackId, stack->txAckId);
|
|
/* Link protocol violation. Discard the symbol and enter the output-error-stopped state. */
|
|
stack->txState = TX_STATE_OUTPUT_ERROR_STOPPED;
|
|
stack->txCounter = 0u;
|
|
stack->statusOutboundErrorPacketRetry++;
|
|
DEBUG_STATE("tx:error-stopped");
|
|
}
|
|
|
|
/* Update the buffer status of the link partner. */
|
|
stack->txBufferStatus = bufferStatus;
|
|
}
|
|
|
|
|
|
static void handlePacketNotAccepted(RioStack_t *stack, const uint8_t arbitrary, const uint8_t cause)
|
|
{
|
|
(void) arbitrary;
|
|
|
|
/* Force the transmitter to enter output-error-stopped state. */
|
|
stack->txState = TX_STATE_OUTPUT_ERROR_STOPPED;
|
|
stack->txCounter = 0u;
|
|
|
|
/* Record the type of error that caused the packet to not being accepted. */
|
|
switch(cause)
|
|
{
|
|
case PACKET_NOT_ACCEPTED_CAUSE_UNEXPECTED_ACKID:
|
|
stack->statusPartnerErrorPacketAckId++;
|
|
break;
|
|
case PACKET_NOT_ACCEPTED_CAUSE_CONTROL_CRC:
|
|
stack->statusPartnerErrorControlCrc++;
|
|
break;
|
|
case PACKET_NOT_ACCEPTED_CAUSE_PACKET_CRC:
|
|
stack->statusPartnerErrorPacketCrc++;
|
|
break;
|
|
case PACKET_NOT_ACCEPTED_CAUSE_ILLEGAL_CHARACTER:
|
|
stack->statusPartnerErrorIllegalCharacter++;
|
|
break;
|
|
default:
|
|
stack->statusPartnerErrorGeneral++;
|
|
break;
|
|
}
|
|
|
|
DEBUG_STATE("tx:error-stopped");
|
|
}
|
|
|
|
|
|
static void handleLinkResponse(RioStack_t *stack, const uint8_t ackId, const uint8_t portStatus)
|
|
{
|
|
uint8_t window;
|
|
uint8_t windowReceived;
|
|
|
|
|
|
(void) portStatus;
|
|
|
|
/* Check if this symbols is expected. */
|
|
if(stack->txState == TX_STATE_OUTPUT_ERROR_STOPPED)
|
|
{
|
|
DEBUG_FRAMING_TX("link-res:%u %u %u", stack->txAckIdWindow, stack->txAckId, ackId);
|
|
|
|
/* Calculate the number of packets that has not received an acknowledge on our side and
|
|
on the link-partner side. */
|
|
window = (stack->txAckIdWindow - stack->txAckId) & 0x1f;
|
|
windowReceived = (ackId - stack->txAckId) & 0x1f;
|
|
|
|
/* Check if the link-partners response is acceptable. */
|
|
if(windowReceived <= window)
|
|
{
|
|
/* A link-response is expected. */
|
|
DEBUG_STATE("tx:recover");
|
|
|
|
/* Remove entries in the queue that the link-partner has sent acknowledges for that has been lost. */
|
|
while(stack->txAckId != ackId)
|
|
{
|
|
stack->txQueue = QueueDequeue(stack->txQueue);
|
|
stack->txAckId = ACKID_INC(stack->txAckId);
|
|
stack->statusOutboundPacketComplete++;
|
|
}
|
|
|
|
/* Set the transmission window to the resend packets that has not been received. */
|
|
stack->txQueue = QueueWindowReset(stack->txQueue);
|
|
stack->txAckIdWindow = ackId;
|
|
stack->txFrameState = TX_FRAME_START;
|
|
|
|
/* Set the transmitter back into normal operation. */
|
|
stack->txState = TX_STATE_LINK_INITIALIZED;
|
|
}
|
|
else
|
|
{
|
|
/* The link-partner response is unacceptable. */
|
|
/* Recovery is not possible. */
|
|
stack->txState = TX_STATE_UNINITIALIZED;
|
|
ASSERT0("Unrecoverable protocol error.");
|
|
}
|
|
}
|
|
else
|
|
{
|
|
/* Not expecting a link-response. */
|
|
/* Just discard this symbol. */
|
|
/* REMARK: Add status counter here??? */
|
|
}
|
|
}
|
|
|
|
|
|
static void handleStartOfPacket(RioStack_t *stack)
|
|
{
|
|
/* Check if a packet is already started. */
|
|
if(stack->rxCounter != 0u)
|
|
{
|
|
/* Packet has already started. */
|
|
/* This indicates an implicit end-of-packet symbol and signals the previous packet as ready. */
|
|
DEBUG_FRAMING_RX("cont=%u", stack->rxAckId);
|
|
|
|
/* Check the packet crc. */
|
|
if(stack->rxCrc == 0x0000u)
|
|
{
|
|
/* The packet has a correct CRC. */
|
|
|
|
/* Check if the packet is long enough to contain a complete packet. */
|
|
if(stack->rxCounter > 3u)
|
|
{
|
|
/* Packet long enough to process. */
|
|
|
|
/* Process the newly received packet and start a new one. */
|
|
handleNewPacketEnd(stack);
|
|
handleNewPacketStart(stack);
|
|
}
|
|
else
|
|
{
|
|
/* The packet has a valid CRC but is too short. */
|
|
/* Packet error. Enter input-error-stopped state. */
|
|
stack->txState = TX_STATE_SEND_PACKET_NOT_ACCEPTED;
|
|
stack->rxState = RX_STATE_INPUT_ERROR_STOPPED;
|
|
stack->rxErrorCause = PACKET_NOT_ACCEPTED_CAUSE_GENERAL;
|
|
stack->statusInboundErrorGeneral++;
|
|
DEBUG_STATE("rx:error-stopped");
|
|
}
|
|
}
|
|
else
|
|
{
|
|
/* The packet has an invalid CRC. */
|
|
/* Packet error. Enter input-error-stopped state. */
|
|
stack->txState = TX_STATE_SEND_PACKET_NOT_ACCEPTED;
|
|
stack->rxState = RX_STATE_INPUT_ERROR_STOPPED;
|
|
stack->rxErrorCause = PACKET_NOT_ACCEPTED_CAUSE_PACKET_CRC;
|
|
stack->statusInboundErrorPacketCrc++;
|
|
DEBUG_STATE("rx:error-stopped");
|
|
}
|
|
}
|
|
else
|
|
{
|
|
/* Packet has not already started. */
|
|
DEBUG_FRAMING_RX("start=%u", stack->rxAckId);
|
|
handleNewPacketStart(stack);
|
|
}
|
|
}
|
|
|
|
|
|
static void handleEndOfPacket(RioStack_t *stack)
|
|
{
|
|
DEBUG_FRAMING_RX("end=%u", stack->rxAckId);
|
|
|
|
/* Check if the CRC is correct. */
|
|
if(stack->rxCrc == 0x0000u)
|
|
{
|
|
/* The packet has a correct CRC. */
|
|
|
|
/* Check if the packet is long enough to contain a complete packet. */
|
|
if(stack->rxCounter > 3u)
|
|
{
|
|
/* Packet long enough to process. */
|
|
|
|
/* Process the newly received packet. */
|
|
handleNewPacketEnd(stack);
|
|
}
|
|
else
|
|
{
|
|
/* The packet has a valid CRC but is too short. */
|
|
/* Packet error. Enter input-error-stopped state. */
|
|
stack->txState = TX_STATE_SEND_PACKET_NOT_ACCEPTED;
|
|
stack->rxState = RX_STATE_INPUT_ERROR_STOPPED;
|
|
stack->rxErrorCause = PACKET_NOT_ACCEPTED_CAUSE_GENERAL;
|
|
stack->statusInboundErrorGeneral++;
|
|
DEBUG_STATE("rx:error-stopped");
|
|
}
|
|
}
|
|
else
|
|
{
|
|
/* The packet has an invalid CRC. */
|
|
/* Packet error. Enter input-error-stopped state. */
|
|
stack->txState = TX_STATE_SEND_PACKET_NOT_ACCEPTED;
|
|
stack->rxState = RX_STATE_INPUT_ERROR_STOPPED;
|
|
stack->rxErrorCause = PACKET_NOT_ACCEPTED_CAUSE_PACKET_CRC;
|
|
stack->statusInboundErrorPacketCrc++;
|
|
DEBUG_STATE("rx:error-stopped");
|
|
}
|
|
}
|
|
|
|
|
|
static void handleNewPacketStart(RioStack_t *stack)
|
|
{
|
|
/* Check if there are buffers available to store the new frame. */
|
|
if (QueueAvailable(stack->rxQueue) > 0u)
|
|
{
|
|
/* There are buffers available to accept the new packet. */
|
|
|
|
/* Update the reception counter to indicate the frame has started. */
|
|
stack->rxCounter = 1;
|
|
}
|
|
else
|
|
{
|
|
/* There are no buffers available. */
|
|
/* Go to input retry stopped state. */
|
|
DEBUG_FRAMING_RX("retry=%u", stack->rxAckId);
|
|
stack->statusInboundPacketRetry++;
|
|
stack->txState = TX_STATE_SEND_PACKET_RETRY;
|
|
stack->rxState = RX_STATE_INPUT_RETRY_STOPPED;
|
|
DEBUG_STATE("rx:retry-stopped");
|
|
}
|
|
}
|
|
|
|
|
|
static void handleNewPacketEnd(RioStack_t *stack)
|
|
{
|
|
uint32_t *packet;
|
|
uint32_t ftype;
|
|
uint32_t transaction;
|
|
|
|
|
|
/* Save the size of the packet. */
|
|
QueueSetSize(stack->rxQueue, (uint32_t)stack->rxCounter - (uint32_t)1ul);
|
|
|
|
/* Get the packet and information about its type. */
|
|
packet = QueueGetBackBuffer(stack->rxQueue);
|
|
ftype = FTYPE_GET(packet);
|
|
transaction = TRANSACTION_GET(packet);
|
|
|
|
#ifdef RIO_TRANSPARENT
|
|
/* Always forward the packet to the top of the stack. */
|
|
stack->rxQueue = QueueEnqueue(stack->rxQueue);
|
|
#else
|
|
/* Check if the packet should be forwarded to the top of the stack. */
|
|
if ((QueueGetBackSize(stack->rxQueue) == MAINTENANCE_TRANSACTION_READ_REQUEST_SIZE) &&
|
|
(ftype == FTYPE_MAINTENANCE) && (transaction == TRANSACTION_MAINT_READ_REQUEST))
|
|
{
|
|
/* Received maintenance read request. */
|
|
/* Send a maintenance read response. This packet is aimed at the stack, it should
|
|
not be forwarded. */
|
|
/* Note that only single word accesses are supported. */
|
|
RIO_sendMaintenanceReadResponse(stack, SRCID_GET(packet),TID_GET(packet), 0xff,
|
|
RIO_readConfig(stack, CONFIG_OFFSET_GET(packet)));
|
|
}
|
|
else if ((QueueGetBackSize(stack->rxQueue) == MAINTENANCE_TRANSACTION_WRITE_REQUEST_SIZE) &&
|
|
(ftype == FTYPE_MAINTENANCE) && (transaction == TRANSACTION_MAINT_WRITE_REQUEST))
|
|
{
|
|
/* Received maintenance write request. */
|
|
/* Send a maintenance write response. This packet is aimed at the stack, it should
|
|
not be forwarded. */
|
|
/* Note that only single word accesses are supported. */
|
|
RIO_writeConfig(stack, CONFIG_OFFSET_GET(packet),
|
|
DOUBLE_WORD_MSB_GET(packet, 0) | DOUBLE_WORD_LSB_GET(packet, 0));
|
|
RIO_sendMaintenanceWriteResponse(stack, SRCID_GET(packet), TID_GET(packet), 0xff);
|
|
}
|
|
else
|
|
{
|
|
/* Forward this packet to the top of the stack. */
|
|
stack->rxQueue = QueueEnqueue(stack->rxQueue);
|
|
}
|
|
#endif
|
|
/* Reset the reception counter. */
|
|
stack->rxCounter = 0u;
|
|
|
|
/* Update the ackId for the receiver. */
|
|
stack->rxAckId = ACKID_INC(stack->rxAckId);
|
|
|
|
/* Update status counter. */
|
|
stack->statusInboundPacketComplete++;
|
|
}
|
|
|
|
|
|
static void handleLinkRequest(RioStack_t *stack, uint8_t cmd)
|
|
{
|
|
/* Check the command of the link-request. */
|
|
if(cmd == LINK_REQUEST_INPUT_STATUS)
|
|
{
|
|
/* Input-status requested. */
|
|
/* Return input port status. */
|
|
|
|
/* Force the transmitter to send a link-response-symbol. */
|
|
stack->txState = TX_STATE_SEND_LINK_RESPONSE;
|
|
}
|
|
else if(cmd == LINK_REQUEST_RESET_DEVICE)
|
|
{
|
|
/* Reset-device requested. */
|
|
/* REMARK: Support this??? */
|
|
}
|
|
else
|
|
{
|
|
/* Unrecognized command. */
|
|
/* Dont do anything. */
|
|
}
|
|
|
|
/* Always cancel an ongoing frame when a link-request has been received. */
|
|
stack->rxCounter = 0;
|
|
|
|
/* Receiving this indicates the link partner having encountered a potential problem. */
|
|
/* Count the number of times this happens. */
|
|
stack->statusPartnerLinkRequest++;
|
|
}
|
|
|
|
|
|
static void sendMaintenanceReadRequest( RioStack_t *stack, const uint16_t destid, const uint16_t srcid, const uint8_t tid,
|
|
const uint8_t hopCount, const uint32_t offset)
|
|
{
|
|
uint32_t content;
|
|
uint16_t crc = 0xffffu;
|
|
|
|
|
|
ASSERT((QueueAvailable(stack->txQueue) > 0u), "Transmission queue packet overflow.");
|
|
|
|
/* ackId(4:0)|0|vc|crf|prio(1:0)|tt(1:0)|ftype(3:0)|destinationId(15:0) */
|
|
/* ackId is set when the packet is transmitted. */
|
|
content = 0x0018ul << 16;
|
|
content |= (uint32_t) destid;
|
|
crc = Crc32(content, crc);
|
|
QueueSetContent(stack->txQueue, 0ul, content);
|
|
|
|
/* sourceId(15:0)|transaction(3:0)|rdsize(3:0)|srcTID(7:0) */
|
|
content = ((uint32_t) srcid) << 16;
|
|
content |= (uint32_t) 0x08ul << 8;
|
|
content |= (uint32_t) tid;
|
|
crc = Crc32(content, crc);
|
|
QueueSetContent(stack->txQueue, 1ul, content);
|
|
|
|
/* hopcount(7:0)|configOffset(20:0)|wdptr|reserved(1:0) */
|
|
content = ((uint32_t) hopCount) << 24;
|
|
content |= offset & (uint32_t) 0x00fffffcul;
|
|
crc = Crc32(content, crc);
|
|
QueueSetContent(stack->txQueue, 2ul, content);
|
|
|
|
/* crc(15:0)|pad(15:0) */
|
|
content = ((uint32_t) crc) << 16;
|
|
QueueSetContent(stack->txQueue, 3ul, content);
|
|
|
|
/* Set the size of the packet and place it in the queue. */
|
|
QueueSetSize(stack->txQueue, 4ul);
|
|
stack->txQueue = QueueEnqueue(stack->txQueue);
|
|
}
|
|
|
|
static void receiveMaintenanceReadRequest( RioStack_t *stack, uint16_t *destid, uint16_t *srcid, uint8_t *tid,
|
|
uint8_t *hopCount, uint32_t *offset)
|
|
{
|
|
uint32_t *packet;
|
|
|
|
|
|
ASSERT(!QueueEmpty(stack->rxQueue), "Reading from empty reception queue.");
|
|
|
|
packet = QueueGetFrontBuffer(stack->rxQueue);
|
|
|
|
*destid = DESTID_GET(packet);
|
|
*srcid = SRCID_GET(packet);
|
|
*tid = TID_GET(packet);
|
|
*hopCount = HOP_GET(packet);
|
|
*offset = CONFIG_OFFSET_GET(packet);
|
|
}
|
|
|
|
static void sendMaintenanceReadResponse( RioStack_t *stack, const uint16_t destid, const uint16_t srcid, const uint8_t tid,
|
|
const uint8_t hopCount, const uint32_t data)
|
|
{
|
|
uint32_t content;
|
|
uint16_t crc = 0xffffu;
|
|
|
|
|
|
/* REMARK: What should we do if there are no buffers available to send the packet... */
|
|
ASSERT((QueueAvailable(stack->txQueue) > 0u), "Transmission queue packet overflow.");
|
|
|
|
/* ackId(4:0)|0|vc|crf|prio(1:0)|tt(1:0)|ftype(3:0)|destinationId(15:0) */
|
|
/* ackId is set when the packet is transmitted. */
|
|
content = (uint32_t)0x0018ul << 16;
|
|
content |= (uint32_t) destid;
|
|
crc = Crc32(content, crc);
|
|
QueueSetContent(stack->txQueue, 0ul, content);
|
|
|
|
/* sourceId(15:0)|transaction(3:0)|rdsize(3:0)|srcTID(7:0) */
|
|
content = (uint32_t) srcid << 16;
|
|
content |= (uint32_t) 0x28ul << 8;
|
|
content |= (uint32_t) tid;
|
|
crc = Crc32(content, crc);
|
|
QueueSetContent(stack->txQueue, 1ul, content);
|
|
|
|
/* hopcount(7:0)|reserved(23:0) */
|
|
content = (uint32_t) (hopCount << 24);
|
|
crc = Crc32(content, crc);
|
|
QueueSetContent(stack->txQueue, 2ul, content);
|
|
|
|
/* double-word 0 */
|
|
/* Send the data in both words since this function cannot know the offset the request was sent to. */
|
|
content = data;
|
|
crc = Crc32(content, crc);
|
|
QueueSetContent(stack->txQueue, 3ul, content);
|
|
content = data;
|
|
crc = Crc32(content, crc);
|
|
QueueSetContent(stack->txQueue, 4ul, content);
|
|
|
|
/* crc(15:0)|pad(15:0) */
|
|
content = (uint32_t)crc << 16;
|
|
QueueSetContent(stack->txQueue, 5ul, content);
|
|
|
|
/* Set the size of the packet and place it in the queue. */
|
|
QueueSetSize(stack->txQueue, 6ul);
|
|
stack->txQueue = QueueEnqueue(stack->txQueue);
|
|
}
|
|
|
|
static void receiveMaintenanceReadResponse( RioStack_t *stack, uint16_t *destid, uint16_t *srcid, uint8_t *tid,
|
|
uint8_t *hopCount, uint32_t *data)
|
|
{
|
|
uint32_t *packet;
|
|
|
|
|
|
ASSERT((data != NULL), "Buffer is not allocated.");
|
|
ASSERT(!QueueEmpty(stack->rxQueue), "Reading from empty reception queue.");
|
|
|
|
packet = QueueGetFrontBuffer(stack->rxQueue);
|
|
|
|
*destid = DESTID_GET(packet);
|
|
*srcid = SRCID_GET(packet);
|
|
*tid = TID_GET(packet);
|
|
*hopCount = HOP_GET(packet);
|
|
*data = DOUBLE_WORD_MSB_GET(packet, 0) | DOUBLE_WORD_LSB_GET(packet, 0);
|
|
}
|
|
|
|
static void sendMaintenanceWriteRequest( RioStack_t *stack, const uint16_t destid, const uint16_t srcid, const uint8_t tid,
|
|
const uint8_t hopCount, const uint32_t offset, const uint32_t data )
|
|
{
|
|
uint32_t content;
|
|
uint16_t crc = 0xffffu;
|
|
|
|
|
|
ASSERT((QueueAvailable(stack->txQueue) > 0u), "Transmission queue packet overflow.");
|
|
|
|
/* ackId(4:0)|0|vc|crf|prio(1:0)|tt(1:0)|ftype(3:0)|destinationId(15:0) */
|
|
/* ackId is set when the packet is transmitted. */
|
|
content = 0x0018ul << 16;
|
|
content |= (uint32_t) destid;
|
|
crc = Crc32(content, crc);
|
|
QueueSetContent(stack->txQueue, 0ul, content);
|
|
|
|
/* sourceId(15:0)|transaction(3:0)|rdsize(3:0)|srcTID(7:0) */
|
|
content = ((uint32_t) srcid) << 16;
|
|
content |= (uint32_t)0x18ul << 8;
|
|
content |= (uint32_t) tid;
|
|
crc = Crc32(content, crc);
|
|
QueueSetContent(stack->txQueue, 1ul, content);
|
|
|
|
/* hopcount(7:0)|configOffset(20:0)|wdptr|reserved(1:0) */
|
|
content = ((uint32_t) hopCount) << 24;
|
|
content |= offset & (uint32_t)0x00fffffcul;
|
|
crc = Crc32(content, crc);
|
|
QueueSetContent(stack->txQueue, 2ul, content);
|
|
|
|
/* double-word 0 */
|
|
/* Note that both words are filled in to avoid looking at the offset. The receiver will not
|
|
look at the other part anyway. The standard does not say anything about the value of the padding. */
|
|
content = data;
|
|
crc = Crc32(content, crc);
|
|
QueueSetContent(stack->txQueue, 3ul, content);
|
|
content = data;
|
|
crc = Crc32(content, crc);
|
|
QueueSetContent(stack->txQueue, 4ul, content);
|
|
|
|
/* crc(15:0)|pad(15:0) */
|
|
content = ((uint32_t) crc) << 16;
|
|
QueueSetContent(stack->txQueue, 5ul, content);
|
|
|
|
/* Set the size of the packet and place it in the queue. */
|
|
QueueSetSize(stack->txQueue, 6ul);
|
|
stack->txQueue = QueueEnqueue(stack->txQueue);
|
|
}
|
|
|
|
static void receiveMaintenanceWriteRequest( RioStack_t *stack, uint16_t *destid, uint16_t *srcid, uint8_t *tid,
|
|
uint8_t *hopCount, uint32_t *offset, uint32_t *data )
|
|
{
|
|
uint32_t *packet;
|
|
|
|
|
|
ASSERT((data != NULL), "Buffer is not allocated.");
|
|
ASSERT(!QueueEmpty(stack->rxQueue), "Reading from empty reception queue.");
|
|
|
|
packet = QueueGetFrontBuffer(stack->rxQueue);
|
|
|
|
*destid = DESTID_GET(packet);
|
|
*srcid = SRCID_GET(packet);
|
|
*tid = TID_GET(packet);
|
|
*hopCount = HOP_GET(packet);
|
|
*offset = CONFIG_OFFSET_GET(packet);
|
|
*data = DOUBLE_WORD_MSB_GET(packet, 0) | DOUBLE_WORD_LSB_GET(packet, 0);
|
|
}
|
|
|
|
static void sendMaintenanceWriteResponse( RioStack_t *stack, const uint16_t destid, const uint16_t srcid, const uint8_t tid,
|
|
const uint8_t hopCount)
|
|
{
|
|
uint32_t content;
|
|
uint16_t crc = 0xffffu;
|
|
|
|
|
|
/* REMARK: What should we do if there are no buffers available to send the packet... */
|
|
ASSERT((QueueAvailable(stack->txQueue) > 0u), "Transmission queue packet overflow.");
|
|
|
|
/* ackId(4:0)|0|vc|crf|prio(1:0)|tt(1:0)|ftype(3:0)|destinationId(15:0) */
|
|
/* ackId is set when the packet is transmitted. */
|
|
content = (uint32_t)0x0018ul << 16;
|
|
content |= (uint32_t) destid;
|
|
crc = Crc32(content, crc);
|
|
QueueSetContent(stack->txQueue, 0ul, content);
|
|
|
|
/* sourceId(15:0)|transaction(3:0)|rdsize(3:0)|srcTID(7:0) */
|
|
content = (uint32_t) srcid << 16;
|
|
content |= (uint32_t)0x38ul << 8;
|
|
content |= (uint32_t) tid;
|
|
crc = Crc32(content, crc);
|
|
QueueSetContent(stack->txQueue, 1ul, content);
|
|
|
|
/* hopcount(7:0)|reserved(23:0) */
|
|
content = hopCount << 24;
|
|
crc = Crc32(content, crc);
|
|
QueueSetContent(stack->txQueue, 2ul, content);
|
|
|
|
/* crc(15:0)|pad(15:0) */
|
|
content = (uint32_t)crc << 16;
|
|
QueueSetContent(stack->txQueue, 3ul, content);
|
|
|
|
/* Set the size of the packet and place it in the queue. */
|
|
QueueSetSize(stack->txQueue, 4ul);
|
|
stack->txQueue = QueueEnqueue(stack->txQueue);
|
|
}
|
|
|
|
static void receiveMaintenanceWriteResponse( RioStack_t *stack, uint16_t *destid, uint16_t *srcid, uint8_t *tid,
|
|
uint8_t *hopCount)
|
|
{
|
|
uint32_t *packet;
|
|
|
|
|
|
ASSERT(!QueueEmpty(stack->rxQueue), "Reading from empty reception queue.");
|
|
|
|
packet = QueueGetFrontBuffer(stack->rxQueue);
|
|
|
|
*destid = DESTID_GET(packet);
|
|
*srcid = SRCID_GET(packet);
|
|
*tid = TID_GET(packet);
|
|
*hopCount = HOP_GET(packet);
|
|
}
|
|
|
|
/* REMARK: Use a packet pointer instead of using the QueueSetContent... */
|
|
static void sendNwrite( RioStack_t *stack, const uint16_t destid, const uint16_t srcid, const uint8_t tid,
|
|
const uint32_t address, const uint16_t bufferSize, const uint8_t *buffer,
|
|
const uint8_t ack)
|
|
{
|
|
uint32_t content;
|
|
uint32_t size;
|
|
uint16_t wrsize = wrsizeGet(address, bufferSize);
|
|
|
|
|
|
ASSERT((QueueAvailable(stack->txQueue) > 0u), "Transmission queue packet overflow.");
|
|
ASSERT((wrsize != 0xffff), "Write access unsupported by protocol.");
|
|
|
|
/* ackId(4:0)|0|vc|crf|prio(1:0)|tt(1:0)|ftype(3:0)|destinationId(15:0) */
|
|
/* ackId is set when the packet is transmitted. */
|
|
content = ((uint32_t)0x0015ul) << 16;
|
|
content |= (uint32_t)destid;
|
|
QueueSetContent(stack->txQueue, 0ul, content);
|
|
|
|
/* sourceId(15:0)|transaction(3:0)|wrsize(3:0)|srcTID(7:0) */
|
|
content = ((uint32_t) srcid) << 16;
|
|
if(ack == 0u)
|
|
{
|
|
/* Send NWRITE. */
|
|
content |= (uint32_t) TRANSACTION_WRITE_NWRITE << 12;
|
|
}
|
|
else
|
|
{
|
|
/* Send NWRITE_R. */
|
|
content |= (uint32_t) TRANSACTION_WRITE_NWRITER << 12;
|
|
}
|
|
content |= (uint32_t) (wrsize & 0x0f00);
|
|
content |= (uint32_t) tid;
|
|
QueueSetContent(stack->txQueue, 1ul, content);
|
|
|
|
/* address(28:0)|wdptr|xamsbs(1:0) */
|
|
/* wrsize also contains wdptr in the lower nibble. */
|
|
/* REMARK: Note that xamsbs cannot be used if the address is a word. If the 2 msb bits in the
|
|
34-bit address should be used, another mechanism to set it should be used. */
|
|
content = (address & 0xfffffff8ul);
|
|
content |= ((uint32_t) (wrsize & 0x000f)) << 2;
|
|
QueueSetContent(stack->txQueue, 2ul, content);
|
|
|
|
/* Place data buffer into the payload of the packet. */
|
|
size = setPacketPayload(QueueGetBackBuffer(stack->txQueue), 12, address & 0x7, bufferSize, buffer);
|
|
|
|
/* Set the size of the packet and place it in the queue. */
|
|
QueueSetSize(stack->txQueue, size+1);
|
|
stack->txQueue = QueueEnqueue(stack->txQueue);
|
|
}
|
|
|
|
static uint16_t receiveNwrite( RioStack_t *stack, uint16_t *destid, uint16_t *srcid, uint8_t *tid,
|
|
uint32_t *address, const uint16_t dataLength, uint8_t *data )
|
|
{
|
|
uint32_t *packet;
|
|
uint8_t offset;
|
|
uint16_t size;
|
|
uint8_t wrsize;
|
|
uint8_t wdptr;
|
|
|
|
|
|
ASSERT((data != NULL), "Buffer is not allocated.");
|
|
ASSERT(!QueueEmpty(stack->rxQueue), "Reading from empty reception queue.");
|
|
|
|
packet = QueueGetFrontBuffer(stack->rxQueue);
|
|
|
|
wrsize = WRSIZE_GET(packet);
|
|
wdptr = WDPTR_GET(packet);
|
|
wrsizeToOffset(wrsize, wdptr, &offset, &size);
|
|
|
|
*destid = DESTID_GET(packet);
|
|
*srcid = SRCID_GET(packet);
|
|
*tid = TID_GET(packet);
|
|
*address = ADDRESS_GET(packet) | offset;
|
|
|
|
if(size > 16)
|
|
{
|
|
/* Remove header and crc from the size count. */
|
|
size = ((QueueGetFrontSize(stack->rxQueue)-4) * 4);
|
|
}
|
|
|
|
/* Check if there is enough room in the receiving buffer. */
|
|
if(size <= dataLength)
|
|
{
|
|
return getPacketPayload(packet, 12, offset, size, data);
|
|
}
|
|
else
|
|
{
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
static void sendNread( RioStack_t *stack, const uint16_t destid, const uint16_t srcid, const uint8_t tid,
|
|
const uint32_t address, const uint16_t dataLength)
|
|
{
|
|
uint32_t content;
|
|
uint16_t crc = 0xffffu;
|
|
uint16_t rdsize = rdsizeGet(address, dataLength);
|
|
|
|
|
|
ASSERT((QueueAvailable(stack->txQueue) > 0u), "Transmission queue packet overflow.");
|
|
ASSERT((rdsize != 0xffff), "Read access unsupported by protocol.");
|
|
|
|
/* ackId(4:0)|0|vc|crf|prio(1:0)|tt(1:0)|ftype(3:0)|destinationId(15:0) */
|
|
/* ackId is set when the packet is transmitted. */
|
|
content = ((uint32_t) 0x0012ul) << 16;
|
|
content |= (uint32_t) destid;
|
|
crc = Crc32(content, crc);
|
|
QueueSetContent(stack->txQueue, 0ul, content);
|
|
|
|
/* sourceId(15:0)|transaction(3:0)|rdsize(3:0)|srcTID(7:0) */
|
|
content = ((uint32_t) srcid) << 16;
|
|
content |= ((uint32_t) TRANSACTION_REQUEST_NREAD) << 12;
|
|
content |= (uint32_t) (rdsize & 0x0f00);
|
|
content |= (uint32_t) tid;
|
|
crc = Crc32(content, crc);
|
|
QueueSetContent(stack->txQueue, 1ul, content);
|
|
|
|
/* address(28:0)|wdptr|xamsbs(1:0) */
|
|
/* rdsize also contains wdptr in the lower nibble. */
|
|
/* REMARK: Note that xamsbs cannot be used if the address is a word. If the 2 msb bits in the
|
|
34-bit address should be used, another mechanism to set it should be used. */
|
|
content = address & 0xfffffff8ul;
|
|
content |= ((uint32_t) (rdsize & 0x000f)) << 2;
|
|
crc = Crc32(content, crc);
|
|
QueueSetContent(stack->txQueue, 2ul, content);
|
|
|
|
/* crc(15:0)|pad(15:0) */
|
|
content = ((uint32_t) crc) << 16;
|
|
QueueSetContent(stack->txQueue, 3ul, content);
|
|
|
|
/* Set the size of the packet and place it in the queue. */
|
|
QueueSetSize(stack->txQueue, 4ul);
|
|
stack->txQueue = QueueEnqueue(stack->txQueue);
|
|
}
|
|
|
|
static void receiveNread( RioStack_t *stack, uint16_t *destid, uint16_t *srcid, uint8_t *tid,
|
|
uint32_t *address, uint16_t *dataLength)
|
|
{
|
|
uint32_t *packet;
|
|
uint8_t offset;
|
|
uint16_t size;
|
|
uint8_t rdsize;
|
|
uint8_t wdptr;
|
|
|
|
|
|
ASSERT(!QueueEmpty(stack->rxQueue), "Reading from empty reception queue.");
|
|
|
|
packet = QueueGetFrontBuffer(stack->rxQueue);
|
|
|
|
rdsize = WRSIZE_GET(packet);
|
|
wdptr = WDPTR_GET(packet);
|
|
rdsizeToOffset(rdsize, wdptr, &offset, &size);
|
|
|
|
*destid = DESTID_GET(packet);
|
|
*srcid = SRCID_GET(packet);
|
|
*tid = TID_GET(packet);
|
|
*address = ADDRESS_GET(packet) | offset;
|
|
*dataLength = size;
|
|
}
|
|
|
|
static void sendResponseDonePayload( RioStack_t *stack, const uint16_t destid, const uint16_t srcid, const uint8_t tid,
|
|
const uint32_t address, const uint16_t bufferSize, const uint8_t *buffer)
|
|
{
|
|
uint32_t content;
|
|
uint32_t size;
|
|
|
|
|
|
ASSERT((buffer != NULL), "Buffer is not allocated.");
|
|
ASSERT((QueueAvailable(stack->txQueue) > 0u), "Transmission queue packet overflow.");
|
|
|
|
/* ackId(4:0)|0|vc|crf|prio(1:0)|tt(1:0)|ftype(3:0)|destinationId(15:0) */
|
|
/* ackId is set when the packet is transmitted. */
|
|
content = 0x001dul << 16;
|
|
content |= (uint32_t) destid;
|
|
QueueSetContent(stack->txQueue, 0ul, content);
|
|
|
|
/* sourceId(15:0)|transaction(3:0)|status(3:0)|targetTID(7:0) */
|
|
content = ((uint32_t) srcid) << 16;
|
|
content |= ((uint32_t) TRANSACTION_RESPONSE_WITH_PAYLOAD) << 12;
|
|
content |= (uint32_t) tid;
|
|
QueueSetContent(stack->txQueue, 1ul, content);
|
|
|
|
/* Place data buffer into the payload of the packet. */
|
|
size = setPacketPayload(QueueGetBackBuffer(stack->txQueue), 8, address & 0x7, bufferSize, buffer);
|
|
|
|
/* Set the size of the packet and place it in the queue. */
|
|
QueueSetSize(stack->txQueue, size+1);
|
|
stack->txQueue = QueueEnqueue(stack->txQueue);
|
|
}
|
|
|
|
|
|
static uint16_t receiveResponseDonePayload( RioStack_t *stack, uint16_t *destid, uint16_t *srcid, uint8_t *tid,
|
|
const uint32_t address, const uint16_t dataLength, uint8_t *data )
|
|
{
|
|
uint32_t *packet;
|
|
|
|
|
|
ASSERT((data != NULL), "Buffer is not allocated.");
|
|
ASSERT(!QueueEmpty(stack->rxQueue), "Reading from empty reception queue.");
|
|
|
|
packet = QueueGetFrontBuffer(stack->rxQueue);
|
|
|
|
*destid = DESTID_GET(packet);
|
|
*srcid = SRCID_GET(packet);
|
|
*tid = TID_GET(packet);
|
|
|
|
return getPacketPayload(packet, 8, address & 0x7, dataLength, data);
|
|
}
|
|
|
|
|
|
static void sendResponse( RioStack_t *stack, const uint16_t destid, const uint16_t srcid, const uint8_t tid,
|
|
const uint8_t status)
|
|
{
|
|
uint32_t content;
|
|
uint16_t crc = 0xffffu;
|
|
|
|
|
|
ASSERT((QueueAvailable(stack->txQueue) > 0u), "Transmission queue packet overflow.");
|
|
|
|
/* ackId(4:0)|0|vc|crf|prio(1:0)|tt(1:0)|ftype(3:0)|destinationId(15:0) */
|
|
/* ackId is set when the packet is transmitted. */
|
|
content = (uint32_t)0x001dul << 16;
|
|
content |= destid;
|
|
crc = Crc32(content, crc);
|
|
QueueSetContent(stack->txQueue, 0ul, content);
|
|
|
|
/* sourceId(15:0)|transaction(3:0)|status(3:0)|targetTID(7:0) */
|
|
content = (uint32_t)srcid << 16;
|
|
content |= ((uint32_t)status & (uint32_t)0x0ful) << 8;
|
|
content |= tid;
|
|
crc = Crc32(content, crc);
|
|
QueueSetContent(stack->txQueue, 1ul, content);
|
|
|
|
/* crc(15:0)|pad(15:0) */
|
|
content = (uint32_t)crc << 16;
|
|
QueueSetContent(stack->txQueue, 2ul, content);
|
|
|
|
/* Set the size of the packet and place it in the queue. */
|
|
QueueSetSize(stack->txQueue, 3ul);
|
|
stack->txQueue = QueueEnqueue(stack->txQueue);
|
|
}
|
|
|
|
|
|
static void receiveResponse( RioStack_t *stack, uint16_t *destid, uint16_t *srcid, uint8_t *tid)
|
|
{
|
|
uint32_t *packet;
|
|
|
|
|
|
ASSERT(!QueueEmpty(stack->rxQueue), "Reading from empty reception queue.");
|
|
|
|
packet = QueueGetFrontBuffer(stack->rxQueue);
|
|
|
|
*destid = DESTID_GET(packet);
|
|
*srcid = SRCID_GET(packet);
|
|
*tid = TID_GET(packet);
|
|
}
|
|
|
|
|
|
static void sendDoorbell( RioStack_t *stack, const uint16_t destid, const uint16_t srcid, const uint8_t tid,
|
|
const uint16_t info )
|
|
{
|
|
uint32_t content;
|
|
uint16_t crc;
|
|
|
|
|
|
ASSERT((QueueAvailable(stack->txQueue) > 0u), "Transmission queue packet overflow.");
|
|
|
|
/* ackId(4:0)|0|vc|crf|prio(1:0)|tt(1:0)|ftype(3:0)|destinationId(15:0) */
|
|
/* ackId is set when the packet is transmitted. */
|
|
content = 0x001aul << 16;
|
|
content |= (uint32_t) destid;
|
|
crc = Crc32(content, 0xffffu);
|
|
QueueSetContent(stack->txQueue, 0ul, content);
|
|
|
|
/* sourceId(15:0)|rsrv(7:0)|srcTID(7:0) */
|
|
content = ((uint32_t) srcid) << 16;
|
|
content |= (uint32_t) tid;
|
|
crc = Crc32(content, crc);
|
|
QueueSetContent(stack->txQueue, 1ul, content);
|
|
|
|
/* infoMSB(7:0)|infoLSB(7:0)|crc(15:0) */
|
|
content = ((uint32_t) info) << 16;
|
|
crc = Crc16(info, crc);
|
|
content |= crc;
|
|
QueueSetContent(stack->txQueue, 2ul, content);
|
|
|
|
/* Set the size of the packet and place it in the queue. */
|
|
QueueSetSize(stack->txQueue, 3ul);
|
|
stack->txQueue = QueueEnqueue(stack->txQueue);
|
|
}
|
|
|
|
|
|
static void receiveDoorbell( RioStack_t *stack, uint16_t *destid, uint16_t *srcid, uint8_t *tid,
|
|
uint16_t *info)
|
|
{
|
|
uint32_t *packet;
|
|
|
|
|
|
ASSERT(!QueueEmpty(stack->rxQueue), "Reading from empty reception queue.");
|
|
|
|
packet = QueueGetFrontBuffer(stack->rxQueue);
|
|
|
|
*destid = DESTID_GET(packet);
|
|
*srcid = SRCID_GET(packet);
|
|
*tid = TID_GET(packet);
|
|
*info = INFO_GET(packet);
|
|
}
|
|
|
|
|
|
static void sendMessage( RioStack_t *stack, const uint16_t destid, const uint16_t srcid, const uint8_t mailbox,
|
|
const uint16_t bufferSize, const uint8_t* bufferData)
|
|
{
|
|
uint32_t content;
|
|
uint32_t size;
|
|
|
|
|
|
ASSERT((QueueAvailable(stack->txQueue) > 0u), "Transmission queue packet overflow.");
|
|
ASSERT((bufferSize <= 256), "Packet sizes larger than 256 are currently unsupported.");
|
|
|
|
/* ackId(4:0)|0|vc|crf|prio(1:0)|tt(1:0)|ftype(3:0)|destinationId(15:0) */
|
|
/* ackId is set when the packet is transmitted. */
|
|
content = ((uint32_t) 0x001bul) << 16;
|
|
content |= (uint32_t) destid;
|
|
QueueSetContent(stack->txQueue, 0ul, content);
|
|
|
|
/* sourceId(15:0)|msglen(3:0)|ssize(3:0)|letter(1:0|mbox(1:0)|xmbox(3:0) */
|
|
content = ((uint32_t) srcid) << 16;
|
|
if(bufferSize <= 8u)
|
|
{
|
|
content |= ((uint32_t) 0x09ul) << 8;
|
|
}
|
|
else if(bufferSize <= 16u)
|
|
{
|
|
content |= ((uint32_t) 0x0aul) << 8;
|
|
}
|
|
else if(bufferSize <= 32u)
|
|
{
|
|
content |= ((uint32_t) 0x0bul) << 8;
|
|
}
|
|
else if(bufferSize <= 64u)
|
|
{
|
|
content |= ((uint32_t) 0x0cul) << 8;
|
|
}
|
|
else if(bufferSize <= 128u)
|
|
{
|
|
content |= ((uint32_t) 0x0dul) << 8;
|
|
}
|
|
else
|
|
{
|
|
content |= ((uint32_t) 0x0eul) << 8;
|
|
}
|
|
content |= ((uint32_t)mailbox & (uint32_t)0xfu) << 4;
|
|
content |= ((uint32_t)mailbox) >> 4;
|
|
QueueSetContent(stack->txQueue, 1ul, content);
|
|
|
|
/* Place data buffer into the payload of the packet. */
|
|
size = setPacketPayload(QueueGetBackBuffer(stack->txQueue), 8, 0, bufferSize, bufferData);
|
|
|
|
/* Set the size of the packet and place it in the queue. */
|
|
QueueSetSize(stack->txQueue, size+1);
|
|
stack->txQueue = QueueEnqueue(stack->txQueue);
|
|
}
|
|
|
|
static uint16_t receiveMessage( RioStack_t *stack, uint16_t *destid, uint16_t *srcid, uint8_t *mailbox,
|
|
const uint16_t dataLength, uint8_t *data )
|
|
{
|
|
uint32_t *packet;
|
|
uint32_t size;
|
|
|
|
|
|
ASSERT((data != NULL), "Buffer is not allocated.");
|
|
ASSERT(!QueueEmpty(stack->rxQueue), "Reading from empty reception queue.");
|
|
|
|
/* Get a pointer to the packet. */
|
|
packet = QueueGetFrontBuffer(stack->rxQueue);
|
|
|
|
/* The higher mailbox numbers are used with messages that cannot be multi-packets. */
|
|
*destid = DESTID_GET(packet);
|
|
*srcid = SRCID_GET(packet);
|
|
*mailbox = XMBOX_GET(packet);
|
|
*mailbox <<= 2;
|
|
*mailbox |= LETTER_GET(packet);
|
|
*mailbox <<= 2;
|
|
*mailbox |= MBOX_GET(packet);
|
|
|
|
/* Calculate the number of bytes to transfer. */
|
|
/* Remove the header and crc from the size count. */
|
|
size = (QueueGetFrontSize(stack->rxQueue)-3) * 4;
|
|
|
|
/* Check if there is enough room in the receiving buffer. */
|
|
if(size <= dataLength)
|
|
{
|
|
return getPacketPayload(packet, 8, 0, size, data);
|
|
}
|
|
else
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
}
|
|
|
|
static void sendMessageResponse( RioStack_t *stack, const uint16_t destid, const uint16_t srcid, const uint8_t mailbox,
|
|
const uint8_t status)
|
|
{
|
|
uint32_t content;
|
|
uint16_t crc = 0xffffu;
|
|
|
|
|
|
ASSERT((QueueAvailable(stack->txQueue) > 0u), "Transmission queue packet overflow.");
|
|
|
|
/* ackId(4:0)|0|vc|crf|prio(1:0)|tt(1:0)|ftype(3:0)|destinationId(15:0) */
|
|
/* ackId is set when the packet is transmitted. */
|
|
content = (uint32_t)0x001dul << 16;
|
|
content |= destid;
|
|
crc = Crc32(content, crc);
|
|
QueueSetContent(stack->txQueue, 0ul, content);
|
|
|
|
/* sourceId(15:0)|transaction(3:0)|status(3:0)|letter(1:0|mbox(1:0)|msgseg(3:0) */
|
|
content = (uint32_t)srcid << 16;
|
|
content |= (uint32_t)0x1ul << 12;
|
|
content |= ((uint32_t)status & (uint32_t)0xful) << 8;
|
|
content |= ((uint32_t)mailbox & (uint32_t)0xful) << 4;
|
|
content |= ((uint32_t)mailbox) >> 4;
|
|
crc = Crc32(content, crc);
|
|
QueueSetContent(stack->txQueue, 1ul, content);
|
|
|
|
/* crc(15:0)|pad(15:0) */
|
|
content = (uint32_t)crc << 16;
|
|
QueueSetContent(stack->txQueue, 2ul, content);
|
|
|
|
/* Set the size of the packet and place it in the queue. */
|
|
QueueSetSize(stack->txQueue, 3ul);
|
|
stack->txQueue = QueueEnqueue(stack->txQueue);
|
|
}
|
|
|
|
static void receiveMessageResponse( RioStack_t *stack, uint16_t *destid, uint16_t *srcid, uint8_t *mailbox)
|
|
{
|
|
uint32_t *packet;
|
|
|
|
|
|
ASSERT(!QueueEmpty(stack->rxQueue), "Reading from empty reception queue.");
|
|
|
|
packet = QueueGetFrontBuffer(stack->rxQueue);
|
|
|
|
*destid = DESTID_GET(packet);
|
|
*srcid = SRCID_GET(packet);
|
|
*mailbox = XMBOX_GET(packet);
|
|
*mailbox <<= 2;
|
|
*mailbox |= LETTER_GET(packet);
|
|
*mailbox <<= 2;
|
|
*mailbox |= MBOX_GET(packet);
|
|
}
|
|
|
|
|
|
static uint16_t getPacketPayload(uint32_t *packet, const uint16_t payloadOffset, const uint16_t dataOffset,
|
|
const uint16_t dataSize, uint8_t *data)
|
|
{
|
|
uint32_t content = 0;
|
|
uint16_t packetIndex;
|
|
uint16_t payloadIndex;
|
|
uint16_t dataIndex;
|
|
|
|
|
|
/* Move bytes from inbound packet queue into the user buffer. */
|
|
/* Long packets contain a CRC in byte 80-81, this is removed when the buffer
|
|
is copied. */
|
|
packetIndex = payloadOffset;
|
|
payloadIndex = 0;
|
|
dataIndex = 0;
|
|
while(dataIndex < dataSize)
|
|
{
|
|
/* Check if a new word should be read from the inbound queue. */
|
|
if((packetIndex & 0x3) == 0)
|
|
{
|
|
/* Get a new word. */
|
|
content = packet[packetIndex>>2];
|
|
}
|
|
else
|
|
{
|
|
/* Update the current word. Remove the MSB, it has already be moved
|
|
to the user buffer. */
|
|
content <<= 8;
|
|
}
|
|
|
|
/* Check if the current byte is CRC. */
|
|
if((packetIndex != 80) && (packetIndex != 81) && (payloadIndex >= dataOffset))
|
|
{
|
|
/* Not CRC. */
|
|
/* Move the byte to the user buffer. */
|
|
data[dataIndex++] = (content >> 24);
|
|
}
|
|
|
|
/* Increment to the next position in the packet. */
|
|
packetIndex++;
|
|
payloadIndex++;
|
|
}
|
|
|
|
return dataIndex;
|
|
}
|
|
|
|
|
|
static uint16_t setPacketPayload(uint32_t *packet, const uint16_t payloadOffset, const uint16_t dataOffset,
|
|
const uint16_t dataSize, const uint8_t *data)
|
|
{
|
|
uint16_t crc = 0xffffu;
|
|
uint32_t content = 0;
|
|
uint16_t packetIndex;
|
|
uint16_t payloadIndex;
|
|
uint16_t dataIndex;
|
|
|
|
|
|
/***************************************************
|
|
* Calculate the CRC for the packet header.
|
|
***************************************************/
|
|
for(packetIndex = 0; packetIndex < payloadOffset; packetIndex+=4)
|
|
{
|
|
crc = Crc32(packet[packetIndex>>2], crc);
|
|
}
|
|
|
|
/***************************************************
|
|
* Pad the data before the actual data is written.
|
|
***************************************************/
|
|
payloadIndex = 0;
|
|
while(payloadIndex < dataOffset)
|
|
{
|
|
content <<= 8;
|
|
|
|
if((packetIndex & 0x3) == 3)
|
|
{
|
|
crc = Crc32(content, crc);
|
|
packet[packetIndex>>2] = content;
|
|
}
|
|
|
|
payloadIndex++;
|
|
packetIndex++;
|
|
}
|
|
|
|
/***************************************************
|
|
* Write content and any embedded CRC.
|
|
***************************************************/
|
|
dataIndex = 0;
|
|
while(dataIndex < dataSize)
|
|
{
|
|
content <<= 8;
|
|
|
|
/* Check if CRC or content should be entered into the packet. */
|
|
if(packetIndex == 80)
|
|
{
|
|
/* CRC MSB. */
|
|
content |= crc >> 8;
|
|
}
|
|
else if(packetIndex == 81)
|
|
{
|
|
/* CRC LSB. */
|
|
content |= crc & 0xff;
|
|
}
|
|
else
|
|
{
|
|
/* Data content. */
|
|
content |= data[dataIndex++];
|
|
payloadIndex++;
|
|
}
|
|
|
|
if((packetIndex & 0x3) == 3)
|
|
{
|
|
crc = Crc32(content, crc);
|
|
packet[packetIndex>>2] = content;
|
|
}
|
|
|
|
packetIndex++;
|
|
}
|
|
|
|
/***************************************************
|
|
* Pad the data to an even double word.
|
|
***************************************************/
|
|
while((payloadIndex & 0x7) != 0)
|
|
{
|
|
content <<= 8;
|
|
|
|
if((packetIndex & 0x3) == 3)
|
|
{
|
|
crc = Crc32(content, crc);
|
|
packet[packetIndex>>2] = content;
|
|
}
|
|
|
|
packetIndex++;
|
|
payloadIndex++;
|
|
}
|
|
|
|
/***************************************************
|
|
* Write the CRC into the packet.
|
|
***************************************************/
|
|
if((packetIndex & 0x3) == 0)
|
|
{
|
|
/* crc(15:0)|pad(15:0) */
|
|
content = ((uint32_t) crc) << 16;
|
|
}
|
|
else
|
|
{
|
|
/* double-wordN-LSB|crc(15:0) */
|
|
content &= 0x0000ffff;
|
|
crc = Crc16(content, crc);
|
|
content <<= 16;
|
|
content |= crc;
|
|
}
|
|
packet[packetIndex>>2] = content;
|
|
|
|
return (packetIndex>>2);
|
|
}
|
|
|
|
|
|
/* \note See the RapidIO standard part1 table 4-4 for details about
|
|
* {address, size}->{wdptr, wrsize} mapping.
|
|
*/
|
|
static uint16_t rdsizeGet(const uint32_t address, const uint16_t size)
|
|
{
|
|
uint8_t wdptr;
|
|
uint8_t rdsize;
|
|
|
|
|
|
switch(size/8)
|
|
{
|
|
case 0:
|
|
/**************************************************************
|
|
* Sub double-word access.
|
|
**************************************************************/
|
|
/* REMARK: The same code as in wrsizeGet for sub
|
|
double-word... use it instead??? */
|
|
switch(size%8)
|
|
{
|
|
case 0:
|
|
/* Not supported by protocol. */
|
|
wdptr = 0xff;
|
|
rdsize = 0xff;
|
|
break;
|
|
case 1:
|
|
/* Reading one byte. */
|
|
/* Any address is allowed. */
|
|
wdptr = (address >> 2) & 0x1;
|
|
rdsize = address & 0x3;
|
|
break;
|
|
case 2:
|
|
/* Reading two bytes. */
|
|
/* Address 0, 2, 4, 6 are valid. */
|
|
if((address & 0x1) == 0)
|
|
{
|
|
wdptr = (address >> 2) & 0x1;
|
|
rdsize = (address & 0x7) | 0x4;
|
|
}
|
|
else
|
|
{
|
|
/* Not supported by protocol. */
|
|
wdptr = 0xff;
|
|
rdsize = 0xff;
|
|
}
|
|
break;
|
|
case 3:
|
|
/* Reading 3 bytes. */
|
|
/* Address 0 and 5 are valid. */
|
|
if(((address & 0x7) == 0) ||
|
|
((address & 0x7) == 5))
|
|
{
|
|
wdptr = (address >> 2) & 0x1;
|
|
rdsize = 0x5ul;
|
|
}
|
|
else
|
|
{
|
|
/* Not supported by protocol. */
|
|
wdptr = 0xff;
|
|
rdsize = 0xff;
|
|
}
|
|
break;
|
|
case 4:
|
|
/* Reading 4 bytes. */
|
|
/* Address 0 and 4 are valid. */
|
|
if(((address & 0x7) == 0) ||
|
|
((address & 0x7) == 4))
|
|
{
|
|
wdptr = (address >> 2) & 0x1;
|
|
rdsize = 0x8ul;
|
|
}
|
|
else
|
|
{
|
|
/* Not supported by protocol. */
|
|
wdptr = 0xff;
|
|
rdsize = 0xff;
|
|
}
|
|
break;
|
|
case 5:
|
|
/* Reading 5 bytes. */
|
|
/* Address 0 and 3 are valid. */
|
|
if(((address & 0x7) == 0) ||
|
|
((address & 0x7) == 3))
|
|
{
|
|
wdptr = (address >> 1) & 0x1;
|
|
rdsize = 0x7ul;
|
|
}
|
|
else
|
|
{
|
|
/* Not supported by protocol. */
|
|
wdptr = 0xff;
|
|
rdsize = 0xff;
|
|
}
|
|
break;
|
|
case 6:
|
|
/* Reading 6 bytes. */
|
|
/* Addresses 0 and 2 are valid. */
|
|
if(((address & 0x7) == 0) ||
|
|
((address & 0x7) == 2))
|
|
{
|
|
wdptr = (address >> 1) & 0x1;
|
|
rdsize = 0x9ul;
|
|
}
|
|
else
|
|
{
|
|
/* Not supported by protocol. */
|
|
wdptr = 0xff;
|
|
rdsize = 0xff;
|
|
}
|
|
break;
|
|
default:
|
|
/* Reading 7 bytes. */
|
|
/* Addresses 0 and 1 are valid. */
|
|
if(((address & 0x7) == 0) ||
|
|
((address & 0x7) == 1))
|
|
{
|
|
wdptr = address & 0x1;
|
|
rdsize = 0xaul;
|
|
}
|
|
else
|
|
{
|
|
/* Not supported by protocol. */
|
|
wdptr = 0xff;
|
|
rdsize = 0xff;
|
|
}
|
|
break;
|
|
}
|
|
break;
|
|
case 1:
|
|
/* Reading 8 bytes. */
|
|
/* Only even double-word address are valid. */
|
|
if((address % 8) == 0)
|
|
{
|
|
wdptr = 0;
|
|
rdsize = 0xbul;
|
|
}
|
|
else
|
|
{
|
|
/* Not supported by protocol. */
|
|
wdptr = 0xff;
|
|
rdsize = 0xff;
|
|
}
|
|
break;
|
|
case 2:
|
|
/* Reading 16 bytes max. */
|
|
/* Only even double-word address are valid. */
|
|
if((address % 8) == 0)
|
|
{
|
|
wdptr = 1;
|
|
rdsize = 0xbul;
|
|
}
|
|
else
|
|
{
|
|
/* Not supported by protocol. */
|
|
wdptr = 0xff;
|
|
rdsize = 0xff;
|
|
}
|
|
break;
|
|
case 3:
|
|
/* Not supported by protocol. */
|
|
wdptr = 0xff;
|
|
rdsize = 0xff;
|
|
break;
|
|
case 4:
|
|
/* Reading 32 bytes max. */
|
|
/* Only even double-word address are valid. */
|
|
if((address & 0x7) == 0)
|
|
{
|
|
wdptr = 0;
|
|
rdsize = 0xcul;
|
|
}
|
|
else
|
|
{
|
|
/* Not supported by protocol. */
|
|
wdptr = 0xff;
|
|
rdsize = 0xff;
|
|
}
|
|
break;
|
|
case 5:
|
|
case 6:
|
|
case 7:
|
|
/* Not supported by protocol. */
|
|
wdptr = 0xff;
|
|
rdsize = 0xff;
|
|
break;
|
|
case 8:
|
|
/* Reading 64 bytes max. */
|
|
/* Only even double-word address are valid. */
|
|
if((address & 0x7) == 0)
|
|
{
|
|
wdptr = 1;
|
|
rdsize = 0xcul;
|
|
}
|
|
else
|
|
{
|
|
/* Not supported by protocol. */
|
|
wdptr = 0xff;
|
|
rdsize = 0xff;
|
|
}
|
|
break;
|
|
case 9:
|
|
case 10:
|
|
case 11:
|
|
/* Not supported by protocol. */
|
|
wdptr = 0xff;
|
|
rdsize = 0xff;
|
|
break;
|
|
case 12:
|
|
/* Reading 96 bytes. */
|
|
/* Only even double-word address are valid. */
|
|
if((address & 0x7) == 0)
|
|
{
|
|
wdptr = 0;
|
|
rdsize = 0xdul;
|
|
}
|
|
else
|
|
{
|
|
/* Not supported by protocol. */
|
|
wdptr = 0xff;
|
|
rdsize = 0xff;
|
|
}
|
|
break;
|
|
case 13:
|
|
case 14:
|
|
case 15:
|
|
/* Not supported by protocol. */
|
|
wdptr = 0xff;
|
|
rdsize = 0xff;
|
|
break;
|
|
case 16:
|
|
/* Reading 128 bytes max. */
|
|
/* Only even double-word address are valid. */
|
|
if((address & 0x7) == 0)
|
|
{
|
|
wdptr = 1;
|
|
rdsize = 0xdul;
|
|
}
|
|
else
|
|
{
|
|
/* Not supported by protocol. */
|
|
wdptr = 0xff;
|
|
rdsize = 0xff;
|
|
}
|
|
break;
|
|
case 17:
|
|
case 18:
|
|
case 19:
|
|
/* Not supported by protocol. */
|
|
wdptr = 0xff;
|
|
rdsize = 0xff;
|
|
break;
|
|
case 20:
|
|
/* Reading 160 bytes. */
|
|
/* Only even double-word address are valid. */
|
|
if((address & 0x7) == 0)
|
|
{
|
|
wdptr = 0;
|
|
rdsize = 0xeul;
|
|
}
|
|
else
|
|
{
|
|
/* Not supported by protocol. */
|
|
wdptr = 0xff;
|
|
rdsize = 0xff;
|
|
}
|
|
break;
|
|
case 21:
|
|
case 22:
|
|
case 23:
|
|
/* Not supported by protocol. */
|
|
wdptr = 0xff;
|
|
rdsize = 0xff;
|
|
break;
|
|
case 24:
|
|
/* Reading 192 bytes. */
|
|
/* Only even double-word address are valid. */
|
|
if((address & 0x7) == 0)
|
|
{
|
|
wdptr = 1;
|
|
rdsize = 0xeul;
|
|
}
|
|
else
|
|
{
|
|
/* Not supported by protocol. */
|
|
wdptr = 0xff;
|
|
rdsize = 0xff;
|
|
}
|
|
break;
|
|
case 25:
|
|
case 26:
|
|
case 27:
|
|
/* Not supported by protocol. */
|
|
wdptr = 0xff;
|
|
rdsize = 0xff;
|
|
break;
|
|
case 28:
|
|
/* Reading 224 bytes. */
|
|
/* Only even double-word address are valid. */
|
|
if((address & 0x7) == 0)
|
|
{
|
|
wdptr = 0;
|
|
rdsize = 0xful;
|
|
}
|
|
else
|
|
{
|
|
/* Not supported by protocol. */
|
|
wdptr = 0xff;
|
|
rdsize = 0xff;
|
|
}
|
|
break;
|
|
case 29:
|
|
case 30:
|
|
case 31:
|
|
/* Not supported by protocol. */
|
|
wdptr = 0xff;
|
|
rdsize = 0xff;
|
|
break;
|
|
case 32:
|
|
/* Reading 256 bytes max. */
|
|
/* Only even double-word address are valid. */
|
|
if((address & 0x7) == 0)
|
|
{
|
|
wdptr = 1;
|
|
rdsize = 0xful;
|
|
}
|
|
else
|
|
{
|
|
/* Not supported by protocol. */
|
|
wdptr = 0xff;
|
|
rdsize = 0xff;
|
|
}
|
|
break;
|
|
default:
|
|
/* Not supported by protocol. */
|
|
wdptr = 0xff;
|
|
rdsize = 0xff;
|
|
break;
|
|
}
|
|
|
|
return ((((uint16_t) rdsize) << 8) | ((uint16_t) wdptr));
|
|
}
|
|
|
|
|
|
void rdsizeToOffset(uint8_t rdsize, uint8_t wdptr, uint8_t *offset, uint16_t *size)
|
|
{
|
|
switch(rdsize)
|
|
{
|
|
case 0:
|
|
case 1:
|
|
case 2:
|
|
case 3:
|
|
*offset = wdptr << 2;
|
|
*offset |= rdsize;
|
|
*size = 1;
|
|
break;
|
|
case 4:
|
|
case 6:
|
|
*offset = wdptr << 2;
|
|
*offset |= rdsize & 0x02;
|
|
*size = 2;
|
|
break;
|
|
case 5:
|
|
*offset = wdptr * 5;
|
|
*size = 3;
|
|
break;
|
|
case 8:
|
|
*offset = wdptr * 4;
|
|
*size = 4;
|
|
break;
|
|
case 7:
|
|
*offset = wdptr * 3;
|
|
*size = 5;
|
|
break;
|
|
case 9:
|
|
*offset = wdptr * 2;
|
|
*size = 6;
|
|
break;
|
|
case 10:
|
|
*offset = wdptr * 1;
|
|
*size = 7;
|
|
break;
|
|
case 11:
|
|
*offset = 0;
|
|
*size = 8 + 8*wdptr;
|
|
break;
|
|
case 12:
|
|
*offset = 0;
|
|
*size = 32 + 32*wdptr;
|
|
break;
|
|
case 13:
|
|
*offset = 0;
|
|
*size = 96 + 32*wdptr;
|
|
break;
|
|
case 14:
|
|
*offset = 0;
|
|
*size = 160 + 32*wdptr;
|
|
break;
|
|
case 15:
|
|
*offset = 0;
|
|
*size = 224 + 32*wdptr;
|
|
break;
|
|
}
|
|
}
|
|
|
|
|
|
static uint16_t wrsizeGet(const uint32_t address, const uint16_t size)
|
|
{
|
|
uint8_t wdptr;
|
|
uint8_t wrsize;
|
|
|
|
|
/* Save the time when this was transmitted. */
|
|
stack->txFrameTimeout[stack->txAckId] = stack->portTime;
|
|
|
switch(size/8)
|
/* Remember that this symbol has been transmitted. */
|
{
|
stack->txCounter = 1;
|
case 0:
|
|
/**************************************************************
|
|
* Sub double-word access.
|
|
**************************************************************/
|
|
switch(size%8)
|
|
{
|
|
case 0:
|
|
/* Not supported by protocol. */
|
|
wdptr = 0xff;
|
|
wrsize = 0xff;
|
|
break;
|
|
case 1:
|
|
/* Writing one byte. */
|
|
/* Any address is allowed. */
|
|
wdptr = (address >> 2) & 0x1;
|
|
wrsize = address & 0x3;
|
|
break;
|
|
case 2:
|
|
/* Writing two bytes. */
|
|
/* Address 0, 2, 4, 6 are valid. */
|
|
if((address & 0x1) == 0)
|
|
{
|
|
wdptr = (address >> 2) & 0x1;
|
|
wrsize = (address & 0x7) | 0x4;
|
|
}
|
|
else
|
|
{
|
|
/* Not supported by protocol. */
|
|
wdptr = 0xff;
|
|
wrsize = 0xff;
|
|
}
|
|
break;
|
|
case 3:
|
|
/* Writing 3 bytes. */
|
|
/* Address 0 and 5 are valid. */
|
|
if(((address & 0x7) == 0) ||
|
|
((address & 0x7) == 5))
|
|
{
|
|
wdptr = (address >> 2) & 0x1;
|
|
wrsize = 0x5ul;
|
|
}
|
|
else
|
|
{
|
|
/* Not supported by protocol. */
|
|
wdptr = 0xff;
|
|
wrsize = 0xff;
|
|
}
|
|
break;
|
|
case 4:
|
|
/* Writing 4 bytes. */
|
|
/* Address 0 and 4 are valid. */
|
|
if(((address & 0x7) == 0) ||
|
|
((address & 0x7) == 4))
|
|
{
|
|
wdptr = (address >> 2) & 0x1;
|
|
wrsize = 0x8ul;
|
|
}
|
|
else
|
|
{
|
|
/* Not supported by protocol. */
|
|
wdptr = 0xff;
|
|
wrsize = 0xff;
|
|
}
|
|
break;
|
|
case 5:
|
|
/* Writing 5 bytes. */
|
|
/* Address 0 and 3 are valid. */
|
|
if(((address & 0x7) == 0) ||
|
|
((address & 0x7) == 3))
|
|
{
|
|
wdptr = (address >> 1) & 0x1;
|
|
wrsize = 0x7ul;
|
|
}
|
|
else
|
|
{
|
|
/* Not supported by protocol. */
|
|
wdptr = 0xff;
|
|
wrsize = 0xff;
|
|
}
|
|
break;
|
|
case 6:
|
|
/* Writing 6 bytes. */
|
|
/* Addresses 0 and 2 are valid. */
|
|
if(((address & 0x7) == 0) ||
|
|
((address & 0x7) == 2))
|
|
{
|
|
wdptr = (address >> 1) & 0x1;
|
|
wrsize = 0x9ul;
|
|
}
|
|
else
|
|
{
|
|
/* Not supported by protocol. */
|
|
wdptr = 0xff;
|
|
wrsize = 0xff;
|
|
}
|
|
break;
|
|
default:
|
|
/* Writing 7 bytes. */
|
|
/* Addresses 0 and 1 are valid. */
|
|
if(((address & 0x7) == 0) ||
|
|
((address & 0x7) == 1))
|
|
{
|
|
wdptr = address & 0x1;
|
|
wrsize = 0xaul;
|
|
}
|
|
else
|
|
{
|
|
/* Not supported by protocol. */
|
|
wdptr = 0xff;
|
|
wrsize = 0xff;
|
|
}
|
|
break;
|
|
}
|
|
break;
|
|
case 1:
|
|
/* Writing 8 bytes. */
|
|
/* Only even double-word address are valid. */
|
|
if((address % 8) == 0)
|
|
{
|
|
wdptr = 0;
|
|
wrsize = 0xbul;
|
|
}
|
|
else
|
|
{
|
|
/* Not supported by protocol. */
|
|
wdptr = 0xff;
|
|
wrsize = 0xff;
|
|
}
|
|
break;
|
|
case 2:
|
|
/* Writing 16 bytes max. */
|
|
/* Only even double-word address are valid. */
|
|
if((address % 8) == 0)
|
|
{
|
|
wdptr = 1;
|
|
wrsize = 0xbul;
|
|
}
|
|
else
|
|
{
|
|
/* Not supported by protocol. */
|
|
wdptr = 0xff;
|
|
wrsize = 0xff;
|
|
}
|
|
break;
|
|
case 3:
|
|
case 4:
|
|
/* Writing 32 bytes max. */
|
|
/* Only even double-word address are valid. */
|
|
if((address & 0x7) == 0)
|
|
{
|
|
wdptr = 0;
|
|
wrsize = 0xcul;
|
|
}
|
|
else
|
|
{
|
|
/* Not supported by protocol. */
|
|
wdptr = 0xff;
|
|
wrsize = 0xff;
|
|
}
|
|
break;
|
|
case 5:
|
|
case 6:
|
|
case 7:
|
|
case 8:
|
|
/* Writing 64 bytes max. */
|
|
/* Only even double-word address are valid. */
|
|
if((address & 0x7) == 0)
|
|
{
|
|
wdptr = 1;
|
|
wrsize = 0xcul;
|
|
}
|
|
else
|
|
{
|
|
/* Not supported by protocol. */
|
|
wdptr = 0xff;
|
|
wrsize = 0xff;
|
|
}
|
|
break;
|
|
case 9:
|
|
case 10:
|
|
case 11:
|
|
case 12:
|
|
case 13:
|
|
case 14:
|
|
case 15:
|
|
case 16:
|
|
/* Writing 128 bytes max. */
|
|
/* Only even double-word address are valid. */
|
|
if((address & 0x7) == 0)
|
|
{
|
|
wdptr = 1;
|
|
wrsize = 0xdul;
|
|
}
|
|
else
|
|
{
|
|
/* Not supported by protocol. */
|
|
wdptr = 0xff;
|
|
wrsize = 0xff;
|
|
}
|
|
break;
|
|
case 17:
|
|
case 18:
|
|
case 19:
|
|
case 20:
|
|
case 21:
|
|
case 22:
|
|
case 23:
|
|
case 24:
|
|
case 25:
|
|
case 26:
|
|
case 27:
|
|
case 28:
|
|
case 29:
|
|
case 30:
|
|
case 31:
|
|
case 32:
|
|
/* Writing 256 bytes max. */
|
|
/* Only even double-word address are valid. */
|
|
if((address & 0x7) == 0)
|
|
{
|
|
wdptr = 1;
|
|
wrsize = 0xful;
|
|
}
|
}
|
else
|
else
|
{
|
{
|
/* Not supported by protocol. */
|
/* A link-request-symbol has been transmitted. */
|
wdptr = 0xff;
|
|
wrsize = 0xff;
|
|
}
|
|
break;
|
|
default:
|
|
/* Not supported by protocol. */
|
|
wdptr = 0xff;
|
|
wrsize = 0xff;
|
|
break;
|
|
}
|
|
|
|
return ((((uint16_t) wrsize) << 8) | ((uint16_t) wdptr));
|
|
}
|
|
|
|
|
|
void wrsizeToOffset(uint8_t wrsize, uint8_t wdptr, uint8_t *offset, uint16_t *size)
|
|
{
|
|
switch(wrsize)
|
|
{
|
|
case 0:
|
|
case 1:
|
|
case 2:
|
|
case 3:
|
|
*offset = wdptr << 2;
|
|
*offset |= wrsize;
|
|
*size = 1;
|
|
break;
|
|
case 4:
|
|
case 6:
|
|
*offset = wdptr << 2;
|
|
*offset |= wrsize & 0x02;
|
|
*size = 2;
|
|
break;
|
|
case 5:
|
|
*offset = wdptr * 5;
|
|
*size = 3;
|
|
break;
|
|
case 8:
|
|
*offset = wdptr * 4;
|
|
*size = 4;
|
|
break;
|
|
case 7:
|
|
*offset = wdptr * 3;
|
|
*size = 5;
|
|
break;
|
|
case 9:
|
|
*offset = wdptr * 2;
|
|
*size = 6;
|
|
break;
|
|
case 10:
|
|
*offset = wdptr * 1;
|
|
*size = 7;
|
|
break;
|
|
case 11:
|
|
*offset = 0;
|
|
*size = 8 + 8*wdptr;
|
|
break;
|
|
case 12:
|
|
*offset = 0;
|
|
*size = 32 + 32*wdptr;
|
|
break;
|
|
case 13:
|
|
*offset = 0;
|
|
*size = 128*wdptr;
|
|
break;
|
|
case 14:
|
|
*offset = 0;
|
|
*size = 0;
|
|
break;
|
|
case 15:
|
|
*offset = 0;
|
|
*size = 256*wdptr;
|
|
break;
|
|
}
|
|
}
|
|
|
|
|
|
static RioSymbol CreateControlSymbol( const uint8_t stype0,
|
|
const uint8_t parameter0, const uint8_t parameter1,
|
|
const uint8_t stype1, const uint8_t cmd)
|
|
{
|
|
RioSymbol s;
|
|
|
|
s.type = RIO_SYMBOL_TYPE_CONTROL;
|
|
|
|
s.data = ((uint32_t)stype0 & (uint32_t)0x07ul) << 21;
|
|
s.data |= ((uint32_t)parameter0 & (uint32_t)0x1ful) << 16;
|
|
s.data |= ((uint32_t)parameter1 & (uint32_t)0x1ful) << 11;
|
|
s.data |= ((uint32_t)stype1 & (uint32_t)0x07ul) << 8;
|
|
s.data |= ((uint32_t)cmd & (uint32_t)0x7ul) << 5;
|
|
s.data |= Crc5(s.data, 0x1fu);
|
|
|
|
return s;
|
|
}
|
|
|
|
|
|
static uint8_t Crc5( const uint32_t data, const uint8_t crc)
|
|
{
|
|
static const uint8_t crcTable[] = {
|
|
0x00u, 0x15u, 0x1fu, 0x0au, 0x0bu, 0x1eu, 0x14u, 0x01u,
|
|
0x16u, 0x03u, 0x09u, 0x1cu, 0x1du, 0x08u, 0x02u, 0x17u,
|
|
0x19u, 0x0cu, 0x06u, 0x13u, 0x12u, 0x07u, 0x0du, 0x18u,
|
|
0x0fu, 0x1au, 0x10u, 0x05u, 0x04u, 0x11u, 0x1bu, 0x0eu
|
|
};
|
|
|
|
uint8_t result;
|
|
uint8_t index;
|
|
|
|
result = crc;
|
|
index = (uint8_t)((data >> 19) & (uint32_t)0x1ful) ^ result;
|
|
result = crcTable[index];
|
|
index = (uint8_t)((data >> 14) & (uint32_t)0x1ful) ^ result;
|
|
result = crcTable[index];
|
|
index = (uint8_t)((data >> 9) & (uint32_t)0x1ful) ^ result;
|
|
result = crcTable[index];
|
|
index = (uint8_t)((data >> 4) & (uint32_t)0x1eul) ^ result;
|
|
result = crcTable[index];
|
|
|
|
return result;
|
|
}
|
|
|
|
|
|
static uint16_t Crc16( const uint16_t data, const uint16_t crc)
|
|
{
|
|
static const uint16_t crcTable[] = {
|
|
0x0000u, 0x1021u, 0x2042u, 0x3063u, 0x4084u, 0x50a5u, 0x60c6u, 0x70e7u,
|
|
0x8108u, 0x9129u, 0xa14au, 0xb16bu, 0xc18cu, 0xd1adu, 0xe1ceu, 0xf1efu,
|
|
0x1231u, 0x0210u, 0x3273u, 0x2252u, 0x52b5u, 0x4294u, 0x72f7u, 0x62d6u,
|
|
0x9339u, 0x8318u, 0xb37bu, 0xa35au, 0xd3bdu, 0xc39cu, 0xf3ffu, 0xe3deu,
|
|
0x2462u, 0x3443u, 0x0420u, 0x1401u, 0x64e6u, 0x74c7u, 0x44a4u, 0x5485u,
|
|
0xa56au, 0xb54bu, 0x8528u, 0x9509u, 0xe5eeu, 0xf5cfu, 0xc5acu, 0xd58du,
|
|
0x3653u, 0x2672u, 0x1611u, 0x0630u, 0x76d7u, 0x66f6u, 0x5695u, 0x46b4u,
|
|
0xb75bu, 0xa77au, 0x9719u, 0x8738u, 0xf7dfu, 0xe7feu, 0xd79du, 0xc7bcu,
|
|
0x48c4u, 0x58e5u, 0x6886u, 0x78a7u, 0x0840u, 0x1861u, 0x2802u, 0x3823u,
|
|
0xc9ccu, 0xd9edu, 0xe98eu, 0xf9afu, 0x8948u, 0x9969u, 0xa90au, 0xb92bu,
|
|
0x5af5u, 0x4ad4u, 0x7ab7u, 0x6a96u, 0x1a71u, 0x0a50u, 0x3a33u, 0x2a12u,
|
|
0xdbfdu, 0xcbdcu, 0xfbbfu, 0xeb9eu, 0x9b79u, 0x8b58u, 0xbb3bu, 0xab1au,
|
|
0x6ca6u, 0x7c87u, 0x4ce4u, 0x5cc5u, 0x2c22u, 0x3c03u, 0x0c60u, 0x1c41u,
|
|
0xedaeu, 0xfd8fu, 0xcdecu, 0xddcdu, 0xad2au, 0xbd0bu, 0x8d68u, 0x9d49u,
|
|
0x7e97u, 0x6eb6u, 0x5ed5u, 0x4ef4u, 0x3e13u, 0x2e32u, 0x1e51u, 0x0e70u,
|
|
0xff9fu, 0xefbeu, 0xdfddu, 0xcffcu, 0xbf1bu, 0xaf3au, 0x9f59u, 0x8f78u,
|
|
0x9188u, 0x81a9u, 0xb1cau, 0xa1ebu, 0xd10cu, 0xc12du, 0xf14eu, 0xe16fu,
|
|
0x1080u, 0x00a1u, 0x30c2u, 0x20e3u, 0x5004u, 0x4025u, 0x7046u, 0x6067u,
|
|
0x83b9u, 0x9398u, 0xa3fbu, 0xb3dau, 0xc33du, 0xd31cu, 0xe37fu, 0xf35eu,
|
|
0x02b1u, 0x1290u, 0x22f3u, 0x32d2u, 0x4235u, 0x5214u, 0x6277u, 0x7256u,
|
|
0xb5eau, 0xa5cbu, 0x95a8u, 0x8589u, 0xf56eu, 0xe54fu, 0xd52cu, 0xc50du,
|
|
0x34e2u, 0x24c3u, 0x14a0u, 0x0481u, 0x7466u, 0x6447u, 0x5424u, 0x4405u,
|
|
0xa7dbu, 0xb7fau, 0x8799u, 0x97b8u, 0xe75fu, 0xf77eu, 0xc71du, 0xd73cu,
|
|
0x26d3u, 0x36f2u, 0x0691u, 0x16b0u, 0x6657u, 0x7676u, 0x4615u, 0x5634u,
|
|
0xd94cu, 0xc96du, 0xf90eu, 0xe92fu, 0x99c8u, 0x89e9u, 0xb98au, 0xa9abu,
|
|
0x5844u, 0x4865u, 0x7806u, 0x6827u, 0x18c0u, 0x08e1u, 0x3882u, 0x28a3u,
|
|
0xcb7du, 0xdb5cu, 0xeb3fu, 0xfb1eu, 0x8bf9u, 0x9bd8u, 0xabbbu, 0xbb9au,
|
|
0x4a75u, 0x5a54u, 0x6a37u, 0x7a16u, 0x0af1u, 0x1ad0u, 0x2ab3u, 0x3a92u,
|
|
0xfd2eu, 0xed0fu, 0xdd6cu, 0xcd4du, 0xbdaau, 0xad8bu, 0x9de8u, 0x8dc9u,
|
|
0x7c26u, 0x6c07u, 0x5c64u, 0x4c45u, 0x3ca2u, 0x2c83u, 0x1ce0u, 0x0cc1u,
|
|
0xef1fu, 0xff3eu, 0xcf5du, 0xdf7cu, 0xaf9bu, 0xbfbau, 0x8fd9u, 0x9ff8u,
|
|
0x6e17u, 0x7e36u, 0x4e55u, 0x5e74u, 0x2e93u, 0x3eb2u, 0x0ed1u, 0x1ef0u
|
|
};
|
|
|
|
uint16_t result;
|
|
uint8_t index;
|
|
|
|
result = crc;
|
|
index = (uint8_t) ((data >> 8) ^ (result >> 8));
|
|
result = (uint16_t) (crcTable[index] ^ (uint16_t)(result << 8));
|
|
index = (uint8_t) ((data) ^ (result >> 8));
|
|
result = (uint16_t) (crcTable[index] ^ (uint16_t)(result << 8));
|
|
|
|
return result;
|
|
}
|
|
|
|
|
|
static uint16_t Crc32( const uint32_t data, uint16_t crc)
|
|
{
|
|
crc = Crc16((uint16_t) (data >> 16), crc);
|
|
crc = Crc16((uint16_t) (data), crc);
|
|
return crc;
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static Queue_t QueueCreate( const uint8_t size, uint32_t *buffer)
|
|
{
|
|
Queue_t q;
|
|
|
|
q.size = size;
|
|
q.available = size;
|
|
q.windowSize = 0u;
|
|
q.windowIndex = 0u;
|
|
q.frontIndex = 0u;
|
|
q.backIndex = 0u;
|
|
q.buffer_p = buffer;
|
|
|
|
return q;
|
|
}
|
|
|
|
|
|
static uint8_t QueueAvailable( const Queue_t q)
|
|
{
|
|
return q.available;
|
|
}
|
|
|
|
|
|
static bool_t QueueEmpty( const Queue_t q)
|
|
{
|
|
return (bool_t) (q.available == q.size);
|
|
}
|
|
|
|
|
|
static uint8_t QueueLength( const Queue_t q)
|
|
{
|
|
return q.size - q.available;
|
|
}
|
|
|
|
|
|
static Queue_t QueueEnqueue( Queue_t q)
|
|
{
|
|
q.backIndex++;
|
|
if(q.backIndex == q.size)
|
|
{
|
|
q.backIndex = 0;
|
|
}
|
|
q.available--;
|
|
return q;
|
|
}
|
|
|
|
|
|
static Queue_t QueueDequeue( Queue_t q)
|
/* Check if the link partner reply has timed out. */
|
{
|
if((stack->portTime - stack->txFrameTimeout[stack->txAckId]) < stack->portTimeout)
|
q.frontIndex++;
|
|
if(q.frontIndex == q.size)
|
|
{
|
|
q.frontIndex = 0;
|
|
}
|
|
q.available++;
|
|
if(q.windowSize == 0)
|
|
{
|
{
|
q.windowIndex = q.frontIndex;
|
/* No timeout. */
|
|
|
|
/* A link-request-symbol has been transmitted. */
|
|
/* Send only idle-symbols until the link-response is received. */
|
|
s.type = RIOSTACK_SYMBOL_TYPE_IDLE;
|
}
|
}
|
else
|
else
|
{
|
{
|
q.windowSize--;
|
/* Link response timeout. */
|
}
|
|
return q;
|
|
}
|
|
|
|
|
|
static bool_t QueueWindowEmpty( const Queue_t q)
|
/* Check if the link-partner has not responded for too many times. */
|
|
if(stack->txCounter < 5)
|
{
|
{
|
return (bool_t) ((q.available + q.windowSize) == q.size);
|
/* Not too many timeouts. */
|
}
|
/* Retry and send a new link-request. */
|
|
|
|
|
static Queue_t QueueWindowReset(Queue_t q)
|
/* Send link-request-symbol (input-status). */
|
{
|
s = CreateControlSymbol(STYPE0_STATUS, stack->rxAckId, QueueAvailable(stack->rxQueue),
|
q.windowIndex = q.frontIndex;
|
STYPE1_LINK_REQUEST, LINK_REQUEST_INPUT_STATUS);
|
q.windowSize = 0;
|
|
return q;
|
|
}
|
|
|
|
|
/* Save the time when this was transmitted. */
|
|
stack->txFrameTimeout[stack->txAckId] = stack->portTime;
|
|
|
static Queue_t QueueWindowNext(Queue_t q)
|
/* Increment the number of times we have retransmitted the link-request. */
|
{
|
stack->txCounter++;
|
q.windowIndex++;
|
}
|
if(q.windowIndex == q.size)
|
else
|
{
|
{
|
q.windowIndex = 0;
|
/* The link partner has not answered for too many times. */
|
|
/* Give up and set the state to uninitialized. */
|
|
stack->txState = TX_STATE_UNINITIALIZED;
|
|
s.type = RIOSTACK_SYMBOL_TYPE_IDLE;
|
|
ASSERT0("No link-response received, giving up.");
|
|
}
|
}
|
}
|
q.windowSize++;
|
|
return q;
|
|
}
|
}
|
|
break;
|
|
|
|
case TX_STATE_UNINITIALIZED:
|
|
default:
|
|
/******************************************************************************
|
|
* Wait for the port to be initialized.
|
|
******************************************************************************/
|
|
|
static void QueueSetSize( Queue_t q, const uint32_t size)
|
/* Send only idle symbols. */
|
{
|
s.type = RIOSTACK_SYMBOL_TYPE_IDLE;
|
(q.buffer_p+(RIO_BUFFER_SIZE*q.backIndex))[0] = size;
|
break;
|
}
|
}
|
|
|
|
/* Return the created symbol. */
|
static void QueueSetContent( Queue_t q, const uint32_t index, const uint32_t content)
|
return s;
|
{
|
|
(q.buffer_p+(RIO_BUFFER_SIZE*q.backIndex))[index+1ul] = content;
|
|
}
|
}
|
|
|
|
|
static uint32_t QueueGetFrontSize( Queue_t q)
|
|
{
|
|
return (q.buffer_p+(RIO_BUFFER_SIZE*q.windowIndex))[0];
|
|
}
|
|
|
|
|
/*******************************************************************************
|
|
* Local RapidIO stack helper functions.
|
|
*******************************************************************************/
|
|
|
static uint32_t QueueGetFrontContent( const Queue_t q, const uint32_t index)
|
static void handleStatus(RioStack_t *stack, const uint8_t ackId, const uint8_t bufferStatus)
|
{
|
{
|
return (q.buffer_p+(RIO_BUFFER_SIZE*q.windowIndex))[index+1ul];
|
/* Update the buffer status of the link partner. */
|
|
(void) ackId;
|
|
stack->txBufferStatus = bufferStatus;
|
}
|
}
|
|
|
|
|
static uint32_t *QueueGetFrontBuffer( const Queue_t q )
|
|
|
static void handlePacketAccepted(RioStack_t *stack, const uint8_t ackId, const uint8_t bufferStatus)
|
{
|
{
|
return &((q.buffer_p+(RIO_BUFFER_SIZE*q.windowIndex))[1]);
|
uint32_t linkLatency;
|
}
|
|
|
|
|
|
static uint32_t QueueGetBackSize( const Queue_t q)
|
/* Check if an acknowledge is expected and that it is for a transmitted packet. */
|
|
if((stack->txAckId != stack->txAckIdWindow) && (ackId == stack->txAckId))
|
{
|
{
|
return (q.buffer_p+(RIO_BUFFER_SIZE*q.backIndex))[0];
|
/* Acknowledge for a recently transmitted packet received. */
|
}
|
|
|
|
|
|
static uint32_t *QueueGetBackBuffer( const Queue_t q )
|
/* Check if the latency of this packet is larger than the largest encountered so far. */
|
|
linkLatency = stack->portTime - stack->txFrameTimeout[ackId];
|
|
if(linkLatency > stack->statusOutboundLinkLatencyMax)
|
{
|
{
|
return &((q.buffer_p+(RIO_BUFFER_SIZE*q.backIndex))[1]);
|
stack->statusOutboundLinkLatencyMax = linkLatency;
|
}
|
}
|
|
|
|
/* Remove the packet from the outbound queue and restart the transmission for
|
#ifdef MODULE_TEST
|
a new packet. */
|
#include <stdio.h>
|
stack->txQueue = QueueDequeue(stack->txQueue);
|
#define PrintS(s) \
|
stack->txAckId = ACKID_INC(stack->txAckId);
|
{ \
|
stack->statusOutboundPacketComplete++;
|
FILE *fd; \
|
|
fd=fopen("testspec.txt", "a"); \
|
|
fputs(s "\n", fd); \
|
|
fclose(fd); \
|
|
}
|
}
|
|
else
|
#define TESTSTART(s) printf(s)
|
{
|
#define TESTEND printf(" passed.\n");
|
/* Acknowledge for an unexpected ackId or not waiting for an acknowledge. */
|
|
/* Link protocol violation. Discard the symbol and enter the output-error-stopped state. */
|
#define TESTCOND(got) \
|
stack->txState = TX_STATE_OUTPUT_ERROR_STOPPED;
|
if (!(got)) \
|
stack->txCounter = 0u;
|
{ \
|
stack->statusOutboundErrorPacketAccepted++;
|
printf("ERROR at line %u:%s=%u (0x%08x)\n", \
|
|
__LINE__, #got, (got), (got)); \
|
|
exit(1); \
|
|
}
|
}
|
|
|
#define TESTEXPR(got, expected) \
|
/* Update the buffer status of the link partner. */
|
if ((got)!=(expected)) \
|
stack->txBufferStatus = bufferStatus;
|
{ \
|
|
printf("ERROR at line %u:%s=%u (0x%08x) expected=%u (0x%08x)\n", \
|
|
__LINE__, #got, (got), (got), (expected), (expected)); \
|
|
exit(1); \
|
|
}
|
}
|
|
|
#define TESTSYMBOL(got, expected) testSymbol(__LINE__, #got, (got), (expected))
|
|
|
|
void testSymbol(uint32_t line, char *expression, RioSymbol got, RioSymbol expected)
|
|
{
|
static void handlePacketRetry(RioStack_t *stack, const uint8_t ackId, const uint8_t bufferStatus)
|
if ((got).type==(expected).type)
|
|
{
|
|
switch ((got).type)
|
|
{
|
|
case RIO_SYMBOL_TYPE_ERROR:
|
|
case RIO_SYMBOL_TYPE_IDLE:
|
|
break;
|
|
case RIO_SYMBOL_TYPE_CONTROL:
|
|
if((got).data != (expected).data)
|
|
{
|
|
if(STYPE0_GET((got).data) != STYPE0_GET((expected).data))
|
|
{
|
|
printf("ERROR at line %u:STYPE0=0x%02x expected=0x%02x\n",
|
|
line, STYPE0_GET((got).data), STYPE0_GET((expected).data));
|
|
}
|
|
if(PARAMETER0_GET((got).data) != PARAMETER0_GET((expected).data))
|
|
{
|
|
printf("ERROR at line %u:PARAMETER0=0x%02x expected=0x%02x\n",
|
|
line, PARAMETER0_GET((got).data), PARAMETER0_GET((expected).data));
|
|
}
|
|
if(PARAMETER1_GET((got).data) != PARAMETER1_GET((expected).data))
|
|
{
|
|
printf("ERROR at line %u:PARAMETER1=0x%02x expected=0x%02x\n",
|
|
line, PARAMETER1_GET((got).data), PARAMETER1_GET((expected).data));
|
|
}
|
|
if(STYPE1_GET((got).data) != STYPE1_GET((expected).data))
|
|
{
|
|
printf("ERROR at line %u:STYPE1=0x%02x expected=0x%02x\n",
|
|
line, STYPE1_GET((got).data), STYPE1_GET((expected).data));
|
|
}
|
|
if(CMD_GET((got).data) != CMD_GET((expected).data))
|
|
{
|
|
printf("ERROR at line %u:CMD=0x%02x expected=0x%02x\n",
|
|
line, CMD_GET((got).data), CMD_GET((expected).data));
|
|
}
|
|
if(CRC5_GET((got).data) != CRC5_GET((expected).data))
|
|
{
|
{
|
printf("ERROR at line %u:CRC5=0x%02x expected=0x%02x\n",
|
/* Check if the retried packet ackId is acceptable. */
|
line, CRC5_GET((got).data), CRC5_GET((expected).data));
|
if(ackId == stack->txAckId)
|
}
|
|
exit(1);
|
|
}
|
|
break;
|
|
case RIO_SYMBOL_TYPE_DATA:
|
|
if((got).data != (expected).data)
|
|
{
|
{
|
printf("ERROR at line %u:%s=%u (0x%08x) expected=%u (0x%08x)\n",
|
/* The request for retry is for the current packet. */
|
line, expression, (got).data, (got).data, (expected).data, (expected).data);
|
/* Force the transmitter to send a RESTART-FROM-RETRY symbol. */
|
exit(1);
|
stack->txState = TX_STATE_OUTPUT_RETRY_STOPPED;
|
}
|
stack->statusOutboundPacketRetry++;
|
break;
|
|
}
|
|
}
|
}
|
else
|
else
|
{
|
{
|
printf("ERROR at line %u:%s=%u (0x%08x) expected=%u (0x%08x)\n",
|
/* Link protocol violation. Discard the symbol and enter the output-error-stopped state. */
|
line, expression, (got).type, (got).type, (expected).type, (expected).type);
|
stack->txState = TX_STATE_OUTPUT_ERROR_STOPPED;
|
exit(1);
|
stack->txCounter = 0u;
|
}
|
stack->statusOutboundErrorPacketRetry++;
|
}
|
}
|
|
|
|
/* Update the buffer status of the link partner. */
|
|
stack->txBufferStatus = bufferStatus;
|
|
}
|
|
|
|
|
uint32_t testConfigWriteData;
|
|
|
|
uint8_t createDoorbell(uint32_t *doorbell, uint8_t ackId, uint16_t destid, uint16_t srcId, uint8_t tid, uint16_t info)
|
static void handlePacketNotAccepted(RioStack_t *stack, const uint8_t arbitrary, const uint8_t cause)
|
{
|
{
|
uint16_t crc;
|
(void) arbitrary;
|
uint32_t content;
|
|
|
|
/* ackId(4:0)|0|vc|crf|prio(1:0)|tt(1:0)|ftype(3:0)|destinationId(15:0) */
|
|
/* ackId is set when the packet is transmitted. */
|
|
content = 0x001aul << 16;
|
|
content |= (uint32_t) destid;
|
|
crc = Crc32(content, 0xffffu);
|
|
doorbell[0] = (((uint32_t) ackId) << 27) | content;
|
|
|
|
/* sourceId(15:0)|rsrv(7:0)|srcTID(7:0) */
|
|
content = ((uint32_t) srcId) << 16;
|
|
content |= (uint32_t) tid;
|
|
crc = Crc32(content, crc);
|
|
doorbell[1] = content;
|
|
|
|
/* infoMSB(7:0)|infoLSB(7:0)|crc(15:0) */
|
|
content = ((uint32_t) info) << 16;
|
|
crc = Crc16(info, crc);
|
|
content |= ((uint32_t) crc);
|
|
doorbell[2] = content;
|
|
|
|
return 3;
|
|
|
|
}
|
|
|
|
uint32_t testConfigRead(RioStack_t *stack, uint32_t offset)
|
/* Force the transmitter to enter output-error-stopped state. */
|
{
|
stack->txState = TX_STATE_OUTPUT_ERROR_STOPPED;
|
switch(offset)
|
stack->txCounter = 0u;
|
{
|
|
case 0:
|
|
return 0x80000006;
|
|
case 4:
|
|
return 0x00a100a2;
|
|
case 8:
|
|
return testConfigWriteData;
|
|
default:
|
|
return 0x00000000;
|
|
}
|
|
}
|
|
|
|
void testConfigWrite(RioStack_t *stack, uint32_t offset, uint32_t data)
|
/* Record the type of error that caused the packet to not being accepted. */
|
{
|
switch(cause)
|
switch(offset)
|
|
{
|
{
|
case 8:
|
case PACKET_NOT_ACCEPTED_CAUSE_UNEXPECTED_ACKID:
|
testConfigWriteData = data;
|
stack->statusPartnerErrorPacketAckId++;
|
|
break;
|
|
case PACKET_NOT_ACCEPTED_CAUSE_CONTROL_CRC:
|
|
stack->statusPartnerErrorControlCrc++;
|
|
break;
|
|
case PACKET_NOT_ACCEPTED_CAUSE_PACKET_CRC:
|
|
stack->statusPartnerErrorPacketCrc++;
|
|
break;
|
|
case PACKET_NOT_ACCEPTED_CAUSE_ILLEGAL_CHARACTER:
|
|
stack->statusPartnerErrorIllegalCharacter++;
|
break;
|
break;
|
default:
|
default:
|
/* Dont do anything. */
|
stack->statusPartnerErrorGeneral++;
|
break;
|
break;
|
}
|
}
|
}
|
}
|
|
|
/*******************************************************************************
|
|
* Module test for this file.
|
|
*******************************************************************************/
|
|
int32_t main(void)
|
|
{
|
|
RioStack_t stack;
|
|
RioStackObserver_t observer;
|
|
uint32_t rxPacketBuffer[RIO_BUFFER_SIZE*8], txPacketBuffer[RIO_BUFFER_SIZE*8];
|
|
RioSymbol s, c, d;
|
|
int i, j, k;
|
|
uint16_t length;
|
|
uint16_t srcid;
|
|
uint8_t tid;
|
|
uint8_t hop;
|
|
uint8_t mailbox;
|
|
uint16_t info;
|
|
uint32_t address;
|
|
uint32_t data;
|
|
uint8_t payload8[256];
|
|
uint8_t payload8Expected[256];
|
|
uint32_t packet[69];
|
|
uint32_t packetLength;
|
|
|
|
|
|
/*************************************************************************
|
|
* Test prelude.
|
|
* Setup the RIO stack for operation.
|
|
*************************************************************************/
|
|
|
|
/* Setup callback handlers for config-space accesses in the implementation-
|
|
defined address range. */
|
|
observer.configRead = testConfigRead;
|
|
observer.configWrite = testConfigWrite;
|
|
|
|
/* Open the stack and set the port status to initialized. */
|
|
RIO_open(&stack, &observer, NULL,
|
|
RIO_BUFFER_SIZE*8, &rxPacketBuffer[0],
|
|
RIO_BUFFER_SIZE*8, &txPacketBuffer[0],
|
|
0xb03b, 0x0000, 0x00000000, 0x0000, 0x0000, 0x0000, 0xffff);
|
|
|
|
/* Set the port timeout. */
|
|
RIO_portSetTimeout(&stack, 1);
|
|
|
|
/* Set the current port time. */
|
|
RIO_portSetTime(&stack, 0);
|
|
|
|
/* Set master enable. */
|
|
RIO_writeConfig(&stack,
|
|
PORT_GENERAL_CONTROL_CSR(EXTENDED_FEATURES_OFFSET), 0x40000000);
|
|
|
|
/******************************************************************************/
|
|
PrintS("----------------------------------------------------------------------");
|
|
PrintS("TG_riostack");
|
|
PrintS("----------------------------------------------------------------------");
|
|
PrintS("TG_riostack-TC1");
|
|
PrintS("Description: Test link initialization and normal packet exchange.");
|
|
PrintS("Requirement: XXXXX");
|
|
PrintS("----------------------------------------------------------------------");
|
|
PrintS("Step 1:");
|
|
PrintS("Action: Send packets when port is uninitialized.");
|
|
PrintS("Result: All packets should be ignored during initialization.");
|
|
PrintS("----------------------------------------------------------------------");
|
|
/******************************************************************************/
|
|
TESTSTART("TG_riostack-TC1-Step1");
|
|
/******************************************************************************/
|
|
|
|
/* Place a packet in the outbound queue to check that it is received once
|
|
the transmitter is placed in the correct state. */
|
|
RIO_sendDoorbell(&stack, 1, 0, 0xdeaf);
|
|
|
|
/* Check that only idle symbols are transmitted when the port has not been
|
|
initialied even if statuses are received. */
|
|
for(i = 0; i < 1024; i++)
|
|
{
|
|
RIO_portAddSymbol(&stack, CreateControlSymbol(STYPE0_STATUS, 0, 1, STYPE1_NOP, 0));
|
|
s = RIO_portGetSymbol(&stack);
|
|
TESTEXPR(s.type, RIO_SYMBOL_TYPE_IDLE);
|
|
}
|
|
|
|
/******************************************************************************/
|
|
TESTEND;
|
|
/*****************************************************************************/
|
|
PrintS("----------------------------------------------------------------------");
|
|
PrintS("Step 2:");
|
|
PrintS("Action: Set port initialized and get symbols from the stack.");
|
|
PrintS("Result: Status-control-symbols should be generated each 256 symbol.");
|
|
PrintS("----------------------------------------------------------------------");
|
|
/*****************************************************************************/
|
|
TESTSTART("TG_riostack-TC1-Step2");
|
|
/*****************************************************************************/
|
|
|
|
/* Set the port status to intialized. */
|
|
RIO_portSetStatus(&stack, 1);
|
|
|
|
/* Set port time. */
|
|
RIO_portSetTime(&stack, 1);
|
|
|
|
/* Check that status-control-symbols are transmitted once every 256 symbol. */
|
|
for(j = 0; j < 15; j++)
|
|
{
|
|
for(i = 0; i < 255; i++)
|
|
{
|
|
s = RIO_portGetSymbol(&stack);
|
|
TESTEXPR(s.type, RIO_SYMBOL_TYPE_IDLE);
|
|
}
|
|
s = RIO_portGetSymbol(&stack);
|
|
c = CreateControlSymbol(STYPE0_STATUS, 0, 8, STYPE1_NOP, 0);
|
|
TESTEXPR(s.type, c.type);
|
|
TESTEXPR(s.data, c.data);
|
|
}
|
|
|
|
/******************************************************************************/
|
|
TESTEND;
|
|
/******************************************************************************/
|
|
PrintS("----------------------------------------------------------------------");
|
|
PrintS("Step 3:");
|
|
PrintS("Action: Add a status-control-symbol to the receiver.");
|
|
PrintS("Result: Status-control-symbols should be generated each 15 symbol.");
|
|
PrintS("----------------------------------------------------------------------");
|
|
/******************************************************************************/
|
|
TESTSTART("TG_riostack-TC1-Step3");
|
|
/*****************************************************************************/
|
|
|
|
/* Insert a status-control-symbol in the receive. */
|
|
RIO_portAddSymbol(&stack, CreateControlSymbol(STYPE0_STATUS, 0, 1, STYPE1_NOP, 0));
|
|
|
|
/* Check that status-control-symbols are transmitted once every 16 symbol. */
|
|
for(i = 0; i < 15; i++)
|
|
{
|
|
s = RIO_portGetSymbol(&stack);
|
|
TESTEXPR(s.type, RIO_SYMBOL_TYPE_IDLE);
|
|
}
|
|
s = RIO_portGetSymbol(&stack);
|
|
c = CreateControlSymbol(STYPE0_STATUS, 0, 8, STYPE1_NOP, 0);
|
|
TESTEXPR(s.type, c.type);
|
|
TESTEXPR(s.data, c.data);
|
|
|
|
/******************************************************************************/
|
|
TESTEND;
|
|
/******************************************************************************/
|
|
PrintS("----------------------------------------------------------------------");
|
|
PrintS("Step 4:");
|
|
PrintS("Action: Add a packet to the receiver.");
|
|
PrintS("Result: Packet should be ignored until the link is initialized.");
|
|
PrintS("----------------------------------------------------------------------");
|
|
/******************************************************************************/
|
|
TESTSTART("TG_riostack-TC1-Step4");
|
|
/*****************************************************************************/
|
|
|
|
/* Send a packet. Note that the start and end of the packet contains a status. */
|
|
packetLength = createDoorbell(packet, 0, 0, 0, 0, 0);
|
|
RIO_portAddSymbol(&stack, CreateControlSymbol(STYPE0_STATUS, 0, 8, STYPE1_START_OF_PACKET, 0));
|
|
for(i = 0; i < packetLength; i++)
|
|
{
|
|
d.type = RIO_SYMBOL_TYPE_DATA;
|
|
d.data = packet[i];
|
|
RIO_portAddSymbol(&stack, d);
|
|
}
|
|
RIO_portAddSymbol(&stack, CreateControlSymbol(STYPE0_STATUS, 0, 8, STYPE1_END_OF_PACKET, 0));
|
|
|
|
/* Check that packet was not received. */
|
|
TESTEXPR(RIO_eventPoll(&stack), RIO_EVENT_NONE);
|
|
|
|
/******************************************************************************/
|
|
TESTEND;
|
|
/******************************************************************************/
|
|
PrintS("----------------------------------------------------------------------");
|
|
PrintS("Step 5:");
|
|
PrintS("Action: Add four more status-control-symbols followed by one with error in ");
|
|
PrintS(" CRC5. Then send a packet.");
|
|
PrintS("Result: The receiver should remain in port initialized and packet should ");
|
|
PrintS(" still be ignored.");
|
|
PrintS("----------------------------------------------------------------------");
|
|
/******************************************************************************/
|
|
TESTSTART("TG_riostack-TC1-Step5");
|
|
/*****************************************************************************/
|
|
|
|
/* Send 4 more status-control-symbols followed by one erronous. */
|
|
for(i = 0; i < 4; i++)
|
|
{
|
|
RIO_portAddSymbol(&stack, CreateControlSymbol(STYPE0_STATUS, 0, 1, STYPE1_NOP, 0));
|
|
}
|
|
c = CreateControlSymbol(STYPE0_STATUS, 0, 1, STYPE1_NOP, 0);
|
|
c.data ^= 1;
|
|
RIO_portAddSymbol(&stack, c);
|
|
|
|
/* Send a packet. Note that the start and end of the packet contains status. */
|
|
packetLength = createDoorbell(packet, 0, 0, 0, 0, 0);
|
|
RIO_portAddSymbol(&stack, CreateControlSymbol(STYPE0_STATUS, 0, 8, STYPE1_START_OF_PACKET, 0));
|
|
for(i = 0; i < packetLength; i++)
|
|
{
|
|
d.type = RIO_SYMBOL_TYPE_DATA;
|
|
d.data = packet[i];
|
|
RIO_portAddSymbol(&stack, d);
|
|
}
|
|
RIO_portAddSymbol(&stack, CreateControlSymbol(STYPE0_STATUS, 0, 8, STYPE1_END_OF_PACKET, 0));
|
|
|
|
/* Check that the packet was ignored. */
|
|
TESTEXPR(RIO_eventPoll(&stack), RIO_EVENT_NONE);
|
|
|
|
/******************************************************************************/
|
|
TESTEND;
|
|
/******************************************************************************/
|
|
PrintS("----------------------------------------------------------------------");
|
|
PrintS("Step 6:");
|
|
PrintS("Action: Add six more status-control-symbols. Then send a packet.");
|
|
PrintS("Result: The receiver should enter link initialized and the packet should ");
|
|
PrintS(" be received.");
|
|
PrintS("----------------------------------------------------------------------");
|
|
/******************************************************************************/
|
|
TESTSTART("TG_riostack-TC1-Step6");
|
|
/*****************************************************************************/
|
|
|
|
/* Send 6 more status-control-symbols. */
|
|
for(i = 0; i < 6; i++)
|
|
{
|
|
RIO_portAddSymbol(&stack, CreateControlSymbol(STYPE0_STATUS, 0, 1, STYPE1_NOP, 0));
|
|
}
|
|
|
|
/* Send a packet and check that it is accepted. */
|
|
/* The ackId on receiver in testobject is updated when this has been transmitted. */
|
|
packetLength = createDoorbell(packet, 0, 0, 0, 0, 0);
|
|
RIO_portAddSymbol(&stack, CreateControlSymbol(STYPE0_STATUS, 0, 8, STYPE1_START_OF_PACKET, 0));
|
|
for(i = 0; i < packetLength; i++)
|
|
{
|
|
d.type = RIO_SYMBOL_TYPE_DATA;
|
|
d.data = packet[i];
|
|
RIO_portAddSymbol(&stack, d);
|
|
}
|
|
RIO_portAddSymbol(&stack, CreateControlSymbol(STYPE0_STATUS, 0, 8, STYPE1_END_OF_PACKET, 0));
|
|
|
|
/* Check that the packet is received. */
|
|
TESTEXPR(RIO_eventPoll(&stack), RIO_EVENT_DOORBELL);
|
|
|
|
/******************************************************************************/
|
|
TESTEND;
|
|
/******************************************************************************/
|
|
PrintS("----------------------------------------------------------------------");
|
|
PrintS("Step 7:");
|
|
PrintS("Action: Get symbols from transmitter.");
|
|
PrintS("Result: Status-control-symbols should still be generated each 15 symbol ");
|
|
PrintS("until a total of 15 status-control-symbols has been transmitted. Once these ");
|
|
PrintS("has been transmitted, the transmitter will be link initialized.");
|
|
PrintS("----------------------------------------------------------------------");
|
|
/******************************************************************************/
|
|
TESTSTART("TG_riostack-TC1-Step7");
|
|
/*****************************************************************************/
|
|
|
|
/* Note that the available buffers in the receiver should have decremented once
|
|
since the previously received packet has not been read from the application
|
|
side of the stack yet. */
|
|
for(j = 0; j < 14; j++)
|
|
{
|
|
for(i = 0; i < 15; i++)
|
|
{
|
|
s = RIO_portGetSymbol(&stack);
|
|
TESTEXPR(s.type, RIO_SYMBOL_TYPE_IDLE);
|
|
}
|
|
s = RIO_portGetSymbol(&stack);
|
|
c = CreateControlSymbol(STYPE0_STATUS, 1, 7, STYPE1_NOP, 0);
|
|
TESTEXPR(s.type, c.type);
|
|
TESTEXPR(s.data, c.data);
|
|
}
|
|
|
|
/******************************************************************************/
|
|
TESTEND;
|
|
/******************************************************************************/
|
|
PrintS("----------------------------------------------------------------------");
|
|
PrintS("Step 8:");
|
|
PrintS("Action: Get the first symbol from the transmitter once the link-intialized ");
|
|
PrintS(" state has been entered.");
|
|
PrintS("Result: A packet-accepted-symbol should be received for the newly received ");
|
|
PrintS(" packet.");
|
|
PrintS("----------------------------------------------------------------------");
|
|
/******************************************************************************/
|
|
TESTSTART("TG_riostack-TC1-Step8");
|
|
/*****************************************************************************/
|
|
|
|
c = CreateControlSymbol(STYPE0_PACKET_ACCEPTED, 0, 7, STYPE1_NOP, 0);
|
|
s = RIO_portGetSymbol(&stack);
|
|
TESTEXPR(s.type, c.type);
|
|
TESTEXPR(s.data, c.data);
|
|
|
|
/******************************************************************************/
|
|
TESTEND;
|
|
/******************************************************************************/
|
|
PrintS("----------------------------------------------------------------------");
|
|
PrintS("Step 9:");
|
|
PrintS("Action: Get the next symbols from the transmitter.");
|
|
PrintS("Result: The packet placed in the outbound queue at startup should be ");
|
|
PrintS(" received. Dont acknowledge the packet yet.");
|
|
PrintS("----------------------------------------------------------------------");
|
|
/******************************************************************************/
|
|
TESTSTART("TG_riostack-TC1-Step9");
|
|
/*****************************************************************************/
|
|
|
|
/* Create a packet. */
|
|
packetLength = createDoorbell(packet, 0, 1, 0xffff, 0, 0xdeaf);
|
|
|
|
/* Receive the start of the frame. */
|
|
c = CreateControlSymbol(STYPE0_STATUS, 1, 7, STYPE1_START_OF_PACKET, 0);
|
|
s = RIO_portGetSymbol(&stack);
|
|
TESTEXPR(s.type, c.type);
|
|
TESTEXPR(s.data, c.data);
|
|
|
|
/* Receive the data of the frame. */
|
|
for(i = 0; i < packetLength; i++)
|
|
{
|
|
s = RIO_portGetSymbol(&stack);
|
|
d.type = RIO_SYMBOL_TYPE_DATA;
|
|
d.data = packet[i];
|
|
TESTEXPR(s.type, d.type);
|
|
TESTEXPR(s.data, d.data);
|
|
}
|
|
|
|
/* Receive the end of the frame. */
|
|
c = CreateControlSymbol(STYPE0_STATUS, 1, 7, STYPE1_END_OF_PACKET, 0);
|
|
s = RIO_portGetSymbol(&stack);
|
|
TESTSYMBOL(s, c);
|
|
|
|
/******************************************************************************/
|
|
TESTEND;
|
|
/******************************************************************************/
|
|
PrintS("----------------------------------------------------------------------");
|
|
PrintS("Step 10:");
|
|
PrintS("Action: Remove the packet from the inbound queue. Dont acknowledge the");
|
|
PrintS(" transmitted packet yet.");
|
|
PrintS("Result: Check that status-control-symbols are sent each 256 symbol and that ");
|
|
PrintS(" the buffer count is updated when the inbound packet has been read.");
|
|
PrintS("----------------------------------------------------------------------");
|
|
/******************************************************************************/
|
|
TESTSTART("TG_riostack-TC1-Step10");
|
|
/*****************************************************************************/
|
|
|
|
/* Simulate the application reading the received packet to free one reception
|
|
buffer. */
|
|
RIO_packetRemove(&stack);
|
|
|
|
/* Check that the status-control-symbols are generated each 256 symbol. */
|
|
for(i = 0; i < 255; i++)
|
|
{
|
|
s = RIO_portGetSymbol(&stack);
|
|
TESTEXPR(s.type, RIO_SYMBOL_TYPE_IDLE);
|
|
}
|
|
|
|
/* Check that the buffer status has been updated. */
|
|
s = RIO_portGetSymbol(&stack);
|
|
c = CreateControlSymbol(STYPE0_STATUS, 1, 8, STYPE1_NOP, 0);
|
|
TESTEXPR(s.type, c.type);
|
|
TESTEXPR(s.data, c.data);
|
|
|
|
/******************************************************************************/
|
|
TESTEND;
|
|
/******************************************************************************/
|
|
PrintS("----------------------------------------------------------------------");
|
|
PrintS("Step 11:");
|
|
PrintS("Action: Send a packet when an acknowledge has not been received.");
|
|
PrintS("Result: Only idle and status control symbols should be transmitted until ");
|
|
PrintS(" the packet-accepted symbol has been received.");
|
|
PrintS("----------------------------------------------------------------------");
|
|
/******************************************************************************/
|
|
TESTSTART("TG_riostack-TC1-Step11");
|
|
/*****************************************************************************/
|
|
|
|
/* Place a packet in the outbound queue. */
|
|
RIO_sendDoorbell(&stack, 2, 1, 0xc0de);
|
|
|
|
packetLength = createDoorbell(packet, 1, 2, 0xffff, 1, 0xc0de);
|
|
|
|
/* Receive the start of the frame. */
|
|
c = CreateControlSymbol(STYPE0_STATUS, 1, 8, STYPE1_START_OF_PACKET, 0);
|
|
s = RIO_portGetSymbol(&stack);
|
|
TESTEXPR(s.type, c.type);
|
|
TESTEXPR(s.data, c.data);
|
|
|
|
/* Receive the data of the frame. */
|
|
for(i = 0; i < packetLength; i++)
|
|
{
|
|
s = RIO_portGetSymbol(&stack);
|
|
d.type = RIO_SYMBOL_TYPE_DATA;
|
|
d.data = packet[i];
|
|
TESTEXPR(s.type, d.type);
|
|
TESTEXPR(s.data, d.data);
|
|
}
|
|
|
|
/* Receive the end of the frame. */
|
|
c = CreateControlSymbol(STYPE0_STATUS, 1, 8, STYPE1_END_OF_PACKET, 0);
|
|
s = RIO_portGetSymbol(&stack);
|
|
TESTSYMBOL(s, c);
|
|
|
|
/******************************************************************************/
|
|
TESTEND;
|
|
/******************************************************************************/
|
|
PrintS("----------------------------------------------------------------------");
|
|
PrintS("Step 12:");
|
|
PrintS("Action: Send a packet-accepted symbol.");
|
|
PrintS("Result: Check that the new packet is transmitted.");
|
|
PrintS("----------------------------------------------------------------------");
|
|
/******************************************************************************/
|
|
TESTSTART("TG_riostack-TC1-Step12");
|
|
/*****************************************************************************/
|
|
|
|
/* Send acknowledge for the first frame. */
|
|
RIO_portAddSymbol(&stack, CreateControlSymbol(STYPE0_PACKET_ACCEPTED, 0, 1, STYPE1_NOP, 0));
|
|
|
|
/* Check that status-control-symbols are transmitted once every 256 symbol with
|
|
updated ackId. */
|
|
for(i = 0; i < 255; i++)
|
|
{
|
|
s = RIO_portGetSymbol(&stack);
|
|
TESTEXPR(s.type, RIO_SYMBOL_TYPE_IDLE);
|
|
}
|
|
s = RIO_portGetSymbol(&stack);
|
|
c = CreateControlSymbol(STYPE0_STATUS, 1, 8, STYPE1_NOP, 0);
|
|
TESTEXPR(s.type, c.type);
|
|
TESTEXPR(s.data, c.data);
|
|
|
|
/******************************************************************************/
|
|
TESTEND;
|
|
/******************************************************************************/
|
|
PrintS("----------------------------------------------------------------------");
|
|
PrintS("Step 13:");
|
|
PrintS("Action: Send a packet-accepted symbol.");
|
|
PrintS("Result: Check that only idle and status-control-symbols are transmitted ");
|
|
PrintS("----------------------------------------------------------------------");
|
|
/******************************************************************************/
|
|
TESTSTART("TG_riostack-TC1-Step13");
|
|
/*****************************************************************************/
|
|
|
|
/* Acknowledge the second frame. */
|
|
RIO_portAddSymbol(&stack, CreateControlSymbol(STYPE0_PACKET_ACCEPTED, 1, 1, STYPE1_NOP, 0));
|
|
|
|
/* Check that status-control-symbols are transmitted once every 256 symbol with
|
|
updated ackId. */
|
|
for(i = 0; i < 255; i++)
|
|
{
|
|
s = RIO_portGetSymbol(&stack);
|
|
TESTEXPR(s.type, RIO_SYMBOL_TYPE_IDLE);
|
|
}
|
|
s = RIO_portGetSymbol(&stack);
|
|
c = CreateControlSymbol(STYPE0_STATUS, 1, 8, STYPE1_NOP, 0);
|
|
TESTEXPR(s.type, c.type);
|
|
TESTEXPR(s.data, c.data);
|
|
|
|
/******************************************************************************/
|
|
TESTEND;
|
|
/******************************************************************************/
|
|
PrintS("----------------------------------------------------------------------");
|
|
PrintS("TG_riostack-TC2");
|
|
PrintS("Description: Test flow control.");
|
|
PrintS("Requirement: XXXXX");
|
|
PrintS("----------------------------------------------------------------------");
|
|
PrintS("Step 1:");
|
|
PrintS("Action: Send packets to receiver but don't acknowledge them.");
|
|
PrintS("Result: The reception queue of the stack is full.");
|
|
PrintS("----------------------------------------------------------------------");
|
|
/******************************************************************************/
|
|
TESTSTART("TG_riostack-TC2-Step1");
|
|
/******************************************************************************/
|
|
|
|
/* Fill input queue in receiver. */
|
|
for(j = 0; j < 8; j++)
|
|
{
|
|
packetLength = createDoorbell(packet, 1+j, 0, 0, 1+j, 0);
|
|
|
|
RIO_portAddSymbol(&stack, CreateControlSymbol(STYPE0_STATUS, 2, 1, STYPE1_START_OF_PACKET, 0));
|
|
for(i = 0; i < packetLength; i++)
|
|
{
|
|
d.type = RIO_SYMBOL_TYPE_DATA;
|
|
d.data = packet[i];
|
|
RIO_portAddSymbol(&stack, d);
|
|
}
|
|
RIO_portAddSymbol(&stack, CreateControlSymbol(STYPE0_STATUS, 2, 1, STYPE1_END_OF_PACKET, 0));
|
|
|
|
c = CreateControlSymbol(STYPE0_PACKET_ACCEPTED, 1+j, 7-j, STYPE1_NOP, 0);
|
|
s = RIO_portGetSymbol(&stack);
|
|
TESTEXPR(s.type, c.type);
|
|
TESTEXPR(s.data, c.data);
|
|
}
|
|
|
|
/******************************************************************************/
|
|
TESTEND;
|
|
/******************************************************************************/
|
|
PrintS("----------------------------------------------------------------------");
|
|
PrintS("Step 2:");
|
|
PrintS("Action: Send a packet when the inbound queue of the stack is full.");
|
|
PrintS("Result: The stack sends a packet-retry symbol. The receiver will end up in ");
|
|
PrintS("input-retry-stopped state.");
|
|
PrintS("----------------------------------------------------------------------");
|
|
/******************************************************************************/
|
|
TESTSTART("TG_riostack-TC2-Step2");
|
|
/******************************************************************************/
|
|
|
|
/* Send another packet. */
|
|
packetLength = createDoorbell(packet, 9, 0, 0, 9, 0);
|
|
RIO_portAddSymbol(&stack, CreateControlSymbol(STYPE0_STATUS, 2, 1, STYPE1_START_OF_PACKET, 0));
|
|
for(i = 0; i < packetLength; i++)
|
|
{
|
|
d.type = RIO_SYMBOL_TYPE_DATA;
|
|
d.data = packet[i];
|
|
RIO_portAddSymbol(&stack, d);
|
|
}
|
|
RIO_portAddSymbol(&stack, CreateControlSymbol(STYPE0_STATUS, 2, 1, STYPE1_END_OF_PACKET, 0));
|
|
|
|
/* Receive indication from stack that the packet must be retried. */
|
|
c = CreateControlSymbol(STYPE0_PACKET_RETRY, 9, 0, STYPE1_NOP, 0);
|
|
s = RIO_portGetSymbol(&stack);
|
|
TESTEXPR(s.type, c.type);
|
|
TESTEXPR(s.data, c.data);
|
|
|
|
/******************************************************************************/
|
|
TESTEND;
|
|
/******************************************************************************/
|
|
PrintS("----------------------------------------------------------------------");
|
|
PrintS("Step 3:");
|
|
PrintS("Action: Send a packet when the receiver is in input-retry-stopped.");
|
|
PrintS("Result: The receiver should ignore the new packet.");
|
|
PrintS("----------------------------------------------------------------------");
|
|
/******************************************************************************/
|
|
TESTSTART("TG_riostack-TC2-Step3");
|
|
/******************************************************************************/
|
|
|
|
/* Resend the packet. */
|
|
packetLength = createDoorbell(packet, 9, 0, 0, 9, 0);
|
|
RIO_portAddSymbol(&stack, CreateControlSymbol(STYPE0_STATUS, 2, 1, STYPE1_START_OF_PACKET, 0));
|
|
for(i = 0; i < packetLength; i++)
|
|
{
|
|
d.type = RIO_SYMBOL_TYPE_DATA;
|
|
d.data = packet[i];
|
|
RIO_portAddSymbol(&stack, d);
|
|
}
|
|
RIO_portAddSymbol(&stack, CreateControlSymbol(STYPE0_STATUS, 2, 1, STYPE1_END_OF_PACKET, 0));
|
|
s = RIO_portGetSymbol(&stack);
|
|
|
|
/* Check that nothing is transmitted. */
|
|
TESTEXPR(s.type, RIO_SYMBOL_TYPE_IDLE);
|
|
|
|
/* REMARK: Send other symbols here to check that they are handled as expected... */
|
|
|
|
/******************************************************************************/
|
|
TESTEND;
|
|
/******************************************************************************/
|
|
PrintS("----------------------------------------------------------------------");
|
|
PrintS("Step 4:");
|
|
PrintS("Action: Send restart-from-retry and resend the previous packet.");
|
|
PrintS("Result: The receiver should leave the input-retry-stopped state and receive ");
|
|
PrintS(" the new frame.");
|
|
PrintS("----------------------------------------------------------------------");
|
|
/******************************************************************************/
|
|
TESTSTART("TG_riostack-TC2-Step4");
|
|
/******************************************************************************/
|
|
|
|
/* Send restart-from-retry. */
|
|
RIO_portAddSymbol(&stack, CreateControlSymbol(STYPE0_STATUS, 2, 1, STYPE1_RESTART_FROM_RETRY, 0));
|
|
|
|
/* Check that the transaction id is correct and remove a packet from the inbound
|
|
queue. One entry in the inbound queue will be empty. */
|
|
RIO_receiveDoorbell(&stack, &srcid, &tid, &info);
|
|
TESTEXPR(tid, 1);
|
|
RIO_packetRemove(&stack);
|
|
|
|
/* Check that the buffer status has changed to show that a buffer is available. */
|
|
s = RIO_portGetSymbol(&stack);
|
|
while(s.type == RIO_SYMBOL_TYPE_IDLE)
|
|
{
|
|
s = RIO_portGetSymbol(&stack);
|
|
}
|
|
c = CreateControlSymbol(STYPE0_STATUS, 9, 1, STYPE1_NOP, 0);
|
|
TESTEXPR(s.type, c.type);
|
|
TESTEXPR(s.data, c.data);
|
|
|
|
/* Resend the packet and check that it is received. */
|
|
packetLength = createDoorbell(packet, 9, 0, 0, 9, 0);
|
|
RIO_portAddSymbol(&stack, CreateControlSymbol(STYPE0_STATUS, 2, 1, STYPE1_START_OF_PACKET, 0));
|
|
for(i = 0; i < packetLength; i++)
|
|
{
|
|
d.type = RIO_SYMBOL_TYPE_DATA;
|
|
d.data = packet[i];
|
|
RIO_portAddSymbol(&stack, d);
|
|
}
|
|
RIO_portAddSymbol(&stack, CreateControlSymbol(STYPE0_STATUS, 2, 1, STYPE1_END_OF_PACKET, 0));
|
|
c = CreateControlSymbol(STYPE0_PACKET_ACCEPTED, 9, 0, STYPE1_NOP, 0);
|
|
s = RIO_portGetSymbol(&stack);
|
|
TESTEXPR(s.type, c.type);
|
|
TESTEXPR(s.data, c.data);
|
|
|
|
/******************************************************************************/
|
|
TESTEND;
|
|
/******************************************************************************/
|
|
PrintS("----------------------------------------------------------------------");
|
|
PrintS("Step 5:");
|
|
PrintS("Action: Place receiver in input-retry-stopped state.");
|
|
PrintS("Result: Check that packets may be transmitted normally.");
|
|
PrintS("----------------------------------------------------------------------");
|
|
/******************************************************************************/
|
|
TESTSTART("TG_riostack-TC2-Step5");
|
|
/******************************************************************************/
|
|
|
|
/* Send another packet and check that the receiver indicates that it should be retried. */
|
|
packetLength = createDoorbell(packet, 10, 0, 0, 10, 0);
|
|
RIO_portAddSymbol(&stack, CreateControlSymbol(STYPE0_STATUS, 2, 1, STYPE1_START_OF_PACKET, 0));
|
|
for(i = 0; i < packetLength; i++)
|
|
{
|
|
d.type = RIO_SYMBOL_TYPE_DATA;
|
|
d.data = packet[i];
|
|
RIO_portAddSymbol(&stack, d);
|
|
}
|
|
RIO_portAddSymbol(&stack, CreateControlSymbol(STYPE0_STATUS, 2, 1, STYPE1_END_OF_PACKET, 0));
|
|
c = CreateControlSymbol(STYPE0_PACKET_RETRY, 10, 0, STYPE1_NOP, 0);
|
|
s = RIO_portGetSymbol(&stack);
|
|
TESTEXPR(s.type, c.type);
|
|
TESTEXPR(s.data, c.data);
|
|
|
|
/* Send two packets to see that the first acknowledge has been processed. */
|
|
RIO_sendDoorbell(&stack, 0, 2, 0xfeed);
|
|
RIO_sendDoorbell(&stack, 0, 3, 0xdeed);
|
|
|
|
/* Get the first packet. */
|
|
packetLength = createDoorbell(packet, 2, 0, 0xffff, 2, 0xfeed);
|
|
c = CreateControlSymbol(STYPE0_STATUS, 10, 0, STYPE1_START_OF_PACKET, 0);
|
|
s = RIO_portGetSymbol(&stack);
|
|
TESTEXPR(s.type, c.type);
|
|
TESTEXPR(s.data, c.data);
|
|
for(i = 0; i < packetLength; i++)
|
|
{
|
|
s = RIO_portGetSymbol(&stack);
|
|
d.type = RIO_SYMBOL_TYPE_DATA;
|
|
d.data = packet[i];
|
|
TESTEXPR(s.type, d.type);
|
|
TESTEXPR(s.data, d.data);
|
|
}
|
|
|
|
/* Get the second packet. */
|
|
packetLength = createDoorbell(packet, 3, 0, 0xffff, 3, 0xdeed);
|
|
c = CreateControlSymbol(STYPE0_STATUS, 10, 0, STYPE1_START_OF_PACKET, 0);
|
|
s = RIO_portGetSymbol(&stack);
|
|
TESTSYMBOL(s, c);
|
|
for(i = 0; i < packetLength; i++)
|
|
{
|
|
s = RIO_portGetSymbol(&stack);
|
|
d.type = RIO_SYMBOL_TYPE_DATA;
|
|
d.data = packet[i];
|
|
TESTEXPR(s.type, d.type);
|
|
TESTEXPR(s.data, d.data);
|
|
}
|
|
c = CreateControlSymbol(STYPE0_STATUS, 10, 0, STYPE1_END_OF_PACKET, 0);
|
|
s = RIO_portGetSymbol(&stack);
|
|
TESTEXPR(s.type, c.type);
|
|
TESTEXPR(s.data, c.data);
|
|
|
|
/* Indicate the packets must be retransmitted. */
|
|
RIO_portAddSymbol(&stack, CreateControlSymbol(STYPE0_PACKET_RETRY, 2, 1, STYPE1_NOP, 0));
|
|
|
|
/* Receive confirmation that the packet will be retransmitted. */
|
|
c = CreateControlSymbol(STYPE0_STATUS, 10, 0, STYPE1_RESTART_FROM_RETRY, 0);
|
|
s = RIO_portGetSymbol(&stack);
|
|
TESTSYMBOL(s, c);
|
|
|
|
/* Get the retransmission of the first packet. */
|
|
packetLength = createDoorbell(packet, 2, 0, 0xffff, 2, 0xfeed);
|
|
c = CreateControlSymbol(STYPE0_STATUS, 10, 0, STYPE1_START_OF_PACKET, 0);
|
|
s = RIO_portGetSymbol(&stack);
|
|
TESTEXPR(s.type, c.type);
|
|
TESTEXPR(s.data, c.data);
|
|
for(i = 0; i < packetLength; i++)
|
|
{
|
|
s = RIO_portGetSymbol(&stack);
|
|
d.type = RIO_SYMBOL_TYPE_DATA;
|
|
d.data = packet[i];
|
|
TESTEXPR(s.type, d.type);
|
|
TESTEXPR(s.data, d.data);
|
|
}
|
|
|
|
/* Get the retransmission of the second packet. */
|
|
packetLength = createDoorbell(packet, 3, 0, 0xffff, 3, 0xdeed);
|
|
c = CreateControlSymbol(STYPE0_STATUS, 10, 0, STYPE1_START_OF_PACKET, 0);
|
|
s = RIO_portGetSymbol(&stack);
|
|
TESTSYMBOL(s, c);
|
|
for(i = 0; i < packetLength; i++)
|
|
{
|
|
s = RIO_portGetSymbol(&stack);
|
|
d.type = RIO_SYMBOL_TYPE_DATA;
|
|
d.data = packet[i];
|
|
TESTEXPR(s.type, d.type);
|
|
TESTEXPR(s.data, d.data);
|
|
}
|
|
c = CreateControlSymbol(STYPE0_STATUS, 10, 0, STYPE1_END_OF_PACKET, 0);
|
|
s = RIO_portGetSymbol(&stack);
|
|
TESTEXPR(s.type, c.type);
|
|
TESTEXPR(s.data, c.data);
|
|
|
|
/* Confirm the reception of the packets. */
|
|
RIO_portAddSymbol(&stack, CreateControlSymbol(STYPE0_PACKET_ACCEPTED, 2, 1, STYPE1_NOP, 0));
|
|
RIO_portAddSymbol(&stack, CreateControlSymbol(STYPE0_PACKET_ACCEPTED, 3, 1, STYPE1_NOP, 0));
|
|
|
|
/******************************************************************************/
|
|
TESTEND;
|
|
/******************************************************************************/
|
|
PrintS("----------------------------------------------------------------------");
|
|
PrintS("Step 6:");
|
|
PrintS("Action: Send status-control-symbol to show that no packets can be ");
|
|
PrintS(" transmitted.");
|
|
PrintS("Result: No packets should be transmitted.");
|
|
PrintS("----------------------------------------------------------------------");
|
|
/******************************************************************************/
|
|
TESTSTART("TG_riostack-TC2-Step6");
|
|
/******************************************************************************/
|
|
|
|
/* Send status with bufferStatus set to zero. */
|
|
RIO_portAddSymbol(&stack, CreateControlSymbol(STYPE0_STATUS, 4, 0, STYPE1_NOP, 0));
|
|
|
|
/* Send a packet. */
|
|
RIO_sendDoorbell(&stack, 0, 4, 0xf00d);
|
|
|
|
/* Check that nothing is transmitted but status-control-symbols. */
|
|
for(i = 0; i < 255; i++)
|
|
{
|
|
s = RIO_portGetSymbol(&stack);
|
|
TESTEXPR(s.type, RIO_SYMBOL_TYPE_IDLE);
|
|
}
|
|
s = RIO_portGetSymbol(&stack);
|
|
c = CreateControlSymbol(STYPE0_STATUS, 10, 0, STYPE1_NOP, 0);
|
|
TESTEXPR(s.type, c.type);
|
|
TESTEXPR(s.data, c.data);
|
|
|
|
/******************************************************************************/
|
|
TESTEND;
|
|
/******************************************************************************/
|
|
PrintS("----------------------------------------------------------------------");
|
|
PrintS("Step 7:");
|
|
PrintS("Action: Indicate free buffers and receive a frame, then request it to be ");
|
|
PrintS("retried.");
|
|
PrintS("Result: The packet should be retransmitted.");
|
|
PrintS("----------------------------------------------------------------------");
|
|
/******************************************************************************/
|
|
TESTSTART("TG_riostack-TC2-Step7");
|
|
/******************************************************************************/
|
|
|
|
/* Send status with bufferStatus set to available. */
|
|
RIO_portAddSymbol(&stack, CreateControlSymbol(STYPE0_STATUS, 4, 1, STYPE1_NOP, 0));
|
|
|
|
/* Get the packet but request it to be retried. */
|
|
packetLength = createDoorbell(packet, 4, 0, 0xffff, 4, 0xf00d);
|
|
c = CreateControlSymbol(STYPE0_STATUS, 10, 0, STYPE1_START_OF_PACKET, 0);
|
|
s = RIO_portGetSymbol(&stack);
|
|
TESTEXPR(s.type, c.type);
|
|
TESTEXPR(s.data, c.data);
|
|
for(i = 0; i < packetLength; i++)
|
|
{
|
|
s = RIO_portGetSymbol(&stack);
|
|
d.type = RIO_SYMBOL_TYPE_DATA;
|
|
d.data = packet[i];
|
|
TESTEXPR(s.type, d.type);
|
|
TESTEXPR(s.data, d.data);
|
|
}
|
|
c = CreateControlSymbol(STYPE0_STATUS, 10, 0, STYPE1_END_OF_PACKET, 0);
|
|
s = RIO_portGetSymbol(&stack);
|
|
TESTEXPR(s.type, c.type);
|
|
TESTEXPR(s.data, c.data);
|
|
RIO_portAddSymbol(&stack, CreateControlSymbol(STYPE0_PACKET_RETRY, 4, 1, STYPE1_NOP, 0));
|
|
|
|
/* Check the acknowledge of the retransmission. */
|
|
c = CreateControlSymbol(STYPE0_STATUS, 10, 0, STYPE1_RESTART_FROM_RETRY, 0);
|
|
s = RIO_portGetSymbol(&stack);
|
|
TESTEXPR(s.type, c.type);
|
|
TESTEXPR(s.data, c.data);
|
|
|
|
/* Get the packet and acknowledge it. */
|
|
packetLength = createDoorbell(packet, 4, 0, 0xffff, 4, 0xf00d);
|
|
c = CreateControlSymbol(STYPE0_STATUS, 10, 0, STYPE1_START_OF_PACKET, 0);
|
|
s = RIO_portGetSymbol(&stack);
|
|
TESTEXPR(s.type, c.type);
|
|
TESTEXPR(s.data, c.data);
|
|
for(i = 0; i < packetLength; i++)
|
|
{
|
|
s = RIO_portGetSymbol(&stack);
|
|
d.type = RIO_SYMBOL_TYPE_DATA;
|
|
d.data = packet[i];
|
|
TESTEXPR(s.type, d.type);
|
|
TESTEXPR(s.data, d.data);
|
|
}
|
|
c = CreateControlSymbol(STYPE0_STATUS, 10, 0, STYPE1_END_OF_PACKET, 0);
|
|
s = RIO_portGetSymbol(&stack);
|
|
TESTEXPR(s.type, c.type);
|
|
TESTEXPR(s.data, c.data);
|
|
RIO_portAddSymbol(&stack, CreateControlSymbol(STYPE0_PACKET_ACCEPTED, 4, 1, STYPE1_NOP, 0));
|
|
|
|
/******************************************************************************/
|
|
TESTEND;
|
|
/******************************************************************************/
|
|
PrintS("----------------------------------------------------------------------");
|
|
PrintS("Step 8:");
|
|
PrintS("Action: Read all inbound packets from the reception queue.");
|
|
PrintS("Result: The buffer status should be updated.");
|
|
PrintS("----------------------------------------------------------------------");
|
|
/******************************************************************************/
|
|
TESTSTART("TG_riostack-TC2-Step8");
|
|
/******************************************************************************/
|
|
|
|
for(j = 0; j < 8; j++)
|
|
{
|
|
RIO_receiveDoorbell(&stack, &srcid, &tid, &info);
|
|
TESTEXPR(tid, j+2);
|
|
RIO_packetRemove(&stack);
|
|
|
|
for(i = 0; i < 255; i++)
|
|
{
|
|
s = RIO_portGetSymbol(&stack);
|
|
TESTEXPR(s.type, RIO_SYMBOL_TYPE_IDLE);
|
|
}
|
|
s = RIO_portGetSymbol(&stack);
|
|
c = CreateControlSymbol(STYPE0_STATUS, 10, j+1, STYPE1_NOP, 0);
|
|
TESTEXPR(s.type, c.type);
|
|
TESTEXPR(s.data, c.data);
|
|
}
|
|
|
|
/******************************************************************************/
|
|
TESTEND;
|
|
/******************************************************************************/
|
|
PrintS("----------------------------------------------------------------------");
|
|
PrintS("Step 9:");
|
|
PrintS("Action: Send a restart-from-retry to make the receiver leave the ");
|
|
PrintS(" input-retry-stopped state.");
|
|
PrintS("Result: New packets should be received again.");
|
|
PrintS("----------------------------------------------------------------------");
|
|
/******************************************************************************/
|
|
TESTSTART("TG_riostack-TC2-Step9");
|
|
/******************************************************************************/
|
|
|
|
/* Send restart-from-retry. */
|
|
RIO_portAddSymbol(&stack, CreateControlSymbol(STYPE0_STATUS, 5, 1, STYPE1_RESTART_FROM_RETRY, 0));
|
|
|
|
|
|
/******************************************************************************/
|
|
TESTEND;
|
|
/******************************************************************************/
|
|
PrintS("----------------------------------------------------------------------");
|
|
PrintS("TG_riostack-TC3");
|
|
PrintS("Description: Test receiver error handling.");
|
|
PrintS("Requirement: XXXXX");
|
|
PrintS("----------------------------------------------------------------------");
|
|
PrintS("Step 1:");
|
|
PrintS("Action: Send invalid ack id in packet.");
|
|
PrintS("Result: Input-error-stopped state should be entered and link-response ");
|
|
PrintS(" should indicate an ackId error.");
|
|
PrintS("----------------------------------------------------------------------");
|
|
/******************************************************************************/
|
|
TESTSTART("TG_riostack-TC3-Step1");
|
|
/******************************************************************************/
|
|
|
|
/* Send packet with invalid ackId, same as sent previously. */
|
|
packetLength = createDoorbell(packet, 9, 0, 0, 10, 0);
|
|
RIO_portAddSymbol(&stack, CreateControlSymbol(STYPE0_STATUS, 5, 1, STYPE1_START_OF_PACKET, 0));
|
|
for(i = 0; i < packetLength; i++)
|
|
{
|
|
d.type = RIO_SYMBOL_TYPE_DATA;
|
|
d.data = packet[i];
|
|
RIO_portAddSymbol(&stack, d);
|
|
}
|
|
RIO_portAddSymbol(&stack, CreateControlSymbol(STYPE0_STATUS, 5, 1, STYPE1_END_OF_PACKET, 0));
|
|
|
|
/* Check that the packet is not accepted with cause error in ackId. */
|
|
c = CreateControlSymbol(STYPE0_PACKET_NOT_ACCEPTED, 0, 1, STYPE1_NOP, 0);
|
|
s = RIO_portGetSymbol(&stack);
|
|
TESTEXPR(s.type, c.type);
|
|
TESTEXPR(s.data, c.data);
|
|
|
|
/* Send a link-request. */
|
|
RIO_portAddSymbol(&stack, CreateControlSymbol(STYPE0_STATUS, 5, 1,
|
|
STYPE1_LINK_REQUEST, LINK_REQUEST_INPUT_STATUS));
|
|
|
|
/* Check that a link-response is returned. */
|
|
/* Note that the status of the input-port will be reported as ok since a
|
|
link-request has been received. */
|
|
c = CreateControlSymbol(STYPE0_LINK_RESPONSE, 10, 16, STYPE1_NOP, 0);
|
|
s = RIO_portGetSymbol(&stack);
|
|
TESTEXPR(s.type, c.type);
|
|
TESTEXPR(s.data, c.data);
|
|
|
|
/* Check that a status is transmitted directly after the link-response. */
|
|
c = CreateControlSymbol(STYPE0_STATUS, 10, 8, STYPE1_NOP, 0);
|
|
s = RIO_portGetSymbol(&stack);
|
|
TESTEXPR(s.type, c.type);
|
|
TESTEXPR(s.data, c.data);
|
|
|
|
/******************************************************************************/
|
|
TESTEND;
|
|
/******************************************************************************/
|
|
PrintS("----------------------------------------------------------------------");
|
|
PrintS("Step 2:");
|
|
PrintS("Action: Send packet with invalid CRC.");
|
|
PrintS("Result: Input-error-stopped state should be entered and link-response ");
|
|
PrintS(" should indicate a CRC error.");
|
|
PrintS("----------------------------------------------------------------------");
|
|
/******************************************************************************/
|
|
TESTSTART("TG_riostack-TC3-Step2");
|
|
/******************************************************************************/
|
|
|
|
/* Send packet with invalid crc. */
|
|
packetLength = createDoorbell(packet, 10, 0, 0, 10, 0);
|
|
packet[0] ^= 0x00000001;
|
|
RIO_portAddSymbol(&stack, CreateControlSymbol(STYPE0_STATUS, 5, 1, STYPE1_START_OF_PACKET, 0));
|
|
for(i = 0; i < packetLength; i++)
|
|
{
|
|
d.type = RIO_SYMBOL_TYPE_DATA;
|
|
d.data = packet[i];
|
|
RIO_portAddSymbol(&stack, d);
|
|
}
|
|
RIO_portAddSymbol(&stack, CreateControlSymbol(STYPE0_STATUS, 5, 1, STYPE1_END_OF_PACKET, 0));
|
|
|
|
/* Check that the packet is not accepted with cause error in ackId. */
|
|
c = CreateControlSymbol(STYPE0_PACKET_NOT_ACCEPTED, 0, 4, STYPE1_NOP, 0);
|
|
s = RIO_portGetSymbol(&stack);
|
|
TESTEXPR(s.type, c.type);
|
|
TESTEXPR(s.data, c.data);
|
|
|
|
/* Send a link-request. */
|
|
RIO_portAddSymbol(&stack, CreateControlSymbol(STYPE0_STATUS, 5, 1,
|
|
STYPE1_LINK_REQUEST, LINK_REQUEST_INPUT_STATUS));
|
|
|
|
/* Check that a link-response is returned. */
|
|
/* Note that the status of the input-port will be reported as ok since a
|
|
link-request has been received. */
|
|
c = CreateControlSymbol(STYPE0_LINK_RESPONSE, 10, 16, STYPE1_NOP, 0);
|
|
s = RIO_portGetSymbol(&stack);
|
|
TESTEXPR(s.type, c.type);
|
|
TESTEXPR(s.data, c.data);
|
|
|
|
/* Check that a status is transmitted directly after the link-response. */
|
|
c = CreateControlSymbol(STYPE0_STATUS, 10, 8, STYPE1_NOP, 0);
|
|
s = RIO_portGetSymbol(&stack);
|
|
TESTEXPR(s.type, c.type);
|
|
TESTEXPR(s.data, c.data);
|
|
|
|
/******************************************************************************/
|
|
TESTEND;
|
|
/******************************************************************************/
|
|
PrintS("----------------------------------------------------------------------");
|
|
PrintS("Step 3:");
|
|
PrintS("Action: Send a packet that is too short.");
|
|
PrintS("Result: Input-error-stopped state should be entered and link-response ");
|
|
PrintS(" should indicate a packet error.");
|
|
PrintS("----------------------------------------------------------------------");
|
|
/******************************************************************************/
|
|
TESTSTART("TG_riostack-TC3-Step3");
|
|
/******************************************************************************/
|
|
|
|
/* Send packet with valid ackid and crc but too short. */
|
|
packetLength = createDoorbell(packet, 10, 0, 0, 10, 0);
|
|
RIO_portAddSymbol(&stack, CreateControlSymbol(STYPE0_STATUS, 5, 1, STYPE1_START_OF_PACKET, 0));
|
|
d.type = RIO_SYMBOL_TYPE_DATA;
|
|
d.data = packet[0];
|
|
RIO_portAddSymbol(&stack, d);
|
|
d.type = RIO_SYMBOL_TYPE_DATA;
|
|
d.data = ((uint32_t) Crc32(packet[0] & 0x07ffffff, 0xffff)) << 16;
|
|
RIO_portAddSymbol(&stack, d);
|
|
RIO_portAddSymbol(&stack, CreateControlSymbol(STYPE0_STATUS, 5, 1, STYPE1_END_OF_PACKET, 0));
|
|
|
|
/* Check that the packet is not accepted with cause error in ackId. */
|
|
c = CreateControlSymbol(STYPE0_PACKET_NOT_ACCEPTED, 0, 31, STYPE1_NOP, 0);
|
|
s = RIO_portGetSymbol(&stack);
|
|
TESTEXPR(s.type, c.type);
|
|
TESTEXPR(s.data, c.data);
|
|
|
|
/* Send a link-request. */
|
|
RIO_portAddSymbol(&stack, CreateControlSymbol(STYPE0_STATUS, 5, 1,
|
|
STYPE1_LINK_REQUEST, LINK_REQUEST_INPUT_STATUS));
|
|
|
|
/* Check that a link-response is returned. */
|
|
/* Note that the status of the input-port will be reported as ok since a
|
|
link-request has been received. */
|
|
c = CreateControlSymbol(STYPE0_LINK_RESPONSE, 10, 16, STYPE1_NOP, 0);
|
|
s = RIO_portGetSymbol(&stack);
|
|
TESTEXPR(s.type, c.type);
|
|
TESTEXPR(s.data, c.data);
|
|
|
|
/* Check that a status is transmitted directly after the link-response. */
|
|
c = CreateControlSymbol(STYPE0_STATUS, 10, 8, STYPE1_NOP, 0);
|
|
s = RIO_portGetSymbol(&stack);
|
|
TESTEXPR(s.type, c.type);
|
|
TESTEXPR(s.data, c.data);
|
|
|
|
/******************************************************************************/
|
|
TESTEND;
|
|
/******************************************************************************/
|
|
PrintS("----------------------------------------------------------------------");
|
|
PrintS("Step 4:");
|
|
PrintS("Action: Send a packet that is too long.");
|
|
PrintS("Result: Input-error-stopped state should be entered and link-response ");
|
|
PrintS(" should indicate a packet error.");
|
|
PrintS("----------------------------------------------------------------------");
|
|
/******************************************************************************/
|
|
TESTSTART("TG_riostack-TC3-Step4");
|
|
/******************************************************************************/
|
|
|
|
/* Send packet with too many data symbols and without a end-of-packet. */
|
|
packetLength = createDoorbell(packet, 10, 0, 0, 10, 0);
|
|
RIO_portAddSymbol(&stack, CreateControlSymbol(STYPE0_STATUS, 5, 1, STYPE1_START_OF_PACKET, 0));
|
|
for(i = 0; i < 70; i++)
|
|
{
|
|
d.type = RIO_SYMBOL_TYPE_DATA;
|
|
d.data = packet[i];
|
|
RIO_portAddSymbol(&stack, d);
|
|
}
|
|
|
|
/* Check that the packet is not accepted with cause error in ackId. */
|
|
c = CreateControlSymbol(STYPE0_PACKET_NOT_ACCEPTED, 0, 31, STYPE1_NOP, 0);
|
|
s = RIO_portGetSymbol(&stack);
|
|
TESTEXPR(s.type, c.type);
|
|
TESTEXPR(s.data, c.data);
|
|
|
|
/* Send a link-request. */
|
|
RIO_portAddSymbol(&stack, CreateControlSymbol(STYPE0_STATUS, 5, 1,
|
|
STYPE1_LINK_REQUEST, LINK_REQUEST_INPUT_STATUS));
|
|
|
|
/* Check that a link-response is returned. */
|
|
/* Note that the status of the input-port will be reported as ok since a
|
|
link-request has been received. */
|
|
c = CreateControlSymbol(STYPE0_LINK_RESPONSE, 10, 16, STYPE1_NOP, 0);
|
|
s = RIO_portGetSymbol(&stack);
|
|
TESTEXPR(s.type, c.type);
|
|
TESTEXPR(s.data, c.data);
|
|
|
|
/* Check that a status is transmitted directly after the link-response. */
|
|
c = CreateControlSymbol(STYPE0_STATUS, 10, 8, STYPE1_NOP, 0);
|
|
s = RIO_portGetSymbol(&stack);
|
|
TESTEXPR(s.type, c.type);
|
|
TESTEXPR(s.data, c.data);
|
|
|
|
/******************************************************************************/
|
|
TESTEND;
|
|
/******************************************************************************/
|
|
PrintS("----------------------------------------------------------------------");
|
|
PrintS("Step 5:");
|
|
PrintS("Action: Send a data symbol without starting a packet.");
|
|
PrintS("Result: Input-error-stopped state should be entered and link-response ");
|
|
PrintS(" should indicate a packet error.");
|
|
PrintS("----------------------------------------------------------------------");
|
|
/******************************************************************************/
|
|
TESTSTART("TG_riostack-TC3-Step5");
|
|
/******************************************************************************/
|
|
|
|
/* Send a data symbol. */
|
|
packetLength = createDoorbell(packet, 10, 0, 0, 10, 0);
|
|
d.type = RIO_SYMBOL_TYPE_DATA;
|
|
d.data = packet[0];
|
|
RIO_portAddSymbol(&stack, d);
|
|
|
|
/* Check that the packet is not accepted with cause error in ackId. */
|
|
c = CreateControlSymbol(STYPE0_PACKET_NOT_ACCEPTED, 0, 31, STYPE1_NOP, 0);
|
|
s = RIO_portGetSymbol(&stack);
|
|
TESTEXPR(s.type, c.type);
|
|
TESTEXPR(s.data, c.data);
|
|
|
|
/* Send a link-request. */
|
|
RIO_portAddSymbol(&stack, CreateControlSymbol(STYPE0_STATUS, 5, 1,
|
|
STYPE1_LINK_REQUEST, LINK_REQUEST_INPUT_STATUS));
|
|
|
|
/* Check that a link-response is returned. */
|
|
/* Note that the status of the input-port will be reported as ok since a
|
|
link-request has been received. */
|
|
c = CreateControlSymbol(STYPE0_LINK_RESPONSE, 10, 16, STYPE1_NOP, 0);
|
|
s = RIO_portGetSymbol(&stack);
|
|
TESTEXPR(s.type, c.type);
|
|
TESTEXPR(s.data, c.data);
|
|
|
|
/* Check that a status is transmitted directly after the link-response. */
|
|
c = CreateControlSymbol(STYPE0_STATUS, 10, 8, STYPE1_NOP, 0);
|
|
s = RIO_portGetSymbol(&stack);
|
|
TESTEXPR(s.type, c.type);
|
|
TESTEXPR(s.data, c.data);
|
|
|
|
/******************************************************************************/
|
|
TESTEND;
|
|
/******************************************************************************/
|
|
PrintS("----------------------------------------------------------------------");
|
|
PrintS("Step 6:");
|
|
PrintS("Action: Send end-of-packet without matching start.");
|
|
PrintS("Result: Input-error-stopped state should be entered and link-response ");
|
|
PrintS(" should indicate a packet error.");
|
|
PrintS("----------------------------------------------------------------------");
|
|
/******************************************************************************/
|
|
TESTSTART("TG_riostack-TC3-Step6");
|
|
/******************************************************************************/
|
|
|
|
/* Send end-of-packet. */
|
|
RIO_portAddSymbol(&stack, CreateControlSymbol(STYPE0_STATUS, 5, 1, STYPE1_END_OF_PACKET, 0));
|
|
|
|
/* Check that the packet is not accepted with cause error in ackId. */
|
|
c = CreateControlSymbol(STYPE0_PACKET_NOT_ACCEPTED, 0, 31, STYPE1_NOP, 0);
|
|
s = RIO_portGetSymbol(&stack);
|
|
TESTEXPR(s.type, c.type);
|
|
TESTEXPR(s.data, c.data);
|
|
|
|
/* Send a link-request. */
|
|
RIO_portAddSymbol(&stack, CreateControlSymbol(STYPE0_STATUS, 5, 1,
|
|
STYPE1_LINK_REQUEST, LINK_REQUEST_INPUT_STATUS));
|
|
|
|
/* Check that a link-response is returned. */
|
|
/* Note that the status of the input-port will be reported as ok since a
|
|
link-request has been received. */
|
|
c = CreateControlSymbol(STYPE0_LINK_RESPONSE, 10, 16, STYPE1_NOP, 0);
|
|
s = RIO_portGetSymbol(&stack);
|
|
TESTEXPR(s.type, c.type);
|
|
TESTEXPR(s.data, c.data);
|
|
|
|
/* Check that a status is transmitted directly after the link-response. */
|
|
c = CreateControlSymbol(STYPE0_STATUS, 10, 8, STYPE1_NOP, 0);
|
|
s = RIO_portGetSymbol(&stack);
|
|
TESTEXPR(s.type, c.type);
|
|
TESTEXPR(s.data, c.data);
|
|
|
|
/******************************************************************************/
|
|
TESTEND;
|
|
/******************************************************************************/
|
|
PrintS("----------------------------------------------------------------------");
|
|
PrintS("Step 7:");
|
|
PrintS("Action: Send a symbol indicating a codec error.");
|
|
PrintS("Result: Input-error-stopped state should be entered and link-response ");
|
|
PrintS(" should indicate a symbol error.");
|
|
PrintS("----------------------------------------------------------------------");
|
|
/******************************************************************************/
|
|
TESTSTART("TG_riostack-TC3-Step7");
|
|
/******************************************************************************/
|
|
|
|
/* Send error-symbol. */
|
|
s.type = RIO_SYMBOL_TYPE_ERROR;
|
|
RIO_portAddSymbol(&stack, s);
|
|
|
|
/* Check that the packet is not accepted with cause error in ackId. */
|
|
c = CreateControlSymbol(STYPE0_PACKET_NOT_ACCEPTED, 0, 5, STYPE1_NOP, 0);
|
|
s = RIO_portGetSymbol(&stack);
|
|
TESTEXPR(s.type, c.type);
|
|
TESTEXPR(s.data, c.data);
|
|
|
|
/* Send a link-request. */
|
|
RIO_portAddSymbol(&stack, CreateControlSymbol(STYPE0_STATUS, 5, 1,
|
|
STYPE1_LINK_REQUEST, LINK_REQUEST_INPUT_STATUS));
|
|
|
|
/* Check that a link-response is returned. */
|
|
/* Note that the status of the input-port will be reported as ok since a
|
|
link-request has been received. */
|
|
c = CreateControlSymbol(STYPE0_LINK_RESPONSE, 10, 16, STYPE1_NOP, 0);
|
|
s = RIO_portGetSymbol(&stack);
|
|
TESTEXPR(s.type, c.type);
|
|
TESTEXPR(s.data, c.data);
|
|
|
|
/* Check that a status is transmitted directly after the link-response. */
|
|
c = CreateControlSymbol(STYPE0_STATUS, 10, 8, STYPE1_NOP, 0);
|
|
s = RIO_portGetSymbol(&stack);
|
|
TESTEXPR(s.type, c.type);
|
|
TESTEXPR(s.data, c.data);
|
|
|
|
/******************************************************************************/
|
|
TESTEND;
|
|
/******************************************************************************/
|
|
PrintS("----------------------------------------------------------------------");
|
|
PrintS("TG_riostack-TC4");
|
|
PrintS("Description: Test transmitter error handling.");
|
|
PrintS("Requirement: XXXXX");
|
|
PrintS("----------------------------------------------------------------------");
|
|
PrintS("Step 1:");
|
|
PrintS("Action: Send acknowledge for a frame that has not been transmitted and ");
|
|
PrintS(" without any frame being expected.");
|
|
PrintS("Result: The transmitter should enter output-error-stopped and send ");
|
|
PrintS(" link-request.");
|
|
PrintS("----------------------------------------------------------------------");
|
|
/******************************************************************************/
|
|
TESTSTART("TG_riostack-TC4-Step1");
|
|
/******************************************************************************/
|
|
|
|
/* Packet acknowledge for unsent frame. */
|
|
RIO_portAddSymbol(&stack, CreateControlSymbol(STYPE0_PACKET_ACCEPTED, 5, 1, STYPE1_NOP, 0));
|
|
|
|
/* Check that a link-request is received as the transmitter enters
|
|
output-error-stopped state. */
|
|
c = CreateControlSymbol(STYPE0_STATUS, 10, 8,
|
|
STYPE1_LINK_REQUEST, LINK_REQUEST_INPUT_STATUS);
|
|
s = RIO_portGetSymbol(&stack);
|
|
TESTEXPR(s.type, c.type);
|
|
TESTEXPR(s.data, c.data);
|
|
|
|
/* Send link-response with expected ackId. */
|
|
RIO_portAddSymbol(&stack, CreateControlSymbol(STYPE0_LINK_RESPONSE, 5, 16, STYPE1_NOP, 0));
|
|
|
|
/* Send a status directly afterwards. */
|
|
RIO_portAddSymbol(&stack, CreateControlSymbol(STYPE0_STATUS, 5, 1, STYPE1_NOP, 0));
|
|
|
|
/* Check that packets are relayed after this. */
|
|
RIO_sendDoorbell(&stack, 0, 5, 2);
|
|
packetLength = createDoorbell(packet, 5, 0, 0xffff, 5, 2);
|
|
c = CreateControlSymbol(STYPE0_STATUS, 10, 8, STYPE1_START_OF_PACKET, 0);
|
|
s = RIO_portGetSymbol(&stack);
|
|
TESTEXPR(s.type, c.type);
|
|
TESTEXPR(s.data, c.data);
|
|
for(i = 0; i < packetLength; i++)
|
|
{
|
|
s = RIO_portGetSymbol(&stack);
|
|
d.type = RIO_SYMBOL_TYPE_DATA;
|
|
d.data = packet[i];
|
|
TESTEXPR(s.type, d.type);
|
|
TESTEXPR(s.data, d.data);
|
|
}
|
|
c = CreateControlSymbol(STYPE0_STATUS, 10, 8, STYPE1_END_OF_PACKET, 0);
|
|
s = RIO_portGetSymbol(&stack);
|
|
TESTEXPR(s.type, c.type);
|
|
TESTEXPR(s.data, c.data);
|
|
RIO_portAddSymbol(&stack, CreateControlSymbol(STYPE0_PACKET_ACCEPTED, 5, 1, STYPE1_NOP, 0));
|
|
|
|
/******************************************************************************/
|
|
TESTEND;
|
|
/******************************************************************************/
|
|
PrintS("----------------------------------------------------------------------");
|
|
PrintS("Step 2:");
|
|
PrintS("Action: Send a packet and send acknowledge for a previous frame. Then send ");
|
|
PrintS(" a link-response indicating that the packet was received (accepted ");
|
|
PrintS(" but reply corrupted).");
|
|
PrintS("Result: The transmitter should enter output-error-stopped state and send ");
|
|
PrintS(" link-request and proceed with the next packet.");
|
|
PrintS("----------------------------------------------------------------------");
|
|
/******************************************************************************/
|
|
TESTSTART("TG_riostack-TC4-Step2");
|
|
/******************************************************************************/
|
|
|
|
/* Send a packet. */
|
|
RIO_sendDoorbell(&stack, 0, 6, 2);
|
|
packetLength = createDoorbell(packet, 6, 0, 0xffff, 6, 2);
|
|
c = CreateControlSymbol(STYPE0_STATUS, 10, 8, STYPE1_START_OF_PACKET, 0);
|
|
s = RIO_portGetSymbol(&stack);
|
|
TESTEXPR(s.type, c.type);
|
|
TESTEXPR(s.data, c.data);
|
|
for(i = 0; i < packetLength; i++)
|
|
{
|
|
s = RIO_portGetSymbol(&stack);
|
|
d.type = RIO_SYMBOL_TYPE_DATA;
|
|
d.data = packet[i];
|
|
TESTEXPR(s.type, d.type);
|
|
TESTEXPR(s.data, d.data);
|
|
}
|
|
c = CreateControlSymbol(STYPE0_STATUS, 10, 8, STYPE1_END_OF_PACKET, 0);
|
|
s = RIO_portGetSymbol(&stack);
|
|
TESTEXPR(s.type, c.type);
|
|
TESTEXPR(s.data, c.data);
|
|
|
|
/* Send acknowledge for another packet. */
|
|
RIO_portAddSymbol(&stack, CreateControlSymbol(STYPE0_PACKET_ACCEPTED, 5, 1, STYPE1_NOP, 0));
|
|
|
|
/* Check that a link-request is received as the transmitter enters
|
|
output-error-stopped state. */
|
|
c = CreateControlSymbol(STYPE0_STATUS, 10, 8,
|
|
STYPE1_LINK_REQUEST, LINK_REQUEST_INPUT_STATUS);
|
|
s = RIO_portGetSymbol(&stack);
|
|
TESTEXPR(s.type, c.type);
|
|
TESTEXPR(s.data, c.data);
|
|
|
|
/* Send link-response with expected ackId. */
|
|
RIO_portAddSymbol(&stack, CreateControlSymbol(STYPE0_LINK_RESPONSE, 7, 16, STYPE1_NOP, 0));
|
|
|
|
/* Send a status directly afterwards. */
|
|
RIO_portAddSymbol(&stack, CreateControlSymbol(STYPE0_STATUS, 7, 1, STYPE1_NOP, 0));
|
|
|
|
/******************************************************************************/
|
|
TESTEND;
|
|
/******************************************************************************/
|
|
PrintS("----------------------------------------------------------------------");
|
|
PrintS("Step 3:");
|
|
PrintS("Action: Send a packet and let the packet-accepted time out. Then send a ");
|
|
PrintS(" link-response indicating that the packet was not received.");
|
|
PrintS("Result: The transmitter should enter output-error-stopped state, send a");
|
|
PrintS(" link-request and then resend the packet.");
|
|
PrintS("----------------------------------------------------------------------");
|
|
/******************************************************************************/
|
|
TESTSTART("TG_riostack-TC4-Step3");
|
|
/******************************************************************************/
|
|
|
|
/* Set the time at frame transmission. */
|
|
RIO_portSetTime(&stack, 2);
|
|
|
|
/* Send an output packet. */
|
|
RIO_sendDoorbell(&stack, 0, 7, 2);
|
|
|
|
/* Receive the transmitted packet. */
|
|
packetLength = createDoorbell(packet, 7, 0, 0xffff, 7, 2);
|
|
c = CreateControlSymbol(STYPE0_STATUS, 10, 8, STYPE1_START_OF_PACKET, 0);
|
|
s = RIO_portGetSymbol(&stack);
|
|
TESTEXPR(s.type, c.type);
|
|
TESTEXPR(s.data, c.data);
|
|
for(i = 0; i < packetLength; i++)
|
|
{
|
|
s = RIO_portGetSymbol(&stack);
|
|
d.type = RIO_SYMBOL_TYPE_DATA;
|
|
d.data = packet[i];
|
|
TESTEXPR(s.type, d.type);
|
|
TESTEXPR(s.data, d.data);
|
|
}
|
|
c = CreateControlSymbol(STYPE0_STATUS, 10, 8, STYPE1_END_OF_PACKET, 0);
|
|
s = RIO_portGetSymbol(&stack);
|
|
TESTEXPR(s.type, c.type);
|
|
TESTEXPR(s.data, c.data);
|
|
|
|
/* Indicate that time has passed to trigger a timeout. */
|
|
RIO_portSetTime(&stack, 3);
|
|
|
|
/* Check that a link-request is received as the transmitter enters
|
|
output-error-stopped state. */
|
|
c = CreateControlSymbol(STYPE0_STATUS, 10, 8,
|
|
STYPE1_LINK_REQUEST, LINK_REQUEST_INPUT_STATUS);
|
|
s = RIO_portGetSymbol(&stack);
|
|
TESTEXPR(s.type, c.type);
|
|
TESTEXPR(s.data, c.data);
|
|
|
|
/* Send link-response with expected ackId. */
|
|
RIO_portAddSymbol(&stack, CreateControlSymbol(STYPE0_LINK_RESPONSE, 7, 16, STYPE1_NOP, 0));
|
|
|
|
/* Send a status directly afterwards. */
|
|
RIO_portAddSymbol(&stack, CreateControlSymbol(STYPE0_STATUS, 7, 1, STYPE1_NOP, 0));
|
|
|
|
/* Receive retransmitted packet. */
|
|
c = CreateControlSymbol(STYPE0_STATUS, 10, 8, STYPE1_START_OF_PACKET, 0);
|
|
s = RIO_portGetSymbol(&stack);
|
|
TESTEXPR(s.type, c.type);
|
|
TESTEXPR(s.data, c.data);
|
|
for(i = 0; i < packetLength; i++)
|
|
{
|
|
s = RIO_portGetSymbol(&stack);
|
|
d.type = RIO_SYMBOL_TYPE_DATA;
|
|
d.data = packet[i];
|
|
TESTEXPR(s.type, d.type);
|
|
TESTEXPR(s.data, d.data);
|
|
}
|
|
c = CreateControlSymbol(STYPE0_STATUS, 10, 8, STYPE1_END_OF_PACKET, 0);
|
|
s = RIO_portGetSymbol(&stack);
|
|
TESTEXPR(s.type, c.type);
|
|
TESTEXPR(s.data, c.data);
|
|
|
|
/* Send acknowledge for the retransmitted packet. */
|
|
RIO_portAddSymbol(&stack, CreateControlSymbol(STYPE0_PACKET_ACCEPTED, 7, 1, STYPE1_NOP, 0));
|
|
|
|
/******************************************************************************/
|
|
TESTEND;
|
|
/******************************************************************************/
|
|
PrintS("----------------------------------------------------------------------");
|
|
PrintS("Step 4:");
|
|
PrintS("Action: Send a packet and then indicate that the packet was not accepted. ");
|
|
PrintS(" Then send a link-response indicating that the packet was not received.");
|
|
PrintS("Result: The transmitter should enter output-error-stopped state, send a");
|
|
PrintS(" link-request and then resend the packet.");
|
|
PrintS("----------------------------------------------------------------------");
|
|
/******************************************************************************/
|
|
TESTSTART("TG_riostack-TC4-Step4");
|
|
/******************************************************************************/
|
|
|
|
/* Send an output packet. */
|
|
RIO_sendDoorbell(&stack, 0, 8, 3);
|
|
|
|
/* Receive the transmitted packet. */
|
|
packetLength = createDoorbell(packet, 8, 0, 0xffff, 8, 3);
|
|
c = CreateControlSymbol(STYPE0_STATUS, 10, 8, STYPE1_START_OF_PACKET, 0);
|
|
s = RIO_portGetSymbol(&stack);
|
|
TESTEXPR(s.type, c.type);
|
|
TESTEXPR(s.data, c.data);
|
|
for(i = 0; i < packetLength; i++)
|
|
{
|
|
s = RIO_portGetSymbol(&stack);
|
|
d.type = RIO_SYMBOL_TYPE_DATA;
|
|
d.data = packet[i];
|
|
TESTEXPR(s.type, d.type);
|
|
TESTEXPR(s.data, d.data);
|
|
}
|
|
c = CreateControlSymbol(STYPE0_STATUS, 10, 8, STYPE1_END_OF_PACKET, 0);
|
|
s = RIO_portGetSymbol(&stack);
|
|
TESTEXPR(s.type, c.type);
|
|
TESTEXPR(s.data, c.data);
|
|
|
|
/* Send packet-not-accepted indicating CRC error. */
|
|
RIO_portAddSymbol(&stack, CreateControlSymbol(STYPE0_PACKET_NOT_ACCEPTED, 0, 4, STYPE1_NOP, 0));
|
|
|
|
/* Check that a link-request is received as the transmitter enters
|
|
output-error-stopped state. */
|
|
c = CreateControlSymbol(STYPE0_STATUS, 10, 8,
|
|
STYPE1_LINK_REQUEST, LINK_REQUEST_INPUT_STATUS);
|
|
s = RIO_portGetSymbol(&stack);
|
|
TESTEXPR(s.type, c.type);
|
|
TESTEXPR(s.data, c.data);
|
|
|
|
/* Send link-response with expected ackId. */
|
|
RIO_portAddSymbol(&stack, CreateControlSymbol(STYPE0_LINK_RESPONSE, 8, 16, STYPE1_NOP, 0));
|
|
|
|
/* Send a status directly afterwards. */
|
|
RIO_portAddSymbol(&stack, CreateControlSymbol(STYPE0_STATUS, 8, 1, STYPE1_NOP, 0));
|
|
|
|
/* Receive retransmitted packet. */
|
|
c = CreateControlSymbol(STYPE0_STATUS, 10, 8, STYPE1_START_OF_PACKET, 0);
|
|
s = RIO_portGetSymbol(&stack);
|
|
TESTEXPR(s.type, c.type);
|
|
TESTEXPR(s.data, c.data);
|
|
for(i = 0; i < packetLength; i++)
|
|
{
|
|
s = RIO_portGetSymbol(&stack);
|
|
d.type = RIO_SYMBOL_TYPE_DATA;
|
|
d.data = packet[i];
|
|
TESTEXPR(s.type, d.type);
|
|
TESTEXPR(s.data, d.data);
|
|
}
|
|
c = CreateControlSymbol(STYPE0_STATUS, 10, 8, STYPE1_END_OF_PACKET, 0);
|
|
s = RIO_portGetSymbol(&stack);
|
|
TESTEXPR(s.type, c.type);
|
|
TESTEXPR(s.data, c.data);
|
|
|
|
/* Send acknowledge for the retransmitted packet. */
|
|
RIO_portAddSymbol(&stack, CreateControlSymbol(STYPE0_PACKET_ACCEPTED, 8, 1, STYPE1_NOP, 0));
|
|
|
|
/******************************************************************************/
|
|
TESTEND;
|
|
/******************************************************************************/
|
|
PrintS("----------------------------------------------------------------------");
|
|
PrintS("Step 5:");
|
|
PrintS("Action: Send a packet-retry for an unexpected packet. Then send a");
|
|
PrintS(" link-response indicating the expected ackId and a normal packet.");
|
|
PrintS("Result: The transmitter should enter output-error-stopped state, send a");
|
|
PrintS(" link-request and then the normal packet.");
|
|
PrintS("----------------------------------------------------------------------");
|
|
/******************************************************************************/
|
|
TESTSTART("TG_riostack-TC4-Step5");
|
|
/******************************************************************************/
|
|
|
|
/* Send packet-retry indicating that a packet should be retransmitted. */
|
|
RIO_portAddSymbol(&stack, CreateControlSymbol(STYPE0_PACKET_RETRY, 8, 1, STYPE1_NOP, 0));
|
|
|
|
/* Check that a link-request is received as the transmitter enters
|
|
output-error-stopped state. */
|
|
c = CreateControlSymbol(STYPE0_STATUS, 10, 8,
|
|
STYPE1_LINK_REQUEST, LINK_REQUEST_INPUT_STATUS);
|
|
s = RIO_portGetSymbol(&stack);
|
|
TESTEXPR(s.type, c.type);
|
|
TESTEXPR(s.data, c.data);
|
|
|
|
/* Send link-response with expected ackId. */
|
|
RIO_portAddSymbol(&stack, CreateControlSymbol(STYPE0_LINK_RESPONSE, 9, 16, STYPE1_NOP, 0));
|
|
|
|
/* Send a status directly afterwards. */
|
|
RIO_portAddSymbol(&stack, CreateControlSymbol(STYPE0_STATUS, 9, 1, STYPE1_NOP, 0));
|
|
|
|
/* Send an output packet. */
|
|
RIO_sendDoorbell(&stack, 0, 9, 4);
|
|
|
|
/* Receive retransmitted packet. */
|
static void handleLinkResponse(RioStack_t *stack, const uint8_t ackId, const uint8_t portStatus)
|
packetLength = createDoorbell(packet, 9, 0, 0xffff, 9, 4);
|
|
c = CreateControlSymbol(STYPE0_STATUS, 10, 8, STYPE1_START_OF_PACKET, 0);
|
|
s = RIO_portGetSymbol(&stack);
|
|
TESTEXPR(s.type, c.type);
|
|
TESTEXPR(s.data, c.data);
|
|
for(i = 0; i < packetLength; i++)
|
|
{
|
{
|
s = RIO_portGetSymbol(&stack);
|
uint8_t window;
|
d.type = RIO_SYMBOL_TYPE_DATA;
|
uint8_t windowReceived;
|
d.data = packet[i];
|
|
TESTEXPR(s.type, d.type);
|
|
TESTEXPR(s.data, d.data);
|
|
}
|
|
c = CreateControlSymbol(STYPE0_STATUS, 10, 8, STYPE1_END_OF_PACKET, 0);
|
|
s = RIO_portGetSymbol(&stack);
|
|
TESTEXPR(s.type, c.type);
|
|
TESTEXPR(s.data, c.data);
|
|
|
|
/* Send acknowledge for the retransmitted packet. */
|
|
RIO_portAddSymbol(&stack, CreateControlSymbol(STYPE0_PACKET_ACCEPTED, 9, 1, STYPE1_NOP, 0));
|
|
|
|
/******************************************************************************/
|
|
TESTEND;
|
|
/******************************************************************************/
|
|
PrintS("----------------------------------------------------------------------");
|
|
PrintS("Step 6:");
|
|
PrintS("Action: Fill outbound queue with packets, then check retransmission when ");
|
|
PrintS(" packet-retry is encountered. ");
|
|
PrintS("Result: Packets should be retried until packet-accepted is received.");
|
|
PrintS("----------------------------------------------------------------------");
|
|
/******************************************************************************/
|
|
TESTSTART("TG_riostack-TC4-Step6");
|
|
/******************************************************************************/
|
|
|
|
TESTCOND(RIO_sendAvailable(&stack, 0));
|
|
RIO_sendDoorbell(&stack, 0, 20, 0xbabe);
|
|
|
|
TESTCOND(RIO_sendAvailable(&stack, 0));
|
|
RIO_sendDoorbell(&stack, 0, 21, 0xbabe);
|
|
|
|
TESTCOND(RIO_sendAvailable(&stack, 0));
|
|
RIO_sendDoorbell(&stack, 0, 22, 0xbabe);
|
|
|
|
TESTCOND(RIO_sendAvailable(&stack, 0));
|
|
RIO_sendDoorbell(&stack, 0, 23, 0xbabe);
|
|
|
|
TESTCOND(RIO_sendAvailable(&stack, 0));
|
|
RIO_sendDoorbell(&stack, 0, 24, 0xbabe);
|
|
|
|
TESTCOND(RIO_sendAvailable(&stack, 0));
|
|
RIO_sendDoorbell(&stack, 0, 25, 0xbabe);
|
|
|
|
TESTCOND(RIO_sendAvailable(&stack, 0));
|
|
RIO_sendDoorbell(&stack, 0, 26, 0xbabe);
|
|
|
|
TESTCOND(RIO_sendAvailable(&stack, 0));
|
|
RIO_sendDoorbell(&stack, 0, 27, 0xbabe);
|
|
|
|
TESTCOND(!RIO_sendAvailable(&stack, 0));
|
(void) portStatus;
|
|
|
/* Receive transmitted packet. */
|
/* Check if this symbols is expected. */
|
packetLength = createDoorbell(packet, 10, 0, 0xffff, 20, 0xbabe);
|
if(stack->txState == TX_STATE_OUTPUT_ERROR_STOPPED)
|
c = CreateControlSymbol(STYPE0_STATUS, 10, 8, STYPE1_START_OF_PACKET, 0);
|
|
s = RIO_portGetSymbol(&stack);
|
|
TESTEXPR(s.type, c.type);
|
|
TESTEXPR(s.data, c.data);
|
|
for(i = 0; i < packetLength; i++)
|
|
{
|
|
s = RIO_portGetSymbol(&stack);
|
|
d.type = RIO_SYMBOL_TYPE_DATA;
|
|
d.data = packet[i];
|
|
TESTEXPR(s.type, d.type);
|
|
TESTEXPR(s.data, d.data);
|
|
}
|
|
packetLength = createDoorbell(packet, 11, 0, 0xffff, 21, 0xbabe);
|
|
c = CreateControlSymbol(STYPE0_STATUS, 10, 8, STYPE1_START_OF_PACKET, 0);
|
|
s = RIO_portGetSymbol(&stack);
|
|
TESTEXPR(s.type, c.type);
|
|
TESTEXPR(s.data, c.data);
|
|
for(i = 0; i < packetLength; i++)
|
|
{
|
{
|
s = RIO_portGetSymbol(&stack);
|
/* Calculate the number of packets that has not received an acknowledge on our side and
|
d.type = RIO_SYMBOL_TYPE_DATA;
|
on the link-partner side. */
|
d.data = packet[i];
|
window = (stack->txAckIdWindow - stack->txAckId) & 0x1f;
|
TESTEXPR(s.type, d.type);
|
windowReceived = (ackId - stack->txAckId) & 0x1f;
|
TESTEXPR(s.data, d.data);
|
|
}
|
/* Check if the link-partners response is acceptable. */
|
packetLength = createDoorbell(packet, 12, 0, 0xffff, 22, 0xbabe);
|
if(windowReceived <= window)
|
c = CreateControlSymbol(STYPE0_STATUS, 10, 8, STYPE1_START_OF_PACKET, 0);
|
|
s = RIO_portGetSymbol(&stack);
|
|
TESTEXPR(s.type, c.type);
|
|
TESTEXPR(s.data, c.data);
|
|
for(i = 0; i < packetLength; i++)
|
|
{
|
{
|
s = RIO_portGetSymbol(&stack);
|
/* A link-response is expected. */
|
d.type = RIO_SYMBOL_TYPE_DATA;
|
|
d.data = packet[i];
|
/* Remove entries in the queue that the link-partner has sent acknowledges for that has been lost. */
|
TESTEXPR(s.type, d.type);
|
while(stack->txAckId != ackId)
|
TESTEXPR(s.data, d.data);
|
|
}
|
|
packetLength = createDoorbell(packet, 13, 0, 0xffff, 23, 0xbabe);
|
|
c = CreateControlSymbol(STYPE0_STATUS, 10, 8, STYPE1_START_OF_PACKET, 0);
|
|
s = RIO_portGetSymbol(&stack);
|
|
TESTEXPR(s.type, c.type);
|
|
TESTEXPR(s.data, c.data);
|
|
for(i = 0; i < packetLength; i++)
|
|
{
|
{
|
s = RIO_portGetSymbol(&stack);
|
stack->txQueue = QueueDequeue(stack->txQueue);
|
d.type = RIO_SYMBOL_TYPE_DATA;
|
stack->txAckId = ACKID_INC(stack->txAckId);
|
d.data = packet[i];
|
stack->statusOutboundPacketComplete++;
|
TESTEXPR(s.type, d.type);
|
|
TESTEXPR(s.data, d.data);
|
|
}
|
}
|
packetLength = createDoorbell(packet, 14, 0, 0xffff, 24, 0xbabe);
|
|
c = CreateControlSymbol(STYPE0_STATUS, 10, 8, STYPE1_START_OF_PACKET, 0);
|
/* Set the transmission window to the resend packets that has not been received. */
|
s = RIO_portGetSymbol(&stack);
|
stack->txQueue = QueueWindowReset(stack->txQueue);
|
TESTEXPR(s.type, c.type);
|
stack->txAckIdWindow = ackId;
|
TESTEXPR(s.data, c.data);
|
stack->txFrameState = TX_FRAME_START;
|
for(i = 0; i < packetLength; i++)
|
|
{
|
/* Set the transmitter back into normal operation. */
|
s = RIO_portGetSymbol(&stack);
|
stack->txState = TX_STATE_LINK_INITIALIZED;
|
d.type = RIO_SYMBOL_TYPE_DATA;
|
|
d.data = packet[i];
|
|
TESTEXPR(s.type, d.type);
|
|
TESTEXPR(s.data, d.data);
|
|
}
|
}
|
packetLength = createDoorbell(packet, 15, 0, 0xffff, 25, 0xbabe);
|
else
|
c = CreateControlSymbol(STYPE0_STATUS, 10, 8, STYPE1_START_OF_PACKET, 0);
|
|
s = RIO_portGetSymbol(&stack);
|
|
TESTEXPR(s.type, c.type);
|
|
TESTEXPR(s.data, c.data);
|
|
for(i = 0; i < packetLength; i++)
|
|
{
|
{
|
s = RIO_portGetSymbol(&stack);
|
/* The link-partner response is unacceptable. */
|
d.type = RIO_SYMBOL_TYPE_DATA;
|
/* Recovery is not possible. */
|
d.data = packet[i];
|
stack->txState = TX_STATE_UNINITIALIZED;
|
TESTEXPR(s.type, d.type);
|
ASSERT0("Unrecoverable protocol error.");
|
TESTEXPR(s.data, d.data);
|
|
}
|
}
|
packetLength = createDoorbell(packet, 16, 0, 0xffff, 26, 0xbabe);
|
|
c = CreateControlSymbol(STYPE0_STATUS, 10, 8, STYPE1_START_OF_PACKET, 0);
|
|
s = RIO_portGetSymbol(&stack);
|
|
TESTEXPR(s.type, c.type);
|
|
TESTEXPR(s.data, c.data);
|
|
for(i = 0; i < packetLength; i++)
|
|
{
|
|
s = RIO_portGetSymbol(&stack);
|
|
d.type = RIO_SYMBOL_TYPE_DATA;
|
|
d.data = packet[i];
|
|
TESTEXPR(s.type, d.type);
|
|
TESTEXPR(s.data, d.data);
|
|
}
|
}
|
packetLength = createDoorbell(packet, 17, 0, 0xffff, 27, 0xbabe);
|
else
|
c = CreateControlSymbol(STYPE0_STATUS, 10, 8, STYPE1_START_OF_PACKET, 0);
|
|
s = RIO_portGetSymbol(&stack);
|
|
TESTEXPR(s.type, c.type);
|
|
TESTEXPR(s.data, c.data);
|
|
for(i = 0; i < packetLength; i++)
|
|
{
|
{
|
s = RIO_portGetSymbol(&stack);
|
/* Not expecting a link-response. */
|
d.type = RIO_SYMBOL_TYPE_DATA;
|
/* Just discard this symbol. */
|
d.data = packet[i];
|
/* REMARK: Add status counter here??? */
|
TESTEXPR(s.type, d.type);
|
|
TESTEXPR(s.data, d.data);
|
|
}
|
}
|
c = CreateControlSymbol(STYPE0_STATUS, 10, 8, STYPE1_END_OF_PACKET, 0);
|
|
s = RIO_portGetSymbol(&stack);
|
|
TESTEXPR(s.type, c.type);
|
|
TESTEXPR(s.data, c.data);
|
|
|
|
for(i = 0; i < 10; i++)
|
|
{
|
|
s = RIO_portGetSymbol(&stack);
|
|
TESTEXPR(s.type, RIO_SYMBOL_TYPE_IDLE);
|
|
}
|
}
|
|
|
/* Request retransmission. */
|
|
RIO_portAddSymbol(&stack, CreateControlSymbol(STYPE0_PACKET_RETRY, 10, 1, STYPE1_NOP, 0));
|
|
|
|
/* Acknowledge retransmission. */
|
|
c = CreateControlSymbol(STYPE0_STATUS, 10, 8, STYPE1_RESTART_FROM_RETRY, 0);
|
|
s = RIO_portGetSymbol(&stack);
|
|
TESTEXPR(s.type, c.type);
|
|
TESTEXPR(s.data, c.data);
|
|
|
|
/* Check retransmitted packets. */
|
static void handleStartOfPacket(RioStack_t *stack)
|
packetLength = createDoorbell(packet, 10, 0, 0xffff, 20, 0xbabe);
|
|
c = CreateControlSymbol(STYPE0_STATUS, 10, 8, STYPE1_START_OF_PACKET, 0);
|
|
s = RIO_portGetSymbol(&stack);
|
|
TESTEXPR(s.type, c.type);
|
|
TESTEXPR(s.data, c.data);
|
|
for(i = 0; i < packetLength; i++)
|
|
{
|
{
|
s = RIO_portGetSymbol(&stack);
|
/* Check if a packet is already started. */
|
d.type = RIO_SYMBOL_TYPE_DATA;
|
if(stack->rxCounter != 0u)
|
d.data = packet[i];
|
|
TESTEXPR(s.type, d.type);
|
|
TESTEXPR(s.data, d.data);
|
|
}
|
|
packetLength = createDoorbell(packet, 11, 0, 0xffff, 21, 0xbabe);
|
|
c = CreateControlSymbol(STYPE0_STATUS, 10, 8, STYPE1_START_OF_PACKET, 0);
|
|
s = RIO_portGetSymbol(&stack);
|
|
TESTEXPR(s.type, c.type);
|
|
TESTEXPR(s.data, c.data);
|
|
for(i = 0; i < packetLength; i++)
|
|
{
|
{
|
s = RIO_portGetSymbol(&stack);
|
/* Packet has already started. */
|
d.type = RIO_SYMBOL_TYPE_DATA;
|
/* This indicates an implicit end-of-packet symbol and signals the previous packet as ready. */
|
d.data = packet[i];
|
|
TESTEXPR(s.type, d.type);
|
/* Check the packet crc. */
|
TESTEXPR(s.data, d.data);
|
if(stack->rxCrc == 0x0000u)
|
}
|
|
packetLength = createDoorbell(packet, 12, 0, 0xffff, 22, 0xbabe);
|
|
c = CreateControlSymbol(STYPE0_STATUS, 10, 8, STYPE1_START_OF_PACKET, 0);
|
|
s = RIO_portGetSymbol(&stack);
|
|
TESTEXPR(s.type, c.type);
|
|
TESTEXPR(s.data, c.data);
|
|
for(i = 0; i < packetLength; i++)
|
|
{
|
{
|
s = RIO_portGetSymbol(&stack);
|
/* The packet has a correct CRC. */
|
d.type = RIO_SYMBOL_TYPE_DATA;
|
|
d.data = packet[i];
|
|
TESTEXPR(s.type, d.type);
|
|
TESTEXPR(s.data, d.data);
|
|
}
|
|
|
|
/* Acknowledge. */
|
/* Check if the packet is long enough to contain a complete packet. */
|
RIO_portAddSymbol(&stack, CreateControlSymbol(STYPE0_PACKET_ACCEPTED, 10, 1, STYPE1_NOP, 0));
|
if(stack->rxCounter > 3u)
|
RIO_portAddSymbol(&stack, CreateControlSymbol(STYPE0_PACKET_ACCEPTED, 11, 1, STYPE1_NOP, 0));
|
{
|
|
/* Packet long enough to process. */
|
|
|
packetLength = createDoorbell(packet, 13, 0, 0xffff, 23, 0xbabe);
|
/* Process the newly received packet and start a new one. */
|
c = CreateControlSymbol(STYPE0_STATUS, 10, 8, STYPE1_START_OF_PACKET, 0);
|
handleNewPacketEnd(stack);
|
s = RIO_portGetSymbol(&stack);
|
handleNewPacketStart(stack);
|
TESTEXPR(s.type, c.type);
|
}
|
TESTEXPR(s.data, c.data);
|
else
|
for(i = 0; i < packetLength; i++)
|
|
{
|
{
|
s = RIO_portGetSymbol(&stack);
|
/* The packet has a valid CRC but is too short. */
|
d.type = RIO_SYMBOL_TYPE_DATA;
|
/* Packet error. Enter input-error-stopped state. */
|
d.data = packet[i];
|
stack->txState = TX_STATE_SEND_PACKET_NOT_ACCEPTED;
|
TESTEXPR(s.type, d.type);
|
stack->rxState = RX_STATE_INPUT_ERROR_STOPPED;
|
TESTEXPR(s.data, d.data);
|
stack->rxErrorCause = PACKET_NOT_ACCEPTED_CAUSE_GENERAL;
|
|
stack->statusInboundErrorGeneral++;
|
}
|
}
|
packetLength = createDoorbell(packet, 14, 0, 0xffff, 24, 0xbabe);
|
|
c = CreateControlSymbol(STYPE0_STATUS, 10, 8, STYPE1_START_OF_PACKET, 0);
|
|
s = RIO_portGetSymbol(&stack);
|
|
TESTEXPR(s.type, c.type);
|
|
TESTEXPR(s.data, c.data);
|
|
for(i = 0; i < packetLength; i++)
|
|
{
|
|
s = RIO_portGetSymbol(&stack);
|
|
d.type = RIO_SYMBOL_TYPE_DATA;
|
|
d.data = packet[i];
|
|
TESTEXPR(s.type, d.type);
|
|
TESTEXPR(s.data, d.data);
|
|
}
|
}
|
|
else
|
RIO_portAddSymbol(&stack, CreateControlSymbol(STYPE0_PACKET_ACCEPTED, 12, 1, STYPE1_NOP, 0));
|
|
|
|
packetLength = createDoorbell(packet, 15, 0, 0xffff, 25, 0xbabe);
|
|
c = CreateControlSymbol(STYPE0_STATUS, 10, 8, STYPE1_START_OF_PACKET, 0);
|
|
s = RIO_portGetSymbol(&stack);
|
|
TESTEXPR(s.type, c.type);
|
|
TESTEXPR(s.data, c.data);
|
|
for(i = 0; i < packetLength; i++)
|
|
{
|
{
|
s = RIO_portGetSymbol(&stack);
|
/* The packet has an invalid CRC. */
|
d.type = RIO_SYMBOL_TYPE_DATA;
|
/* Packet error. Enter input-error-stopped state. */
|
d.data = packet[i];
|
stack->txState = TX_STATE_SEND_PACKET_NOT_ACCEPTED;
|
TESTEXPR(s.type, d.type);
|
stack->rxState = RX_STATE_INPUT_ERROR_STOPPED;
|
TESTEXPR(s.data, d.data);
|
stack->rxErrorCause = PACKET_NOT_ACCEPTED_CAUSE_PACKET_CRC;
|
|
stack->statusInboundErrorPacketCrc++;
|
}
|
}
|
|
|
RIO_portAddSymbol(&stack, CreateControlSymbol(STYPE0_PACKET_ACCEPTED, 13, 1, STYPE1_NOP, 0));
|
|
|
|
packetLength = createDoorbell(packet, 16, 0, 0xffff, 26, 0xbabe);
|
|
c = CreateControlSymbol(STYPE0_STATUS, 10, 8, STYPE1_START_OF_PACKET, 0);
|
|
s = RIO_portGetSymbol(&stack);
|
|
TESTEXPR(s.type, c.type);
|
|
TESTEXPR(s.data, c.data);
|
|
RIO_portAddSymbol(&stack, CreateControlSymbol(STYPE0_PACKET_ACCEPTED, 14, 1, STYPE1_NOP, 0));
|
|
for(i = 0; i < packetLength; i++)
|
|
{
|
|
s = RIO_portGetSymbol(&stack);
|
|
d.type = RIO_SYMBOL_TYPE_DATA;
|
|
d.data = packet[i];
|
|
TESTEXPR(s.type, d.type);
|
|
TESTEXPR(s.data, d.data);
|
|
}
|
}
|
packetLength = createDoorbell(packet, 17, 0, 0xffff, 27, 0xbabe);
|
else
|
c = CreateControlSymbol(STYPE0_STATUS, 10, 8, STYPE1_START_OF_PACKET, 0);
|
|
s = RIO_portGetSymbol(&stack);
|
|
TESTEXPR(s.type, c.type);
|
|
TESTEXPR(s.data, c.data);
|
|
for(i = 0; i < packetLength; i++)
|
|
{
|
{
|
s = RIO_portGetSymbol(&stack);
|
/* Packet has not already started. */
|
d.type = RIO_SYMBOL_TYPE_DATA;
|
handleNewPacketStart(stack);
|
d.data = packet[i];
|
|
TESTEXPR(s.type, d.type);
|
|
TESTEXPR(s.data, d.data);
|
|
}
|
}
|
RIO_portAddSymbol(&stack, CreateControlSymbol(STYPE0_PACKET_ACCEPTED, 15, 1, STYPE1_NOP, 0));
|
|
c = CreateControlSymbol(STYPE0_STATUS, 10, 8, STYPE1_END_OF_PACKET, 0);
|
|
s = RIO_portGetSymbol(&stack);
|
|
TESTEXPR(s.type, c.type);
|
|
TESTEXPR(s.data, c.data);
|
|
|
|
RIO_portAddSymbol(&stack, CreateControlSymbol(STYPE0_PACKET_ACCEPTED, 16, 1, STYPE1_NOP, 0));
|
|
RIO_portAddSymbol(&stack, CreateControlSymbol(STYPE0_PACKET_ACCEPTED, 17, 1, STYPE1_NOP, 0));
|
|
|
|
|
|
/*************************************************************************
|
|
* Reset ackIds to be able to use the stack in loopback for the testcases
|
|
* below.
|
|
*************************************************************************/
|
|
|
|
stack.rxAckId = 0;
|
|
stack.rxAckIdAcked = 0;
|
|
stack.txAckId = 0;
|
|
stack.txAckIdWindow = 0;
|
|
|
|
/******************************************************************************/
|
|
TESTEND;
|
|
/******************************************************************************/
|
|
PrintS("----------------------------------------------------------------------");
|
|
PrintS("TG_riostack-TC5");
|
|
PrintS("Description: Test MAINTENANCE-READ-REQUEST, MAINTENANCE-READ-RESPONSE,");
|
|
PrintS(" MAINTENANCE-WRITE-REQUEST and MAINTENANCE-WRITE-RESPONSE packets.");
|
|
PrintS("Requirement: XXXXX");
|
|
PrintS("----------------------------------------------------------------------");
|
|
PrintS("Step 1:");
|
|
PrintS("Action: Send two read requests to read identity and address of stack.");
|
|
PrintS("Result: The identity and address defined at RIO_open should be returned.");
|
|
PrintS("----------------------------------------------------------------------");
|
|
/******************************************************************************/
|
|
TESTSTART("TG_riostack-TC5-Step1");
|
|
/******************************************************************************/
|
|
|
|
/* Send two read requests. */
|
|
RIO_sendMaintenanceReadRequest(&stack, 0xffff, 10, 0, 0x00000000);
|
|
RIO_sendMaintenanceReadRequest(&stack, 0xffff, 11, 0, 0x00000060);
|
|
|
|
TESTEXPR(RIO_outboundQueueLength(&stack), 2);
|
|
|
|
while(RIO_inboundQueueLength(&stack) != 2)
|
|
{
|
|
s = RIO_portGetSymbol(&stack);
|
|
RIO_portAddSymbol(&stack, s);
|
|
}
|
}
|
|
|
RIO_receiveMaintenanceReadResponse(&stack, &srcid, &tid, &hop, &data);
|
|
TESTEXPR(srcid, 0xffff);
|
|
TESTEXPR(tid, 10);
|
|
TESTEXPR(hop, 0xff);
|
|
TESTEXPR(data, 0x0000b03b);
|
|
RIO_packetRemove(&stack);
|
|
|
|
RIO_receiveMaintenanceReadResponse(&stack, &srcid, &tid, &hop, &data);
|
|
TESTEXPR(srcid, 0xffff);
|
|
TESTEXPR(tid, 11);
|
|
TESTEXPR(hop, 0xff);
|
|
TESTEXPR(data, 0x0000ffff);
|
|
RIO_packetRemove(&stack);
|
|
|
|
/******************************************************************************/
|
|
TESTEND;
|
|
/******************************************************************************/
|
|
PrintS("----------------------------------------------------------------------");
|
|
PrintS("Step 2:");
|
|
PrintS("Action: Send a write requests to write base device id of the stack.");
|
|
PrintS("Result: The identity and address defined at RIO_open should be returned.");
|
|
PrintS("----------------------------------------------------------------------");
|
|
/******************************************************************************/
|
|
TESTSTART("TG_riostack-TC5-Step2");
|
|
/******************************************************************************/
|
|
|
|
/* Write base device id. */
|
static void handleEndOfPacket(RioStack_t *stack)
|
RIO_sendMaintenanceWriteRequest(&stack, 0xffff, 12, 0, 0x00000060, 0xdead);
|
|
while(RIO_eventPoll(&stack) != RIO_EVENT_MAINT_WRITE_RESPONSE)
|
|
{
|
{
|
s = RIO_portGetSymbol(&stack);
|
/* Check if the CRC is correct. */
|
RIO_portAddSymbol(&stack, s);
|
if(stack->rxCrc == 0x0000u)
|
}
|
|
|
|
RIO_receiveMaintenanceWriteResponse(&stack, &srcid, &tid, &hop);
|
|
TESTEXPR(srcid, 0xdead);
|
|
TESTEXPR(tid, 12);
|
|
TESTEXPR(hop, 0xff);
|
|
RIO_packetRemove(&stack);
|
|
|
|
/* Read back the written base device id. */
|
|
RIO_sendMaintenanceReadRequest(&stack, 0xffff, 14, 0, 0x00000060);
|
|
while(RIO_eventPoll(&stack) != RIO_EVENT_MAINT_READ_RESPONSE)
|
|
{
|
{
|
s = RIO_portGetSymbol(&stack);
|
/* The packet has a correct CRC. */
|
RIO_portAddSymbol(&stack, s);
|
|
}
|
|
|
|
RIO_receiveMaintenanceReadResponse(&stack, &srcid, &tid, &hop, &data);
|
|
TESTEXPR(srcid, 0xdead);
|
|
TESTEXPR(tid, 14);
|
|
TESTEXPR(hop, 0xff);
|
|
TESTEXPR(data, 0x0000dead);
|
|
RIO_packetRemove(&stack);
|
|
|
|
/******************************************************************************/
|
|
TESTEND;
|
|
/******************************************************************************/
|
|
PrintS("----------------------------------------------------------------------");
|
|
PrintS("Step 3:");
|
|
PrintS("Action: Send a write requests to write to the implementation defined ");
|
|
PrintS(" configuration space of the stack.");
|
|
PrintS("Result: The same data should be returned.");
|
|
PrintS("----------------------------------------------------------------------");
|
|
/******************************************************************************/
|
|
TESTSTART("TG_riostack-TC5-Step3");
|
|
/******************************************************************************/
|
|
|
|
/* Write to implementation defined space. */
|
|
RIO_sendMaintenanceWriteRequest(&stack, 0xffff, 14, 0, 0x00010004, 0x01020304);
|
|
RIO_sendMaintenanceWriteRequest(&stack, 0xffff, 15, 0, 0x00010008, 0xc0debabe);
|
|
RIO_sendMaintenanceWriteRequest(&stack, 0xffff, 16, 0, 0x0001000c, 0x05060708);
|
|
|
|
while(RIO_eventPoll(&stack) != RIO_EVENT_MAINT_WRITE_RESPONSE)
|
/* Check if the packet is long enough to contain a complete packet. */
|
|
if(stack->rxCounter > 3u)
|
{
|
{
|
s = RIO_portGetSymbol(&stack);
|
/* Packet long enough to process. */
|
RIO_portAddSymbol(&stack, s);
|
|
}
|
|
|
|
RIO_receiveMaintenanceWriteResponse(&stack, &srcid, &tid, &hop);
|
|
TESTEXPR(srcid, 0xdead);
|
|
TESTEXPR(tid, 14);
|
|
TESTEXPR(hop, 0xff);
|
|
RIO_packetRemove(&stack);
|
|
|
|
while(RIO_eventPoll(&stack) != RIO_EVENT_MAINT_WRITE_RESPONSE)
|
/* Process the newly received packet. */
|
{
|
handleNewPacketEnd(stack);
|
s = RIO_portGetSymbol(&stack);
|
|
RIO_portAddSymbol(&stack, s);
|
|
}
|
}
|
|
else
|
RIO_receiveMaintenanceWriteResponse(&stack, &srcid, &tid, &hop);
|
|
TESTEXPR(srcid, 0xdead);
|
|
TESTEXPR(tid, 15);
|
|
TESTEXPR(hop, 0xff);
|
|
RIO_packetRemove(&stack);
|
|
|
|
while(RIO_eventPoll(&stack) != RIO_EVENT_MAINT_WRITE_RESPONSE)
|
|
{
|
{
|
s = RIO_portGetSymbol(&stack);
|
/* The packet has a valid CRC but is too short. */
|
RIO_portAddSymbol(&stack, s);
|
/* Packet error. Enter input-error-stopped state. */
|
|
stack->txState = TX_STATE_SEND_PACKET_NOT_ACCEPTED;
|
|
stack->rxState = RX_STATE_INPUT_ERROR_STOPPED;
|
|
stack->rxErrorCause = PACKET_NOT_ACCEPTED_CAUSE_GENERAL;
|
|
stack->statusInboundErrorGeneral++;
|
}
|
}
|
|
}
|
RIO_receiveMaintenanceWriteResponse(&stack, &srcid, &tid, &hop);
|
else
|
TESTEXPR(srcid, 0xdead);
|
|
TESTEXPR(tid, 16);
|
|
TESTEXPR(hop, 0xff);
|
|
RIO_packetRemove(&stack);
|
|
|
|
/* Read from implementation defined space. */
|
|
RIO_sendMaintenanceReadRequest(&stack, 0xffff, 14, 0, 0x00010000);
|
|
RIO_sendMaintenanceReadRequest(&stack, 0xffff, 15, 0, 0x00010004);
|
|
RIO_sendMaintenanceReadRequest(&stack, 0xffff, 16, 0, 0x00010008);
|
|
RIO_sendMaintenanceReadRequest(&stack, 0xffff, 17, 0, 0x0001000c);
|
|
|
|
while(RIO_inboundQueueLength(&stack) != 4)
|
|
{
|
{
|
s = RIO_portGetSymbol(&stack);
|
/* The packet has an invalid CRC. */
|
RIO_portAddSymbol(&stack, s);
|
/* Packet error. Enter input-error-stopped state. */
|
|
stack->txState = TX_STATE_SEND_PACKET_NOT_ACCEPTED;
|
|
stack->rxState = RX_STATE_INPUT_ERROR_STOPPED;
|
|
stack->rxErrorCause = PACKET_NOT_ACCEPTED_CAUSE_PACKET_CRC;
|
|
stack->statusInboundErrorPacketCrc++;
|
|
}
|
}
|
}
|
|
|
RIO_receiveMaintenanceReadResponse(&stack, &srcid, &tid, &hop, &data);
|
|
TESTEXPR(srcid, 0xdead);
|
|
TESTEXPR(tid, 14);
|
|
TESTEXPR(hop, 0xff);
|
|
TESTEXPR(data, 0x80000006);
|
|
RIO_packetRemove(&stack);
|
|
|
|
RIO_receiveMaintenanceReadResponse(&stack, &srcid, &tid, &hop, &data);
|
|
TESTEXPR(srcid, 0xdead);
|
|
TESTEXPR(tid, 15);
|
|
TESTEXPR(hop, 0xff);
|
|
TESTEXPR(data, 0x00a100a2);
|
|
RIO_packetRemove(&stack);
|
|
|
|
RIO_receiveMaintenanceReadResponse(&stack, &srcid, &tid, &hop, &data);
|
|
TESTEXPR(srcid, 0xdead);
|
|
TESTEXPR(tid, 16);
|
|
TESTEXPR(hop, 0xff);
|
|
TESTEXPR(data, 0xc0debabe);
|
|
RIO_packetRemove(&stack);
|
|
|
|
RIO_receiveMaintenanceReadResponse(&stack, &srcid, &tid, &hop, &data);
|
|
TESTEXPR(srcid, 0xdead);
|
|
TESTEXPR(tid, 17);
|
|
TESTEXPR(hop, 0xff);
|
|
TESTEXPR(data, 0x00000000);
|
|
RIO_packetRemove(&stack);
|
|
|
|
/******************************************************************************/
|
|
TESTEND;
|
|
/******************************************************************************/
|
|
PrintS("----------------------------------------------------------------------");
|
|
PrintS("TG_riostack-TC6");
|
|
PrintS("Description: Test NREAD packets.");
|
|
PrintS("Requirement: XXXXX");
|
|
PrintS("----------------------------------------------------------------------");
|
|
PrintS("Step 1:");
|
|
PrintS("Action: Send one byte using NREAD and receive it at the other side.");
|
|
PrintS("Result: The same NREAD should be received as has been sent.");
|
|
PrintS("----------------------------------------------------------------------");
|
|
/******************************************************************************/
|
|
TESTSTART("TG_riostack-TC6-Step1");
|
|
/******************************************************************************/
|
|
|
|
for(j = 0; j < 8; j++)
|
static void handleNewPacketStart(RioStack_t *stack)
|
{
|
{
|
RIO_sendNread(&stack, 0x0060, j, 0xaaaaaaaa+j, 1);
|
/* Check if there are buffers available to store the new frame. */
|
|
if (QueueAvailable(stack->rxQueue) > 0u)
|
while(RIO_eventPoll(&stack) != RIO_EVENT_NREAD)
|
|
{
|
{
|
s = RIO_portGetSymbol(&stack);
|
/* There are buffers available to accept the new packet. */
|
RIO_portAddSymbol(&stack, s);
|
|
}
|
|
|
|
RIO_receiveNread(&stack, &srcid, &tid, &address, &length);
|
|
|
|
TESTEXPR(tid, j);
|
|
TESTEXPR(srcid, 0xdead);
|
|
TESTEXPR(address, 0xaaaaaaaa+j);
|
|
TESTEXPR(length, 1);
|
|
|
|
RIO_packetRemove(&stack);
|
/* Update the reception counter to indicate the frame has started. */
|
|
stack->rxCounter = 1;
|
}
|
}
|
|
else
|
/******************************************************************************/
|
|
TESTEND;
|
|
/******************************************************************************/
|
|
PrintS("----------------------------------------------------------------------");
|
|
PrintS("Step 2:");
|
|
PrintS("Action: Send two bytes using NREAD and receive it at the other side.");
|
|
PrintS("Result: The same NREAD should be received as has been sent.");
|
|
PrintS("----------------------------------------------------------------------");
|
|
/******************************************************************************/
|
|
TESTSTART("TG_riostack-TC6-Step2");
|
|
/******************************************************************************/
|
|
|
|
for(j = 0; j < 4; j++)
|
|
{
|
|
RIO_sendNread(&stack, 0x0060, j, 0x00000008+2*j, 2);
|
|
|
|
while(RIO_eventPoll(&stack) != RIO_EVENT_NREAD)
|
|
{
|
{
|
s = RIO_portGetSymbol(&stack);
|
/* There are no buffers available. */
|
RIO_portAddSymbol(&stack, s);
|
/* Go to input retry stopped state. */
|
|
stack->statusInboundPacketRetry++;
|
|
stack->txState = TX_STATE_SEND_PACKET_RETRY;
|
|
stack->rxState = RX_STATE_INPUT_RETRY_STOPPED;
|
}
|
}
|
|
|
RIO_receiveNread(&stack, &srcid, &tid, &address, &length);
|
|
|
|
TESTEXPR(tid, j);
|
|
TESTEXPR(srcid, 0xdead);
|
|
TESTEXPR(address, 0x00000008+2*j);
|
|
TESTEXPR(length, 2);
|
|
|
|
RIO_packetRemove(&stack);
|
|
}
|
}
|
|
|
/******************************************************************************/
|
|
TESTEND;
|
|
/******************************************************************************/
|
|
PrintS("----------------------------------------------------------------------");
|
|
PrintS("Step 3:");
|
|
PrintS("Action: Send three to seven bytes using NREAD and receive it at the other ");
|
|
PrintS(" side.");
|
|
PrintS("Result: The same NREAD should be received as has been sent.");
|
|
PrintS("----------------------------------------------------------------------");
|
|
/******************************************************************************/
|
|
TESTSTART("TG_riostack-TC6-Step3");
|
|
/******************************************************************************/
|
|
|
|
for(k = 3; k < 8; k++)
|
|
{
|
|
for(j = 0; j < 2; j++)
|
|
{
|
|
RIO_sendNread(&stack, 0x0060, j, 0x00000008+(8-k)*j, k);
|
|
|
|
while(RIO_eventPoll(&stack) != RIO_EVENT_NREAD)
|
static void handleNewPacketEnd(RioStack_t *stack)
|
{
|
{
|
s = RIO_portGetSymbol(&stack);
|
/* Save the size of the packet. */
|
RIO_portAddSymbol(&stack, s);
|
QueueSetSize(stack->rxQueue, (uint32_t)stack->rxCounter - (uint32_t)1ul);
|
}
|
|
|
|
RIO_receiveNread(&stack, &srcid, &tid, &address, &length);
|
|
|
|
TESTEXPR(tid, j);
|
/* Always forward the packet to the top of the stack. */
|
TESTEXPR(srcid, 0xdead);
|
stack->rxQueue = QueueEnqueue(stack->rxQueue);
|
TESTEXPR(address, 0x00000008+(8-k)*j);
|
|
TESTEXPR(length, k);
|
|
|
|
RIO_packetRemove(&stack);
|
/* Make sure the CRC is reset to an invalid value to avoid a packet
|
}
|
accidentally being accepted. */
|
}
|
stack->rxCrc = 0xffff;
|
|
|
/******************************************************************************/
|
/* Reset the reception counter. */
|
TESTEND;
|
stack->rxCounter = 0u;
|
/******************************************************************************/
|
|
PrintS("----------------------------------------------------------------------");
|
|
PrintS("Step 4:");
|
|
PrintS("Action: Send one and two double words using NREAD and receive it at the ");
|
|
PrintS(" other side.");
|
|
PrintS("Result: The same NREAD should be received as has been sent.");
|
|
PrintS("----------------------------------------------------------------------");
|
|
/******************************************************************************/
|
|
TESTSTART("TG_riostack-TC6-Step4");
|
|
/******************************************************************************/
|
|
|
|
for(j = 0; j < 2; j++)
|
/* Update the ackId for the receiver. */
|
{
|
stack->rxAckId = ACKID_INC(stack->rxAckId);
|
RIO_sendNread(&stack, 0x0060, j, 0x00000008+8*j, 8*j+8);
|
|
|
|
while(RIO_eventPoll(&stack) != RIO_EVENT_NREAD)
|
/* Update status counter. */
|
{
|
stack->statusInboundPacketComplete++;
|
s = RIO_portGetSymbol(&stack);
|
|
RIO_portAddSymbol(&stack, s);
|
|
}
|
}
|
|
|
RIO_receiveNread(&stack, &srcid, &tid, &address, &length);
|
|
|
|
TESTEXPR(tid, j);
|
|
TESTEXPR(srcid, 0xdead);
|
|
TESTEXPR(address, 0x00000008+8*j);
|
|
TESTEXPR(length, 8*j+8);
|
|
|
|
RIO_packetRemove(&stack);
|
|
}
|
|
|
|
/******************************************************************************/
|
|
TESTEND;
|
|
/******************************************************************************/
|
|
PrintS("----------------------------------------------------------------------");
|
|
PrintS("Step 5:");
|
|
PrintS("Action: Send multiple of four full double words using NREAD and receive it");
|
|
PrintS("at the other side.");
|
|
PrintS("Result: The same NREAD should be received as has been sent.");
|
|
PrintS("----------------------------------------------------------------------");
|
|
/******************************************************************************/
|
|
TESTSTART("TG_riostack-TC6-Step5");
|
|
/******************************************************************************/
|
|
|
|
for(j = 0; j < 8; j++)
|
static void handleLinkRequest(RioStack_t *stack, uint8_t cmd)
|
{
|
{
|
RIO_sendNread(&stack, 0x0060, j, 0x00000008+8*j, 32*j+32);
|
/* Check the command of the link-request. */
|
|
if(cmd == LINK_REQUEST_INPUT_STATUS)
|
while(RIO_eventPoll(&stack) != RIO_EVENT_NREAD)
|
|
{
|
{
|
s = RIO_portGetSymbol(&stack);
|
/* Input-status requested. */
|
RIO_portAddSymbol(&stack, s);
|
/* Return input port status. */
|
}
|
|
|
|
RIO_receiveNread(&stack, &srcid, &tid, &address, &length);
|
|
|
|
TESTEXPR(tid, j);
|
|
TESTEXPR(srcid, 0xdead);
|
|
TESTEXPR(address, 0x00000008+8*j);
|
|
TESTEXPR(length, 32*j+32);
|
|
|
|
RIO_packetRemove(&stack);
|
/* Force the transmitter to send a link-response-symbol. */
|
|
stack->txState = TX_STATE_SEND_LINK_RESPONSE;
|
}
|
}
|
|
else if(cmd == LINK_REQUEST_RESET_DEVICE)
|
/* REMARK: Add negative testcase where all unallowed address, size combinations
|
|
are sent...*/
|
|
|
|
/******************************************************************************/
|
|
TESTEND;
|
|
/******************************************************************************/
|
|
PrintS("----------------------------------------------------------------------");
|
|
PrintS("TG_riostack-TC7");
|
|
PrintS("Description: Test NWRITER packets.");
|
|
PrintS("Requirement: XXXXX");
|
|
PrintS("----------------------------------------------------------------------");
|
|
PrintS("Step 1:");
|
|
PrintS("Action: Send one byte using NWRITER and receive it at the other side.");
|
|
PrintS("Result: The same NWRITER should be received as has been sent.");
|
|
PrintS("----------------------------------------------------------------------");
|
|
/******************************************************************************/
|
|
TESTSTART("TG_riostack-TC7-Step1");
|
|
/******************************************************************************/
|
|
|
|
for(j = 0; j < 8; j++)
|
|
{
|
{
|
for(i = 0; i < 1; i++)
|
/* Reset-device requested. */
|
|
/* REMARK: Support this??? */
|
|
}
|
|
else
|
{
|
{
|
payload8[i] = i+j+1;
|
/* Unrecognized command. */
|
payload8Expected[i] = 0;
|
/* Dont do anything. */
|
}
|
}
|
|
|
RIO_sendNwrite(&stack, 0x0060, 0xaaaaaaaa+j, 1, payload8);
|
/* Always cancel an ongoing frame when a link-request has been received. */
|
|
stack->rxCounter = 0;
|
|
|
while(RIO_eventPoll(&stack) != RIO_EVENT_NWRITE)
|
/* Receiving this indicates the link partner having encountered a potential problem. */
|
{
|
/* Count the number of times this happens. */
|
s = RIO_portGetSymbol(&stack);
|
stack->statusPartnerLinkRequest++;
|
RIO_portAddSymbol(&stack, s);
|
|
}
|
}
|
|
|
length = RIO_receiveNwrite(&stack, &srcid, &tid, &address, sizeof(payload8Expected), payload8Expected);
|
|
|
|
TESTEXPR(length, 1);
|
|
TESTEXPR(srcid, 0xdead);
|
|
TESTEXPR(address, 0xaaaaaaaa+j);
|
|
|
|
for(i = 0; i < 1; i++)
|
static RioSymbol_t CreateControlSymbol(const uint8_t stype0,
|
|
const uint8_t parameter0, const uint8_t parameter1,
|
|
const uint8_t stype1, const uint8_t cmd)
|
{
|
{
|
TESTEXPR(payload8Expected[i], i+j+1);
|
RioSymbol_t s;
|
}
|
|
|
|
RIO_packetRemove(&stack);
|
s.type = RIOSTACK_SYMBOL_TYPE_CONTROL;
|
}
|
|
|
|
/******************************************************************************/
|
s.data = ((uint32_t)stype0 & (uint32_t)0x07ul) << 21;
|
TESTEND;
|
s.data |= ((uint32_t)parameter0 & (uint32_t)0x1ful) << 16;
|
/******************************************************************************/
|
s.data |= ((uint32_t)parameter1 & (uint32_t)0x1ful) << 11;
|
PrintS("----------------------------------------------------------------------");
|
s.data |= ((uint32_t)stype1 & (uint32_t)0x07ul) << 8;
|
PrintS("Step 2:");
|
s.data |= ((uint32_t)cmd & (uint32_t)0x7ul) << 5;
|
PrintS("Action: Send two bytes using NWRITE and receive it at the other side.");
|
s.data |= Crc5(s.data, 0x1fu);
|
PrintS("Result: The same NWRITE should be received as has been sent.");
|
|
PrintS("----------------------------------------------------------------------");
|
|
/******************************************************************************/
|
|
TESTSTART("TG_riostack-TC7-Step2");
|
|
/******************************************************************************/
|
|
|
|
for(j = 0; j < 4; j++)
|
return s;
|
{
|
|
for(i = 0; i < 2; i++)
|
|
{
|
|
payload8[i] = i+j;
|
|
payload8Expected[i] = 0;
|
|
}
|
}
|
|
|
RIO_sendNwriteR(&stack, 0x0060, j, 0x00000008+2*j, 2, payload8);
|
|
|
|
while(RIO_eventPoll(&stack) != RIO_EVENT_NWRITE_R)
|
|
|
static uint8_t Crc5(const uint32_t data, const uint8_t crc)
|
{
|
{
|
s = RIO_portGetSymbol(&stack);
|
static const uint8_t crcTable[] = {
|
RIO_portAddSymbol(&stack, s);
|
0x00u, 0x15u, 0x1fu, 0x0au, 0x0bu, 0x1eu, 0x14u, 0x01u,
|
}
|
0x16u, 0x03u, 0x09u, 0x1cu, 0x1du, 0x08u, 0x02u, 0x17u,
|
|
0x19u, 0x0cu, 0x06u, 0x13u, 0x12u, 0x07u, 0x0du, 0x18u,
|
|
0x0fu, 0x1au, 0x10u, 0x05u, 0x04u, 0x11u, 0x1bu, 0x0eu
|
|
};
|
|
|
length = RIO_receiveNwrite(&stack, &srcid, &tid, &address, sizeof(payload8Expected), payload8Expected);
|
uint8_t result;
|
|
uint8_t index;
|
|
|
TESTEXPR(tid, j);
|
result = crc;
|
TESTEXPR(srcid, 0xdead);
|
index = (uint8_t)((data >> 19) & (uint32_t)0x1ful) ^ result;
|
TESTEXPR(address, 0x00000008+2*j);
|
result = crcTable[index];
|
TESTEXPR(length, 2);
|
index = (uint8_t)((data >> 14) & (uint32_t)0x1ful) ^ result;
|
|
result = crcTable[index];
|
|
index = (uint8_t)((data >> 9) & (uint32_t)0x1ful) ^ result;
|
|
result = crcTable[index];
|
|
index = (uint8_t)((data >> 4) & (uint32_t)0x1eul) ^ result;
|
|
result = crcTable[index];
|
|
|
for(i = 0; i < 2; i++)
|
return result;
|
{
|
|
TESTEXPR(payload8Expected[i], i+j);
|
|
}
|
}
|
|
|
RIO_packetRemove(&stack);
|
|
}
|
|
|
|
/******************************************************************************/
|
/*******************************************************************************************
|
TESTEND;
|
* Internal queue functions.
|
/******************************************************************************/
|
*******************************************************************************************/
|
PrintS("----------------------------------------------------------------------");
|
|
PrintS("Step 3:");
|
|
PrintS("Action: Send three to seven bytes using NWRITE and receive it at the other ");
|
|
PrintS(" side.");
|
|
PrintS("Result: The same NWRITE should be received as has been sent.");
|
|
PrintS("----------------------------------------------------------------------");
|
|
/******************************************************************************/
|
|
TESTSTART("TG_riostack-TC7-Step3");
|
|
/******************************************************************************/
|
|
|
|
for(k = 3; k < 8; k++)
|
static Queue_t QueueCreate(const uint8_t size, uint32_t *buffer)
|
{
|
|
for(j = 0; j < 2; j++)
|
|
{
|
|
for(i = 0; i < k; i++)
|
|
{
|
{
|
payload8[i] = i+j+1;
|
Queue_t q;
|
payload8Expected[i] = 0;
|
|
}
|
|
|
|
RIO_sendNwriteR(&stack, 0x0060, j, 0x00000008+(8-k)*j, k, payload8);
|
q.size = size;
|
|
q.available = size;
|
|
q.windowSize = 0u;
|
|
q.windowIndex = 0u;
|
|
q.frontIndex = 0u;
|
|
q.backIndex = 0u;
|
|
q.buffer_p = buffer;
|
|
|
while(RIO_eventPoll(&stack) != RIO_EVENT_NWRITE_R)
|
return q;
|
{
|
|
s = RIO_portGetSymbol(&stack);
|
|
RIO_portAddSymbol(&stack, s);
|
|
}
|
}
|
|
|
length = RIO_receiveNwrite(&stack, &srcid, &tid, &address, sizeof(payload8Expected), payload8Expected);
|
|
|
|
TESTEXPR(tid, j);
|
|
TESTEXPR(srcid, 0xdead);
|
|
TESTEXPR(address, 0x00000008+(8-k)*j);
|
|
TESTEXPR(length, k);
|
|
|
|
for(i = 0; i < k; i++)
|
static uint8_t QueueAvailable(const Queue_t q)
|
{
|
{
|
TESTEXPR(payload8Expected[i], i+j+1);
|
return q.available;
|
}
|
}
|
|
|
RIO_packetRemove(&stack);
|
|
}
|
|
}
|
|
|
|
/******************************************************************************/
|
|
TESTEND;
|
|
/******************************************************************************/
|
|
PrintS("----------------------------------------------------------------------");
|
|
PrintS("Step 4:");
|
|
PrintS("Action: Send full double words using NWRITE and receive it at the other side.");
|
|
PrintS("Result: The same NWRITE should be received as has been sent.");
|
|
PrintS("----------------------------------------------------------------------");
|
|
/******************************************************************************/
|
|
TESTSTART("TG_riostack-TC7-Step4");
|
|
/******************************************************************************/
|
|
|
|
for(j = 1; j < 32; j++)
|
static int QueueEmpty(const Queue_t q)
|
{
|
|
for(i = 0; i < 8*j; i++)
|
|
{
|
{
|
payload8[i] = i+j+1;
|
return (q.available == q.size);
|
payload8Expected[i] = 0;
|
|
}
|
}
|
|
|
RIO_sendNwriteR(&stack, 0x0060, j, 0x00000008+8*j, 8*j, payload8);
|
|
|
|
while(RIO_eventPoll(&stack) != RIO_EVENT_NWRITE_R)
|
|
|
static uint8_t QueueLength(const Queue_t q)
|
{
|
{
|
s = RIO_portGetSymbol(&stack);
|
return q.size - q.available;
|
RIO_portAddSymbol(&stack, s);
|
|
}
|
}
|
|
|
length = RIO_receiveNwrite(&stack, &srcid, &tid, &address, sizeof(payload8Expected), payload8Expected);
|
|
|
|
TESTEXPR(tid, j);
|
|
TESTEXPR(srcid, 0xdead);
|
|
TESTEXPR(address, 0x00000008+8*j);
|
|
TESTEXPR(length, 8*j);
|
|
|
|
for(i = 0; i < 8*j; i++)
|
static Queue_t QueueEnqueue(Queue_t q)
|
|
{
|
|
q.backIndex++;
|
|
if(q.backIndex == q.size)
|
{
|
{
|
TESTEXPR(payload8Expected[i], (uint8_t) (i+j+1));
|
q.backIndex = 0;
|
}
|
}
|
|
q.available--;
|
RIO_packetRemove(&stack);
|
return q;
|
}
|
}
|
|
|
/******************************************************************************/
|
|
TESTEND;
|
|
/******************************************************************************/
|
|
PrintS("----------------------------------------------------------------------");
|
|
PrintS("TG_riostack-TC8");
|
|
PrintS("Description: Test RESPONSE packets.");
|
|
PrintS("Requirement: XXXXX");
|
|
PrintS("----------------------------------------------------------------------");
|
|
PrintS("Step 1:");
|
|
PrintS("Action: Send one byte using RESPONSE_WITH_PAYLOAD and receive it at the ");
|
|
PrintS(" other side.");
|
|
PrintS("Result: The same RESPONSE_WITH_PAYLOAD should be received as has been sent.");
|
|
PrintS("----------------------------------------------------------------------");
|
|
/******************************************************************************/
|
|
TESTSTART("TG_riostack-TC8-Step1");
|
|
/******************************************************************************/
|
|
|
|
for(j = 0; j < 8; j++)
|
|
|
static Queue_t QueueDequeue(Queue_t q)
|
{
|
{
|
for(i = 0; i < 1; i++)
|
q.frontIndex++;
|
|
if(q.frontIndex == q.size)
|
{
|
{
|
payload8[i] = i+j+1;
|
q.frontIndex = 0;
|
payload8Expected[i] = 0;
|
|
}
|
}
|
|
q.available++;
|
RIO_sendResponseDonePayload(&stack, 0x0060, j, 0x00000008+j, 1, payload8);
|
if(q.windowSize == 0)
|
|
|
while(RIO_eventPoll(&stack) != RIO_EVENT_RESPONSE_DONE_PAYLOAD)
|
|
{
|
{
|
s = RIO_portGetSymbol(&stack);
|
q.windowIndex = q.frontIndex;
|
RIO_portAddSymbol(&stack, s);
|
|
}
|
}
|
|
else
|
length = RIO_receiveResponseDonePayload(&stack, &srcid, &tid, 0x00000008+j, 1, payload8Expected);
|
|
|
|
TESTEXPR(tid, j);
|
|
TESTEXPR(srcid, 0xdead);
|
|
TESTEXPR(length, 1);
|
|
|
|
for(i = 0; i < 1; i++)
|
|
{
|
{
|
TESTEXPR(payload8Expected[i], i+j+1);
|
q.windowSize--;
|
}
|
}
|
|
return q;
|
RIO_packetRemove(&stack);
|
|
}
|
}
|
|
|
/******************************************************************************/
|
|
TESTEND;
|
|
/******************************************************************************/
|
|
PrintS("----------------------------------------------------------------------");
|
|
PrintS("TG_riostack-TC9");
|
|
PrintS("Description: Test DOORBELL packet and its response.");
|
|
PrintS("Requirement: XXXXX");
|
|
PrintS("----------------------------------------------------------------------");
|
|
PrintS("Step 1:");
|
|
PrintS("Action: Send a doorbell.");
|
|
PrintS("Result: The received doorbell should have the same properties as the sent.");
|
|
PrintS("----------------------------------------------------------------------");
|
|
/******************************************************************************/
|
|
TESTSTART("TG_riostack-TC9-Step1");
|
|
/******************************************************************************/
|
|
|
|
RIO_sendDoorbell(&stack, 0x0060, 16, 0xbabe);
|
|
|
|
while(RIO_eventPoll(&stack) != RIO_EVENT_DOORBELL)
|
static int QueueWindowEmpty(const Queue_t q)
|
{
|
{
|
s = RIO_portGetSymbol(&stack);
|
return ((q.available + q.windowSize) == q.size);
|
RIO_portAddSymbol(&stack, s);
|
|
}
|
}
|
|
|
RIO_receiveDoorbell(&stack, &srcid, &tid, &info);
|
|
|
|
TESTEXPR(srcid, 0xdead);
|
|
TESTEXPR(tid, 16);
|
|
TESTEXPR(info, 0xbabe);
|
|
RIO_packetRemove(&stack);
|
|
|
|
/******************************************************************************/
|
|
TESTEND;
|
|
/******************************************************************************/
|
|
PrintS("----------------------------------------------------------------------");
|
|
PrintS("Step 2:");
|
|
PrintS("Action: Send a response that is used for doorbells.");
|
|
PrintS("Result: The same data should be returned.");
|
|
PrintS("----------------------------------------------------------------------");
|
|
/******************************************************************************/
|
|
TESTSTART("TG_riostack-TC9-Step2");
|
|
/******************************************************************************/
|
|
|
|
RIO_sendResponseDone(&stack, 0x0060, 16);
|
|
|
|
while(RIO_eventPoll(&stack) != RIO_EVENT_RESPONSE_DONE)
|
static Queue_t QueueWindowReset(Queue_t q)
|
{
|
{
|
s = RIO_portGetSymbol(&stack);
|
q.windowIndex = q.frontIndex;
|
RIO_portAddSymbol(&stack, s);
|
q.windowSize = 0;
|
|
return q;
|
}
|
}
|
|
|
RIO_receiveResponseDone(&stack, &srcid, &tid);
|
|
|
|
TESTEXPR(srcid, 0xdead);
|
|
TESTEXPR(tid, 16);
|
|
RIO_packetRemove(&stack);
|
|
|
|
/******************************************************************************/
|
static Queue_t QueueWindowNext(Queue_t q)
|
TESTEND;
|
|
/******************************************************************************/
|
|
PrintS("----------------------------------------------------------------------");
|
|
PrintS("TG_riostack-TC10");
|
|
PrintS("Description: Test MESSAGE packets.");
|
|
PrintS("Requirement: XXXXX");
|
|
PrintS("----------------------------------------------------------------------");
|
|
PrintS("Step 1:");
|
|
PrintS("Action: Send increasing number of byte using MESSAGE on all mailboxes");
|
|
PrintS(" and receive it at the other side.");
|
|
PrintS("Result: The same MESSAGE on the correct mailbox should be received as has");
|
|
PrintS(" been sent.");
|
|
PrintS("----------------------------------------------------------------------");
|
|
/******************************************************************************/
|
|
TESTSTART("TG_riostack-TC10-Step1");
|
|
/******************************************************************************/
|
|
|
|
for(k = 0; k < 256; k++)
|
|
{
|
|
for(j = 1; j < 256; j++)
|
|
{
|
{
|
for(i = 0; i < j; i++)
|
q.windowIndex++;
|
|
if(q.windowIndex == q.size)
|
{
|
{
|
payload8[i] = i+j+1;
|
q.windowIndex = 0;
|
payload8Expected[i] = 0;
|
|
}
|
}
|
|
q.windowSize++;
|
RIO_sendMessage(&stack, 0x0060, k, j, payload8);
|
return q;
|
|
|
while(RIO_eventPoll(&stack) != RIO_EVENT_MESSAGE)
|
|
{
|
|
s = RIO_portGetSymbol(&stack);
|
|
RIO_portAddSymbol(&stack, s);
|
|
}
|
}
|
|
|
length = RIO_receiveMessage(&stack, &srcid, &mailbox, sizeof(payload8Expected), payload8Expected);
|
|
|
|
TESTEXPR(srcid, 0xdead);
|
|
TESTEXPR(mailbox, k);
|
|
TESTEXPR(length, (((j-1)/8)+1)*8);
|
|
|
|
for(i = 0; i < j; i++)
|
static void QueueSetSize(Queue_t q, const uint32_t size)
|
{
|
{
|
TESTEXPR(payload8Expected[i], (uint8_t) (i+j+1));
|
(q.buffer_p+(RIOSTACK_BUFFER_SIZE*q.backIndex))[0] = size;
|
}
|
}
|
|
|
RIO_packetRemove(&stack);
|
|
}
|
|
}
|
|
|
|
/******************************************************************************/
|
|
TESTEND;
|
|
/******************************************************************************/
|
|
PrintS("----------------------------------------------------------------------");
|
|
PrintS("Step 2:");
|
|
PrintS("Action: Send a MESSAGE-RESPONSE from all mailboxes.");
|
|
PrintS("Result: The same MESSAGE-RESPONSE should be received as has been sent.");
|
|
PrintS("----------------------------------------------------------------------");
|
|
/******************************************************************************/
|
|
TESTSTART("TG_riostack-TC10-Step2");
|
|
/******************************************************************************/
|
|
|
|
for(i = 0; i < 256; i++)
|
|
{
|
|
RIO_sendMessageResponseDone(&stack, 0x0060, i);
|
|
|
|
while(RIO_eventPoll(&stack) != RIO_EVENT_MESSAGE_RESPONSE_DONE)
|
static void QueueSetContent(Queue_t q, const uint32_t index, const uint32_t content)
|
{
|
{
|
s = RIO_portGetSymbol(&stack);
|
(q.buffer_p+(RIOSTACK_BUFFER_SIZE*q.backIndex))[index+1ul] = content;
|
RIO_portAddSymbol(&stack, s);
|
|
}
|
}
|
|
|
RIO_receiveMessageResponseDone(&stack, &srcid, &mailbox);
|
|
|
|
TESTEXPR(srcid, 0xdead);
|
|
TESTEXPR(mailbox, i);
|
static uint32_t QueueGetSize(Queue_t q)
|
RIO_packetRemove(&stack);
|
{
|
|
return (q.buffer_p+(RIOSTACK_BUFFER_SIZE*q.windowIndex))[0];
|
}
|
}
|
|
|
/******************************************************************************/
|
|
TESTEND;
|
|
/******************************************************************************/
|
|
PrintS("----------------------------------------------------------------------");
|
|
PrintS("TG_riostack-TC11");
|
|
PrintS("Description: Test reading and writing raw packets.");
|
|
PrintS("Requirement: XXXXX");
|
|
PrintS("----------------------------------------------------------------------");
|
|
PrintS("Step 1:");
|
|
PrintS("Action: Send a packet using normal functions then copy it using the ");
|
|
PrintS(" packetGet() and packetSet() functions. ");
|
|
PrintS("Result: The same packet should be received when copied.");
|
|
PrintS("----------------------------------------------------------------------");
|
|
/******************************************************************************/
|
|
TESTSTART("TG_riostack-TC11-Step1");
|
|
/******************************************************************************/
|
|
|
|
RIO_sendDoorbell(&stack, 0x0060, 1, 0xca1e);
|
|
|
|
while(RIO_eventPoll(&stack) != RIO_EVENT_DOORBELL)
|
static uint32_t QueueGetFrontContent(const Queue_t q, const uint32_t index)
|
{
|
{
|
s = RIO_portGetSymbol(&stack);
|
return (q.buffer_p+(RIOSTACK_BUFFER_SIZE*q.windowIndex))[index+1ul];
|
RIO_portAddSymbol(&stack, s);
|
|
}
|
}
|
|
|
RIO_receiveDoorbell(&stack, &srcid, &tid, &info);
|
|
|
|
TESTEXPR(srcid, 0xdead);
|
|
TESTEXPR(tid, 1);
|
|
TESTEXPR(info, 0xca1e);
|
|
|
|
packetLength = RIO_packetGet(&stack, sizeof(packet)/4, packet);
|
static uint32_t *QueueGetFrontBuffer(const Queue_t q )
|
RIO_packetSet(&stack, packetLength, packet);
|
|
|
|
while(RIO_eventPoll(&stack) != RIO_EVENT_DOORBELL)
|
|
{
|
{
|
s = RIO_portGetSymbol(&stack);
|
return &((q.buffer_p+(RIOSTACK_BUFFER_SIZE*q.windowIndex))[1]);
|
RIO_portAddSymbol(&stack, s);
|
|
}
|
}
|
|
|
TESTEXPR(srcid, 0xdead);
|
|
TESTEXPR(tid, 1);
|
|
TESTEXPR(info, 0xca1e);
|
|
RIO_packetRemove(&stack);
|
|
|
|
/******************************************************************************/
|
|
TESTEND;
|
|
/******************************************************************************/
|
|
|
|
return 0;
|
static uint32_t *QueueGetBackBuffer(const Queue_t q )
|
|
{
|
|
return &((q.buffer_p+(RIOSTACK_BUFFER_SIZE*q.backIndex))[1]);
|
}
|
}
|
#endif
|
|
|
|
/*************************** end of file **************************************/
|
/*************************** end of file **************************************/
|
|
|
No newline at end of file
|
No newline at end of file
|