Commit 1bdb9a67 authored by Delia Cellarier's avatar Delia Cellarier

Drivers for serial including escaping

parent 9edc2137
......@@ -82,6 +82,7 @@ package body PolyORB_HI_Drivers_Native_UART is
use PolyORB_HI.Messages;
use PolyORB_HI.Utils;
use PolyORB_HI.Output;
use type Ada.Streams.Stream_Element_Offset;
type Node_Record is record
-- UART is a simple protocol, we use one port to send, assuming
......@@ -98,6 +99,8 @@ package body PolyORB_HI_Drivers_Native_UART is
subtype Message_Length_Stream is Stream_Element_Array
(1 .. Message_Length_Size);
subtype Framed_AS_Full_Stream is
Ada.Streams.Stream_Element_Array (1 .. 2*PDU_Size + 2);
subtype AS_Full_Stream is Ada.Streams.Stream_Element_Array (1 .. PDU_Size);
subtype Full_Stream is Stream_Element_Array (1 .. PDU_Size);
......@@ -106,8 +109,13 @@ package body PolyORB_HI_Drivers_Native_UART is
function To_PO_HI_Full_Stream is new Ada.Unchecked_Conversion
(AS_Full_Stream, Full_Stream);
-- Start marker to synchronize
START_MARKER : Unsigned_8 := 16#A0#;
-- Constant bytes for framing
START_MARKER : Constant Unsigned_8 := 16#A0#;
STOP_MARKER : Constant Unsigned_8 := 16#B0#;
ESC : Constant Unsigned_8 := 16#C0#;
ESC_START : Constant Unsigned_8 := 16#CA#;
ESC_STOP : Constant Unsigned_8 := 16#CB#;
ESC_ESC : Constant Unsigned_8 := 16#CC#;
----------------
-- Initialize --
......@@ -274,13 +282,15 @@ package body PolyORB_HI_Drivers_Native_UART is
-------------
procedure Receive is
use type Ada.Streams.Stream_Element_Offset;
-- use type Ada.Streams.Stream_Element_Offset;
SEL : AS_Message_Length_Stream;
-- SEL : AS_Message_Length_Stream;
SEA : AS_Full_Stream;
Framed_SEA : Framed_AS_Full_Stream;
SEO : Ada.Streams.Stream_Element_Offset;
Packet_Size : Ada.Streams.Stream_Element_Offset;
Data_Received_Index : Ada.Streams.Stream_Element_Offset;
-- Packet_Size : Ada.Streams.Stream_Element_Offset;
Last_Index : Ada.Streams.Stream_Element_Offset;
begin
Main_Loop : loop
......@@ -288,62 +298,68 @@ package body PolyORB_HI_Drivers_Native_UART is
-- UART is a character-oriented protocol
-- Framing
while Unsigned_8(SEL (1)) /= START_MARKER loop
-- Buffer for framed message
Framed_SEA := (others => 0);
Last_Index := 1;
-- Synchronization
while Unsigned_8 (Framed_SEA (1)) /= START_MARKER loop
GNAT.Serial_Communications.Read
(Nodes (My_Node).UART_Port,
SEL (1 .. 1),
Framed_SEA (1 .. 1),
SEO);
end loop;
-- 1/ Receive message length
GNAT.Serial_Communications.Read
(Nodes (My_Node).UART_Port, SEL, SEO);
Packet_Size := Ada.Streams.Stream_Element_Offset
(To_Length (To_PO_HI_Message_Length_Stream (SEL)));
SEO := Packet_Size;
SEA (1 .. Message_Length_Size) := SEL;
Data_Received_Index := Message_Length_Size + 1;
while Data_Received_Index <= Packet_Size + Message_Length_Size loop
-- Receive full message
while Unsigned_8 (Framed_SEA (SEO)) /= STOP_MARKER loop
-- We must loop to make sure we receive all data
GNAT.Serial_Communications.Read
(Nodes (My_Node).UART_Port,
SEA (Data_Received_Index .. SEO + 1),
Framed_SEA (SEO + 1 .. 2*PDU_Size + 2),
SEO);
Data_Received_Index := 1 + SEO + 1;
end loop;
-- 2/ Receive full message
if SEO /= SEA'First - 1 then
-- Put_Line
-- (Normal,
-- "UART received"
-- & Ada.Streams.Stream_Element_Offset'Image (SEO)
-- & " bytes");
-- Deliver to the peer handler
begin
PolyORB_HI_Generated.Transport.Deliver
(Corresponding_Entity
(Unsigned_8 (SEA (Message_Length_Size + 1))),
To_PO_HI_Full_Stream (SEA)
(1 .. Stream_Element_Offset (SEO)));
exception
when E : others =>
null; -- Put_Line (Ada.Exceptions.Exception_Information (E));
end;
-- Remove escaped characters
declare
i : Ada.Streams.Stream_Element_Offset := 2;
begin
while i < SEO loop
if Unsigned_8 (Framed_SEA (i)) = ESC
then
case Unsigned_8 (Framed_SEA (i + 1)) is
when ESC_START => SEA (Last_Index)
:= Ada.Streams.Stream_Element(START_MARKER);
when ESC_STOP => SEA (Last_Index)
:= Ada.Streams.Stream_Element(STOP_MARKER);
when ESC_ESC => SEA (Last_Index)
:= Ada.Streams.Stream_Element(ESC);
when others => null; -- should not happen
end case;
i := i + 2;
else
SEA (Last_Index) := Framed_SEA (i);
i := i + 1;
end if;
Last_Index := Last_Index + 1;
end loop;
end;
-- Deliver to the peer handler
begin
PolyORB_HI_Generated.Transport.Deliver
(Corresponding_Entity
(Unsigned_8 (SEA (Message_Length_Size + 1))),
To_PO_HI_Full_Stream (SEA)
(1 .. Stream_Element_Offset (Last_Index - 1)));
exception
when E : others =>
null; -- Put_Line (Ada.Exceptions.Exception_Information (E));
end;
else
null; -- Put_Line ("Got error");
end if;
end loop Main_Loop;
end Receive;
......@@ -358,7 +374,7 @@ package body PolyORB_HI_Drivers_Native_UART is
return Error_Kind
is
pragma Unreferenced (Node);
use type Ada.Streams.Stream_Element_Offset;
-- use type Ada.Streams.Stream_Element_Offset;
-- We cannot cast both array types using
-- Ada.Unchecked_Conversion because they are unconstrained
......@@ -371,7 +387,8 @@ package body PolyORB_HI_Drivers_Native_UART is
pragma Import (Ada, Msg);
for Msg'Address use Message'Address;
Packet : Ada.Streams.Stream_Element_Array
(1 .. Ada.Streams.Stream_Element_Offset (Size + 1));
(1 .. Ada.Streams.Stream_Element_Offset (2*Size + 2));
SEO : Ada.Streams.Stream_Element_Offset := 1;
begin
-- Put_Line ("Using user-provided UART stack to send");
......@@ -381,11 +398,30 @@ package body PolyORB_HI_Drivers_Native_UART is
-- Adding a Start byte at the beginning
Packet (1) := Ada.Streams.Stream_Element (START_MARKER);
Packet (2 .. Ada.Streams.Stream_Element_Offset (Size + 1)) := Msg;
-- Escaping
for i in 1 .. Ada.Streams.Stream_Element_Offset (Size) loop
case Unsigned_8 (Msg (i)) is
when START_MARKER => Packet (SEO + 1) := Ada.Streams.Stream_Element (ESC);
Packet (SEO + 2) := Ada.Streams.Stream_Element (ESC_START);
SEO := SEO + 2;
when STOP_MARKER => Packet (SEO + 1) := Ada.Streams.Stream_Element (ESC);
Packet (SEO + 2) := Ada.Streams.Stream_Element (ESC_STOP);
SEO := SEO + 2;
when ESC => Packet (SEO + 1) := Ada.Streams.Stream_Element (ESC);
Packet (SEO + 2) := Ada.Streams.Stream_Element (ESC_ESC);
SEO := SEO + 2;
when others => Packet (SEO + 1) := Msg (i);
SEO := SEO + 1;
end case;
end loop;
-- Adding a Stop byte at the end
Packet (SEO + 1) := Ada.Streams.Stream_Element (STOP_MARKER);
GNAT.Serial_Communications.Write
(Port => Nodes (My_Node).UART_Port,
Buffer => Packet);
Buffer => Packet(1 .. SEO + 1));
return Error_Kind'(Error_None);
-- Note: we have no way to know there was an error here
......
------------------------------------------------------------------------------
-- --
-- PolyORB HI COMPONENTS --
-- --
-- P O L Y O R B _ H I _ D R I V E R S _ S T M 3 2 F 4 _ U A R T --
-- --
-- B o d y --
-- --
-- Copyright (C) 2012-2015 ESA & ISAE. --
-- --
-- PolyORB-HI is free software; you can redistribute it and/or modify under --
-- terms of the GNU General Public License as published by the Free Soft- --
-- ware Foundation; either version 3, or (at your option) any later ver- --
-- sion. PolyORB-HI 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. --
-- --
-- As a special exception under Section 7 of GPL version 3, you are granted --
-- additional permissions described in the GCC Runtime Library Exception, --
-- version 3.1, as published by the Free Software Foundation. --
-- --
-- You should have received a copy of the GNU General Public License and --
-- a copy of the GCC Runtime Library Exception along with this program; --
-- see the files COPYING3 and COPYING.RUNTIME respectively. If not, see --
-- <http://www.gnu.org/licenses/>. --
-- --
-- PolyORB-HI/Ada is maintained by the TASTE project --
-- (taste-users@lists.tuxfamily.org) --
-- --
------------------------------------------------------------------------------
-- Notes : in RM0090 section 10-3-3 we can find the mapping table for the DMA
-- it says for example that DMA1 can be connected to the transmitter of USART2
......@@ -32,7 +61,6 @@ with Ada.Interrupts; use Ada.Interrupts;
with Ada.Interrupts.Names; use Ada.Interrupts.Names;
-- with Types; use Types;
with Interfaces;
--with CRC; use CRC;
With Ada.Exceptions;
with Ada.Unchecked_Conversion;
......@@ -127,16 +155,20 @@ package body PolyORB_HI_Drivers_STM32F4_UART is
Nodes : array (Node_Type) of Node_Record;
-- One-message buffer for reception --aliased ?
Synchro : Boolean := False;
Message_Ready : STC.Suspension_Object;
Len_Complete : Boolean := False;
Synchro : Boolean := False;
Escaped : Boolean := False;
SEA : AS_Full_Stream;
SEL : AS_Message_Length_Stream;
Packet_Size : Ada.Streams.Stream_Element_Offset;
Data_Received_Index : Ada.Streams.Stream_Element_Offset := 1;
Data_Received_Index : Ada.Streams.Stream_Element_Offset := 0;
Packet_Size : Ada.Streams.Stream_Element_Offset := 0;
-- Start marker to synchronize
START_MARKER : Unsigned_8 := 16#A0#;
-- Constant bytes for framing
START_MARKER : Constant Unsigned_8 := 16#A0#;
STOP_MARKER : Constant Unsigned_8 := 16#B0#;
ESC : Constant Unsigned_8 := 16#C0#;
ESC_START : Constant Unsigned_8 := 16#CA#;
ESC_STOP : Constant Unsigned_8 := 16#CB#;
ESC_ESC : Constant Unsigned_8 := 16#CC#;
----------------
-- Initialize --
......@@ -353,7 +385,7 @@ package body PolyORB_HI_Drivers_STM32F4_UART is
(Corresponding_Entity
(Unsigned_8 (SEA (Message_Length_Size + 1))),
To_PO_HI_Full_Stream (SEA)
(1 .. Stream_Element_Offset (Packet_Size + Message_Length_Size)));
(1 .. Stream_Element_Offset (Packet_Size)));
exception
when E : others =>
null; -- Put_Line (Ada.Exceptions.Exception_Information (E));
......@@ -376,44 +408,54 @@ package body PolyORB_HI_Drivers_STM32F4_UART is
protected body Reception is
procedure Handle_Reception is
use type Ada.Streams.Stream_Element_Offset;
-- Receive one char.
Received_char : constant Character := Character'Val(Current_Input (Transceiver));
use type Ada.Streams.Stream_Element_Offset;
-- Receive one char.
Received_char : constant Unsigned_8 := Unsigned_8 (Current_Input (Transceiver));
Original_char : Unsigned_8;
begin
--No framing, escaping for now
begin
-- Synchronization with Start byte
if not Synchro
then
Synchro := (Unsigned_8 (Current_Input (Transceiver)) = START_MARKER);
Synchro := (Received_char = START_MARKER);
-- Received Stop Marker ?
elsif Received_char = STOP_MARKER
then
-- Reception complete
Synchro := False;
Escaped := False;
Packet_Size := Data_Received_Index;
Data_Received_Index := 0;
loop
exit when not Status (Transceiver, Read_Data_Register_Not_Empty);
end loop;
STC.Set_True(Message_Ready);
else
if not Len_Complete
-- Remove escaping if previous character was ESC
if Escaped
then
SEL(Data_Received_Index) := Ada.Streams.Stream_Element
(Character'Pos(Received_char));
Data_Received_Index := Data_Received_Index + 1;
if Data_Received_Index = Message_Length_Size + 1
then
-- Lenght received
Len_Complete := True;
Packet_Size := Ada.Streams.Stream_Element_Offset
(To_Length (To_PO_HI_Message_Length_Stream (SEL)));
SEA (1 .. Message_Length_Size) := SEL;
end if;
case Received_char is
when ESC_START => Original_char := START_MARKER;
when ESC_STOP => Original_char := STOP_MARKER;
when ESC_ESC => Original_char := ESC;
when others => null; -- should not happen
end case;
else
SEA(Data_Received_Index) := Ada.Streams.Stream_Element
(Character'Pos(Received_char));
Original_char := Received_char;
end if;
-- Received ESC character ? If yes, not added to buffer
Escaped := (Received_char = ESC);
-- Store character into buffer
if not Escaped
then
Data_Received_Index := Data_Received_Index + 1;
if Data_Received_Index = Message_Length_Size + Packet_Size + 1
then
-- Reception complete
Len_Complete := False;
Data_Received_Index := 1;
loop
exit when not Status (Transceiver, Read_Data_Register_Not_Empty);
end loop;
STC.Set_True(Message_Ready);
end if;
SEA(Data_Received_Index) := Ada.Streams.Stream_Element
(Original_char);
end if;
end if;
......@@ -455,9 +497,9 @@ package body PolyORB_HI_Drivers_STM32F4_UART is
(1 .. Ada.Streams.Stream_Element_Offset (Size));
pragma Import (Ada, Msg);
for Msg'Address use Message'Address;
-- Msg_CRC : Unsigned_32 := Make(Msg);
Packet : Ada.Streams.Stream_Element_Array
(1 .. Ada.Streams.Stream_Element_Offset (Size + 1));
(1 .. Ada.Streams.Stream_Element_Offset (2*Size + 2));
SEO : Ada.Streams.Stream_Element_Offset := 1;
begin
-- Put_Line ("Using user-provided UART stack to send");
......@@ -467,7 +509,26 @@ package body PolyORB_HI_Drivers_STM32F4_UART is
-- Adding a Start byte at the beginning
Packet (1) := Ada.Streams.Stream_Element (START_MARKER);
Packet (2 .. Ada.Streams.Stream_Element_Offset (Size + 1)) := Msg;
-- Escaping
for i in 1 .. Ada.Streams.Stream_Element_Offset (Size) loop
case Unsigned_8 (Msg (i)) is
when START_MARKER => Packet (SEO + 1) := Ada.Streams.Stream_Element (ESC);
Packet (SEO + 2) := Ada.Streams.Stream_Element (ESC_START);
SEO := SEO + 2;
when STOP_MARKER => Packet (SEO + 1) := Ada.Streams.Stream_Element (ESC);
Packet (SEO + 2) := Ada.Streams.Stream_Element (ESC_STOP);
SEO := SEO + 2;
when ESC => Packet (SEO + 1) := Ada.Streams.Stream_Element (ESC);
Packet (SEO + 2) := Ada.Streams.Stream_Element (ESC_ESC);
SEO := SEO + 2;
when others => Packet (SEO + 1) := Msg (i);
SEO := SEO + 1;
end case;
end loop;
-- Adding a Stop byte at the end
Packet (SEO + 1) := Ada.Streams.Stream_Element (STOP_MARKER);
-- Previous Send should have left status "Transfer Complete Indicated"
-- We must clear it before starting a new transfer
......@@ -477,7 +538,7 @@ package body PolyORB_HI_Drivers_STM32F4_UART is
Tx_Stream,
Source => Packet'Address,
Destination => Data_Register_Address (Transceiver),
Data_Count => UInt16 (Size + 1)); --legal ?
Data_Count => UInt16 (SEO + 1)); -- too small ?
Enable_DMA_Transmit_Requests (Transceiver);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment