URL
https://opencores.org/ocsvn/rio/rio/trunk
Subversion Repositories rio
Compare Revisions
- This comparison shows the changes necessary to convert path
/rio
- from Rev 19 to Rev 20
- ↔ Reverse comparison
Rev 19 → Rev 20
/trunk/bench/vhdl/TestRioPcsUart.vhd
0,0 → 1,674
------------------------------------------------------------------------------- |
-- |
-- RapidIO IP Library Core |
-- |
-- This file is part of the RapidIO IP library project |
-- http://www.opencores.org/cores/rio/ |
-- |
-- Description |
-- This file contains a testbench for RioPcsUart. |
-- |
-- To Do: |
-- - |
-- |
-- 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 |
-- |
------------------------------------------------------------------------------- |
|
------------------------------------------------------------------------------- |
-- TestRioPcsUart. |
------------------------------------------------------------------------------- |
|
library ieee; |
use ieee.std_logic_1164.all; |
use ieee.numeric_std.all; |
library std; |
use std.textio.all; |
use work.test_common.all; |
use work.rio_common.all; |
|
|
------------------------------------------------------------------------------- |
-- Entity for TestRioPcsUart. |
------------------------------------------------------------------------------- |
entity TestRioPcsUart is |
end entity; |
|
|
------------------------------------------------------------------------------- |
-- Architecture for TestUart. |
------------------------------------------------------------------------------- |
architecture TestRioPcsUartImpl of TestRioPcsUart is |
|
component RioFifo1 is |
generic( |
WIDTH : natural); |
port( |
clk : in std_logic; |
areset_n : in std_logic; |
|
empty_o : out std_logic; |
read_i : in std_logic; |
data_o : out std_logic_vector(WIDTH-1 downto 0); |
|
full_o : out std_logic; |
write_i : in std_logic; |
data_i : in std_logic_vector(WIDTH-1 downto 0)); |
end component; |
|
component RioSymbolConverter is |
port( |
clk : in std_logic; |
areset_n : in std_logic; |
|
portInitialized_o : out std_logic; |
outboundSymbolEmpty_i : in std_logic; |
outboundSymbolRead_o : out std_logic; |
outboundSymbol_i : in std_logic_vector(33 downto 0); |
inboundSymbolFull_i : in std_logic; |
inboundSymbolWrite_o : out std_logic; |
inboundSymbol_o : out std_logic_vector(33 downto 0); |
|
uartEmpty_i : in std_logic; |
uartRead_o : out std_logic; |
uartData_i : in std_logic_vector(7 downto 0); |
uartFull_i : in std_logic; |
uartWrite_o : out std_logic; |
uartData_o : out std_logic_vector(7 downto 0)); |
end component; |
|
signal clk : std_logic; |
signal areset_n : std_logic; |
|
signal portInitialized : std_logic; |
|
signal outboundSymbolEmpty : std_logic; |
signal outboundSymbolRead : std_logic; |
signal outboundSymbolReadData : std_logic_vector(33 downto 0); |
signal outboundSymbolFull : std_logic; |
signal outboundSymbolWrite : std_logic; |
signal outboundSymbolWriteData : std_logic_vector(33 downto 0); |
|
signal inboundSymbolFull : std_logic; |
signal inboundSymbolWrite : std_logic; |
signal inboundSymbolWriteData : std_logic_vector(33 downto 0); |
|
signal uartInboundEmpty : std_logic; |
signal uartInboundRead : std_logic; |
signal uartInboundReadData : std_logic_vector(7 downto 0); |
signal uartInboundFull : std_logic; |
signal uartInboundWrite : std_logic; |
signal uartInboundWriteData : std_logic_vector(7 downto 0); |
|
signal uartOutboundFull : std_logic; |
signal uartOutboundWrite : std_logic; |
signal uartOutboundWriteData : std_logic_vector(7 downto 0); |
|
begin |
|
----------------------------------------------------------------------------- |
-- Clock generation. |
----------------------------------------------------------------------------- |
ClockGenerator: process |
begin |
clk <= '0'; |
wait for 20 ns; |
clk <= '1'; |
wait for 20 ns; |
end process; |
|
|
----------------------------------------------------------------------------- |
-- Serial protocol test driver. |
----------------------------------------------------------------------------- |
TestDriver: process |
|
--------------------------------------------------------------------------- |
-- Procedure to read a symbol. |
--------------------------------------------------------------------------- |
procedure ReadSymbol( |
constant symbolType : in std_logic_vector(1 downto 0); |
constant symbolContent : in std_logic_vector(31 downto 0) := x"00000000") is |
begin |
inboundSymbolFull <= '0'; |
wait until inboundSymbolWrite = '1' and clk'event and clk = '1'; |
inboundSymbolFull <= '1'; |
|
assert symbolType = inboundSymbolWriteData(33 downto 32) |
report "Missmatching symbol type:expected=" & |
integer'image(to_integer(unsigned(symbolType))) & |
" got=" & |
integer'image(to_integer(unsigned(outboundSymbolWriteData(33 downto 32)))) |
severity error; |
|
if (symbolType = SYMBOL_CONTROL_SC) or (symbolType = SYMBOL_CONTROL_PD) then |
assert symbolContent(31 downto 8) = inboundSymbolWriteData(31 downto 8) |
report "Missmatching symbol content:expected=" & |
integer'image(to_integer(unsigned(symbolContent(31 downto 8)))) & |
" got=" & |
integer'image(to_integer(unsigned(inboundSymbolWriteData(31 downto 8)))) |
severity error; |
elsif (symbolType = SYMBOL_DATA) then |
assert symbolContent(31 downto 0) = inboundSymbolWriteData(31 downto 0) |
report "Missmatching symbol content:expected=" & |
integer'image(to_integer(unsigned(symbolContent(31 downto 0)))) & |
" got=" & |
integer'image(to_integer(unsigned(inboundSymbolWriteData(31 downto 0)))) |
severity error; |
end if; |
end procedure; |
|
--------------------------------------------------------------------------- |
-- Procedure to write a symbol. |
--------------------------------------------------------------------------- |
procedure WriteSymbol( |
constant symbolType : in std_logic_vector(1 downto 0); |
constant symbolContent : in std_logic_vector(31 downto 0) := x"00000000") is |
begin |
wait until outboundSymbolFull = '0' and clk'event and clk = '1'; |
outboundSymbolWrite <= '1'; |
outboundSymbolWriteData <= symbolType & symbolContent; |
wait until clk'event and clk = '1'; |
outboundSymbolWrite <= '0'; |
end procedure; |
|
--------------------------------------------------------------------------- |
-- Procedure to read an octet. |
--------------------------------------------------------------------------- |
procedure ReadOctet( |
constant octet : in std_logic_vector(7 downto 0) := x"00") is |
begin |
uartOutboundFull <= '0'; |
wait until uartOutboundWrite = '1' and clk'event and clk = '1'; |
uartOutboundFull <= '1'; |
|
assert uartOutboundWriteData = octet |
report "Missmatching octet content:expected=" & |
integer'image(to_integer(unsigned(octet))) & |
" got=" & |
integer'image(to_integer(unsigned(uartOutboundWriteData))) |
severity error; |
end procedure; |
|
--------------------------------------------------------------------------- |
-- Procedure to send a symbol. |
--------------------------------------------------------------------------- |
procedure WriteOctet( |
constant octet : in std_logic_vector(7 downto 0) := x"00") is |
begin |
wait until uartInboundFull = '0' and clk'event and clk = '1'; |
uartInboundWrite <= '1'; |
uartInboundWriteData <= octet; |
wait until clk'event and clk = '1'; |
uartInboundWrite <= '0'; |
end procedure; |
|
--------------------------------------------------------------------------- |
-- Process variables. |
--------------------------------------------------------------------------- |
|
begin |
--------------------------------------------------------------------------- |
-- Test case initialization. |
--------------------------------------------------------------------------- |
|
uartOutboundFull <= '1'; |
uartInboundWrite <= '0'; |
|
inboundSymbolFull <= '1'; |
outboundSymbolWrite <= '0'; |
|
-- Generate a startup reset pulse. |
areset_n <= '0'; |
wait until clk'event and clk = '1'; |
wait until clk'event and clk = '1'; |
areset_n <= '1'; |
wait until clk'event and clk = '1'; |
wait until clk'event and clk = '1'; |
|
--------------------------------------------------------------------------- |
PrintS("-----------------------------------------------------------------"); |
PrintS("TG_RioPcsUart"); |
PrintS("-----------------------------------------------------------------"); |
PrintS("TG_RioPcsUart-TC1"); |
PrintS("Description: Check initial silence time."); |
PrintS("Requirement: XXXXX"); |
PrintS("-----------------------------------------------------------------"); |
PrintS("Step 1:"); |
PrintS("Action: ."); |
PrintS("Result: ."); |
--------------------------------------------------------------------------- |
PrintR("TG_RioPcsUart-TC1-Step1"); |
--------------------------------------------------------------------------- |
|
WriteSymbol(SYMBOL_IDLE); |
|
uartOutboundFull <= '0'; |
for i in 0 to 4095 loop |
wait until clk'event and clk = '1'; |
assert uartOutboundWrite = '0' report "Sending during silence time." |
severity error; |
end loop; |
|
ReadOctet(x"7e"); |
|
--------------------------------------------------------------------------- |
PrintS("-----------------------------------------------------------------"); |
PrintS("TG_RioPcsUart-TC2"); |
PrintS("Description: Check outbound symbol generation."); |
PrintS("Requirement: XXXXX"); |
PrintS("-----------------------------------------------------------------"); |
PrintS("Step 1:"); |
PrintS("Action: ."); |
PrintS("Result: ."); |
--------------------------------------------------------------------------- |
PrintR("TG_RioPcsUart-TC2-Step1"); |
--------------------------------------------------------------------------- |
|
WriteSymbol(SYMBOL_IDLE); |
ReadOctet(x"7e"); |
WriteSymbol(SYMBOL_IDLE); |
ReadOctet(x"7e"); |
WriteSymbol(SYMBOL_IDLE); |
ReadOctet(x"7e"); |
|
--------------------------------------------------------------------------- |
PrintS("Step 2:"); |
PrintS("Action: ."); |
PrintS("Result: ."); |
--------------------------------------------------------------------------- |
PrintR("TG_RioPcsUart-TC2-Step2"); |
--------------------------------------------------------------------------- |
|
WriteSymbol(SYMBOL_CONTROL_SC, x"123456" & "XXXXXXXX"); |
ReadOctet(x"12"); |
ReadOctet(x"34"); |
ReadOctet(x"56"); |
ReadOctet(x"7e"); |
|
--------------------------------------------------------------------------- |
PrintS("Step 3:"); |
PrintS("Action: ."); |
PrintS("Result: ."); |
--------------------------------------------------------------------------- |
PrintR("TG_RioPcsUart-TC2-Step3"); |
--------------------------------------------------------------------------- |
|
WriteSymbol(SYMBOL_CONTROL_PD, x"7d7d7d" & "XXXXXXXX"); |
ReadOctet(x"7d"); |
ReadOctet(x"5d"); |
ReadOctet(x"7d"); |
ReadOctet(x"5d"); |
ReadOctet(x"7d"); |
ReadOctet(x"5d"); |
ReadOctet(x"7e"); |
|
--------------------------------------------------------------------------- |
PrintS("Step 4:"); |
PrintS("Action: ."); |
PrintS("Result: ."); |
--------------------------------------------------------------------------- |
PrintR("TG_RioPcsUart-TC2-Step4"); |
--------------------------------------------------------------------------- |
|
WriteSymbol(SYMBOL_CONTROL_SC, x"7e7e7e" & "XXXXXXXX"); |
ReadOctet(x"7d"); |
ReadOctet(x"5e"); |
ReadOctet(x"7d"); |
ReadOctet(x"5e"); |
ReadOctet(x"7d"); |
ReadOctet(x"5e"); |
ReadOctet(x"7e"); |
|
--------------------------------------------------------------------------- |
PrintS("Step 5:"); |
PrintS("Action: ."); |
PrintS("Result: ."); |
--------------------------------------------------------------------------- |
PrintR("TG_RioPcsUart-TC2-Step5"); |
--------------------------------------------------------------------------- |
|
WriteSymbol(SYMBOL_CONTROL_PD, x"7d7f7e" & "XXXXXXXX"); |
ReadOctet(x"7d"); |
ReadOctet(x"5d"); |
ReadOctet(x"7f"); |
ReadOctet(x"7d"); |
ReadOctet(x"5e"); |
ReadOctet(x"7e"); |
|
--------------------------------------------------------------------------- |
PrintS("Step 6:"); |
PrintS("Action: ."); |
PrintS("Result: ."); |
--------------------------------------------------------------------------- |
PrintR("TG_RioPcsUart-TC2-Step6"); |
--------------------------------------------------------------------------- |
|
WriteSymbol(SYMBOL_DATA, x"12345678"); |
ReadOctet(x"12"); |
ReadOctet(x"34"); |
ReadOctet(x"56"); |
ReadOctet(x"78"); |
|
--------------------------------------------------------------------------- |
PrintS("Step 7:"); |
PrintS("Action: ."); |
PrintS("Result: ."); |
--------------------------------------------------------------------------- |
PrintR("TG_RioPcsUart-TC2-Step7"); |
--------------------------------------------------------------------------- |
|
WriteSymbol(SYMBOL_DATA, x"7d7d7d7d"); |
ReadOctet(x"7d"); |
ReadOctet(x"5d"); |
ReadOctet(x"7d"); |
ReadOctet(x"5d"); |
ReadOctet(x"7d"); |
ReadOctet(x"5d"); |
ReadOctet(x"7d"); |
ReadOctet(x"5d"); |
|
--------------------------------------------------------------------------- |
PrintS("Step 8:"); |
PrintS("Action: ."); |
PrintS("Result: ."); |
--------------------------------------------------------------------------- |
PrintR("TG_RioPcsUart-TC2-Step8"); |
--------------------------------------------------------------------------- |
|
WriteSymbol(SYMBOL_DATA, x"7e7e7e7e"); |
ReadOctet(x"7d"); |
ReadOctet(x"5e"); |
ReadOctet(x"7d"); |
ReadOctet(x"5e"); |
ReadOctet(x"7d"); |
ReadOctet(x"5e"); |
ReadOctet(x"7d"); |
ReadOctet(x"5e"); |
|
--------------------------------------------------------------------------- |
PrintS("Step 9:"); |
PrintS("Action: ."); |
PrintS("Result: ."); |
--------------------------------------------------------------------------- |
PrintR("TG_RioPcsUart-TC2-Step9"); |
--------------------------------------------------------------------------- |
|
WriteSymbol(SYMBOL_DATA, x"7d7f7e7f"); |
ReadOctet(x"7d"); |
ReadOctet(x"5d"); |
ReadOctet(x"7f"); |
ReadOctet(x"7d"); |
ReadOctet(x"5e"); |
ReadOctet(x"7f"); |
|
--------------------------------------------------------------------------- |
PrintS("Step 10:"); |
PrintS("Action: ."); |
PrintS("Result: ."); |
--------------------------------------------------------------------------- |
PrintR("TG_RioPcsUart-TC2-Step10"); |
--------------------------------------------------------------------------- |
|
WriteSymbol(SYMBOL_IDLE); |
ReadOctet(x"7e"); |
WriteSymbol(SYMBOL_CONTROL_SC, x"123456" & "XXXXXXXX"); |
ReadOctet(x"12"); |
ReadOctet(x"34"); |
ReadOctet(x"56"); |
ReadOctet(x"7e"); |
WriteSymbol(SYMBOL_DATA, x"789abcde"); |
ReadOctet(x"78"); |
ReadOctet(x"9a"); |
ReadOctet(x"bc"); |
ReadOctet(x"de"); |
WriteSymbol(SYMBOL_CONTROL_SC, x"123456" & "XXXXXXXX"); |
ReadOctet(x"12"); |
ReadOctet(x"34"); |
ReadOctet(x"56"); |
ReadOctet(x"7e"); |
WriteSymbol(SYMBOL_DATA, x"789abcde"); |
ReadOctet(x"78"); |
ReadOctet(x"9a"); |
ReadOctet(x"bc"); |
ReadOctet(x"de"); |
WriteSymbol(SYMBOL_DATA, x"789abcde"); |
ReadOctet(x"78"); |
ReadOctet(x"9a"); |
ReadOctet(x"bc"); |
ReadOctet(x"de"); |
|
--------------------------------------------------------------------------- |
PrintS("-----------------------------------------------------------------"); |
PrintS("TG_RioPcsUart-TC3"); |
PrintS("Description: Check inbound symbol generation."); |
PrintS("Requirement: XXXXX"); |
PrintS("-----------------------------------------------------------------"); |
PrintS("Step 1:"); |
PrintS("Action: ."); |
PrintS("Result: ."); |
--------------------------------------------------------------------------- |
PrintR("TG_RioPcsUart-TC3-Step1"); |
--------------------------------------------------------------------------- |
|
WriteOctet(x"7e"); |
WriteOctet(x"7e"); |
ReadSymbol(SYMBOL_IDLE); |
|
--------------------------------------------------------------------------- |
PrintS("Step :"); |
PrintS("Action: ."); |
PrintS("Result: ."); |
--------------------------------------------------------------------------- |
PrintR("TG_RioPcsUart-TC3-Step"); |
--------------------------------------------------------------------------- |
|
WriteOctet(x"12"); |
WriteOctet(x"7e"); |
ReadSymbol(SYMBOL_IDLE); |
|
--------------------------------------------------------------------------- |
PrintS("Step :"); |
PrintS("Action: ."); |
PrintS("Result: ."); |
--------------------------------------------------------------------------- |
PrintR("TG_RioPcsUart-TC3-Step"); |
--------------------------------------------------------------------------- |
|
WriteOctet(x"34"); |
WriteOctet(x"56"); |
WriteOctet(x"7e"); |
ReadSymbol(SYMBOL_IDLE); |
|
--------------------------------------------------------------------------- |
PrintS("Step :"); |
PrintS("Action: ."); |
PrintS("Result: ."); |
--------------------------------------------------------------------------- |
PrintR("TG_RioPcsUart-TC3-Step"); |
--------------------------------------------------------------------------- |
|
WriteOctet(x"78"); |
WriteOctet(x"9a"); |
WriteOctet(x"bc"); |
WriteOctet(x"7e"); |
ReadSymbol(SYMBOL_CONTROL_SC, x"789abc" & "XXXXXXXX"); |
|
--------------------------------------------------------------------------- |
PrintS("Step :"); |
PrintS("Action: ."); |
PrintS("Result: ."); |
--------------------------------------------------------------------------- |
PrintR("TG_RioPcsUart-TC3-Step"); |
--------------------------------------------------------------------------- |
|
WriteOctet(x"7d"); |
WriteOctet(x"5d"); |
WriteOctet(x"7d"); |
WriteOctet(x"5d"); |
WriteOctet(x"7d"); |
WriteOctet(x"5d"); |
WriteOctet(x"7e"); |
ReadSymbol(SYMBOL_CONTROL_SC, x"7d7d7d" & "XXXXXXXX"); |
|
--------------------------------------------------------------------------- |
PrintS("Step :"); |
PrintS("Action: ."); |
PrintS("Result: ."); |
--------------------------------------------------------------------------- |
PrintR("TG_RioPcsUart-TC3-Step"); |
--------------------------------------------------------------------------- |
|
WriteOctet(x"7d"); |
WriteOctet(x"5e"); |
WriteOctet(x"7d"); |
WriteOctet(x"5e"); |
WriteOctet(x"7d"); |
WriteOctet(x"5e"); |
WriteOctet(x"7e"); |
ReadSymbol(SYMBOL_CONTROL_SC, x"7e7e7e" & "XXXXXXXX"); |
|
--------------------------------------------------------------------------- |
PrintS("Step :"); |
PrintS("Action: ."); |
PrintS("Result: ."); |
--------------------------------------------------------------------------- |
PrintR("TG_RioPcsUart-TC3-Step"); |
--------------------------------------------------------------------------- |
|
WriteOctet(x"f1"); |
WriteOctet(x"11"); |
WriteOctet(x"22"); |
WriteOctet(x"33"); |
ReadSymbol(SYMBOL_DATA, x"f1112233"); |
|
--------------------------------------------------------------------------- |
PrintS("Step :"); |
PrintS("Action: ."); |
PrintS("Result: ."); |
--------------------------------------------------------------------------- |
PrintR("TG_RioPcsUart-TC3-Step"); |
--------------------------------------------------------------------------- |
|
WriteOctet(x"7e"); |
ReadSymbol(SYMBOL_IDLE); |
|
--------------------------------------------------------------------------- |
PrintS("Step :"); |
PrintS("Action: ."); |
PrintS("Result: ."); |
--------------------------------------------------------------------------- |
PrintR("TG_RioPcsUart-TC3-Step"); |
--------------------------------------------------------------------------- |
|
WriteOctet(x"7d"); |
WriteOctet(x"5d"); |
WriteOctet(x"7d"); |
WriteOctet(x"5d"); |
WriteOctet(x"7d"); |
WriteOctet(x"5d"); |
WriteOctet(x"7d"); |
WriteOctet(x"5d"); |
ReadSymbol(SYMBOL_DATA, x"7d7d7d7d"); |
|
--------------------------------------------------------------------------- |
PrintS("Step :"); |
PrintS("Action: ."); |
PrintS("Result: ."); |
--------------------------------------------------------------------------- |
PrintR("TG_RioPcsUart-TC3-Step"); |
--------------------------------------------------------------------------- |
|
WriteOctet(x"7d"); |
WriteOctet(x"5e"); |
WriteOctet(x"7d"); |
WriteOctet(x"5e"); |
WriteOctet(x"7d"); |
WriteOctet(x"5e"); |
WriteOctet(x"7d"); |
WriteOctet(x"5e"); |
ReadSymbol(SYMBOL_DATA, x"7e7e7e7e"); |
|
--------------------------------------------------------------------------- |
PrintS("Step :"); |
PrintS("Action: ."); |
PrintS("Result: ."); |
--------------------------------------------------------------------------- |
PrintR("TG_RioPcsUart-TC3-Step"); |
--------------------------------------------------------------------------- |
|
WriteOctet(x"44"); |
WriteOctet(x"55"); |
WriteOctet(x"66"); |
WriteOctet(x"77"); |
ReadSymbol(SYMBOL_DATA, x"44556677"); |
WriteOctet(x"88"); |
WriteOctet(x"99"); |
WriteOctet(x"aa"); |
WriteOctet(x"bb"); |
ReadSymbol(SYMBOL_DATA, x"8899aabb"); |
|
--------------------------------------------------------------------------- |
-- Test completed. |
--------------------------------------------------------------------------- |
|
TestEnd; |
end process; |
|
|
----------------------------------------------------------------------------- |
-- |
----------------------------------------------------------------------------- |
|
OutboundSymbolFifo: RioFifo1 |
generic map(WIDTH=>34) |
port map( |
clk=>clk, areset_n=>areset_n, |
empty_o=>outboundSymbolEmpty, read_i=>outboundSymbolRead, data_o=>outboundSymbolReadData, |
full_o=>outboundSymbolFull, write_i=>outboundSymbolWrite, data_i=>outboundSymbolWriteData); |
|
InboundOctetFifo: RioFifo1 |
generic map(WIDTH=>8) |
port map( |
clk=>clk, areset_n=>areset_n, |
empty_o=>uartInboundEmpty, read_i=>uartInboundRead, data_o=>uartInboundReadData, |
full_o=>uartInboundFull, write_i=>uartInboundWrite, data_i=>uartInboundWriteData); |
|
TestSymbolConverter: RioSymbolConverter |
port map( |
clk=>clk, areset_n=>areset_n, |
portInitialized_o=>portInitialized, |
outboundSymbolEmpty_i=>outboundSymbolEmpty, |
outboundSymbolRead_o=>outboundSymbolRead, outboundSymbol_i=>outboundSymbolReadData, |
inboundSymbolFull_i=>inboundSymbolFull, |
inboundSymbolWrite_o=>inboundSymbolWrite, inboundSymbol_o=>inboundSymbolWriteData, |
uartEmpty_i=>uartInboundEmpty, uartRead_o=>uartInboundRead, uartData_i=>uartInboundReadData, |
uartFull_i=>uartOutboundFull, uartWrite_o=>uartOutboundWrite, uartData_o=>uartOutboundWriteData); |
|
end architecture; |
trunk/bench/vhdl/TestRioPcsUart.vhd
Property changes :
Added: svn:executable
## -0,0 +1 ##
+*
\ No newline at end of property
Index: trunk/bench/vhdl/TestUart.vhd
===================================================================
--- trunk/bench/vhdl/TestUart.vhd (nonexistent)
+++ trunk/bench/vhdl/TestUart.vhd (revision 20)
@@ -0,0 +1,228 @@
+-------------------------------------------------------------------------------
+--
+-- RapidIO IP Library Core
+--
+-- This file is part of the RapidIO IP library project
+-- http://www.opencores.org/cores/rio/
+--
+-- Description
+-- Contains a testbench for the generic UART entity.
+--
+-- To Do:
+-- -
+--
+-- 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
+--
+-------------------------------------------------------------------------------
+
+
+-------------------------------------------------------------------------------
+-- TestUart.
+-------------------------------------------------------------------------------
+
+library ieee;
+use ieee.std_logic_1164.all;
+use ieee.numeric_std.all;
+library std;
+use std.textio.all;
+use work.test_common.all;
+
+
+-------------------------------------------------------------------------------
+-- Entity for TestUart.
+-------------------------------------------------------------------------------
+entity TestUart is
+end entity;
+
+
+-------------------------------------------------------------------------------
+-- Architecture for TestUart.
+-------------------------------------------------------------------------------
+architecture TestUartImpl of TestUart is
+
+ component Uart is
+ generic(
+ DIVISOR_WIDTH : natural;
+ DATA_WIDTH : natural);
+ port(
+ clk : in std_logic;
+ areset_n : in std_logic;
+
+ divisor_i : in std_logic_vector(DIVISOR_WIDTH-1 downto 0);
+
+ serial_i : in std_logic;
+ serial_o : out std_logic;
+
+ empty_o : out std_logic;
+ read_i : in std_logic;
+ data_o : out std_logic_vector(DATA_WIDTH-1 downto 0);
+
+ full_o : out std_logic;
+ write_i : in std_logic;
+ data_i : in std_logic_vector(DATA_WIDTH-1 downto 0));
+ end component;
+
+ signal clk : std_logic;
+ signal areset_n : std_logic;
+
+ signal rxSerial : std_logic;
+ signal txSerial : std_logic;
+
+ signal rxEmpty : std_logic;
+ signal rxRead : std_logic;
+ signal rxData : std_logic_vector(7 downto 0);
+
+ signal txFull : std_logic;
+ signal txWrite : std_logic;
+ signal txData : std_logic_vector(7 downto 0);
+
+begin
+
+ -----------------------------------------------------------------------------
+ -- Clock generation.
+ -----------------------------------------------------------------------------
+ ClockGenerator: process
+ begin
+ clk <= '0';
+ wait for 20 ns;
+ clk <= '1';
+ wait for 20 ns;
+ end process;
+
+
+ -----------------------------------------------------------------------------
+ -- Serial port emulator.
+ -----------------------------------------------------------------------------
+ TestDriver: process
+
+ procedure SerialSend(
+ constant data : in std_logic_vector(7 downto 0)) is
+ variable outgoing : std_logic_vector(9 downto 0);
+ begin
+ -- Create the complete transmission character.
+ outgoing(0) := '0';
+ for i in 0 to 7 loop
+ outgoing(i+1) := data(i);
+ end loop;
+ outgoing(9) := '1';
+
+ -- Send the character.
+ for i in 0 to 9 loop
+ txSerial <= outgoing(i);
+ wait for 500 ns;
+ end loop;
+ end procedure;
+
+ procedure SerialReceive(
+ constant data : in std_logic_vector(7 downto 0)) is
+ variable incomming : std_logic_vector(9 downto 0);
+ begin
+ -- Receive the character.
+ wait until rxSerial = '0';
+ incomming(0) := '0';
+ for i in 1 to 9 loop
+ wait for 500 ns;
+ incomming(i) := rxSerial;
+ end loop;
+
+ -- Check if the received character is expected.
+ assert (incomming(0) = '0') report "Start bit." severity error;
+ assert (incomming(8 downto 1) = data) report "Data bit" severity error;
+ assert (incomming(9) = '1') report "Stop bit." severity error;
+ end procedure;
+
+ begin
+ txSerial <= '1';
+ txWrite <= '0';
+ rxRead <= '0';
+ areset_n <= '0';
+
+ wait until clk'event and clk = '1';
+ wait until clk'event and clk = '1';
+ areset_n <= '1';
+ wait until clk'event and clk = '1';
+ wait until clk'event and clk = '1';
+
+ ---------------------------------------------------------------------------
+ -- Send byte to uart.
+ ---------------------------------------------------------------------------
+ SerialSend(x"55");
+ wait until rxEmpty = '0' and clk'event and clk = '1';
+ rxRead <= '1';
+ wait until clk'event and clk = '1';
+ rxRead <= '0';
+ wait until clk'event and clk = '1';
+ assert rxData = x"55" report "rxData" severity error;
+
+ SerialSend(x"62");
+ wait until rxEmpty = '0' and clk'event and clk = '1';
+ rxRead <= '1';
+ wait until clk'event and clk = '1';
+ rxRead <= '0';
+ wait until clk'event and clk = '1';
+ assert rxData = x"62" report "rxData" severity error;
+
+ wait until txFull = '0' and clk'event and clk = '1';
+ txWrite <= '1';
+ txData <= x"55";
+ wait until clk'event and clk = '1';
+ txWrite <= '0';
+ SerialReceive(x"55");
+
+ wait until txFull = '0' and clk'event and clk = '1';
+ txWrite <= '1';
+ txData <= x"62";
+ wait until clk'event and clk = '1';
+ txWrite <= '0';
+ SerialReceive(x"62");
+
+ -- REMARK: Formalize the tests and write more testcases...
+
+ ---------------------------------------------------------------------------
+ -- Test completed.
+ ---------------------------------------------------------------------------
+
+ TestEnd;
+ end process;
+
+
+ -----------------------------------------------------------------------------
+ -- Instantiate the uart.
+ -----------------------------------------------------------------------------
+
+ UartInst: Uart
+ generic map(DIVISOR_WIDTH=>4, DATA_WIDTH=>8)
+ port map(
+ clk=>clk, areset_n=>areset_n,
+ divisor_i=>"1011",
+ serial_i=>txSerial, serial_o=>rxSerial,
+ empty_o=>rxEmpty, read_i=>rxRead, data_o=>rxData,
+ full_o=>txFull, write_i=>txWrite, data_i=>txData);
+
+end architecture;
trunk/bench/vhdl/TestUart.vhd
Property changes :
Added: svn:executable
## -0,0 +1 ##
+*
\ No newline at end of property
Index: trunk/rtl/vhdl/RioPacketBuffer.vhd
===================================================================
--- trunk/rtl/vhdl/RioPacketBuffer.vhd (revision 19)
+++ trunk/rtl/vhdl/RioPacketBuffer.vhd (revision 20)
@@ -55,11 +55,24 @@
-------------------------------------------------------------------------------
-- Entity for RioPacketBuffer.
+--
+-- Generic variables
+-- -----------------
+-- SIZE_ADDRESS_WIDTH - The number of frames in powers of two.
+-- CONTENT_ADDRESS_WIDTH - The total number of entries in the memory that can
+-- be used to store packet data.
+-- CONTENT_WIDTH - The width of the data to store as packet content in the memory.
+-- MAX_PACKET_SIZE - The number of entries that must be available for a new
+-- complete full sized packet to be received. This option is present to ensure
+-- that it is always possible to move a packet to the storage without being
+-- surprised that the storage is suddenly empty.
-------------------------------------------------------------------------------
entity RioPacketBuffer is
generic(
SIZE_ADDRESS_WIDTH : natural := 6;
- CONTENT_ADDRESS_WIDTH : natural := 8);
+ CONTENT_ADDRESS_WIDTH : natural := 8;
+ CONTENT_WIDTH : natural := 32;
+ MAX_PACKET_SIZE : natural := 69);
port(
clk : in std_logic;
areset_n : in std_logic;
@@ -68,29 +81,31 @@
inboundWriteFrame_i : in std_logic;
inboundWriteFrameAbort_i : in std_logic;
inboundWriteContent_i : in std_logic;
- inboundWriteContentData_i : in std_logic_vector(31 downto 0);
+ inboundWriteContentData_i : in std_logic_vector(CONTENT_WIDTH-1 downto 0);
inboundReadFrameEmpty_o : out std_logic;
inboundReadFrame_i : in std_logic;
inboundReadFrameRestart_i : in std_logic;
inboundReadFrameAborted_o : out std_logic;
+ inboundReadFrameSize_o : out std_logic_vector(CONTENT_ADDRESS_WIDTH-1 downto 0);
inboundReadContentEmpty_o : out std_logic;
inboundReadContent_i : in std_logic;
inboundReadContentEnd_o : out std_logic;
- inboundReadContentData_o : out std_logic_vector(31 downto 0);
+ inboundReadContentData_o : out std_logic_vector(CONTENT_WIDTH-1 downto 0);
outboundWriteFrameFull_o : out std_logic;
outboundWriteFrame_i : in std_logic;
outboundWriteFrameAbort_i : in std_logic;
outboundWriteContent_i : in std_logic;
- outboundWriteContentData_i : in std_logic_vector(31 downto 0);
+ outboundWriteContentData_i : in std_logic_vector(CONTENT_WIDTH-1 downto 0);
outboundReadFrameEmpty_o : out std_logic;
outboundReadFrame_i : in std_logic;
outboundReadFrameRestart_i : in std_logic;
outboundReadFrameAborted_o : out std_logic;
+ outboundReadFrameSize_o : out std_logic_vector(CONTENT_ADDRESS_WIDTH-1 downto 0);
outboundReadContentEmpty_o : out std_logic;
outboundReadContent_i : in std_logic;
outboundReadContentEnd_o : out std_logic;
- outboundReadContentData_o : out std_logic_vector(31 downto 0));
+ outboundReadContentData_o : out std_logic_vector(CONTENT_WIDTH-1 downto 0));
end entity;
@@ -102,7 +117,9 @@
component PacketBufferContinous is
generic(
SIZE_ADDRESS_WIDTH : natural;
- CONTENT_ADDRESS_WIDTH : natural);
+ CONTENT_ADDRESS_WIDTH : natural;
+ CONTENT_WIDTH : natural;
+ MAX_PACKET_SIZE : natural);
port(
clk : in std_logic;
areset_n : in std_logic;
@@ -111,16 +128,17 @@
writeFrame_i : in std_logic;
writeFrameAbort_i : in std_logic;
writeContent_i : in std_logic;
- writeContentData_i : in std_logic_vector(31 downto 0);
+ writeContentData_i : in std_logic_vector(CONTENT_WIDTH-1 downto 0);
readFrameEmpty_o : out std_logic;
readFrame_i : in std_logic;
readFrameRestart_i : in std_logic;
readFrameAborted_o : out std_logic;
+ readFrameSize_o : out std_logic_vector(CONTENT_ADDRESS_WIDTH-1 downto 0);
readContentEmpty_o : out std_logic;
readContent_i : in std_logic;
readContentEnd_o : out std_logic;
- readContentData_o : out std_logic_vector(31 downto 0));
+ readContentData_o : out std_logic_vector(CONTENT_WIDTH-1 downto 0));
end component;
begin
@@ -131,7 +149,9 @@
OutboundPacketBuffer: PacketBufferContinous
generic map(
SIZE_ADDRESS_WIDTH=>SIZE_ADDRESS_WIDTH,
- CONTENT_ADDRESS_WIDTH=>CONTENT_ADDRESS_WIDTH)
+ CONTENT_ADDRESS_WIDTH=>CONTENT_ADDRESS_WIDTH,
+ CONTENT_WIDTH=>CONTENT_WIDTH,
+ MAX_PACKET_SIZE=>MAX_PACKET_SIZE)
port map(
clk=>clk,
areset_n=>areset_n,
@@ -142,6 +162,7 @@
readFrameEmpty_o=>outboundReadFrameEmpty_o,
readFrame_i=>outboundReadFrame_i, readFrameRestart_i=>outboundReadFrameRestart_i,
readFrameAborted_o=>outboundReadFrameAborted_o,
+ readFrameSize_o=>outboundReadFrameSize_o,
readContentEmpty_o=>outboundReadContentEmpty_o,
readContent_i=>outboundReadContent_i, readContentEnd_o=>outboundReadContentEnd_o,
readContentData_o=>outboundReadContentData_o);
@@ -152,7 +173,9 @@
InboundPacketBuffer: PacketBufferContinous
generic map(
SIZE_ADDRESS_WIDTH=>SIZE_ADDRESS_WIDTH,
- CONTENT_ADDRESS_WIDTH=>CONTENT_ADDRESS_WIDTH)
+ CONTENT_ADDRESS_WIDTH=>CONTENT_ADDRESS_WIDTH,
+ CONTENT_WIDTH=>CONTENT_WIDTH,
+ MAX_PACKET_SIZE=>MAX_PACKET_SIZE)
port map(
clk=>clk,
areset_n=>areset_n,
@@ -163,6 +186,7 @@
readFrameEmpty_o=>inboundReadFrameEmpty_o,
readFrame_i=>inboundReadFrame_i, readFrameRestart_i=>inboundReadFrameRestart_i,
readFrameAborted_o=>inboundReadFrameAborted_o,
+ readFrameSize_o=>inboundReadFrameSize_o,
readContentEmpty_o=>inboundReadContentEmpty_o,
readContent_i=>inboundReadContent_i, readContentEnd_o=>inboundReadContentEnd_o,
readContentData_o=>inboundReadContentData_o);
@@ -188,7 +212,9 @@
entity RioPacketBufferWindow is
generic(
SIZE_ADDRESS_WIDTH : natural := 6;
- CONTENT_ADDRESS_WIDTH : natural := 8);
+ CONTENT_ADDRESS_WIDTH : natural := 8;
+ CONTENT_WIDTH : natural := 32;
+ MAX_PACKET_SIZE : natural := 69);
port(
clk : in std_logic;
areset_n : in std_logic;
@@ -197,7 +223,7 @@
inboundWriteFrame_i : in std_logic;
inboundWriteFrameAbort_i : in std_logic;
inboundWriteContent_i : in std_logic;
- inboundWriteContentData_i : in std_logic_vector(31 downto 0);
+ inboundWriteContentData_i : in std_logic_vector(CONTENT_WIDTH-1 downto 0);
inboundReadFrameEmpty_o : out std_logic;
inboundReadFrame_i : in std_logic;
inboundReadFrameRestart_i : in std_logic;
@@ -205,13 +231,13 @@
inboundReadContentEmpty_o : out std_logic;
inboundReadContent_i : in std_logic;
inboundReadContentEnd_o : out std_logic;
- inboundReadContentData_o : out std_logic_vector(31 downto 0);
+ inboundReadContentData_o : out std_logic_vector(CONTENT_WIDTH-1 downto 0);
outboundWriteFrameFull_o : out std_logic;
outboundWriteFrame_i : in std_logic;
outboundWriteFrameAbort_i : in std_logic;
outboundWriteContent_i : in std_logic;
- outboundWriteContentData_i : in std_logic_vector(31 downto 0);
+ outboundWriteContentData_i : in std_logic_vector(CONTENT_WIDTH-1 downto 0);
outboundReadFrameEmpty_o : out std_logic;
outboundReadFrame_i : in std_logic;
outboundReadFrameRestart_i : in std_logic;
@@ -222,7 +248,7 @@
outboundReadContentEmpty_o : out std_logic;
outboundReadContent_i : in std_logic;
outboundReadContentEnd_o : out std_logic;
- outboundReadContentData_o : out std_logic_vector(31 downto 0));
+ outboundReadContentData_o : out std_logic_vector(CONTENT_WIDTH-1 downto 0));
end entity;
@@ -234,7 +260,9 @@
component PacketBufferContinous is
generic(
SIZE_ADDRESS_WIDTH : natural;
- CONTENT_ADDRESS_WIDTH : natural);
+ CONTENT_ADDRESS_WIDTH : natural;
+ CONTENT_WIDTH : natural;
+ MAX_PACKET_SIZE : natural);
port(
clk : in std_logic;
areset_n : in std_logic;
@@ -243,23 +271,26 @@
writeFrame_i : in std_logic;
writeFrameAbort_i : in std_logic;
writeContent_i : in std_logic;
- writeContentData_i : in std_logic_vector(31 downto 0);
+ writeContentData_i : in std_logic_vector(CONTENT_WIDTH-1 downto 0);
readFrameEmpty_o : out std_logic;
readFrame_i : in std_logic;
readFrameRestart_i : in std_logic;
readFrameAborted_o : out std_logic;
+ readFrameSize_o : out std_logic_vector(CONTENT_ADDRESS_WIDTH-1 downto 0);
readContentEmpty_o : out std_logic;
readContent_i : in std_logic;
readContentEnd_o : out std_logic;
- readContentData_o : out std_logic_vector(31 downto 0));
+ readContentData_o : out std_logic_vector(CONTENT_WIDTH-1 downto 0));
end component;
component PacketBufferContinousWindow is
generic(
SIZE_ADDRESS_WIDTH : natural;
- CONTENT_ADDRESS_WIDTH : natural);
+ CONTENT_ADDRESS_WIDTH : natural;
+ CONTENT_WIDTH : natural;
+ MAX_PACKET_SIZE : natural);
port(
clk : in std_logic;
areset_n : in std_logic;
@@ -268,7 +299,7 @@
writeFrame_i : in std_logic;
writeFrameAbort_i : in std_logic;
writeContent_i : in std_logic;
- writeContentData_i : in std_logic_vector(31 downto 0);
+ writeContentData_i : in std_logic_vector(CONTENT_WIDTH-1 downto 0);
readFrameEmpty_o : out std_logic;
readFrame_i : in std_logic;
@@ -282,7 +313,7 @@
readContentEmpty_o : out std_logic;
readContent_i : in std_logic;
readContentEnd_o : out std_logic;
- readContentData_o : out std_logic_vector(31 downto 0));
+ readContentData_o : out std_logic_vector(CONTENT_WIDTH-1 downto 0));
end component;
begin
@@ -293,7 +324,9 @@
OutboundPacketBuffer: PacketBufferContinousWindow
generic map(
SIZE_ADDRESS_WIDTH=>SIZE_ADDRESS_WIDTH,
- CONTENT_ADDRESS_WIDTH=>CONTENT_ADDRESS_WIDTH)
+ CONTENT_ADDRESS_WIDTH=>CONTENT_ADDRESS_WIDTH,
+ CONTENT_WIDTH=>CONTENT_WIDTH,
+ MAX_PACKET_SIZE=>MAX_PACKET_SIZE)
port map(
clk=>clk,
areset_n=>areset_n,
@@ -317,7 +350,9 @@
InboundPacketBuffer: PacketBufferContinous
generic map(
SIZE_ADDRESS_WIDTH=>SIZE_ADDRESS_WIDTH,
- CONTENT_ADDRESS_WIDTH=>CONTENT_ADDRESS_WIDTH)
+ CONTENT_ADDRESS_WIDTH=>CONTENT_ADDRESS_WIDTH,
+ CONTENT_WIDTH=>CONTENT_WIDTH,
+ MAX_PACKET_SIZE=>MAX_PACKET_SIZE)
port map(
clk=>clk,
areset_n=>areset_n,
@@ -328,6 +363,7 @@
readFrameEmpty_o=>inboundReadFrameEmpty_o,
readFrame_i=>inboundReadFrame_i, readFrameRestart_i=>inboundReadFrameRestart_i,
readFrameAborted_o=>inboundReadFrameAborted_o,
+ readFrameSize_o=>open,
readContentEmpty_o=>inboundReadContentEmpty_o,
readContent_i=>inboundReadContent_i, readContentEnd_o=>inboundReadContentEnd_o,
readContentData_o=>inboundReadContentData_o);
@@ -355,7 +391,9 @@
entity PacketBufferContinous is
generic(
SIZE_ADDRESS_WIDTH : natural;
- CONTENT_ADDRESS_WIDTH : natural);
+ CONTENT_ADDRESS_WIDTH : natural;
+ CONTENT_WIDTH : natural;
+ MAX_PACKET_SIZE : natural);
port(
clk : in std_logic;
areset_n : in std_logic;
@@ -364,17 +402,18 @@
writeFrame_i : in std_logic;
writeFrameAbort_i : in std_logic;
writeContent_i : in std_logic;
- writeContentData_i : in std_logic_vector(31 downto 0);
+ writeContentData_i : in std_logic_vector(CONTENT_WIDTH-1 downto 0);
readFrameEmpty_o : out std_logic;
readFrame_i : in std_logic;
readFrameRestart_i : in std_logic;
readFrameAborted_o : out std_logic;
+ readFrameSize_o : out std_logic_vector(CONTENT_ADDRESS_WIDTH-1 downto 0);
readContentEmpty_o : out std_logic;
readContent_i : in std_logic;
readContentEnd_o : out std_logic;
- readContentData_o : out std_logic_vector(31 downto 0));
+ readContentData_o : out std_logic_vector(CONTENT_WIDTH-1 downto 0));
end entity;
@@ -458,7 +497,7 @@
-----------------------------------------------------------------------------
writeFrameFull_o <= '1' when ((backIndexNext = frontIndex) or
- (available <= 68)) else '0';
+ (available < MAX_PACKET_SIZE)) else '0';
Writer: process(clk, areset_n)
begin
@@ -510,6 +549,7 @@
readFrameEmpty_o <= '1' when (frontIndex = backIndex) else '0';
readContentEmpty_o <= '1' when ((frontIndex = backIndex) and
(memoryWrite_p = memoryRead_p)) else '0';
+ readFrameSize_o <= std_logic_vector(readFrameEnd_p - memoryStart_p);
Reader: process(clk, areset_n)
begin
@@ -563,7 +603,7 @@
-- REMARK: Use paritybits here as well to make sure the frame data does not
-- become corrupt???
FrameContent: MemorySimpleDualPort
- generic map(ADDRESS_WIDTH=>CONTENT_ADDRESS_WIDTH, DATA_WIDTH=>32)
+ generic map(ADDRESS_WIDTH=>CONTENT_ADDRESS_WIDTH, DATA_WIDTH=>CONTENT_WIDTH)
port map(
clkA_i=>clk, enableA_i=>writeContent_i,
addressA_i=>std_logic_vector(memoryWrite_p), dataA_i=>writeContentData_i,
@@ -592,7 +632,9 @@
entity PacketBufferContinousWindow is
generic(
SIZE_ADDRESS_WIDTH : natural;
- CONTENT_ADDRESS_WIDTH : natural);
+ CONTENT_ADDRESS_WIDTH : natural;
+ CONTENT_WIDTH : natural;
+ MAX_PACKET_SIZE : natural);
port(
clk : in std_logic;
areset_n : in std_logic;
@@ -601,7 +643,7 @@
writeFrame_i : in std_logic;
writeFrameAbort_i : in std_logic;
writeContent_i : in std_logic;
- writeContentData_i : in std_logic_vector(31 downto 0);
+ writeContentData_i : in std_logic_vector(CONTENT_WIDTH-1 downto 0);
readFrameEmpty_o : out std_logic;
readFrame_i : in std_logic;
@@ -615,7 +657,7 @@
readContentEmpty_o : out std_logic;
readContent_i : in std_logic;
readContentEnd_o : out std_logic;
- readContentData_o : out std_logic_vector(31 downto 0));
+ readContentData_o : out std_logic_vector(CONTENT_WIDTH-1 downto 0));
end entity;
@@ -701,7 +743,7 @@
-----------------------------------------------------------------------------
writeFrameFull_o <= '1' when ((backIndexNext = frontIndex) or
- (available <= 68)) else '0';
+ (available < MAX_PACKET_SIZE)) else '0';
Writer: process(clk, areset_n)
begin
@@ -821,7 +863,7 @@
-- REMARK: Use paritybits here as well to make sure the frame data does not
-- become corrupt???
FrameContent: MemorySimpleDualPort
- generic map(ADDRESS_WIDTH=>CONTENT_ADDRESS_WIDTH, DATA_WIDTH=>32)
+ generic map(ADDRESS_WIDTH=>CONTENT_ADDRESS_WIDTH, DATA_WIDTH=>CONTENT_WIDTH)
port map(
clkA_i=>clk, enableA_i=>writeContent_i,
addressA_i=>std_logic_vector(memoryWrite_p), dataA_i=>writeContentData_i,
/trunk/rtl/vhdl/RioPcsUart.vhd
0,0 → 1,641
------------------------------------------------------------------------------- |
-- |
-- RapidIO IP Library Core |
-- |
-- This file is part of the RapidIO IP library project |
-- http://www.opencores.org/cores/rio/ |
-- |
-- Description |
-- This file contains a PCS (Physical Control Sublayer) that can transfer |
-- RapidIO symbols accross a 2Mbit 8-bit UART transmission channel. |
-- The coding is similar to the coding used by PPP and uses flags (0x7e) |
-- and escape-sequences (0x7d) to encode special characters. |
-- |
-- To Do: |
-- - |
-- |
-- 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 |
-- |
------------------------------------------------------------------------------- |
|
------------------------------------------------------------------------------- |
-- RioPcsUart |
------------------------------------------------------------------------------- |
library ieee; |
use ieee.std_logic_1164.all; |
use ieee.numeric_std.all; |
use work.rio_common.all; |
|
|
------------------------------------------------------------------------------- |
-- Entity for RioPcsUart. |
------------------------------------------------------------------------------- |
entity RioPcsUart is |
generic( |
DIVISOR_WIDTH : natural); |
port( |
clk : in std_logic; |
areset_n : in std_logic; |
|
divisor_i : in std_logic_vector(DIVISOR_WIDTH-1 downto 0); |
|
portInitialized_o : out std_logic; |
outboundSymbolEmpty_i : in std_logic; |
outboundSymbolRead_o : out std_logic; |
outboundSymbol_i : in std_logic_vector(33 downto 0); |
inboundSymbolFull_i : in std_logic; |
inboundSymbolWrite_o : out std_logic; |
inboundSymbol_o : out std_logic_vector(33 downto 0); |
|
serial_o : out std_logic; |
serial_i : in std_logic); |
end entity; |
|
|
------------------------------------------------------------------------------- |
-- Architecture for RioPcsUart. |
------------------------------------------------------------------------------- |
architecture RioPcsUartImpl of RioPcsUart is |
|
component RioSymbolConverter is |
port( |
clk : in std_logic; |
areset_n : in std_logic; |
|
portInitialized_o : out std_logic; |
outboundSymbolEmpty_i : in std_logic; |
outboundSymbolRead_o : out std_logic; |
outboundSymbol_i : in std_logic_vector(33 downto 0); |
inboundSymbolFull_i : in std_logic; |
inboundSymbolWrite_o : out std_logic; |
inboundSymbol_o : out std_logic_vector(33 downto 0); |
|
uartEmpty_i : in std_logic; |
uartRead_o : out std_logic; |
uartData_i : in std_logic_vector(7 downto 0); |
uartFull_i : in std_logic; |
uartWrite_o : out std_logic; |
uartData_o : out std_logic_vector(7 downto 0)); |
end component; |
|
component Uart is |
generic( |
DIVISOR_WIDTH : natural; |
DATA_WIDTH : natural); |
port( |
clk : in std_logic; |
areset_n : in std_logic; |
|
divisor_i : in std_logic_vector(DIVISOR_WIDTH-1 downto 0); |
|
serial_i : in std_logic; |
serial_o : out std_logic; |
|
empty_o : out std_logic; |
read_i : in std_logic; |
data_o : out std_logic_vector(DATA_WIDTH-1 downto 0); |
|
full_o : out std_logic; |
write_i : in std_logic; |
data_i : in std_logic_vector(DATA_WIDTH-1 downto 0)); |
end component; |
|
signal uartEmpty : std_logic; |
signal uartRead : std_logic; |
signal uartReadData : std_logic_vector(7 downto 0); |
signal uartFull : std_logic; |
signal uartWrite : std_logic; |
signal uartWriteData : std_logic_vector(7 downto 0); |
|
begin |
|
SymbolConverter: RioSymbolConverter |
port map( |
clk=>clk, areset_n=>areset_n, |
portInitialized_o=>portInitialized_o, |
outboundSymbolEmpty_i=>outboundSymbolEmpty_i, |
outboundSymbolRead_o=>outboundSymbolRead_o, outboundSymbol_i=>outboundSymbol_i, |
inboundSymbolFull_i=>inboundSymbolFull_i, |
inboundSymbolWrite_o=>inboundSymbolWrite_o, inboundSymbol_o=>inboundSymbol_o, |
uartEmpty_i=>uartEmpty, uartRead_o=>uartRead, uartData_i=>uartReadData, |
uartFull_i=>uartFull, uartWrite_o=>uartWrite, uartData_o=>uartWriteData); |
|
UartInst: Uart |
generic map(DIVISOR_WIDTH=>DIVISOR_WIDTH, DATA_WIDTH=>8) |
port map( |
clk=>clk, areset_n=>areset_n, |
divisor_i=>divisor_i, |
serial_i=>serial_i, serial_o=>serial_o, |
empty_o=>uartEmpty, read_i=>uartRead, data_o=>uartReadData, |
full_o=>uartFull, write_i=>uartWrite, data_i=>uartWriteData); |
|
end architecture; |
|
|
|
------------------------------------------------------------------------------- |
-- This module encodes and decodes RapidIO symbols for transmission on a 8-bit |
-- UART using HDLC-like framing (see PPP). |
-- When an idle-symbol is received it will be preceeded by an idle link for a |
-- few micro seconds. This idle link time is used to synchronize the receiver |
-- in the link partner that needs to know when a character is starting and not. |
------------------------------------------------------------------------------- |
library ieee; |
use ieee.std_logic_1164.all; |
use ieee.numeric_std.all; |
use work.rio_common.all; |
|
|
------------------------------------------------------------------------------- |
-- Entity for RioSymbolConverter. |
------------------------------------------------------------------------------- |
entity RioSymbolConverter is |
port( |
clk : in std_logic; |
areset_n : in std_logic; |
|
portInitialized_o : out std_logic; |
outboundSymbolEmpty_i : in std_logic; |
outboundSymbolRead_o : out std_logic; |
outboundSymbol_i : in std_logic_vector(33 downto 0); |
inboundSymbolFull_i : in std_logic; |
inboundSymbolWrite_o : out std_logic; |
inboundSymbol_o : out std_logic_vector(33 downto 0); |
|
uartEmpty_i : in std_logic; |
uartRead_o : out std_logic; |
uartData_i : in std_logic_vector(7 downto 0); |
uartFull_i : in std_logic; |
uartWrite_o : out std_logic; |
uartData_o : out std_logic_vector(7 downto 0)); |
end entity; |
|
|
------------------------------------------------------------------------------- |
-- Architecture for RioSymbolConverter. |
------------------------------------------------------------------------------- |
architecture RioSymbolConverterImpl of RioSymbolConverter is |
|
-- Define the flag sequence and the control escape sequence. |
constant FLAG_SEQUENCE : std_logic_vector(7 downto 0) := x"7e"; |
constant CONTROL_ESCAPE : std_logic_vector(7 downto 0) := x"7d"; |
constant SILENCE_TIME : natural := 4095; |
constant IDLE_SYMBOL_TIME : natural := 256; |
constant LINK_LOST_TIME : natural := 4095; |
|
type TxStateType is (STATE_SILENCE, STATE_IDLE_0, STATE_IDLE_1, |
STATE_BUSY_1, STATE_BUSY_2, STATE_SEND_FLAG); |
signal txState : TxStateType; |
signal txStateCounter : unsigned(1 downto 0); |
signal outboundSymbolData : std_logic_vector(7 downto 0); |
|
type RxStateType is (STATE_INIT, STATE_NORMAL); |
signal rxState : RxStateType; |
signal rxStateCounter : unsigned(1 downto 0); |
signal escapeFound : std_logic; |
|
signal txTimerReset : std_logic; |
signal txTimerEnable : std_logic; |
signal txTimerCounter : unsigned(11 downto 0); |
signal silenceTxTimerDone : std_logic; |
signal idleTxTimerDone : std_logic; |
|
signal rxTimerReset : std_logic; |
signal rxTimerEnable : std_logic; |
signal rxTimerCounter : unsigned(11 downto 0); |
signal lostRxTimerDone : std_logic; |
|
signal uartWrite : std_logic; |
signal uartRead : std_logic; |
|
begin |
|
-- Set the port initialized once the receiver enters its normal state. |
portInitialized_o <= '1' when (rxState = STATE_NORMAL) else '0'; |
|
----------------------------------------------------------------------------- |
-- Timer functionallity. |
----------------------------------------------------------------------------- |
|
silenceTxTimerDone <= '1' when (txTimerCounter = SILENCE_TIME) else '0'; |
idleTxTimerDone <= '1' when (txTimerCounter = IDLE_SYMBOL_TIME) else '0'; |
|
process(areset_n, clk) |
begin |
if (areset_n = '0') then |
txTimerCounter <= (others => '0'); |
elsif (clk'event and clk = '1') then |
if (txTimerReset = '1') then |
txTimerCounter <= (others => '0'); |
elsif (txTimerEnable = '1') then |
txTimerCounter <= txTimerCounter + 1; |
end if; |
end if; |
end process; |
|
lostRxTimerDone <= '1' when (rxTimerCounter = LINK_LOST_TIME) else '0'; |
|
process(areset_n, clk) |
begin |
if (areset_n = '0') then |
rxTimerCounter <= (others => '0'); |
elsif (clk'event and clk = '1') then |
if (rxTimerReset = '1') then |
rxTimerCounter <= (others => '0'); |
elsif (rxTimerEnable = '1') then |
rxTimerCounter <= rxTimerCounter + 1; |
end if; |
end if; |
end process; |
|
----------------------------------------------------------------------------- |
-- Link symbol encoder process. |
----------------------------------------------------------------------------- |
outboundSymbolData <= outboundSymbol_i(31 downto 24) when txStateCounter = 0 else |
outboundSymbol_i(23 downto 16) when txStateCounter = 1 else |
outboundSymbol_i(15 downto 8) when txStateCounter = 2 else |
outboundSymbol_i(7 downto 0); |
|
uartWrite_o <= uartWrite; |
Outbound: process(areset_n, clk) |
begin |
if (areset_n = '0') then |
txState <= STATE_SILENCE; |
txStateCounter <= (others => '0'); |
|
txTimerReset <= '0'; |
txTimerEnable <= '0'; |
|
outboundSymbolRead_o <= '0'; |
|
uartWrite <= '0'; |
uartData_o <= (others => '0'); |
elsif (clk'event and clk = '1') then |
txTimerReset <= '0'; |
outboundSymbolRead_o <= '0'; |
uartWrite <= '0'; |
|
-- Check if the UART is ready for new data. |
if (uartFull_i = '0') and (uartWrite = '0') then |
-- The UART want new data to transmitt. |
|
-- Check the transmission state. |
case txState is |
|
when STATE_SILENCE => |
------------------------------------------------------------------- |
-- Wait for a while to let the linkpartner detect a link break. |
------------------------------------------------------------------- |
-- Check if the silence timer has expired. |
if (silenceTxTimerDone = '1') then |
-- Silence timer expired. |
-- Reset the timer and proceed to transmitting symbols. |
txTimerReset <= '1'; |
txTimerEnable <= '0'; |
txState <= STATE_IDLE_0; |
else |
txTimerEnable <= '1'; |
end if; |
|
when STATE_IDLE_0 => |
----------------------------------------------------------------- |
-- Wait for a new symbol to be received. An idle symbol is followed |
-- by a small inter-character idle time to let the receiver in the |
-- link partner synchronize itself to the link. |
----------------------------------------------------------------- |
|
-- Reset the state counter for the symbol generation. |
txStateCounter <= "00"; |
|
-- Check if a new symbol is available. |
if (outboundSymbolEmpty_i = '0') then |
-- A new symbol is available. |
|
-- Check if the new symbol is idle, control or data. |
if (outboundSymbol_i(33 downto 32) /= SYMBOL_IDLE) then |
-- Control or data symbol. |
txState <= STATE_BUSY_1; |
else |
-- Send idle sequence. |
txState <= STATE_IDLE_1; |
end if; |
else |
-- No new symbols are ready. |
-- Dont do anything. |
end if; |
|
when STATE_IDLE_1 => |
------------------------------------------------------------------- |
-- Wait until the idle timer has expired to let the link be idle in |
-- between idle symbols. |
------------------------------------------------------------------- |
|
-- Check if the idle timer has expired. |
if (idleTxTimerDone = '1') then |
-- Idle timer has expired. |
-- Reset the timer and disable it. |
txTimerReset <= '1'; |
txTimerEnable <= '0'; |
|
-- Write a flag to indicate idle link. |
uartWrite <= '1'; |
uartData_o <= FLAG_SEQUENCE; |
|
-- Get a new symbol. |
outboundSymbolRead_o <= '1'; |
txState <= STATE_IDLE_0; |
else |
-- Idle timer has not expired yet. |
txTimerEnable <= '1'; |
end if; |
|
when STATE_BUSY_1 => |
----------------------------------------------------------------- |
-- Encode a control or data symbol. If stuffing is needed the next |
-- busy state is called. |
----------------------------------------------------------------- |
|
-- Check if the octet is a flag or escape character. |
if ((outboundSymbolData = FLAG_SEQUENCE) or |
(outboundSymbolData = CONTROL_ESCAPE)) then |
-- Flag or escape octet. |
uartWrite <= '1'; |
uartData_o <= CONTROL_ESCAPE; |
txState <= STATE_BUSY_2; |
else |
-- Ordinary octet. |
|
-- Write the octet to the uart. |
uartWrite <= '1'; |
uartData_o <= outboundSymbolData; |
|
-- Update to the next octet in the symbol. |
txStateCounter <= txStateCounter + 1; |
|
-- Check if the symbol has been sent. |
if (txStateCounter = 3) then |
-- Data symbol sent. |
outboundSymbolRead_o <= '1'; |
txState <= STATE_IDLE_0; |
elsif ((txStateCounter = 2) and |
(outboundSymbol_i(33 downto 32) /= SYMBOL_DATA)) then |
-- Control symbol sent. |
txState <= STATE_SEND_FLAG; |
else |
-- Symbol not completly sent. |
txState <= STATE_BUSY_1; |
end if; |
end if; |
|
when STATE_BUSY_2 => |
----------------------------------------------------------------- |
-- Byte stuff a flag or escape sequence found in the symbol data |
-- content. |
----------------------------------------------------------------- |
|
-- Byte stuff the control character. |
uartWrite <= '1'; |
uartData_o <= outboundSymbolData xor x"20"; |
|
-- Update to the next symbol. |
txStateCounter <= txStateCounter + 1; |
|
-- Check if the symbol has been sent. |
if (txStateCounter = 3) then |
-- Data symbol sent. |
outboundSymbolRead_o <= '1'; |
txState <= STATE_IDLE_0; |
elsif ((txStateCounter = 2) and |
(outboundSymbol_i(33 downto 32) /= SYMBOL_DATA)) then |
-- Control symbol sent. |
txState <= STATE_SEND_FLAG; |
else |
-- Symbol not completly sent. |
txState <= STATE_BUSY_1; |
end if; |
|
when STATE_SEND_FLAG => |
----------------------------------------------------------------- |
-- Force a flag to be written to the link. |
----------------------------------------------------------------- |
|
uartWrite <= '1'; |
uartData_o <= FLAG_SEQUENCE; |
outboundSymbolRead_o <= '1'; |
txState <= STATE_IDLE_0; |
|
when others => |
----------------------------------------------------------------- |
-- Unknown state. |
----------------------------------------------------------------- |
txState <= STATE_IDLE_0; |
|
end case; |
else |
-- The UART is busy transmitting. |
-- Wait for the UART to complete. |
end if; |
end if; |
end process; |
|
|
----------------------------------------------------------------------------- |
-- Link symbol decoder process. |
----------------------------------------------------------------------------- |
uartRead_o <= uartRead; |
Inbound: process(areset_n, clk) |
begin |
if (areset_n = '0') then |
rxState <= STATE_INIT; |
rxStateCounter <= (others => '0'); |
escapeFound <= '0'; |
|
rxTimerReset <= '0'; |
rxTimerEnable <= '0'; |
|
inboundSymbolWrite_o <= '0'; |
inboundSymbol_o <= (others => '0'); |
|
uartRead <= '0'; |
elsif (clk'event and clk = '1') then |
rxTimerReset <= '0'; |
inboundSymbolWrite_o <= '0'; |
uartRead <= '0'; |
|
case rxState is |
|
when STATE_INIT => |
------------------------------------------------------------------- |
-- Wait for a flag to be received. |
------------------------------------------------------------------- |
-- Check if any new data is ready. |
if (uartRead = '0') and (uartEmpty_i = '0') then |
-- New data is ready from the uart. |
|
-- Check if a flag has been received. |
if (uartData_i = FLAG_SEQUENCE) then |
-- A flag has been received. |
-- Considder the port to be initialized. |
rxState <= STATE_NORMAL; |
rxStateCounter <= (others => '0'); |
escapeFound <= '0'; |
rxTimerReset <= '1'; |
rxTimerEnable <= '1'; |
uartRead <= '1'; |
else |
-- Something that is not a flag has been received. |
-- Discard the data and wait for a flag. |
uartRead <= '1'; |
end if; |
else |
-- Waiting for inbound data. |
-- Dont do anything. |
end if; |
|
when STATE_NORMAL => |
------------------------------------------------------------------- |
-- Parse the incoming stream and create symbols. |
------------------------------------------------------------------- |
|
-- Check if the link lost timer has expired. |
if (lostRxTimerDone = '1') then |
-- The link lost timer has expired. |
-- Reset the timer, disable it and go back to the initial state. |
rxTimerReset <= '1'; |
rxTimerEnable <= '0'; |
rxState <= STATE_INIT; |
else |
-- The link lost timer has not expired. |
|
-- Check if any new data is ready. |
if (uartRead = '0') and (uartEmpty_i = '0') then |
-- New data is ready from the uart. |
|
-- Reset the link lost timer. |
rxTimerReset <= '1'; |
|
-- Check if a flag has been received. |
if (uartData_i /= FLAG_SEQUENCE) then |
-- The received octet was not a flag. |
|
-- Check if the octet was a contol character. |
if (uartData_i /= CONTROL_ESCAPE) then |
-- The octet was not a control character. |
|
-- Check where in a symbol the reception is. |
case rxStateCounter is |
|
when "00" => |
inboundSymbol_o(33 downto 32) <= SYMBOL_IDLE; |
if (escapeFound = '0') then |
inboundSymbol_o(31 downto 24) <= uartData_i; |
else |
inboundSymbol_o(31 downto 24) <= uartData_i xor x"20"; |
end if; |
rxStateCounter <= rxStateCounter + 1; |
|
when "01" => |
inboundSymbol_o(33 downto 32) <= SYMBOL_IDLE; |
if (escapeFound = '0') then |
inboundSymbol_o(23 downto 16) <= uartData_i; |
else |
inboundSymbol_o(23 downto 16) <= uartData_i xor x"20"; |
end if; |
rxStateCounter <= rxStateCounter + 1; |
|
when "10" => |
inboundSymbol_o(33 downto 32) <= SYMBOL_CONTROL; |
if (escapeFound = '0') then |
inboundSymbol_o(15 downto 8) <= uartData_i; |
else |
inboundSymbol_o(15 downto 8) <= uartData_i xor x"20"; |
end if; |
rxStateCounter <= rxStateCounter + 1; |
|
when "11" => |
inboundSymbol_o(33 downto 32) <= SYMBOL_DATA; |
if (escapeFound = '0') then |
inboundSymbol_o(7 downto 0) <= uartData_i; |
else |
inboundSymbol_o(7 downto 0) <= uartData_i xor x"20"; |
end if; |
rxStateCounter <= rxStateCounter + 1; |
inboundSymbolWrite_o <= '1'; |
|
when others => |
rxStateCounter <= "00"; |
|
end case; |
|
-- Read the octet from the uart. |
uartRead <= '1'; |
escapeFound <= '0'; |
else |
-- Control escape received. |
|
-- Read the octet and indicate that an escape character has been received. |
uartRead <= '1'; |
escapeFound <= '1'; |
end if; |
else |
-- Flag received. |
|
-- Check if there are any unsent symbols pending. |
if (rxStateCounter = 0) then |
-- No pending symbol. |
-- Send an idle symbol. |
inboundSymbolWrite_o <= '1'; |
inboundSymbol_o(33 downto 32) <= SYMBOL_IDLE; |
else |
-- Pending symbol. |
-- Send the pending symbol. |
inboundSymbolWrite_o <= '1'; |
end if; |
|
-- Read and discard the octet. |
uartRead <= '1'; |
rxStateCounter <= "00"; |
end if; |
else |
-- Waiting for inbound data. |
-- Dont do anything. |
end if; |
end if; |
|
when others => |
------------------------------------------------------------------- |
-- Unknown state. |
------------------------------------------------------------------- |
null; |
|
end case; |
end if; |
end process; |
|
end architecture; |
trunk/rtl/vhdl/RioPcsUart.vhd
Property changes :
Added: svn:executable
## -0,0 +1 ##
+*
\ No newline at end of property
Index: trunk/rtl/vhdl/Uart.vhd
===================================================================
--- trunk/rtl/vhdl/Uart.vhd (nonexistent)
+++ trunk/rtl/vhdl/Uart.vhd (revision 20)
@@ -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
+-- Generic UART with FIFO interface.
+--
+-- To Do:
+-- -
+--
+-- 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
+--
+-------------------------------------------------------------------------------
+
+-------------------------------------------------------------------------------
+-- Uart implementation.
+-------------------------------------------------------------------------------
+
+library ieee;
+use ieee.std_logic_1164.all;
+use ieee.numeric_std.all;
+
+
+-------------------------------------------------------------------------------
+-- Entity for Uart.
+-------------------------------------------------------------------------------
+entity Uart is
+ generic(
+ DIVISOR_WIDTH : natural;
+ DATA_WIDTH : natural);
+ port(
+ clk : in std_logic;
+ areset_n : in std_logic;
+
+ divisor_i : in std_logic_vector(DIVISOR_WIDTH-1 downto 0);
+
+ serial_i : in std_logic;
+ serial_o : out std_logic;
+
+ empty_o : out std_logic;
+ read_i : in std_logic;
+ data_o : out std_logic_vector(DATA_WIDTH-1 downto 0);
+
+ full_o : out std_logic;
+ write_i : in std_logic;
+ data_i : in std_logic_vector(DATA_WIDTH-1 downto 0));
+end entity;
+
+
+-------------------------------------------------------------------------------
+-- Architecture for Uart.
+-------------------------------------------------------------------------------
+architecture UartImpl of Uart is
+ signal bitDuration : unsigned(DIVISOR_WIDTH-1 downto 0);
+ signal bitSample : unsigned(DIVISOR_WIDTH-1 downto 0);
+
+ type StateTypeRx is (STATE_INIT, STATE_IDLE,
+ STATE_START, STATE_DATA, STATE_STOP);
+ signal rxState : StateTypeRx;
+ signal rxShifter : std_logic_vector(DATA_WIDTH-1 downto 0);
+ signal rxCounter : unsigned(DIVISOR_WIDTH-1 downto 0);
+ signal rxBitCounter : natural range 0 to DATA_WIDTH-1;
+ signal rxComplete : std_logic;
+ signal rxData : std_logic_vector(DATA_WIDTH-1 downto 0);
+
+ type StateTypeRxFifo is (STATE_EMPTY, STATE_WAITREAD);
+ signal rxFifoState : StateTypeRxFifo;
+
+ type StateTypeTx is (STATE_IDLE, STATE_SEND);
+ signal txState : StateTypeTx;
+ signal txShifter : std_logic_vector(DATA_WIDTH downto 0);
+ signal txCounter : unsigned(DIVISOR_WIDTH-1 downto 0);
+ signal txBitCounter : natural range 0 to DATA_WIDTH+1;
+
+begin
+
+ -- Setup the tick values when a bit is complete and when to sample it.
+ bitDuration <= unsigned(divisor_i);
+ bitSample <= '0' & unsigned(divisor_i(DIVISOR_WIDTH-1 downto 1));
+
+ -----------------------------------------------------------------------------
+ -- UART receiving process.
+ -----------------------------------------------------------------------------
+ Receiver: process(clk, areset_n)
+ begin
+ if (areset_n = '0') then
+ rxState <= STATE_INIT;
+ rxShifter <= (others => '0');
+ rxBitCounter <= 0;
+ rxCounter <= (others => '0');
+
+ rxComplete <= '0';
+ rxData <= (others => '0');
+ elsif (clk'event and (clk = '1')) then
+ rxComplete <= '0';
+
+ case rxState is
+
+ when STATE_INIT =>
+ ---------------------------------------------------------------------
+ -- Wait for the line to become idle.
+ ---------------------------------------------------------------------
+ if (serial_i = '1') then
+ rxState <= STATE_IDLE;
+ end if;
+
+ when STATE_IDLE =>
+ ---------------------------------------------------------------------
+ -- Wait for a long enough start pulse.
+ ---------------------------------------------------------------------
+ if (serial_i = '0') then
+ -- The serial input is zero, indicating a start bit.
+
+ -- Check how long it has been zero.
+ if (rxCounter = bitSample) then
+ -- It has been zero long enough.
+ -- Proceed to read the full start bit before starting to sample
+ -- the data.
+ rxState <= STATE_START;
+ else
+ -- Stay in this state until it has lasted long enough.
+ end if;
+
+ -- Update to next sampling interval.
+ rxCounter <= rxCounter + 1;
+ else
+ -- The serial input is not zero.
+ -- Restart the sampling interval.
+ rxCounter <= (others => '0');
+ end if;
+
+ when STATE_START =>
+ ---------------------------------------------------------------------
+ -- Wait for the startbit to end.
+ ---------------------------------------------------------------------
+ if (rxCounter = bitDuration) then
+ rxCounter <= (others => '0');
+ rxState <= STATE_DATA;
+ else
+ rxCounter <= rxCounter + 1;
+ end if;
+
+ when STATE_DATA =>
+ ---------------------------------------------------------------------
+ -- Sample data bits where it's appropriate.
+ ---------------------------------------------------------------------
+ if (rxCounter = bitDuration) then
+ -- End of bit.
+ -- Check if all the data bits has been read.
+ if (rxBitCounter = (DATA_WIDTH-1)) then
+ -- All data bits read.
+ -- Read the stop bit.
+ rxState <= STATE_STOP;
+ rxBitCounter <= 0;
+ else
+ -- Continue to read more data bits.
+ rxBitCounter <= rxBitCounter + 1;
+ end if;
+
+ -- Restart sampling interval.
+ rxCounter <= (others => '0');
+ elsif (rxCounter = bitSample) then
+ -- Sample the bit and continue to sample until the bit ends.
+ rxShifter <= serial_i & rxShifter((DATA_WIDTH-1) downto 1);
+ rxCounter <= rxCounter + 1;
+ else
+ -- Wait for the middle or the end of the data to be reached.
+ rxCounter <= rxCounter + 1;
+ end if;
+
+ when STATE_STOP =>
+ ---------------------------------------------------------------------
+ -- Sample stop bit where it's appropriate.
+ ---------------------------------------------------------------------
+ if (rxCounter = bitSample) then
+ -- Sample the stop bit.
+
+ -- Check if the stop bit is valid.
+ if (serial_i = '1') then
+ -- The stop bit is ok.
+ -- Forward the read data.
+ rxComplete <= '1';
+ rxData <= rxShifter;
+ else
+ -- The stop bit is not ok.
+ -- Do not forward the data character.
+ end if;
+
+ -- Reset sampling counter and go back to the init state.
+ rxState <= STATE_INIT;
+ rxCounter <= (others => '0');
+ else
+ -- Wait for the middle or the end of the data to be reached.
+ rxCounter <= rxCounter + 1;
+ end if;
+
+ when others =>
+ ---------------------------------------------------------------------
+ -- Undefined state.
+ ---------------------------------------------------------------------
+ rxState <= STATE_IDLE;
+ rxCounter <= (others => '0');
+
+ end case;
+ end if;
+ end process;
+
+ -----------------------------------------------------------------------------
+ -- UART receiver fifo.
+ -----------------------------------------------------------------------------
+ ReceiverFifo: process(clk, areset_n)
+ begin
+ if (areset_n = '0') then
+ empty_o <= '1';
+ data_o <= (others => '0');
+ rxFifoState <= STATE_EMPTY;
+ elsif (clk'event and (clk = '1')) then
+ case rxFifoState is
+
+ when STATE_EMPTY =>
+ -- Wait for data to be forwarded from the UART receiver.
+ if (rxComplete = '1') then
+ -- Indicate there is data to read from.
+ empty_o <= '0';
+ data_o <= rxData;
+ rxFifoState <= STATE_WAITREAD;
+ else
+ -- Wait for data to be received.
+ end if;
+
+ when STATE_WAITREAD =>
+ -- Wait for the data to be read from the output port.
+ if (read_i = '1') then
+ -- The data has been read.
+ empty_o <= '1';
+ rxFifoState <= STATE_EMPTY;
+ end if;
+ -- Check if new data has been forwarded from the UART.
+ if (rxComplete = '1') then
+ -- New data has been forwarded without the output port being read.
+ -- Overrun. Data has been lost.
+ -- REMARK: Indicate this???
+ end if;
+
+ when others =>
+ -- Undefined state.
+ rxFifoState <= STATE_EMPTY;
+ end case;
+ end if;
+ end process;
+
+ -----------------------------------------------------------------------------
+ -- UART transmitter process.
+ -----------------------------------------------------------------------------
+ Transmitter: process(clk, areset_n)
+ begin
+ if (areset_n = '0') then
+ txState <= STATE_IDLE;
+ txShifter <= (others => '0');
+ txBitCounter <= 0;
+ txCounter <= (others => '0');
+
+ full_o <= '0';
+ serial_o <= '1';
+ elsif (clk'event and (clk = '1')) then
+ case txState is
+
+ when STATE_IDLE =>
+ ---------------------------------------------------------------------
+ -- Wait for new data to be input on the input port.
+ ---------------------------------------------------------------------
+ if (write_i = '1') then
+ -- New data present.
+ full_o <= '1';
+ txShifter <= "1" & data_i;
+ txCounter <= (others => '0');
+ txBitCounter <= 0;
+ txState <= STATE_SEND;
+ serial_o <= '0';
+ end if;
+
+ when STATE_SEND =>
+ ---------------------------------------------------------------------
+ -- Wait for the bit to be completly transmitted.
+ ---------------------------------------------------------------------
+ if (txCounter = bitDuration) then
+ -- The bit has been sent.
+
+ -- Check if the full character has been sent.
+ if (txBitCounter = (DATA_WIDTH+1)) then
+ -- Character has been sent.
+ full_o <= '0';
+ txState <= STATE_IDLE;
+ else
+ -- Character has not been sent yet.
+ -- Send the next bit.
+ serial_o <= txShifter(0);
+ txShifter <= "0" & txShifter(DATA_WIDTH downto 1);
+ txBitCounter <= txBitCounter + 1;
+ end if;
+
+ -- Update to the next bit.
+ txCounter <= (others => '0');
+ else
+ -- Wait for the end of the bit.
+ txCounter <= txCounter + 1;
+ end if;
+
+ when others =>
+ ---------------------------------------------------------------------
+ -- Undefined state.
+ ---------------------------------------------------------------------
+ txState <= STATE_IDLE;
+
+ end case;
+ end if;
+ end process;
+
+end architecture;
+
trunk/rtl/vhdl/Uart.vhd
Property changes :
Added: svn:executable
## -0,0 +1 ##
+*
\ No newline at end of property
Index: trunk/sw/stack/riostack.c
===================================================================
--- trunk/sw/stack/riostack.c (nonexistent)
+++ trunk/sw/stack/riostack.c (revision 20)
@@ -0,0 +1,8225 @@
+/*******************************************************************************
+ *
+ * RapidIO IP Library Core
+ *
+ * This file is part of the RapidIO IP library project
+ * http://www.opencores.org/cores/rio/
+ *
+ * Description:
+ * This file contains a software implementation of a RapidIO stack according to
+ * the 2.2 version, part 6, of the standard. Only short control symbols are
+ * supported.
+ *
+ * Symbols are in four flavors, idle, control, data and error. They are abstract
+ * and should be serialized by any implementation to be sent on a transmission
+ * 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
+ * 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.
+ *
+ * -----------------
+ * | OS dependent |
+ * | (your code) |
+ * -----------------
+ * |
+ * -----------------
+ * | RioStack |
+ * -----------------
+ * |
+ * -----------------
+ * | Symbol Codec |
+ * | (your code) |
+ * -----------------
+ * |
+ * -----------------
+ * | Port driver |
+ * -----------------
+ * |
+ * -----------------
+ * | Physical port |
+ * -----------------
+ *
+ * The symbol codec maps a RapidIO symbol to the physical transmission media.
+ *
+ * Some typical patterns to handle this stack are:
+ * Initialization:
+ * RIO_open(...);
+ * RIO_portSetTimeout(...);
+ * ...
+ *
+ * RIO_portSetStatus(1);
+ *
+ * Bottom-half traffic handling:
+ * RIO_portSetTime(...);
+ *
+ * RIO_portAddSymbol(...);
+ * s = RIO_portGetSymbol(...);
+ *
+ *
+ * Receiving packets:
+ * switch(RIO_eventPoll(...))
+ * {
+ * case RIO_EVENT_DOORBELL:
+ * RIO_receiveDoorbell(...);
+ * ...
+ * }
+ * RIO_packetRemove();
+ *
+ * Transmitting packets:
+ * if(RIO_sendAvailable(...))
+ * {
+ * RIO_sendDoorbell(...);
+ * }
+ * ...
+ *
+ * More details about the usage can be found in the module tests in the end of
+ * this file.
+ *
+ * To Do:
+ * -
+ *
+ * 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
+ *
+ *******************************************************************************/
+
+/**
+ * \file riostack.c
+ */
+
+/*******************************************************************************
+ * Includes
+ *******************************************************************************/
+
+#include "riostack.h"
+
+
+/*lint -e961 Allow function like macros. */
+/*lint -e621 Long identifier names allowed to increase readability. */
+/*lint -w2 */
+
+
+/* lint --estring(960,17.4) It is not possible to implement a rio stack without some
+ * pointer arithmetic */
+
+/*******************************************************************************
+ * Local macro definitions
+ *******************************************************************************/
+
+/* Macro to update 5-bit ackId counters. */
+#define ACKID_INC(ackId) (((ackId)+1)&0x1f)
+
+/* Macros to get entries from a control symbol. */
+#define STYPE0_GET(data) ((uint8_t) (((data) >> 21) & 0x00000007u))
+#define PARAMETER0_GET(data) ((uint8_t) (((data) >> 16) & 0x00000001fu))
+#define PARAMETER1_GET(data) ((uint8_t) (((data) >> 11) & 0x00000001fu))
+#define STYPE1_GET(data) ((uint8_t) (((data) >> 8) & 0x00000007u))
+#define CMD_GET(data) ((uint8_t) (((data) >> 5) & 0x00000007u))
+#define CRC5_GET(data) ((uint8_t) (((data) >> 0) & 0x0000001fu))
+
+/* 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 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)]
+
+/* Transmitter frame states. */
+#define TX_FRAME_START ((uint8_t)0u)
+#define TX_FRAME_BODY ((uint8_t)1u)
+
+/* Control symbol constants. */
+#define STYPE0_PACKET_ACCEPTED ((uint8_t)0x00u)
+#define STYPE0_PACKET_RETRY ((uint8_t)0x01u)
+#define STYPE0_PACKET_NOT_ACCEPTED ((uint8_t)0x02u)
+#define STYPE0_RESERVED ((uint8_t)0x03u)
+#define STYPE0_STATUS ((uint8_t)0x04u)
+#define STYPE0_VC_STATUS ((uint8_t)0x05u)
+#define STYPE0_LINK_RESPONSE ((uint8_t)0x06u)
+#define STYPE0_IMPLEMENTATION_DEFINED ((uint8_t)0x07u)
+#define STYPE1_START_OF_PACKET ((uint8_t)0x00u)
+#define STYPE1_STOMP ((uint8_t)0x01u)
+#define STYPE1_END_OF_PACKET ((uint8_t)0x02u)
+#define STYPE1_RESTART_FROM_RETRY ((uint8_t)0x03u)
+#define STYPE1_LINK_REQUEST ((uint8_t)0x04u)
+#define STYPE1_MULTICAST_EVENT ((uint8_t)0x05u)
+#define STYPE1_RESERVED ((uint8_t)0x06u)
+#define STYPE1_NOP ((uint8_t)0x07u)
+
+/* Packet ftype constants. */
+#define FTYPE_REQUEST 0x2
+#define FTYPE_WRITE 0x5
+#define FTYPE_MAINTENANCE 0x8
+#define FTYPE_DOORBELL 0xa
+#define FTYPE_MESSAGE 0xb
+#define FTYPE_RESPONSE 0xd
+
+/* Transaction constants. */
+#define TRANSACTION_MAINT_READ_REQUEST 0
+#define TRANSACTION_MAINT_WRITE_REQUEST 1
+#define TRANSACTION_MAINT_READ_RESPONSE 2
+#define TRANSACTION_MAINT_WRITE_RESPONSE 3
+#define TRANSACTION_WRITE_NWRITE 4
+#define TRANSACTION_WRITE_NWRITER 5
+#define TRANSACTION_REQUEST_NREAD 4
+#define TRANSACTION_RESPONSE_NO_PAYLOAD 0
+#define TRANSACTION_RESPONSE_MESSAGE_RESPONSE 1
+#define TRANSACTION_RESPONSE_WITH_PAYLOAD 8
+
+/* Maintenance transaction lengths. */
+#define MAINTENANCE_TRANSACTION_READ_REQUEST_SIZE ((uint32_t) 4ul)
+#define MAINTENANCE_TRANSACTION_WRITE_REQUEST_SIZE ((uint32_t) 6ul)
+#define MAINTENANCE_TRANSACTION_READ_RESPONSE_SIZE ((uint32_t) 6ul)
+#define MAINTENANCE_TRANSACTION_WRITE_RESPONSE_SIZE ((uint32_t) 4ul)
+
+/* Constants used to forward different errors to the link partner. */
+#define PACKET_NOT_ACCEPTED_CAUSE_RESERVED 0u
+#define PACKET_NOT_ACCEPTED_CAUSE_UNEXPECTED_ACKID 1u
+#define PACKET_NOT_ACCEPTED_CAUSE_CONTROL_CRC 2u
+#define PACKET_NOT_ACCEPTED_CAUSE_NON_MAINTENANCE 3u
+#define PACKET_NOT_ACCEPTED_CAUSE_PACKET_CRC 4u
+#define PACKET_NOT_ACCEPTED_CAUSE_ILLEGAL_CHARACTER 5u
+#define PACKET_NOT_ACCEPTED_CAUSE_NO_RESOURCE 6u
+#define PACKET_NOT_ACCEPTED_CAUSE_DESCRAMBLER 7u
+#define PACKET_NOT_ACCEPTED_CAUSE_GENERAL 31u
+
+/* Constants used to request link-responses. */
+#define LINK_REQUEST_RESET_DEVICE 3u
+#define LINK_REQUEST_INPUT_STATUS 4u
+
+/* Constants used to forward a port status in a link-resonse. */
+#define LINK_RESPONSE_PORT_STATUS_ERROR 2u
+#define LINK_RESPONSE_PORT_STATUS_RETRY_STOPPED 4u
+#define LINK_RESPONSE_PORT_STATUS_ERROR_STOPPED 5u
+#define LINK_RESPONSE_PORT_STATUS_OK 16u
+
+/*******************************************************************************
+ * Local typedefs
+ *******************************************************************************/
+
+/*******************************************************************************
+ * Global declarations
+ *******************************************************************************/
+
+/*******************************************************************************
+ * Local declarations
+ *******************************************************************************/
+
+/*******************************************************************************
+ * Local function prototypes
+ *******************************************************************************/
+
+/* Helper functions for protocol events. */
+static void handleStatus(RioStack_t *stack, const uint8_t ackId, const uint8_t bufferStatus);
+static void handlePacketAccepted(RioStack_t *stack, const uint8_t ackId, const uint8_t bufferStatus);
+static void handlePacketRetry(RioStack_t *stack, const uint8_t ackId, const uint8_t bufferStatus);
+static void handlePacketNotAccepted(RioStack_t *stack, const uint8_t arbitrary, const uint8_t cause);
+static void handleLinkResponse(RioStack_t *stack, const uint8_t ackId, const uint8_t portStatus);
+static void handleStartOfPacket(RioStack_t *stack);
+static void handleEndOfPacket(RioStack_t *stack);
+static void handleLinkRequest(RioStack_t *stack, uint8_t cmd);
+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.
+ *
+ * \param[in] stype0 The stype0 value.
+ * \param[in] parameter0 The parameter0 value.
+ * \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);
+
+/**
+ * \brief Function to calculate ITU-CRC5, polynom=0x15.
+ *
+ * \param[in] data The data of a control symbol.
+ * \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);
+
+/**
+ * \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.
+ * \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);
+
+/**
+ * \brief Get number of available elements.
+ *
+ * \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 );
+
+/**
+ * \brief Get if the queue is empty or not.
+ *
+ * \param[in] q The queue to operate on.
+ * \return Non-zero if the queue is empty.
+ */
+static bool_t QueueEmpty( const Queue_t q);
+
+/**
+ * \brief Get the length of a queue.
+ *
+ * \param[in] q The queue to operate on.
+ * \return The number of elements in the queue.
+ */
+static uint8_t QueueLength( const Queue_t q);
+
+/**
+ * \brief Add a new element to the queue.
+ *
+ * \param[in] q The queue to operate on.
+ * \return A queue with one added element.
+ */
+static Queue_t QueueEnqueue( Queue_t q);
+
+/**
+ * \brief Remove an element from the queue.
+ *
+ * \param[in] q The queue to operate on.
+ * \return A queue with on removed element.
+ */
+static Queue_t QueueDequeue( Queue_t q);
+
+/**
+ * \brief Check if the readout window is empty.
+ *
+ * \param[in] q The queue to operate on.
+ * \return If the readout window is empty.
+ */
+static bool_t QueueWindowEmpty( const Queue_t q);
+
+/**
+ * \brief Reset the window to none.
+ *
+ * \param[in] q The queue to operate on.
+ * \return The updated Queue_t structure.
+ */
+static Queue_t QueueWindowReset(Queue_t q);
+
+/**
+ * \brief Increase the window to the next pending element.
+ *
+ * \param[in] q The queue to operate on.
+ * \return The updated Queue_t structure.
+ */
+static Queue_t QueueWindowNext(Queue_t q);
+
+/**
+ * \brief Set actual size of the newest element.
+ *
+ * \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);
+
+/**
+ * \brief Set content at a specified index in the newest element.
+ *
+ * \param[in] q The queue to operate on.
+ * \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);
+
+/**
+ * \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 );
+
+/**
+ * \brief Get the size of the oldest element.
+ * \param[in] q The queue to operate on.
+ * \return The size of the element.
+ */
+static uint32_t QueueGetFrontSize( Queue_t q );
+
+/**
+ * \brief Get the content of the oldest element at specified index.
+ * \param[in] q The queue to operate on.
+ * \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);
+
+/**
+ * \brief Get a pointer to the buffer of the oldest element.
+ *
+ * \param[in] q The queue to operate on.
+ * \return A pointer to the content.
+ */
+static uint32_t *QueueGetFrontBuffer( Queue_t q );
+
+
+
+/*******************************************************************************
+ * 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 )
+{
+ /* Port time and timeout limit. */
+ stack->portTime = 0u;
+ stack->portTimeout = 1000u;
+
+ /* Setup the receiver. */
+ stack->rxState = RX_STATE_UNINITIALIZED;
+ stack->rxCounter = 0u;
+ stack->rxCrc = 0xffffu;
+ stack->rxStatusReceived = 0u;
+ stack->rxAckId = 0u;
+ stack->rxAckIdAcked = 0u;
+ stack->rxErrorCause = PACKET_NOT_ACCEPTED_CAUSE_RESERVED;
+ stack->rxQueue = QueueCreate((uint8_t) (rxPacketBufferSize/RIO_BUFFER_SIZE), rxPacketBuffer);
+
+ /* Setup the transmitter. */
+ stack->txState = TX_STATE_UNINITIALIZED;
+ stack->txCounter = 0u;
+ stack->txStatusCounter = 0u;
+ stack->txFrameState = TX_FRAME_START;
+ stack->txAckId = 0u;
+ stack->txAckIdWindow = 0u;
+ stack->txQueue = QueueCreate((uint8_t) (txPacketBufferSize/RIO_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;
+ stack->statusInboundErrorControlCrc = 0ul;
+ stack->statusInboundErrorPacketAckId = 0ul;
+ stack->statusInboundErrorPacketCrc = 0ul;
+ stack->statusInboundErrorIllegalCharacter = 0ul;
+ stack->statusInboundErrorGeneral = 0ul;
+ stack->statusInboundErrorPacketUnsupported = 0ul;
+
+ /* Setup status counters for outbound direction. */
+ stack->statusOutboundPacketComplete = 0ul;
+ stack->statusOutboundPacketRetry = 0ul;
+ stack->statusOutboundErrorTimeout = 0ul;
+ stack->statusOutboundErrorPacketAccepted = 0ul;
+ stack->statusOutboundErrorPacketRetry = 0ul;
+
+ /* Setup status counters for potential problems on the link-partner. */
+ stack->statusPartnerLinkRequest = 0ul;
+ stack->statusPartnerErrorControlCrc = 0ul;
+ stack->statusPartnerErrorPacketAckId = 0ul;
+ stack->statusPartnerErrorPacketCrc = 0ul;
+ 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.
+ *******************************************************************************************/
+
+RioStatusType RIO_getStatus( RioStack_t *stack )
+{
+ RioStatusType status;
+
+
+ /* 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
+ {
+ /* The link is not up yet. */
+ status = RIO_STATUS_UNINITIALIZED;
+ }
+
+ return status;
+}
+
+
+uint8_t RIO_outboundQueueLength( 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 )
+{
+ 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;
+}
+
+
+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 )
+{
+ /* 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 i;
+ uint32_t size;
+ uint32_t *src;
+
+
+ ASSERT(!QueueEmpty(stack->rxQueue), "Reading from empty reception queue.");
+
+ /* 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. */
+ for(i = 0; i < size; i++)
+ {
+ dest[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. */
+ 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)
+{
+ /* Check the area of the access. */
+ if(offset < 0x00010000ul)
+ {
+ /* 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;
+ }
+ }
+ 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)
+{
+ 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);
+}
+#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 )
+{
+ receiveMaintenanceWriteRequest(stack, destid, srcid, tid, hopCount, offset, data);
+}
+#else
+void RIO_receiveMaintenanceWriteRequest( RioStack_t *stack, uint16_t *srcid, uint8_t *tid,
+ uint8_t *hopCount, uint32_t *offset, uint32_t *data )
+{
+ receiveMaintenanceWriteRequest(stack, srcid, srcid, tid, hopCount, offset, data);
+}
+#endif
+
+#ifdef RIO_TRANSPARENT
+void RIO_sendMaintenanceWriteResponse( RioStack_t *stack, const uint16_t destid, const uint16_t srcid, const uint8_t tid,
+ const uint8_t hopCount)
+{
+ sendMaintenanceWriteResponse(stack, destid, srcid, tid, hopCount);
+}
+#else
+void RIO_sendMaintenanceWriteResponse( RioStack_t *stack, const uint16_t destid, const uint8_t tid,
+ const uint8_t hopCount)
+{
+ sendMaintenanceWriteResponse(stack, destid, stack->baseDeviceId, tid, hopCount);
+}
+#endif
+
+#ifdef RIO_TRANSPARENT
+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)
+{
+ sendNwrite(stack, destid, srcid, 0, address, size, data, 0u);
+}
+#else
+void RIO_sendNwrite( RioStack_t *stack, const uint16_t destid,
+ const uint32_t address, const uint16_t size, const uint8_t *data)
+{
+ sendNwrite(stack, destid, stack->baseDeviceId, 0, address, size, data, 0u);
+}
+#endif
+
+#ifdef RIO_TRANSPARENT
+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
+
+/*******************************************************************************************
+ * Logical I/O NREAD functions.
+ *******************************************************************************************/
+
+#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);
+}
+#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.
+ *******************************************************************************************/
+
+#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 )
+{
+ sendDoorbell(stack, destid, srcid, tid, info);
+}
+#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 )
+{
+ return receiveMessage(stack, destid, srcid, mailbox, dataLength, data);
+}
+#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)
+{
+ 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)
+ {
+ stack->rxState = RX_STATE_PORT_INITIALIZED;
+ stack->rxCounter = 0u;
+ stack->rxCrc = 0xffffu;
+ stack->rxStatusReceived = 0;
+ stack->rxAckId = 0u;
+ stack->rxAckIdAcked = 0u;
+ stack->rxErrorCause = PACKET_NOT_ACCEPTED_CAUSE_RESERVED;
+
+ stack->txState = TX_STATE_PORT_INITIALIZED;
+ stack->txCounter = 0u;
+ stack->txStatusCounter = 0u;
+ stack->txFrameState = TX_FRAME_START;
+ stack->txAckId = 0u;
+ stack->txAckIdWindow = 0u;
+ }
+ else
+ {
+ stack->rxState = RX_STATE_UNINITIALIZED;
+ stack->txState = TX_STATE_UNINITIALIZED;
+ }
+}
+
+
+void RIO_portSetTime( RioStack_t *stack, const uint32_t time)
+{
+ stack->portTime = time;
+}
+
+
+void RIO_portSetTimeout( RioStack_t *stack, const uint32_t time)
+{
+ stack->portTimeout = time;
+}
+
+
+void RIO_portAddSymbol( RioStack_t *stack, const RioSymbol s)
+{
+ uint8_t stype0;
+ uint8_t parameter0;
+ uint8_t parameter1;
+ uint8_t stype1;
+
+
+ switch(stack->rxState)
+ {
+ case RX_STATE_PORT_INITIALIZED:
+ /******************************************************************************
+ * PORT_INITIALIZED
+ * This state is entered to initialize the link. Only status-control-symbols
+ * are accepted in this state. When 7 error-free, i.e. with CRC5 correct, status
+ * control symbols has been received, change state to linkInitialized.
+ ******************************************************************************/
+
+ /* Check the type of symbol. */
+ if(s.type == RIO_SYMBOL_TYPE_CONTROL)
+ {
+ /* This is a control symbol. */
+
+ /* Check that the control symbol contains no errors. */
+ if(Crc5(s.data, 0x1fu) == (s.data & 0x1ful))
+ {
+ /* Error-free control symbol. */
+
+ /* Check if the symbol is a status symbol. */
+ stype0 = STYPE0_GET(s.data);
+ if(stype0 == STYPE0_STATUS)
+ {
+ /* Status symbol received. */
+
+ /* Indicate an error-free status has been received. */
+ stack->rxStatusReceived = 1;
+
+ /* Check if enough status control symbols has been received. */
+ if(stack->rxCounter == 7u)
+ {
+ /* Enough correct status control symbols has been received without
+ errors in between. */
+
+ /* Setup the transmitter with the content of the symbol. */
+ stack->txAckId = PARAMETER0_GET(s.data);
+ stack->txAckIdWindow = stack->txAckId;
+ stack->txBufferStatus = PARAMETER1_GET(s.data);
+
+ /* Set the transmitter in its normal operational mode. */
+ stack->rxState = RX_STATE_LINK_INITIALIZED;
+ stack->rxCounter = 0u;
+ DEBUG_STATE("rx:normal");
+ }
+ else
+ {
+ /* Count the number of consequitive error-free status control symbols
+ that has been received. */
+ stack->rxCounter++;
+ }
+ }
+ else
+ {
+ /* The received symbol is not a status symbol. */
+ /* Discard it. */
+ }
+ }
+ else
+ {
+ /* CRC error in control symbol. */
+ /* Restart counting error-free status-control-symbols. */
+ stack->rxCounter = 0u;
+ }
+ }
+ else
+ {
+ /* Not a control symbol. */
+ /* Discard the symbol. */
+ }
+
+ break;
+
+ case RX_STATE_LINK_INITIALIZED:
+ /******************************************************************************
+ * LINK_INITIALIZED
+ * The normal state. Accept packets and forward them.
+ ******************************************************************************/
+
+ /* Check the type of symbol. */
+ switch(s.type)
+ {
+ case RIO_SYMBOL_TYPE_CONTROL:
+ /**************************************************************************
+ * This is a control symbol.
+ **************************************************************************/
+
+ /* Check if the CRC is correct. */
+ if(Crc5(s.data, 0x1fu) == (s.data & (uint8_t)0x1ful))
+ {
+ /* The CRC is correct. */
+
+ /* Get the content of the control symbol. */
+ stype0 = STYPE0_GET(s.data);
+ parameter0 = PARAMETER0_GET(s.data);
+ parameter1 = PARAMETER1_GET(s.data);
+ stype1 = STYPE1_GET(s.data);
+
+ /**********************************************************************************
+ * Check the stype0 part of the symbol.
+ * Note that errors in this should trigger OUTPUT_ERROR_STOPPED.
+ **********************************************************************************/
+ switch(stype0)
+ {
+ case STYPE0_STATUS:
+ /* A status containing the current ackId and the buffer status has been
+ received. */
+ handleStatus(stack, parameter0, parameter1);
+ break;
+
+ case STYPE0_PACKET_ACCEPTED:
+ /* A packet has been accepted by the link partner. */
+ handlePacketAccepted(stack, parameter0, parameter1);
+ break;
+
+ case STYPE0_PACKET_RETRY:
+ /* The link partner wants us to initiate a restart of the received ackId. */
+ handlePacketRetry(stack, parameter0, parameter1);
+ break;
+
+ case STYPE0_PACKET_NOT_ACCEPTED:
+ /* The link partner indicates that a packet has been rejected. */
+ handlePacketNotAccepted(stack, parameter0, parameter1);
+ break;
+
+ case STYPE0_LINK_RESPONSE:
+ /* The link partner has sent a response to a link-request. */
+ handleLinkResponse(stack, parameter0, parameter1);
+ break;
+
+ case STYPE0_VC_STATUS:
+ case STYPE0_RESERVED:
+ case STYPE0_IMPLEMENTATION_DEFINED:
+ default:
+ /* Unsupported symbol received. */
+ /* Discard them. */
+ break;
+ }
+
+ /**********************************************************************************
+ * Check the stype1 part of the symbol.
+ * Note that errors in this should trigger INPUT_ERROR_STOPPED.
+ **********************************************************************************/
+ switch(stype1)
+ {
+ case STYPE1_START_OF_PACKET:
+ /* Start of a new packet. */
+ handleStartOfPacket(stack);
+ break;
+
+ case STYPE1_END_OF_PACKET:
+ /* Ending a packet. */
+ handleEndOfPacket(stack);
+ break;
+
+ case STYPE1_STOMP:
+ /* Cancel the currently received frame. */
+ stack->rxCounter = 0;
+ break;
+
+ case STYPE1_RESTART_FROM_RETRY:
+ /* Cancel the currently received frame when in this state. */
+ stack->rxCounter = 0;
+ break;
+
+ case STYPE1_LINK_REQUEST:
+ /* A link-request has been received. */
+ handleLinkRequest(stack, CMD_GET(s.data));
+ break;
+
+ case STYPE1_NOP:
+ /* No operation symbol. */
+ /* Discard these. */
+ break;
+
+ case STYPE1_MULTICAST_EVENT:
+ case STYPE1_RESERVED:
+ default:
+ /* Unsupported symbol received. */
+ /* Discard them. */
+ break;
+ }
+ }
+ else
+ {
+ /* The control symbol CRC is incorrect. */
+ /* Corrupted control symbol. Discard the symbol and enter the input-error-stopped state. */
+ stack->txState = TX_STATE_SEND_PACKET_NOT_ACCEPTED;
+ stack->rxState = RX_STATE_INPUT_ERROR_STOPPED;
+ stack->rxErrorCause = PACKET_NOT_ACCEPTED_CAUSE_CONTROL_CRC;
+ stack->statusInboundErrorControlCrc++;
+ DEBUG_STATE("rx:error-stopped");
+ }
+ break;
+
+ case RIO_SYMBOL_TYPE_DATA:
+ /**************************************************************************
+ * This is a data symbol.
+ **************************************************************************/
+
+ /* Check if a packet has been started and that it is not too long. */
+ if ((stack->rxCounter >= 1u) && (stack->rxCounter <= RIO_PACKET_SIZE))
+ {
+ /* A packet has been started. */
+
+ /* Check if the ackId is correct on the first part of the packet. */
+ if ((stack->rxCounter > 1u) ||
+ ((stack->rxCounter == 1u) && (((uint8_t)(s.data >> 27)) == stack->rxAckId)))
+ {
+ /* The ackId is the expected one. */
+
+ /* Check if this is the first symbol of a packet. */
+ if (stack->rxCounter == 1u)
+ {
+ /* 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);
+ }
+ else
+ {
+ /* This is not the first symbol. */
+ /* Continue to calculate the CRC of the packet. */
+ stack->rxCrc = Crc32(s.data, stack->rxCrc);
+ }
+
+ /* Save the new data in the packet queue and update the reception counter. */
+ QueueSetContent(stack->rxQueue, (uint32_t)stack->rxCounter - (uint32_t)1ul, s.data);
+ stack->rxCounter++;
+ }
+ else
+ {
+ 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;
+ stack->rxState = RX_STATE_INPUT_ERROR_STOPPED;
+ stack->rxErrorCause = PACKET_NOT_ACCEPTED_CAUSE_UNEXPECTED_ACKID;
+ stack->statusInboundErrorPacketAckId++;
+ DEBUG_STATE("rx:error-stopped");
+ }
+ }
+ else
+ {
+ /* No packet has been started or the packet is too long. */
+ /* Packet error. Enter input-error-stopped state. */
+ stack->txState = TX_STATE_SEND_PACKET_NOT_ACCEPTED;
+ stack->rxState = RX_STATE_INPUT_ERROR_STOPPED;
+ stack->rxErrorCause = PACKET_NOT_ACCEPTED_CAUSE_GENERAL;
+ stack->statusInboundErrorGeneral++;
+ DEBUG_STATE("rx:error-stopped");
+ }
+ break;
+
+ case RIO_SYMBOL_TYPE_ERROR:
+ /**************************************************************************
+ * The decoder has received a erronous symbol.
+ **************************************************************************/
+
+ /* 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_IDLE:
+ default:
+ /**************************************************************************
+ * Idle symbol or unsupported symbol.
+ **************************************************************************/
+
+ /* Discard these for now. */
+ break;
+ }
+ break;
+
+ case RX_STATE_INPUT_RETRY_STOPPED:
+ /******************************************************************************
+ * INPUT_RETRY_STOPPED
+ * This state is entered when no more buffers was available and a packet was
+ * received. When in this state, all packets should be discarded until a
+ * RESTART-FROM-RETRY symbol is received. See section 5.9.1.4 of the standard.
+ * Note that it is only the input side of the port that are affected, not the
+ * output side. Packets may still be transmitted and acknowledges should be
+ * accepted.
+ ******************************************************************************/
+
+ /* Check the type of symbol. */
+ switch(s.type)
+ {
+ case RIO_SYMBOL_TYPE_CONTROL:
+ /* This is a control symbol. */
+
+ /* Check if the CRC is correct. */
+ if(Crc5(s.data, 0x1fu) == (s.data & (uint8_t)0x1ful))
+ {
+ /* The CRC is correct. */
+
+ /* Get the content of the control symbol. */
+ stype0 = STYPE0_GET(s.data);
+ parameter0 = PARAMETER0_GET(s.data);
+ parameter1 = PARAMETER1_GET(s.data);
+ stype1 = STYPE1_GET(s.data);
+
+ /* Check the stype0 part of the symbol. */
+ switch(stype0)
+ {
+ case STYPE0_STATUS:
+ /* A status containing the current ackId and the buffer status has been
+ received. */
+ handleStatus(stack, parameter0, parameter1);
+ break;
+
+ case STYPE0_PACKET_ACCEPTED:
+ /* A packet has been accepted by the link partner. */
+ handlePacketAccepted(stack, parameter0, parameter1);
+ break;
+
+ case STYPE0_PACKET_RETRY:
+ /* The link partner wants us to initiate a restart of the received ackId. */
+ handlePacketRetry(stack, parameter0, parameter1);
+ break;
+
+ case STYPE0_PACKET_NOT_ACCEPTED:
+ /* The link partner indicates that a packet has been rejected. */
+ handlePacketNotAccepted(stack, parameter0, parameter1);
+ break;
+
+ case STYPE0_LINK_RESPONSE:
+ /* The link partner has sent a response to a link-request. */
+ handleLinkResponse(stack, parameter0, parameter1);
+ break;
+
+ case STYPE0_VC_STATUS:
+ case STYPE0_RESERVED:
+ case STYPE0_IMPLEMENTATION_DEFINED:
+ default:
+ /* Unsupported symbol received. */
+ /* Discard them. */
+ break;
+ }
+
+ /* Check the stype1 part of the symbol. */
+ switch(stype1)
+ {
+ case STYPE1_START_OF_PACKET:
+ /* Starting new frames are ignored in this state. */
+ break;
+
+ case STYPE1_END_OF_PACKET:
+ /* Ending new frames are ignored in this state. */
+ break;
+
+ case STYPE1_STOMP:
+ /* Restarting frames are ignored in this state. */
+ break;
+
+ case STYPE1_RESTART_FROM_RETRY:
+ /* The link partner has confirmed our packet-retry-symbol. */
+ /* Go back to the normal state and reset the frame reception. */
+ stack->rxState = RX_STATE_LINK_INITIALIZED;
+ stack->rxCounter = 0u;
+ DEBUG_STATE("rx:normal(restart)");
+ break;
+
+ case STYPE1_LINK_REQUEST:
+ /* A link-request has been received. */
+ handleLinkRequest(stack, CMD_GET(s.data));
+ stack->rxState = RX_STATE_LINK_INITIALIZED;
+ DEBUG_STATE("rx:normal(link-req)");
+ break;
+
+ case STYPE1_NOP:
+ /* No operation symbol. */
+ /* Discard these. */
+ break;
+
+ case STYPE1_MULTICAST_EVENT:
+ case STYPE1_RESERVED:
+ default:
+ /* Unsupported symbol received. */
+ /* Discard them. */
+ break;
+ }
+ }
+ else
+ {
+ /* The control symbol CRC is incorrect. */
+ /* Corrupted control symbol. Discard the symbol and enter the input-error-stopped state. */
+ stack->txState = TX_STATE_SEND_PACKET_NOT_ACCEPTED;
+ stack->rxState = RX_STATE_INPUT_ERROR_STOPPED;
+ stack->rxErrorCause = PACKET_NOT_ACCEPTED_CAUSE_CONTROL_CRC;
+ stack->statusInboundErrorControlCrc++;
+ DEBUG_STATE("rx:error-stopped");
+ }
+ break;
+
+ case RIO_SYMBOL_TYPE_ERROR:
+ /* Idle symbol error. Place the receiver in input-error-stopped state. */
+ stack->txState = TX_STATE_SEND_PACKET_NOT_ACCEPTED;
+ stack->rxState = RX_STATE_INPUT_ERROR_STOPPED;
+ stack->rxErrorCause = PACKET_NOT_ACCEPTED_CAUSE_ILLEGAL_CHARACTER;
+ stack->statusInboundErrorIllegalCharacter++;
+ DEBUG_STATE("rx:error-stopped");
+ break;
+
+ case RIO_SYMBOL_TYPE_DATA:
+ case RIO_SYMBOL_TYPE_IDLE:
+ default:
+ /* Data or idle symbol. */
+ /* Discard these in this state. */
+ break;
+ }
+ break;
+
+ case RX_STATE_INPUT_ERROR_STOPPED:
+ /******************************************************************************
+ * INPUT_ERROR_STOPPED
+ * This state is entered when an error situation has occurred. When in this
+ * state, all symbols should be discarded until a link-request-symbols has
+ * been received. See section 5.13.2.6 in part 6 of the standard.
+ * Note that it is only the input side of the port that are affected, not the
+ * output side. Packets may still be transmitted and acknowledges should be
+ * accepted.
+ ******************************************************************************/
+
+ /* Check the type of symbol. */
+ switch(s.type)
+ {
+ case RIO_SYMBOL_TYPE_CONTROL:
+ /* This is a control symbol. */
+
+ /* Check if the CRC is correct. */
+ if(Crc5(s.data, 0x1fu) == (s.data & (uint8_t)0x1ful))
+ {
+ /* The CRC is correct. */
+
+ /* Get the content of the control symbol. */
+ stype0 = STYPE0_GET(s.data);
+ parameter0 = PARAMETER0_GET(s.data);
+ parameter1 = PARAMETER1_GET(s.data);
+ stype1 = STYPE1_GET(s.data);
+
+ /* Check the stype0 part of the symbol. */
+ switch(stype0)
+ {
+ case STYPE0_STATUS:
+ /* A status containing the current ackId and the buffer status has been
+ received. */
+ handleStatus(stack, parameter0, parameter1);
+ break;
+
+ case STYPE0_PACKET_ACCEPTED:
+ /* A packet has been accepted by the link partner. */
+ handlePacketAccepted(stack, parameter0, parameter1);
+ break;
+
+ case STYPE0_PACKET_RETRY:
+ /* The link partner wants us to initiate a restart of the received ackId. */
+ handlePacketRetry(stack, parameter0, parameter1);
+ break;
+
+ case STYPE0_PACKET_NOT_ACCEPTED:
+ /* The link partner indicates that a packet has been rejected. */
+ handlePacketNotAccepted(stack, parameter0, parameter1);
+ break;
+
+ case STYPE0_LINK_RESPONSE:
+ /* The link partner has sent a response to a link-request. */
+ handleLinkResponse(stack, parameter0, parameter1);
+ break;
+
+ case STYPE0_VC_STATUS:
+ case STYPE0_RESERVED:
+ case STYPE0_IMPLEMENTATION_DEFINED:
+ default:
+ /* Unsupported symbol received. */
+ /* Discard them. */
+ break;
+ }
+
+ /* Check the stype1 part of the symbol. */
+ switch(stype1)
+ {
+ case STYPE1_START_OF_PACKET:
+ /* Starting new frames are ignored in this state. */
+ break;
+
+ case STYPE1_END_OF_PACKET:
+ /* Ending new frames are ignored in this state. */
+ break;
+
+ case STYPE1_STOMP:
+ /* Restarting frames are ignored in this state. */
+ break;
+
+ case STYPE1_RESTART_FROM_RETRY:
+ /* Restart-from-retry are ignored in this state. */
+ break;
+
+ case STYPE1_LINK_REQUEST:
+ /* This is the symbol we have been waiting for. */
+ /* Force the transmitter to send a link-response and go back into the normal
+ operational state. */
+ /* The transmitter will always send a status as the first symbol after this. */
+ handleLinkRequest(stack, CMD_GET(s.data));
+ stack->rxState = RX_STATE_LINK_INITIALIZED;
+ DEBUG_STATE("rx:normal(link-req)");
+ break;
+
+ case STYPE1_NOP:
+ /* No operation symbol. */
+ /* Discard these. */
+ break;
+
+ case STYPE1_MULTICAST_EVENT:
+ case STYPE1_RESERVED:
+ default:
+ /* Unsupported symbol received. */
+ /* Discard them. */
+ break;
+ }
+ }
+ else
+ {
+ /* The CRC is incorrect. */
+ /* Discard these in this state. */
+ }
+ break;
+
+ case RIO_SYMBOL_TYPE_DATA:
+ case RIO_SYMBOL_TYPE_IDLE:
+ case RIO_SYMBOL_TYPE_ERROR:
+ default:
+ /* Data, idle or error symbol. */
+ /* Discard these in this state. */
+ break;
+ }
+ break;
+
+ case RX_STATE_UNINITIALIZED:
+ default:
+ /******************************************************************************
+ * Wait for the port to be initialized.
+ ******************************************************************************/
+
+ /* Discard all incoming symbols. */
+ break;
+ }
+}
+
+
+
+RioSymbol RIO_portGetSymbol( RioStack_t *stack )
+{
+ RioSymbol s;
+
+
+ switch(stack->txState)
+ {
+ case TX_STATE_PORT_INITIALIZED:
+ /******************************************************************************
+ * PORT_INITIALIZED
+ * This state is entered to initialize the link. Send status-control-symbols
+ * once in a while until the receiver has received enough error-free status-
+ * control-symbols and we have transmitted enough status-control-symbols. Once
+ * an error-free status-control-symbol has been received, the statuses are
+ * transmitted more frequently to decrease the time for the link to be
+ * initialized.
+ ******************************************************************************/
+
+ /* Check if an idle symbol or a status control symbol should be sent. */
+ if(((stack->rxStatusReceived == 0) && (stack->txCounter == 255u)) ||
+ ((stack->rxStatusReceived == 1) && (stack->txCounter >= 15u)))
+ {
+ /* A control symbol should be sent. */
+
+ /* Create a new status symbol and reset the transmission counter. */
+ stack->txCounter = 0u;
+ s = CreateControlSymbol(STYPE0_STATUS, stack->rxAckId, QueueAvailable(stack->rxQueue),
+ STYPE1_NOP, 0u);
+
+ /* Check if the receiver has received any error-free status and that we
+ have sent at least 15 status control symbols. */
+ if((stack->rxStatusReceived == 1) && (stack->txStatusCounter < 15u))
+ {
+ /* Has not sent enough status control symbols. */
+ stack->txStatusCounter++;
+ }
+ else
+ {
+ /* Has sent enough status control symbols. */
+ /* Dont do anything. */
+ }
+ }
+ else
+ {
+ /* Idle symbol should be sent. */
+ s.type = RIO_SYMBOL_TYPE_IDLE;
+ stack->txCounter++;
+ }
+
+ /* Check if we are ready to set the transmitter in a link initialized state. */
+ if ((stack->rxState == RX_STATE_LINK_INITIALIZED) && (stack->txStatusCounter == 15u))
+ {
+ /* Ready to go to link initialized. */
+ stack->txState = TX_STATE_LINK_INITIALIZED;
+ stack->txFrameState = TX_FRAME_START;
+ stack->txStatusCounter = 0u;
+ DEBUG_STATE("tx:normal");
+ }
+ else
+ {
+ /* Not ready to go to link initialized. */
+ /* Dont do anything. */
+ }
+
+ break;
+
+ case TX_STATE_LINK_INITIALIZED:
+ /******************************************************************************
+ * LINK_INITIALIZED
+ * The normal state. Accept packets and forward them. Send acknowledges when
+ * the receiver has received complete packets.
+ ******************************************************************************/
+
+ /* Check if the receiver wants to acknowledge a packet. */
+ if(stack->rxAckId == stack->rxAckIdAcked)
+ {
+ /* The receiver does not want to acknowledge a packet. */
+
+ /* Check if there are any outstanding packets and if it has timed out. */
+ if((stack->txAckId == stack->txAckIdWindow) ||
+ ((stack->portTime - stack->txFrameTimeout[stack->txAckId]) < stack->portTimeout))
+ {
+ /* There are no outstanding packets or there has been no timeout. */
+
+ /* Check if a packet is ongoing. */
+ if(stack->txFrameState == TX_FRAME_BODY)
+ {
+ /* A packet transmission is ongoing. */
+
+ /* Check if the packet has been completly sent. */
+ if(stack->txCounter != QueueGetFrontSize(stack->txQueue))
+ {
+ /* The packet has not been completly sent. */
+
+ /* Create a new data symbol to transmit. */
+ s.type = RIO_SYMBOL_TYPE_DATA;
+ s.data = QueueGetFrontContent(stack->txQueue, (uint32_t)stack->txCounter);
+
+ /* Check if this is the first symbol in a packet. */
+ if (stack->txCounter == 0u)
+ {
+ /* Place the correct ackId in the right place. */
+ s.data |= (uint32_t)stack->txAckIdWindow << 27;
+ }
+ else
+ {
+ /* Dont do anything. */
+ }
+
+ /* Update the transmission counter. */
+ stack->txCounter++;
+
+ /* A status control symbol was not sent. Update the status counter. */
+ stack->txStatusCounter++;
+ }
+ else
+ {
+ /* The packet has been sent. */
+
+ /* Save the timeout time and update to the next ackId. */
+ stack->txFrameTimeout[stack->txAckIdWindow] = stack->portTime;
+ stack->txAckIdWindow = ACKID_INC(stack->txAckIdWindow);
+ stack->txQueue = QueueWindowNext(stack->txQueue);
+
+ /* Check if there are more packets pending to be sent. */
+ /* Also check that there are buffer available at the receiver and that not too many
+ packets are outstanding. */
+ if(!QueueWindowEmpty(stack->txQueue) && (stack->txBufferStatus > 0) &&
+ (((stack->txAckIdWindow - stack->txAckId) & 0x1f) != 31))
+ {
+ /* More pending packets. */
+ DEBUG_FRAMING_TX("cont=%i", stack->txAckIdWindow);
+ /* Create a control symbol to signal that the new packet has started. */
+ s = CreateControlSymbol(STYPE0_STATUS, stack->rxAckId, QueueAvailable(stack->rxQueue),
+ STYPE1_START_OF_PACKET, 0u);
+
+ /* Restart transmission counter. */
+ stack->txCounter = 0;
+ }
+ else
+ {
+ /* No more pending packets. */
+ DEBUG_FRAMING_TX("end=%i", stack->txAckIdWindow);
+ /* Create a control symbol to signal that the packet has ended. */
+ s = CreateControlSymbol(STYPE0_STATUS, stack->rxAckId, QueueAvailable(stack->rxQueue),
+ STYPE1_END_OF_PACKET, 0u);
+
+ /* Go back to wait for a new frame. */
+ stack->txFrameState = TX_FRAME_START;
+ }
+
+ /* A status control symbol has been sent. Reset the status counter. */
+ stack->txStatusCounter = 0u;
+ }
+ }
+ else
+ {
+ /* No packet is being sent. */
+
+ /* Check if there are any pending packets to start sending. */
+ /* Also check that there are buffer available at the receiver and that not too many
+ packets are outstanding. */
+ if(!QueueWindowEmpty(stack->txQueue) && (stack->txBufferStatus > 0) &&
+ (((stack->txAckIdWindow - stack->txAckId) & 0x1f) != 31))
+ {
+ /* There is a pending packet to send. */
+ DEBUG_FRAMING_TX("start=%i", stack->txAckIdWindow);
+ /* Send a start-of-packet control symbol to start to send the packet. */
+ s = CreateControlSymbol(STYPE0_STATUS, stack->rxAckId, QueueAvailable(stack->rxQueue),
+ STYPE1_START_OF_PACKET, 0u);
+ stack->txFrameState = TX_FRAME_BODY;
+ stack->txCounter = 0u;
+
+ /* A status control symbol has been sent. Reset the status counter. */
+ stack->txStatusCounter = 0u;
+ }
+ else
+ {
+ /* There are no pending packets to send. */
+
+ /* Check if a status control symbol must be transmitted. */
+ if(stack->txStatusCounter < 255u)
+ {
+ /* Not required to send a status control symbol. */
+
+ /* Send an idle-symbol. */
+ s.type = RIO_SYMBOL_TYPE_IDLE;
+ stack->txStatusCounter++;
+ }
+ else
+ {
+ /* Must send a status control symbol. */
+
+ /* Create a status control symbol. */
+ s = CreateControlSymbol(STYPE0_STATUS, stack->rxAckId, QueueAvailable(stack->rxQueue),
+ STYPE1_NOP, 0u);
+
+ /* A status control symbol has been sent. Reset the status counter. */
+ stack->txStatusCounter = 0u;
+ }
+ }
+ }
+ }
+ else
+ {
+ /* There has been a timeout. */
+ /* A packet has been sent but no packet-accepted has been received. */
+ DEBUG_FRAMING_TX("timeout=%i", stack->txAckId);
+ /* Send link-request-symbol (input-status). */
+ s = CreateControlSymbol(STYPE0_STATUS, stack->rxAckId, QueueAvailable(stack->rxQueue),
+ STYPE1_LINK_REQUEST, LINK_REQUEST_INPUT_STATUS);
+
+ /* Save the time when this was transmitted. */
+ stack->txFrameTimeout[stack->txAckId] = stack->portTime;
+
+ /* Remember that this symbol has been transmitted. */
+ stack->txCounter = 1;
+
+ /* Go into the output error stopped state. */
+ stack->txState = TX_STATE_OUTPUT_ERROR_STOPPED;
+ stack->statusOutboundErrorTimeout++;
+ DEBUG_STATE("tx:error-stopped");
+ }
+ }
+ else
+ {
+ /* The receiver wants us to send an acknowledgement. */
+ s = CreateControlSymbol(STYPE0_PACKET_ACCEPTED, stack->rxAckIdAcked, QueueAvailable(stack->rxQueue),
+ STYPE1_NOP, 0u);
+ stack->rxAckIdAcked = ACKID_INC(stack->rxAckIdAcked);
+
+ /* A status control symbol was not sent. Update the status counter. */
+ stack->txStatusCounter++;
+ }
+ break;
+
+ case TX_STATE_SEND_PACKET_RETRY:
+ /******************************************************************************
+ * SEND_PACKET_RETRY
+ * This state is set by the receiver to force a packet-retry-symbol to be
+ * transmitted.
+ ******************************************************************************/
+
+ /* Check if the receiver wants to acknowledge a packet. */
+ /* This must be done first or we will get an error for a missmatching
+ ackId in the link-partner. */
+ if(stack->rxAckId == stack->rxAckIdAcked)
+ {
+ /* No pending acknowledge. */
+
+ /* Send a packet-retry symbol to tell the link partner to retry the last frame. */
+ s = CreateControlSymbol(STYPE0_PACKET_RETRY, stack->rxAckId, QueueAvailable(stack->rxQueue),
+ STYPE1_NOP, 0u);
+
+ /* Proceed with normal transmission. */
+ stack->txState = TX_STATE_LINK_INITIALIZED;
+
+ /* A status control symbol was not sent. Update the status counter. */
+ stack->txStatusCounter++;
+ }
+ else
+ {
+
+ /* The receiver wants us to send an acknowledgement. */
+ s = CreateControlSymbol(STYPE0_PACKET_ACCEPTED, stack->rxAckIdAcked, QueueAvailable(stack->rxQueue),
+ STYPE1_NOP, 0u);
+ stack->rxAckIdAcked = ACKID_INC(stack->rxAckIdAcked);
+
+ /* A status control symbol was not sent. Update the status counter. */
+ stack->txStatusCounter++;
+ }
+ break;
+
+ case TX_STATE_SEND_PACKET_NOT_ACCEPTED:
+ /******************************************************************************
+ * SEND_PACKET_NOT_ACCEPTED
+ * This state is set by the receiver to force a packet-not-accepted-symbol to be
+ * transmitted.
+ ******************************************************************************/
+
+ /* Send a packet-not-accepted symbol to indicate an error on the link. */
+ s = CreateControlSymbol(STYPE0_PACKET_NOT_ACCEPTED, 0, stack->rxErrorCause,
+ STYPE1_NOP, 0u);
+
+ /* Proceed with normal transmission. */
+ stack->txState = TX_STATE_LINK_INITIALIZED;
+
+ /* A status control symbol was not sent. Update the status counter. */
+ stack->txStatusCounter++;
+ break;
+
+ case TX_STATE_SEND_LINK_RESPONSE:
+ /******************************************************************************
+ * SEND_LINK_RESPONSE
+ * This state is set by the receiver to force a link-response-symbol to be
+ * transmitted.
+ ******************************************************************************/
+
+ DEBUG_FRAMING_RX("link-res:%u", stack->rxAckId);
+
+ /* Check the state of the receiver. */
+ /* REMARK: If a link-request gives this response and a link-request also makes the receiver
+ enter the normal operational state, none of these states except the normal state will ever
+ be used... */
+ if((stack->rxState == RX_STATE_LINK_INITIALIZED) || (stack->rxState == RX_STATE_PORT_INITIALIZED))
+ {
+ /* Normal state. */
+ s = CreateControlSymbol(STYPE0_LINK_RESPONSE, stack->rxAckId, LINK_RESPONSE_PORT_STATUS_OK,
+ STYPE1_NOP, 0u);
+ }
+ else if(stack->rxState == RX_STATE_INPUT_RETRY_STOPPED)
+ {
+ /* Input-retry-stopped state. */
+ s = CreateControlSymbol(STYPE0_LINK_RESPONSE, stack->rxAckId, LINK_RESPONSE_PORT_STATUS_RETRY_STOPPED,
+ STYPE1_NOP, 0u);
+ }
+ else if(stack->rxState == RX_STATE_INPUT_ERROR_STOPPED)
+ {
+ /* Input-error-stopped state. */
+ s = CreateControlSymbol(STYPE0_LINK_RESPONSE, stack->rxAckId, LINK_RESPONSE_PORT_STATUS_ERROR_STOPPED,
+ STYPE1_NOP, 0u);
+ }
+ else
+ {
+ /* Not in the defined states. */
+ s = CreateControlSymbol(STYPE0_LINK_RESPONSE, stack->rxAckId, LINK_RESPONSE_PORT_STATUS_ERROR,
+ STYPE1_NOP, 0u);
+ }
+
+ /* Proceed with normal transmission. */
+ stack->txState = TX_STATE_LINK_INITIALIZED;
+
+ /* Force a status to be transmitted the next time to comply to the input-error-stopped
+ state rules. */
+ stack->txStatusCounter = 255;
+ break;
+
+ case TX_STATE_OUTPUT_RETRY_STOPPED:
+ /******************************************************************************
+ * OUTPUT_RETRY_STOPPED
+ * This state is entered when the link-partner has transmitted a
+ * packet-retry-symbol. The packet-retry-symbol is acknowledged by sending a
+ * restart-from-retry-symbol.
+ * This state follows 5.9.1.5 in part 6.
+ ******************************************************************************/
+
+ /* Send a restart-from-retry symbol to acknowledge. */
+ s = CreateControlSymbol(STYPE0_STATUS, stack->rxAckId, QueueAvailable(stack->rxQueue),
+ STYPE1_RESTART_FROM_RETRY, 0u);
+
+ /* Restart the current frame and proceed with normal operation. */
+ stack->txFrameState = TX_FRAME_START;
+ stack->txState = TX_STATE_LINK_INITIALIZED;
+ stack->txCounter = 0;
+ DEBUG_STATE("tx:normal");
+
+ /* Discard all packets that has not received a matching packet-accepted. */
+ stack->txAckIdWindow = stack->txAckId;
+ stack->txQueue = QueueWindowReset(stack->txQueue);
+
+ /* A status control symbol was sent. Reset the status counter. */
+ stack->txStatusCounter = 0;
+ break;
+
+ case TX_STATE_OUTPUT_ERROR_STOPPED:
+ /******************************************************************************
+ * OUTPUT_ERROR_STOPPED
+ * This state is entered when the link partner has encountered any problem
+ * which is indicated by sending a packet-not-accepted symbol or if a packet
+ * timeout has expired. The error condition is acknowledged by sending a
+ * link-request-symbol and then wait for a link-response reply.
+ * This state follows 5.13.2.7 in part 6.
+ ******************************************************************************/
+
+ /* Check if a link-request-symbol has been transmitted. */
+ if(stack->txCounter == 0)
+ {
+ /* A link-request-symbol has not been transmitted. */
+
+ /* Send link-request-symbol (input-status). */
+ s = CreateControlSymbol(STYPE0_STATUS, stack->rxAckId, QueueAvailable(stack->rxQueue),
+ STYPE1_LINK_REQUEST, LINK_REQUEST_INPUT_STATUS);
+
+ /* Save the time when this was transmitted. */
+ stack->txFrameTimeout[stack->txAckId] = stack->portTime;
+
+ /* Remember that this symbol has been transmitted. */
+ stack->txCounter = 1;
+ }
+ else
+ {
+ /* A link-request-symbol has been transmitted. */
+
+ /* Check if the link partner reply has timed out. */
+ if((stack->portTime - stack->txFrameTimeout[stack->txAckId]) < stack->portTimeout)
+ {
+ /* No timeout. */
+
+ /* A link-request-symbol has been transmitted. */
+ /* Send only idle-symbols until the link-response is received. */
+ s.type = RIO_SYMBOL_TYPE_IDLE;
+ }
+ else
+ {
+ /* Link response timeout. */
+
+ /* Check if the link-partner has not responded for too many times. */
+ if(stack->txCounter < 5)
+ {
+ /* Not too many timeouts. */
+ /* Retry and send a new link-request. */
+
+ /* Send link-request-symbol (input-status). */
+ s = CreateControlSymbol(STYPE0_STATUS, stack->rxAckId, QueueAvailable(stack->rxQueue),
+ STYPE1_LINK_REQUEST, LINK_REQUEST_INPUT_STATUS);
+
+ /* Save the time when this was transmitted. */
+ stack->txFrameTimeout[stack->txAckId] = stack->portTime;
+
+ /* Increment the number of times we have retransmitted the link-request. */
+ stack->txCounter++;
+ }
+ else
+ {
+ /* The link partner has not answered for too many times. */
+ /* Give up and set the state to uninitialized. */
+ stack->txState = TX_STATE_UNINITIALIZED;
+ s.type = RIO_SYMBOL_TYPE_IDLE;
+ ASSERT0("No link-response received, giving up.");
+ }
+ }
+ }
+ break;
+
+ case TX_STATE_UNINITIALIZED:
+ default:
+ /******************************************************************************
+ * Wait for the port to be initialized.
+ ******************************************************************************/
+
+ /* Send only idle symbols. */
+ s.type = RIO_SYMBOL_TYPE_IDLE;
+ break;
+ }
+
+ /* Return the created symbol. */
+ return s;
+}
+
+/*******************************************************************************
+ * Deprecated functions
+ *******************************************************************************/
+
+uint8_t RIO_packetTid( RioStack_t *stack )
+{
+ ASSERT(!QueueEmpty(stack->rxQueue) , "Reading from empty reception queue.");
+
+ return (uint8_t) (QueueGetFrontContent(stack->rxQueue, 1ul) & 0xfful);
+}
+
+
+uint16_t RIO_packetDestination( RioStack_t *stack )
+{
+ ASSERT(!QueueEmpty(stack->rxQueue), "Reading from empty reception queue.");
+
+ return (uint16_t) (QueueGetFrontContent(stack->rxQueue, 0ul));
+}
+
+
+uint16_t RIO_packetSource( RioStack_t *stack )
+{
+ ASSERT(!QueueEmpty(stack->rxQueue), "Reading from empty reception queue.");
+
+ return (uint16_t) (QueueGetFrontContent(stack->rxQueue, 1ul) >> 16);
+}
+
+
+uint8_t RIO_readMaintenanceReadRequestHop( RioStack_t *stack )
+{
+ ASSERT(!QueueEmpty(stack->rxQueue), "Reading from empty reception queue.");
+
+ return (QueueGetFrontContent(stack->rxQueue, 2ul) >> 24);
+}
+
+uint32_t RIO_readMaintenanceReadRequestOffset( RioStack_t *stack )
+{
+ ASSERT(!QueueEmpty(stack->rxQueue), "Reading from empty reception queue.");
+
+ return (QueueGetFrontContent(stack->rxQueue, 2ul) & 0x00fffffcul);
+}
+
+uint8_t RIO_readMaintenanceReadResponseHop( RioStack_t *stack )
+{
+ ASSERT(!QueueEmpty(stack->rxQueue), "Reading from empty reception queue.");
+
+ return (QueueGetFrontContent(stack->rxQueue, 2ul) >> 24);
+}
+
+uint32_t RIO_readMaintenanceReadResponse( RioStack_t *stack )
+{
+ uint32_t readData;
+
+
+ ASSERT(!QueueEmpty(stack->rxQueue), "Reading from empty reception queue.");
+
+ /* There is no way of knowing where the data is positioned. */
+ /* Bit-or the two words together since one of the words are zero. */
+ readData = QueueGetFrontContent(stack->rxQueue, 3ul);
+ readData |= QueueGetFrontContent(stack->rxQueue, 4ul);
+ return readData;
+}
+
+uint8_t RIO_readMaintenanceWriteRequestHop( RioStack_t *stack )
+{
+ ASSERT(!QueueEmpty(stack->rxQueue), "Reading from empty reception queue.");
+
+ return (QueueGetFrontContent(stack->rxQueue, 2ul) >> 24);
+}
+
+uint32_t RIO_readMaintenanceWriteRequestOffset( RioStack_t *stack )
+{
+ ASSERT(!QueueEmpty(stack->rxQueue), "Reading from empty reception queue.");
+
+ return (QueueGetFrontContent(stack->rxQueue, 2ul) & 0x00fffffcul);
+}
+
+uint32_t RIO_readMaintenanceWriteRequestData( RioStack_t *stack )
+{
+ ASSERT(!QueueEmpty(stack->rxQueue), "Reading from empty reception queue.");
+
+ return (QueueGetFrontContent(stack->rxQueue, 3ul) | QueueGetFrontContent(stack->rxQueue, 4ul));
+}
+
+uint8_t RIO_readMaintenanceWriteResponseHop( RioStack_t *stack )
+{
+ return (uint8_t) (QueueGetFrontContent(stack->rxQueue, 2ul) >> 24);
+}
+
+
+
+void RIO_sendNwrite8( RioStack_t *stack, const uint16_t destid, const uint32_t address,
+ const uint8_t data)
+{
+ sendNwrite(stack, destid, stack->baseDeviceId, 0, address, 1, &data, 0u);
+}
+
+
+void RIO_sendNwriteR8( RioStack_t *stack, const uint16_t destid, const uint8_t tid, const uint32_t address,
+ const uint8_t data)
+{
+ sendNwrite(stack, destid, stack->baseDeviceId, tid, address, 1, &data, 1u);
+}
+
+
+uint32_t RIO_readNwriteAddress8( RioStack_t *stack )
+{
+ uint32_t address;
+
+
+ ASSERT(!QueueEmpty(stack->rxQueue), "Reading from empty reception queue.");
+
+ /* Assemble the address from the wrsize field and the address itself to get a byte address. */
+ address = (QueueGetFrontContent(stack->rxQueue, 1ul) >> 8) & (uint32_t)0x00000003ul;
+ address |= QueueGetFrontContent(stack->rxQueue, 2ul) & (uint32_t)0xfffffffcul;
+
+ return address;
+}
+
+
+uint8_t RIO_readNwriteSize8( RioStack_t *stack )
+{
+ uint8_t wrsize;
+ uint8_t n;
+
+
+ ASSERT(!QueueEmpty(stack->rxQueue), "Reading from empty reception queue.");
+
+ /* Get the wrsize field from the packet and check its value. */
+ wrsize = (uint8_t) ((QueueGetFrontContent(stack->rxQueue, 1ul) >> 8) & (uint32_t)0xful);
+ switch(wrsize)
+ {
+ case 0:
+ /* Reading one byte. */
+ n = 1u;
+ break;
+ case 1:
+ /* Reading one byte. */
+ n = 1u;
+ break;
+ case 2:
+ /* Reading one byte. */
+ n = 1u;
+ break;
+ case 3:
+ /* Reading one byte. */
+ n = 1u;
+ break;
+ default:
+ /* Unsupported. */
+ n = 0u;
+ break;
+ }
+
+ return n;
+}
+
+
+uint8_t RIO_readNwritePayload8( RioStack_t *stack )
+{
+ uint8_t returnValue;
+ uint32_t readData;
+
+
+ ASSERT(!QueueEmpty(stack->rxQueue), "Reading from empty reception queue.");
+
+ /* Since there is no way of knowing where the byte will be placed,
+ OR all bytes in the payload and return it. */
+ readData = QueueGetFrontContent(stack->rxQueue, 3ul);
+ returnValue = (uint8_t) (readData >> 24);
+ returnValue |= (uint8_t) (readData >> 16);
+ returnValue |= (uint8_t) (readData >> 8);
+ returnValue |= (uint8_t) (readData);
+ readData = QueueGetFrontContent(stack->rxQueue, 4ul);
+ returnValue |= (uint8_t) (readData >> 24);
+ returnValue |= (uint8_t) (readData >> 16);
+ returnValue |= (uint8_t) (readData >> 8);
+ returnValue |= (uint8_t) (readData);
+
+ return returnValue;
+}
+
+void RIO_sendNread8( RioStack_t *stack, const uint16_t destid, const uint8_t tid, const uint32_t address)
+{
+ uint32_t content;
+ uint16_t crc = 0xffffu;
+
+
+ ASSERT((QueueAvailable(stack->txQueue) > 0u), "Transmission queue packet overflow.");
+
+ /* ackId(4:0)|0|vc|crf|prio(1:0)|tt(1:0)|ftype(3:0)|destinationId(15:0) */
+ /* ackId is set when the packet is transmitted. */
+ content = ((uint32_t) 0x0012ul) << 16;
+ content |= (uint32_t) destid;
+ crc = Crc32(content, crc);
+ QueueSetContent(stack->txQueue, 0ul, content);
+
+ /* sourceId(15:0)|transaction(3:0)|rdsize(3:0)|srcTID(7:0) */
+ content = ((uint32_t) stack->baseDeviceId) << 16;
+ content |= ((uint32_t) 0x4ul) << 12;
+ content |= (address & (uint32_t)0x00000003ul) << 8;
+ content |= (uint32_t) tid;
+ crc = Crc32(content, crc);
+ QueueSetContent(stack->txQueue, 1ul, content);
+
+ /* address(28:0)|wdptr|xamsbs(1:0) */
+ /* xamsbs cannot be used if the address is a word. */
+ content = address & (uint32_t)0xfffffffcul;
+ crc = Crc32(content, crc);
+ QueueSetContent(stack->txQueue, 2ul, content);
+
+ /* crc(15:0)|pad(15:0) */
+ content = ((uint32_t) crc) << 16;
+ QueueSetContent(stack->txQueue, 3ul, content);
+
+ /* Set the size of the packet and place it in the queue. */
+ QueueSetSize(stack->txQueue, 4ul);
+ stack->txQueue = QueueEnqueue(stack->txQueue);
+}
+
+
+uint32_t RIO_readNreadAddress8( RioStack_t *stack )
+{
+ uint32_t address;
+
+
+ ASSERT(!QueueEmpty(stack->rxQueue), "Reading from empty reception queue.");
+
+ /* Assemble the address from the rdsize field and the address itself to get a byte address. */
+ address = (QueueGetFrontContent(stack->rxQueue, 1ul) >> 8) & (uint32_t)0x00000003ul;
+ address |= QueueGetFrontContent(stack->rxQueue, 2ul) & (uint32_t)0xfffffffcul;
+
+ return address;
+}
+
+
+uint8_t RIO_readNreadSize8( RioStack_t *stack )
+{
+ uint8_t rdsize;
+ uint8_t n;
+
+
+ ASSERT(!QueueEmpty(stack->rxQueue), "Reading from empty reception queue.");
+
+ /* Get the rdsize field from the packet and check its value. */
+ rdsize = (uint8_t) ((QueueGetFrontContent(stack->rxQueue, 1ul) >> 8) & (uint32_t)0xful);
+ switch(rdsize)
+ {
+ case 0:
+ /* Reading one byte. */
+ n = 1u;
+ break;
+ case 1:
+ /* Reading one byte. */
+ n = 1u;
+ break;
+ case 2:
+ /* Reading one byte. */
+ n = 1u;
+ break;
+ case 3:
+ /* Reading one byte. */
+ n = 1u;
+ break;
+ default:
+ /* Unsupported. */
+ n = 0u;
+ break;
+ }
+
+ return n;
+}
+
+
+void RIO_sendMessage8( RioStack_t *stack, const uint16_t destid, const uint8_t mailbox, const uint16_t size, const uint8_t* data)
+{
+ uint32_t content;
+ uint16_t crc = 0xffffu;
+ uint32_t packetIndex;
+ uint32_t dataIndex;
+
+
+ ASSERT((QueueAvailable(stack->txQueue) > 0u), "Transmission queue packet overflow.");
+ ASSERT((size <= 256), "Packet sizes over 256 are currently unsupported.");
+
+ /* ackId(4:0)|0|vc|crf|prio(1:0)|tt(1:0)|ftype(3:0)|destinationId(15:0) */
+ /* ackId is set when the packet is transmitted. */
+ content = ((uint32_t) 0x001bul) << 16;
+ content |= (uint32_t) destid;
+ crc = Crc32(content, crc);
+ QueueSetContent(stack->txQueue, 0ul, content);
+
+ /* sourceId(15:0)|msglen(3:0)|ssize(3:0)|letter(1:0|mbox(1:0)|xmbox(3:0) */
+ content = ((uint32_t) stack->baseDeviceId) << 16;
+ if(size <= 8u)
+ {
+ content |= ((uint32_t) 0x09ul) << 8;
+ }
+ else if(size <= 16u)
+ {
+ content |= ((uint32_t) 0x0aul) << 8;
+ }
+ else if(size <= 32u)
+ {
+ content |= ((uint32_t) 0x0bul) << 8;
+ }
+ else if(size <= 64u)
+ {
+ content |= ((uint32_t) 0x0cul) << 8;
+ }
+ else if(size <= 128u)
+ {
+ content |= ((uint32_t) 0x0dul) << 8;
+ }
+ else
+ {
+ content |= ((uint32_t) 0x0eul) << 8;
+ }
+ content |= ((uint32_t)mailbox & (uint32_t)0xfu) << 4;
+ content |= ((uint32_t)mailbox) >> 4;
+ crc = Crc32(content, crc);
+ QueueSetContent(stack->txQueue, 1ul, content);
+
+ /* double-word0...double-wordN */
+ dataIndex = 0;
+ packetIndex = 8;
+ while(dataIndex < size)
+ {
+ content <<= 8;
+ if(packetIndex == 80)
+ {
+ content |= crc >> 8;
+ }
+ else if(packetIndex == 81)
+ {
+ content |= crc & 0xff;
+ }
+ else
+ {
+ content |= data[dataIndex++];
+ }
+
+ if((packetIndex & 0x3) == 3)
+ {
+ crc = Crc32(content, crc);
+ QueueSetContent(stack->txQueue, packetIndex>>2, content);
+ }
+
+ packetIndex++;
+ }
+
+ /* Pad the data to an even double word. */
+ while((dataIndex & 0x7) != 0)
+ {
+ content <<= 8;
+ dataIndex++;
+
+ if((packetIndex & 0x3) == 3)
+ {
+ crc = Crc32(content, crc);
+ QueueSetContent(stack->txQueue, packetIndex>>2, content);
+ }
+
+ packetIndex++;
+ }
+
+ /* Check where the CRC should be placed. */
+ if((packetIndex & 0x3) == 0)
+ {
+ /* crc(15:0)|pad(15:0) */
+ content = ((uint32_t) crc) << 16;
+ }
+ else
+ {
+ /* double-wordN-LSB|crc(15:0) */
+ content &= 0x0000ffff;
+ crc = Crc16(content, crc);
+ content <<= 16;
+ content |= crc;
+ }
+
+ /* Set the crc. */
+ QueueSetContent(stack->txQueue, packetIndex>>2, content);
+
+ /* Set the size of the packet and place it in the queue. */
+ QueueSetSize(stack->txQueue, 1+(packetIndex>>2));
+ stack->txQueue = QueueEnqueue(stack->txQueue);
+}
+
+
+uint8_t RIO_readMessageMbox( RioStack_t *stack )
+{
+ ASSERT(!QueueEmpty(stack->rxQueue), "Reading from empty reception queue." );
+
+ return (uint8_t) ((QueueGetFrontContent(stack->rxQueue, 1ul) >> 4) & (uint32_t)0xful);
+}
+
+
+uint16_t RIO_readMessageSize8( RioStack_t *stack )
+{
+ ASSERT(!QueueEmpty(stack->rxQueue), "Reading from empty reception queue.");
+
+ return (uint16_t) (4ul*(QueueGetFrontSize(stack->rxQueue) - 3ul));
+}
+
+
+/*lint -save -e613 */
+void RIO_readMessagePayload8( RioStack_t *stack, uint8_t* buffer )
+{
+ uint32_t size;
+ uint32_t dataIndex;
+ uint32_t packetIndex;
+ uint32_t content = 0;;
+
+
+ ASSERT((buffer != NULL), "Buffer is not allocated.");
+ ASSERT(!QueueEmpty(stack->rxQueue), "Reading from empty reception queue.");
+
+ /* Move bytes from inbound packet queue into the user buffer. */
+ /* Long messages contain a CRC in byte 80-81, this is removed when the buffer
+ is copied. */
+ size = QueueGetFrontSize(stack->rxQueue);
+ dataIndex = 0;
+ packetIndex = 8;
+ while((packetIndex>>2) < size)
+ {
+ /* Check if a new word should be read from the inbound queue. */
+ if((packetIndex & 0x3) == 0)
+ {
+ /* Get a new word. */
+ content = QueueGetFrontContent(stack->rxQueue, packetIndex>>2);
+ }
+ else
+ {
+ /* Update the current word. Remove the MSB, it has already be moved
+ to the user buffer. */
+ content <<= 8;
+ }
+
+ /* Check if the current byte is CRC. */
+ if((packetIndex != 80) && (packetIndex != 81))
+ {
+ /* Not CRC. */
+ /* Move the byte to the user buffer. */
+ buffer[dataIndex++] = (content >> 24);
+ }
+
+ /* Increment to the next position in the packet. */
+ packetIndex++;
+ }
+}
+/*lint -restore */
+
+uint16_t RIO_readDoorbellInfo( RioStack_t *stack )
+{
+ ASSERT(!QueueEmpty(stack->rxQueue), "Reading from empty reception queue.");
+
+ return (uint16_t) (QueueGetFrontContent(stack->rxQueue, 2ul) >> 16);
+}
+
+
+void RIO_sendResponseDone8( RioStack_t *stack, const uint16_t destid, const uint8_t tid, const uint32_t address, const uint8_t data)
+{
+ uint32_t content;
+ uint16_t crc = 0xffffu;
+
+
+ ASSERT((QueueAvailable(stack->txQueue) > 0u), "Transmission queue packet overflow.");
+
+ /* ackId(4:0)|0|vc|crf|prio(1:0)|tt(1:0)|ftype(3:0)|destinationId(15:0) */
+ /* ackId is set when the packet is transmitted. */
+ content = 0x001dul << 16;
+ content |= (uint32_t) destid;
+ crc = Crc32(content, crc);
+ QueueSetContent(stack->txQueue, 0ul, content);
+
+ /* sourceId(15:0)|transaction(3:0)|status(3:0)|targetTID(7:0) */
+ content = ((uint32_t) stack->baseDeviceId) << 16;
+ content |= (uint32_t)0x80ul << 8;
+ content |= (uint32_t) tid;
+ crc = Crc32(content, crc);
+ QueueSetContent(stack->txQueue, 1ul, content);
+
+ /* double-word 0 */
+ switch(address & 0x7ul)
+ {
+ case 0:
+ /* MSB byte. */
+ content = ((uint32_t) data) << 24;
+ crc = Crc32(content, crc);
+ QueueSetContent(stack->txQueue, 2ul, content);
+ content = 0x00000000ul;
+ crc = Crc32(content, crc);
+ QueueSetContent(stack->txQueue, 3ul, content);
+ break;
+ case 1:
+ content = ((uint32_t) data) << 16;
+ crc = Crc32(content, crc);
+ QueueSetContent(stack->txQueue, 2ul, content);
+ content = 0x00000000ul;
+ crc = Crc32(content, crc);
+ QueueSetContent(stack->txQueue, 3ul, content);
+ break;
+ case 2:
+ content = ((uint32_t) data) << 8;
+ crc = Crc32(content, crc);
+ QueueSetContent(stack->txQueue, 2ul, content);
+ content = 0x00000000ul;
+ crc = Crc32(content, crc);
+ QueueSetContent(stack->txQueue, 3ul, content);
+ break;
+ case 3:
+ content = ((uint32_t) data);
+ crc = Crc32(content, crc);
+ QueueSetContent(stack->txQueue, 2ul, content);
+ content = 0x00000000ul;
+ crc = Crc32(content, crc);
+ QueueSetContent(stack->txQueue, 3ul, content);
+ break;
+ case 4:
+ content = 0x00000000ul;
+ crc = Crc32(content, crc);
+ QueueSetContent(stack->txQueue, 2ul, content);
+ content = ((uint32_t) data) << 24;
+ crc = Crc32(content, crc);
+ QueueSetContent(stack->txQueue, 3ul, content);
+ break;
+ case 5:
+ content = 0x00000000ul;
+ crc = Crc32(content, crc);
+ QueueSetContent(stack->txQueue, 2ul, content);
+ content = ((uint32_t) data) << 16;
+ crc = Crc32(content, crc);
+ QueueSetContent(stack->txQueue, 3ul, content);
+ break;
+ case 6:
+ content = 0x00000000ul;
+ crc = Crc32(content, crc);
+ QueueSetContent(stack->txQueue, 2ul, content);
+ content = ((uint32_t) data) << 8;
+ crc = Crc32(content, crc);
+ QueueSetContent(stack->txQueue, 3ul, content);
+ break;
+ default:
+ /* LSB byte. */
+ content = 0x00000000ul;
+ crc = Crc32(content, crc);
+ QueueSetContent(stack->txQueue, 2ul, content);
+ content = ((uint32_t) data);
+ crc = Crc32(content, crc);
+ QueueSetContent(stack->txQueue, 3ul, content);
+ break;
+ }
+
+ /* crc(15:0)|pad(15:0) */
+ content = ((uint32_t) crc) << 16;
+ QueueSetContent(stack->txQueue, 4ul, content);
+
+ /* Set the size of the packet and place it in the queue. */
+ QueueSetSize(stack->txQueue, 5ul);
+ stack->txQueue = QueueEnqueue(stack->txQueue);
+}
+
+
+uint8_t RIO_readResponseDone8( RioStack_t *stack )
+{
+ uint8_t returnValue;
+ uint32_t readData;
+
+
+ ASSERT(!QueueEmpty(stack->rxQueue), "Reading from empty reception queue.");
+
+ /* Since there is no way of knowing where the byte will be placed,
+ OR all bytes in the reply and return it. */
+ readData = QueueGetFrontContent(stack->rxQueue, 2ul);
+ returnValue = (uint8_t) (readData >> 24);
+ returnValue |= (uint8_t) (readData >> 16);
+ returnValue |= (uint8_t) (readData >> 8);
+ returnValue |= (uint8_t) (readData);
+ readData = QueueGetFrontContent(stack->rxQueue, 3ul);
+ returnValue |= (uint8_t) (readData >> 24);
+ returnValue |= (uint8_t) (readData >> 16);
+ returnValue |= (uint8_t) (readData >> 8);
+ returnValue |= (uint8_t) (readData);
+
+ return returnValue;
+}
+
+
+
+/*******************************************************************************
+ * Local functions
+ *******************************************************************************/
+
+
+static void handleStatus(RioStack_t *stack, const uint8_t ackId, const uint8_t bufferStatus)
+{
+ /* Update the buffer status of the link partner. */
+ (void) ackId;
+ stack->txBufferStatus = bufferStatus;
+}
+
+
+static void handlePacketAccepted(RioStack_t *stack, const uint8_t ackId, const uint8_t bufferStatus)
+{
+ /* Check if an acknowledge is expected and that it is for a transmitted packet. */
+ if((stack->txAckId != stack->txAckIdWindow) && (ackId == stack->txAckId))
+ {
+ DEBUG_FRAMING_TX("ack=%i", ackId);
+ /* Acknowledge for a recently transmitted packet received. */
+ /* Remove the packet from the outbound queue and restart the transmission for
+ a new packet. */
+ stack->txQueue = QueueDequeue(stack->txQueue);
+ stack->txAckId = ACKID_INC(stack->txAckId);
+ stack->statusOutboundPacketComplete++;
+ }
+ else
+ {
+ DEBUG_FRAMING_TX("*ack=%i", ackId);
+ /* Acknowledge for an unexpected ackId or not waiting for an acknowledge. */
+ /* Link protocol violation. Discard the symbol and enter the output-error-stopped state. */
+ stack->txState = TX_STATE_OUTPUT_ERROR_STOPPED;
+ stack->txCounter = 0u;
+ stack->statusOutboundErrorPacketAccepted++;
+ DEBUG_STATE("tx:error-stopped");
+ }
+
+ /* Update the buffer status of the link partner. */
+ stack->txBufferStatus = bufferStatus;
+}
+
+
+static void handlePacketRetry(RioStack_t *stack, const uint8_t ackId, const uint8_t bufferStatus)
+{
+ /* Check if the retried packet ackId is acceptable. */
+ if(ackId == stack->txAckId)
+ {
+ DEBUG_FRAMING_TX("retry=%u", ackId);
+ /* The request for retry is for the current packet. */
+ /* Force the transmitter to send a RESTART-FROM-RETRY symbol. */
+ stack->txState = TX_STATE_OUTPUT_RETRY_STOPPED;
+ stack->statusOutboundPacketRetry++;
+ DEBUG_STATE("tx:retry-stopped");
+ }
+ else
+ {
+ DEBUG_FRAMING_TX("*retry=%u %u", ackId, stack->txAckId);
+ /* Link protocol violation. Discard the symbol and enter the output-error-stopped state. */
+ stack->txState = TX_STATE_OUTPUT_ERROR_STOPPED;
+ stack->txCounter = 0u;
+ stack->statusOutboundErrorPacketRetry++;
+ DEBUG_STATE("tx:error-stopped");
+ }
+
+ /* Update the buffer status of the link partner. */
+ stack->txBufferStatus = bufferStatus;
+}
+
+
+static void handlePacketNotAccepted(RioStack_t *stack, const uint8_t arbitrary, const uint8_t cause)
+{
+ (void) arbitrary;
+
+ /* Force the transmitter to enter output-error-stopped state. */
+ stack->txState = TX_STATE_OUTPUT_ERROR_STOPPED;
+ stack->txCounter = 0u;
+
+ /* Record the type of error that caused the packet to not being accepted. */
+ switch(cause)
+ {
+ case PACKET_NOT_ACCEPTED_CAUSE_UNEXPECTED_ACKID:
+ stack->statusPartnerErrorPacketAckId++;
+ break;
+ case PACKET_NOT_ACCEPTED_CAUSE_CONTROL_CRC:
+ stack->statusPartnerErrorControlCrc++;
+ break;
+ case PACKET_NOT_ACCEPTED_CAUSE_PACKET_CRC:
+ stack->statusPartnerErrorPacketCrc++;
+ break;
+ case PACKET_NOT_ACCEPTED_CAUSE_ILLEGAL_CHARACTER:
+ stack->statusPartnerErrorIllegalCharacter++;
+ break;
+ default:
+ stack->statusPartnerErrorGeneral++;
+ break;
+ }
+
+ DEBUG_STATE("tx:error-stopped");
+}
+
+
+static void handleLinkResponse(RioStack_t *stack, const uint8_t ackId, const uint8_t portStatus)
+{
+ uint8_t window;
+ uint8_t windowReceived;
+
+
+ (void) portStatus;
+
+ /* Check if this symbols is expected. */
+ if(stack->txState == TX_STATE_OUTPUT_ERROR_STOPPED)
+ {
+ DEBUG_FRAMING_TX("link-res:%u %u %u", stack->txAckIdWindow, stack->txAckId, ackId);
+
+ /* Calculate the number of packets that has not received an acknowledge on our side and
+ on the link-partner side. */
+ window = (stack->txAckIdWindow - stack->txAckId) & 0x1f;
+ windowReceived = (ackId - stack->txAckId) & 0x1f;
+
+ /* Check if the link-partners response is acceptable. */
+ if(windowReceived <= window)
+ {
+ /* A link-response is expected. */
+ DEBUG_STATE("tx:recover");
+
+ /* Remove entries in the queue that the link-partner has sent acknowledges for that has been lost. */
+ while(stack->txAckId != ackId)
+ {
+ stack->txQueue = QueueDequeue(stack->txQueue);
+ stack->txAckId = ACKID_INC(stack->txAckId);
+ stack->statusOutboundPacketComplete++;
+ }
+
+ /* Set the transmission window to the resend packets that has not been received. */
+ stack->txQueue = QueueWindowReset(stack->txQueue);
+ stack->txAckIdWindow = ackId;
+ stack->txFrameState = TX_FRAME_START;
+
+ /* Set the transmitter back into normal operation. */
+ stack->txState = TX_STATE_LINK_INITIALIZED;
+ }
+ else
+ {
+ /* The link-partner response is unacceptable. */
+ /* Recovery is not possible. */
+ stack->txState = TX_STATE_UNINITIALIZED;
+ ASSERT0("Unrecoverable protocol error.");
+ }
+ }
+ else
+ {
+ /* Not expecting a link-response. */
+ /* Just discard this symbol. */
+ /* REMARK: Add status counter here??? */
+ }
+}
+
+
+static void handleStartOfPacket(RioStack_t *stack)
+{
+ /* Check if a packet is already started. */
+ if(stack->rxCounter != 0u)
+ {
+ /* Packet has already started. */
+ /* This indicates an implicit end-of-packet symbol and signals the previous packet as ready. */
+ DEBUG_FRAMING_RX("cont=%u", stack->rxAckId);
+
+ /* Check the packet crc. */
+ if(stack->rxCrc == 0x0000u)
+ {
+ /* The packet has a correct CRC. */
+
+ /* Check if the packet is long enough to contain a complete packet. */
+ if(stack->rxCounter > 3u)
+ {
+ /* Packet long enough to process. */
+
+ /* Process the newly received packet and start a new one. */
+ handleNewPacketEnd(stack);
+ handleNewPacketStart(stack);
+ }
+ else
+ {
+ /* The packet has a valid CRC but is too short. */
+ /* Packet error. Enter input-error-stopped state. */
+ stack->txState = TX_STATE_SEND_PACKET_NOT_ACCEPTED;
+ stack->rxState = RX_STATE_INPUT_ERROR_STOPPED;
+ stack->rxErrorCause = PACKET_NOT_ACCEPTED_CAUSE_GENERAL;
+ stack->statusInboundErrorGeneral++;
+ DEBUG_STATE("rx:error-stopped");
+ }
+ }
+ else
+ {
+ /* The packet has an invalid CRC. */
+ /* Packet error. Enter input-error-stopped state. */
+ stack->txState = TX_STATE_SEND_PACKET_NOT_ACCEPTED;
+ stack->rxState = RX_STATE_INPUT_ERROR_STOPPED;
+ stack->rxErrorCause = PACKET_NOT_ACCEPTED_CAUSE_PACKET_CRC;
+ stack->statusInboundErrorPacketCrc++;
+ DEBUG_STATE("rx:error-stopped");
+ }
+ }
+ else
+ {
+ /* Packet has not already started. */
+ DEBUG_FRAMING_RX("start=%u", stack->rxAckId);
+ handleNewPacketStart(stack);
+ }
+}
+
+
+static void handleEndOfPacket(RioStack_t *stack)
+{
+ DEBUG_FRAMING_RX("end=%u", stack->rxAckId);
+
+ /* Check if the CRC is correct. */
+ if(stack->rxCrc == 0x0000u)
+ {
+ /* The packet has a correct CRC. */
+
+ /* Check if the packet is long enough to contain a complete packet. */
+ if(stack->rxCounter > 3u)
+ {
+ /* Packet long enough to process. */
+
+ /* Process the newly received packet. */
+ handleNewPacketEnd(stack);
+ }
+ else
+ {
+ /* The packet has a valid CRC but is too short. */
+ /* Packet error. Enter input-error-stopped state. */
+ stack->txState = TX_STATE_SEND_PACKET_NOT_ACCEPTED;
+ stack->rxState = RX_STATE_INPUT_ERROR_STOPPED;
+ stack->rxErrorCause = PACKET_NOT_ACCEPTED_CAUSE_GENERAL;
+ stack->statusInboundErrorGeneral++;
+ DEBUG_STATE("rx:error-stopped");
+ }
+ }
+ else
+ {
+ /* The packet has an invalid CRC. */
+ /* Packet error. Enter input-error-stopped state. */
+ stack->txState = TX_STATE_SEND_PACKET_NOT_ACCEPTED;
+ stack->rxState = RX_STATE_INPUT_ERROR_STOPPED;
+ stack->rxErrorCause = PACKET_NOT_ACCEPTED_CAUSE_PACKET_CRC;
+ stack->statusInboundErrorPacketCrc++;
+ DEBUG_STATE("rx:error-stopped");
+ }
+}
+
+
+static void handleNewPacketStart(RioStack_t *stack)
+{
+ /* Check if there are buffers available to store the new frame. */
+ if (QueueAvailable(stack->rxQueue) > 0u)
+ {
+ /* There are buffers available to accept the new packet. */
+
+ /* Update the reception counter to indicate the frame has started. */
+ stack->rxCounter = 1;
+ }
+ else
+ {
+ /* There are no buffers available. */
+ /* Go to input retry stopped state. */
+ DEBUG_FRAMING_RX("retry=%u", stack->rxAckId);
+ stack->statusInboundPacketRetry++;
+ stack->txState = TX_STATE_SEND_PACKET_RETRY;
+ stack->rxState = RX_STATE_INPUT_RETRY_STOPPED;
+ DEBUG_STATE("rx:retry-stopped");
+ }
+}
+
+
+static void handleNewPacketEnd(RioStack_t *stack)
+{
+ uint32_t *packet;
+ uint32_t ftype;
+ uint32_t transaction;
+
+
+ /* Save the size of the packet. */
+ QueueSetSize(stack->rxQueue, (uint32_t)stack->rxCounter - (uint32_t)1ul);
+
+ /* Get the packet and information about its type. */
+ packet = QueueGetBackBuffer(stack->rxQueue);
+ ftype = FTYPE_GET(packet);
+ transaction = TRANSACTION_GET(packet);
+
+#ifdef RIO_TRANSPARENT
+ /* Always forward the packet to the top of the stack. */
+ stack->rxQueue = QueueEnqueue(stack->rxQueue);
+#else
+ /* Check if the packet should be forwarded to the top of the stack. */
+ if ((QueueGetBackSize(stack->rxQueue) == MAINTENANCE_TRANSACTION_READ_REQUEST_SIZE) &&
+ (ftype == FTYPE_MAINTENANCE) && (transaction == TRANSACTION_MAINT_READ_REQUEST))
+ {
+ /* Received maintenance read request. */
+ /* Send a maintenance read response. This packet is aimed at the stack, it should
+ not be forwarded. */
+ /* Note that only single word accesses are supported. */
+ RIO_sendMaintenanceReadResponse(stack, SRCID_GET(packet),TID_GET(packet), 0xff,
+ RIO_readConfig(stack, CONFIG_OFFSET_GET(packet)));
+ }
+ else if ((QueueGetBackSize(stack->rxQueue) == MAINTENANCE_TRANSACTION_WRITE_REQUEST_SIZE) &&
+ (ftype == FTYPE_MAINTENANCE) && (transaction == TRANSACTION_MAINT_WRITE_REQUEST))
+ {
+ /* Received maintenance write request. */
+ /* Send a maintenance write response. This packet is aimed at the stack, it should
+ not be forwarded. */
+ /* Note that only single word accesses are supported. */
+ RIO_writeConfig(stack, CONFIG_OFFSET_GET(packet),
+ DOUBLE_WORD_MSB_GET(packet, 0) | DOUBLE_WORD_LSB_GET(packet, 0));
+ RIO_sendMaintenanceWriteResponse(stack, SRCID_GET(packet), TID_GET(packet), 0xff);
+ }
+ else
+ {
+ /* Forward this packet to the top of the stack. */
+ stack->rxQueue = QueueEnqueue(stack->rxQueue);
+ }
+#endif
+ /* Reset the reception counter. */
+ stack->rxCounter = 0u;
+
+ /* Update the ackId for the receiver. */
+ stack->rxAckId = ACKID_INC(stack->rxAckId);
+
+ /* Update status counter. */
+ stack->statusInboundPacketComplete++;
+}
+
+
+static void handleLinkRequest(RioStack_t *stack, uint8_t cmd)
+{
+ /* Check the command of the link-request. */
+ if(cmd == LINK_REQUEST_INPUT_STATUS)
+ {
+ /* Input-status requested. */
+ /* Return input port status. */
+
+ /* Force the transmitter to send a link-response-symbol. */
+ stack->txState = TX_STATE_SEND_LINK_RESPONSE;
+ }
+ else if(cmd == LINK_REQUEST_RESET_DEVICE)
+ {
+ /* Reset-device requested. */
+ /* REMARK: Support this??? */
+ }
+ else
+ {
+ /* Unrecognized command. */
+ /* Dont do anything. */
+ }
+
+ /* Always cancel an ongoing frame when a link-request has been received. */
+ stack->rxCounter = 0;
+
+ /* Receiving this indicates the link partner having encountered a potential problem. */
+ /* Count the number of times this happens. */
+ stack->statusPartnerLinkRequest++;
+}
+
+
+static void sendMaintenanceReadRequest( RioStack_t *stack, const uint16_t destid, const uint16_t srcid, const uint8_t tid,
+ const uint8_t hopCount, const uint32_t offset)
+{
+ uint32_t content;
+ uint16_t crc = 0xffffu;
+
+
+ ASSERT((QueueAvailable(stack->txQueue) > 0u), "Transmission queue packet overflow.");
+
+ /* ackId(4:0)|0|vc|crf|prio(1:0)|tt(1:0)|ftype(3:0)|destinationId(15:0) */
+ /* ackId is set when the packet is transmitted. */
+ content = 0x0018ul << 16;
+ content |= (uint32_t) destid;
+ crc = Crc32(content, crc);
+ QueueSetContent(stack->txQueue, 0ul, content);
+
+ /* sourceId(15:0)|transaction(3:0)|rdsize(3:0)|srcTID(7:0) */
+ content = ((uint32_t) srcid) << 16;
+ content |= (uint32_t) 0x08ul << 8;
+ content |= (uint32_t) tid;
+ crc = Crc32(content, crc);
+ QueueSetContent(stack->txQueue, 1ul, content);
+
+ /* hopcount(7:0)|configOffset(20:0)|wdptr|reserved(1:0) */
+ content = ((uint32_t) hopCount) << 24;
+ content |= offset & (uint32_t) 0x00fffffcul;
+ crc = Crc32(content, crc);
+ QueueSetContent(stack->txQueue, 2ul, content);
+
+ /* crc(15:0)|pad(15:0) */
+ content = ((uint32_t) crc) << 16;
+ QueueSetContent(stack->txQueue, 3ul, content);
+
+ /* Set the size of the packet and place it in the queue. */
+ QueueSetSize(stack->txQueue, 4ul);
+ stack->txQueue = QueueEnqueue(stack->txQueue);
+}
+
+static void receiveMaintenanceReadRequest( RioStack_t *stack, uint16_t *destid, uint16_t *srcid, uint8_t *tid,
+ uint8_t *hopCount, uint32_t *offset)
+{
+ uint32_t *packet;
+
+
+ ASSERT(!QueueEmpty(stack->rxQueue), "Reading from empty reception queue.");
+
+ packet = QueueGetFrontBuffer(stack->rxQueue);
+
+ *destid = DESTID_GET(packet);
+ *srcid = SRCID_GET(packet);
+ *tid = TID_GET(packet);
+ *hopCount = HOP_GET(packet);
+ *offset = CONFIG_OFFSET_GET(packet);
+}
+
+static void sendMaintenanceReadResponse( RioStack_t *stack, const uint16_t destid, const uint16_t srcid, const uint8_t tid,
+ const uint8_t hopCount, const uint32_t data)
+{
+ uint32_t content;
+ uint16_t crc = 0xffffu;
+
+
+ /* REMARK: What should we do if there are no buffers available to send the packet... */
+ ASSERT((QueueAvailable(stack->txQueue) > 0u), "Transmission queue packet overflow.");
+
+ /* ackId(4:0)|0|vc|crf|prio(1:0)|tt(1:0)|ftype(3:0)|destinationId(15:0) */
+ /* ackId is set when the packet is transmitted. */
+ content = (uint32_t)0x0018ul << 16;
+ content |= (uint32_t) destid;
+ crc = Crc32(content, crc);
+ QueueSetContent(stack->txQueue, 0ul, content);
+
+ /* sourceId(15:0)|transaction(3:0)|rdsize(3:0)|srcTID(7:0) */
+ content = (uint32_t) srcid << 16;
+ content |= (uint32_t) 0x28ul << 8;
+ content |= (uint32_t) tid;
+ crc = Crc32(content, crc);
+ QueueSetContent(stack->txQueue, 1ul, content);
+
+ /* hopcount(7:0)|reserved(23:0) */
+ content = (uint32_t) (hopCount << 24);
+ crc = Crc32(content, crc);
+ QueueSetContent(stack->txQueue, 2ul, content);
+
+ /* double-word 0 */
+ /* Send the data in both words since this function cannot know the offset the request was sent to. */
+ content = data;
+ crc = Crc32(content, crc);
+ QueueSetContent(stack->txQueue, 3ul, content);
+ content = data;
+ crc = Crc32(content, crc);
+ QueueSetContent(stack->txQueue, 4ul, content);
+
+ /* crc(15:0)|pad(15:0) */
+ content = (uint32_t)crc << 16;
+ QueueSetContent(stack->txQueue, 5ul, content);
+
+ /* Set the size of the packet and place it in the queue. */
+ QueueSetSize(stack->txQueue, 6ul);
+ stack->txQueue = QueueEnqueue(stack->txQueue);
+}
+
+static void receiveMaintenanceReadResponse( RioStack_t *stack, uint16_t *destid, uint16_t *srcid, uint8_t *tid,
+ uint8_t *hopCount, uint32_t *data)
+{
+ uint32_t *packet;
+
+
+ ASSERT((data != NULL), "Buffer is not allocated.");
+ ASSERT(!QueueEmpty(stack->rxQueue), "Reading from empty reception queue.");
+
+ packet = QueueGetFrontBuffer(stack->rxQueue);
+
+ *destid = DESTID_GET(packet);
+ *srcid = SRCID_GET(packet);
+ *tid = TID_GET(packet);
+ *hopCount = HOP_GET(packet);
+ *data = DOUBLE_WORD_MSB_GET(packet, 0) | DOUBLE_WORD_LSB_GET(packet, 0);
+}
+
+static void sendMaintenanceWriteRequest( RioStack_t *stack, const uint16_t destid, const uint16_t srcid, const uint8_t tid,
+ const uint8_t hopCount, const uint32_t offset, const uint32_t data )
+{
+ uint32_t content;
+ uint16_t crc = 0xffffu;
+
+
+ ASSERT((QueueAvailable(stack->txQueue) > 0u), "Transmission queue packet overflow.");
+
+ /* ackId(4:0)|0|vc|crf|prio(1:0)|tt(1:0)|ftype(3:0)|destinationId(15:0) */
+ /* ackId is set when the packet is transmitted. */
+ content = 0x0018ul << 16;
+ content |= (uint32_t) destid;
+ crc = Crc32(content, crc);
+ QueueSetContent(stack->txQueue, 0ul, content);
+
+ /* sourceId(15:0)|transaction(3:0)|rdsize(3:0)|srcTID(7:0) */
+ content = ((uint32_t) srcid) << 16;
+ content |= (uint32_t)0x18ul << 8;
+ content |= (uint32_t) tid;
+ crc = Crc32(content, crc);
+ QueueSetContent(stack->txQueue, 1ul, content);
+
+ /* hopcount(7:0)|configOffset(20:0)|wdptr|reserved(1:0) */
+ content = ((uint32_t) hopCount) << 24;
+ content |= offset & (uint32_t)0x00fffffcul;
+ crc = Crc32(content, crc);
+ QueueSetContent(stack->txQueue, 2ul, content);
+
+ /* double-word 0 */
+ /* Note that both words are filled in to avoid looking at the offset. The receiver will not
+ look at the other part anyway. The standard does not say anything about the value of the padding. */
+ content = data;
+ crc = Crc32(content, crc);
+ QueueSetContent(stack->txQueue, 3ul, content);
+ content = data;
+ crc = Crc32(content, crc);
+ QueueSetContent(stack->txQueue, 4ul, content);
+
+ /* crc(15:0)|pad(15:0) */
+ content = ((uint32_t) crc) << 16;
+ QueueSetContent(stack->txQueue, 5ul, content);
+
+ /* Set the size of the packet and place it in the queue. */
+ QueueSetSize(stack->txQueue, 6ul);
+ stack->txQueue = QueueEnqueue(stack->txQueue);
+}
+
+static void receiveMaintenanceWriteRequest( RioStack_t *stack, uint16_t *destid, uint16_t *srcid, uint8_t *tid,
+ uint8_t *hopCount, uint32_t *offset, uint32_t *data )
+{
+ uint32_t *packet;
+
+
+ ASSERT((data != NULL), "Buffer is not allocated.");
+ ASSERT(!QueueEmpty(stack->rxQueue), "Reading from empty reception queue.");
+
+ packet = QueueGetFrontBuffer(stack->rxQueue);
+
+ *destid = DESTID_GET(packet);
+ *srcid = SRCID_GET(packet);
+ *tid = TID_GET(packet);
+ *hopCount = HOP_GET(packet);
+ *offset = CONFIG_OFFSET_GET(packet);
+ *data = DOUBLE_WORD_MSB_GET(packet, 0) | DOUBLE_WORD_LSB_GET(packet, 0);
+}
+
+static void sendMaintenanceWriteResponse( RioStack_t *stack, const uint16_t destid, const uint16_t srcid, const uint8_t tid,
+ const uint8_t hopCount)
+{
+ uint32_t content;
+ uint16_t crc = 0xffffu;
+
+
+ /* REMARK: What should we do if there are no buffers available to send the packet... */
+ ASSERT((QueueAvailable(stack->txQueue) > 0u), "Transmission queue packet overflow.");
+
+ /* ackId(4:0)|0|vc|crf|prio(1:0)|tt(1:0)|ftype(3:0)|destinationId(15:0) */
+ /* ackId is set when the packet is transmitted. */
+ content = (uint32_t)0x0018ul << 16;
+ content |= (uint32_t) destid;
+ crc = Crc32(content, crc);
+ QueueSetContent(stack->txQueue, 0ul, content);
+
+ /* sourceId(15:0)|transaction(3:0)|rdsize(3:0)|srcTID(7:0) */
+ content = (uint32_t) srcid << 16;
+ content |= (uint32_t)0x38ul << 8;
+ content |= (uint32_t) tid;
+ crc = Crc32(content, crc);
+ QueueSetContent(stack->txQueue, 1ul, content);
+
+ /* hopcount(7:0)|reserved(23:0) */
+ content = hopCount << 24;
+ crc = Crc32(content, crc);
+ QueueSetContent(stack->txQueue, 2ul, content);
+
+ /* crc(15:0)|pad(15:0) */
+ content = (uint32_t)crc << 16;
+ QueueSetContent(stack->txQueue, 3ul, content);
+
+ /* Set the size of the packet and place it in the queue. */
+ QueueSetSize(stack->txQueue, 4ul);
+ stack->txQueue = QueueEnqueue(stack->txQueue);
+}
+
+static void receiveMaintenanceWriteResponse( RioStack_t *stack, uint16_t *destid, uint16_t *srcid, uint8_t *tid,
+ uint8_t *hopCount)
+{
+ uint32_t *packet;
+
+
+ ASSERT(!QueueEmpty(stack->rxQueue), "Reading from empty reception queue.");
+
+ packet = QueueGetFrontBuffer(stack->rxQueue);
+
+ *destid = DESTID_GET(packet);
+ *srcid = SRCID_GET(packet);
+ *tid = TID_GET(packet);
+ *hopCount = HOP_GET(packet);
+}
+
+/* REMARK: Use a packet pointer instead of using the QueueSetContent... */
+static void sendNwrite( RioStack_t *stack, const uint16_t destid, const uint16_t srcid, const uint8_t tid,
+ const uint32_t address, const uint16_t bufferSize, const uint8_t *buffer,
+ const uint8_t ack)
+{
+ uint32_t content;
+ uint32_t size;
+ uint16_t wrsize = wrsizeGet(address, bufferSize);
+
+
+ ASSERT((QueueAvailable(stack->txQueue) > 0u), "Transmission queue packet overflow.");
+ ASSERT((wrsize != 0xffff), "Write access unsupported by protocol.");
+
+ /* ackId(4:0)|0|vc|crf|prio(1:0)|tt(1:0)|ftype(3:0)|destinationId(15:0) */
+ /* ackId is set when the packet is transmitted. */
+ content = ((uint32_t)0x0015ul) << 16;
+ content |= (uint32_t)destid;
+ QueueSetContent(stack->txQueue, 0ul, content);
+
+ /* sourceId(15:0)|transaction(3:0)|wrsize(3:0)|srcTID(7:0) */
+ content = ((uint32_t) srcid) << 16;
+ if(ack == 0u)
+ {
+ /* Send NWRITE. */
+ content |= (uint32_t) TRANSACTION_WRITE_NWRITE << 12;
+ }
+ else
+ {
+ /* Send NWRITE_R. */
+ content |= (uint32_t) TRANSACTION_WRITE_NWRITER << 12;
+ }
+ content |= (uint32_t) (wrsize & 0x0f00);
+ content |= (uint32_t) tid;
+ QueueSetContent(stack->txQueue, 1ul, content);
+
+ /* address(28:0)|wdptr|xamsbs(1:0) */
+ /* wrsize also contains wdptr in the lower nibble. */
+ /* REMARK: Note that xamsbs cannot be used if the address is a word. If the 2 msb bits in the
+ 34-bit address should be used, another mechanism to set it should be used. */
+ content = (address & 0xfffffff8ul);
+ content |= ((uint32_t) (wrsize & 0x000f)) << 2;
+ QueueSetContent(stack->txQueue, 2ul, content);
+
+ /* Place data buffer into the payload of the packet. */
+ size = setPacketPayload(QueueGetBackBuffer(stack->txQueue), 12, address & 0x7, bufferSize, buffer);
+
+ /* Set the size of the packet and place it in the queue. */
+ QueueSetSize(stack->txQueue, size+1);
+ stack->txQueue = QueueEnqueue(stack->txQueue);
+}
+
+static uint16_t receiveNwrite( RioStack_t *stack, uint16_t *destid, uint16_t *srcid, uint8_t *tid,
+ uint32_t *address, const uint16_t dataLength, uint8_t *data )
+{
+ uint32_t *packet;
+ uint8_t offset;
+ uint16_t size;
+ uint8_t wrsize;
+ uint8_t wdptr;
+
+
+ ASSERT((data != NULL), "Buffer is not allocated.");
+ ASSERT(!QueueEmpty(stack->rxQueue), "Reading from empty reception queue.");
+
+ packet = QueueGetFrontBuffer(stack->rxQueue);
+
+ wrsize = WRSIZE_GET(packet);
+ wdptr = WDPTR_GET(packet);
+ wrsizeToOffset(wrsize, wdptr, &offset, &size);
+
+ *destid = DESTID_GET(packet);
+ *srcid = SRCID_GET(packet);
+ *tid = TID_GET(packet);
+ *address = ADDRESS_GET(packet) | offset;
+
+ if(size > 16)
+ {
+ /* Remove header and crc from the size count. */
+ size = ((QueueGetFrontSize(stack->rxQueue)-4) * 4);
+ }
+
+ /* Check if there is enough room in the receiving buffer. */
+ if(size <= dataLength)
+ {
+ return getPacketPayload(packet, 12, offset, size, data);
+ }
+ else
+ {
+ return 0;
+ }
+}
+
+static void sendNread( RioStack_t *stack, const uint16_t destid, const uint16_t srcid, const uint8_t tid,
+ const uint32_t address, const uint16_t dataLength)
+{
+ uint32_t content;
+ uint16_t crc = 0xffffu;
+ uint16_t rdsize = rdsizeGet(address, dataLength);
+
+
+ ASSERT((QueueAvailable(stack->txQueue) > 0u), "Transmission queue packet overflow.");
+ ASSERT((rdsize != 0xffff), "Read access unsupported by protocol.");
+
+ /* ackId(4:0)|0|vc|crf|prio(1:0)|tt(1:0)|ftype(3:0)|destinationId(15:0) */
+ /* ackId is set when the packet is transmitted. */
+ content = ((uint32_t) 0x0012ul) << 16;
+ content |= (uint32_t) destid;
+ crc = Crc32(content, crc);
+ QueueSetContent(stack->txQueue, 0ul, content);
+
+ /* sourceId(15:0)|transaction(3:0)|rdsize(3:0)|srcTID(7:0) */
+ content = ((uint32_t) srcid) << 16;
+ content |= ((uint32_t) TRANSACTION_REQUEST_NREAD) << 12;
+ content |= (uint32_t) (rdsize & 0x0f00);
+ content |= (uint32_t) tid;
+ crc = Crc32(content, crc);
+ QueueSetContent(stack->txQueue, 1ul, content);
+
+ /* address(28:0)|wdptr|xamsbs(1:0) */
+ /* rdsize also contains wdptr in the lower nibble. */
+ /* REMARK: Note that xamsbs cannot be used if the address is a word. If the 2 msb bits in the
+ 34-bit address should be used, another mechanism to set it should be used. */
+ content = address & 0xfffffff8ul;
+ content |= ((uint32_t) (rdsize & 0x000f)) << 2;
+ crc = Crc32(content, crc);
+ QueueSetContent(stack->txQueue, 2ul, content);
+
+ /* crc(15:0)|pad(15:0) */
+ content = ((uint32_t) crc) << 16;
+ QueueSetContent(stack->txQueue, 3ul, content);
+
+ /* Set the size of the packet and place it in the queue. */
+ QueueSetSize(stack->txQueue, 4ul);
+ stack->txQueue = QueueEnqueue(stack->txQueue);
+}
+
+static void receiveNread( RioStack_t *stack, uint16_t *destid, uint16_t *srcid, uint8_t *tid,
+ uint32_t *address, uint16_t *dataLength)
+{
+ uint32_t *packet;
+ uint8_t offset;
+ uint16_t size;
+ uint8_t rdsize;
+ uint8_t wdptr;
+
+
+ ASSERT(!QueueEmpty(stack->rxQueue), "Reading from empty reception queue.");
+
+ packet = QueueGetFrontBuffer(stack->rxQueue);
+
+ rdsize = WRSIZE_GET(packet);
+ wdptr = WDPTR_GET(packet);
+ rdsizeToOffset(rdsize, wdptr, &offset, &size);
+
+ *destid = DESTID_GET(packet);
+ *srcid = SRCID_GET(packet);
+ *tid = TID_GET(packet);
+ *address = ADDRESS_GET(packet) | offset;
+ *dataLength = size;
+}
+
+static void sendResponseDonePayload( RioStack_t *stack, const uint16_t destid, const uint16_t srcid, const uint8_t tid,
+ const uint32_t address, const uint16_t bufferSize, const uint8_t *buffer)
+{
+ uint32_t content;
+ uint32_t size;
+
+
+ ASSERT((buffer != NULL), "Buffer is not allocated.");
+ ASSERT((QueueAvailable(stack->txQueue) > 0u), "Transmission queue packet overflow.");
+
+ /* ackId(4:0)|0|vc|crf|prio(1:0)|tt(1:0)|ftype(3:0)|destinationId(15:0) */
+ /* ackId is set when the packet is transmitted. */
+ content = 0x001dul << 16;
+ content |= (uint32_t) destid;
+ QueueSetContent(stack->txQueue, 0ul, content);
+
+ /* sourceId(15:0)|transaction(3:0)|status(3:0)|targetTID(7:0) */
+ content = ((uint32_t) srcid) << 16;
+ content |= ((uint32_t) TRANSACTION_RESPONSE_WITH_PAYLOAD) << 12;
+ content |= (uint32_t) tid;
+ QueueSetContent(stack->txQueue, 1ul, content);
+
+ /* Place data buffer into the payload of the packet. */
+ size = setPacketPayload(QueueGetBackBuffer(stack->txQueue), 8, address & 0x7, bufferSize, buffer);
+
+ /* Set the size of the packet and place it in the queue. */
+ QueueSetSize(stack->txQueue, size+1);
+ stack->txQueue = QueueEnqueue(stack->txQueue);
+}
+
+
+static uint16_t receiveResponseDonePayload( RioStack_t *stack, uint16_t *destid, uint16_t *srcid, uint8_t *tid,
+ const uint32_t address, const uint16_t dataLength, uint8_t *data )
+{
+ uint32_t *packet;
+
+
+ ASSERT((data != NULL), "Buffer is not allocated.");
+ ASSERT(!QueueEmpty(stack->rxQueue), "Reading from empty reception queue.");
+
+ packet = QueueGetFrontBuffer(stack->rxQueue);
+
+ *destid = DESTID_GET(packet);
+ *srcid = SRCID_GET(packet);
+ *tid = TID_GET(packet);
+
+ return getPacketPayload(packet, 8, address & 0x7, dataLength, data);
+}
+
+
+static void sendResponse( RioStack_t *stack, const uint16_t destid, const uint16_t srcid, const uint8_t tid,
+ const uint8_t status)
+{
+ uint32_t content;
+ uint16_t crc = 0xffffu;
+
+
+ ASSERT((QueueAvailable(stack->txQueue) > 0u), "Transmission queue packet overflow.");
+
+ /* ackId(4:0)|0|vc|crf|prio(1:0)|tt(1:0)|ftype(3:0)|destinationId(15:0) */
+ /* ackId is set when the packet is transmitted. */
+ content = (uint32_t)0x001dul << 16;
+ content |= destid;
+ crc = Crc32(content, crc);
+ QueueSetContent(stack->txQueue, 0ul, content);
+
+ /* sourceId(15:0)|transaction(3:0)|status(3:0)|targetTID(7:0) */
+ content = (uint32_t)srcid << 16;
+ content |= ((uint32_t)status & (uint32_t)0x0ful) << 8;
+ content |= tid;
+ crc = Crc32(content, crc);
+ QueueSetContent(stack->txQueue, 1ul, content);
+
+ /* crc(15:0)|pad(15:0) */
+ content = (uint32_t)crc << 16;
+ QueueSetContent(stack->txQueue, 2ul, content);
+
+ /* Set the size of the packet and place it in the queue. */
+ QueueSetSize(stack->txQueue, 3ul);
+ stack->txQueue = QueueEnqueue(stack->txQueue);
+}
+
+
+static void receiveResponse( RioStack_t *stack, uint16_t *destid, uint16_t *srcid, uint8_t *tid)
+{
+ uint32_t *packet;
+
+
+ ASSERT(!QueueEmpty(stack->rxQueue), "Reading from empty reception queue.");
+
+ packet = QueueGetFrontBuffer(stack->rxQueue);
+
+ *destid = DESTID_GET(packet);
+ *srcid = SRCID_GET(packet);
+ *tid = TID_GET(packet);
+}
+
+
+static void sendDoorbell( RioStack_t *stack, const uint16_t destid, const uint16_t srcid, const uint8_t tid,
+ const uint16_t info )
+{
+ uint32_t content;
+ uint16_t crc;
+
+
+ ASSERT((QueueAvailable(stack->txQueue) > 0u), "Transmission queue packet overflow.");
+
+ /* ackId(4:0)|0|vc|crf|prio(1:0)|tt(1:0)|ftype(3:0)|destinationId(15:0) */
+ /* ackId is set when the packet is transmitted. */
+ content = 0x001aul << 16;
+ content |= (uint32_t) destid;
+ crc = Crc32(content, 0xffffu);
+ QueueSetContent(stack->txQueue, 0ul, content);
+
+ /* sourceId(15:0)|rsrv(7:0)|srcTID(7:0) */
+ content = ((uint32_t) srcid) << 16;
+ content |= (uint32_t) tid;
+ crc = Crc32(content, crc);
+ QueueSetContent(stack->txQueue, 1ul, content);
+
+ /* infoMSB(7:0)|infoLSB(7:0)|crc(15:0) */
+ content = ((uint32_t) info) << 16;
+ crc = Crc16(info, crc);
+ content |= crc;
+ QueueSetContent(stack->txQueue, 2ul, content);
+
+ /* Set the size of the packet and place it in the queue. */
+ QueueSetSize(stack->txQueue, 3ul);
+ stack->txQueue = QueueEnqueue(stack->txQueue);
+}
+
+
+static void receiveDoorbell( RioStack_t *stack, uint16_t *destid, uint16_t *srcid, uint8_t *tid,
+ uint16_t *info)
+{
+ uint32_t *packet;
+
+
+ ASSERT(!QueueEmpty(stack->rxQueue), "Reading from empty reception queue.");
+
+ packet = QueueGetFrontBuffer(stack->rxQueue);
+
+ *destid = DESTID_GET(packet);
+ *srcid = SRCID_GET(packet);
+ *tid = TID_GET(packet);
+ *info = INFO_GET(packet);
+}
+
+
+static void sendMessage( RioStack_t *stack, const uint16_t destid, const uint16_t srcid, const uint8_t mailbox,
+ const uint16_t bufferSize, const uint8_t* bufferData)
+{
+ uint32_t content;
+ uint32_t size;
+
+
+ ASSERT((QueueAvailable(stack->txQueue) > 0u), "Transmission queue packet overflow.");
+ ASSERT((bufferSize <= 256), "Packet sizes larger than 256 are currently unsupported.");
+
+ /* ackId(4:0)|0|vc|crf|prio(1:0)|tt(1:0)|ftype(3:0)|destinationId(15:0) */
+ /* ackId is set when the packet is transmitted. */
+ content = ((uint32_t) 0x001bul) << 16;
+ content |= (uint32_t) destid;
+ QueueSetContent(stack->txQueue, 0ul, content);
+
+ /* sourceId(15:0)|msglen(3:0)|ssize(3:0)|letter(1:0|mbox(1:0)|xmbox(3:0) */
+ content = ((uint32_t) srcid) << 16;
+ if(bufferSize <= 8u)
+ {
+ content |= ((uint32_t) 0x09ul) << 8;
+ }
+ else if(bufferSize <= 16u)
+ {
+ content |= ((uint32_t) 0x0aul) << 8;
+ }
+ else if(bufferSize <= 32u)
+ {
+ content |= ((uint32_t) 0x0bul) << 8;
+ }
+ else if(bufferSize <= 64u)
+ {
+ content |= ((uint32_t) 0x0cul) << 8;
+ }
+ else if(bufferSize <= 128u)
+ {
+ content |= ((uint32_t) 0x0dul) << 8;
+ }
+ else
+ {
+ content |= ((uint32_t) 0x0eul) << 8;
+ }
+ content |= ((uint32_t)mailbox & (uint32_t)0xfu) << 4;
+ content |= ((uint32_t)mailbox) >> 4;
+ QueueSetContent(stack->txQueue, 1ul, content);
+
+ /* Place data buffer into the payload of the packet. */
+ size = setPacketPayload(QueueGetBackBuffer(stack->txQueue), 8, 0, bufferSize, bufferData);
+
+ /* Set the size of the packet and place it in the queue. */
+ QueueSetSize(stack->txQueue, size+1);
+ stack->txQueue = QueueEnqueue(stack->txQueue);
+}
+
+static uint16_t receiveMessage( RioStack_t *stack, uint16_t *destid, uint16_t *srcid, uint8_t *mailbox,
+ const uint16_t dataLength, uint8_t *data )
+{
+ uint32_t *packet;
+ uint32_t size;
+
+
+ ASSERT((data != NULL), "Buffer is not allocated.");
+ ASSERT(!QueueEmpty(stack->rxQueue), "Reading from empty reception queue.");
+
+ /* Get a pointer to the packet. */
+ packet = QueueGetFrontBuffer(stack->rxQueue);
+
+ /* The higher mailbox numbers are used with messages that cannot be multi-packets. */
+ *destid = DESTID_GET(packet);
+ *srcid = SRCID_GET(packet);
+ *mailbox = XMBOX_GET(packet);
+ *mailbox <<= 2;
+ *mailbox |= LETTER_GET(packet);
+ *mailbox <<= 2;
+ *mailbox |= MBOX_GET(packet);
+
+ /* Calculate the number of bytes to transfer. */
+ /* Remove the header and crc from the size count. */
+ size = (QueueGetFrontSize(stack->rxQueue)-3) * 4;
+
+ /* Check if there is enough room in the receiving buffer. */
+ if(size <= dataLength)
+ {
+ return getPacketPayload(packet, 8, 0, size, data);
+ }
+ else
+ {
+ return 0;
+ }
+
+}
+
+static void sendMessageResponse( RioStack_t *stack, const uint16_t destid, const uint16_t srcid, const uint8_t mailbox,
+ const uint8_t status)
+{
+ uint32_t content;
+ uint16_t crc = 0xffffu;
+
+
+ ASSERT((QueueAvailable(stack->txQueue) > 0u), "Transmission queue packet overflow.");
+
+ /* ackId(4:0)|0|vc|crf|prio(1:0)|tt(1:0)|ftype(3:0)|destinationId(15:0) */
+ /* ackId is set when the packet is transmitted. */
+ content = (uint32_t)0x001dul << 16;
+ content |= destid;
+ crc = Crc32(content, crc);
+ QueueSetContent(stack->txQueue, 0ul, content);
+
+ /* sourceId(15:0)|transaction(3:0)|status(3:0)|letter(1:0|mbox(1:0)|msgseg(3:0) */
+ content = (uint32_t)srcid << 16;
+ content |= (uint32_t)0x1ul << 12;
+ content |= ((uint32_t)status & (uint32_t)0xful) << 8;
+ content |= ((uint32_t)mailbox & (uint32_t)0xful) << 4;
+ content |= ((uint32_t)mailbox) >> 4;
+ crc = Crc32(content, crc);
+ QueueSetContent(stack->txQueue, 1ul, content);
+
+ /* crc(15:0)|pad(15:0) */
+ content = (uint32_t)crc << 16;
+ QueueSetContent(stack->txQueue, 2ul, content);
+
+ /* Set the size of the packet and place it in the queue. */
+ QueueSetSize(stack->txQueue, 3ul);
+ stack->txQueue = QueueEnqueue(stack->txQueue);
+}
+
+static void receiveMessageResponse( RioStack_t *stack, uint16_t *destid, uint16_t *srcid, uint8_t *mailbox)
+{
+ uint32_t *packet;
+
+
+ ASSERT(!QueueEmpty(stack->rxQueue), "Reading from empty reception queue.");
+
+ packet = QueueGetFrontBuffer(stack->rxQueue);
+
+ *destid = DESTID_GET(packet);
+ *srcid = SRCID_GET(packet);
+ *mailbox = XMBOX_GET(packet);
+ *mailbox <<= 2;
+ *mailbox |= LETTER_GET(packet);
+ *mailbox <<= 2;
+ *mailbox |= MBOX_GET(packet);
+}
+
+
+static uint16_t getPacketPayload(uint32_t *packet, const uint16_t payloadOffset, const uint16_t dataOffset,
+ const uint16_t dataSize, uint8_t *data)
+{
+ uint32_t content = 0;
+ uint16_t packetIndex;
+ uint16_t payloadIndex;
+ uint16_t dataIndex;
+
+
+ /* Move bytes from inbound packet queue into the user buffer. */
+ /* Long packets contain a CRC in byte 80-81, this is removed when the buffer
+ is copied. */
+ packetIndex = payloadOffset;
+ payloadIndex = 0;
+ dataIndex = 0;
+ while(dataIndex < dataSize)
+ {
+ /* Check if a new word should be read from the inbound queue. */
+ if((packetIndex & 0x3) == 0)
+ {
+ /* Get a new word. */
+ content = packet[packetIndex>>2];
+ }
+ else
+ {
+ /* Update the current word. Remove the MSB, it has already be moved
+ to the user buffer. */
+ content <<= 8;
+ }
+
+ /* Check if the current byte is CRC. */
+ if((packetIndex != 80) && (packetIndex != 81) && (payloadIndex >= dataOffset))
+ {
+ /* Not CRC. */
+ /* Move the byte to the user buffer. */
+ data[dataIndex++] = (content >> 24);
+ }
+
+ /* Increment to the next position in the packet. */
+ packetIndex++;
+ payloadIndex++;
+ }
+
+ return dataIndex;
+}
+
+
+static uint16_t setPacketPayload(uint32_t *packet, const uint16_t payloadOffset, const uint16_t dataOffset,
+ const uint16_t dataSize, const uint8_t *data)
+{
+ uint16_t crc = 0xffffu;
+ uint32_t content = 0;
+ uint16_t packetIndex;
+ uint16_t payloadIndex;
+ uint16_t dataIndex;
+
+
+ /***************************************************
+ * Calculate the CRC for the packet header.
+ ***************************************************/
+ for(packetIndex = 0; packetIndex < payloadOffset; packetIndex+=4)
+ {
+ crc = Crc32(packet[packetIndex>>2], crc);
+ }
+
+ /***************************************************
+ * Pad the data before the actual data is written.
+ ***************************************************/
+ payloadIndex = 0;
+ while(payloadIndex < dataOffset)
+ {
+ content <<= 8;
+
+ if((packetIndex & 0x3) == 3)
+ {
+ crc = Crc32(content, crc);
+ packet[packetIndex>>2] = content;
+ }
+
+ payloadIndex++;
+ packetIndex++;
+ }
+
+ /***************************************************
+ * Write content and any embedded CRC.
+ ***************************************************/
+ dataIndex = 0;
+ while(dataIndex < dataSize)
+ {
+ content <<= 8;
+
+ /* Check if CRC or content should be entered into the packet. */
+ if(packetIndex == 80)
+ {
+ /* CRC MSB. */
+ content |= crc >> 8;
+ }
+ else if(packetIndex == 81)
+ {
+ /* CRC LSB. */
+ content |= crc & 0xff;
+ }
+ else
+ {
+ /* Data content. */
+ content |= data[dataIndex++];
+ payloadIndex++;
+ }
+
+ if((packetIndex & 0x3) == 3)
+ {
+ crc = Crc32(content, crc);
+ packet[packetIndex>>2] = content;
+ }
+
+ packetIndex++;
+ }
+
+ /***************************************************
+ * Pad the data to an even double word.
+ ***************************************************/
+ while((payloadIndex & 0x7) != 0)
+ {
+ content <<= 8;
+
+ if((packetIndex & 0x3) == 3)
+ {
+ crc = Crc32(content, crc);
+ packet[packetIndex>>2] = content;
+ }
+
+ packetIndex++;
+ payloadIndex++;
+ }
+
+ /***************************************************
+ * Write the CRC into the packet.
+ ***************************************************/
+ if((packetIndex & 0x3) == 0)
+ {
+ /* crc(15:0)|pad(15:0) */
+ content = ((uint32_t) crc) << 16;
+ }
+ else
+ {
+ /* double-wordN-LSB|crc(15:0) */
+ content &= 0x0000ffff;
+ crc = Crc16(content, crc);
+ content <<= 16;
+ content |= crc;
+ }
+ packet[packetIndex>>2] = content;
+
+ return (packetIndex>>2);
+}
+
+
+/* \note See the RapidIO standard part1 table 4-4 for details about
+ * {address, size}->{wdptr, wrsize} mapping.
+ */
+static uint16_t rdsizeGet(const uint32_t address, const uint16_t size)
+{
+ uint8_t wdptr;
+ uint8_t rdsize;
+
+
+ switch(size/8)
+ {
+ case 0:
+ /**************************************************************
+ * Sub double-word access.
+ **************************************************************/
+ /* REMARK: The same code as in wrsizeGet for sub
+ double-word... use it instead??? */
+ switch(size%8)
+ {
+ case 0:
+ /* Not supported by protocol. */
+ wdptr = 0xff;
+ rdsize = 0xff;
+ break;
+ case 1:
+ /* Reading one byte. */
+ /* Any address is allowed. */
+ wdptr = (address >> 2) & 0x1;
+ rdsize = address & 0x3;
+ break;
+ case 2:
+ /* Reading two bytes. */
+ /* Address 0, 2, 4, 6 are valid. */
+ if((address & 0x1) == 0)
+ {
+ wdptr = (address >> 2) & 0x1;
+ rdsize = (address & 0x7) | 0x4;
+ }
+ else
+ {
+ /* Not supported by protocol. */
+ wdptr = 0xff;
+ rdsize = 0xff;
+ }
+ break;
+ case 3:
+ /* Reading 3 bytes. */
+ /* Address 0 and 5 are valid. */
+ if(((address & 0x7) == 0) ||
+ ((address & 0x7) == 5))
+ {
+ wdptr = (address >> 2) & 0x1;
+ rdsize = 0x5ul;
+ }
+ else
+ {
+ /* Not supported by protocol. */
+ wdptr = 0xff;
+ rdsize = 0xff;
+ }
+ break;
+ case 4:
+ /* Reading 4 bytes. */
+ /* Address 0 and 4 are valid. */
+ if(((address & 0x7) == 0) ||
+ ((address & 0x7) == 4))
+ {
+ wdptr = (address >> 2) & 0x1;
+ rdsize = 0x8ul;
+ }
+ else
+ {
+ /* Not supported by protocol. */
+ wdptr = 0xff;
+ rdsize = 0xff;
+ }
+ break;
+ case 5:
+ /* Reading 5 bytes. */
+ /* Address 0 and 3 are valid. */
+ if(((address & 0x7) == 0) ||
+ ((address & 0x7) == 3))
+ {
+ wdptr = (address >> 1) & 0x1;
+ rdsize = 0x7ul;
+ }
+ else
+ {
+ /* Not supported by protocol. */
+ wdptr = 0xff;
+ rdsize = 0xff;
+ }
+ break;
+ case 6:
+ /* Reading 6 bytes. */
+ /* Addresses 0 and 2 are valid. */
+ if(((address & 0x7) == 0) ||
+ ((address & 0x7) == 2))
+ {
+ wdptr = (address >> 1) & 0x1;
+ rdsize = 0x9ul;
+ }
+ else
+ {
+ /* Not supported by protocol. */
+ wdptr = 0xff;
+ rdsize = 0xff;
+ }
+ break;
+ default:
+ /* Reading 7 bytes. */
+ /* Addresses 0 and 1 are valid. */
+ if(((address & 0x7) == 0) ||
+ ((address & 0x7) == 1))
+ {
+ wdptr = address & 0x1;
+ rdsize = 0xaul;
+ }
+ else
+ {
+ /* Not supported by protocol. */
+ wdptr = 0xff;
+ rdsize = 0xff;
+ }
+ break;
+ }
+ break;
+ case 1:
+ /* Reading 8 bytes. */
+ /* Only even double-word address are valid. */
+ if((address % 8) == 0)
+ {
+ wdptr = 0;
+ rdsize = 0xbul;
+ }
+ else
+ {
+ /* Not supported by protocol. */
+ wdptr = 0xff;
+ rdsize = 0xff;
+ }
+ break;
+ case 2:
+ /* Reading 16 bytes max. */
+ /* Only even double-word address are valid. */
+ if((address % 8) == 0)
+ {
+ wdptr = 1;
+ rdsize = 0xbul;
+ }
+ else
+ {
+ /* Not supported by protocol. */
+ wdptr = 0xff;
+ rdsize = 0xff;
+ }
+ break;
+ case 3:
+ /* Not supported by protocol. */
+ wdptr = 0xff;
+ rdsize = 0xff;
+ break;
+ case 4:
+ /* Reading 32 bytes max. */
+ /* Only even double-word address are valid. */
+ if((address & 0x7) == 0)
+ {
+ wdptr = 0;
+ rdsize = 0xcul;
+ }
+ else
+ {
+ /* Not supported by protocol. */
+ wdptr = 0xff;
+ rdsize = 0xff;
+ }
+ break;
+ case 5:
+ case 6:
+ case 7:
+ /* Not supported by protocol. */
+ wdptr = 0xff;
+ rdsize = 0xff;
+ break;
+ case 8:
+ /* Reading 64 bytes max. */
+ /* Only even double-word address are valid. */
+ if((address & 0x7) == 0)
+ {
+ wdptr = 1;
+ rdsize = 0xcul;
+ }
+ else
+ {
+ /* Not supported by protocol. */
+ wdptr = 0xff;
+ rdsize = 0xff;
+ }
+ break;
+ case 9:
+ case 10:
+ case 11:
+ /* Not supported by protocol. */
+ wdptr = 0xff;
+ rdsize = 0xff;
+ break;
+ case 12:
+ /* Reading 96 bytes. */
+ /* Only even double-word address are valid. */
+ if((address & 0x7) == 0)
+ {
+ wdptr = 0;
+ rdsize = 0xdul;
+ }
+ else
+ {
+ /* Not supported by protocol. */
+ wdptr = 0xff;
+ rdsize = 0xff;
+ }
+ break;
+ case 13:
+ case 14:
+ case 15:
+ /* Not supported by protocol. */
+ wdptr = 0xff;
+ rdsize = 0xff;
+ break;
+ case 16:
+ /* Reading 128 bytes max. */
+ /* Only even double-word address are valid. */
+ if((address & 0x7) == 0)
+ {
+ wdptr = 1;
+ rdsize = 0xdul;
+ }
+ else
+ {
+ /* Not supported by protocol. */
+ wdptr = 0xff;
+ rdsize = 0xff;
+ }
+ break;
+ case 17:
+ case 18:
+ case 19:
+ /* Not supported by protocol. */
+ wdptr = 0xff;
+ rdsize = 0xff;
+ break;
+ case 20:
+ /* Reading 160 bytes. */
+ /* Only even double-word address are valid. */
+ if((address & 0x7) == 0)
+ {
+ wdptr = 0;
+ rdsize = 0xeul;
+ }
+ else
+ {
+ /* Not supported by protocol. */
+ wdptr = 0xff;
+ rdsize = 0xff;
+ }
+ break;
+ case 21:
+ case 22:
+ case 23:
+ /* Not supported by protocol. */
+ wdptr = 0xff;
+ rdsize = 0xff;
+ break;
+ case 24:
+ /* Reading 192 bytes. */
+ /* Only even double-word address are valid. */
+ if((address & 0x7) == 0)
+ {
+ wdptr = 1;
+ rdsize = 0xeul;
+ }
+ else
+ {
+ /* Not supported by protocol. */
+ wdptr = 0xff;
+ rdsize = 0xff;
+ }
+ break;
+ case 25:
+ case 26:
+ case 27:
+ /* Not supported by protocol. */
+ wdptr = 0xff;
+ rdsize = 0xff;
+ break;
+ case 28:
+ /* Reading 224 bytes. */
+ /* Only even double-word address are valid. */
+ if((address & 0x7) == 0)
+ {
+ wdptr = 0;
+ rdsize = 0xful;
+ }
+ else
+ {
+ /* Not supported by protocol. */
+ wdptr = 0xff;
+ rdsize = 0xff;
+ }
+ break;
+ case 29:
+ case 30:
+ case 31:
+ /* Not supported by protocol. */
+ wdptr = 0xff;
+ rdsize = 0xff;
+ break;
+ case 32:
+ /* Reading 256 bytes max. */
+ /* Only even double-word address are valid. */
+ if((address & 0x7) == 0)
+ {
+ wdptr = 1;
+ rdsize = 0xful;
+ }
+ else
+ {
+ /* Not supported by protocol. */
+ wdptr = 0xff;
+ rdsize = 0xff;
+ }
+ break;
+ default:
+ /* Not supported by protocol. */
+ wdptr = 0xff;
+ rdsize = 0xff;
+ break;
+ }
+
+ return ((((uint16_t) rdsize) << 8) | ((uint16_t) wdptr));
+}
+
+
+void rdsizeToOffset(uint8_t rdsize, uint8_t wdptr, uint8_t *offset, uint16_t *size)
+{
+ switch(rdsize)
+ {
+ case 0:
+ case 1:
+ case 2:
+ case 3:
+ *offset = wdptr << 2;
+ *offset |= rdsize;
+ *size = 1;
+ break;
+ case 4:
+ case 6:
+ *offset = wdptr << 2;
+ *offset |= rdsize & 0x02;
+ *size = 2;
+ break;
+ case 5:
+ *offset = wdptr * 5;
+ *size = 3;
+ break;
+ case 8:
+ *offset = wdptr * 4;
+ *size = 4;
+ break;
+ case 7:
+ *offset = wdptr * 3;
+ *size = 5;
+ break;
+ case 9:
+ *offset = wdptr * 2;
+ *size = 6;
+ break;
+ case 10:
+ *offset = wdptr * 1;
+ *size = 7;
+ break;
+ case 11:
+ *offset = 0;
+ *size = 8 + 8*wdptr;
+ break;
+ case 12:
+ *offset = 0;
+ *size = 32 + 32*wdptr;
+ break;
+ case 13:
+ *offset = 0;
+ *size = 96 + 32*wdptr;
+ break;
+ case 14:
+ *offset = 0;
+ *size = 160 + 32*wdptr;
+ break;
+ case 15:
+ *offset = 0;
+ *size = 224 + 32*wdptr;
+ break;
+ }
+}
+
+
+static uint16_t wrsizeGet(const uint32_t address, const uint16_t size)
+{
+ uint8_t wdptr;
+ uint8_t wrsize;
+
+
+ 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;
+ s.data |= ((uint32_t)stype1 & (uint32_t)0x07ul) << 8;
+ s.data |= ((uint32_t)cmd & (uint32_t)0x7ul) << 5;
+ s.data |= Crc5(s.data, 0x1fu);
+
+ return s;
+}
+
+
+static uint8_t Crc5( const uint32_t data, const uint8_t crc)
+{
+ static const uint8_t crcTable[] = {
+ 0x00u, 0x15u, 0x1fu, 0x0au, 0x0bu, 0x1eu, 0x14u, 0x01u,
+ 0x16u, 0x03u, 0x09u, 0x1cu, 0x1du, 0x08u, 0x02u, 0x17u,
+ 0x19u, 0x0cu, 0x06u, 0x13u, 0x12u, 0x07u, 0x0du, 0x18u,
+ 0x0fu, 0x1au, 0x10u, 0x05u, 0x04u, 0x11u, 0x1bu, 0x0eu
+ };
+
+ uint8_t result;
+ uint8_t index;
+
+ result = crc;
+ index = (uint8_t)((data >> 19) & (uint32_t)0x1ful) ^ result;
+ result = crcTable[index];
+ index = (uint8_t)((data >> 14) & (uint32_t)0x1ful) ^ result;
+ result = crcTable[index];
+ index = (uint8_t)((data >> 9) & (uint32_t)0x1ful) ^ result;
+ result = crcTable[index];
+ index = (uint8_t)((data >> 4) & (uint32_t)0x1eul) ^ result;
+ result = crcTable[index];
+
+ return result;
+}
+
+
+static uint16_t Crc16( const uint16_t data, const uint16_t crc)
+{
+ static const uint16_t crcTable[] = {
+ 0x0000u, 0x1021u, 0x2042u, 0x3063u, 0x4084u, 0x50a5u, 0x60c6u, 0x70e7u,
+ 0x8108u, 0x9129u, 0xa14au, 0xb16bu, 0xc18cu, 0xd1adu, 0xe1ceu, 0xf1efu,
+ 0x1231u, 0x0210u, 0x3273u, 0x2252u, 0x52b5u, 0x4294u, 0x72f7u, 0x62d6u,
+ 0x9339u, 0x8318u, 0xb37bu, 0xa35au, 0xd3bdu, 0xc39cu, 0xf3ffu, 0xe3deu,
+ 0x2462u, 0x3443u, 0x0420u, 0x1401u, 0x64e6u, 0x74c7u, 0x44a4u, 0x5485u,
+ 0xa56au, 0xb54bu, 0x8528u, 0x9509u, 0xe5eeu, 0xf5cfu, 0xc5acu, 0xd58du,
+ 0x3653u, 0x2672u, 0x1611u, 0x0630u, 0x76d7u, 0x66f6u, 0x5695u, 0x46b4u,
+ 0xb75bu, 0xa77au, 0x9719u, 0x8738u, 0xf7dfu, 0xe7feu, 0xd79du, 0xc7bcu,
+ 0x48c4u, 0x58e5u, 0x6886u, 0x78a7u, 0x0840u, 0x1861u, 0x2802u, 0x3823u,
+ 0xc9ccu, 0xd9edu, 0xe98eu, 0xf9afu, 0x8948u, 0x9969u, 0xa90au, 0xb92bu,
+ 0x5af5u, 0x4ad4u, 0x7ab7u, 0x6a96u, 0x1a71u, 0x0a50u, 0x3a33u, 0x2a12u,
+ 0xdbfdu, 0xcbdcu, 0xfbbfu, 0xeb9eu, 0x9b79u, 0x8b58u, 0xbb3bu, 0xab1au,
+ 0x6ca6u, 0x7c87u, 0x4ce4u, 0x5cc5u, 0x2c22u, 0x3c03u, 0x0c60u, 0x1c41u,
+ 0xedaeu, 0xfd8fu, 0xcdecu, 0xddcdu, 0xad2au, 0xbd0bu, 0x8d68u, 0x9d49u,
+ 0x7e97u, 0x6eb6u, 0x5ed5u, 0x4ef4u, 0x3e13u, 0x2e32u, 0x1e51u, 0x0e70u,
+ 0xff9fu, 0xefbeu, 0xdfddu, 0xcffcu, 0xbf1bu, 0xaf3au, 0x9f59u, 0x8f78u,
+ 0x9188u, 0x81a9u, 0xb1cau, 0xa1ebu, 0xd10cu, 0xc12du, 0xf14eu, 0xe16fu,
+ 0x1080u, 0x00a1u, 0x30c2u, 0x20e3u, 0x5004u, 0x4025u, 0x7046u, 0x6067u,
+ 0x83b9u, 0x9398u, 0xa3fbu, 0xb3dau, 0xc33du, 0xd31cu, 0xe37fu, 0xf35eu,
+ 0x02b1u, 0x1290u, 0x22f3u, 0x32d2u, 0x4235u, 0x5214u, 0x6277u, 0x7256u,
+ 0xb5eau, 0xa5cbu, 0x95a8u, 0x8589u, 0xf56eu, 0xe54fu, 0xd52cu, 0xc50du,
+ 0x34e2u, 0x24c3u, 0x14a0u, 0x0481u, 0x7466u, 0x6447u, 0x5424u, 0x4405u,
+ 0xa7dbu, 0xb7fau, 0x8799u, 0x97b8u, 0xe75fu, 0xf77eu, 0xc71du, 0xd73cu,
+ 0x26d3u, 0x36f2u, 0x0691u, 0x16b0u, 0x6657u, 0x7676u, 0x4615u, 0x5634u,
+ 0xd94cu, 0xc96du, 0xf90eu, 0xe92fu, 0x99c8u, 0x89e9u, 0xb98au, 0xa9abu,
+ 0x5844u, 0x4865u, 0x7806u, 0x6827u, 0x18c0u, 0x08e1u, 0x3882u, 0x28a3u,
+ 0xcb7du, 0xdb5cu, 0xeb3fu, 0xfb1eu, 0x8bf9u, 0x9bd8u, 0xabbbu, 0xbb9au,
+ 0x4a75u, 0x5a54u, 0x6a37u, 0x7a16u, 0x0af1u, 0x1ad0u, 0x2ab3u, 0x3a92u,
+ 0xfd2eu, 0xed0fu, 0xdd6cu, 0xcd4du, 0xbdaau, 0xad8bu, 0x9de8u, 0x8dc9u,
+ 0x7c26u, 0x6c07u, 0x5c64u, 0x4c45u, 0x3ca2u, 0x2c83u, 0x1ce0u, 0x0cc1u,
+ 0xef1fu, 0xff3eu, 0xcf5du, 0xdf7cu, 0xaf9bu, 0xbfbau, 0x8fd9u, 0x9ff8u,
+ 0x6e17u, 0x7e36u, 0x4e55u, 0x5e74u, 0x2e93u, 0x3eb2u, 0x0ed1u, 0x1ef0u
+ };
+
+ uint16_t result;
+ uint8_t index;
+
+ result = crc;
+ index = (uint8_t) ((data >> 8) ^ (result >> 8));
+ result = (uint16_t) (crcTable[index] ^ (uint16_t)(result << 8));
+ index = (uint8_t) ((data) ^ (result >> 8));
+ result = (uint16_t) (crcTable[index] ^ (uint16_t)(result << 8));
+
+ return result;
+}
+
+
+static uint16_t Crc32( const uint32_t data, uint16_t crc)
+{
+ crc = Crc16((uint16_t) (data >> 16), crc);
+ crc = Crc16((uint16_t) (data), crc);
+ return crc;
+}
+
+
+
+
+
+static Queue_t QueueCreate( const uint8_t size, uint32_t *buffer)
+{
+ Queue_t q;
+
+ q.size = size;
+ q.available = size;
+ q.windowSize = 0u;
+ q.windowIndex = 0u;
+ q.frontIndex = 0u;
+ q.backIndex = 0u;
+ q.buffer_p = buffer;
+
+ return q;
+}
+
+
+static uint8_t QueueAvailable( const Queue_t q)
+{
+ return q.available;
+}
+
+
+static bool_t QueueEmpty( const Queue_t q)
+{
+ return (bool_t) (q.available == q.size);
+}
+
+
+static uint8_t QueueLength( const Queue_t q)
+{
+ return q.size - q.available;
+}
+
+
+static Queue_t QueueEnqueue( Queue_t q)
+{
+ q.backIndex++;
+ if(q.backIndex == q.size)
+ {
+ q.backIndex = 0;
+ }
+ q.available--;
+ return q;
+}
+
+
+static Queue_t QueueDequeue( Queue_t q)
+{
+ q.frontIndex++;
+ if(q.frontIndex == q.size)
+ {
+ q.frontIndex = 0;
+ }
+ q.available++;
+ if(q.windowSize == 0)
+ {
+ q.windowIndex = q.frontIndex;
+ }
+ else
+ {
+ q.windowSize--;
+ }
+ return q;
+}
+
+
+static bool_t QueueWindowEmpty( const Queue_t q)
+{
+ return (bool_t) ((q.available + q.windowSize) == q.size);
+}
+
+
+static Queue_t QueueWindowReset(Queue_t q)
+{
+ q.windowIndex = q.frontIndex;
+ q.windowSize = 0;
+ return q;
+}
+
+
+static Queue_t QueueWindowNext(Queue_t q)
+{
+ q.windowIndex++;
+ if(q.windowIndex == q.size)
+ {
+ q.windowIndex = 0;
+ }
+ q.windowSize++;
+ return q;
+}
+
+
+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)
+{
+ (q.buffer_p+(RIO_BUFFER_SIZE*q.backIndex))[index+1ul] = content;
+}
+
+
+static uint32_t QueueGetFrontSize( Queue_t q)
+{
+ return (q.buffer_p+(RIO_BUFFER_SIZE*q.windowIndex))[0];
+}
+
+
+static uint32_t QueueGetFrontContent( const Queue_t q, const uint32_t index)
+{
+ return (q.buffer_p+(RIO_BUFFER_SIZE*q.windowIndex))[index+1ul];
+}
+
+
+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)
+{
+ return (q.buffer_p+(RIO_BUFFER_SIZE*q.backIndex))[0];
+}
+
+
+static uint32_t *QueueGetBackBuffer( const Queue_t q )
+{
+ return &((q.buffer_p+(RIO_BUFFER_SIZE*q.backIndex))[1]);
+}
+
+
+#ifdef MODULE_TEST
+#include
+#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)
+{
+ 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);
+ }
+}
+
+
+
+uint32_t testConfigWriteData;
+
+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 = Crc32(content, 0xffffu);
+ doorbell[0] = (((uint32_t) ackId) << 27) | content;
+
+ /* sourceId(15:0)|rsrv(7:0)|srcTID(7:0) */
+ content = ((uint32_t) srcId) << 16;
+ content |= (uint32_t) tid;
+ crc = Crc32(content, crc);
+ doorbell[1] = content;
+
+ /* infoMSB(7:0)|infoLSB(7:0)|crc(15:0) */
+ content = ((uint32_t) info) << 16;
+ crc = Crc16(info, crc);
+ content |= ((uint32_t) crc);
+ doorbell[2] = content;
+
+ return 3;
+
+}
+
+uint32_t testConfigRead(RioStack_t *stack, uint32_t offset)
+{
+ 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)
+{
+ 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;
+}
+#endif
+
+/*************************** end of file **************************************/
trunk/sw/stack/riostack.c
Property changes :
Added: svn:executable
## -0,0 +1 ##
+*
\ No newline at end of property
Index: trunk/sw/stack/rioconfig.h
===================================================================
--- trunk/sw/stack/rioconfig.h (nonexistent)
+++ trunk/sw/stack/rioconfig.h (revision 20)
@@ -0,0 +1,95 @@
+/*******************************************************************************
+ *
+ * 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 implementation dependent information needed to build
+ * the riostack. Replace declarations and definitions in this file to customize
+ * for your own compiler environment.
+ *
+ * To Do:
+ * -
+ *
+ * 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
+#define __RIO_CONFIG
+
+/*******************************************************************************
+* Includes
+*******************************************************************************/
+
+#include
+#include
+
+/*******************************************************************************
+* Global typedefs
+*******************************************************************************/
+
+#ifndef ASSERT
+#ifdef MODULE_TEST
+#include
+#define ASSERT(c, s) (c)?:fprintf(stderr, s)
+#endif
+#endif
+
+#ifndef ASSERT0
+#ifdef MODULE_TEST
+#include
+#define ASSERT0(s) fprintf(stderr, s)
+#endif
+#endif
+
+#ifndef DEBUG_OUT
+#define DEBUG_OUT(...)
+#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
+*******************************************************************************/
+
+/*******************************************************************************
+* Global function prototypes
+*******************************************************************************/
+
+#endif // __RIO_CONFIG
+
+/*************************** end of file **************************************/
trunk/sw/stack/rioconfig.h
Property changes :
Added: svn:executable
## -0,0 +1 ##
+*
\ No newline at end of property
Index: trunk/sw/stack/riostack.h
===================================================================
--- trunk/sw/stack/riostack.h (nonexistent)
+++ trunk/sw/stack/riostack.h (revision 20)
@@ -0,0 +1,1736 @@
+/*******************************************************************************
+ *
+ * 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 function prototypes and types that are needed to be
+ * able to use the riostack.c module.
+ *
+ * To Do:
+ * -
+ *
+ * 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
+ *
+ *******************************************************************************/
+
+/**
+ * \file riostack.h
+ */
+
+#ifndef _RIOSTACK_H
+#define _RIOSTACK_H
+
+/*******************************************************************************
+ * Includes
+ *******************************************************************************/
+
+#include "rioconfig.h"
+
+
+/*******************************************************************************
+ * 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)
+
+/* 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;
+
+
+/*
+ * RapidIO symbol definition.
+ * Idle symbol: Sent when nothing else to send. Does not use the data field.
+ * Control symbol: Sent when starting, ending and acknowleding a packet. Data
+ * is right aligned, (Unused, C0, C1, C2) where C0 is transmitted/received first.
+ * Data symbol: Sent to transfer packets. Uses the full data field, (D0, D1,
+ * D2, D3) where D0 is transmitted/received first.
+ * Error symbols are created when a symbols could not be created and the stack
+ * should know about it.
+ */
+typedef struct
+{
+ RioSymbolType type;
+ uint32_t data;
+} RioSymbol;
+
+
+/* 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;
+
+
+/* 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;
+
+
+/* Queue definition. */
+typedef struct
+{
+ uint8_t size;
+ uint8_t available;
+ uint8_t windowSize;
+ uint8_t windowIndex;
+ uint8_t frontIndex;
+ uint8_t backIndex;
+ 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
+{
+ /* Receiver variables. */
+ RioReceiverState rxState;
+ uint8_t rxCounter;
+ uint16_t rxCrc;
+ uint8_t rxStatusReceived;
+ uint8_t rxAckId;
+ uint8_t rxAckIdAcked;
+ uint8_t rxErrorCause;
+ Queue_t rxQueue;
+
+ /* Transmitter variables. */
+ RioTransmitterState txState;
+ uint8_t txCounter;
+ uint16_t txStatusCounter;
+ uint8_t txFrameState;
+ uint32_t txFrameTimeout[32];
+ uint8_t txAckId;
+ uint8_t txAckIdWindow;
+ uint8_t txBufferStatus;
+ Queue_t txQueue;
+
+ /* Common protocol stack variables. */
+ 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;
+
+ /** The number of retried received packets.
+ This will happen if the receiver does not have resources available when an inbound packet is received. */
+ uint32_t statusInboundPacketRetry;
+
+ /** The number of received erronous control symbols.
+ This may happen if the inbound link has a high bit-error-rate. */
+ uint32_t statusInboundErrorControlCrc;
+
+ /** The number of received packets with an unexpected ackId.
+ This may happen if the inbound link has a high bit-error-rate. */
+ uint32_t statusInboundErrorPacketAckId;
+
+ /** The number of received packets with a checksum error.
+ This may happen if the inbound link has a high bit-error-rate. */
+ uint32_t statusInboundErrorPacketCrc;
+
+ /** The number of received symbols that contains an illegals character.
+ This may happen if the inbound link has a high bit-error-rate or if characters are missing in the
+ inbound character stream. */
+ uint32_t statusInboundErrorIllegalCharacter;
+
+ /** The number of general errors encountered at the receiver that does not fit into the other categories.
+ This happens if too short or too long packets are received. */
+ uint32_t statusInboundErrorGeneral;
+
+ /** The number of received packets that were discarded since they were unsupported by the stack.
+ This will happen if an inbound packet contains information that cannot be accessed using the function API
+ of the stack. */
+ uint32_t statusInboundErrorPacketUnsupported;
+
+ /** The number of successfully transmitted packets. */
+ uint32_t statusOutboundPacketComplete;
+
+ /** 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. */
+ uint32_t statusOutboundPacketRetry;
+
+ /** The number of outbound packets that has had its retransmission timer expired.
+ This happens if the latency of the system is too high or if a packet is corrupted due to a high
+ bit-error-rate on the outbound link. */
+ uint32_t statusOutboundErrorTimeout;
+
+ /** The number of packet-accepted that was received that contained an unexpected ackId.
+ This happens if the transmitter and the link-partner is out of synchronization, probably due
+ to a software error. */
+ uint32_t statusOutboundErrorPacketAccepted;
+
+ /** The number of packet-retry that was received that contained an unexpected ackId.
+ This happens if the transmitter and the link-partner is out of synchronization, probably due to
+ a software error. */
+ uint32_t statusOutboundErrorPacketRetry;
+
+ /** The number of received link-requests.
+ This happens if the link-partner transmitter has found an error and need to resynchronize itself
+ to the receiver. */
+ uint32_t statusPartnerLinkRequest;
+
+ /** The number of received erronous control symbols at the link-partner receiver.
+ This may happen if the outbound link has a high bit-error-rate. */
+ uint32_t statusPartnerErrorControlCrc;
+
+ /** The number of received packets with an unexpected ackId at the link-partner receiver.
+ This may happen if the outbound link has a high bit-error-rate. */
+ uint32_t statusPartnerErrorPacketAckId;
+
+ /** The number of received packets with a checksum error at the link-partner receiver.
+ This may happen if the outbound link has a high bit-error-rate. */
+ uint32_t statusPartnerErrorPacketCrc;
+
+ /** The number of received symbols that contains an illegals character at the link-parter receiver.
+ This may happen if the outbound link has a high bit-error-rate or if characters are missing in the
+ outbound character stream. */
+ uint32_t statusPartnerErrorIllegalCharacter;
+
+ /** The number of general errors encountered at the receiver that does not fit into the other categories.
+ This happens depending on the link-partner implementation. */
+ uint32_t statusPartnerErrorGeneral;
+
+ /* Callback structure. */
+ const RioStackObserver_t *observer;
+
+ /* Private user data. */
+ const void *private;
+} RioStack_t;
+
+
+/*******************************************************************************
+ * Global function prototypes
+ *******************************************************************************/
+
+/**
+ * \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.
+ * \param[in] rxPacketBuffer Pointer to buffer to store inbound packets in.
+ * \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
+ * 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.
+ *
+ * The rxPacket/txPacket arguments are word buffers that are used internally to store the
+ * inbound and outbound packet queues.
+ *
+ * The config argument constants are used as identification when maintenance packets
+ * are received and replied to. They should be set to make the device where the stack
+ * is used easily identifiable on the net.
+ *
+ * \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 );
+
+/*******************************************************************************************
+ * Stack status functions.
+ * Note that status counters are access directly in the stack-structure.
+ *******************************************************************************************/
+
+/**
+ * \brief Get the status of the link.
+ *
+ * \param[in] stack The stack to operate on.
+ * \return Returns the status of the link.
+ *
+ * This function indicates if the link is up and ready to relay packets.
+ */
+RioStatusType RIO_getStatus( RioStack_t *stack );
+
+/**
+ * \brief Get the number of pending outbound packets.
+ *
+ * \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.
+ */
+uint8_t RIO_outboundQueueLength( RioStack_t *stack );
+
+/**
+ * \brief Get the number of pending inbound packets.
+ *
+ * \param[in] stack The stack to operate on.
+ * \return Returns the number of pending inbound packets.
+ *
+ * This function checks the inbound queue and returns the number of packets
+ * that has been received but not read by the user yet.
+ */
+uint8_t RIO_inboundQueueLength( RioStack_t *stack );
+
+/*******************************************************************************************
+ * Packet reception functions.
+ *******************************************************************************************/
+
+/**
+ * \brief Check for new events.
+ *
+ * \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.
+ *
+ * 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.
+ */
+RioEventType RIO_eventPoll( RioStack_t *stack );
+
+/**
+ * \brief Remove a packet from the stack.
+ * \param[in] stack The stack to operate on.
+ *
+ * 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.
+ *
+ * Return if there are buffers available to send a packet of a specified size.
+ *
+ * \note If the response is negative, it might be positive later if outbound
+ * packets has been sent and new buffers becomes available.
+ *
+ * \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
+ * 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.
+ */
+#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
+
+/**
+ * \brief Send a maintenance read 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 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.
+ */
+#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
+
+/**
+ * \brief Read a received maintenance read 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 in the response.
+ * \param[out] hopCount The hop_count set in the read response.
+ * \param[out] data The data in the response.
+ *
+ * This function reads a received maintanance read response packet.
+ */
+#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
+
+/*******************************************************************************************
+ * Logical I/O MAINTENANCE-WRITE functions.
+ *******************************************************************************************/
+
+/**
+ * \brief Send a maintenance write 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 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.
+ *
+ * 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.
+ */
+#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
+
+/**
+ * \brief Read a received maintenance write request.
+ *
+ * \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.
+ *
+ * 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.
+ */
+#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
+
+/**
+ * \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)
+ *******************************************************************************************/
+
+/**
+ * \brief Set a port current time.
+ *
+ * \param[in] stack The stack to operate on.
+ * \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 allow for the stack to handle timeouts.
+ */
+void RIO_portSetTime( RioStack_t *stack, const uint32_t time);
+
+/**
+ * \brief Set a port timeout limit.
+ *
+ * \param[in] stack The stack to operate on.
+ * \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().
+ *
+ * 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);
+
+/**
+ * \brief Set a ports status.
+ *
+ * \param[in] stack The stack to operate on.
+ * \param[in] initialized The state of the port.
+ *
+ * If set to non-zero, the symbol encoder/decoder indicates to the stack that
+ * it is successfully encoding/decoding symbol, i.e. synchronized to the link.
+ *
+ * This function indicates to the stack if the port that are encoding/decoding
+ * symbols are ready to accept other symbols than idle-symbols. If the
+ * 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 );
+
+/**
+ * \brief Add a new symbol to the RapidIO stack.
+ *
+ * \param[in] stack The stack to operate on.
+ * \param[in] s A symbol received from a port.
+ *
+ * This function is used to insert new data, read from a port, into the stack. The
+ * symbols will be concatenated to form packets that can be accessed using other
+ * functions.
+ */
+void RIO_portAddSymbol( RioStack_t *stack, const RioSymbol s );
+
+/**
+ * \brief Get the next symbol to transmit on a port.
+ *
+ * \param[in] stack The stack to operate on.
+ * \return A symbol that should be sent on a port.
+ *
+ * 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 );
+
+
+/*******************************************************************************************
+ * 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 */
+
+/*************************** end of file **************************************/
trunk/sw/stack/riostack.h
Property changes :
Added: svn:executable
## -0,0 +1 ##
+*
\ No newline at end of property
Index: trunk/sw/codec/riocodecuart.c
===================================================================
--- trunk/sw/codec/riocodecuart.c (nonexistent)
+++ trunk/sw/codec/riocodecuart.c (revision 20)
@@ -0,0 +1,548 @@
+/*******************************************************************************
+ *
+ * RapidIO IP Library Core
+ *
+ * This file is part of the RapidIO IP library project
+ * http://www.opencores.org/cores/rio/
+ *
+ * Description:
+ * This file contains code that can serialize and deserialize rio symbols onto
+ * and from an 8-bit UART transmission channel.
+ *
+ * To Do:
+ * -
+ *
+ * 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
+ *
+ *******************************************************************************/
+
+#include
+
+typedef enum
+{
+ RIO_SYMBOL_TYPE_IDLE, RIO_SYMBOL_TYPE_CONTROL,
+ RIO_SYMBOL_TYPE_DATA, RIO_SYMBOL_TYPE_ERROR
+} RioSymbolType;
+
+typedef struct
+{
+ RioSymbolType type;
+ uint32_t data;
+} RioSymbol;
+
+typedef struct
+{
+
+} RioStack_t;
+
+void RIO_portAddSymbol( RioStack_t *stack, const RioSymbol s );
+RioSymbol RIO_portGetSymbol( RioStack_t *stack );
+
+
+void receiveByte(RioStack_t *stack, uint8_t incoming)
+{
+ static RioSymbol rxSymbol;
+ static uint8_t flagFound = 0;
+ static uint8_t symbolCounter = 0;
+
+
+ if(incoming != 0x7e)
+ {
+ if(incoming != 0x7d)
+ {
+ if(flagFound)
+ {
+ incoming ^= 0x20;
+ }
+ else
+ {
+ /* Dont do anything. */
+ }
+
+ switch(symbolCounter)
+ {
+ case 0:
+ rxSymbol.type = RIO_SYMBOL_TYPE_ERROR;
+ rxSymbol.data = incoming;
+ symbolCounter++;
+ break;
+ case 1:
+ rxSymbol.type = RIO_SYMBOL_TYPE_ERROR;
+ rxSymbol.data <<= 8;
+ rxSymbol.data |= incoming;
+ symbolCounter++;
+ break;
+ case 2:
+ rxSymbol.type = RIO_SYMBOL_TYPE_CONTROL;
+ rxSymbol.data <<= 8;
+ rxSymbol.data |= incoming;
+ symbolCounter++;
+ break;
+ case 3:
+ rxSymbol.type = RIO_SYMBOL_TYPE_DATA;
+ rxSymbol.data <<= 8;
+ rxSymbol.data |= incoming;
+
+ RIO_portAddSymbol(stack, rxSymbol);
+
+ rxSymbol.data = 0x00000000;
+ symbolCounter = 0;
+ break;
+ }
+
+ flagFound = 0;
+ }
+ else
+ {
+ flagFound = 1;
+ }
+ }
+ else
+ {
+ if(symbolCounter == 0)
+ {
+ rxSymbol.type = RIO_SYMBOL_TYPE_IDLE;
+ RIO_portAddSymbol(stack, rxSymbol);
+ }
+ else
+ {
+ RIO_portAddSymbol(stack, rxSymbol);
+ }
+
+ symbolCounter = 0;
+ }
+}
+
+uint8_t transmitByte(RioStack_t *stack)
+{
+ uint8_t returnValue;
+ static uint8_t symbolCounter = 3;
+ static uint8_t stuffing = 0;
+ static RioSymbol txSymbol;
+ uint8_t outbound;
+
+
+ /* Check if the previous symbol has been sent. */
+ if((symbolCounter == 3) && (stuffing == 0))
+ {
+ /* Symbol sent. */
+
+ /* Get a new symbol. */
+ txSymbol = RIO_portGetSymbol(stack);
+ if(txSymbol.type == RIO_SYMBOL_TYPE_CONTROL)
+ {
+ txSymbol.data <<= 8;
+ }
+ }
+ else
+ {
+ /* Symbol not sent. */
+ /* Continue to send the old symbol. */
+ }
+
+ /* Check if a flag should be sent. */
+ if ((txSymbol.type == RIO_SYMBOL_TYPE_IDLE) ||
+ ((stuffing == 0) && (symbolCounter == 0) && (txSymbol.type == RIO_SYMBOL_TYPE_CONTROL)))
+ {
+ /* A flag needs to be sent. */
+ /* An idle symbol should be sent as a flag and a control symbol should always be
+ terminated by a flag. */
+ returnValue = 0x7e;
+ symbolCounter = 3;
+ stuffing = 0;
+ }
+ else
+ {
+ /* A flag does not need to be sent. */
+
+ /* Get the current byte in the symbol. */
+ outbound = txSymbol.data >> (8*symbolCounter);
+
+ /* Check if stuffing is active. */
+ if(!stuffing)
+ {
+ /* No stuffing active. */
+
+ /* Check if the current byte needs to be stuffed. */
+ if((outbound != 0x7e) && (outbound != 0x7d))
+ {
+ /* The current byte does not need to be stuffed. */
+ returnValue = outbound;
+ symbolCounter = (symbolCounter - 1) & 0x3;
+ }
+ else
+ {
+ /* The current byte needs to be stuffed. */
+ returnValue = 0x7d;
+ stuffing = 1;
+ }
+ }
+ else
+ {
+ /* Stuffing is active. */
+ /* An escape sequence has been sent, transmit the original data but change it to not being a flag. */
+ returnValue = outbound ^ 0x20;
+ stuffing = 0;
+ symbolCounter = (symbolCounter - 1) & 0x3;
+ }
+ }
+
+ return returnValue;
+}
+
+
+
+/*******************************************************************************
+ * Module test code.
+ *******************************************************************************/
+
+#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); \
+ }
+static RioSymbol txSymbol;
+static uint8_t txNewSymbol;
+static RioSymbol rxSymbol;
+static uint8_t rxNewSymbol;
+void RIO_portAddSymbol( RioStack_t *stack, const RioSymbol s )
+{
+ rxNewSymbol = 1;
+ rxSymbol = s;
+}
+RioSymbol RIO_portGetSymbol( RioStack_t *stack )
+{
+ if(txNewSymbol)
+ {
+ txNewSymbol = 0;
+ return txSymbol;
+ }
+ else
+ {
+ RioSymbol s;
+ s.type = RIO_SYMBOL_TYPE_ERROR;
+ return s;
+ }
+}
+int main(int argc, char *argv[])
+{
+ RioStack_t *stack;
+
+ /***************************************************************
+ * Test receiver.
+ ***************************************************************/
+
+ /* Receive a flag. */
+ rxNewSymbol = 0;
+ receiveByte(stack, 0x7e);
+ TESTEXPR(rxNewSymbol, 1);
+ TESTEXPR(rxSymbol.type, RIO_SYMBOL_TYPE_IDLE);
+
+ /* Receive not a flag followed by flag. */
+ rxNewSymbol = 0;
+ receiveByte(stack, 0xaa);
+ receiveByte(stack, 0x7e);
+ TESTEXPR(rxNewSymbol, 1);
+ TESTEXPR(rxSymbol.type, RIO_SYMBOL_TYPE_ERROR);
+
+ /* Receive not a flag twice followed by flag. */
+ rxNewSymbol = 0;
+ receiveByte(stack, 0xaa);
+ receiveByte(stack, 0x55);
+ receiveByte(stack, 0x7e);
+ TESTEXPR(rxNewSymbol, 1);
+ TESTEXPR(rxSymbol.type, RIO_SYMBOL_TYPE_ERROR);
+
+ /* Receive a control symbol followed by flag. */
+ rxNewSymbol = 0;
+ receiveByte(stack, 0x11);
+ receiveByte(stack, 0x22);
+ receiveByte(stack, 0x33);
+ receiveByte(stack, 0x7e);
+ TESTEXPR(rxNewSymbol, 1);
+ TESTEXPR(rxSymbol.type, RIO_SYMBOL_TYPE_CONTROL);
+ TESTEXPR(rxSymbol.data, 0x00112233);
+
+ /* Receive a data symbol. */
+ rxNewSymbol = 0;
+ receiveByte(stack, 0x44);
+ receiveByte(stack, 0x55);
+ receiveByte(stack, 0x66);
+ receiveByte(stack, 0x77);
+ TESTEXPR(rxNewSymbol, 1);
+ TESTEXPR(rxSymbol.type, RIO_SYMBOL_TYPE_DATA);
+ TESTEXPR(rxSymbol.data, 0x44556677);
+
+ /* Receive a back-to-back data symbol. */
+ rxNewSymbol = 0;
+ receiveByte(stack, 0x88);
+ receiveByte(stack, 0x99);
+ receiveByte(stack, 0xaa);
+ receiveByte(stack, 0xbb);
+ TESTEXPR(rxNewSymbol, 1);
+ TESTEXPR(rxSymbol.type, RIO_SYMBOL_TYPE_DATA);
+ TESTEXPR(rxSymbol.data, 0x8899aabb);
+
+ /* Receive a back-to-back control symbol. */
+ rxNewSymbol = 0;
+ receiveByte(stack, 0xcc);
+ receiveByte(stack, 0xdd);
+ receiveByte(stack, 0xee);
+ receiveByte(stack, 0x7e);
+ TESTEXPR(rxNewSymbol, 1);
+ TESTEXPR(rxSymbol.type, RIO_SYMBOL_TYPE_CONTROL);
+ TESTEXPR(rxSymbol.data, 0x00ccddee);
+
+ /* Test control symbol with one stuffed byte. */
+ rxNewSymbol = 0;
+ receiveByte(stack, 0x7d);
+ receiveByte(stack, 0x5e);
+ receiveByte(stack, 0xff);
+ receiveByte(stack, 0x01);
+ receiveByte(stack, 0x7e);
+ TESTEXPR(rxNewSymbol, 1);
+ TESTEXPR(rxSymbol.type, RIO_SYMBOL_TYPE_CONTROL);
+ TESTEXPR(rxSymbol.data, 0x007eff01);
+
+ /* Test control symbol with two stuffed bytes. */
+ rxNewSymbol = 0;
+ receiveByte(stack, 0x7d);
+ receiveByte(stack, 0x5e);
+ receiveByte(stack, 0xff);
+ receiveByte(stack, 0x7d);
+ receiveByte(stack, 0x5d);
+ receiveByte(stack, 0x7e);
+ TESTEXPR(rxNewSymbol, 1);
+ TESTEXPR(rxSymbol.type, RIO_SYMBOL_TYPE_CONTROL);
+ TESTEXPR(rxSymbol.data, 0x007eff7d);
+
+ /* Test control symbol with three stuffed bytes. */
+ rxNewSymbol = 0;
+ receiveByte(stack, 0x7d);
+ receiveByte(stack, 0x5d);
+ receiveByte(stack, 0x7d);
+ receiveByte(stack, 0x5e);
+ receiveByte(stack, 0x7d);
+ receiveByte(stack, 0x5d);
+ receiveByte(stack, 0x7e);
+ TESTEXPR(rxNewSymbol, 1);
+ TESTEXPR(rxSymbol.type, RIO_SYMBOL_TYPE_CONTROL);
+ TESTEXPR(rxSymbol.data, 0x007d7e7d);
+
+ /* Test data symbol with one stuffed byte. */
+ rxNewSymbol = 0;
+ receiveByte(stack, 0x7d);
+ receiveByte(stack, 0x5e);
+ receiveByte(stack, 0x00);
+ receiveByte(stack, 0x01);
+ receiveByte(stack, 0x02);
+ TESTEXPR(rxNewSymbol, 1);
+ TESTEXPR(rxSymbol.type, RIO_SYMBOL_TYPE_DATA);
+ TESTEXPR(rxSymbol.data, 0x7e000102);
+
+ /* Test data symbol with two stuffed bytes. */
+ rxNewSymbol = 0;
+ receiveByte(stack, 0x7d);
+ receiveByte(stack, 0x5e);
+ receiveByte(stack, 0x7d);
+ receiveByte(stack, 0x5d);
+ receiveByte(stack, 0x03);
+ receiveByte(stack, 0x04);
+ TESTEXPR(rxNewSymbol, 1);
+ TESTEXPR(rxSymbol.type, RIO_SYMBOL_TYPE_DATA);
+ TESTEXPR(rxSymbol.data, 0x7e7d0304);
+
+ /* Test data symbol with three stuffed bytes. */
+ rxNewSymbol = 0;
+ receiveByte(stack, 0x7d);
+ receiveByte(stack, 0x5e);
+ receiveByte(stack, 0x7d);
+ receiveByte(stack, 0x5d);
+ receiveByte(stack, 0x7d);
+ receiveByte(stack, 0x5e);
+ receiveByte(stack, 0x05);
+ TESTEXPR(rxNewSymbol, 1);
+ TESTEXPR(rxSymbol.type, RIO_SYMBOL_TYPE_DATA);
+ TESTEXPR(rxSymbol.data, 0x7e7d7e05);
+
+ /* Test data symbol with four stuffed bytes. */
+ rxNewSymbol = 0;
+ receiveByte(stack, 0x7d);
+ receiveByte(stack, 0x5e);
+ receiveByte(stack, 0x7d);
+ receiveByte(stack, 0x5d);
+ receiveByte(stack, 0x7d);
+ receiveByte(stack, 0x5e);
+ receiveByte(stack, 0x7d);
+ receiveByte(stack, 0x5d);
+ TESTEXPR(rxNewSymbol, 1);
+ TESTEXPR(rxSymbol.type, RIO_SYMBOL_TYPE_DATA);
+ TESTEXPR(rxSymbol.data, 0x7e7d7e7d);
+
+ /***************************************************************
+ * Test transmitter.
+ ***************************************************************/
+
+ /* Test transmission of idle symbol. */
+ txNewSymbol = 1;
+ txSymbol.type = RIO_SYMBOL_TYPE_IDLE;
+ TESTEXPR(transmitByte(stack), 0x7e);
+
+ /* Test transmission of control symbol. */
+ txNewSymbol = 1;
+ txSymbol.type = RIO_SYMBOL_TYPE_CONTROL;
+ txSymbol.data = 0x00112233;
+ TESTEXPR(transmitByte(stack), 0x11);
+ TESTEXPR(transmitByte(stack), 0x22);
+ TESTEXPR(transmitByte(stack), 0x33);
+ TESTEXPR(transmitByte(stack), 0x7e);
+
+ /* Test transmission of data symbol. */
+ txNewSymbol = 1;
+ txSymbol.type = RIO_SYMBOL_TYPE_DATA;
+ txSymbol.data = 0x44556677;
+ TESTEXPR(transmitByte(stack), 0x44);
+ TESTEXPR(transmitByte(stack), 0x55);
+ TESTEXPR(transmitByte(stack), 0x66);
+ TESTEXPR(transmitByte(stack), 0x77);
+
+ /* Test transmission of back-to-back data symbol. */
+ txNewSymbol = 1;
+ txSymbol.type = RIO_SYMBOL_TYPE_DATA;
+ txSymbol.data = 0x8899aabb;
+ TESTEXPR(transmitByte(stack), 0x88);
+ TESTEXPR(transmitByte(stack), 0x99);
+ TESTEXPR(transmitByte(stack), 0xaa);
+ TESTEXPR(transmitByte(stack), 0xbb);
+
+ /* Test transmission of back-to-back control symbol. */
+ txNewSymbol = 1;
+ txSymbol.type = RIO_SYMBOL_TYPE_CONTROL;
+ txSymbol.data = 0xffccddee;
+ TESTEXPR(transmitByte(stack), 0xcc);
+ TESTEXPR(transmitByte(stack), 0xdd);
+ TESTEXPR(transmitByte(stack), 0xee);
+ TESTEXPR(transmitByte(stack), 0x7e);
+
+ /* Test transmission of back-to-back control symbol. */
+ txNewSymbol = 1;
+ txSymbol.type = RIO_SYMBOL_TYPE_CONTROL;
+ txSymbol.data = 0xff010203;
+ TESTEXPR(transmitByte(stack), 0x01);
+ TESTEXPR(transmitByte(stack), 0x02);
+ TESTEXPR(transmitByte(stack), 0x03);
+ TESTEXPR(transmitByte(stack), 0x7e);
+
+ /* Test transmission of control symbol with one stuffed byte. */
+ txNewSymbol = 1;
+ txSymbol.type = RIO_SYMBOL_TYPE_CONTROL;
+ txSymbol.data = 0xff7e0102;
+ TESTEXPR(transmitByte(stack), 0x7d);
+ TESTEXPR(transmitByte(stack), 0x5e);
+ TESTEXPR(transmitByte(stack), 0x01);
+ TESTEXPR(transmitByte(stack), 0x02);
+ TESTEXPR(transmitByte(stack), 0x7e);
+
+ /* Test transmission of stuffed control symbol with two stuffed bytes. */
+ txNewSymbol = 1;
+ txSymbol.type = RIO_SYMBOL_TYPE_CONTROL;
+ txSymbol.data = 0xff7e7d01;
+ TESTEXPR(transmitByte(stack), 0x7d);
+ TESTEXPR(transmitByte(stack), 0x5e);
+ TESTEXPR(transmitByte(stack), 0x7d);
+ TESTEXPR(transmitByte(stack), 0x5d);
+ TESTEXPR(transmitByte(stack), 0x01);
+ TESTEXPR(transmitByte(stack), 0x7e);
+
+ /* Test transmission of stuffed control symbol with three stuffed bytes. */
+ txNewSymbol = 1;
+ txSymbol.type = RIO_SYMBOL_TYPE_CONTROL;
+ txSymbol.data = 0xff7e7d7e;
+ TESTEXPR(transmitByte(stack), 0x7d);
+ TESTEXPR(transmitByte(stack), 0x5e);
+ TESTEXPR(transmitByte(stack), 0x7d);
+ TESTEXPR(transmitByte(stack), 0x5d);
+ TESTEXPR(transmitByte(stack), 0x7d);
+ TESTEXPR(transmitByte(stack), 0x5e);
+ TESTEXPR(transmitByte(stack), 0x7e);
+
+ /* Test transmission of data symbol with one stuffed byte. */
+ txNewSymbol = 1;
+ txSymbol.type = RIO_SYMBOL_TYPE_DATA;
+ txSymbol.data = 0x7e010203;
+ TESTEXPR(transmitByte(stack), 0x7d);
+ TESTEXPR(transmitByte(stack), 0x5e);
+ TESTEXPR(transmitByte(stack), 0x01);
+ TESTEXPR(transmitByte(stack), 0x02);
+ TESTEXPR(transmitByte(stack), 0x03);
+
+ /* Test transmission of data symbol with two stuffed byte. */
+ txNewSymbol = 1;
+ txSymbol.type = RIO_SYMBOL_TYPE_DATA;
+ txSymbol.data = 0x7e7d0102;
+ TESTEXPR(transmitByte(stack), 0x7d);
+ TESTEXPR(transmitByte(stack), 0x5e);
+ TESTEXPR(transmitByte(stack), 0x7d);
+ TESTEXPR(transmitByte(stack), 0x5d);
+ TESTEXPR(transmitByte(stack), 0x01);
+ TESTEXPR(transmitByte(stack), 0x02);
+
+ /* Test transmission of data symbol with three stuffed byte. */
+ txNewSymbol = 1;
+ txSymbol.type = RIO_SYMBOL_TYPE_DATA;
+ txSymbol.data = 0x7e7d7e01;
+ TESTEXPR(transmitByte(stack), 0x7d);
+ TESTEXPR(transmitByte(stack), 0x5e);
+ TESTEXPR(transmitByte(stack), 0x7d);
+ TESTEXPR(transmitByte(stack), 0x5d);
+ TESTEXPR(transmitByte(stack), 0x7d);
+ TESTEXPR(transmitByte(stack), 0x5e);
+ TESTEXPR(transmitByte(stack), 0x01);
+
+ /* Test transmission of data symbol with four stuffed byte. */
+ txNewSymbol = 1;
+ txSymbol.type = RIO_SYMBOL_TYPE_DATA;
+ txSymbol.data = 0x7e7d7e7d;
+ TESTEXPR(transmitByte(stack), 0x7d);
+ TESTEXPR(transmitByte(stack), 0x5e);
+ TESTEXPR(transmitByte(stack), 0x7d);
+ TESTEXPR(transmitByte(stack), 0x5d);
+ TESTEXPR(transmitByte(stack), 0x7d);
+ TESTEXPR(transmitByte(stack), 0x5e);
+ TESTEXPR(transmitByte(stack), 0x7d);
+ TESTEXPR(transmitByte(stack), 0x5d);
+
+ /***************************************************************
+ * Test complete.
+ ***************************************************************/
+
+ printf("Test complete.\n");
+}
trunk/sw/codec/riocodecuart.c
Property changes :
Added: svn:executable
## -0,0 +1 ##
+*
\ No newline at end of property