OpenCores
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

powered by: WebSVN 2.1.0

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