OpenCores
URL https://opencores.org/ocsvn/rio/rio/trunk

Subversion Repositories rio

Compare Revisions

  • This comparison shows the changes necessary to convert path
    /
    from Rev 48 to Rev 49
    Reverse comparison

Rev 48 → Rev 49

/rio/trunk/sw/stack/test_riostack.c
0,0 → 1,1955
/*******************************************************************************
*
* RapidIO IP Library Core
*
* This file is part of the RapidIO IP library project
* http://www.opencores.org/cores/rio/
*
* Description:
* This file contains automatic regression tests for riopacket. Compile and
* run it by using:
* gcc -o testriostack test_riostack.c riopacket.c -fprofile-arcs -ftest-coverage
* ./testriostack
* gcov test_riostack.c
*
* To Do:
* -
*
* Author(s):
* - Magnus Rosenius, magro732@opencores.org
*
*******************************************************************************
*
* Copyright (C) 2015 Authors and OPENCORES.ORG
*
* This source file may be used and distributed without
* restriction provided that this copyright statement is not
* removed from the file and that any derivative work contains
* the original copyright notice and the associated disclaimer.
*
* This source file is free software; you can redistribute it
* and/or modify it under the terms of the GNU Lesser General
* Public License as published by the Free Software Foundation;
* either version 2.1 of the License, or (at your option) any
* later version.
*
* This source is distributed in the hope that it will be
* useful, but WITHOUT ANY WARRANTY; without even the implied
* warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
* PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General
* Public License along with this source; if not, download it
* from http://www.opencores.org/lgpl.shtml
*
*******************************************************************************/
#include <stdio.h>
#include <stdlib.h>
 
#define MODULE_TEST
#include "riostack.c"
 
#define PrintS(s) \
{ \
FILE *fd; \
fd=fopen("testspec.txt", "a"); \
fputs(s "\n", fd); \
fclose(fd); \
}
 
#define TESTSTART(s) printf(s)
#define TESTEND printf(" passed.\n");
 
#define TESTCOND(got) \
if (!(got)) \
{ \
printf("\nERROR at line %u:%s=%u (0x%08x)\n", \
__LINE__, #got, (got), (got)); \
exit(1); \
}
 
#define TESTEXPR(got, expected) \
if ((got)!=(expected)) \
{ \
printf("\nERROR 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_t got, RioSymbol_t expected)
{
if ((got).type==(expected).type)
{
switch ((got).type)
{
case RIOSTACK_SYMBOL_TYPE_ERROR:
case RIOSTACK_SYMBOL_TYPE_IDLE:
break;
case RIOSTACK_SYMBOL_TYPE_CONTROL:
if((got).data != (expected).data)
{
if(STYPE0_GET((got).data) != STYPE0_GET((expected).data))
{
printf("\nERROR 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("\nERROR 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("\nERROR 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("\nERROR 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("\nERROR 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("\nERROR at line %u:CRC5=0x%02x expected=0x%02x\n",
line, CRC5_GET((got).data), CRC5_GET((expected).data));
}
exit(1);
}
break;
case RIOSTACK_SYMBOL_TYPE_DATA:
if((got).data != (expected).data)
{
printf("\nERROR at line %u:%s=%u (0x%08x) expected=%u (0x%08x)\n",
line, expression, (got).data, (got).data, (expected).data, (expected).data);
exit(1);
}
break;
}
}
else
{
printf("\nERROR at line %u:%s=%u (0x%08x) expected=%u (0x%08x)\n",
line, expression, (got).type, (got).type, (expected).type, (expected).type);
exit(1);
}
}
 
 
 
uint8_t createDoorbell(uint32_t *doorbell, uint8_t ackId, uint16_t destid, uint16_t srcId, uint8_t tid, uint16_t info)
{
uint16_t crc;
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 = RIOPACKET_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 = RIOPACKET_Crc32(content, crc);
doorbell[1] = content;
 
/* infoMSB(7:0)|infoLSB(7:0)|crc(15:0) */
content = ((uint32_t) info) << 16;
crc = RIOPACKET_Crc16(info, crc);
content |= ((uint32_t) crc);
doorbell[2] = content;
 
return 3;
 
}
 
/*******************************************************************************
* Module test for this file.
*******************************************************************************/
int32_t main(void)
{
RioStack_t stack;
uint32_t rxPacketBuffer[RIOSTACK_BUFFER_SIZE*8], txPacketBuffer[RIOSTACK_BUFFER_SIZE*8];
RioPacket_t rioPacket;
uint32_t packet[69];
RioSymbol_t s, c, d;
int i, j, k;
uint16_t length;
uint16_t dstid;
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 packetLength;
 
 
/*************************************************************************
* Test prelude.
* Setup the RIO stack for operation.
*************************************************************************/
 
/* Open the stack and set the port status to initialized. */
RIOSTACK_open(&stack, NULL,
RIOSTACK_BUFFER_SIZE*8, &rxPacketBuffer[0],
RIOSTACK_BUFFER_SIZE*8, &txPacketBuffer[0]);
 
/* Set the port timeout. */
RIOSTACK_portSetTimeout(&stack, 1);
 
/* Set the current port time. */
RIOSTACK_portSetTime(&stack, 0);
 
/******************************************************************************/
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. */
RIOPACKET_setDoorbell(&rioPacket, 1, 0xffff, 0, 0xdeaf);
RIOSTACK_setOutboundPacket(&stack, &rioPacket);
/* 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++)
{
RIOSTACK_portAddSymbol(&stack, CreateControlSymbol(STYPE0_STATUS, 0, 1, STYPE1_NOP, 0));
s = RIOSTACK_portGetSymbol(&stack);
TESTEXPR(s.type, RIOSTACK_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. */
RIOSTACK_portSetStatus(&stack, 1);
 
/* Set port time. */
RIOSTACK_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 = RIOSTACK_portGetSymbol(&stack);
TESTEXPR(s.type, RIOSTACK_SYMBOL_TYPE_IDLE);
}
s = RIOSTACK_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. */
RIOSTACK_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 = RIOSTACK_portGetSymbol(&stack);
TESTEXPR(s.type, RIOSTACK_SYMBOL_TYPE_IDLE);
}
s = RIOSTACK_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);
RIOSTACK_portAddSymbol(&stack, CreateControlSymbol(STYPE0_STATUS, 0, 8, STYPE1_START_OF_PACKET, 0));
for(i = 0; i < packetLength; i++)
{
d.type = RIOSTACK_SYMBOL_TYPE_DATA;
d.data = packet[i];
RIOSTACK_portAddSymbol(&stack, d);
}
RIOSTACK_portAddSymbol(&stack, CreateControlSymbol(STYPE0_STATUS, 0, 8, STYPE1_END_OF_PACKET, 0));
 
/* Check that packet was not received. */
TESTEXPR(RIOSTACK_getInboundQueueLength(&stack), 0);
 
/******************************************************************************/
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++)
{
RIOSTACK_portAddSymbol(&stack, CreateControlSymbol(STYPE0_STATUS, 0, 1, STYPE1_NOP, 0));
}
c = CreateControlSymbol(STYPE0_STATUS, 0, 1, STYPE1_NOP, 0);
c.data ^= 1;
RIOSTACK_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);
RIOSTACK_portAddSymbol(&stack, CreateControlSymbol(STYPE0_STATUS, 0, 8, STYPE1_START_OF_PACKET, 0));
for(i = 0; i < packetLength; i++)
{
d.type = RIOSTACK_SYMBOL_TYPE_DATA;
d.data = packet[i];
RIOSTACK_portAddSymbol(&stack, d);
}
RIOSTACK_portAddSymbol(&stack, CreateControlSymbol(STYPE0_STATUS, 0, 8, STYPE1_END_OF_PACKET, 0));
 
/* Check that the packet was ignored. */
TESTEXPR(RIOSTACK_getInboundQueueLength(&stack), 0);
 
/******************************************************************************/
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++)
{
RIOSTACK_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);
RIOSTACK_portAddSymbol(&stack, CreateControlSymbol(STYPE0_STATUS, 0, 8, STYPE1_START_OF_PACKET, 0));
for(i = 0; i < packetLength; i++)
{
d.type = RIOSTACK_SYMBOL_TYPE_DATA;
d.data = packet[i];
RIOSTACK_portAddSymbol(&stack, d);
}
RIOSTACK_portAddSymbol(&stack, CreateControlSymbol(STYPE0_STATUS, 0, 8, STYPE1_END_OF_PACKET, 0));
 
/* Check that the packet is received. */
TESTEXPR(RIOSTACK_getInboundQueueLength(&stack), 1);
 
/******************************************************************************/
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 = RIOSTACK_portGetSymbol(&stack);
TESTEXPR(s.type, RIOSTACK_SYMBOL_TYPE_IDLE);
}
s = RIOSTACK_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 = RIOSTACK_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 = RIOSTACK_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 = RIOSTACK_portGetSymbol(&stack);
d.type = RIOSTACK_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 = RIOSTACK_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. */
RIOSTACK_getInboundPacket(&stack, &rioPacket);
 
/* Check that the status-control-symbols are generated each 256 symbol. */
for(i = 0; i < 255; i++)
{
s = RIOSTACK_portGetSymbol(&stack);
TESTEXPR(s.type, RIOSTACK_SYMBOL_TYPE_IDLE);
}
 
/* Check that the buffer status has been updated. */
s = RIOSTACK_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. */
RIOPACKET_setDoorbell(&rioPacket, 2, 0xffff, 1, 0xc0de);
RIOSTACK_setOutboundPacket(&stack, &rioPacket);
 
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 = RIOSTACK_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 = RIOSTACK_portGetSymbol(&stack);
d.type = RIOSTACK_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 = RIOSTACK_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. */
RIOSTACK_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 = RIOSTACK_portGetSymbol(&stack);
TESTEXPR(s.type, RIOSTACK_SYMBOL_TYPE_IDLE);
}
s = RIOSTACK_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. */
RIOSTACK_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 = RIOSTACK_portGetSymbol(&stack);
TESTEXPR(s.type, RIOSTACK_SYMBOL_TYPE_IDLE);
}
s = RIOSTACK_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);
 
RIOSTACK_portAddSymbol(&stack, CreateControlSymbol(STYPE0_STATUS, 2, 1, STYPE1_START_OF_PACKET, 0));
for(i = 0; i < packetLength; i++)
{
d.type = RIOSTACK_SYMBOL_TYPE_DATA;
d.data = packet[i];
RIOSTACK_portAddSymbol(&stack, d);
}
RIOSTACK_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 = RIOSTACK_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);
RIOSTACK_portAddSymbol(&stack, CreateControlSymbol(STYPE0_STATUS, 2, 1, STYPE1_START_OF_PACKET, 0));
for(i = 0; i < packetLength; i++)
{
d.type = RIOSTACK_SYMBOL_TYPE_DATA;
d.data = packet[i];
RIOSTACK_portAddSymbol(&stack, d);
}
RIOSTACK_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 = RIOSTACK_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);
RIOSTACK_portAddSymbol(&stack, CreateControlSymbol(STYPE0_STATUS, 2, 1, STYPE1_START_OF_PACKET, 0));
for(i = 0; i < packetLength; i++)
{
d.type = RIOSTACK_SYMBOL_TYPE_DATA;
d.data = packet[i];
RIOSTACK_portAddSymbol(&stack, d);
}
RIOSTACK_portAddSymbol(&stack, CreateControlSymbol(STYPE0_STATUS, 2, 1, STYPE1_END_OF_PACKET, 0));
s = RIOSTACK_portGetSymbol(&stack);
 
/* Check that nothing is transmitted. */
TESTEXPR(s.type, RIOSTACK_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. */
RIOSTACK_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. */
RIOSTACK_getInboundPacket(&stack, &rioPacket);
RIOPACKET_getDoorbell(&rioPacket, &dstid, &srcid, &tid, &info);
TESTEXPR(tid, 1);
 
/* Check that the buffer status has changed to show that a buffer is available. */
s = RIOSTACK_portGetSymbol(&stack);
while(s.type == RIOSTACK_SYMBOL_TYPE_IDLE)
{
s = RIOSTACK_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);
RIOSTACK_portAddSymbol(&stack, CreateControlSymbol(STYPE0_STATUS, 2, 1, STYPE1_START_OF_PACKET, 0));
for(i = 0; i < packetLength; i++)
{
d.type = RIOSTACK_SYMBOL_TYPE_DATA;
d.data = packet[i];
RIOSTACK_portAddSymbol(&stack, d);
}
RIOSTACK_portAddSymbol(&stack, CreateControlSymbol(STYPE0_STATUS, 2, 1, STYPE1_END_OF_PACKET, 0));
c = CreateControlSymbol(STYPE0_PACKET_ACCEPTED, 9, 0, STYPE1_NOP, 0);
s = RIOSTACK_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);
RIOSTACK_portAddSymbol(&stack, CreateControlSymbol(STYPE0_STATUS, 2, 1, STYPE1_START_OF_PACKET, 0));
for(i = 0; i < packetLength; i++)
{
d.type = RIOSTACK_SYMBOL_TYPE_DATA;
d.data = packet[i];
RIOSTACK_portAddSymbol(&stack, d);
}
RIOSTACK_portAddSymbol(&stack, CreateControlSymbol(STYPE0_STATUS, 2, 1, STYPE1_END_OF_PACKET, 0));
c = CreateControlSymbol(STYPE0_PACKET_RETRY, 10, 0, STYPE1_NOP, 0);
s = RIOSTACK_portGetSymbol(&stack);
TESTEXPR(s.type, c.type);
TESTEXPR(s.data, c.data);
 
/* Send two packets to see that the first acknowledge has been processed. */
RIOPACKET_setDoorbell(&rioPacket, 0, 0xffff, 2, 0xfeed);
RIOSTACK_setOutboundPacket(&stack, &rioPacket);
RIOPACKET_setDoorbell(&rioPacket, 0, 0xffff, 3, 0xdeed);
RIOSTACK_setOutboundPacket(&stack, &rioPacket);
 
/* Get the first packet. */
packetLength = createDoorbell(packet, 2, 0, 0xffff, 2, 0xfeed);
c = CreateControlSymbol(STYPE0_STATUS, 10, 0, STYPE1_START_OF_PACKET, 0);
s = RIOSTACK_portGetSymbol(&stack);
TESTEXPR(s.type, c.type);
TESTEXPR(s.data, c.data);
for(i = 0; i < packetLength; i++)
{
s = RIOSTACK_portGetSymbol(&stack);
d.type = RIOSTACK_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 = RIOSTACK_portGetSymbol(&stack);
TESTSYMBOL(s, c);
for(i = 0; i < packetLength; i++)
{
s = RIOSTACK_portGetSymbol(&stack);
d.type = RIOSTACK_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 = RIOSTACK_portGetSymbol(&stack);
TESTEXPR(s.type, c.type);
TESTEXPR(s.data, c.data);
 
/* Indicate the packets must be retransmitted. */
RIOSTACK_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 = RIOSTACK_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 = RIOSTACK_portGetSymbol(&stack);
TESTEXPR(s.type, c.type);
TESTEXPR(s.data, c.data);
for(i = 0; i < packetLength; i++)
{
s = RIOSTACK_portGetSymbol(&stack);
d.type = RIOSTACK_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 = RIOSTACK_portGetSymbol(&stack);
TESTSYMBOL(s, c);
for(i = 0; i < packetLength; i++)
{
s = RIOSTACK_portGetSymbol(&stack);
d.type = RIOSTACK_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 = RIOSTACK_portGetSymbol(&stack);
TESTEXPR(s.type, c.type);
TESTEXPR(s.data, c.data);
 
/* Confirm the reception of the packets. */
RIOSTACK_portAddSymbol(&stack, CreateControlSymbol(STYPE0_PACKET_ACCEPTED, 2, 1, STYPE1_NOP, 0));
RIOSTACK_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. */
RIOSTACK_portAddSymbol(&stack, CreateControlSymbol(STYPE0_STATUS, 4, 0, STYPE1_NOP, 0));
 
/* Send a packet. */
RIOPACKET_setDoorbell(&rioPacket, 0, 0xffff, 4, 0xf00d);
RIOSTACK_setOutboundPacket(&stack, &rioPacket);
 
/* Check that nothing is transmitted but status-control-symbols. */
for(i = 0; i < 255; i++)
{
s = RIOSTACK_portGetSymbol(&stack);
TESTEXPR(s.type, RIOSTACK_SYMBOL_TYPE_IDLE);
}
s = RIOSTACK_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. */
RIOSTACK_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 = RIOSTACK_portGetSymbol(&stack);
TESTEXPR(s.type, c.type);
TESTEXPR(s.data, c.data);
for(i = 0; i < packetLength; i++)
{
s = RIOSTACK_portGetSymbol(&stack);
d.type = RIOSTACK_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 = RIOSTACK_portGetSymbol(&stack);
TESTEXPR(s.type, c.type);
TESTEXPR(s.data, c.data);
RIOSTACK_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 = RIOSTACK_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 = RIOSTACK_portGetSymbol(&stack);
TESTEXPR(s.type, c.type);
TESTEXPR(s.data, c.data);
for(i = 0; i < packetLength; i++)
{
s = RIOSTACK_portGetSymbol(&stack);
d.type = RIOSTACK_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 = RIOSTACK_portGetSymbol(&stack);
TESTEXPR(s.type, c.type);
TESTEXPR(s.data, c.data);
RIOSTACK_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++)
{
RIOSTACK_getInboundPacket(&stack, &rioPacket);
RIOPACKET_getDoorbell(&rioPacket, &dstid, &srcid, &tid, &info);
TESTEXPR(tid, j+2);
for(i = 0; i < 255; i++)
{
s = RIOSTACK_portGetSymbol(&stack);
TESTEXPR(s.type, RIOSTACK_SYMBOL_TYPE_IDLE);
}
s = RIOSTACK_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. */
RIOSTACK_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);
RIOSTACK_portAddSymbol(&stack, CreateControlSymbol(STYPE0_STATUS, 5, 1, STYPE1_START_OF_PACKET, 0));
for(i = 0; i < packetLength; i++)
{
d.type = RIOSTACK_SYMBOL_TYPE_DATA;
d.data = packet[i];
RIOSTACK_portAddSymbol(&stack, d);
}
RIOSTACK_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 = RIOSTACK_portGetSymbol(&stack);
TESTEXPR(s.type, c.type);
TESTEXPR(s.data, c.data);
 
/* Send a link-request. */
RIOSTACK_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 = RIOSTACK_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 = RIOSTACK_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;
RIOSTACK_portAddSymbol(&stack, CreateControlSymbol(STYPE0_STATUS, 5, 1, STYPE1_START_OF_PACKET, 0));
for(i = 0; i < packetLength; i++)
{
d.type = RIOSTACK_SYMBOL_TYPE_DATA;
d.data = packet[i];
RIOSTACK_portAddSymbol(&stack, d);
}
RIOSTACK_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 = RIOSTACK_portGetSymbol(&stack);
TESTEXPR(s.type, c.type);
TESTEXPR(s.data, c.data);
 
/* Send a link-request. */
RIOSTACK_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 = RIOSTACK_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 = RIOSTACK_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);
RIOSTACK_portAddSymbol(&stack, CreateControlSymbol(STYPE0_STATUS, 5, 1, STYPE1_START_OF_PACKET, 0));
d.type = RIOSTACK_SYMBOL_TYPE_DATA;
d.data = packet[0];
RIOSTACK_portAddSymbol(&stack, d);
d.type = RIOSTACK_SYMBOL_TYPE_DATA;
d.data = ((uint32_t) RIOPACKET_Crc32(packet[0] & 0x07ffffff, 0xffff)) << 16;
RIOSTACK_portAddSymbol(&stack, d);
RIOSTACK_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 = RIOSTACK_portGetSymbol(&stack);
TESTEXPR(s.type, c.type);
TESTEXPR(s.data, c.data);
 
/* Send a link-request. */
RIOSTACK_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 = RIOSTACK_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 = RIOSTACK_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);
RIOSTACK_portAddSymbol(&stack, CreateControlSymbol(STYPE0_STATUS, 5, 1, STYPE1_START_OF_PACKET, 0));
for(i = 0; i < packetLength; i++)
{
d.type = RIOSTACK_SYMBOL_TYPE_DATA;
d.data = packet[i];
RIOSTACK_portAddSymbol(&stack, d);
}
for(; i < 70; i++)
{
d.type = RIOSTACK_SYMBOL_TYPE_DATA;
d.data = i;
RIOSTACK_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 = RIOSTACK_portGetSymbol(&stack);
TESTEXPR(s.type, c.type);
TESTEXPR(s.data, c.data);
 
/* Send a link-request. */
RIOSTACK_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 = RIOSTACK_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 = RIOSTACK_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 = RIOSTACK_SYMBOL_TYPE_DATA;
d.data = packet[0];
RIOSTACK_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 = RIOSTACK_portGetSymbol(&stack);
TESTEXPR(s.type, c.type);
TESTEXPR(s.data, c.data);
 
/* Send a link-request. */
RIOSTACK_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 = RIOSTACK_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 = RIOSTACK_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. */
RIOSTACK_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 = RIOSTACK_portGetSymbol(&stack);
TESTSYMBOL(s, c);
 
/* Send a link-request. */
RIOSTACK_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 = RIOSTACK_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 = RIOSTACK_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 = RIOSTACK_SYMBOL_TYPE_ERROR;
RIOSTACK_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 = RIOSTACK_portGetSymbol(&stack);
TESTEXPR(s.type, c.type);
TESTEXPR(s.data, c.data);
 
/* Send a link-request. */
RIOSTACK_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 = RIOSTACK_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 = RIOSTACK_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. */
RIOSTACK_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 = RIOSTACK_portGetSymbol(&stack);
TESTEXPR(s.type, c.type);
TESTEXPR(s.data, c.data);
 
/* Send link-response with expected ackId. */
RIOSTACK_portAddSymbol(&stack, CreateControlSymbol(STYPE0_LINK_RESPONSE, 5, 16, STYPE1_NOP, 0));
/* Send a status directly afterwards. */
RIOSTACK_portAddSymbol(&stack, CreateControlSymbol(STYPE0_STATUS, 5, 1, STYPE1_NOP, 0));
 
/* Check that packets are relayed after this. */
RIOPACKET_setDoorbell(&rioPacket, 0, 0xffff, 5, 2);
RIOSTACK_setOutboundPacket(&stack, &rioPacket);
packetLength = createDoorbell(packet, 5, 0, 0xffff, 5, 2);
c = CreateControlSymbol(STYPE0_STATUS, 10, 8, STYPE1_START_OF_PACKET, 0);
s = RIOSTACK_portGetSymbol(&stack);
TESTEXPR(s.type, c.type);
TESTEXPR(s.data, c.data);
for(i = 0; i < packetLength; i++)
{
s = RIOSTACK_portGetSymbol(&stack);
d.type = RIOSTACK_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 = RIOSTACK_portGetSymbol(&stack);
TESTEXPR(s.type, c.type);
TESTEXPR(s.data, c.data);
RIOSTACK_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. */
RIOPACKET_setDoorbell(&rioPacket, 0, 0xffff, 6, 2);
RIOSTACK_setOutboundPacket(&stack, &rioPacket);
packetLength = createDoorbell(packet, 6, 0, 0xffff, 6, 2);
c = CreateControlSymbol(STYPE0_STATUS, 10, 8, STYPE1_START_OF_PACKET, 0);
s = RIOSTACK_portGetSymbol(&stack);
TESTEXPR(s.type, c.type);
TESTEXPR(s.data, c.data);
for(i = 0; i < packetLength; i++)
{
s = RIOSTACK_portGetSymbol(&stack);
d.type = RIOSTACK_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 = RIOSTACK_portGetSymbol(&stack);
TESTEXPR(s.type, c.type);
TESTEXPR(s.data, c.data);
 
/* Send acknowledge for another packet. */
RIOSTACK_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 = RIOSTACK_portGetSymbol(&stack);
TESTEXPR(s.type, c.type);
TESTEXPR(s.data, c.data);
 
/* Send link-response with expected ackId. */
RIOSTACK_portAddSymbol(&stack, CreateControlSymbol(STYPE0_LINK_RESPONSE, 7, 16, STYPE1_NOP, 0));
/* Send a status directly afterwards. */
RIOSTACK_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. */
RIOSTACK_portSetTime(&stack, 2);
 
/* Send an output packet. */
RIOPACKET_setDoorbell(&rioPacket, 0, 0xffff, 7, 2);
RIOSTACK_setOutboundPacket(&stack, &rioPacket);
 
/* Receive the transmitted packet. */
packetLength = createDoorbell(packet, 7, 0, 0xffff, 7, 2);
c = CreateControlSymbol(STYPE0_STATUS, 10, 8, STYPE1_START_OF_PACKET, 0);
s = RIOSTACK_portGetSymbol(&stack);
TESTEXPR(s.type, c.type);
TESTEXPR(s.data, c.data);
for(i = 0; i < packetLength; i++)
{
s = RIOSTACK_portGetSymbol(&stack);
d.type = RIOSTACK_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 = RIOSTACK_portGetSymbol(&stack);
TESTEXPR(s.type, c.type);
TESTEXPR(s.data, c.data);
 
/* Indicate that time has passed to trigger a timeout. */
RIOSTACK_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 = RIOSTACK_portGetSymbol(&stack);
TESTEXPR(s.type, c.type);
TESTEXPR(s.data, c.data);
 
/* Send link-response with expected ackId. */
RIOSTACK_portAddSymbol(&stack, CreateControlSymbol(STYPE0_LINK_RESPONSE, 7, 16, STYPE1_NOP, 0));
/* Send a status directly afterwards. */
RIOSTACK_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 = RIOSTACK_portGetSymbol(&stack);
TESTEXPR(s.type, c.type);
TESTEXPR(s.data, c.data);
for(i = 0; i < packetLength; i++)
{
s = RIOSTACK_portGetSymbol(&stack);
d.type = RIOSTACK_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 = RIOSTACK_portGetSymbol(&stack);
TESTEXPR(s.type, c.type);
TESTEXPR(s.data, c.data);
 
/* Send acknowledge for the retransmitted packet. */
RIOSTACK_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. */
RIOPACKET_setDoorbell(&rioPacket, 0, 0xffff, 8, 3);
RIOSTACK_setOutboundPacket(&stack, &rioPacket);
 
/* Receive the transmitted packet. */
packetLength = createDoorbell(packet, 8, 0, 0xffff, 8, 3);
c = CreateControlSymbol(STYPE0_STATUS, 10, 8, STYPE1_START_OF_PACKET, 0);
s = RIOSTACK_portGetSymbol(&stack);
TESTEXPR(s.type, c.type);
TESTEXPR(s.data, c.data);
for(i = 0; i < packetLength; i++)
{
s = RIOSTACK_portGetSymbol(&stack);
d.type = RIOSTACK_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 = RIOSTACK_portGetSymbol(&stack);
TESTEXPR(s.type, c.type);
TESTEXPR(s.data, c.data);
 
/* Send packet-not-accepted indicating CRC error. */
RIOSTACK_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 = RIOSTACK_portGetSymbol(&stack);
TESTEXPR(s.type, c.type);
TESTEXPR(s.data, c.data);
 
/* Send link-response with expected ackId. */
RIOSTACK_portAddSymbol(&stack, CreateControlSymbol(STYPE0_LINK_RESPONSE, 8, 16, STYPE1_NOP, 0));
/* Send a status directly afterwards. */
RIOSTACK_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 = RIOSTACK_portGetSymbol(&stack);
TESTEXPR(s.type, c.type);
TESTEXPR(s.data, c.data);
for(i = 0; i < packetLength; i++)
{
s = RIOSTACK_portGetSymbol(&stack);
d.type = RIOSTACK_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 = RIOSTACK_portGetSymbol(&stack);
TESTEXPR(s.type, c.type);
TESTEXPR(s.data, c.data);
 
/* Send acknowledge for the retransmitted packet. */
RIOSTACK_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. */
RIOSTACK_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 = RIOSTACK_portGetSymbol(&stack);
TESTEXPR(s.type, c.type);
TESTEXPR(s.data, c.data);
 
/* Send link-response with expected ackId. */
RIOSTACK_portAddSymbol(&stack, CreateControlSymbol(STYPE0_LINK_RESPONSE, 9, 16, STYPE1_NOP, 0));
/* Send a status directly afterwards. */
RIOSTACK_portAddSymbol(&stack, CreateControlSymbol(STYPE0_STATUS, 9, 1, STYPE1_NOP, 0));
 
/* Send an output packet. */
RIOPACKET_setDoorbell(&rioPacket, 0, 0xffff, 9, 4);
RIOSTACK_setOutboundPacket(&stack, &rioPacket);
 
/* Receive retransmitted packet. */
packetLength = createDoorbell(packet, 9, 0, 0xffff, 9, 4);
c = CreateControlSymbol(STYPE0_STATUS, 10, 8, STYPE1_START_OF_PACKET, 0);
s = RIOSTACK_portGetSymbol(&stack);
TESTEXPR(s.type, c.type);
TESTEXPR(s.data, c.data);
for(i = 0; i < packetLength; i++)
{
s = RIOSTACK_portGetSymbol(&stack);
d.type = RIOSTACK_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 = RIOSTACK_portGetSymbol(&stack);
TESTEXPR(s.type, c.type);
TESTEXPR(s.data, c.data);
 
/* Send acknowledge for the retransmitted packet. */
RIOSTACK_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(RIOSTACK_getOutboundQueueAvailable(&stack) > 0);
RIOPACKET_setDoorbell(&rioPacket, 0, 0xffff, 20, 0xbabe);
RIOSTACK_setOutboundPacket(&stack, &rioPacket);
 
TESTCOND(RIOSTACK_getOutboundQueueAvailable(&stack) > 0);
RIOPACKET_setDoorbell(&rioPacket, 0, 0xffff, 21, 0xbabe);
RIOSTACK_setOutboundPacket(&stack, &rioPacket);
 
TESTCOND(RIOSTACK_getOutboundQueueAvailable(&stack) > 0);
RIOPACKET_setDoorbell(&rioPacket, 0, 0xffff, 22, 0xbabe);
RIOSTACK_setOutboundPacket(&stack, &rioPacket);
 
TESTCOND(RIOSTACK_getOutboundQueueAvailable(&stack) > 0);
RIOPACKET_setDoorbell(&rioPacket, 0, 0xffff, 23, 0xbabe);
RIOSTACK_setOutboundPacket(&stack, &rioPacket);
 
TESTCOND(RIOSTACK_getOutboundQueueAvailable(&stack) > 0);
RIOPACKET_setDoorbell(&rioPacket, 0, 0xffff, 24, 0xbabe);
RIOSTACK_setOutboundPacket(&stack, &rioPacket);
 
TESTCOND(RIOSTACK_getOutboundQueueAvailable(&stack) > 0);
RIOPACKET_setDoorbell(&rioPacket, 0, 0xffff, 25, 0xbabe);
RIOSTACK_setOutboundPacket(&stack, &rioPacket);
 
TESTCOND(RIOSTACK_getOutboundQueueAvailable(&stack) > 0);
RIOPACKET_setDoorbell(&rioPacket, 0, 0xffff, 26, 0xbabe);
RIOSTACK_setOutboundPacket(&stack, &rioPacket);
 
TESTCOND(RIOSTACK_getOutboundQueueAvailable(&stack) > 0);
RIOPACKET_setDoorbell(&rioPacket, 0, 0xffff, 27, 0xbabe);
RIOSTACK_setOutboundPacket(&stack, &rioPacket);
 
TESTCOND(RIOSTACK_getOutboundQueueAvailable(&stack) == 0);
 
/* Receive transmitted packet. */
packetLength = createDoorbell(packet, 10, 0, 0xffff, 20, 0xbabe);
c = CreateControlSymbol(STYPE0_STATUS, 10, 8, STYPE1_START_OF_PACKET, 0);
s = RIOSTACK_portGetSymbol(&stack);
TESTEXPR(s.type, c.type);
TESTEXPR(s.data, c.data);
for(i = 0; i < packetLength; i++)
{
s = RIOSTACK_portGetSymbol(&stack);
d.type = RIOSTACK_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 = RIOSTACK_portGetSymbol(&stack);
TESTEXPR(s.type, c.type);
TESTEXPR(s.data, c.data);
for(i = 0; i < packetLength; i++)
{
s = RIOSTACK_portGetSymbol(&stack);
d.type = RIOSTACK_SYMBOL_TYPE_DATA;
d.data = packet[i];
TESTEXPR(s.type, d.type);
TESTEXPR(s.data, d.data);
}
packetLength = createDoorbell(packet, 12, 0, 0xffff, 22, 0xbabe);
c = CreateControlSymbol(STYPE0_STATUS, 10, 8, STYPE1_START_OF_PACKET, 0);
s = RIOSTACK_portGetSymbol(&stack);
TESTEXPR(s.type, c.type);
TESTEXPR(s.data, c.data);
for(i = 0; i < packetLength; i++)
{
s = RIOSTACK_portGetSymbol(&stack);
d.type = RIOSTACK_SYMBOL_TYPE_DATA;
d.data = packet[i];
TESTEXPR(s.type, d.type);
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 = RIOSTACK_portGetSymbol(&stack);
TESTEXPR(s.type, c.type);
TESTEXPR(s.data, c.data);
for(i = 0; i < packetLength; i++)
{
s = RIOSTACK_portGetSymbol(&stack);
d.type = RIOSTACK_SYMBOL_TYPE_DATA;
d.data = packet[i];
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);
s = RIOSTACK_portGetSymbol(&stack);
TESTEXPR(s.type, c.type);
TESTEXPR(s.data, c.data);
for(i = 0; i < packetLength; i++)
{
s = RIOSTACK_portGetSymbol(&stack);
d.type = RIOSTACK_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);
c = CreateControlSymbol(STYPE0_STATUS, 10, 8, STYPE1_START_OF_PACKET, 0);
s = RIOSTACK_portGetSymbol(&stack);
TESTEXPR(s.type, c.type);
TESTEXPR(s.data, c.data);
for(i = 0; i < packetLength; i++)
{
s = RIOSTACK_portGetSymbol(&stack);
d.type = RIOSTACK_SYMBOL_TYPE_DATA;
d.data = packet[i];
TESTEXPR(s.type, d.type);
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 = RIOSTACK_portGetSymbol(&stack);
TESTEXPR(s.type, c.type);
TESTEXPR(s.data, c.data);
for(i = 0; i < packetLength; i++)
{
s = RIOSTACK_portGetSymbol(&stack);
d.type = RIOSTACK_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);
c = CreateControlSymbol(STYPE0_STATUS, 10, 8, STYPE1_START_OF_PACKET, 0);
s = RIOSTACK_portGetSymbol(&stack);
TESTEXPR(s.type, c.type);
TESTEXPR(s.data, c.data);
for(i = 0; i < packetLength; i++)
{
s = RIOSTACK_portGetSymbol(&stack);
d.type = RIOSTACK_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 = RIOSTACK_portGetSymbol(&stack);
TESTEXPR(s.type, c.type);
TESTEXPR(s.data, c.data);
 
for(i = 0; i < 10; i++)
{
s = RIOSTACK_portGetSymbol(&stack);
TESTEXPR(s.type, RIOSTACK_SYMBOL_TYPE_IDLE);
}
 
/* Request retransmission. */
RIOSTACK_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 = RIOSTACK_portGetSymbol(&stack);
TESTEXPR(s.type, c.type);
TESTEXPR(s.data, c.data);
 
/* Check retransmitted packets. */
packetLength = createDoorbell(packet, 10, 0, 0xffff, 20, 0xbabe);
c = CreateControlSymbol(STYPE0_STATUS, 10, 8, STYPE1_START_OF_PACKET, 0);
s = RIOSTACK_portGetSymbol(&stack);
TESTEXPR(s.type, c.type);
TESTEXPR(s.data, c.data);
for(i = 0; i < packetLength; i++)
{
s = RIOSTACK_portGetSymbol(&stack);
d.type = RIOSTACK_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 = RIOSTACK_portGetSymbol(&stack);
TESTEXPR(s.type, c.type);
TESTEXPR(s.data, c.data);
for(i = 0; i < packetLength; i++)
{
s = RIOSTACK_portGetSymbol(&stack);
d.type = RIOSTACK_SYMBOL_TYPE_DATA;
d.data = packet[i];
TESTEXPR(s.type, d.type);
TESTEXPR(s.data, d.data);
}
packetLength = createDoorbell(packet, 12, 0, 0xffff, 22, 0xbabe);
c = CreateControlSymbol(STYPE0_STATUS, 10, 8, STYPE1_START_OF_PACKET, 0);
s = RIOSTACK_portGetSymbol(&stack);
TESTEXPR(s.type, c.type);
TESTEXPR(s.data, c.data);
for(i = 0; i < packetLength; i++)
{
s = RIOSTACK_portGetSymbol(&stack);
d.type = RIOSTACK_SYMBOL_TYPE_DATA;
d.data = packet[i];
TESTEXPR(s.type, d.type);
TESTEXPR(s.data, d.data);
}
 
/* Acknowledge. */
RIOSTACK_portAddSymbol(&stack, CreateControlSymbol(STYPE0_PACKET_ACCEPTED, 10, 1, STYPE1_NOP, 0));
RIOSTACK_portAddSymbol(&stack, CreateControlSymbol(STYPE0_PACKET_ACCEPTED, 11, 1, STYPE1_NOP, 0));
 
packetLength = createDoorbell(packet, 13, 0, 0xffff, 23, 0xbabe);
c = CreateControlSymbol(STYPE0_STATUS, 10, 8, STYPE1_START_OF_PACKET, 0);
s = RIOSTACK_portGetSymbol(&stack);
TESTEXPR(s.type, c.type);
TESTEXPR(s.data, c.data);
for(i = 0; i < packetLength; i++)
{
s = RIOSTACK_portGetSymbol(&stack);
d.type = RIOSTACK_SYMBOL_TYPE_DATA;
d.data = packet[i];
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);
s = RIOSTACK_portGetSymbol(&stack);
TESTEXPR(s.type, c.type);
TESTEXPR(s.data, c.data);
for(i = 0; i < packetLength; i++)
{
s = RIOSTACK_portGetSymbol(&stack);
d.type = RIOSTACK_SYMBOL_TYPE_DATA;
d.data = packet[i];
TESTEXPR(s.type, d.type);
TESTEXPR(s.data, d.data);
}
 
RIOSTACK_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 = RIOSTACK_portGetSymbol(&stack);
TESTEXPR(s.type, c.type);
TESTEXPR(s.data, c.data);
for(i = 0; i < packetLength; i++)
{
s = RIOSTACK_portGetSymbol(&stack);
d.type = RIOSTACK_SYMBOL_TYPE_DATA;
d.data = packet[i];
TESTEXPR(s.type, d.type);
TESTEXPR(s.data, d.data);
}
 
RIOSTACK_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 = RIOSTACK_portGetSymbol(&stack);
TESTEXPR(s.type, c.type);
TESTEXPR(s.data, c.data);
RIOSTACK_portAddSymbol(&stack, CreateControlSymbol(STYPE0_PACKET_ACCEPTED, 14, 1, STYPE1_NOP, 0));
for(i = 0; i < packetLength; i++)
{
s = RIOSTACK_portGetSymbol(&stack);
d.type = RIOSTACK_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);
c = CreateControlSymbol(STYPE0_STATUS, 10, 8, STYPE1_START_OF_PACKET, 0);
s = RIOSTACK_portGetSymbol(&stack);
TESTEXPR(s.type, c.type);
TESTEXPR(s.data, c.data);
for(i = 0; i < packetLength; i++)
{
s = RIOSTACK_portGetSymbol(&stack);
d.type = RIOSTACK_SYMBOL_TYPE_DATA;
d.data = packet[i];
TESTEXPR(s.type, d.type);
TESTEXPR(s.data, d.data);
}
RIOSTACK_portAddSymbol(&stack, CreateControlSymbol(STYPE0_PACKET_ACCEPTED, 15, 1, STYPE1_NOP, 0));
c = CreateControlSymbol(STYPE0_STATUS, 10, 8, STYPE1_END_OF_PACKET, 0);
s = RIOSTACK_portGetSymbol(&stack);
TESTEXPR(s.type, c.type);
TESTEXPR(s.data, c.data);
 
RIOSTACK_portAddSymbol(&stack, CreateControlSymbol(STYPE0_PACKET_ACCEPTED, 16, 1, STYPE1_NOP, 0));
RIOSTACK_portAddSymbol(&stack, CreateControlSymbol(STYPE0_PACKET_ACCEPTED, 17, 1, STYPE1_NOP, 0));
 
/******************************************************************************/
TESTEND;
/******************************************************************************/
 
return 0;
}
 
/*************************** end of file **************************************/
/rio/trunk/sw/stack/riostack.c
15,19 → 15,20
* 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.
*
* Symbols are inserted into the stack by calling RIO_portAddSymbol() and symbols to
* transmit are fetched from the stack using RIO_portGetSymbol(). These two
* functions are the low-level interface towards a physical transmission channel.
* The function RIO_portSetStatus() is used to indicate to the stack that initial
* Symbols are inserted into the stack from the lower-half by calling
* RIOSTACK_portAddSymbol() and symbols to transmit are fetched from the stack
* using RIOSTACK_portGetSymbol(). These two functions are the low-level interface
* 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
* is ready to accept other symbols than idle. The procedure is to set the port
* status to initialized once idle symbols are successfully received.
*
* On the high-level interface are rio_sendXXX() functions used to create and
* insert packets into the outbound transmission queue. The RIO_eventPoll()
* function is used to check if any packet is available for reading in the
* inbound reception queue. These packets are then accessed using
* rio_receiveXXX() functions.
* On the upper-half interface are the RIOSTACK_setOutboundPacket() function used to
* insert packets into the outbound transmission queue and RIOSTACK_getInboundPacket()
* is used to get packet from the inbound reception queue. The
* RIOSTACK_getInboundQueueLength() function is used to check if any packet is available
* for reading in the inbound reception queue.
*
* -----------------
* | OS dependent |
55,40 → 56,37
*
* Some typical patterns to handle this stack are:
* Initialization:
* RIO_open(...);
* RIO_portSetTimeout(...);
* RIOSTACK_open(...);
* RIOSTACK_portSetTimeout(...);
* ...
* <Symbol transcoder is successfully decoding symbols from the link>
* RIO_portSetStatus(1);
* RIOSTACK_portSetStatus(1);
*
* Bottom-half traffic handling:
* RIO_portSetTime(...);
* RIOSTACK_portSetTime(...);
* <get symbol from decoder>
* RIO_portAddSymbol(...);
* s = RIO_portGetSymbol(...);
* RIOSTACK_portAddSymbol(...);
* s = RIOSTACK_portGetSymbol(...);
* <send symbol to encoder>
*
* Receiving packets:
* switch(RIO_eventPoll(...))
* if(RIOSTACK_getInboundQueueLength(...) > 0)
* {
* case RIO_EVENT_DOORBELL:
* RIO_receiveDoorbell(...);
* ...
* RIOSTACK_getInboundPacket(...);
* <process the new packet>
* }
* RIO_packetRemove();
*
* 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
* this file.
* More details about the usage can be found in the module tests in test_riostack.c.
*
* To Do:
* -
* - Optimize the packing of stype0 and stype1 into control symbols.
*
* Author(s):
* - Magnus Rosenius, magro732@opencores.org
95,7 → 93,7
*
*******************************************************************************
*
* Copyright (C) 2013 Authors and OPENCORES.ORG
* Copyright (C) 2015 Authors and OPENCORES.ORG
*
* This source file may be used and distributed without
* restriction provided that this copyright statement is not
120,6 → 118,7
*
*******************************************************************************/
 
 
/**
* \file riostack.c
*/
136,9 → 135,10
/*lint -w2 */
 
 
/* 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 */
 
/*******************************************************************************
* Local macro definitions
*******************************************************************************/
246,18 → 246,26
#define LINK_RESPONSE_PORT_STATUS_ERROR_STOPPED 5u
#define LINK_RESPONSE_PORT_STATUS_OK 16u
 
 
 
/*******************************************************************************
* Local typedefs
*******************************************************************************/
 
 
 
/*******************************************************************************
* Global declarations
*******************************************************************************/
 
 
 
/*******************************************************************************
* Local declarations
*******************************************************************************/
 
 
 
/*******************************************************************************
* Local function prototypes
*******************************************************************************/
274,67 → 282,6
static void handleNewPacketStart(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.
*
343,15 → 290,14
* \param[in] parameter1 The parameter1 value.
* \param[in] stype1 The stype1 value.
* \param[in] cmd The cmd value.
* \param[out] None
* \return The control symbol that were created from the input parameters.
*
* This function creates a control symbol with the specified arguments and
* calculates a CRC-5 checksum according to the standard specification.
*/
static RioSymbol CreateControlSymbol( const uint8_t stype0,
const uint8_t parameter0, const uint8_t parameter1,
const uint8_t stype1, const uint8_t cmd);
static RioSymbol_t CreateControlSymbol(const uint8_t stype0,
const uint8_t parameter0, const uint8_t parameter1,
const uint8_t stype1, const uint8_t cmd);
 
/**
* \brief Function to calculate ITU-CRC5, polynom=0x15.
360,43 → 306,17
* \param[in] crc The crc to initiate the result with.
* \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.
*
* \param[in] The number of entries in the queue.
* \param[in] A pointer to the buffer to store the content in.
* \param[in] size The number of entries in the queue.
* \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
* 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);
 
/**
* \brief Get number of available elements.
404,7 → 324,7
* \param[in] q The queue to operate on.
* \return The number of free packet buffers in the queue.
*/
static uint8_t QueueAvailable( const Queue_t q );
static uint8_t QueueAvailable(const Queue_t q );
 
/**
* \brief Get if the queue is empty or not.
412,7 → 332,7
* \param[in] q The queue to operate on.
* \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.
420,7 → 340,7
* \param[in] q The queue to operate on.
* \return The number of elements in the queue.
*/
static uint8_t QueueLength( const Queue_t q);
static uint8_t QueueLength(const Queue_t q);
 
/**
* \brief Add a new element to the queue.
428,7 → 348,7
* \param[in] q The queue to operate on.
* \return A queue with one added element.
*/
static Queue_t QueueEnqueue( Queue_t q);
static Queue_t QueueEnqueue(Queue_t q);
 
/**
* \brief Remove an element from the queue.
436,7 → 356,7
* \param[in] q The queue to operate on.
* \return A queue with on removed element.
*/
static Queue_t QueueDequeue( Queue_t q);
static Queue_t QueueDequeue(Queue_t q);
 
/**
* \brief Check if the readout window is empty.
444,7 → 364,7
* \param[in] q The queue to operate on.
* \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.
468,7 → 388,7
* \param[in] q The queue to operate on.
* \param[in] size The size to set the newest content size to.
*/
static void QueueSetSize( Queue_t q, const uint32_t size);
static void QueueSetSize(Queue_t q, const uint32_t size);
 
/**
* \brief Set content at a specified index in the newest element.
477,23 → 397,15
* \param[in] index posititon into the 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.
*
* \param[in] q The queue to operate on.
* \return A pointer to the content.
*/
static uint32_t *QueueGetBackBuffer( Queue_t q );
static uint32_t *QueueGetBackBuffer(Queue_t q );
 
/**
* \brief Get the size of the oldest element.
500,7 → 412,7
* \param[in] q The queue to operate on.
* \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.
508,7 → 420,7
* \param[in] index The index into the element to get the content from.
* \return content of element at index position.
*/
static uint32_t QueueGetFrontContent( Queue_t q, const uint32_t index);
static uint32_t QueueGetFrontContent(Queue_t q, const uint32_t index);
 
/**
* \brief Get a pointer to the buffer of the oldest element.
516,7 → 428,7
* \param[in] q The queue to operate on.
* \return A pointer to the content.
*/
static uint32_t *QueueGetFrontBuffer( Queue_t q );
static uint32_t *QueueGetFrontBuffer(Queue_t q );
 
 
 
524,13 → 436,9
* Global functions
*******************************************************************************/
 
void RIO_open( RioStack_t *stack, const RioStackObserver_t *observer, const void *private,
const uint32_t rxPacketBufferSize, uint32_t *rxPacketBuffer,
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 )
void RIOSTACK_open(RioStack_t *stack, void *private,
const uint32_t rxPacketBufferSize, uint32_t *rxPacketBuffer,
const uint32_t txPacketBufferSize, uint32_t *txPacketBuffer)
{
/* Port time and timeout limit. */
stack->portTime = 0u;
544,7 → 452,7
stack->rxAckId = 0u;
stack->rxAckIdAcked = 0u;
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. */
stack->txState = TX_STATE_UNINITIALIZED;
553,26 → 461,8
stack->txFrameState = TX_FRAME_START;
stack->txAckId = 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. */
stack->statusInboundPacketComplete = 0ul;
stack->statusInboundPacketRetry = 0ul;
585,6 → 475,7
 
/* Setup status counters for outbound direction. */
stack->statusOutboundPacketComplete = 0ul;
stack->statusOutboundLinkLatencyMax = 0ul;
stack->statusOutboundPacketRetry = 0ul;
stack->statusOutboundErrorTimeout = 0ul;
stack->statusOutboundErrorPacketAccepted = 0ul;
598,1126 → 489,140
stack->statusPartnerErrorIllegalCharacter = 0ul;
stack->statusPartnerErrorGeneral = 0ul;
 
/* Set callback structure. */
stack->observer = observer;
 
/* Set pointer to user private data. */
stack->private = private;
}
 
 
 
/*******************************************************************************************
* Stack status functions.
* Note that status counters are access directly in the stack-structure.
* Stack status and queue access functions.
* 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. */
if(stack->masterEnable)
{
/* Allowed to act as master. */
status = RIO_STATUS_OPERATIONAL;
}
else
{
/* Not allowed to act as master. */
/* The enumeration process has not been completed yet. */
status = RIO_STATUS_ENUMERATION;
}
}
else
void RIOSTACK_clearOutboundQueue(RioStack_t *stack)
{
while(!QueueEmpty(stack->txQueue))
{
/* The link is not up yet. */
status = RIO_STATUS_UNINITIALIZED;
stack->txQueue = QueueDequeue(stack->txQueue);
}
 
return status;
}
 
 
uint8_t RIO_outboundQueueLength( RioStack_t *stack )
 
uint8_t RIOSTACK_getOutboundQueueLength(RioStack_t *stack)
{
return QueueLength(stack->txQueue);
}
 
 
uint8_t RIO_inboundQueueLength( RioStack_t *stack )
{
return QueueLength(stack->rxQueue);
}
 
 
/*******************************************************************************************
* Packet reception functions.
*******************************************************************************************/
 
RioEventType RIO_eventPoll( RioStack_t *stack )
uint8_t RIOSTACK_getOutboundQueueAvailable(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. */
if(!QueueEmpty(stack->rxQueue))
{
/* There are new pending packets. */
 
/* 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. */
switch(ftype)
{
case FTYPE_REQUEST:
/* Request class. */
 
/* Check transaction type. */
switch(transaction)
{
case TRANSACTION_REQUEST_NREAD:
/* Supported NREAD request. */
event = RIO_EVENT_NREAD;
break;
 
default:
/* Unsupported request transaction. */
/* 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:
/* NWRITE_R transaction. */
if(QueueGetFrontSize(stack->rxQueue) >= 6ul)
{
/* Supported NWRITE_R request. */
event = RIO_EVENT_NWRITE_R;
}
else
{
/* Unsupported size. */
/* REMARK: Throw these away for now. */
stack->statusInboundErrorPacketUnsupported++;
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:
/* 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. */
/* 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. */
if(QueueGetFrontSize(stack->rxQueue) == MAINTENANCE_TRANSACTION_WRITE_RESPONSE_SIZE)
{
/* Supported maintenance write response. */
event = RIO_EVENT_MAINT_WRITE_RESPONSE;
}
else
{
/* Unsupported maintenance write response. */
/* 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. */
if(QueueGetFrontSize(stack->rxQueue) == 3ul)
{
/* Supported doorbell. */
event = RIO_EVENT_DOORBELL;
}
else
{
/* Unsupported doorbell request. */
/* REMARK: Throw these away for now. */
stack->statusInboundErrorPacketUnsupported++;
stack->rxQueue = QueueDequeue(stack->rxQueue);
event = RIO_EVENT_NONE;
}
break;
 
case FTYPE_MESSAGE:
/* Message class. */
 
/* Check msglen to see if this packet continues. */
if(MSGLEN_GET(packet) == 0ul)
{
/* Single-packet message. */
event = RIO_EVENT_MESSAGE;
}
else
{
/* Unsupported message type. */
/* REMARK: Throw these away for now. */
stack->statusInboundErrorPacketUnsupported++;
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)
{
case 0x00000000:
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)
{
case 0x00000000:
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:
/* Unsupported response transaction. */
/* REMARK: Throw these away for now. */
stack->statusInboundErrorPacketUnsupported++;
stack->rxQueue = QueueDequeue(stack->rxQueue);
event = RIO_EVENT_NONE;
break;
}
break;
 
default:
/* Unsupported class. */
/* REMARK: Throw these away for now. */
stack->statusInboundErrorPacketUnsupported++;
stack->rxQueue = QueueDequeue(stack->rxQueue);
event = RIO_EVENT_NONE;
break;
}
}
else
{
/* No pending events available. */
event = RIO_EVENT_NONE;
}
 
return event;
return QueueAvailable(stack->txQueue);
}
 
 
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_setOutboundPacket(RioStack_t *stack, RioPacket_t *packet)
{
/* Return if there are buffers available and if the requested size is less
than or equal to the maximum payload that fits into one packet. */
return (bool_t) (stack->masterEnable && (size <= 256u) && (QueueAvailable(stack->txQueue) > 0u));
}
 
 
uint32_t RIO_packetGet( RioStack_t *stack, uint32_t length, uint32_t *dest)
{
uint32_t *src, *dst;
uint32_t size;
uint32_t i;
uint32_t size;
uint32_t *src;
 
 
ASSERT(!QueueEmpty(stack->rxQueue), "Reading from empty reception queue.");
ASSERT((QueueAvailable(stack->txQueue) > 0u),
"Transmission queue packet overflow.");
 
/* Get the size and a pointer to the raw packet. */
size = QueueGetFrontSize(stack->rxQueue);
src = QueueGetFrontBuffer(stack->rxQueue);
 
ASSERT((length >= size), "Too short destination packet.");
 
/* Copy the packet to the destination packet pointer. */
src = &packet->payload[0];
dst = QueueGetBackBuffer(stack->txQueue);
size = packet->size;
for(i = 0; i < size; i++)
{
dest[i] = src[i];
dst[i] = src[i];
}
 
/* Remove the packet from the queue. */
stack->rxQueue = QueueDequeue(stack->rxQueue);
 
/* Return the size of the copied packet. */
return size;
}
 
 
void RIO_packetSet( RioStack_t *stack, uint32_t length, uint32_t *src)
{
uint32_t i;
uint32_t *dest;
 
 
ASSERT((QueueAvailable(stack->txQueue) > 0), "Writing to full transmission queue.");
ASSERT((length < RIO_PACKET_SIZE), "Writing a too large packet.");
 
/* 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];
}
 
/* Make sure the ackId field of the copied packet is reset. */
/* Unless this is done, the ackId field of the transmitted packet may be corrupted. */
dest[0] &= 0x03ffffff;
 
/* Enqueue the new packet. */
QueueSetSize(stack->txQueue, size);
stack->txQueue = QueueEnqueue(stack->txQueue);
}
 
/*******************************************************************************************
* Configuration-space access methods.
*******************************************************************************************/
 
uint32_t RIO_readConfig( RioStack_t *stack, const uint32_t offset )
{
uint32_t data;
 
/* Check the area of the access. */
if(offset < 0x10000ul)
{
/* Access is in not in implementation-defined space. */
 
/* Check offset and return. */
switch(offset)
{
case DEVICE_IDENTITY_CAR:
data = (uint32_t)stack->deviceIdentity << 16;
data |= stack->deviceVendorIdentity;
break;
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;
case DESTINATION_OPERATIONS_CAR:
/* Supporting doorbells and data messages. */
data = 0x00000c00ul;
break;
case PROCESSING_ELEMENT_LOGICAL_LAYER_CONTROL_CSR:
/* Supports 34-bit addresses. */
data = 0x00000001ul;
break;
case BASE_DEVICE_ID_CSR:
data = stack->baseDeviceId;
break;
case HOST_BASE_DEVICE_ID_LOCK_CSR:
data = stack->hostBaseDeviceIdLock & (uint32_t)0x0000fffful;
break;
case COMPONENT_TAG_CSR:
data = stack->componentTag;
break;
case LP_SERIAL_REGISTER_BLOCK_HEADER(EXTENDED_FEATURES_OFFSET):
/* Indicate Generic end point device and no more extended features. */
data = 0x00000001ul;
break;
case PORT_LINK_TIMEOUT_CONTROL_CSR(EXTENDED_FEATURES_OFFSET):
/* REMARK: Implement this... */
data = 0x00000000ul;
break;
case PORT_RESPONSE_TIMEOUT_CONTROL_CSR(EXTENDED_FEATURES_OFFSET):
/* REMARK: Implement this... */
data = 0x00000000ul;
break;
case PORT_GENERAL_CONTROL_CSR(EXTENDED_FEATURES_OFFSET):
/* Return the host, master enable bit and the discovered bit. */
data = ((uint32_t) stack->host) << 31;
data |= ((uint32_t) stack->masterEnable) << 30;
data |= ((uint32_t) stack->discovered) << 29;
break;
case PORT_N_LOCAL_ACKID_CSR(EXTENDED_FEATURES_OFFSET, 0u):
data = ((uint32_t) stack->rxAckId) << 24;
data |= ((uint32_t) stack->txAckId) << 8;
data |= ((uint32_t) stack->txAckIdWindow);
break;
case PORT_N_ERROR_AND_STATUS_CSR(EXTENDED_FEATURES_OFFSET, 0u):
/* Indicate the port status here. */
if((stack->txState == TX_STATE_LINK_INITIALIZED) &&
(stack->rxState == RX_STATE_LINK_INITIALIZED))
{
/* Port ok. */
data = 0x00000002ul;
}
else
{
/* Port not ok. */
data = 0x00000001ul;
}
break;
default:
data = 0x00000000ul;
break;
}
}
else
{
/* Access is in implementation-defined space. */
 
/* Check if there are any registered callback. */
if((stack->observer != NULL) &&
(stack->observer->configRead != NULL))
{
/* Call the observer callback to handle the access. */
data = stack->observer->configRead(stack, offset - 0x00010000ul);
}
else
{
data = 0x00000000ul;
}
}
 
return data;
}
 
 
void RIO_writeConfig( RioStack_t *stack, const uint32_t offset, const uint32_t data)
void RIOSTACK_clearInboundQueue(RioStack_t *stack)
{
/* Check the area of the access. */
if(offset < 0x00010000ul)
while(!QueueEmpty(stack->rxQueue))
{
/* Access is not in implementation-defined space. */
 
/* Check offset and execute request. */
switch(offset)
{
case BASE_DEVICE_ID_CSR:
stack->baseDeviceId = (uint16_t) data;
break;
case HOST_BASE_DEVICE_ID_LOCK_CSR:
if (stack->hostBaseDeviceIdLock == 0xfffffffful)
{
stack->hostBaseDeviceIdLock = (uint16_t)data;
}
else
{
if ((stack->hostBaseDeviceIdLock & (uint32_t)0x0000fffful) ==
(data & (uint32_t)0x0000fffful))
{
stack->hostBaseDeviceIdLock = 0xfffffffful;
}
else
{
/* Ignore the write. */
}
}
break;
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);
}
}
stack->rxAckId = (uint8_t) ((data >> 24) & 0x1f);
stack->txAckId = (uint8_t) ((data >> 8) & 0x1f);
stack->txAckIdWindow = (uint8_t) (data & 0x1f);
break;
default:
break;
}
stack->rxQueue = QueueDequeue(stack->rxQueue);
}
else
{
/* Access is in implementation-defined space. */
 
/* Check if there are any registered callback. */
if((stack->observer != NULL) &&
(stack->observer->configWrite != NULL))
{
/* Call the observer callback to handle the access. */
stack->observer->configWrite(stack, offset - 0x00010000ul, data);
}
else
{
/* Dont do anything. */
}
}
}
 
 
/*******************************************************************************************
* Logical I/O MAINTENANCE-READ functions.
*******************************************************************************************/
 
#ifdef RIO_TRANSPARENT
void RIO_sendMaintenanceReadRequest( RioStack_t *stack, const uint16_t destid, const uint16_t srcid, const uint8_t tid,
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
 
#ifdef RIO_TRANSPARENT
void RIO_receiveMaintenanceReadRequest( RioStack_t *stack, uint16_t *destid, uint16_t *srcid, uint8_t *tid,
uint8_t *hopCount, uint32_t *offset)
{
receiveMaintenanceReadRequest( stack, destid, srcid, tid, hopCount, offset);
}
#else
void RIO_receiveMaintenanceReadRequest( RioStack_t *stack, uint16_t *srcid, uint8_t *tid,
uint8_t *hopCount, uint32_t *offset)
{
receiveMaintenanceReadRequest( stack, srcid, srcid, tid, hopCount, offset);
}
#endif
 
#ifdef RIO_TRANSPARENT
void RIO_sendMaintenanceReadResponse( RioStack_t *stack, const uint16_t destid, const uint16_t srcid, const uint8_t tid,
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);
}
#endif
 
#ifdef RIO_TRANSPARENT
void RIO_receiveMaintenanceReadResponse( RioStack_t *stack, uint16_t *destid, uint16_t *srcid, uint8_t *tid,
uint8_t *hopCount, uint32_t *data)
uint8_t RIOSTACK_getInboundQueueLength(RioStack_t *stack)
{
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);
return QueueLength(stack->rxQueue);
}
#endif
 
/*******************************************************************************************
* Logical I/O MAINTENANCE-WRITE functions.
*******************************************************************************************/
 
#ifdef RIO_TRANSPARENT
void RIO_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 )
{
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);
}
#endif
 
#ifdef RIO_TRANSPARENT
void RIO_receiveMaintenanceWriteRequest( RioStack_t *stack, uint16_t *destid, uint16_t *srcid, uint8_t *tid,
uint8_t *hopCount, uint32_t *offset, uint32_t *data )
uint8_t RIOSTACK_getInboundQueueAvailable(RioStack_t *stack)
{
receiveMaintenanceWriteRequest(stack, destid, srcid, tid, hopCount, offset, data);
return QueueAvailable(stack->rxQueue);
}
#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
void RIO_receiveMaintenanceWriteResponse( RioStack_t *stack, uint16_t *destid, uint16_t *srcid, uint8_t *tid,
uint8_t *hopCount)
{
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
 
/*******************************************************************************************
* Logical I/O NWRITE/NWRITER functions.
*******************************************************************************************/
 
#ifdef RIO_TRANSPARENT
void RIO_sendNwrite( RioStack_t *stack, const uint16_t destid, const uint16_t srcid,
const uint32_t address, const uint16_t size, const uint8_t *data)
void RIOSTACK_getInboundPacket(RioStack_t *stack, RioPacket_t *packet)
{
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
uint32_t *src, *dst;
uint32_t size;
uint32_t i;
 
#ifdef RIO_TRANSPARENT
void RIO_sendNwriteR( RioStack_t *stack, const uint16_t destid, const uint16_t srcid, const uint8_t tid,
const uint32_t address, const uint16_t size, const uint8_t *data)
{
sendNwrite(stack, destid, srcid, tid, address, size, data, 1u);
}
#else
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
uint16_t RIO_receiveNwrite( RioStack_t *stack, uint16_t *destid, uint16_t *srcid, uint8_t *tid,
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);
}
#endif
ASSERT(!QueueEmpty(stack->rxQueue), "Reading from empty reception queue.");
 
/*******************************************************************************************
* Logical I/O NREAD functions.
*******************************************************************************************/
src = QueueGetFrontBuffer(stack->rxQueue);
dst = &packet->payload[0];
size = QueueGetSize(stack->rxQueue);
for(i = 0; i < size; i++)
{
dst[i] = src[i];
}
 
#ifdef RIO_TRANSPARENT
void RIO_sendNread( RioStack_t *stack, const uint16_t destid, const uint16_t srcid, const uint8_t tid,
const uint32_t address, const uint16_t dataLength)
{
sendNread(stack, destid, srcid, tid, address, dataLength);
packet->size = size;
stack->rxQueue = QueueDequeue(stack->rxQueue);
}
#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
void RIO_receiveNread( RioStack_t *stack, uint16_t *destid, uint16_t *srcid, uint8_t *tid,
uint32_t *address, uint16_t *dataLength)
{
receiveNread( stack, destid, srcid, tid, address, dataLength);
}
#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
 
/*******************************************************************************************
* Logical I/O RESPONSE-DONE-PAYLOAD, RESPONSE-DONE, RESPONSE-RETRY and RESPONSE-ERROR
* functions.
*******************************************************************************************/
 
 
#ifdef RIO_TRANSPARENT
void RIO_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)
{
sendResponseDonePayload(stack, destid, srcid, tid, address, bufferSize, buffer);
}
#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
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);
}
#endif
 
#ifdef RIO_TRANSPARENT
void RIO_sendResponseDone( RioStack_t *stack, const uint16_t destid, const uint16_t srcid, const uint8_t tid)
{
sendResponse(stack, destid, srcid, tid, 0x0u);
}
#else
void RIO_sendResponseDone( RioStack_t *stack, const uint16_t destid, const uint8_t tid)
{
sendResponse(stack, destid, stack->baseDeviceId, tid, 0x0u);
}
#endif
 
 
#ifdef RIO_TRANSPARENT
void RIO_receiveResponseDone( RioStack_t *stack, uint16_t *destid, uint16_t *srcid, uint8_t *tid)
{
receiveResponse(stack, destid, srcid, tid);
}
#else
void RIO_receiveResponseDone( RioStack_t *stack, uint16_t *srcid, uint8_t *tid)
{
receiveResponse(stack, srcid, srcid, tid);
}
#endif
 
 
#ifdef RIO_TRANSPARENT
void RIO_sendResponseRetry( RioStack_t *stack, const uint16_t destid, const uint16_t srcid, const uint8_t tid )
{
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);
}
#endif
 
 
#ifdef RIO_TRANSPARENT
void RIO_receiveResponseRetry( RioStack_t *stack, uint16_t *destid, uint16_t *srcid, uint8_t *tid)
{
receiveResponse(stack, destid, srcid, tid);
}
#else
void RIO_receiveResponseRetry( RioStack_t *stack, uint16_t *srcid, uint8_t *tid)
{
receiveResponse(stack, srcid, srcid, tid);
}
#endif
 
 
#ifdef RIO_TRANSPARENT
void RIO_sendResponseError( RioStack_t *stack, const uint16_t destid, const uint16_t srcid, const uint8_t tid)
{
sendResponse(stack, destid, srcid, tid, 0x7u);
}
#else
void RIO_sendResponseError( RioStack_t *stack, const uint16_t destid, const uint8_t tid)
{
sendResponse(stack, destid, stack->baseDeviceId, tid, 0x7u);
}
#endif
 
 
#ifdef RIO_TRANSPARENT
void RIO_receiveResponseError( RioStack_t *stack, uint16_t *destid, uint16_t *srcid, uint8_t *tid)
{
receiveResponse(stack, destid, srcid, tid);
}
#else
void RIO_receiveResponseError( RioStack_t *stack, uint16_t *srcid, uint8_t *tid)
{
receiveResponse(stack, srcid, srcid, tid);
}
#endif
 
 
 
/*******************************************************************************************
* Logical message passing DOORBELL and MESSAGE functions.
* Packet port functions.
*******************************************************************************************/
 
#ifdef RIO_TRANSPARENT
void RIO_sendDoorbell( RioStack_t *stack, const uint16_t destid, const uint16_t srcid, const uint8_t tid,
const uint16_t info )
void RIOSTACK_portSetTime(RioStack_t *stack, const uint32_t time)
{
sendDoorbell(stack, destid, srcid, tid, info);
stack->portTime = time;
}
#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
void RIO_receiveDoorbell( RioStack_t *stack, uint16_t *srcid, uint8_t *tid,
uint16_t *info)
{
receiveDoorbell(stack, srcid, srcid, tid, info);
}
#endif
 
#ifdef RIO_TRANSPARENT
void RIO_sendMessage( RioStack_t *stack, const uint16_t destid, const uint16_t srcid, const uint8_t mailbox,
const uint16_t bufferSize, const uint8_t* bufferData)
{
sendMessage(stack, destid, srcid, mailbox, bufferSize, bufferData);
}
#else
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
 
#ifdef RIO_TRANSPARENT
uint16_t RIO_receiveMessage( RioStack_t *stack, uint16_t *destid, uint16_t *srcid, uint8_t *mailbox,
const uint16_t dataLength, uint8_t *data )
void RIOSTACK_portSetTimeout(RioStack_t *stack, const uint32_t time)
{
return receiveMessage(stack, destid, srcid, mailbox, dataLength, data);
stack->portTimeout = time;
}
#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)
{
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);
}
#endif
 
 
#ifdef RIO_TRANSPARENT
void RIO_receiveMessageResponseDone( RioStack_t *stack, uint16_t *destid, uint16_t *srcid, uint8_t *mailbox)
void RIOSTACK_portSetStatus(RioStack_t *stack, const uint8_t initialized)
{
receiveMessageResponse(stack, destid, srcid, mailbox);
}
#else
void RIO_receiveMessageResponseDone( RioStack_t *stack, uint16_t *srcid, uint8_t *mailbox)
{
receiveMessageResponse(stack, srcid, srcid, mailbox);
}
#endif
 
 
#ifdef RIO_TRANSPARENT
void RIO_sendMessageResponseRetry( RioStack_t *stack, const uint16_t destid, const uint16_t srcid, const uint8_t mailbox)
{
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);
}
#endif
 
 
#ifdef RIO_TRANSPARENT
void RIO_receiveMessageResponseRetry( RioStack_t *stack, uint16_t *destid, uint16_t *srcid, uint8_t *mailbox)
{
receiveMessageResponse(stack, destid, srcid, mailbox);
}
#else
void RIO_receiveMessageResponseRetry( RioStack_t *stack, uint16_t *srcid, uint8_t *mailbox)
{
receiveMessageResponse(stack, srcid, srcid, mailbox);
}
#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
void RIO_sendMessageResponseError( RioStack_t *stack, const uint16_t destid, const uint8_t mailbox)
{
sendMessageResponse(stack, destid, stack->baseDeviceId, mailbox, 0x7u);
}
#endif
 
 
#ifdef RIO_TRANSPARENT
void RIO_receiveMessageResponseError( RioStack_t *stack, uint16_t *destid, uint16_t *srcid, uint8_t *mailbox)
{
receiveMessageResponse(stack, destid, srcid, mailbox);
}
#else
void RIO_receiveMessageResponseError( RioStack_t *stack, uint16_t *srcid, uint8_t *mailbox)
{
receiveMessageResponse(stack, srcid, srcid, mailbox);
}
#endif
 
 
void RIO_portSetStatus( RioStack_t *stack, const uint8_t initialized)
{
/* REMARK: Clean the queues here as well??? */
if (initialized)
{
1744,20 → 649,9
}
 
 
void RIO_portSetTime( RioStack_t *stack, const uint32_t time)
{
stack->portTime = time;
}
 
 
void RIO_portSetTimeout( RioStack_t *stack, const uint32_t time)
void RIOSTACK_portAddSymbol(RioStack_t *stack, const RioSymbol_t s)
{
stack->portTimeout = time;
}
 
 
void RIO_portAddSymbol( RioStack_t *stack, const RioSymbol s)
{
uint8_t stype0;
uint8_t parameter0;
uint8_t parameter1;
1775,7 → 669,7
******************************************************************************/
/* Check the type of symbol. */
if(s.type == RIO_SYMBOL_TYPE_CONTROL)
if(s.type == RIOSTACK_SYMBOL_TYPE_CONTROL)
{
/* This is a control symbol. */
 
1807,7 → 701,6
/* Set the transmitter in its normal operational mode. */
stack->rxState = RX_STATE_LINK_INITIALIZED;
stack->rxCounter = 0u;
DEBUG_STATE("rx:normal");
}
else
{
1846,7 → 739,7
/* Check the type of symbol. */
switch(s.type)
{
case RIO_SYMBOL_TYPE_CONTROL:
case RIOSTACK_SYMBOL_TYPE_CONTROL:
/**************************************************************************
* This is a control symbol.
**************************************************************************/
1955,17 → 848,16
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_DATA:
case RIOSTACK_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))
if ((stack->rxCounter >= 1u) && (stack->rxCounter <= RIOPACKET_SIZE_MAX))
{
/* A packet has been started. */
 
1981,13 → 873,13
/* 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 = Crc32(s.data & (uint32_t)0x03fffffful, 0xffffu);
stack->rxCrc = RIOPACKET_Crc32(s.data & (uint32_t)0x03fffffful, 0xffffu);
}
else
{
/* This is not the first symbol. */
/* Continue to calculate the CRC of the packet. */
stack->rxCrc = Crc32(s.data, stack->rxCrc);
stack->rxCrc = RIOPACKET_Crc32(s.data, stack->rxCrc);
}
 
/* Save the new data in the packet queue and update the reception counter. */
1996,8 → 888,6
}
else
{
DEBUG_FRAMING_RX("error=%u %u", stack->rxAckId, s.data>>27);
 
/* The ackId is not correct. */
/* Packet error. Enter input-error-stopped state. */
stack->txState = TX_STATE_SEND_PACKET_NOT_ACCEPTED;
2004,7 → 894,6
stack->rxState = RX_STATE_INPUT_ERROR_STOPPED;
stack->rxErrorCause = PACKET_NOT_ACCEPTED_CAUSE_UNEXPECTED_ACKID;
stack->statusInboundErrorPacketAckId++;
DEBUG_STATE("rx:error-stopped");
}
}
else
2015,11 → 904,10
stack->rxState = RX_STATE_INPUT_ERROR_STOPPED;
stack->rxErrorCause = PACKET_NOT_ACCEPTED_CAUSE_GENERAL;
stack->statusInboundErrorGeneral++;
DEBUG_STATE("rx:error-stopped");
}
break;
 
case RIO_SYMBOL_TYPE_ERROR:
case RIOSTACK_SYMBOL_TYPE_ERROR:
/**************************************************************************
* The decoder has received a erronous symbol.
**************************************************************************/
2029,10 → 917,9
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_IDLE:
case RIOSTACK_SYMBOL_TYPE_IDLE:
default:
/**************************************************************************
* Idle symbol or unsupported symbol.
2057,7 → 944,7
/* Check the type of symbol. */
switch(s.type)
{
case RIO_SYMBOL_TYPE_CONTROL:
case RIOSTACK_SYMBOL_TYPE_CONTROL:
/* This is a control symbol. */
 
/* Check if the CRC is correct. */
2129,7 → 1016,6
/* 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:
2136,7 → 1022,6
/* 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:
2160,21 → 1045,19
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:
case RIOSTACK_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:
case RIOSTACK_SYMBOL_TYPE_DATA:
case RIOSTACK_SYMBOL_TYPE_IDLE:
default:
/* Data or idle symbol. */
/* Discard these in this state. */
2196,7 → 1079,7
/* Check the type of symbol. */
switch(s.type)
{
case RIO_SYMBOL_TYPE_CONTROL:
case RIOSTACK_SYMBOL_TYPE_CONTROL:
/* This is a control symbol. */
 
/* Check if the CRC is correct. */
2274,7 → 1157,6
/* 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:
2297,9 → 1179,9
}
break;
 
case RIO_SYMBOL_TYPE_DATA:
case RIO_SYMBOL_TYPE_IDLE:
case RIO_SYMBOL_TYPE_ERROR:
case RIOSTACK_SYMBOL_TYPE_DATA:
case RIOSTACK_SYMBOL_TYPE_IDLE:
case RIOSTACK_SYMBOL_TYPE_ERROR:
default:
/* Data, idle or error symbol. */
/* Discard these in this state. */
2320,9 → 1202,9
 
 
 
RioSymbol RIO_portGetSymbol( RioStack_t *stack )
RioSymbol_t RIOSTACK_portGetSymbol(RioStack_t *stack )
{
RioSymbol s;
RioSymbol_t s;
 
 
switch(stack->txState)
2365,7 → 1247,7
else
{
/* Idle symbol should be sent. */
s.type = RIO_SYMBOL_TYPE_IDLE;
s.type = RIOSTACK_SYMBOL_TYPE_IDLE;
stack->txCounter++;
}
 
2376,7 → 1258,6
stack->txState = TX_STATE_LINK_INITIALIZED;
stack->txFrameState = TX_FRAME_START;
stack->txStatusCounter = 0u;
DEBUG_STATE("tx:normal");
}
else
{
2410,12 → 1291,12
/* A packet transmission is ongoing. */
 
/* Check if the packet has been completly sent. */
if(stack->txCounter != QueueGetFrontSize(stack->txQueue))
if(stack->txCounter != QueueGetSize(stack->txQueue))
{
/* The packet has not been completly sent. */
 
/* Create a new data symbol to transmit. */
s.type = RIO_SYMBOL_TYPE_DATA;
s.type = RIOSTACK_SYMBOL_TYPE_DATA;
s.data = QueueGetFrontContent(stack->txQueue, (uint32_t)stack->txCounter);
/* Check if this is the first symbol in a packet. */
2451,7 → 1332,6
(((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);
2462,7 → 1342,6
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);
2486,7 → 1365,6
(((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);
2506,7 → 1384,7
/* Not required to send a status control symbol. */
 
/* Send an idle-symbol. */
s.type = RIO_SYMBOL_TYPE_IDLE;
s.type = RIOSTACK_SYMBOL_TYPE_IDLE;
stack->txStatusCounter++;
}
else
2527,7 → 1405,6
{
/* 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);
2541,7 → 1418,6
/* Go into the output error stopped state. */
stack->txState = TX_STATE_OUTPUT_ERROR_STOPPED;
stack->statusOutboundErrorTimeout++;
DEBUG_STATE("tx:error-stopped");
}
}
else
2618,8 → 1494,6
* 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
2674,7 → 1548,6
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;
2720,7 → 1593,7
 
/* A link-request-symbol has been transmitted. */
/* Send only idle-symbols until the link-response is received. */
s.type = RIO_SYMBOL_TYPE_IDLE;
s.type = RIOSTACK_SYMBOL_TYPE_IDLE;
}
else
{
2747,7 → 1620,7
/* 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;
s.type = RIOSTACK_SYMBOL_TYPE_IDLE;
ASSERT0("No link-response received, giving up.");
}
}
2761,7 → 1634,7
******************************************************************************/
 
/* Send only idle symbols. */
s.type = RIO_SYMBOL_TYPE_IDLE;
s.type = RIOSTACK_SYMBOL_TYPE_IDLE;
break;
}
 
2769,601 → 1642,12
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
* Local RapidIO stack helper functions.
*******************************************************************************/
 
 
static void handleStatus(RioStack_t *stack, const uint8_t ackId, const uint8_t bufferStatus)
{
/* Update the buffer status of the link partner. */
3372,13 → 1656,24
}
 
 
 
static void handlePacketAccepted(RioStack_t *stack, const uint8_t ackId, const uint8_t bufferStatus)
{
uint32_t linkLatency;
 
 
/* 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. */
 
/* 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)
{
stack->statusOutboundLinkLatencyMax = linkLatency;
}
 
/* Remove the packet from the outbound queue and restart the transmission for
a new packet. */
stack->txQueue = QueueDequeue(stack->txQueue);
3387,13 → 1682,11
}
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. */
3401,26 → 1694,23
}
 
 
 
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. */
3428,6 → 1718,7
}
 
 
 
static void handlePacketNotAccepted(RioStack_t *stack, const uint8_t arbitrary, const uint8_t cause)
{
(void) arbitrary;
3455,11 → 1746,10
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;
3471,8 → 1761,6
/* 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;
3482,7 → 1770,6
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)
3517,6 → 1804,7
}
 
 
 
static void handleStartOfPacket(RioStack_t *stack)
{
/* Check if a packet is already started. */
3524,7 → 1812,6
{
/* 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)
3548,7 → 1835,6
stack->rxState = RX_STATE_INPUT_ERROR_STOPPED;
stack->rxErrorCause = PACKET_NOT_ACCEPTED_CAUSE_GENERAL;
stack->statusInboundErrorGeneral++;
DEBUG_STATE("rx:error-stopped");
}
}
else
3559,22 → 1845,19
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)
{
3596,7 → 1879,6
stack->rxState = RX_STATE_INPUT_ERROR_STOPPED;
stack->rxErrorCause = PACKET_NOT_ACCEPTED_CAUSE_GENERAL;
stack->statusInboundErrorGeneral++;
DEBUG_STATE("rx:error-stopped");
}
}
else
3607,11 → 1889,11
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. */
3626,62 → 1908,26
{
/* 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
 
/* Make sure the CRC is reset to an invalid value to avoid a packet
accidentally being accepted. */
stack->rxCrc = 0xffff;
 
/* Reset the reception counter. */
stack->rxCounter = 0u;
 
3693,6 → 1939,7
}
 
 
 
static void handleLinkRequest(RioStack_t *stack, uint8_t cmd)
{
/* Check the command of the link-request. */
3724,1582 → 1971,15
}
 
 
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)
static RioSymbol_t CreateControlSymbol(const uint8_t stype0,
const uint8_t parameter0, const uint8_t parameter1,
const uint8_t stype1, const uint8_t cmd)
{
uint32_t *packet;
RioSymbol_t s;
 
s.type = RIOSTACK_SYMBOL_TYPE_CONTROL;
 
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;
 
 
switch(size/8)
{
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
{
/* Not supported by protocol. */
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;
5311,7 → 1991,8
}
 
 
static uint8_t Crc5( const uint32_t data, const uint8_t crc)
 
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,
5337,69 → 2018,12
}
 
 
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
};
/*******************************************************************************************
* Internal queue functions.
*******************************************************************************************/
 
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)
static Queue_t QueueCreate(const uint8_t size, uint32_t *buffer)
{
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;
5414,25 → 2038,29
}
 
 
static uint8_t QueueAvailable( const Queue_t q)
 
static uint8_t QueueAvailable(const Queue_t q)
{
return q.available;
}
 
 
static bool_t QueueEmpty( const Queue_t q)
 
static int QueueEmpty(const Queue_t q)
{
return (bool_t) (q.available == q.size);
return (q.available == q.size);
}
 
 
static uint8_t QueueLength( const Queue_t q)
 
static uint8_t QueueLength(const Queue_t q)
{
return q.size - q.available;
}
 
 
static Queue_t QueueEnqueue( Queue_t q)
 
static Queue_t QueueEnqueue(Queue_t q)
{
q.backIndex++;
if(q.backIndex == q.size)
5444,7 → 2072,8
}
 
 
static Queue_t QueueDequeue( Queue_t q)
 
static Queue_t QueueDequeue(Queue_t q)
{
q.frontIndex++;
if(q.frontIndex == q.size)
5464,12 → 2093,14
}
 
 
static bool_t QueueWindowEmpty( const Queue_t q)
 
static int QueueWindowEmpty(const Queue_t q)
{
return (bool_t) ((q.available + q.windowSize) == q.size);
return ((q.available + q.windowSize) == q.size);
}
 
 
 
static Queue_t QueueWindowReset(Queue_t q)
{
q.windowIndex = q.frontIndex;
5478,6 → 2109,7
}
 
 
 
static Queue_t QueueWindowNext(Queue_t q)
{
q.windowIndex++;
5490,2736 → 2122,45
}
 
 
static void QueueSetSize( Queue_t q, const uint32_t size)
{
(q.buffer_p+(RIO_BUFFER_SIZE*q.backIndex))[0] = size;
}
 
 
static void QueueSetContent( Queue_t q, const uint32_t index, const uint32_t content)
static void QueueSetSize(Queue_t q, const uint32_t size)
{
(q.buffer_p+(RIO_BUFFER_SIZE*q.backIndex))[index+1ul] = content;
(q.buffer_p+(RIOSTACK_BUFFER_SIZE*q.backIndex))[0] = size;
}
 
 
static uint32_t QueueGetFrontSize( Queue_t q)
{
return (q.buffer_p+(RIO_BUFFER_SIZE*q.windowIndex))[0];
}
 
 
static uint32_t QueueGetFrontContent( const Queue_t q, const uint32_t index)
static void QueueSetContent(Queue_t q, const uint32_t index, const uint32_t content)
{
return (q.buffer_p+(RIO_BUFFER_SIZE*q.windowIndex))[index+1ul];
(q.buffer_p+(RIOSTACK_BUFFER_SIZE*q.backIndex))[index+1ul] = content;
}
 
 
static uint32_t *QueueGetFrontBuffer( const Queue_t q )
{
return &((q.buffer_p+(RIO_BUFFER_SIZE*q.windowIndex))[1]);
}
 
 
static uint32_t QueueGetBackSize( const Queue_t q)
static uint32_t QueueGetSize(Queue_t q)
{
return (q.buffer_p+(RIO_BUFFER_SIZE*q.backIndex))[0];
return (q.buffer_p+(RIOSTACK_BUFFER_SIZE*q.windowIndex))[0];
}
 
 
static uint32_t *QueueGetBackBuffer( const Queue_t q )
{
return &((q.buffer_p+(RIO_BUFFER_SIZE*q.backIndex))[1]);
}
 
 
#ifdef MODULE_TEST
#include <stdio.h>
#define PrintS(s) \
{ \
FILE *fd; \
fd=fopen("testspec.txt", "a"); \
fputs(s "\n", fd); \
fclose(fd); \
}
 
#define TESTSTART(s) printf(s)
#define TESTEND printf(" passed.\n");
 
#define TESTCOND(got) \
if (!(got)) \
{ \
printf("ERROR at line %u:%s=%u (0x%08x)\n", \
__LINE__, #got, (got), (got)); \
exit(1); \
}
 
#define TESTEXPR(got, expected) \
if ((got)!=(expected)) \
{ \
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 uint32_t QueueGetFrontContent(const Queue_t q, const uint32_t index)
{
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",
line, CRC5_GET((got).data), CRC5_GET((expected).data));
}
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",
line, expression, (got).data, (got).data, (expected).data, (expected).data);
exit(1);
}
break;
}
}
else
{
printf("ERROR at line %u:%s=%u (0x%08x) expected=%u (0x%08x)\n",
line, expression, (got).type, (got).type, (expected).type, (expected).type);
exit(1);
}
return (q.buffer_p+(RIOSTACK_BUFFER_SIZE*q.windowIndex))[index+1ul];
}
 
 
 
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 uint32_t *QueueGetFrontBuffer(const Queue_t q )
{
uint16_t crc;
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;
 
return &((q.buffer_p+(RIOSTACK_BUFFER_SIZE*q.windowIndex))[1]);
}
 
uint32_t testConfigRead(RioStack_t *stack, uint32_t offset)
{
switch(offset)
{
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)
{
switch(offset)
{
case 8:
testConfigWriteData = data;
break;
default:
/* Dont do anything. */
break;
}
}
 
/*******************************************************************************
* Module test for this file.
*******************************************************************************/
int32_t main(void)
static uint32_t *QueueGetBackBuffer(const Queue_t q )
{
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. */
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);
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, 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));
 
/* Receive transmitted packet. */
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);
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);
d.type = RIO_SYMBOL_TYPE_DATA;
d.data = packet[i];
TESTEXPR(s.type, d.type);
TESTEXPR(s.data, d.data);
}
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);
d.type = RIO_SYMBOL_TYPE_DATA;
d.data = packet[i];
TESTEXPR(s.type, d.type);
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);
d.type = RIO_SYMBOL_TYPE_DATA;
d.data = packet[i];
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);
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, 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);
d.type = RIO_SYMBOL_TYPE_DATA;
d.data = packet[i];
TESTEXPR(s.type, d.type);
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);
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);
 
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. */
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);
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);
d.type = RIO_SYMBOL_TYPE_DATA;
d.data = packet[i];
TESTEXPR(s.type, d.type);
TESTEXPR(s.data, d.data);
}
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);
d.type = RIO_SYMBOL_TYPE_DATA;
d.data = packet[i];
TESTEXPR(s.type, d.type);
TESTEXPR(s.data, d.data);
}
 
/* Acknowledge. */
RIO_portAddSymbol(&stack, CreateControlSymbol(STYPE0_PACKET_ACCEPTED, 10, 1, STYPE1_NOP, 0));
RIO_portAddSymbol(&stack, CreateControlSymbol(STYPE0_PACKET_ACCEPTED, 11, 1, STYPE1_NOP, 0));
 
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);
d.type = RIO_SYMBOL_TYPE_DATA;
d.data = packet[i];
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);
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);
}
 
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);
d.type = RIO_SYMBOL_TYPE_DATA;
d.data = packet[i];
TESTEXPR(s.type, d.type);
TESTEXPR(s.data, d.data);
}
 
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);
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);
}
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. */
RIO_sendMaintenanceWriteRequest(&stack, 0xffff, 12, 0, 0x00000060, 0xdead);
while(RIO_eventPoll(&stack) != RIO_EVENT_MAINT_WRITE_RESPONSE)
{
s = RIO_portGetSymbol(&stack);
RIO_portAddSymbol(&stack, s);
}
 
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);
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)
{
s = RIO_portGetSymbol(&stack);
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)
{
s = RIO_portGetSymbol(&stack);
RIO_portAddSymbol(&stack, s);
}
 
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);
RIO_portAddSymbol(&stack, s);
}
 
RIO_receiveMaintenanceWriteResponse(&stack, &srcid, &tid, &hop);
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);
RIO_portAddSymbol(&stack, s);
}
 
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++)
{
RIO_sendNread(&stack, 0x0060, j, 0xaaaaaaaa+j, 1);
while(RIO_eventPoll(&stack) != RIO_EVENT_NREAD)
{
s = RIO_portGetSymbol(&stack);
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);
}
 
/******************************************************************************/
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);
RIO_portAddSymbol(&stack, s);
}
 
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)
{
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-k)*j);
TESTEXPR(length, k);
RIO_packetRemove(&stack);
}
}
 
/******************************************************************************/
TESTEND;
/******************************************************************************/
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++)
{
RIO_sendNread(&stack, 0x0060, j, 0x00000008+8*j, 8*j+8);
while(RIO_eventPoll(&stack) != RIO_EVENT_NREAD)
{
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++)
{
RIO_sendNread(&stack, 0x0060, j, 0x00000008+8*j, 32*j+32);
while(RIO_eventPoll(&stack) != RIO_EVENT_NREAD)
{
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, 32*j+32);
RIO_packetRemove(&stack);
}
 
/* 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++)
{
payload8[i] = i+j+1;
payload8Expected[i] = 0;
}
RIO_sendNwrite(&stack, 0x0060, 0xaaaaaaaa+j, 1, payload8);
while(RIO_eventPoll(&stack) != RIO_EVENT_NWRITE)
{
s = RIO_portGetSymbol(&stack);
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++)
{
TESTEXPR(payload8Expected[i], i+j+1);
}
RIO_packetRemove(&stack);
}
 
/******************************************************************************/
TESTEND;
/******************************************************************************/
PrintS("----------------------------------------------------------------------");
PrintS("Step 2:");
PrintS("Action: Send two bytes 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-Step2");
/******************************************************************************/
 
for(j = 0; j < 4; j++)
{
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)
{
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+2*j);
TESTEXPR(length, 2);
for(i = 0; i < 2; i++)
{
TESTEXPR(payload8Expected[i], i+j);
}
 
RIO_packetRemove(&stack);
}
 
/******************************************************************************/
TESTEND;
/******************************************************************************/
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++)
{
for(j = 0; j < 2; j++)
{
for(i = 0; i < k; i++)
{
payload8[i] = i+j+1;
payload8Expected[i] = 0;
}
 
RIO_sendNwriteR(&stack, 0x0060, j, 0x00000008+(8-k)*j, k, payload8);
 
while(RIO_eventPoll(&stack) != RIO_EVENT_NWRITE_R)
{
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++)
{
TESTEXPR(payload8Expected[i], i+j+1);
}
 
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++)
{
for(i = 0; i < 8*j; i++)
{
payload8[i] = i+j+1;
payload8Expected[i] = 0;
}
 
RIO_sendNwriteR(&stack, 0x0060, j, 0x00000008+8*j, 8*j, payload8);
while(RIO_eventPoll(&stack) != RIO_EVENT_NWRITE_R)
{
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*j);
TESTEXPR(length, 8*j);
for(i = 0; i < 8*j; i++)
{
TESTEXPR(payload8Expected[i], (uint8_t) (i+j+1));
}
RIO_packetRemove(&stack);
}
 
/******************************************************************************/
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++)
{
for(i = 0; i < 1; i++)
{
payload8[i] = i+j+1;
payload8Expected[i] = 0;
}
 
RIO_sendResponseDonePayload(&stack, 0x0060, j, 0x00000008+j, 1, payload8);
while(RIO_eventPoll(&stack) != RIO_EVENT_RESPONSE_DONE_PAYLOAD)
{
s = RIO_portGetSymbol(&stack);
RIO_portAddSymbol(&stack, s);
}
 
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);
}
 
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)
{
s = RIO_portGetSymbol(&stack);
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)
{
s = RIO_portGetSymbol(&stack);
RIO_portAddSymbol(&stack, s);
}
 
RIO_receiveResponseDone(&stack, &srcid, &tid);
 
TESTEXPR(srcid, 0xdead);
TESTEXPR(tid, 16);
RIO_packetRemove(&stack);
 
/******************************************************************************/
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++)
{
payload8[i] = i+j+1;
payload8Expected[i] = 0;
}
 
RIO_sendMessage(&stack, 0x0060, k, j, payload8);
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++)
{
TESTEXPR(payload8Expected[i], (uint8_t) (i+j+1));
}
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)
{
s = RIO_portGetSymbol(&stack);
RIO_portAddSymbol(&stack, s);
}
 
RIO_receiveMessageResponseDone(&stack, &srcid, &mailbox);
 
TESTEXPR(srcid, 0xdead);
TESTEXPR(mailbox, i);
RIO_packetRemove(&stack);
}
 
/******************************************************************************/
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)
{
s = RIO_portGetSymbol(&stack);
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);
RIO_packetSet(&stack, packetLength, packet);
 
while(RIO_eventPoll(&stack) != RIO_EVENT_DOORBELL)
{
s = RIO_portGetSymbol(&stack);
RIO_portAddSymbol(&stack, s);
}
 
TESTEXPR(srcid, 0xdead);
TESTEXPR(tid, 1);
TESTEXPR(info, 0xca1e);
RIO_packetRemove(&stack);
 
/******************************************************************************/
TESTEND;
/******************************************************************************/
 
return 0;
return &((q.buffer_p+(RIOSTACK_BUFFER_SIZE*q.backIndex))[1]);
}
#endif
/*************************** end of file **************************************/
/rio/trunk/sw/stack/test_riopacket.c
0,0 → 1,349
/*******************************************************************************
*
* RapidIO IP Library Core
*
* This file is part of the RapidIO IP library project
* http://www.opencores.org/cores/rio/
*
* Description:
* This file contains automatic regression tests for riopacket. Compile and
* run it by using:
* gcc -o testriopacket test_riopacket.c -fprofile-arcs -ftest-coverage
* ./testriopacket
* gcov test_riopacket.c
*
* To Do:
* -
*
* Author(s):
* - Magnus Rosenius, magro732@opencores.org
*
*******************************************************************************
*
* Copyright (C) 2015 Authors and OPENCORES.ORG
*
* This source file may be used and distributed without
* restriction provided that this copyright statement is not
* removed from the file and that any derivative work contains
* the original copyright notice and the associated disclaimer.
*
* This source file is free software; you can redistribute it
* and/or modify it under the terms of the GNU Lesser General
* Public License as published by the Free Software Foundation;
* either version 2.1 of the License, or (at your option) any
* later version.
*
* This source is distributed in the hope that it will be
* useful, but WITHOUT ANY WARRANTY; without even the implied
* warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
* PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General
* Public License along with this source; if not, download it
* from http://www.opencores.org/lgpl.shtml
*
*******************************************************************************/
#include <stdio.h>
#include <stdlib.h>
 
#define MODULE_TEST
#include "riopacket.c"
 
#define PrintS(s) \
{ \
FILE *fd; \
fd=fopen("testspec.txt", "a"); \
fputs(s "\n", fd); \
fclose(fd); \
}
 
#define TESTSTART(s) printf(s)
#define TESTEND printf(" passed.\n");
 
#define TESTCOND(got) \
if (!(got)) \
{ \
printf("\nERROR at line %u:%s=%u (0x%08x)\n", \
__LINE__, #got, (got), (got)); \
exit(1); \
}
 
#define TESTEXPR(got, expected) \
if ((got)!=(expected)) \
{ \
printf("\nERROR at line %u:%s=%u (0x%08x) expected=%u (0x%08x)\n", \
__LINE__, #got, (got), (got), (expected), (expected)); \
exit(1); \
}
 
#define TESTPACKET(got, expected) testSymbol(__LINE__, #got, (got), (expected))
 
void testPacket(uint32_t line, char *expression, RioPacket_t got, RioPacket_t expected)
{
int i;
 
 
if ((got).size==(expected).size)
{
for(i = 0; i < got.size; i++)
{
if(got.payload[i] != expected.payload[i])
{
printf("\nERROR at line %u:%s:payload[%u]:=%u (0x%08x) expected=%u (0x%08x)\n",
line, expression, i, (got).payload[i], (got).payload[i], (expected).payload[i], (expected).payload[i]);
exit(1);
}
}
}
else
{
printf("\nERROR at line %u:%s:size=%u (0x%08x) expected=%u (0x%08x)\n",
line, expression, (got).size, (got).size, (expected).size, (expected).size);
exit(1);
}
}
 
void packetClear(RioPacket_t *packet)
{
uint32_t i;
 
for(i = 0; i < RIOPACKET_SIZE_MAX; i++)
{
packet->payload[i] = 0xdeadbeef;
}
}
 
/*******************************************************************************
* Module test for this file.
*******************************************************************************/
int32_t main(void)
{
RioPacket_t packet;
int i, j, k;
uint16_t length;
uint16_t dstidExpected, dstid;
uint16_t srcidExpected, srcid;
uint8_t tidExpected, tid;
uint8_t hopExpected, hop;
uint8_t mailboxExpected, mailbox;
uint16_t infoExpected, info;
uint32_t addressExpected, address;
uint32_t dataExpected, data;
 
uint16_t payloadSizeExpected, payloadSize;
uint8_t payloadExpected[256], payload[256];
 
uint8_t buffer[512];
uint16_t bufferSize;
 
srand(0);
 
/******************************************************************************/
PrintS("----------------------------------------------------------------------");
PrintS("TG_riopacket-TC1");
PrintS("Description: Test packet initialization, validation and appending.");
PrintS("Requirement: XXXXX");
PrintS("----------------------------------------------------------------------");
PrintS("Step 1:");
PrintS("Action: ");
PrintS("Result: ");
PrintS("----------------------------------------------------------------------");
/******************************************************************************/
TESTSTART("TG_riostack-TC1-Step1");
/******************************************************************************/
 
RIOPACKET_init(&packet);
 
TESTEXPR(RIOPACKET_size(&packet), 0);
TESTCOND(!RIOPACKET_valid(&packet));
 
RIOPACKET_append(&packet, 0x001a0001);
 
TESTEXPR(RIOPACKET_size(&packet), 1);
TESTCOND(!RIOPACKET_valid(&packet));
 
RIOPACKET_append(&packet, 0xffff0000);
 
TESTEXPR(RIOPACKET_size(&packet), 2);
TESTCOND(!RIOPACKET_valid(&packet));
 
RIOPACKET_append(&packet, 0xdeaf9903);
 
TESTEXPR(RIOPACKET_size(&packet), 3);
TESTCOND(RIOPACKET_valid(&packet));
 
/* Check that altering the ackid does not affect the validity of the packet. */
packet.payload[0] |= 0xfc000000;
TESTCOND(RIOPACKET_valid(&packet));
 
/* Access the packet and check its content. */
TESTEXPR(RIOPACKET_getFtype(&packet), RIOPACKET_FTYPE_DOORBELL);
TESTEXPR(RIOPACKET_getDestination(&packet), 0x0001);
TESTEXPR(RIOPACKET_getSource(&packet), 0xffff);
TESTEXPR(RIOPACKET_getTid(&packet), 0x00);
RIOPACKET_getDoorbell(&packet, &dstid, &srcid, &tid, &info);
TESTEXPR(dstid, 0x0001);
TESTEXPR(srcid, 0xffff);
TESTEXPR(tid, 0x00);
TESTEXPR(info, 0xdeaf);
 
bufferSize = RIOPACKET_serialize(&packet, sizeof(buffer), buffer);
TESTEXPR(bufferSize, 13);
TESTEXPR(buffer[0], 0x03);
TESTEXPR(buffer[1], 0xfc);
TESTEXPR(buffer[2], 0x1a);
TESTEXPR(buffer[3], 0x00);
TESTEXPR(buffer[4], 0x01);
TESTEXPR(buffer[5], 0xff);
TESTEXPR(buffer[6], 0xff);
TESTEXPR(buffer[7], 0x00);
TESTEXPR(buffer[8], 0x00);
TESTEXPR(buffer[9], 0xde);
TESTEXPR(buffer[10], 0xaf);
TESTEXPR(buffer[11], 0x99);
TESTEXPR(buffer[12], 0x03);
 
RIOPACKET_init(&packet);
RIOPACKET_deserialize(&packet, bufferSize, buffer);
TESTCOND(RIOPACKET_valid(&packet));
TESTEXPR(RIOPACKET_getFtype(&packet), RIOPACKET_FTYPE_DOORBELL);
TESTEXPR(RIOPACKET_getDestination(&packet), 0x0001);
TESTEXPR(RIOPACKET_getSource(&packet), 0xffff);
TESTEXPR(RIOPACKET_getTid(&packet), 0x00);
RIOPACKET_getDoorbell(&packet, &dstid, &srcid, &tid, &info);
TESTEXPR(dstid, 0x0001);
TESTEXPR(srcid, 0xffff);
TESTEXPR(tid, 0x00);
TESTEXPR(info, 0xdeaf);
 
/******************************************************************************/
TESTEND;
/******************************************************************************/
/******************************************************************************/
PrintS("----------------------------------------------------------------------");
PrintS("TG_riopacket-TC2");
PrintS("Description: Test maintenance packets.");
PrintS("Requirement: XXXXX");
PrintS("----------------------------------------------------------------------");
PrintS("Step 1:");
PrintS("Action: ");
PrintS("Result: ");
PrintS("----------------------------------------------------------------------");
/******************************************************************************/
TESTSTART("TG_riostack-TC2-Step1");
/******************************************************************************/
 
RIOPACKET_init(&packet);
RIOPACKET_setMaintReadRequest(&packet, 0xc0de, 0xbabe, 0x13, 0x41, 0xffffffff);
RIOPACKET_getMaintReadRequest(&packet, &dstid, &srcid, &hop, &tid, &address);
 
TESTCOND(RIOPACKET_valid(&packet));
TESTEXPR(dstid, 0xc0de);
TESTEXPR(srcid, 0xbabe);
TESTEXPR(hop, 0x13);
TESTEXPR(tid, 0x41);
TESTEXPR(address, 0x00fffffc);
/******************************************************************************/
TESTEND;
/******************************************************************************/
/******************************************************************************/
PrintS("----------------------------------------------------------------------");
PrintS("TG_riopacket-TC3");
PrintS("Description: Test input/output packets.");
PrintS("Requirement: XXXXX");
PrintS("----------------------------------------------------------------------");
PrintS("Step 1:");
PrintS("Action: ");
PrintS("Result: ");
PrintS("----------------------------------------------------------------------");
/******************************************************************************/
TESTSTART("TG_riostack-TC3-Step1");
/******************************************************************************/
 
 
/******************************************************************************/
TESTEND;
/******************************************************************************/
/******************************************************************************/
PrintS("----------------------------------------------------------------------");
PrintS("TG_riopacket-TC4");
PrintS("Description: Test message passing packets.");
PrintS("Requirement: XXXXX");
PrintS("----------------------------------------------------------------------");
PrintS("Step 1:");
PrintS("Action: Send a message with invalid payload length.");
PrintS("Result: No packet should be generated.");
PrintS("----------------------------------------------------------------------");
/******************************************************************************/
TESTSTART("TG_riostack-TC4-Step1");
/******************************************************************************/
 
RIOPACKET_setMessage(&packet, 0xdead, 0xbeef, 0xc0, 0, &payloadExpected[0]);
 
TESTEXPR(packet.size, 0);
TESTCOND(!RIOPACKET_valid(&packet));
 
RIOPACKET_setMessage(&packet, 0xdead, 0xbeef, 0xc0, 257, &payloadExpected[0]);
 
TESTEXPR(packet.size, 0);
TESTCOND(!RIOPACKET_valid(&packet));
 
/******************************************************************************/
TESTEND;
/******************************************************************************/
PrintS("----------------------------------------------------------------------");
PrintS("Step 2:");
PrintS("Action: Test sending all possible payload sizes on random deviceIds ");
PrintS(" and mailboxes.");
PrintS("Result: The content of the packet should be equal to what was entered.");
PrintS("----------------------------------------------------------------------");
/******************************************************************************/
TESTSTART("TG_riostack-TC4-Step2");
/******************************************************************************/
 
for(i = 1; i <= 256; i++)
{
dstidExpected = rand();
srcidExpected = rand();
mailboxExpected = rand();
 
if((i%8) == 0)
{
payloadSizeExpected = 8*(i/8);
}
else
{
payloadSizeExpected = 8*(i/8+1);
}
 
for(j = 0; j < i; j++)
{
payloadExpected[j] = rand();
}
RIOPACKET_setMessage(&packet, dstidExpected, srcidExpected, mailboxExpected,
i, &payloadExpected[0]);
TESTCOND(RIOPACKET_valid(&packet));
 
RIOPACKET_getMessage(&packet, &dstid, &srcid, &mailbox, &payloadSize, &(payload[0]));
TESTEXPR(dstid, dstidExpected);
TESTEXPR(srcid, srcidExpected);
TESTEXPR(mailbox, mailboxExpected);
TESTEXPR(payloadSize, payloadSizeExpected);
for(j = 0; j < i; j++)
{
TESTEXPR(payload[j], payloadExpected[j]);
}
}
 
/******************************************************************************/
TESTEND;
/******************************************************************************/
 
return 0;
}
 
/*************************** end of file **************************************/
/rio/trunk/sw/stack/riopacket.c
0,0 → 1,3123
/*******************************************************************************
*
* RapidIO IP Library Core
*
* This file is part of the RapidIO IP library project
* http://www.opencores.org/cores/rio/
*
* Description:
* This file contains an "object" that can create and parse RapidIO packets.
* It is used in the SW RapidIO stack, riostack.c, but can also be used
* stand-alone together with other software, for example to tunnel RapidIO
* packet over an arbitrary network.
* More details about the usage can be found in the module tests in
* test_riopacket.c.
*
* To Do:
* - Add packet handlers for 8-bit deviceIds.
*
* Author(s):
* - Magnus Rosenius, magro732@opencores.org
*
*******************************************************************************
*
* Copyright (C) 2015 Authors and OPENCORES.ORG
*
* This source file may be used and distributed without
* restriction provided that this copyright statement is not
* removed from the file and that any derivative work contains
* the original copyright notice and the associated disclaimer.
*
* This source file is free software; you can redistribute it
* and/or modify it under the terms of the GNU Lesser General
* Public License as published by the Free Software Foundation;
* either version 2.1 of the License, or (at your option) any
* later version.
*
* This source is distributed in the hope that it will be
* useful, but WITHOUT ANY WARRANTY; without even the implied
* warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
* PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General
* Public License along with this source; if not, download it
* from http://www.opencores.org/lgpl.shtml
*
*******************************************************************************/
/**
* \file riopacket.c
*/
 
/*******************************************************************************
* Includes
*******************************************************************************/
 
#include "riopacket.h"
 
/* Let lint report errors and warnings only. */
/*lint -w2 */
 
 
/*******************************************************************************
* Local macro definitions
*******************************************************************************/
 
/* Macros to get entries from a packet in a buffer. */
#define FTYPE_GET(p) (((p)[0] >> 16) & 0xf)
#define DESTID_GET(p) ((p)[0] & 0xffff)
#define SRCID_GET(p) (((p)[1] >> 16) & 0xffff)
#define TRANSACTION_GET(p) (((p)[1] >> 12) & 0xf)
#define MSGLEN_GET(p) TRANSACTION_GET(p)
#define SSIZE_GET(p) (((p)[1] >> 8) & 0xf)
#define LETTER_GET(p) (((p)[1] >> 6) & 0x3)
#define MBOX_GET(p) (((p)[1] >> 4) & 0x3)
#define MSGSEG_GET(p) ((p)[1] & 0xf)
#define XMBOX_GET(p) MSGSEG_GET(p)
#define RDSIZE_GET(p) SSIZE_GET(p)
#define WRSIZE_GET(p) SSIZE_GET(p)
#define STATUS_GET(p) SSIZE_GET(p)
#define TID_GET(p) ((p)[1] & 0xff)
#define HOP_GET(p) (((p)[2] >> 24) & 0xff)
#define CONFIG_OFFSET_GET(p) ((p)[2] & 0x00fffffcul)
#define INFO_GET(p) (((p)[2] >> 16) & 0xffff)
#define ADDRESS_GET(p) ((p)[2] & 0xfffffff8ul)
#define WDPTR_GET(p) (((p)[2] >> 2) & 0x1)
#define XAMBS_GET(p) ((p)[2] & 0x3)
#define DOUBLE_WORD_MSB_GET(p, i) (p)[3+(2*i+0)]
#define DOUBLE_WORD_LSB_GET(p, i) (p)[3+(2*i+1)]
 
 
 
/*******************************************************************************
* Local function prototypes
*******************************************************************************/
 
/* Functions to help get and set payload in the packets. */
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);
 
 
 
/*******************************************************************************
* Global function prototypes
*******************************************************************************/
 
/**
* \brief Initialize a packet to an empty packet.
*
* \param[in] packet The packet to operate on.
*
* This function sets the size of a packet to zero.
*
* \note Any previous content is NOT purged.
*/
void RIOPACKET_init(RioPacket_t *packet)
{
packet->size = 0;
}
 
 
/**
* \brief Return the size of a packet.
*
* \param[in] packet The packet to operate on.
* \return The size of the packet.
*
* This function gets the size of a packet in words (32-bit).
*/
uint8_t RIOPACKET_size(RioPacket_t *packet)
{
return packet->size;
}
 
 
/**
* \brief Append data to a packet.
*
* \param[in] packet The packet to operate on.
* \param[in] word The word to append.
*
* This function appends a specificed word (32-bit) to the end of a packet.
*/
void RIOPACKET_append(RioPacket_t *packet, uint32_t word)
{
if(packet->size < RIOPACKET_SIZE_MAX)
{
packet->payload[packet->size] = word;
packet->size++;
}
}
 
 
/**
* \brief Check if a packet is a valid RapidIO packet.
*
* \param[in] packet The packet to operate on.
* \return The return value is zero if not ok, non-zero otherwise.
*
* This function checks if a packet has a correct length and a correct CRC.
* Both the embedded crc and the trailing crc are checked.
*/
int RIOPACKET_valid(RioPacket_t *packet)
{
int returnValue;
uint32_t i;
uint16_t crc;
 
 
/* Check that the size of the packet is ok. */
if((packet->size >= RIOPACKET_SIZE_MIN) &&
(packet->size <= RIOPACKET_SIZE_MAX))
{
/* The packet has a valid length. */
 
/* Calculate CRC on the first word and disregard the ackId. */
crc = RIOPACKET_Crc32(packet->payload[0] & 0x03fffffful, 0xffffu);
 
/* Check if the packet contains an embedded crc. */
if(packet->size < 20)
{
/* The packet contains only one trailing crc. */
for(i = 1; i < packet->size; i++)
{
crc = RIOPACKET_Crc32(packet->payload[i], crc);
}
returnValue = (crc == 0x0000u);
}
else
{
/* The packet contains both a trailing and an embedded crc. */
 
/* Read payload to the embedded crc. Include the embedded crc in
the crc calculation.*/
for(i = 1; i < 20; i++)
{
crc = RIOPACKET_Crc32(packet->payload[i], crc);
}
 
/* Check the embedded crc. */
if(crc != ((uint16_t) (packet->payload[i] >> 16)))
{
/* The embedded crc is not ok. */
returnValue = 0;
}
else
{
/* Read the rest of the payload including the trailing crc. */
for(i = 20; i < packet->size; i++)
{
crc = RIOPACKET_Crc32(packet->payload[i], crc);
}
returnValue = (crc == 0x0000u);
}
}
}
else
{
/* The packet does not have a valid length. */
returnValue = 0;
}
 
return returnValue;
}
 
 
/**
* \brief Convert (serializes) a packet into an array of bytes.
*
* \param[in] packet The packet to operate on.
* \param[in] size The size of the buffer to write to.
* \param[out] buffer The address to write the result to.
* \return The number of bytes that were written. The value 0 will be returned if the
* serialized buffer does not fit into the provided buffer.
*
* This function serializes a packet into an array of bytes that can be transfered on
* a transmission channel.
*/
int RIOPACKET_serialize(RioPacket_t *packet, const uint16_t size, uint8_t *buffer)
{
int returnValue;
int i;
 
 
/* Check if the packet fits into the provided buffer. */
if(size >= ((4*packet->size)+1))
{
/* The packet fits. */
 
/* Write the size of the packet and the packet content itself to the buffer. */
buffer[0] = packet->size;
for(i = 0; i < packet->size; i++)
{
buffer[(4*i)+1] = (packet->payload[i] >> 24) & 0xff;
buffer[(4*i)+2] = (packet->payload[i] >> 16) & 0xff;
buffer[(4*i)+3] = (packet->payload[i] >> 8) & 0xff;
buffer[(4*i)+4] = (packet->payload[i] >> 0) & 0xff;
}
/* Write the number of bytes that were written. */
returnValue = (4*packet->size)+1;
}
else
{
/* The packet does not fit into the provided buffer. */
returnValue = 0;
}
 
return returnValue;
}
 
 
/**
* \brief Convert (deserializes) an array of bytes to a packet.
*
* \param[in] packet The packet to operate on.
* \param[in] size The size of the buffer to read from.
* \param[in] buffer The address to read from.
* \return The number of words contained in the resulting packet. The value 0 is
* returned if the deserialization was unsuccessfull.
*
* This function deserializes a packet from a byte array that was previously created
* by RIOPACKET_serialize().
*
* \note It is recommended to use RIOPACKET_valid() to verify the integrity of the packet
* once it has been deserialized.
*/
int RIOPACKET_deserialize(RioPacket_t *packet, const uint16_t size, const uint8_t *buffer)
{
int i;
uint32_t temp = 0;
 
 
/* Check if the buffer contains a valid packet length. */
if(((buffer[0] >= RIOPACKET_SIZE_MIN) &&
(buffer[0] <= RIOPACKET_SIZE_MAX)) &&
((4*buffer[0]+1) <= size))
{
/* The buffer contains a valid packet length. */
 
/* Read the size of the packet and the packet content itself from the buffer. */
packet->size = buffer[0];
for(i = 0; (i < 4*packet->size); i++)
{
temp <<= 8;
temp |= buffer[i+1];
if((i%4) == 3)
{
packet->payload[i/4] = temp;
}
}
}
else
{
/* The buffer does not contain a valid packet length. */
packet->size = 0;
}
 
return packet->size;
}
 
 
/**
* \brief Convert a packet into a printable buffer.
*
* \param[in] packet The packet to operate on.
* \param[in] buffer The address to write the string to.
*
* This function converts a packet into a human readable '\0'-terminated ASCII-format and
* write it to the argument buffer.
*
* \note The caller must guarantee that the destination buffer is large enough to contain
* the resulting string.
*/
#ifdef ENABLE_TOSTRING
#include <stdio.h>
void RIOPACKET_toString(RioPacket_t *packet, char *buffer)
{
uint8_t ftype;
uint8_t transaction;
uint16_t destId;
uint16_t srcId;
uint8_t tid;
 
 
ftype = RIOPACKET_getFtype(packet);
transaction = RIOPACKET_getTransaction(packet);
/* Check the message type and switch on it. */
switch(ftype)
{
case RIOPACKET_FTYPE_REQUEST:
/**************************************************************************************
* A REQUEST has been received.
**************************************************************************************/
{
uint32_t address;
uint16_t payloadSize;
 
 
if(transaction == RIOPACKET_TRANSACTION_REQUEST_NREAD)
{
RIOPACKET_getNread(packet, &destId, &srcId, &tid, &address, &payloadSize);
sprintf(buffer,
"NREAD: dstid=%04x srcid=%04x tid=%02x address=%08x payloadSize=%04x",
destId, srcId, tid, address, payloadSize);
}
else
{
sprintf(buffer, "UNKNOWN:ftype=%02x transaction=%02x", ftype, transaction);
}
}
break;
 
case RIOPACKET_FTYPE_WRITE:
/**************************************************************************************
* An WRITE has been received.
**************************************************************************************/
{
uint32_t address;
uint16_t payloadSize;
uint8_t payload[256];
uint32_t index;
uint32_t i;
 
 
if(transaction == RIOPACKET_TRANSACTION_WRITE_NWRITE)
{
RIOPACKET_getNwrite(packet, &destId, &srcId, &address, &payloadSize, payload);
 
index = sprintf(&buffer[0],
"NWRITE: dstid=%04x srcid=%04x address=%08x payloadSize=%04x",
destId, srcId, address, payloadSize);
for(i = 0; i < payloadSize; i++)
{
index += sprintf(&buffer[index], "%02x", payload[i]);
}
}
else if(transaction == RIOPACKET_TRANSACTION_WRITE_NWRITER)
{
RIOPACKET_getNwriteR(packet, &destId, &srcId, &tid, &address, &payloadSize, payload);
 
index = sprintf(&buffer[0],
"NWRITER: dstid=%04x srcid=%04x tid=%02x address=%08x payloadSize=%04x",
destId, srcId, tid, address, payloadSize);
for(i = 0; i < payloadSize; i++)
{
index += sprintf(&buffer[index], "%02x", payload[i]);
}
}
else
{
sprintf(buffer, "UNKNOWN:ftype=%02x transaction=%02x", ftype, transaction);
}
}
break;
 
case RIOPACKET_FTYPE_MAINTENANCE:
/**************************************************************************************
* A maintenance packet has been received.
**************************************************************************************/
{
uint8_t hop;
uint32_t offset;
uint32_t data;
 
 
/* Check the transaction to determine the type. */
if(transaction == RIOPACKET_TRANSACTION_MAINT_READ_REQUEST)
{
/* Maintenance read request. */
RIOPACKET_getMaintReadRequest(packet, &destId, &srcId, &hop, &tid, &offset);
sprintf(buffer,
"MAINTREADREQUEST: dstid=%04x srcid=%04x tid=%02x hop=%02x offset=%08x",
destId, srcId, tid, hop, offset);
}
else if(transaction == RIOPACKET_TRANSACTION_MAINT_WRITE_REQUEST)
{
/* Maintenance write request. */
RIOPACKET_getMaintWriteRequest(packet, &destId, &srcId, &hop, &tid, &offset, &data);
sprintf(buffer,
"MAINTWRITEREQUEST: dstid=%04x srcid=%04x tid=%02x hop=%02x offset=%08x data=%08x",
destId, srcId, tid, hop, offset, data);
}
else if(transaction == RIOPACKET_TRANSACTION_MAINT_READ_RESPONSE)
{
/* Maintenance read response. */
RIOPACKET_getMaintReadResponse(packet, &destId, &srcId, &tid, &data);
sprintf(buffer,
"MAINTREADRESPONSE: dstid=%04x srcid=%04x tid=%02x data=%08x",
destId, srcId, tid, data);
}
else if(transaction == RIOPACKET_TRANSACTION_MAINT_WRITE_RESPONSE)
{
/* Maintenance write repsonse. */
RIOPACKET_getMaintWriteResponse(packet, &destId, &srcId, &tid);
sprintf(buffer,
"MAINTWRITERESPONSE: dstid=%04x srcid=%04x tid=%02x",
destId, srcId, tid);
}
else if(transaction == RIOPACKET_TRANSACTION_MAINT_PORT_WRITE_REQUEST)
{
uint32_t componentTag;
uint32_t portErrorDetect;
uint32_t implementationSpecific;
uint8_t portId;
uint32_t logicalTransportErrorDetect;
/* Maintenance port write packet. */
RIOPACKET_getMaintPortWrite(packet, &destId, &srcId,
&componentTag, &portErrorDetect, &implementationSpecific,
&portId, &logicalTransportErrorDetect);
sprintf(buffer,
"MAINTPORTWRITE: dstid=%04x srcid=%04x componentTag=%08x portErrorDetect=%08x"
"implementationSpecific=%08x portId=%02x logicalTransportErrorDetect=%08x",
destId, srcId, componentTag, portErrorDetect, implementationSpecific, portId,
logicalTransportErrorDetect);
}
else
{
sprintf(buffer, "UNKNOWN:ftype=%02x transaction=%02x", ftype, transaction);
}
}
break;
 
case RIOPACKET_FTYPE_DOORBELL:
/**************************************************************************************
* A doorbell packet has been received.
**************************************************************************************/
{
uint16_t info;
 
 
RIOPACKET_getDoorbell(packet, &destId, &srcId, &tid, &info);
sprintf(buffer,
"DOORBELL: dstid=%04x srcid=%04x tid=%02x info=%04x",
destId, srcId, tid, info);
}
break;
 
case RIOPACKET_FTYPE_MESSAGE:
/**************************************************************************************
* A messaget has been received.
**************************************************************************************/
{
uint16_t payloadSize;
uint8_t payload[256];
uint32_t index;
uint32_t i;
 
 
RIOPACKET_getMessage(packet, &destId, &srcId, &tid, &payloadSize, payload);
 
index = sprintf(&buffer[0],
"MESSAGE: dstid=%04x srcid=%04x mailbox=%02x payloadSize=%04x",
destId, srcId, tid, payloadSize);
for(i = 0; i < payloadSize; i++)
{
index += sprintf(&buffer[index], "%02x", payload[i]);
}
}
break;
 
case RIOPACKET_FTYPE_RESPONSE:
/**************************************************************************************
* A response packet has been received.
**************************************************************************************/
{
uint8_t status;
uint16_t payloadSize;
uint8_t payload[256];
 
 
if(transaction == RIOPACKET_TRANSACTION_RESPONSE_NO_PAYLOAD)
{
RIOPACKET_getResponseNoPayload(packet, &destId, &srcId, &tid, &status);
sprintf(buffer,
"RESPONSENOPAYLOAD: dstid=%04x srcid=%04x tid=%02x status=%02x",
destId, srcId, tid, status);
}
else if(transaction == RIOPACKET_TRANSACTION_RESPONSE_MESSAGE_RESPONSE)
{
RIOPACKET_getResponseMessage(packet, &destId, &srcId, &tid, &status);
sprintf(buffer,
"RESPONSEMESSAGE: dstid=%04x srcid=%04x mailbox=%02x status=%02x",
destId, srcId, tid, status);
}
else if(transaction == RIOPACKET_TRANSACTION_RESPONSE_WITH_PAYLOAD)
{
uint32_t i;
uint32_t index;
 
 
RIOPACKET_getResponseWithPayload(packet, &destId, &srcId, &tid, 0, &payloadSize, payload);
 
index = sprintf(&buffer[0],
"RESPONSEWITHPAYLOAD: dstid=%04x srcid=%04x tid=%02x payloadSize=%04x ",
destId, srcId, tid, payloadSize);
for(i = 0; i < payloadSize; i++)
{
index += sprintf(&buffer[index], "%02x", payload[i]);
}
}
else
{
sprintf(buffer, "UNKNOWN:ftype=%02x transaction=%02x", ftype, transaction);
}
}
break;
 
default:
/**************************************************************************************
* Unsupported ftype.
**************************************************************************************/
sprintf(buffer, "UNKNOWN:ftype=%02x transaction=%02x", ftype, transaction);
break;
}
 
return;
}
#endif
 
 
/**
* \brief Return the ftype of a packet.
*
* \param[in] packet The packet to operate on.
* \return The ftype of the packet.
*
* This function gets the ftype of a packet.
*/
uint8_t RIOPACKET_getFtype(RioPacket_t *packet)
{
return FTYPE_GET(packet->payload);
}
 
 
/**
* \brief Return the destination deviceId of a packet.
*
* \param[in] packet The packet to operate on.
* \return The destination deviceId of the packet.
*
* This function gets the destination deviceId of a packet.
*/
uint16_t RIOPACKET_getDestination(RioPacket_t *packet)
{
return DESTID_GET(packet->payload);
}
 
 
/**
* \brief Return the source deviceId of a packet.
*
* \param[in] packet The packet to operate on.
* \return The source deviceId of the packet.
*
* This function gets the source deviceId of a packet.
*/
uint16_t RIOPACKET_getSource(RioPacket_t *packet)
{
return SRCID_GET(packet->payload);
}
 
 
/**
* \brief Return the transaction of a packet.
*
* \param[in] packet The packet to operate on.
* \return The transaction of the packet.
*
* This function gets the transaction field of a packet.
*
* \note Not all packets contain a transaction field.
*/
uint8_t RIOPACKET_getTransaction(RioPacket_t *packet)
{
return TRANSACTION_GET(packet->payload);
}
 
 
/**
* \brief Return the transaction identifier of a packet.
*
* \param[in] packet The packet to operate on.
* \return The transaction identifier of the packet.
*
* This function gets the transaction identifier field of a packet.
*
* \note Not all packets contain a transaction identifier field.
*/
uint8_t RIOPACKET_getTid(RioPacket_t *packet)
{
return TID_GET(packet->payload);
}
 
 
/*******************************************************************************************
* Logical I/O MAINTENANCE-READ functions.
*******************************************************************************************/
 
/**
* \brief Set the packet to contain a maintenance read request.
*
* \param[in] packet The packet to operate on.
* \param[in] destId The deviceId to use as destination in the packet.
* \param[in] srcId The deviceId to use as source in the packet.
* \param[in] hop The hop_count to set in the packet.
* \param[in] tid The transaction identifier to set in the packet.
* \param[in] offset The byte address in the configuration space to read.
*
* This function sets the content of a packet to a maintenance read request packet containing
* a request to read one word in configuration space.
*
*/
void RIOPACKET_setMaintReadRequest(RioPacket_t *packet,
uint16_t destId, uint16_t srcId, uint8_t hop,
uint8_t tid, uint32_t offset)
{
uint32_t content;
uint16_t crc = 0xffffu;
 
 
/* 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 but must be set to zero. */
content = 0x00180000ul;
content |= (uint32_t) destId;
crc = RIOPACKET_Crc32(content, crc);
packet->payload[0] = content;
 
/* sourceId(15:0)|transaction(3:0)|rdsize(3:0)|srcTID(7:0) */
content = ((uint32_t) srcId) << 16;
content |= (uint32_t) RIOPACKET_TRANSACTION_MAINT_READ_REQUEST << 12;
content |= (uint32_t) 8ul << 8;
content |= (uint32_t) tid;
crc = RIOPACKET_Crc32(content, crc);
packet->payload[1] = content;
 
/* hopcount(7:0)|configOffset(20:0)|wdptr|reserved(1:0) */
content = ((uint32_t) hop) << 24;
content |= offset & 0x00fffffcul;
crc = RIOPACKET_Crc32(content, crc);
packet->payload[2] = content;
 
/* crc(15:0)|pad(15:0) */
content = ((uint32_t) crc) << 16;
packet->payload[3] = content;
 
/* Set the size of the packet. */
packet->size = 4;
}
 
 
/**
* \brief Get entries from a maintenance read request.
*
* \param[in] packet The packet to operate on.
* \param[out] destId The destination deviceId in this packet.
* \param[out] srcId The source deviceId in this packet.
* \param[out] hop The hop_count in this packet.
* \param[out] tid The transaction id to be returned in the response to this request.
* \param[out] offset The byte address in the configuration space to read.
*
* This function returns the content of a packet as if it contained a maintenance read
* request packet.
*
* \note Use the ftype and transaction fields to see if the packet is indeed a
* maintenance read request.
* \note If the packet does not contain a maintenance read request, the result
* will be undefined.
*/
void RIOPACKET_getMaintReadRequest(RioPacket_t *packet,
uint16_t *destId, uint16_t *srcId, uint8_t *hop,
uint8_t *tid, uint32_t *offset)
{
*destId = DESTID_GET(packet->payload);
*srcId = SRCID_GET(packet->payload);
*tid = TID_GET(packet->payload);
*hop = HOP_GET(packet->payload);
*offset = CONFIG_OFFSET_GET(packet->payload);
}
 
 
/**
* \brief Set the packet to contain a maintenance read response.
*
* \param[in] packet The packet to operate on.
* \param[in] destId The deviceId to use as destination in the packet.
* \param[in] srcId The deviceId to use as source in the packet.
* \param[in] tid The transaction identifier to set in the packet.
* \param[in] data The data to send in the packet.
*
* This function sets the content of a packet to a maintanance read response packet
* containing a response to a request reading one word in configuration space.
*/
void RIOPACKET_setMaintReadResponse(RioPacket_t *packet,
uint16_t destId, uint16_t srcId,
uint8_t tid, uint32_t data)
{
uint32_t content;
uint16_t crc = 0xffffu;
 
 
/* 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 = 0x00180000ul;
content |= (uint32_t) destId;
crc = RIOPACKET_Crc32(content, crc);
packet->payload[0] = content;
 
/* sourceId(15:0)|transaction(3:0)|status(3:0)|srcTID(7:0) */
content = (uint32_t) srcId << 16;
content |= (uint32_t) RIOPACKET_TRANSACTION_MAINT_READ_RESPONSE << 12;
content |= (uint32_t) RIOPACKET_RESPONSE_STATUS_DONE << 8;
content |= (uint32_t) tid;
crc = RIOPACKET_Crc32(content, crc);
packet->payload[1] = content;
 
/* hopcount(7:0)|reserved(23:0) */
/* HopCount should always be set to 0xff in responses. */
content = 0xff000000ul;
crc = RIOPACKET_Crc32(content, crc);
packet->payload[2] = 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 = RIOPACKET_Crc32(content, crc);
packet->payload[3] = content;
content = data;
crc = RIOPACKET_Crc32(content, crc);
packet->payload[4] = content;
 
/* crc(15:0)|pad(15:0) */
content = ((uint32_t) crc) << 16;
packet->payload[5] = content;
 
/* Set the size of the packet. */
packet->size = 6;
}
 
 
/**
* \brief Get entries from a maintenance read response.
*
* \param[in] packet The packet to operate on.
* \param[out] destId The destination deviceId in this packet.
* \param[out] srcId The source deviceId in this packet.
* \param[out] tid The transaction identifier in the response.
* \param[out] data The data in the response.
*
* This function returns the content of a packet as if it contained a maintenance
* read response packet.
*
* \note Use the ftype and transaction fields to see if the packet is indeed a
* maintenance read response.
* \note If the packet does not contain a maintenance read response, the result
* will be undefined.
*/
void RIOPACKET_getMaintReadResponse(RioPacket_t *packet,
uint16_t *destId, uint16_t *srcId,
uint8_t *tid, uint32_t *data)
{
*destId = DESTID_GET(packet->payload);
*srcId = SRCID_GET(packet->payload);
*tid = TID_GET(packet->payload);
*data = DOUBLE_WORD_MSB_GET(packet->payload, 0) | DOUBLE_WORD_LSB_GET(packet->payload, 0);
}
 
 
/*******************************************************************************************
* Logical I/O MAINTENANCE-WRITE functions.
*******************************************************************************************/
 
/**
* \brief Set the packet to contain a maintenance write request.
*
* \param[in] packet The packet to operate on.
* \param[in] destId The deviceId to use as destination in the packet.
* \param[in] srcId The deviceId to use as source in the packet.
* \param[in] hop The hop_count to set in the packet.
* \param[in] tid The transaction identifier to set in the packet.
* \param[in] offset The byte address in the configuration space to write to.
* \param[in] data The data to write in configuration space.
*
* This function sets the content of a packet to a maintenance write request packet
* containing a request to write one word in configuration space.
*/
void RIOPACKET_setMaintWriteRequest(RioPacket_t *packet,
uint16_t destId, uint16_t srcId, uint8_t hop,
uint8_t tid, uint32_t offset, uint32_t data)
{
uint32_t content;
uint16_t crc = 0xffffu;
 
 
/* 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 = 0x00180000ul;
content |= (uint32_t) destId;
crc = RIOPACKET_Crc32(content, crc);
packet->payload[0] = content;
 
/* sourceId(15:0)|transaction(3:0)|rdsize(3:0)|srcTID(7:0) */
content = ((uint32_t) srcId) << 16;
content |= (uint32_t) RIOPACKET_TRANSACTION_MAINT_WRITE_REQUEST << 12;
content |= (uint32_t) 8ul << 8;
content |= (uint32_t) tid;
crc = RIOPACKET_Crc32(content, crc);
packet->payload[1] = content;
 
/* hopcount(7:0)|configOffset(20:0)|wdptr|reserved(1:0) */
content = ((uint32_t) hop) << 24;
content |= offset & 0x00fffffcul;
crc = RIOPACKET_Crc32(content, crc);
packet->payload[2] = 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 = RIOPACKET_Crc32(content, crc);
packet->payload[3] = content;
content = data;
crc = RIOPACKET_Crc32(content, crc);
packet->payload[4] = content;
 
/* crc(15:0)|pad(15:0) */
content = ((uint32_t) crc) << 16;
packet->payload[5] = content;
 
/* Set the size of the packet. */
packet->size = 6;
}
 
 
/**
* \brief Get entries from a maintenance write request.
*
* \param[in] packet The packet to operate on.
* \param[out] destId The destination deviceId in this packet.
* \param[out] srcId The source deviceId in this packet.
* \param[out] hop The hop_count in this packet.
* \param[out] tid The transaction id in this packet.
* \param[out] offset The byte address in the configuration space to read.
* \param[out] data The data to requested to be written in configuration space.
*
* This function returns the content of a packet as if it contained a maintenance write
* request packet.
*
* \note Use the ftype and transaction fields to see if the packet is indeed a
* maintenance write request.
* \note If the packet does not contain a maintenance write request, the result
* will be undefined.
*/
void RIOPACKET_getMaintWriteRequest(RioPacket_t *packet,
uint16_t *destId, uint16_t *srcId, uint8_t *hop,
uint8_t *tid, uint32_t *offset, uint32_t *data)
{
*destId = DESTID_GET(packet->payload);
*srcId = SRCID_GET(packet->payload);
*tid = TID_GET(packet->payload);
*hop = HOP_GET(packet->payload);
*offset = CONFIG_OFFSET_GET(packet->payload);
*data = DOUBLE_WORD_MSB_GET(packet->payload, 0) | DOUBLE_WORD_LSB_GET(packet->payload, 0);
}
 
 
/**
* \brief Set the packet to contain a maintenance write response.
*
* \param[in] packet The packet to operate on.
* \param[in] destId The deviceId to use as destination in the packet.
* \param[in] srcId The deviceId to use as source in the packet.
* \param[in] tid The transaction identifier to set in the packet.
*
* This function sets the content of a packet to a maintanance write response packet
* containing a response to a request writing one word in configuration space.
*/
void RIOPACKET_setMaintWriteResponse(RioPacket_t *packet,
uint16_t destId, uint16_t srcId,
uint8_t tid)
{
uint32_t content;
uint16_t crc = 0xffffu;
 
 
/* 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 = 0x00180000ul;
content |= (uint32_t) destId;
crc = RIOPACKET_Crc32(content, crc);
packet->payload[0] = content;
 
/* sourceId(15:0)|transaction(3:0)|status(3:0)|srcTID(7:0) */
content = ((uint32_t) srcId) << 16;
content |= (uint32_t) RIOPACKET_TRANSACTION_MAINT_WRITE_RESPONSE << 12;
content |= (uint32_t) RIOPACKET_RESPONSE_STATUS_DONE << 8;
content |= (uint32_t) tid;
crc = RIOPACKET_Crc32(content, crc);
packet->payload[1] = content;
 
/* hopcount(7:0)|reserved(23:0) */
/* HopCount should always be set to 0xff in responses. */
content = 0xff000000ul;
crc = RIOPACKET_Crc32(content, crc);
packet->payload[2] = content;
 
/* crc(15:0)|pad(15:0) */
content = ((uint32_t) crc) << 16;
packet->payload[3] = content;
 
/* Set the size of the packet. */
packet->size = 4;
}
 
 
/**
* \brief Get entries from a maintenance write response.
*
* \param[in] packet The packet to operate on.
* \param[out] destId The destination deviceId in this packet.
* \param[out] srcId The source deviceId in this packet.
* \param[out] tid The transaction identifier in the response.
*
* This function returns the content of a packet as if it contained a maintenance
* write response packet.
*
* \note Use the ftype and transaction fields to see if the packet is indeed a
* maintenance write response.
* \note If the packet does not contain a maintenance write response, the result
* will be undefined.
*/
void RIOPACKET_getMaintWriteResponse(RioPacket_t *packet,
uint16_t *destId, uint16_t *srcId,
uint8_t *tid)
{
*destId = DESTID_GET(packet->payload);
*srcId = SRCID_GET(packet->payload);
*tid = TID_GET(packet->payload);
}
 
 
/*******************************************************************************************
* Logical I/O MAINTENANCE-PORTWRITE functions.
*******************************************************************************************/
 
/**
* \brief Set the packet to contain a maintenance port-write request.
*
* \param[in] packet The packet to operate on.
* \param[in] destId The deviceId to use as destination in the packet.
* \param[in] srcId The deviceId to use as source in the packet.
* \param[in] componentTag The value of the componentTag register to set in the packet.
* \param[in] portErrorDetect The value of the Port N Error Detect CSR to set in the packet.
* \param[in] implementationSpecific An implementation specific value to set in the packet.
* \param[in] portId The port ID of the port to set in the packet.
* \param[in] logicalTransportErrorDetect The value of the Logical/Transport Layer
* Error Detect CSR to set in the packet.
*
* This function sets the content of a packet to a maintenance port-write request packet.
*/
void RIOPACKET_setMaintPortWrite(RioPacket_t *packet,
uint16_t destId, uint16_t srcId,
uint32_t componentTag, uint32_t portErrorDetect,
uint32_t implementationSpecific, uint8_t portId,
uint32_t logicalTransportErrorDetect)
{
uint32_t content;
uint16_t crc = 0xffffu;
 
 
/* 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 = 0x00180000ul;
content |= (uint32_t) destId;
crc = RIOPACKET_Crc32(content, crc);
packet->payload[0] = content;
 
/* sourceId(15:0)|transaction(3:0)|rdsize(3:0)|srcTID(7:0) */
content = (uint32_t) srcId << 16;
content |= (uint32_t) RIOPACKET_TRANSACTION_MAINT_PORT_WRITE_REQUEST << 12;
crc = RIOPACKET_Crc32(content, crc);
packet->payload[1] = content;
 
/* hopcount(7:0)|reserved(23:0) */
content = 0x00000000ul;
crc = RIOPACKET_Crc32(content, crc);
packet->payload[2] = content;
 
/* double-word 0 */
content = componentTag;
crc = RIOPACKET_Crc32(content, crc);
packet->payload[3] = content;
content = portErrorDetect;
crc = RIOPACKET_Crc32(content, crc);
packet->payload[4] = content;
 
/* double-word 1 */
content = implementationSpecific << 8;
content |= (uint32_t) portId;
crc = RIOPACKET_Crc32(content, crc);
packet->payload[5] = content;
content = logicalTransportErrorDetect;
crc = RIOPACKET_Crc32(content, crc);
packet->payload[6] = content;
 
/* crc(15:0)|pad(15:0) */
content = ((uint32_t) crc) << 16;
packet->payload[7] = content;
 
/* Set the size of the packet. */
packet->size = 8;
}
 
 
/**
* \brief Get entries from a maintenance port-write request.
*
* \param[in] packet The packet to operate on.
* \param[out] destId The device id of the destination end point.
* \param[out] srcId The device id of the source end point.
* \param[out] componentTag The value of the componentTag register in this packet.
* \param[out] portErrorDetect The value of the Port N Error Detect CSR in this packet.
* \param[out] implementationSpecific An implementation specific value in this packet.
* \param[out] portId The port ID of the port in this packet.
* \param[out] logicalTransportErrorDetect The value of the Logical/Transport Layer
* Error Detect CSR in this packet.
*
* This function returns the content of a packet as if it contained a maintenance port-write
* request packet.
*
* \note Use the ftype and transaction fields to see if the packet is indeed a
* maintenance port-write request.
* \note If the packet does not contain a maintenance port-write request, the result
* will be undefined.
*/
void RIOPACKET_getMaintPortWrite(RioPacket_t *packet,
uint16_t *destId, uint16_t *srcId,
uint32_t *componentTag, uint32_t *portErrorDetect,
uint32_t *implementationSpecific, uint8_t *portId,
uint32_t *logicalTransportErrorDetect)
{
*destId = DESTID_GET(packet->payload);
*srcId = SRCID_GET(packet->payload);
*componentTag = packet->payload[3];
*portErrorDetect = packet->payload[4];
*implementationSpecific = packet->payload[5] >> 8;
*portId = (uint8_t) (packet->payload[5] & 0xff);
*logicalTransportErrorDetect = packet->payload[6];
}
 
 
/*******************************************************************************************
* Logical I/O NWRITE/NWRITER functions.
*******************************************************************************************/
 
/**
* \brief Set a packet to contain an NWRITE.
*
* \param[in] packet The packet to operate on.
* \param[in] destId The deviceId to use as destination in the packet.
* \param[in] srcId The deviceId to use as source in the packet.
* \param[in] address The byte address in IO-space to write to.
* \param[in] payloadSize The number of bytes to write. The largest allowed size is 256 bytes.
* \param[in] payload A pointer to the array of bytes to write.
*
* This function sets the content of a packet to an NWRITE containing a request
* to write the number of bytes specified by payloadSize to the address specified by the
* address argument.
*
* \note The address is a byte address.
*
* \note Not all combinations of addresses and sizes are allowed. The packet will be empty
* if an unallowed address/payloadSize combination is used. Use RIOPACKET_getWritePacketSize()
* to get the maximum size to use based on the address and payloadSize.
*/
void RIOPACKET_setNwrite(RioPacket_t *packet, uint16_t destId, uint16_t srcId,
uint32_t address, uint16_t payloadSize, uint8_t *payload)
{
uint32_t content;
uint16_t wrsize;
 
/* Convert the address and size to the wrsize field and check if the combination is valid. */
wrsize = wrsizeGet(address, payloadSize);
if(wrsize != 0xffff)
{
/* The address and size field combination is valid. */
 
/* 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 = 0x00150000ul;
content |= (uint32_t) destId;
packet->payload[0] = content;
/* sourceId(15:0)|transaction(3:0)|wrsize(3:0)|srcTID(7:0) */
content = ((uint32_t) srcId) << 16;
content |= (uint32_t) RIOPACKET_TRANSACTION_WRITE_NWRITE << 12;
content |= (uint32_t) (wrsize & 0x0f00);
packet->payload[1] = 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;
packet->payload[2] = content;
/* Place the payload buffer into the payload of the packet. */
/* This function also calculates the CRC. */
packet->size = setPacketPayload(&(packet->payload[0]), 12, address & 0x7, payloadSize, payload);
}
else
{
/* The address and size field combination is not valid. */
/* Cannot create a packet from these arguments, indicate this by setting the packet size to zero. */
packet->size = 0;
}
}
 
 
/**
* \brief Get entries from a NWRITE.
*
* \param[in] packet The packet to operate on.
* \param[out] destId The destination deviceId in this packet.
* \param[out] srcId The source deviceId in this packet.
* \param[out] address The byte address into IO-space requested to be written.
* \param[out] payloadSize The number of bytes requested to be written.
* \param[out] payload The data requested to be written.
*
* This function returns the content of a packet as if it contained an NWRITE.
*
* \note The address is a byte address.
*
* \note Any padding contained in double-word0 will be removed and the content
* will be placed where the payload pointer is pointing.
*/
void RIOPACKET_getNwrite(RioPacket_t *packet, uint16_t *destId, uint16_t *srcId,
uint32_t *address, uint16_t *payloadSize, uint8_t *payload)
{
uint8_t wrsize;
uint8_t wdptr;
uint8_t offset = 0;
uint16_t size = 0;
 
 
wrsize = WRSIZE_GET(packet->payload);
wdptr = WDPTR_GET(packet->payload);
wrsizeToOffset(wrsize, wdptr, &offset, &size);
 
*destId = DESTID_GET(packet->payload);
*srcId = SRCID_GET(packet->payload);
*address = ADDRESS_GET(packet->payload) | offset;
 
if(size > 16)
{
size = 4*(packet->size-4);
}
else
{
/* The size already contains the correct value. */
}
 
 
*payloadSize = getPacketPayload(&(packet->payload[0]), 12, offset, size, payload);
}
 
 
 
/**
* \brief Set a packet to contain an NWRITER.
*
* \param[in] packet The packet to operate on.
* \param[in] destId The deviceId to use as destination in the packet.
* \param[in] srcId The deviceId to use as source in the packet.
* \param[in] tid The transaction identifier to set in the packet.
* \param[in] address The byte address in IO-space to write to.
* \param[in] payloadSize The number of bytes to write. The largest allowed size is 256 bytes.
* \param[in] payload A pointer to the array of bytes to write.
*
* This function sets the content of a packet to an NWRITER containing a request
* to write the number of bytes specified by payloadSize to the address specified by the
* address argument. This packet requires a RESPONSE containing the transaction identifier
* specified in this packet.
*
* \note The address is a byte address.
*
* \note Not all combinations of addresses and sizes are allowed. The packet will be empty
* if an unallowed address/payloadSize combination is used. Use RIOPACKET_getWritePacketSize()
* to get the maximum size to use based on the address and payloadSize.
*/
void RIOPACKET_setNwriteR(RioPacket_t *packet, uint16_t destId, uint16_t srcId, uint8_t tid,
uint32_t address, uint16_t payloadSize, uint8_t *payload)
{
uint32_t content;
uint16_t wrsize;
 
/* Convert the address and size to the wrsize field and check if the combination is valid. */
wrsize = wrsizeGet(address, payloadSize);
if(wrsize != 0xffff)
{
/* The address and size field combination is valid. */
 
/* 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 = 0x00150000ul;
content |= (uint32_t) destId;
packet->payload[0] = content;
/* sourceId(15:0)|transaction(3:0)|wrsize(3:0)|srcTID(7:0) */
content = ((uint32_t) srcId) << 16;
content |= (uint32_t) RIOPACKET_TRANSACTION_WRITE_NWRITER << 12;
content |= (uint32_t) (wrsize & 0x0f00);
content |= (uint32_t) tid;
packet->payload[1] = 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;
packet->payload[2] = content;
/* Place the payload buffer into the payload of the packet. */
/* This function also calculates the CRC. */
packet->size = setPacketPayload(&(packet->payload[0]), 12, address & 0x7, payloadSize, payload);
}
else
{
/* The address and size field combination is not valid. */
/* Cannot create a packet from these arguments, indicate this by setting the packet size to zero. */
packet->size = 0;
}
}
 
 
/**
* \brief Get entries from a NWRITER.
*
* \param[in] packet The packet to operate on.
* \param[out] destId The destination deviceId in this packet.
* \param[out] srcId The source deviceId in this packet.
* \param[out] tid The transaction id in this packet.
* \param[out] address The byte address into IO-space requested to be written.
* \param[out] payloadSize The number of bytes requested to be written.
* \param[out] payload The data requested to be written.
*
* This function returns the content of a packet as if it contained an NWRITER.
*
* \note The address is a byte address.
*
* \note Any padding contained in double-word0 will be removed and the content
* will be placed where the payload pointer is pointing.
*/
void RIOPACKET_getNwriteR(RioPacket_t *packet, uint16_t *destId, uint16_t *srcId, uint8_t *tid,
uint32_t *address, uint16_t *payloadSize, uint8_t *payload)
{
uint8_t wrsize;
uint8_t wdptr;
uint8_t offset = 0;
uint16_t size = 0;
 
 
wrsize = WRSIZE_GET(packet->payload);
wdptr = WDPTR_GET(packet->payload);
wrsizeToOffset(wrsize, wdptr, &offset, &size);
*destId = DESTID_GET(packet->payload);
*srcId = SRCID_GET(packet->payload);
*tid = TID_GET(packet->payload);
*address = ADDRESS_GET(packet->payload) | offset;
if(size > 16)
{
size = 4*(packet->size-4);
}
else
{
/* The size already contains the correct value. */
}
 
*payloadSize = getPacketPayload(&(packet->payload[0]), 12, offset, size, payload);
}
 
 
/*******************************************************************************************
* Logical I/O NREAD functions.
*******************************************************************************************/
 
/**
* \brief Set a packet to contain an NREAD.
*
* \param[in] packet The packet to operate on.
* \param[in] destId The deviceId to use as destination in the packet.
* \param[in] srcId The deviceId to use as source in the packet.
* \param[in] tid The transaction id to set in the response.
* \param[in] address The byte address to read from.
* \param[in] payloadSize The number of bytes to read. The largest allowed size is 256 bytes.
*
* This function sets the content of a packet to an NREAD containing a request
* to read the number of bytes specified by payloadSize from the address specified by the
* address argument.
*
* \note The address is a byte address.
*
* \note Not all combinations of address and length are allowed. The packet will be empty
* if an unallowed address/payloadSize combination is used. Use RIOPACKET_getReadPacketSize()
* to get the maximum size to use based on the address and payloadSize.
*/
void RIOPACKET_setNread(RioPacket_t *packet, uint16_t destId, uint16_t srcId, uint8_t tid,
uint32_t address, uint16_t payloadSize)
{
uint32_t content;
uint16_t crc = 0xffffu;
uint16_t rdsize;
 
 
/* Convert the address and size to the rdsize field and check if the combination is valid. */
rdsize = rdsizeGet(address, payloadSize);
if(rdsize != 0xffff)
{
/* The address and size field combination is valid. */
 
/* 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 = 0x00120000ul;
content |= (uint32_t) destId;
crc = RIOPACKET_Crc32(content, crc);
packet->payload[0] = content;
 
/* sourceId(15:0)|transaction(3:0)|rdsize(3:0)|srcTID(7:0) */
content = ((uint32_t) srcId) << 16;
content |= ((uint32_t) RIOPACKET_TRANSACTION_REQUEST_NREAD) << 12;
content |= (uint32_t) (rdsize & 0x0f00);
content |= (uint32_t) tid;
crc = RIOPACKET_Crc32(content, crc);
packet->payload[1] = 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 = RIOPACKET_Crc32(content, crc);
packet->payload[2] = content;
 
/* crc(15:0)|pad(15:0) */
content = ((uint32_t) crc) << 16;
packet->payload[3] = content;
 
/* Set the size of the packet. */
packet->size = 4;
}
else
{
/* The address and size field combination is not valid. */
/* Cannot create a packet from these arguments, indicate this by setting the packet size to zero. */
packet->size = 0;
}
}
 
 
/**
* \brief Get entries from an NREAD.
*
* \param[in] packet The packet to operate on.
* \param[out] destId The destination deviceId in this packet.
* \param[out] srcId The source deviceId in this packet.
* \param[out] tid The transaction id in this packet.
* \param[out] address The byte address into IO-space requested to be written.
* \param[out] payloadSize The number of bytes requested to be read.
*
* This function returns the content of a packet as if it contained an NREAD.
*
* \note The address is a byte address.
*/
void RIOPACKET_getNread(RioPacket_t *packet, uint16_t *destId, uint16_t *srcId, uint8_t *tid,
uint32_t *address, uint16_t *payloadSize)
{
uint8_t rdsize;
uint8_t wdptr;
uint8_t offset = 0;
uint16_t size = 0;
 
 
rdsize = WRSIZE_GET(packet->payload);
wdptr = WDPTR_GET(packet->payload);
rdsizeToOffset(rdsize, wdptr, &offset, &size);
 
*destId = DESTID_GET(packet->payload);
*srcId = SRCID_GET(packet->payload);
*tid = TID_GET(packet->payload);
*address = ADDRESS_GET(packet->payload) | offset;
*payloadSize = size;
}
 
 
 
/*******************************************************************************************
* Logical message passing DOORBELL and MESSAGE functions.
*******************************************************************************************/
 
/**
* \brief Set a packet to contain a DOORBELL.
*
* \param[in] packet The packet to operate on.
* \param[in] destId The deviceId to use as destination in the packet.
* \param[in] srcId The deviceId to use as source in the packet.
* \param[in] tid The transaction identifier to set in the packet.
* \param[in] info The information to send with the doorbell.
*
* This function sets the content of a packet to a DOORBELL.
*/
void RIOPACKET_setDoorbell(RioPacket_t *packet, uint16_t destId, uint16_t srcId, uint8_t tid,
uint16_t info)
{
uint32_t content;
uint16_t crc = 0xffffu;
 
 
/* 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 = 0x001a0000ul;
content |= (uint32_t) destId;
crc = RIOPACKET_Crc32(content, crc);
packet->payload[0] = content;
 
/* sourceId(15:0)|rsrv(7:0)|srcTID(7:0) */
content = ((uint32_t) srcId) << 16;
content |= (uint32_t) tid;
crc = RIOPACKET_Crc32(content, crc);
packet->payload[1] = content;
 
/* infoMSB(7:0)|infoLSB(7:0)|crc(15:0) */
content = ((uint32_t) info) << 16;
crc = RIOPACKET_Crc16(info, crc);
content |= crc;
packet->payload[2] = content;
 
/* Set the size of the packet. */
packet->size = 3;
}
 
 
/**
* \brief Get entries from a DOORBELL.
*
* \param[in] packet The packet to operate on.
* \param[out] destId The destination deviceId in this packet.
* \param[out] srcId The source deviceId in this packet.
* \param[out] tid The transaction identifier in this packet.
* \param[out] info The information field in this packet.
*
* This function returns the content of a packet as if it contained a DOORBELL.
*/
void RIOPACKET_getDoorbell(RioPacket_t *packet, uint16_t *destId, uint16_t *srcId, uint8_t *tid,
uint16_t *info)
{
*destId = DESTID_GET(packet->payload);
*srcId = SRCID_GET(packet->payload);
*tid = TID_GET(packet->payload);
*info = INFO_GET(packet->payload);
}
 
 
/**
* \brief Set a packet to contain a MESSAGE.
*
* \param[in] packet The packet to operate on.
* \param[in] destId The deviceId to use as destination in the packet.
* \param[in] srcId The deviceId to use as source in the packet.
* \param[in] mailbox The mailbox to send the message to.
* \param[in] payloadSize The number of bytes to place into the message.
* \param[in] payload A pointer to the array of bytes to place into the message.
*
* This function sets the content of a packet to contain a MESSAGE.
*
* \note The mailbox argument maps to the packet fields as:
* {xmbox(3:0), letter(1:0), mbox(1:0)} which means that mailbox 0-15 can support
* multipacket messages and 16-255 can handle only single packet messages.
*
* \note The payload size has to be larger than zero and less than 256.
*
* \note Only payloads of even double-words are supported by the protocol itself. Payload
* that is shorter will be padded.
*/
void RIOPACKET_setMessage(RioPacket_t *packet, uint16_t destId, uint16_t srcId, uint8_t mailbox,
uint16_t payloadSize, uint8_t *payload)
{
uint32_t content;
 
 
/* Make sure that the message payload size is larger than zero. */
if((payloadSize > 0) && (payloadSize <= 256))
{
/* The payload size is larger than zero. */
 
/* 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 = 0x001b0000ul;
content |= (uint32_t) destId;
packet->payload[0] = content;
/* sourceId(15:0)|msglen(3:0)|ssize(3:0)|letter(1:0)|mbox(1:0)|msgseg(3:0)/xmbox(3:0) */
content = ((uint32_t) srcId) << 16;
if(payloadSize <= 8u)
{
content |= 0x00000900ul;
}
else if(payloadSize <= 16u)
{
content |= 0x00000a00ul;
}
else if(payloadSize <= 32u)
{
content |= 0x00000b00ul;
}
else if(payloadSize <= 64u)
{
content |= 0x00000c00ul;
}
else if(payloadSize <= 128u)
{
content |= 0x00000d00ul;
}
else
{
content |= 0x00000e00ul;
}
content |= (((uint32_t) mailbox) & 0xful) << 4;
content |= ((uint32_t) mailbox) >> 4;
packet->payload[1] = content;
 
/* Place data buffer into the payload of the packet and set the size. */
packet->size = setPacketPayload(&(packet->payload[0]), 8, 0, payloadSize, payload);
}
else
{
/* The payload size is not allowed. */
/* Unable to create the new packet. */
packet->size = 0;
}
}
 
 
/**
* \brief Get entries from a MESSAGE.
*
* \param[in] packet The packet to operate on.
* \param[out] destId The destination deviceId in this packet.
* \param[out] srcId The source deviceId in this packet.
* \param[out] mailbox The mailbox the message is received on.
* \param[out] payloadSize The number of bytes in the payload.
* \param[out] payload The payload of the packet.
*
* This function returns the content of a packet as if it contained a MESSAGE.
*
* \note The mailbox argument maps to the packet fields as:
* {xmbox(3:0), letter(1:0), mbox(1:0)} which means that mailbox 0-15 can support
* multipacket messages and 16-255 can handle only single packet messages.
*
* \note Only payloads of even double-words are supported by the protocol itself so the
* returned payloadSize is always an even multiple of eight.
*/
void RIOPACKET_getMessage(RioPacket_t *packet, uint16_t *destId, uint16_t *srcId, uint8_t *mailbox,
uint16_t *payloadSize, uint8_t *payload)
{
*destId = DESTID_GET(packet->payload);
*srcId = SRCID_GET(packet->payload);
*mailbox = XMBOX_GET(packet->payload);
*mailbox <<= 2;
*mailbox |= LETTER_GET(packet->payload);
*mailbox <<= 2;
*mailbox |= MBOX_GET(packet->payload);
*payloadSize = getPacketPayload(&(packet->payload[0]), 8, 0, (packet->size-3)*4, payload);
}
 
 
 
 
/*******************************************************************************************
* Logical I/O RESPONSE-DONE-PAYLOAD, RESPONSE-DONE, RESPONSE-RETRY and RESPONSE-ERROR
* functions.
*******************************************************************************************/
 
/**
* \brief Set a packet to contain a RESPONSE without payload.
*
* \param[in] packet The packet to operate on.
* \param[in] destId The deviceId to use as destination in the packet.
* \param[in] srcId The deviceId to use as source in the packet.
* \param[in] tid The transaction id to send the response for.
* \param[in] status The status to send in the packet.
*
* This function sets the content of a packet to contain a RESPONSE without payload.
*
* \note The tid field must be the same value as the packet contained that this is the
* response for.
*
* \note The status field should be either of the values RIOPACKET_RESPONSE_STATUS_XXXX.
*/
void RIOPACKET_setResponseNoPayload(RioPacket_t *packet,
uint16_t destId, uint16_t srcId,
uint8_t tid, uint8_t status)
{
uint32_t content;
uint16_t crc = 0xffffu;
 
 
/* 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 = 0x001d0000ul;
content |= (uint32_t) destId;
crc = RIOPACKET_Crc32(content, crc);
packet->payload[0] = content;
 
/* sourceId(15:0)|transaction(3:0)|status(3:0)|targetTID(7:0) */
content = ((uint32_t) srcId) << 16;
content |= ((uint32_t) RIOPACKET_TRANSACTION_RESPONSE_NO_PAYLOAD) << 12;
content |= ((uint32_t) (status & 0xf)) << 8;
content |= (uint32_t) tid;
crc = RIOPACKET_Crc32(content, crc);
packet->payload[1] = content;
 
/* crc(15:0)|pad(15:0) */
content = ((uint32_t) crc) << 16;
packet->payload[2] = content;
 
/* Set the size of the packet. */
packet->size = 3;
}
 
 
/**
* \brief Get entries from a RESPONSE without payload.
*
* \param[in] packet The packet to operate on.
* \param[out] destId The destination deviceId in this packet.
* \param[out] srcId The source deviceId in this packet.
* \param[out] tid The transaction identifier in this packet.
* \param[out] status The status in this packet.
*
* This function returns the content of a packet as if it contained a RESPONSE.
*/
void RIOPACKET_getResponseNoPayload(RioPacket_t *packet,
uint16_t *destId, uint16_t *srcId,
uint8_t *tid, uint8_t *status)
{
*destId = DESTID_GET(packet->payload);
*srcId = SRCID_GET(packet->payload);
*tid = TID_GET(packet->payload);
*status = STATUS_GET(packet->payload);
}
 
 
 
/**
* \brief Set a packet to contain a RESPONSE also containing payload.
*
* \param[in] packet The packet to operate on.
* \param[in] destId The deviceId to use as destination in the packet.
* \param[in] srcId The deviceId to use as source in the packet.
* \param[in] tid The transaction id to send the response for.
* \param[in] offset The offset into the payload to start to write the input payload to.
* \param[in] payloadSize The size of the payload to return in the reply.
* \param[in] payload The payload to return in the reply.
*
* This function sets the content of a packet to contain a RESPOSE with payload.
*
* \note The tid field must be the same value as the packet contained that this is the
* response for.
*
* \note The offset field can be used to offset the payload in a response to, for
* example, an NREAD.
*
* \note The payloadSize must match the size of the packet that this is the
* response for.
*/
void RIOPACKET_setResponseWithPayload(RioPacket_t *packet,
uint16_t destId, uint16_t srcId,
uint8_t tid, uint8_t offset,
uint16_t payloadSize, uint8_t *payload)
{
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 = 0x001d0000ul;
content |= (uint32_t) destId;
packet->payload[0] = content;
/* sourceId(15:0)|transaction(3:0)|status(3:0)|targetTID(7:0) */
/* status=DONE is 0. */
content = ((uint32_t) srcId) << 16;
content |= ((uint32_t) RIOPACKET_TRANSACTION_RESPONSE_WITH_PAYLOAD) << 12;
content |= (uint32_t) tid;
packet->payload[1] = content;
 
packet->size = setPacketPayload(&(packet->payload[0]), 8, offset & 0x7, payloadSize, payload);
}
 
/**
* \brief Get entries from a RESPONSE containing payload.
*
* \param[in] packet The packet to operate on.
* \param[out] destId The destination deviceId in this packet.
* \param[out] srcId The source deviceId in this packet.
* \param[out] tid The transaction identifier in this packet.
* \param[in] offset The offset into the payload to start reading from.
* \param[out] payloadSize The number of bytes in the payload.
* \param[out] payload The payload of the packet.
*
* This function returns the content of a packet as if it contained a RESPONSE with payload.
*
* \note The offset field can be used to read the payload in a response to, for
* example, an NREAD.
*/
void RIOPACKET_getResponseWithPayload(RioPacket_t *packet,
uint16_t *destId, uint16_t *srcId,
uint8_t *tid, uint8_t offset,
uint16_t *payloadSize, uint8_t *payload)
{
*destId = DESTID_GET(packet->payload);
*srcId = SRCID_GET(packet->payload);
*tid = TID_GET(packet->payload);
*payloadSize = getPacketPayload(&(packet->payload[0]), 8, offset & 0x7, (packet->size-3)*4, payload);
}
 
 
 
/**
* \brief Set a packet to contains a RESPONSE to a message.
*
* \param[in] packet The packet to operate on.
* \param[in] destId The deviceId to use as destination in the packet.
* \param[in] srcId The deviceId to use as source in the packet.
* \param[in] mailbox The mailbox to send the message to.
* \param[in] status The status to send in the packet.
*
* This function is used to send a response indicating a successfull
* completion in reply to a previously received packet.
*
* \note The mailbox field should contain the same value as the packet that this is the
* response to.
*
* \note The status field should be either of the values RIOPACKET_RESPONSE_STATUS_XXXX.
*/
void RIOPACKET_setResponseMessage(RioPacket_t *packet,
uint16_t destId, uint16_t srcId,
uint8_t mailbox, uint8_t status)
{
uint32_t content;
uint16_t crc = 0xffffu;
 
 
/* 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 = 0x001d0000ul;
content |= (uint32_t) destId;
crc = RIOPACKET_Crc32(content, crc);
packet->payload[0] = 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) RIOPACKET_TRANSACTION_RESPONSE_MESSAGE_RESPONSE) << 12;
content |= ((uint32_t) (status & 0xf)) << 8;
content |= ((uint32_t) (mailbox & 0xf)) << 4;
content |= ((uint32_t) mailbox) >> 4;
crc = RIOPACKET_Crc32(content, crc);
packet->payload[1] = content;
 
/* crc(15:0)|pad(15:0) */
content = ((uint32_t) crc) << 16;
packet->payload[2] = content;
 
/* Set the size of the packet. */
packet->size = 3;
}
 
/**
* \brief Get entries from a RESPONSE to a message.
*
* \param[in] packet The packet to operate on.
* \param[out] destId The destination deviceId in this packet.
* \param[out] srcId The source deviceId in this packet.
* \param[out] mailbox The mailbox the response should be sent to.
* \param[out] status The status in the packet.
*
* This function returns the content of a packet as if it contained a RESPONSE to a message.
*/
void RIOPACKET_getResponseMessage(RioPacket_t *packet,
uint16_t *destId, uint16_t *srcId,
uint8_t *mailbox, uint8_t *status)
{
*destId = DESTID_GET(packet->payload);
*srcId = SRCID_GET(packet->payload);
*mailbox = XMBOX_GET(packet->payload);
*mailbox <<= 2;
*mailbox |= LETTER_GET(packet->payload);
*mailbox <<= 2;
*mailbox |= MBOX_GET(packet->payload);
*status = STATUS_GET(packet->payload);
}
 
 
/**
* \brief Calculate a new CRC16 value.
*
* \param[in] data The new data (16-bit) to update the current crc value with.
* \param[in] crc The old crc value that should be updated.
* \returns The new crc value based on the input arguments.
*
* This function calculates a new crc value using the generator polynom
* P(X)=x16+x12+x5+1. It is defined in RapidIO 3.0 part6 chapter 2.4.2.
*/
uint16_t RIOPACKET_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;
}
 
 
/**
* \brief Calculate a new CRC16 value.
*
* \param[in] data The new data (32-bit) to update the current crc value with.
* \param[in] crc The old crc value that should be updated.
* \returns The new crc value based on the input arguments.
*
* This function calculates a new crc value using the generator polynom
* P(X)=x16+x12+x5+1. It is defined in RapidIO 3.0 part6 chapter 2.4.2.
*/
uint16_t RIOPACKET_Crc32(const uint32_t data, uint16_t crc)
{
crc = RIOPACKET_Crc16((uint16_t) (data >> 16), crc);
crc = RIOPACKET_Crc16((uint16_t) (data), crc);
return crc;
}
 
 
/**
* \brief Get the maximum size of an NWRITE payload.
*
* \param[in] address The starting address to write to in the NWRITE.
* \param[in] size The total size of the access to NWRITE.
* \returns The maximum number of bytes that are allowed to send in a single
* NWRITE packet that conforms to the RapidIO standard.
*
* This function calculates the maximum sized NWRITE packet payload that are
* possible to send without breaking the limitations in the RapidIO specification.
* It is intended to be called repeatedly.
*
* Example: An area with address=0x00007 and size=258 needs to be written.
* Call RIOPACKET_getWritePacketSize(0x00007, 258)->1.
* Send an NWRITE to address=0x00007 and size=1.
* Update the address and size with the returned value->
* address+=1->address=0x00008 size-=1->size=257.
* Call RIOPACKET_getWritePacketSize(0x00008, 257)->256.
* Send an NWRITE to address=0x00008 and size=256.
* Update the address and size with the returned value->
* address+=256->address=0x00108 size-=256->size=1.
* Call RIOPACKET_getWritePacketSize(0x00108, 1)->1.
* Send an NWRITE to address=0x00108 and size=1.
* Update the address and size with the returned value->
* address+=1->address=0x00109 size-=1->size=0.
* All the data has been written.
*
*/
uint32_t RIOPACKET_getWritePacketSize(uint32_t address, uint32_t size)
{
uint32_t returnValue;
 
 
switch(address%8)
{
case 0:
if(size >= 256)
{
returnValue = 256;
}
else if(size >= 8)
{
returnValue = size - (size % 8);
}
else
{
returnValue = size;
}
break;
case 1:
if(size >= 7)
{
returnValue = 7;
}
else
{
returnValue = 1;
}
break;
case 2:
if(size >= 6)
{
returnValue = 6;
}
else if(size >= 2)
{
returnValue = 2;
}
else
{
returnValue = 1;
}
break;
case 3:
if(size >= 5)
{
returnValue = 5;
}
else
{
returnValue = 1;
}
break;
case 4:
if(size >= 4)
{
returnValue = 4;
}
else if(size >= 2)
{
returnValue = 2;
}
else
{
returnValue = 1;
}
break;
case 5:
if(size >= 3)
{
returnValue = 3;
}
else
{
returnValue = 1;
}
break;
case 6:
if(size >= 2)
{
returnValue = 2;
}
else
{
returnValue = 1;
}
break;
default:
returnValue = 1;
break;
}
return returnValue;
}
 
 
/**
* \brief Get the maximum size of an NREAD payload.
*
* \param[in] address The starting address to read from in the NREAD.
* \param[in] size The total size of the access to NREAD.
* \returns The maximum number of bytes that are allowed to send in a single
* NREAD packet that conforms to the RapidIO standard.
*
* This function calculates the maximum sized NREAD packet payload that are
* possible to send without breaking the limitations in the RapidIO specification.
* It is intended to be called repeatedly.
*
* Example: An area with address=0x00007 and size=258 needs to be read.
* Call RIOPACKET_getReadPacketSize(0x00007, 258)->1.
* Send an NREAD to address=0x00007 and size=1.
* Update the address and size with the returned value->
* address+=1->address=0x00008 size-=1->size=257.
* Call RIOPACKET_getReadPacketSize(0x00008, 257)->256.
* Send an NREAD to address=0x00008 and size=256.
* Update the address and size with the returned value->
* address+=256->address=0x00108 size-=256->size=1.
* Call RIOPACKET_getReadPacketSize(0x00108, 1)->1.
* Send an NREAD to address=0x00108 and size=1.
* Update the address and size with the returned value->
* address+=1->address=0x00109 size-=1->size=0.
* All the data has been read.
*
*/
uint32_t RIOPACKET_getReadPacketSize(uint32_t address, uint32_t size)
{
uint32_t returnValue;
 
 
switch(address%8)
{
case 0:
if(size >= 256)
{
returnValue = 256;
}
else if(size >= 224)
{
returnValue = 224;
}
else if(size >= 192)
{
returnValue = 192;
}
else if(size >= 160)
{
returnValue = 160;
}
else if(size >= 128)
{
returnValue = 128;
}
else if(size >= 96)
{
returnValue = 96;
}
else if(size >= 64)
{
returnValue = 64;
}
else if(size >= 32)
{
returnValue = 32;
}
else if(size >= 16)
{
returnValue = 16;
}
else if(size >= 8)
{
returnValue = 8;
}
else
{
returnValue = size;
}
break;
case 1:
if(size >= 7)
{
returnValue = 7;
}
else
{
returnValue = 1;
}
break;
case 2:
if(size >= 6)
{
returnValue = 6;
}
else if(size >= 2)
{
returnValue = 2;
}
else
{
returnValue = 1;
}
break;
case 3:
if(size >= 5)
{
returnValue = 5;
}
else
{
returnValue = 1;
}
break;
case 4:
if(size >= 4)
{
returnValue = 4;
}
else if(size >= 2)
{
returnValue = 2;
}
else
{
returnValue = 1;
}
break;
case 5:
if(size >= 3)
{
returnValue = 3;
}
else
{
returnValue = 1;
}
break;
case 6:
if(size >= 2)
{
returnValue = 2;
}
else
{
returnValue = 1;
}
break;
default:
returnValue = 1;
break;
}
return returnValue;
}
 
 
 
/*******************************************************************************
* Locally used helper functions.
*******************************************************************************/
 
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 payload bytes from RapidIO packet into a 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 = RIOPACKET_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 = RIOPACKET_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 = RIOPACKET_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 = RIOPACKET_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 = RIOPACKET_Crc16(content, crc);
content <<= 16;
content |= crc;
}
packet[packetIndex>>2] = content;
 
return (packetIndex>>2)+1;
}
 
 
 
/* \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.
**************************************************************/
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;
 
 
switch(size/8)
{
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
{
/* Not supported by protocol. */
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;
}
}
 
/*************************** end of file **************************************/
/rio/trunk/sw/stack/rioconfig.h
10,6 → 10,8
* the riostack. Replace declarations and definitions in this file to customize
* for your own compiler environment.
*
* No copyright for this file since it has to be changed.
*
* To Do:
* -
*
16,31 → 18,6
* Author(s):
* - Magnus Rosenius, magro732@opencores.org
*
*******************************************************************************
*
* Copyright (C) 2013 Authors and OPENCORES.ORG
*
* This source file may be used and distributed without
* restriction provided that this copyright statement is not
* removed from the file and that any derivative work contains
* the original copyright notice and the associated disclaimer.
*
* This source file is free software; you can redistribute it
* and/or modify it under the terms of the GNU Lesser General
* Public License as published by the Free Software Foundation;
* either version 2.1 of the License, or (at your option) any
* later version.
*
* This source is distributed in the hope that it will be
* useful, but WITHOUT ANY WARRANTY; without even the implied
* warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
* PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General
* Public License along with this source; if not, download it
* from http://www.opencores.org/lgpl.shtml
*
*******************************************************************************/
 
#ifndef __RIO_CONFIG
51,7 → 28,6
*******************************************************************************/
 
#include <stdint.h>
#include <stdlib.h>
 
/*******************************************************************************
* Global typedefs
72,16 → 48,9
#endif
 
#ifndef DEBUG_OUT
#define DEBUG_OUT(...)
#define DEBUG_OUT(...) fprintf(stderr, __VA_ARGS__)
#endif
 
#define DEBUG_STATE(...) /*DEBUG_OUT(__VA_ARGS__)*/
#define DEBUG_FRAMING_RX(...) /*DEBUG_OUT(__VA_ARGS__)*/
#define DEBUG_FRAMING_TX(...) /*DEBUG_OUT(__VA_ARGS__)*/
 
typedef uint8_t bool_t;
 
 
/*******************************************************************************
* Global declarations
*******************************************************************************/
/rio/trunk/sw/stack/riostack.h
6,8 → 6,7
* http://www.opencores.org/cores/rio/
*
* Description:
* This file contains the function prototypes and types that are needed to be
* able to use the riostack.c module.
* This file contains the API of the riostack.c module.
*
* To Do:
* -
17,7 → 16,7
*
*******************************************************************************
*
* Copyright (C) 2013 Authors and OPENCORES.ORG
* Copyright (C) 2015 Authors and OPENCORES.ORG
*
* This source file may be used and distributed without
* restriction provided that this copyright statement is not
54,6 → 53,7
*******************************************************************************/
 
#include "rioconfig.h"
#include "riopacket.h"
 
 
/*******************************************************************************
60,47 → 60,17
* Global typedefs
*******************************************************************************/
 
/* The maximum size of a RapidIO packet. */
#define RIO_PACKET_SIZE ((uint8_t)69u)
 
/* The size of a maximum sized RapidIO packet when stored in memory. */
/* One entry contains a header with the used buffer size. */
#define RIO_BUFFER_SIZE (RIO_PACKET_SIZE+1u)
#define RIOSTACK_BUFFER_SIZE (RIOPACKET_SIZE_MAX+1u)
 
/* Configuration space offsets. */
#define DEVICE_IDENTITY_CAR ((uint32_t)0x00000000ul)
#define DEVICE_INFORMATION_CAR ((uint32_t)0x00000004ul)
#define ASSEMBLY_IDENTITY_CAR ((uint32_t)0x00000008ul)
#define ASSEMBLY_INFORMATION_CAR ((uint32_t)0x0000000cul)
#define PROCESSING_ELEMENT_FEATURES_CAR ((uint32_t)0x00000010ul)
#define SWITCH_PORT_INFORMATION_CAR ((uint32_t)0x00000014ul)
#define SOURCE_OPERATIONS_CAR ((uint32_t)0x00000018ul)
#define DESTINATION_OPERATIONS_CAR ((uint32_t)0x0000001cul)
#define SWITCH_ROUTE_TABLE_DESTINATION_ID_LIMIT_CAR ((uint32_t)0x00000034ul)
#define PROCESSING_ELEMENT_LOGICAL_LAYER_CONTROL_CSR ((uint32_t)0x0000004cul)
#define BASE_DEVICE_ID_CSR ((uint32_t)0x00000060ul)
#define HOST_BASE_DEVICE_ID_LOCK_CSR ((uint32_t)0x00000068ul)
#define COMPONENT_TAG_CSR ((uint32_t)0x0000006cul)
#define STANDARD_ROUTE_CONFIGURATION_DESTINATION_ID_SELECT_CSR ((uint32_t)0x00000070ul)
#define STANDARD_ROUTE_CONFIGURATION_PORT_SELECT_CSR ((uint32_t)0x00000074ul)
#define STANDARD_ROUTE_DEFAULT_PORT_CSR ((uint32_t)0x00000078ul)
#define EXTENDED_FEATURES_OFFSET ((uint32_t)0x00000100ul)
#define IMPLEMENTATION_DEFINED_OFFSET ((uint32_t)0x00010000ul)
#define LP_SERIAL_REGISTER_BLOCK_HEADER(offset) (offset)
#define PORT_LINK_TIMEOUT_CONTROL_CSR(offset) ((offset) + 0x00000020ul)
#define PORT_RESPONSE_TIMEOUT_CONTROL_CSR(offset) ((offset) + 0x00000024ul)
#define PORT_GENERAL_CONTROL_CSR(offset) ((offset) + 0x0000003cul)
#define PORT_N_LOCAL_ACKID_CSR(offset, n) ((offset) + (0x00000048ul+((n)*0x00000020ul)))
#define PORT_N_ERROR_AND_STATUS_CSR(offset, n) ((offset) + (0x00000058ul+((n)*0x00000020ul)))
#define PORT_N_CONTROL_CSR(offset, n) ((offset) + (0x0000005cul+((n)*0x00000020ul)))
 
 
/* Define the different types of RioSymbols. */
typedef enum
{
RIO_SYMBOL_TYPE_IDLE, RIO_SYMBOL_TYPE_CONTROL,
RIO_SYMBOL_TYPE_DATA, RIO_SYMBOL_TYPE_ERROR
} RioSymbolType;
{
RIOSTACK_SYMBOL_TYPE_IDLE, RIOSTACK_SYMBOL_TYPE_CONTROL,
RIOSTACK_SYMBOL_TYPE_DATA, RIOSTACK_SYMBOL_TYPE_ERROR
} RioSymbolType_t;
 
 
/*
115,50 → 85,26
*/
typedef struct
{
RioSymbolType type;
RioSymbolType_t type;
uint32_t data;
} RioSymbol;
} RioSymbol_t;
 
/* Define different events that may happen in the stack. */
typedef enum
{
RIO_EVENT_NONE,
RIO_EVENT_NREAD, RIO_EVENT_NWRITE, RIO_EVENT_NWRITE_R,
RIO_EVENT_DOORBELL, RIO_EVENT_MESSAGE,
RIO_EVENT_MAINT_READ_REQUEST, RIO_EVENT_MAINT_WRITE_REQUEST,
RIO_EVENT_MAINT_READ_RESPONSE, RIO_EVENT_MAINT_WRITE_RESPONSE,
RIO_EVENT_RESPONSE_DONE, RIO_EVENT_RESPONSE_DONE_PAYLOAD,
RIO_EVENT_RESPONSE_RETRY, RIO_EVENT_RESPONSE_ERROR,
RIO_EVENT_MESSAGE_RESPONSE_DONE, RIO_EVENT_MESSAGE_RESPONSE_RETRY,
RIO_EVENT_MESSAGE_RESPONSE_ERROR
} RioEventType;
 
 
/* Define different states the link may be in. */
typedef enum
{
RIO_STATUS_UNINITIALIZED,
RIO_STATUS_ENUMERATION,
RIO_STATUS_OPERATIONAL
} RioStatusType;
 
 
/* Receiver states. */
typedef enum
{
RX_STATE_UNINITIALIZED, RX_STATE_PORT_INITIALIZED, RX_STATE_LINK_INITIALIZED,
RX_STATE_INPUT_RETRY_STOPPED, RX_STATE_INPUT_ERROR_STOPPED
} RioReceiverState;
{
RX_STATE_UNINITIALIZED, RX_STATE_PORT_INITIALIZED, RX_STATE_LINK_INITIALIZED,
RX_STATE_INPUT_RETRY_STOPPED, RX_STATE_INPUT_ERROR_STOPPED
} RioReceiverState_t;
 
 
/* Transmitter states. */
typedef enum
{
TX_STATE_UNINITIALIZED, TX_STATE_PORT_INITIALIZED, TX_STATE_LINK_INITIALIZED,
TX_STATE_SEND_PACKET_RETRY, TX_STATE_SEND_PACKET_NOT_ACCEPTED, TX_STATE_SEND_LINK_RESPONSE,
TX_STATE_OUTPUT_RETRY_STOPPED, TX_STATE_OUTPUT_ERROR_STOPPED
} RioTransmitterState;
{
TX_STATE_UNINITIALIZED, TX_STATE_PORT_INITIALIZED, TX_STATE_LINK_INITIALIZED,
TX_STATE_SEND_PACKET_RETRY, TX_STATE_SEND_PACKET_NOT_ACCEPTED, TX_STATE_SEND_LINK_RESPONSE,
TX_STATE_OUTPUT_RETRY_STOPPED, TX_STATE_OUTPUT_ERROR_STOPPED
} RioTransmitterState_t;
 
 
/* Queue definition. */
173,22 → 119,13
uint32_t *buffer_p;
} Queue_t;
 
/* Forward declaration for the RioStack-structure. */
struct RioStack_t;
 
/* Structure to enter callback function pointers in. */
typedef struct
{
uint32_t (*configRead)(struct RioStack_t *stack, uint32_t offset);
void (*configWrite)(struct RioStack_t *stack, uint32_t offset, uint32_t data);
} RioStackObserver_t;
 
 
/* Define the structure to keep all the RapidIO stack variables. */
typedef struct RioStack_t
typedef struct
{
/* Receiver variables. */
RioReceiverState rxState;
RioReceiverState_t rxState;
uint8_t rxCounter;
uint16_t rxCrc;
uint8_t rxStatusReceived;
198,7 → 135,7
Queue_t rxQueue;
 
/* Transmitter variables. */
RioTransmitterState txState;
RioTransmitterState_t txState;
uint8_t txCounter;
uint16_t txStatusCounter;
uint8_t txFrameState;
212,20 → 149,6
uint32_t portTime;
uint32_t portTimeout;
 
/* Common protocol stack variables updated visible via the configuration space. */
uint16_t deviceIdentity;
uint16_t deviceVendorIdentity;
uint32_t deviceRev;
uint16_t assyIdentity;
uint16_t assyVendorIdentity;
uint16_t assyRev;
uint16_t baseDeviceId;
uint32_t hostBaseDeviceIdLock;
uint32_t componentTag;
uint8_t host;
uint8_t masterEnable;
uint8_t discovered;
 
/** The number of successfully received packets. */
uint32_t statusInboundPacketComplete;
 
262,6 → 185,9
/** The number of successfully transmitted packets. */
uint32_t statusOutboundPacketComplete;
 
/** The maximum time between a completed outbound packet and the reception of its pcakcet-accepted control-symbol. */
uint32_t statusOutboundLinkLatencyMax;
 
/** The number of retried transmitted packets.
This will happen if the receiver at the link-partner does not have resources available when an outbound
packet is received. */
308,11 → 234,8
This happens depending on the link-partner implementation. */
uint32_t statusPartnerErrorGeneral;
 
/* Callback structure. */
const RioStackObserver_t *observer;
 
/* Private user data. */
const void *private;
void* private;
} RioStack_t;
 
 
324,7 → 247,6
* \brief Open the RapidIO stack for operation.
*
* \param[in] stack Stack instance to operate on.
* \param[in] observer Callback structure to use when events happen.
* \param[in] private Pointer to an opaque data area containing private user data.
* \param[in] rxPacketBufferSize Number of words to use as reception buffer. This
* argument specifies the size of rxPacketBuffer.
332,24 → 254,10
* \param[in] txPacketBufferSize Number of words to use as transmission buffer. This
* argument specifies the size of txPacketBuffer.
* \param[in] txPacketBuffer Pointer to buffer to store outbound packets in.
* \param[in] configDeviceVendorId Constant to use as deviceVendorIdentity when
* accessed in configuration space. (See Part 1, chapter 5.4.1)
* \param[in] configDeviceId Constant to use as deviceIdentity when accessed in
* configuration space. (See Part 1, chapter 5.4.1)
* \param[in] configDeviceRevisionId Constant to use as deviceRev when accessed in
* configuration space. (See Part 1, chapter 5.4.2)
* \param[in] configAssyVendorId Constant to use as assyVendorIdentity when accessed in
* configuration space. (See Part 1, chapter 5.4.3)
* \param[in] configAssyId Constant to use as assyIdentity when accessed in
* configuration space. (See Part 1, chapter 5.4.3)
* \param[in] configAssyRevisionId Constant to use as assyRev when accessed in
* configuration space. (See Part 1, chapter 5.4.4)
* \param[in] configBaseDeviceId The deviceId (source address) to use at startup when
* sending packets.
*
* This function initializes all internally used variables in the stack. The stack will
* however not be operational until the transcoder has signalled that it is ready for
* other symbols than idle. This is done using the function RIO_setPortStatus(). Once
* other symbols than idle. This is done using the function RIOSTACK_setPortStatus(). Once
* this function has been called it is possible to get and set symbols and to issue
* requests. The requests will be transmitted once the link initialization has
* been completed.
363,13 → 271,9
*
* \note The reception buffers can only support maximum 31 buffers.
*/
void RIO_open( RioStack_t *stack, const RioStackObserver_t *observer, const void *private,
const uint32_t rxPacketBufferSize, uint32_t *rxPacketBuffer,
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 );
void RIOSTACK_open(RioStack_t *stack, void *private,
const uint32_t rxPacketBufferSize, uint32_t *rxPacketBuffer,
const uint32_t txPacketBufferSize, uint32_t *txPacketBuffer);
 
/*******************************************************************************************
* Stack status functions.
380,902 → 284,105
* \brief Get the status of the link.
*
* \param[in] stack The stack to operate on.
* \return Returns the status of the link.
* \return Returns the status of the link, zero if link is uninitialized and non-zero if
* the link is initialized.
*
* This function indicates if the link is up and ready to relay packets.
* This function indicates if the link is up and ready to relay packets.
*/
RioStatusType RIO_getStatus( RioStack_t *stack );
int RIOSTACK_getStatus(RioStack_t *stack);
 
/**
* \brief Get the number of pending outbound packets.
* \brief Clear outbound queue.
*
* \param[in] stack The stack to operate on.
* \return Returns the number of pending outbound packets.
*
* This function checks the outbound queue and returns the number of packets
* that are pending to be transmitted onto the link.
* This function clears all pending packet in the outbound queue.
*/
uint8_t RIO_outboundQueueLength( RioStack_t *stack );
void RIOSTACK_clearOutboundQueue(RioStack_t *stack);
 
/**
* \brief Get the number of pending inbound packets.
* \brief Get the number of pending outbound packets.
*
* \param[in] stack The stack to operate on.
* \return Returns the number of pending inbound packets.
* \return Returns the number of pending outbound packets.
*
* This function checks the inbound queue and returns the number of packets
* that has been received but not read by the user yet.
* This function checks the outbound queue and returns the number of packets
* that are pending to be transmitted onto the link.
*/
uint8_t RIO_inboundQueueLength( RioStack_t *stack );
uint8_t RIOSTACK_getOutboundQueueLength(RioStack_t *stack);
 
/*******************************************************************************************
* Packet reception functions.
*******************************************************************************************/
 
/**
* \brief Check for new events.
* \brief Get the number of available outbound packets.
*
* \param[in] stack The stack to operate on.
* \return Returns the value RIO_EVENT_NONE if no event is pending and
* something else if there are pending events.
* \return Returns the number of available outbound packets.
*
* This function polls the incoming queue of packets and returns the
* type of packet present there. The return value from this function
* indicates which access functions that should be used to read the
* received packet.
*
* \note When a packet has been processed, RIO_packetRemove() must be called to free the
* used resources in the inbound queue.
* This function checks the outbound queue and returns the number of packets
* that are available before the queue is full.
*/
RioEventType RIO_eventPoll( RioStack_t *stack );
uint8_t RIOSTACK_getOutboundQueueAvailable(RioStack_t *stack);
 
/**
* \brief Remove a packet from the stack.
* \param[in] stack The stack to operate on.
* \brief Add a packet to the outbound queue.
*
* Remove a pending packet from the stack. The incoming packet queue is updated
* to remove the received packet.
*/
void RIO_packetRemove( RioStack_t *stack );
 
/**
* \brief Check transmission buffers.
*
* \param[in] stack The stack to operate on.
* \param[in] size The size of the buffer that is about to be sent.
* \return Returns non-zero if a buffer with the specified size fits into the
* internal transmission buffers.
* \param[in] packet The packet to send.
*
* Return if there are buffers available to send a packet of a specified size.
* This function sends a packet.
*
* \note If the response is negative, it might be positive later if outbound
* packets has been sent and new buffers becomes available.
* \note The packet CRC is not checked. It must have been checked before it is used as
* argument to this function.
*
* \note Set size to zero if there is no user definded payload.
*/
bool_t RIO_sendAvailable( RioStack_t *stack, const uint16_t size );
 
/**
* \brief Get a raw packet from inbound queue.
*
* \param[in] stack The stack to operate on.
* \param[in] length The size of the buffer to write the packet to.
* \param[in] dest Pointer to where to copy the raw packet.
* \return The number of words copied.
*
* This function copies a raw packet in the inbound queue into a word buffer. An assert
* will occur if the packet does not fit into the provided buffer.
*
* \note The packet is automatically removed from the inbound queue. Do not use
* RIO_packetRemove() to remove it.
*/
uint32_t RIO_packetGet( RioStack_t *stack, uint32_t length, uint32_t *dest);
 
/**
* \brief Set a raw packet in outbound queue.
*
* \param[in] stack The stack to operate on.
* \param[in] length The size of the packet to write.
* \param[in] src Pointer to where to copy the raw packet from.
*
* This function copies a raw packet from a source buffer into the outbound queue.
* An assert will occur if the packet does not fit into the internal buffer.
*
* \note Calling this function resembles a send-function, the packet will be placed in the
* outbound queue for transmission.
*
* \note If the copied packet does not have a correct CRC it might lock the stack since
* retransmissions will be done until forever.
*/
void RIO_packetSet( RioStack_t *stack, uint32_t length, uint32_t *src);
 
/*******************************************************************************************
* Configuration-space access methods.
*******************************************************************************************/
 
/**
* \brief Read configuration space.
*
* \param[in] stack The stack to operate on.
* \param[in] offset The configuration space address to read.
* \return The data read on the configuration space address specified.
*
* This function reads a configuration space offset and returns the content of
* the entry.
*/
uint32_t RIO_readConfig( RioStack_t *stack, const uint32_t offset );
 
/**
* \brief Write configuration space.
*
* \param[in] stack The stack to operate on.
* \param[in] offset The configuration space address to write to.
* \param[in] data The data to write to the configuration space.
*
* This function writes to a configuration space offset and sets the
* content to the specified data.
*/
void RIO_writeConfig( RioStack_t *stack, const uint32_t offset, const uint32_t data);
 
/*******************************************************************************************
* Logical I/O MAINTENANCE-READ functions.
*******************************************************************************************/
 
/**
* \brief Send a maintenance read request.
*
* \param[in] stack The stack to operate on.
* \param[in] destid The device id of the destination end point.
* \param[in] tid The transaction id to be returned in the response.
* \param[in] hopCount The hop_count to set in the read request.
* \param[in] offset The byte address in the configuration space to read.
*
* This function creates and sends a maintenance read request packet.
*
* \note Call RIO_sendAvailable() before this function is called to make sure
* \note Call RIOSTACK_outboundQueueAvailable() before this function is called to make sure
* the outbound queue has transmission buffers available.
*/
#ifdef RIO_TRANSPARENT
void RIO_sendMaintenanceReadRequest(RioStack_t *stack, const uint16_t destid, const uint16_t srcid, const uint8_t tid,
const uint8_t hopCount, const uint32_t offset );
#else
void RIO_sendMaintenanceReadRequest(RioStack_t *stack, const uint16_t destid, const uint8_t tid,
const uint8_t hopCount, const uint32_t offset );
#endif
 
/**
* \brief Read a received maintenance read request.
*
* \param[in] stack The stack to operate on.
* \param[out] srcid The device id of the destination end point.
* \param[out] tid The transaction id to be returned in the response.
* \param[out] hopCount The hop_count to set in the read request.
* \param[out] offset The byte address in the configuration space to read.
*
* This function reads a received maintenance read request packet.
*
* \note In normal operational mode, the stack answers maintenance requests
* automatically without user intervention. This function should only be
* called if the stack is compiled in transparent mode.
* \note Use RIOSTACK_getStatus() to know when a packet is allowed to be transmitted.
*/
#ifdef RIO_TRANSPARENT
void RIO_receiveMaintenanceReadRequest(RioStack_t *stack, uint16_t *destid, uint16_t *srcid, uint8_t *tid,
uint8_t *hopCount, uint32_t *offset);
#else
void RIO_receiveMaintenanceReadRequest(RioStack_t *stack, uint16_t *srcid, uint8_t *tid,
uint8_t *hopCount, uint32_t *offset);
#endif
void RIOSTACK_setOutboundPacket(RioStack_t *stack, RioPacket_t *packet);
 
/**
* \brief Send a maintenance read response.
* \brief Clear inbound queue.
*
* \param[in] stack The stack to operate on.
* \param[in] destid The device id of the destination end point.
* \param[in] tid The transaction id to be returned in the response.
* \param[in] hopCount The hop_count to set in the read request.
* \param[in] data The data to send in the response.
*
* This function creates a maintanance read response packet that should be
* sent when a request is received.
*
* \note Call RIO_sendAvailable() before this function is called to make sure
* the outbound queue has transmission buffers available.
*
* \note In normal operational mode, the stack answers maintenance requests
* automatically without user intervention. This function should only be
* called if the stack is compiled in transparent mode.
* This function clears all pending packet in the inbound queue.
*/
#ifdef RIO_TRANSPARENT
void RIO_sendMaintenanceReadResponse( RioStack_t *stack, const uint16_t destid, const uint16_t srcid, const uint8_t tid,
const uint8_t hopCount, const uint32_t data);
#else
void RIO_sendMaintenanceReadResponse( RioStack_t *stack, const uint16_t destid, const uint8_t tid,
const uint8_t hopCount, const uint32_t data);
#endif
void RIOSTACK_clearInboundQueue(RioStack_t *stack);
 
/**
* \brief Read a received maintenance read response.
* \brief Get the number of pending inbound packets.
*
* \param[in] stack The stack to operate on.
* \param[out] srcid The device id of the source end point.
* \param[out] tid The transaction id in the response.
* \param[out] hopCount The hop_count set in the read response.
* \param[out] data The data in the response.
* \return Returns the number of pending inbound packets.
*
* This function reads a received maintanance read response packet.
* This function checks the inbound queue and returns the number of packets
* that has been received but not read by the user yet.
*/
#ifdef RIO_TRANSPARENT
void RIO_receiveMaintenanceReadResponse( RioStack_t *stack, uint16_t *destid, uint16_t *srcid, uint8_t *tid,
uint8_t *hopCount, uint32_t *data);
#else
void RIO_receiveMaintenanceReadResponse( RioStack_t *stack, uint16_t *srcid, uint8_t *tid,
uint8_t *hopCount, uint32_t *data);
#endif
uint8_t RIOSTACK_getInboundQueueLength(RioStack_t *stack);
 
/*******************************************************************************************
* Logical I/O MAINTENANCE-WRITE functions.
*******************************************************************************************/
 
/**
* \brief Send a maintenance write request.
* \brief Get the number of available inbound packets.
*
* \param[in] stack The stack to operate on.
* \param[in] destid The device id of the destination end point.
* \param[in] tid The transaction id to be returned in the response.
* \param[in] hopCount The hop_count to set in the write request.
* \param[in] offset The byte address in the configuration space to write to.
* \param[in] data The data to write in configuration space.
* \return Returns the number of available inbound packets.
*
* This function creates and sends a maintenance write request packet.
*
* \note Call RIO_sendAvailable() before this function is called to make sure
* the outbound queue has transmission buffers available.
* This function checks the inbound queue and returns the number of packets
* that can be received without the queue is full.
*/
#ifdef RIO_TRANSPARENT
void RIO_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 );
#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 );
#endif
uint8_t RIOSTACK_getInboundQueueAvailable(RioStack_t *stack);
 
/**
* \brief Read a received maintenance write request.
* \brief Get, remove and return a packet from the inbound queue.
*
* \param[in] stack The stack to operate on.
* \param[out] destid The device id of the destination end point.
* \param[out] tid The transaction id to be returned in the response.
* \param[out] hopCount The hop_count to set in the write request.
* \param[out] offset The byte address in the configuration space to write to.
* \param[out] data The data to write in configuration space.
* \param[in] packet The packet to receive to.
*
* This function creates and sends a maintenance write request packet. The reply
* is received using RIO_eventPoll-function and RIO_packetTid together with the return
* value from this function.
*
* \note Call RIO_sendAvailable() before this function is called to make sure
* the outbound queue has transmission buffers available.
*
* \note In normal operational mode, the stack answers maintenance requests
* automatically without user intervention. This function should only be
* called if the stack is compiled in transparent mode.
* This function moves a packet from the inbound packet queue to the location of the packet
* in the argument list.
*/
#ifdef RIO_TRANSPARENT
void RIO_receiveMaintenanceWriteRequest( RioStack_t *stack, uint16_t *destid, uint16_t *srcid, uint8_t *tid,
uint8_t *hopCount, uint32_t *offset, uint32_t *data );
#else
void RIO_receiveMaintenanceWriteRequest( RioStack_t *stack, uint16_t *srcid, uint8_t *tid,
uint8_t *hopCount, uint32_t *offset, uint32_t *data );
#endif
void RIOSTACK_getInboundPacket(RioStack_t *stack, RioPacket_t *packet);
 
/**
* \brief Send a maintenance write response.
*
* \param[in] stack The stack to operate on.
* \param[in] destid The device id of the destination end point.
* \param[in] tid The transaction id to be returned.
* \param[in] hopCount The hop_count to set in the write response.
*
* This function creates a maintanance write response packet from a pending
* maintenance read request. The generated packet are placed in the outbound
* packet queue.
*
* \note In normal operational mode, the stack answers maintenance requests
* automatically without user intervention. This function should only be
* called if the stack is compiled in transparent mode.
*/
#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);
#else
void RIO_sendMaintenanceWriteResponse( RioStack_t *stack, const uint16_t destid, const uint8_t tid,
const uint8_t hopCount);
#endif
 
/**
* \brief Read a received maintenance write response.
*
* \param[in] stack The stack to operate on.
* \param[out] srcid The device id of the source end point.
* \param[out] tid The transaction id read in the response.
* \param[out] hopCount The hop_count read in the write response.
*
* This function creates a maintanance write response packet from a pending
* maintenance read request. The generated packet are placed in the outbound
* packet queue.
*
* \note In normal operational mode, the stack answers maintenance requests
* automatically without user intervention. This function should only be
* called if the stack is compiled in transparent mode.
*/
#ifdef RIO_TRANSPARENT
void RIO_receiveMaintenanceWriteResponse( RioStack_t *stack, uint16_t *destid, uint16_t *srcid, uint8_t *tid,
uint8_t *hopCount);
#else
void RIO_receiveMaintenanceWriteResponse( RioStack_t *stack, uint16_t *srcid, uint8_t *tid,
uint8_t *hopCount);
#endif
 
/*******************************************************************************************
* Logical I/O NWRITE/NWRITER functions.
*******************************************************************************************/
 
/**
* \brief Send an NWRITE request to write a byte array.
*
* \param[in] stack The stack to operate on.
* \param[in] destid The device id of the destination end point.
* \param[in] address The byte address to write to.
* \param[in] dataLength The number of bytes to write. The largest allowed size is 256 bytes.
* \param[in] data A pointer to the array of bytes to write.
*
* This function creates and sends an NWRITE request packet to write a number
* of bytes to a specified address. No reply will be received.
*
* \note The address is a byte address, not a word address.
*
* \note Call RIO_sendAvailable() before this function is called to make sure
* the outbound queue has transmission buffers available.
*
* \note Not all combinations of addresses and sizes are allowed. See table below:
* -------------------------------------------------------------------------------------
* size | valid byte in double-word
* -------------------------------------------------------------------------------------
* 1 | 10000000, 01000000, 00100000, 00010000, 00001000, 00000100, 00000010, 00000001
* 2 | 11000000, 00110000, 00001100, 00000011
* 3 | 11100000, 00000111
* 4 | 11110000, 00001111
* 5 | 11111000, 00011111
* 6 | 11111100, 00111111
* 7 | 11111110, 01111111
* 8*N | 11111111 (N={1...32})
* --------------------------------------------------------------------------------------
* See RapidIO 2.2 part1 table 4-4 for more details. Asserts will occurr if an invalid
* combination is detected.
*/
#ifdef RIO_TRANSPARENT
void RIO_sendNwrite( RioStack_t *stack, const uint16_t destid, const uint16_t srcid,
const uint32_t address, const uint16_t dataLength, const uint8_t *data );
#else
void RIO_sendNwrite( RioStack_t *stack, const uint16_t destid,
const uint32_t address, const uint16_t dataLength, const uint8_t *data );
#endif
 
/**
* \brief Send an NWRITER request to write a byte array.
*
* \param[in] stack The stack to operate on.
* \param[in] destid The device id of the destination end point.
* \param[in] tid The transaction id to set in the response.
* \param[in] address The byte address to write to.
* \param[in] dataLength The number of bytes to write. The largest allowed size is 256 bytes.
* \param[in] data A pointer to the array of bytes to write.
*
* This function creates and sends an NWRITE request packet to write a number
* of bytes to a specified address. A reply will be received when the write has been completed.
*
* \note The address is a byte address, not a word address.
*
* \note Call RIO_sendAvailable() before this function is called to make sure
* the outbound queue has transmission buffers available.
*
* \note Not all combinations of addresses and sizes are allowed. See table below:
* -------------------------------------------------------------------------------------
* size | valid byte in double-word
* -------------------------------------------------------------------------------------
* 1 | 10000000, 01000000, 00100000, 00010000, 00001000, 00000100, 00000010, 00000001
* 2 | 11000000, 00110000, 00001100, 00000011
* 3 | 11100000, 00000111
* 4 | 11110000, 00001111
* 5 | 11111000, 00011111
* 6 | 11111100, 00111111
* 7 | 11111110, 01111111
* 8*N | 11111111 (N={1...32})
* --------------------------------------------------------------------------------------
* See RapidIO 2.2 part1 table 4-4 for more details. Asserts will occurr if an invalid
* combination is detected.
*/
#ifdef RIO_TRANSPARENT
void RIO_sendNwriteR( RioStack_t *stack, const uint16_t destid, const uint16_t srcid, const uint8_t tid,
const uint32_t address, const uint16_t dataLength, const uint8_t *data );
#else
void RIO_sendNwriteR( RioStack_t *stack, const uint16_t destid, const uint8_t tid,
const uint32_t address, const uint16_t dataLength, const uint8_t *data );
#endif
 
/**
* \brief Read a received NWRITE/NWRITER request.
*
* \param[in] stack The stack to operate on.
* \param[out] srcid The device id of the destination end point.
* \param[out] tid The transaction id in the response. Undefined value when NWRITE is read.
* \param[out] address The byte address to write to.
* \param[in] dataLength The number of bytes allocated in data.
* \param[in] data A pointer to the array of bytes to copy to.
* \return The number of bytes copied into data.
*
* This function reads a received NWRITE/NWRITER request packet to write a number
* of bytes to a specified address. Used to receive both NWRITE and NWRITER. The payload
* of the packet is copied into the provided buffer pointed to by data.
*
* \note The address is a byte address, not a word address.
*/
#ifdef RIO_TRANSPARENT
uint16_t RIO_receiveNwrite( RioStack_t *stack, uint16_t *destid, uint16_t *srcid, uint8_t *tid,
uint32_t *address, const uint16_t dataLength, uint8_t *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 );
#endif
 
/*******************************************************************************************
* Logical I/O NREAD functions.
*******************************************************************************************/
 
/**
* \brief Send an NREAD request to read a byte array.
*
* \param[in] stack The stack to operate on.
* \param[in] destid The device id of the destination end point.
* \param[in] tid The transaction id to set in the response.
* \param[in] address The byte address to write to.
* \param[in] dataLength The number of bytes to write. The largest allowed size is 256 bytes.
*
* This function creates and sends an NWRITE request packet to write a number
* of bytes to a specified address. A reply will be received when the write has been completed.
*
* \note The address is a byte address, not a word address.
*
* \note Call RIO_sendAvailable() before this function is called to make sure
* the outbound queue has transmission buffers available.
*
* \note Not all combinations of address and length are allowed. See table below:
* -------------------------------------------------------------------------------------
* size | valid byte in double-word
* -------------------------------------------------------------------------------------
* 1 | 10000000, 01000000, 00100000, 00010000, 00001000, 00000100, 00000010, 00000001
* 2 | 11000000, 00110000, 00001100, 00000011
* 3 | 11100000, 00000111
* 4 | 11110000, 00001111
* 5 | 11111000, 00011111
* 6 | 11111100, 00111111
* 7 | 11111110, 01111111
* -------------------------------------------------------------------------------------
* For full double-words the following byte sizes are allowed:
* 8, 16, 32, 64, 96, 128, 160, 192, 224, 256
* --------------------------------------------------------------------------------------
* See RapidIO 2.2 part1 table 4-4 for more details. Asserts will occurr if an invalid
* combination is detected.
*/
#ifdef RIO_TRANSPARENT
void RIO_sendNread( RioStack_t *stack, const uint16_t destid, const uint16_t srcid, const uint8_t tid,
const uint32_t address, const uint16_t dataLength);
#else
void RIO_sendNread( RioStack_t *stack, const uint16_t destid, const uint8_t tid,
const uint32_t address, const uint16_t dataLength);
#endif
 
/**
* \brief Read a received NREAD request.
*
* \param[in] stack The stack to operate on.
* \param[out] srcid The device id of the destination end point.
* \param[out] tid The transaction id in the response.
* \param[out] address The byte address to write to.
* \param[in] dataLength The number of bytes allocated in data.
*
* This function reads a received NREAD request packet to read a number
* of bytes at a specified address.
*
* \note The address is a byte address, not a word address.
*/
#ifdef RIO_TRANSPARENT
void RIO_receiveNread( RioStack_t *stack, uint16_t *destid, uint16_t *srcid, uint8_t *tid,
uint32_t *address, uint16_t *dataLength);
#else
void RIO_receiveNread( RioStack_t *stack, uint16_t *srcid, uint8_t *tid,
uint32_t *address, uint16_t *dataLength);
#endif
 
/*******************************************************************************************
* Logical I/O RESPONSE-DONE-PAYLOAD, RESPONSE-DONE, RESPONSE-RETRY and RESPONSE-ERROR
* functions.
*******************************************************************************************/
 
/**
* \brief Send a response with data payload.
*
* \param[in] stack The stack to operate on.
* \param[in] destid The destination identifier of the response.
* \param[in] tid The transaction identifier for the reply. It should correspond to
* the tid in the received packet for which this response is sent.
* \param[in] address The byte address that was read. It should correspond to
* the address in the received packet for which this response is sent.
* \param[in] dataLength The size of the data buffer to return in the reply. It
* should correspond to the dataLength in the received packet for which this response
* is sent.
* \param[in] data The data buffer to return in the reply.
*
* This function creates a response packet with the specified destination
* identifier, transaction id and data payload. The generated packet are placed
* in the outbound packet queue.
*
* \note Call RIO_sendAvailable() before this function is called to make sure
* the outbound queue has transmission buffers available.
*/
#ifdef RIO_TRANSPARENT
void RIO_sendResponseDonePayload( RioStack_t *stack, const uint16_t destid, const uint16_t srcid, const uint8_t tid,
const uint32_t address, const uint16_t dataLength, const uint8_t *data);
#else
void RIO_sendResponseDonePayload( RioStack_t *stack, const uint16_t destid, const uint8_t tid,
const uint32_t address, const uint16_t dataLength, const uint8_t *data);
#endif
 
/**
* \brief Read payload from a response with payload.
*
* \param[in] stack The stack to operate on.
* \param[out] srcid The device id of the destination end point.
* \param[out] tid The transaction id in the response.
* \param[in] address The byte address that was read. It should correspond to
* the address in the received packet for which this response is sent.
* \param[in] dataLength The size of the data buffer to return in the reply. It
* should correspond to the dataLength in the received packet for which this response
* is sent.
* \param[in] data Pointer to a buffer to where the data in the response will be copied.
* \return The number of bytes copied from the data payload contained in the response.
*
* This function reads a response packet and returns a the byte payload contained within.
*/
#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 );
#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 );
#endif
 
/**
* \brief Send a response.
*
* \param[in] stack The stack to operate on.
* \param[in] destid The device identifier of the target to send the response to.
* \param[in] tid The transaction id to send the response for. This should be the
* same value as the packet that this response was received with.
*
* This function is used to send a response indicating a successfull
* completion in reply to a previously received packet.
*
* \note Call RIO_sendAvailable() before this function is called to make sure
* the outbound queue has transmission buffers available.
*/
#ifdef RIO_TRANSPARENT
void RIO_sendResponseDone( RioStack_t *stack, const uint16_t destid, const uint16_t srcid, const uint8_t tid );
 
#else
void RIO_sendResponseDone( RioStack_t *stack, const uint16_t destid, const uint8_t tid );
 
#endif
/**
* \brief Read a received response.
*
* \param[in] stack The stack to operate on.
* \param[out] srcid The device identifier of the source of the response.
* \param[out] tid The transaction id in the response.
*
* This function is used to read a received response indicating a successfull
* completion in reply to a previously sent packet.
*
* \note Call RIO_sendAvailable() before this function is called to make sure
* the outbound queue has transmission buffers available.
*/
#ifdef RIO_TRANSPARENT
void RIO_receiveResponseDone( RioStack_t *stack, uint16_t *destid, uint16_t *srcid, uint8_t *tid );
 
#else
void RIO_receiveResponseDone( RioStack_t *stack, uint16_t *srcid, uint8_t *tid );
 
#endif
/**
* \brief Send a retry response.
*
* \param[in] stack The stack to operate on.
* \param[in] destid The device identifier of the target to send the response to.
* \param[in] tid The transaction id to send the response for. This should be the
* same value as the packet that this response was received with.
*
* This function is used to send a response indicating a busy resource
* in reply to a previously received packet.
*
* \note Call RIO_sendAvailable() before this function is called to make sure
* the outbound queue has transmission buffers available.
*/
#ifdef RIO_TRANSPARENT
void RIO_sendResponseRetry( RioStack_t *stack, const uint16_t destid, const uint16_t srcid, const uint8_t tid );
 
#else
void RIO_sendResponseRetry( RioStack_t *stack, const uint16_t destid, const uint8_t tid );
 
#endif
/**
* \brief Read a received retry response.
*
* \param[in] stack The stack to operate on.
* \param[out] srcid The device identifier of the source of the response.
* \param[out] tid The transaction id in the response.
*
* This function is used to read a received response indicating a retry condition
* in reply to a previously sent packet.
*
* \note Call RIO_sendAvailable() before this function is called to make sure
* the outbound queue has transmission buffers available.
*/
#ifdef RIO_TRANSPARENT
void RIO_receiveResponseRetry( RioStack_t *stack, uint16_t *destid, uint16_t *srcid, uint8_t *tid );
 
#else
void RIO_receiveResponseRetry( RioStack_t *stack, uint16_t *srcid, uint8_t *tid );
 
#endif
/**
* \brief Send a error response.
*
* \param[in] stack The stack to operate on.
* \param[in] destid The device identifier of the target to send the response to.
* \param[in] tid The transaction id to send the response for. This should be the
* same value as the packet that this response was received with.
*
* This function is used to send a response indicating a busy resource
* in reply to a previously received packet.
*
* \note Call RIO_sendAvailable() before this function is called to make sure
* the outbound queue has transmission buffers available.
*/
#ifdef RIO_TRANSPARENT
void RIO_sendResponseError( RioStack_t *stack, const uint16_t destid, const uint16_t srcid, const uint8_t tid );
#else
void RIO_sendResponseError( RioStack_t *stack, const uint16_t destid, const uint8_t tid );
#endif
 
/**
* \brief Read a received error response.
*
* \param[in] stack The stack to operate on.
* \param[out] srcid The device identifier of the source of the response.
* \param[out] tid The transaction id in the response.
*
* This function is used to read a received response indicating an error condition
* in reply to a previously sent packet.
*
* \note Call RIO_sendAvailable() before this function is called to make sure
* the outbound queue has transmission buffers available.
*/
#ifdef RIO_TRANSPARENT
void RIO_receiveResponseError( RioStack_t *stack, uint16_t *destid, uint16_t *srcid, uint8_t *tid );
#else
void RIO_receiveResponseError( RioStack_t *stack, uint16_t *srcid, uint8_t *tid );
#endif
 
/*******************************************************************************************
* Logical message passing DOORBELL and MESSAGE functions.
*******************************************************************************************/
 
/**
* \brief Send a doorbell.
*
* \param[in] stack The stack to operate on.
* \param[in] destid The device id of the destination end point.
* \param[in] tid The transaction id to be returned in the response.
* \param[in] info The information to send with the doorbell.
* \return An identifier that maps to the doorbell response that are received using
* RIO_packetTid.
*
* This function is used to send a doorbell to a remote endpoint. A response
* should be sent when the doorbell has been processed using the RIO_sendResponseDone(),
* RIO_sendResponseRetry() or RIO_sendResponseError() functions.
*
* \note Call RIO_sendAvailable() before this function is called to make sure
* the outbound queue has transmission buffers available.
*/
#ifdef RIO_TRANSPARENT
void RIO_sendDoorbell( RioStack_t *stack, const uint16_t destid, const uint16_t srcid, const uint8_t tid,
const uint16_t info);
#else
void RIO_sendDoorbell( RioStack_t *stack, const uint16_t destid, const uint8_t tid,
const uint16_t info);
#endif
 
/**
* \brief Read a received a doorbell.
*
* \param[in] stack The stack to operate on.
* \param[out] srcid The device id of the source end point.
* \param[out] tid The transaction id to be returned in the response.
* \param[out] info The information to send with the doorbell.
*
* This function is used to read a received doorbell from a remote endpoint.
*/
#ifdef RIO_TRANSPARENT
void RIO_receiveDoorbell( RioStack_t *stack, uint16_t *destid, uint16_t *srcid, uint8_t *tid,
uint16_t *info);
#else
void RIO_receiveDoorbell( RioStack_t *stack, uint16_t *srcid, uint8_t *tid,
uint16_t *info);
#endif
 
/**
* \brief Send a message.
*
* \param[in] stack The stack to operate on.
* \param[in] destid The device id of the destination endpoint.
* \param[in] mailbox The mailbox to send the message to.
* \param[in] dataLength The size of the buffer to copy to.
* \param[in] buffer A byte pointer to the message payload to send.
*
* This function sends a single packet message to a destination mailbox.
*
* \note Mailbox 0-15 can support multipacket (when support is enabled)
* messages and 16-255 can only handle singlepacket messages. Dont use mailbox
* 0-15 unless you know that there will be large packets transmitted on it.
*/
#ifdef RIO_TRANSPARENT
void RIO_sendMessage( RioStack_t *stack, const uint16_t destid, const uint16_t srcid, const uint8_t mailbox,
const uint16_t dataLength, const uint8_t *data );
#else
void RIO_sendMessage( RioStack_t *stack, const uint16_t destid, const uint8_t mailbox,
const uint16_t dataLength, const uint8_t *data );
#endif
 
/**
* \brief Read a received message.
*
* \param[in] stack The stack to operate on.
* \param[out] srcid The device id of the source endpoint.
* \param[out] mailbox The mailbox the message is received on.
* \param[in] dataLength The size of the buffer to copy to.
* \param[in] data A byte pointer to the message payload to read.
* \return The number of bytes copied. A zero will be returned if unable to copy.
*
* This function reads a single packet message to a destination mailbox.
*/
#ifdef RIO_TRANSPARENT
uint16_t RIO_receiveMessage( RioStack_t *stack, uint16_t *destid, uint16_t *srcid, uint8_t *mailbox,
const uint16_t dataLength, uint8_t *data );
#else
uint16_t RIO_receiveMessage( RioStack_t *stack, uint16_t *srcid, uint8_t *mailbox,
const uint16_t dataLength, uint8_t *data );
#endif
 
/*******************************************************************************************
* Logical message passing MESSAGE-RESPONSE functions.
*******************************************************************************************/
 
/**
* \brief Send a message response.
*
* \param[in] stack The stack to operate on.
* \param[in] destid The device identifier of the target to send the response to.
* \param[in] mailbox The mailbox to send the response to.
*
* This function is used to send a message response indicating a successfull
* completion in reply to a previously received message.
*
* \note Call RIO_sendAvailable() before this function is called to make sure
* the outbound queue has transmission buffers available.
*/
#ifdef RIO_TRANSPARENT
void RIO_sendMessageResponseDone( RioStack_t *stack, const uint16_t destid, const uint16_t srcid, const uint8_t mailbox );
#else
void RIO_sendMessageResponseDone( RioStack_t *stack, const uint16_t destid, const uint8_t mailbox );
#endif
 
/**
* \brief Read a received message response.
*
* \param[in] stack The stack to operate on.
* \param[out] srcid The device identifier of the source endpoint.
* \param[out] mailbox The mailbox the response is for.
*
* This function is used to read a received message response indicating a successfull
* completion in reply to a previously sent message.
*/
#ifdef RIO_TRANSPARENT
void RIO_receiveMessageResponseDone( RioStack_t *stack, uint16_t *destid, uint16_t *srcid, uint8_t *mailbox );
#else
void RIO_receiveMessageResponseDone( RioStack_t *stack, uint16_t *srcid, uint8_t *mailbox );
#endif
 
/**
* \brief Send a message retry response.
*
* \param[in] stack The stack to operate on.
* \param[in] destid The device identifier of the target to send the response to.
* \param[in] mailbox The mailbox to send the response to.
*
* This function is used to send a message response indicating a busy resource
* in reply to a previously received message.
*
* \note Call RIO_sendAvailable() before this function is called to make sure
* the outbound queue has transmission buffers available.
*/
#ifdef RIO_TRANSPARENT
void RIO_sendMessageResponseRetry( RioStack_t *stack, const uint16_t destid, const uint16_t srcid, const uint8_t mailbox );
#else
void RIO_sendMessageResponseRetry( RioStack_t *stack, const uint16_t destid, const uint8_t mailbox );
#endif
 
/**
* \brief Read a received message retry response.
*
* \param[in] stack The stack to operate on.
* \param[out] srcid The device identifier of the source endpoint.
* \param[out] mailbox The mailbox the response is for.
*
* This function is used to read a received message retry response indicating a retry
* condition in reply to a previously sent message.
*/
#ifdef RIO_TRANSPARENT
void RIO_receiveMessageResponseRetry( RioStack_t *stack, uint16_t *destid, uint16_t *srcid, uint8_t *mailbox );
#else
void RIO_receiveMessageResponseRetry( RioStack_t *stack, uint16_t *srcid, uint8_t *mailbox );
#endif
 
/**
* \brief Send a message error response.
*
* \param[in] stack The stack to operate on.
* \param[in] destid The device identifier of the target to send the response to.
* \param[in] mailbox The mailbox to send the response to.
*
* This function is used to send a message response indicating a busy resource
* in reply to a previously received message.
*
* \note Call RIO_sendAvailable() before this function is called to make sure
* the outbound queue has transmission buffers available.
*/
#ifdef RIO_TRANSPARENT
void RIO_sendMessageResponseError( RioStack_t *stack, const uint16_t destid, const uint16_t srcid, const uint8_t mailbox );
#else
void RIO_sendMessageResponseError( RioStack_t *stack, const uint16_t destid, const uint8_t mailbox );
#endif
 
/**
* \brief Read a received message error response.
*
* \param[in] stack The stack to operate on.
* \param[out] srcid The device identifier of the source endpoint.
* \param[out] mailbox The mailbox the response is for.
*
* This function is used to read a received message error response indicating an error
* condition in reply to a previously sent message.
*/
#ifdef RIO_TRANSPARENT
void RIO_receiveMessageResponseError( RioStack_t *stack, uint16_t *destid, uint16_t *srcid, uint8_t *mailbox );
#else
void RIO_receiveMessageResponseError( RioStack_t *stack, uint16_t *srcid, uint8_t *mailbox );
#endif
 
/*******************************************************************************************
* Port functions (backend API towards physical device)
*******************************************************************************************/
 
1286,10 → 393,10
* \param[in] time The current time without unit.
*
* This function indicates to the stack the current time and this is used internally
* to calculate when a packet timeout should be triggered. Use this together with RIO_setPortTimeout()
* to calculate when a packet timeout should be triggered. Use this together with RIOSTACK_setPortTimeout()
* to allow for the stack to handle timeouts.
*/
void RIO_portSetTime( RioStack_t *stack, const uint32_t time);
void RIOSTACK_portSetTime( RioStack_t *stack, const uint32_t time);
 
/**
* \brief Set a port timeout limit.
1298,12 → 405,12
* \param[in] time The time out threshold.
*
* The time to wait for a response from the link partner. The unit of the
* timeout value should be the same as the time used in RIO_setPortTime().
* timeout value should be the same as the time used in RIOSTACK_setPortTime().
*
* This function is used to set a timeout threshold value and is used to know when
* an acknowledge should have been received from a link partner.
*/
void RIO_portSetTimeout( RioStack_t *stack, const uint32_t time);
void RIOSTACK_portSetTimeout( RioStack_t *stack, const uint32_t time);
 
/**
* \brief Set a ports status.
1319,7 → 426,7
* encoding/decoding loses synchronization then this function should be called
* with an argument equal to zero to force the stack to resynchronize the link.
*/
void RIO_portSetStatus( RioStack_t *stack, const uint8_t initialized );
void RIOSTACK_portSetStatus( RioStack_t *stack, const uint8_t initialized );
 
/**
* \brief Add a new symbol to the RapidIO stack.
1331,7 → 438,7
* symbols will be concatenated to form packets that can be accessed using other
* functions.
*/
void RIO_portAddSymbol( RioStack_t *stack, const RioSymbol s );
void RIOSTACK_portAddSymbol( RioStack_t *stack, const RioSymbol_t s );
 
/**
* \brief Get the next symbol to transmit on a port.
1342,395 → 449,8
* This function is used to fetch new symbols to transmit on a port. Packets that
* are inserted are split into symbols that are accessed with this function.
*/
RioSymbol RIO_portGetSymbol( RioStack_t *stack );
RioSymbol_t RIOSTACK_portGetSymbol( RioStack_t *stack );
 
 
/*******************************************************************************************
* DEPRECATED
* Will be removed.
*******************************************************************************************/
 
/**
* \brief Read packet transaction identification.
* \param[in] stack The stack to operate on.
* \return The identification of the packet. This matches a transaction identifier
* that are set as argument when a send-function are called.
*
* This function is used to correlate a sent packet to a received response.
*
* \note This function cannot be used when receiving messages on mailboxes. Use
* RIO_readMessageMailbox() instead.
*/
uint8_t RIO_packetTid( RioStack_t *stack );
 
/**
* \brief Read packet destination identification.
* \param[in] stack The stack to operate on.
* \return The destination device identifier of the packet.
*
* This function is used to get the destination device identifier of a received packet.
*/
uint16_t RIO_packetDestination( RioStack_t *stack );
 
/**
* \brief Read packet source identification.
* \param[in] stack The stack to operate on.
* \return The source device identifier of the packet.
*
* This function is used to get the source device identifier of a received packet.
*/
uint16_t RIO_packetSource( RioStack_t *stack );
 
/**
* \brief Read a maintenance read request hop count value.
*
* \param[in] stack The stack to operate on.
* \return The hopcount value of the packet.
*
* This function returns the hop count value of a received maintenance read
* request packet.
*
* \note In normal operational mode, the stack answers maintenance requests
* automatically without user intervention. This function should only be
* called if the stack is compiled in transparent mode.
*/
uint8_t RIO_readMaintenanceReadRequestHop( RioStack_t *stack );
 
/**
* \brief Read a maintenance read request offset value.
*
* \param[in] stack The stack to operate on.
* \return The offset value of the packet.
*
* This function returns the offset value of a received maintenance read
* request packet.
*
* \note In normal operational mode, the stack answers maintenance requests
* automatically without user intervention. This function should only be
* called if the stack is compiled in transparent mode.
*/
uint32_t RIO_readMaintenanceReadRequestOffset( RioStack_t *stack );
 
/**
* \brief Read a maintenance read response hop count value.
*
* \param[in] stack The stack to operate on.
* \return The hop count value of the packet.
*
* This function returns the hop count value of a received maintenance read
* response packet.
*
* \note In normal operational mode, the stack answers maintenance requests
* automatically without user intervention. This function should only be
* called if the stack is compiled in transparent mode.
*/
uint8_t RIO_readMaintenanceReadResponseHop( RioStack_t *stack );
 
/**
* \brief Read a maintenance read response offset value.
*
* \param[in] stack The stack to operate on.
* \return The offset value of the packet.
*
* This function returns the offset value of a received maintenance read
* response packet.
*
* \note In normal operational mode, the stack answers maintenance requests
* automatically without user intervention. This function should only be
* called if the stack is compiled in transparent mode.
*/
uint32_t RIO_readMaintenanceReadResponse( RioStack_t *stack );
 
/**
* \brief Read a maintenance write request hop count value.
*
* \param[in] stack The stack to operate on.
* \return The hopcount value of the packet.
*
* This function returns the hop count value of a received maintenance write
* request packet.
*
* \note In normal operational mode, the stack answers maintenance requests
* automatically without user intervention. This function should only be
* called if the stack is compiled in transparent mode.
*/
uint8_t RIO_readMaintenanceWriteRequestHop( RioStack_t *stack );
 
/**
* \brief Read a maintenance write request offset value.
*
* \param[in] stack The stack to operate on.
* \return The offset value of the packet.
*
* This function returns the offset value of a received maintenance write
* request packet.
*
* \note In normal operational mode, the stack answers maintenance requests
* automatically without user intervention. This function should only be
* called if the stack is compiled in transparent mode.
*/
uint32_t RIO_readMaintenanceWriteRequestOffset( RioStack_t *stack );
 
/**
* \brief Read a maintenance write request data value.
*
* \param[in] stack The stack to operate on.
* \return The data value of the packet.
*
* This function returns the data value of a received maintenance write
* request packet.
*
* \note In normal operational mode, the stack answers maintenance requests
* automatically without user intervention. This function should only be
* called if the stack is compiled in transparent mode.
*/
uint32_t RIO_readMaintenanceWriteRequestData( RioStack_t *stack );
 
/**
* \brief Read a maintenance write response hop count value.
*
* \param[in] stack The stack to operate on.
* \return The hopcount value of the packet.
*
* This function returns the hop count value of a received maintenance write
* response packet.
*
* \note In normal operational mode, the stack answers maintenance requests
* automatically without user intervention. This function should only be
* called if the stack is compiled in transparent mode.
*/
uint8_t RIO_readMaintenanceWriteResponseHop( RioStack_t *stack );
 
/**
* \brief Send an NWRITE request to write a byte.
*
* \param[in] stack The stack to operate on.
* \param[in] destid The device id of the destination end point.
* \param[in] address The byte address to write to.
* \param[in] data The byte data to write.
* This function creates and sends an NWRITE request packet. No reply will be received.
*
* \note The address is a byte address, not a word address.
*
* \note Call RIO_sendAvailable() before this function is called to make sure
* the outbound queue has transmission buffers available.
*/
void RIO_sendNwrite8( RioStack_t *stack, const uint16_t destid, const uint32_t address, const uint8_t data );
 
/**
* \brief Send an NWRITE_R request to write a byte.
*
* \param[in] stack The stack to operate on.
* \param[in] destid The device id of the destination end point.
* \param[in] tid The transaction id to be returned in the response.
* \param[in] address The byte address to write to.
* \param[in] data The byte data to write.
* \return An identifier that maps to the packet transaction identifier that are received using
* RIO_packetTid.
*
* This function creates and sends an NWRITE_R request packet. A reply should be received
* when the write has been completed.
*
* \note The address is a byte address, not a word address.
*
* \note Call RIO_sendAvailable() before this function is called to make sure
* the outbound queue has transmission buffers available.
*/
void RIO_sendNwriteR8( RioStack_t *stack, const uint16_t destid, const uint8_t tid, const uint32_t address, const uint8_t data );
 
/**
* \brief Get the byte address from an NWRITE or NWRITE_R packet.
*
* \param[in] stack The stack to operate on.
* \return The byte address contained in the NWRITE or NWRITE_R packet.
*
* This function reads a received an NWRITE or NWRITE_R request packet and fetches the address
* contained within.
*
* \note The address is a byte address, not a word address.
*/
uint32_t RIO_readNwriteAddress8( RioStack_t *stack );
 
/**
* \brief Get the number of bytes to write from an NWRITE or NWRITE_R packet.
*
* \param[in] stack The stack to operate on.
* \return The number of bytes requested to be written in a NWRITE or NWRITE_R packet.
*
* This function reads a received an NWRITE or NWRITE_R request packet and fetches the
* number of bytes requested to be written.
*
* \note The returned size is the number of bytes.
*/
uint8_t RIO_readNwriteSize8( RioStack_t *stack );
 
/**
* \brief Get the byte to write from a NWRITE or NWRITE_R packet.
*
* \param[in] stack The stack to operate on.
* \return The byte requested to be written in a NWRITE or NWRITE_R packet.
*
* This function reads a received an NWRITE or NWRITE_R request packet and fetches the
* byte to write.
*/
uint8_t RIO_readNwritePayload8( RioStack_t *stack );
 
 
/**
* \brief Send a NREAD request to read a byte.
*
* \param[in] stack The stack to operate on.
* \param[in] destid The device id of the destination end point.
* \param[in] tid The transaction id to be returned in the response.
* \param[in] address The byte address to read.
* \return An identifier that maps to the packet identifier that are received using
* RIO_packetTid.
*
* This function creates and sends an NREAD request packet. The response packet will
* contain one byte of data. The reply is received using RIO_readResponseDone8().
*
* \note The address is a byte address, not a word address.
*
* \note Call RIO_sendAvailable() before this function is called to make sure
* the outbound queue has transmission buffers available.
*/
void RIO_sendNread8( RioStack_t *stack, const uint16_t destid, const uint8_t tid, const uint32_t address );
 
 
/**
* \brief Get the byte address from a NREAD packet.
*
* \param[in] stack The stack to operate on.
* \return The byte address contained in a NREAD packet.
*
* This function reads a received an NREAD request packet and fetches the address
* contained within.
*
* \note The address is a byte address, not a word address.
*/
uint32_t RIO_readNreadAddress8( RioStack_t *stack );
 
/**
* \brief Get the number of bytes to read from a NREAD packet.
*
* \param[in] stack The stack to operate on.
* \return The number of bytes requested to read in a NREAD packet.
*
* This function reads a received an NREAD request packet and fetches the
* number of bytes to return in the reply.
*
* \note The returned size is the number of bytes.
*/
uint8_t RIO_readNreadSize8( RioStack_t *stack );
 
/**
* \brief Get a doorbell info field.
*
* \param[in] stack The stack to operate on.
* \return The info field of a doorbell.
*
* This function is used to read and return the info field of a received doorbell.
*/
uint16_t RIO_readDoorbellInfo( RioStack_t *stack );
 
/**
* \brief Send a byte message.
*
* \param[in] stack The stack to operate on.
* \param[in] destid The device identifier of the target to send the message to.
* \param[in] mbox The mailbox to send the message to.
* \param[in] size The number of bytes to send.
* \param[in] data A pointer to an array of bytes to send. The parameter size indicates
* the number of bytes to send.
*
* This functions sends a message to a mailbox in an end-point target. A message response
* should be sent when the message has been processed using the RIO_sendMessageResponseDone(),
* RIO_sendMessageResponseRetry() or RIO_sendMessageResponseError() functions.
*
* \note All sizes that are transmitted are even double words. If 48-bits are
* sent then 64 bits will be received on the other side with the last bits
* padded to zero.
*
* \note Call RIO_sendAvailable() before this function is called to make sure
* the outbound queue has transmission buffers available.
*/
void RIO_sendMessage8( RioStack_t *stack, const uint16_t destid, const uint8_t mbox, const uint16_t size, const uint8_t *data );
 
/**
* \brief Read a received message mailbox.
*
* \param[in] stack The stack to operate on.
* \return The mailbox of a received message.
*
* This function returns the mailbox of an incoming message.
*/
uint8_t RIO_readMessageMbox( RioStack_t *stack );
 
/**
* \brief Read a received message payload size in bytes.
*
* \param[in] stack The stack to operate on.
* \return The size in bytes of the received message payload.
*
* This function returns the number of bytes that was received in
* an incoming message.
*
* \note All sizes that are actually transmitted are even double words. If
* 48-bits are sent then 64 bits will be received on the other side with
* the last bits padded to zero.
*/
uint16_t RIO_readMessageSize8( RioStack_t *stack );
 
/**
* \brief Get the payload of a received message.
*
* \param[in] stack The stack to operate on.
* \param[out] buffer A byte pointer to where to place the payload.
* \return None
* This function is used to copy the byte content of a received message.
*/
void RIO_readMessagePayload8( RioStack_t *stack, uint8_t *buffer );
 
/**
* \brief Send a response with one byte data payload.
*
* \param[in] stack The stack to operate on.
* \param[in] destid The destination identifier of the response.
* \param[in] tid The transaction identifier for the reply. It should correspond to
* the tid in the received packet for which this response is sent.
* \param[in] address The byte address that was read.
* \param[in] data The data to return in the reply.
*
* This function creates a response packet with the specified destination
* identifier, transaction id and data payload. The generated packet are placed
* in the outbound packet queue.
*
* \note Call RIO_sendAvailable() before this function is called to make sure
* the outbound queue has transmission buffers available.
*/
void RIO_sendResponseDone8( RioStack_t *stack, const uint16_t destid, const uint8_t tid, const uint32_t address, const uint8_t data );
 
/**
* \brief Read a one byte payload from a response.
*
* \param[in] stack The stack to operate on.
* \return The byte data payload contained in the response.
*
* This function reads a response packet and returns a one byte payload
* contained within.
*/
uint8_t RIO_readResponseDone8( RioStack_t *stack );
 
/**
* \brief Get the target mailbox.
*
* \param[in] stack The stack to operate on.
* \return The target mailbox.
*
* This function is used to get the target mailbox of a message response.
*/
uint8_t RIO_readMessageResponseMbox( RioStack_t *stack );
 
#endif /* _RIO_STACK_H */
#endif /* _RIOSTACK_H */
/*************************** end of file **************************************/
/rio/trunk/sw/stack/riopacket.h
0,0 → 1,267
/*******************************************************************************
*
* RapidIO IP Library Core
*
* This file is part of the RapidIO IP library project
* http://www.opencores.org/cores/rio/
*
* Description:
* This file contains the public API for riopacket.
*
* To Do:
* -
*
* Author(s):
* - Magnus Rosenius, magro732@opencores.org
*
*******************************************************************************
*
* Copyright (C) 2015 Authors and OPENCORES.ORG
*
* This source file may be used and distributed without
* restriction provided that this copyright statement is not
* removed from the file and that any derivative work contains
* the original copyright notice and the associated disclaimer.
*
* This source file is free software; you can redistribute it
* and/or modify it under the terms of the GNU Lesser General
* Public License as published by the Free Software Foundation;
* either version 2.1 of the License, or (at your option) any
* later version.
*
* This source is distributed in the hope that it will be
* useful, but WITHOUT ANY WARRANTY; without even the implied
* warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
* PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General
* Public License along with this source; if not, download it
* from http://www.opencores.org/lgpl.shtml
*
*******************************************************************************/
/**
* \file riopacket.c
*/
 
#ifndef __RIOPACKET_H
#define __RIOPACKET_H
 
/*******************************************************************************
* Includes
*******************************************************************************/
 
#include "rioconfig.h"
 
 
/*******************************************************************************
* Global typedefs
*******************************************************************************/
 
/* The maximum size of a RapidIO packet in words (32-bit). */
#define RIOPACKET_SIZE_MIN 3u
#define RIOPACKET_SIZE_MAX 69u
 
/* Configuration space offsets. */
#define DEVICE_IDENTITY_CAR ((uint32_t)0x00000000ul)
#define DEVICE_INFORMATION_CAR ((uint32_t)0x00000004ul)
#define ASSEMBLY_IDENTITY_CAR ((uint32_t)0x00000008ul)
#define ASSEMBLY_INFORMATION_CAR ((uint32_t)0x0000000cul)
#define PROCESSING_ELEMENT_FEATURES_CAR ((uint32_t)0x00000010ul)
#define SWITCH_PORT_INFORMATION_CAR ((uint32_t)0x00000014ul)
#define SOURCE_OPERATIONS_CAR ((uint32_t)0x00000018ul)
#define DESTINATION_OPERATIONS_CAR ((uint32_t)0x0000001cul)
#define SWITCH_ROUTE_TABLE_DESTINATION_ID_LIMIT_CAR ((uint32_t)0x00000034ul)
#define PROCESSING_ELEMENT_LOGICAL_LAYER_CONTROL_CSR ((uint32_t)0x0000004cul)
#define BASE_DEVICE_ID_CSR ((uint32_t)0x00000060ul)
#define HOST_BASE_DEVICE_ID_LOCK_CSR ((uint32_t)0x00000068ul)
#define COMPONENT_TAG_CSR ((uint32_t)0x0000006cul)
#define STANDARD_ROUTE_CONFIGURATION_DESTINATION_ID_SELECT_CSR ((uint32_t)0x00000070ul)
#define STANDARD_ROUTE_CONFIGURATION_PORT_SELECT_CSR ((uint32_t)0x00000074ul)
#define STANDARD_ROUTE_DEFAULT_PORT_CSR ((uint32_t)0x00000078ul)
#define EXTENDED_FEATURES_OFFSET ((uint32_t)0x00000100ul)
#define IMPLEMENTATION_DEFINED_OFFSET ((uint32_t)0x00010000ul)
#define LP_SERIAL_REGISTER_BLOCK_HEADER(offset) (offset)
#define PORT_LINK_TIMEOUT_CONTROL_CSR(offset) ((offset) + 0x00000020ul)
#define PORT_RESPONSE_TIMEOUT_CONTROL_CSR(offset) ((offset) + 0x00000024ul)
#define PORT_GENERAL_CONTROL_CSR(offset) ((offset) + 0x0000003cul)
#define PORT_N_LOCAL_ACKID_CSR(offset, n) ((offset) + (0x00000048ul+((n)*0x00000020ul)))
#define PORT_N_ERROR_AND_STATUS_CSR(offset, n) ((offset) + (0x00000058ul+((n)*0x00000020ul)))
#define PORT_N_CONTROL_CSR(offset, n) ((offset) + (0x0000005cul+((n)*0x00000020ul)))
 
/* Packet ftype constants. */
#define RIOPACKET_FTYPE_REQUEST 0x2
#define RIOPACKET_FTYPE_WRITE 0x5
#define RIOPACKET_FTYPE_MAINTENANCE 0x8
#define RIOPACKET_FTYPE_DOORBELL 0xa
#define RIOPACKET_FTYPE_MESSAGE 0xb
#define RIOPACKET_FTYPE_RESPONSE 0xd
 
/* Transaction constants. */
#define RIOPACKET_TRANSACTION_MAINT_READ_REQUEST 0ul
#define RIOPACKET_TRANSACTION_MAINT_WRITE_REQUEST 1ul
#define RIOPACKET_TRANSACTION_MAINT_READ_RESPONSE 2ul
#define RIOPACKET_TRANSACTION_MAINT_WRITE_RESPONSE 3ul
#define RIOPACKET_TRANSACTION_MAINT_PORT_WRITE_REQUEST 4ul
#define RIOPACKET_TRANSACTION_WRITE_NWRITE 4ul
#define RIOPACKET_TRANSACTION_WRITE_NWRITER 5ul
#define RIOPACKET_TRANSACTION_REQUEST_NREAD 4ul
#define RIOPACKET_TRANSACTION_RESPONSE_NO_PAYLOAD 0ul
#define RIOPACKET_TRANSACTION_RESPONSE_MESSAGE_RESPONSE 1ul
#define RIOPACKET_TRANSACTION_RESPONSE_WITH_PAYLOAD 8ul
 
/* Response status constants. */
#define RIOPACKET_RESPONSE_STATUS_DONE 0ul
#define RIOPACKET_RESPONSE_STATUS_RETRY 3ul
#define RIOPACKET_RESPONSE_STATUS_ERROR 7ul
 
 
/* The structure containing a RapidIO packet. */
typedef struct
{
/* Size in words. */
uint8_t size;
uint32_t payload[RIOPACKET_SIZE_MAX];
} RioPacket_t;
 
 
 
/*******************************************************************************
* Global function prototypes
*******************************************************************************/
 
void RIOPACKET_init(RioPacket_t *packet);
uint8_t RIOPACKET_size(RioPacket_t *packet);
void RIOPACKET_append(RioPacket_t *packet, uint32_t word);
 
int RIOPACKET_valid(RioPacket_t *packet);
 
int RIOPACKET_serialize(RioPacket_t *packet, const uint16_t size, uint8_t *buffer);
int RIOPACKET_deserialize(RioPacket_t *packet, const uint16_t size, const uint8_t *buffer);
 
#ifdef ENABLE_TOSTRING
#include <stdio.h>
void RIOPACKET_toString(RioPacket_t *packet, char *buffer);
#endif
 
uint8_t RIOPACKET_getFtype(RioPacket_t *packet);
uint16_t RIOPACKET_getDestination(RioPacket_t *packet);
uint16_t RIOPACKET_getSource(RioPacket_t *packet);
uint8_t RIOPACKET_getTransaction(RioPacket_t *packet);
uint8_t RIOPACKET_getTid(RioPacket_t *packet);
 
void RIOPACKET_setMaintReadRequest(RioPacket_t *packet,
uint16_t destId, uint16_t srcId, uint8_t hop,
uint8_t tid, uint32_t offset);
void RIOPACKET_getMaintReadRequest(RioPacket_t *packet,
uint16_t *destId, uint16_t *srcId, uint8_t *hop,
uint8_t *tid, uint32_t *offset);
 
void RIOPACKET_setMaintReadResponse(RioPacket_t *packet,
uint16_t destId, uint16_t srcId,
uint8_t tid, uint32_t data);
void RIOPACKET_getMaintReadResponse(RioPacket_t *packet,
uint16_t *destId, uint16_t *srcId,
uint8_t *tid, uint32_t *data);
 
void RIOPACKET_setMaintWriteRequest(RioPacket_t *packet,
uint16_t destId, uint16_t srcId, uint8_t hop,
uint8_t tid, uint32_t offset, uint32_t data);
void RIOPACKET_getMaintWriteRequest(RioPacket_t *packet,
uint16_t *destId, uint16_t *srcId, uint8_t *hop,
uint8_t *tid, uint32_t *offset, uint32_t *data);
 
void RIOPACKET_setMaintWriteResponse(RioPacket_t *packet,
uint16_t destId, uint16_t srcId,
uint8_t tid);
void RIOPACKET_getMaintWriteResponse(RioPacket_t *packet,
uint16_t *destId, uint16_t *srcId,
uint8_t *tid);
 
void RIOPACKET_setMaintPortWrite(RioPacket_t *packet,
uint16_t destId, uint16_t srcId,
uint32_t componentTag, uint32_t portErrorDetect,
uint32_t implementationSpecific, uint8_t portId,
uint32_t logicalTransportErrorDetect);
void RIOPACKET_getMaintPortWrite(RioPacket_t *packet,
uint16_t *destId, uint16_t *srcId,
uint32_t *componentTag, uint32_t *portErrorDetect,
uint32_t *implementationSpecific, uint8_t *portId,
uint32_t *logicalTransportErrorDetect);
 
void RIOPACKET_setNwrite(RioPacket_t *packet,
uint16_t destId, uint16_t srcId,
uint32_t address, uint16_t payloadSize, uint8_t *payload);
void RIOPACKET_getNwrite(RioPacket_t *packet,
uint16_t *destId, uint16_t *srcId,
uint32_t *address, uint16_t *payloadSize, uint8_t *payload);
 
void RIOPACKET_setNwriteR(RioPacket_t *packet,
uint16_t destId, uint16_t srcId,
uint8_t tid,
uint32_t address, uint16_t payloadSize, uint8_t *payload);
void RIOPACKET_getNwriteR(RioPacket_t *packet,
uint16_t *destId, uint16_t *srcId,
uint8_t *tid,
uint32_t *address, uint16_t *payloadSize, uint8_t *payload);
 
void RIOPACKET_setNread(RioPacket_t *packet,
uint16_t destId, uint16_t srcId,
uint8_t tid,
uint32_t address, uint16_t payloadSize);
void RIOPACKET_getNread(RioPacket_t *packet,
uint16_t *destId, uint16_t *srcId,
uint8_t *tid,
uint32_t *address, uint16_t *payloadSize);
 
 
void RIOPACKET_setDoorbell(RioPacket_t *packet,
uint16_t destId, uint16_t srcId,
uint8_t tid, uint16_t info);
void RIOPACKET_getDoorbell(RioPacket_t *packet,
uint16_t *destId, uint16_t *srcId,
uint8_t *tid, uint16_t *info);
 
void RIOPACKET_setMessage(RioPacket_t *packet,
uint16_t destId, uint16_t srcId,
uint8_t mailbox,
uint16_t size, uint8_t *payload);
void RIOPACKET_getMessage(RioPacket_t *packet,
uint16_t *destId, uint16_t *srcId,
uint8_t *mailbox,
uint16_t *size, uint8_t *payload);
 
 
void RIOPACKET_setResponseNoPayload(RioPacket_t *packet,
uint16_t destId, uint16_t srcId,
uint8_t tid, uint8_t status);
void RIOPACKET_getResponseNoPayload(RioPacket_t *packet,
uint16_t *destId, uint16_t *srcId,
uint8_t *tid, uint8_t *status);
 
void RIOPACKET_setResponseWithPayload(RioPacket_t *packet,
uint16_t destId, uint16_t srcId,
uint8_t tid, uint8_t offset,
uint16_t size, uint8_t *payload);
void RIOPACKET_getResponseWithPayload(RioPacket_t *packet,
uint16_t *destId, uint16_t *srcId,
uint8_t *tid, uint8_t offset,
uint16_t *size, uint8_t *payload);
 
void RIOPACKET_setResponseMessage(RioPacket_t *packet,
uint16_t destId, uint16_t srcId,
uint8_t mailbox, uint8_t status);
void RIOPACKET_getResponseMessage(RioPacket_t *packet,
uint16_t *destId, uint16_t *srcId,
uint8_t *mailbox, uint8_t *status);
 
uint16_t RIOPACKET_Crc16( const uint16_t data, const uint16_t crc);
uint16_t RIOPACKET_Crc32( const uint32_t data, uint16_t crc);
 
uint32_t RIOPACKET_getReadPacketSize(uint32_t address, uint32_t size);
uint32_t RIOPACKET_getWritePacketSize(uint32_t address, uint32_t size);
 
#endif
 
/*************************** end of file **************************************/

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.