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 **************************************/ |