FFFISCom Library V1.

0 User Guide

FFFISCom Library V1.0 User Guide

Table of Contents
1. Introduction ....................................................................................... 1 1.1. What this document is... ............................................................. 1 1.2. What this document is not... ........................................................ 1 2. Installation ........................................................................................ 2 2.1. Missing section title .................................................................. 2 3. The basic concepts .............................................................................. 3 3.1. A pure library ........................................................................... 3 3.2. Layers .................................................................................... 3 3.2.1. Decomposing the functionality of the application layer .................. 4 3.3. Configuration structures ............................................................. 4 3.4. Nodes ..................................................................................... 4 3.4.1. The data structure ................................................................... 4 3.4.2. Initializing the structure ........................................................... 5 3.4.3. The clock reference node ......................................................... 5 3.4.4. Dealing with functions returning pointers to structures ................... 5 3.5. Connections ............................................................................. 6 3.6. Timing .................................................................................... 7 3.7. Threading ................................................................................ 7 3.8. Error-detecting codes ................................................................. 7 3.8.1. Redundant hashes ................................................................... 7 3.8.2. Barriers ................................................................................ 8 4. The source files .................................................................................. 9 4.1. The header files to include .......................................................... 9 4.2. The header file to update ............................................................ 9 5. Typical usage ................................................................................... 10 5.1. Using the protocol layers (STL and SLL) ..................................... 10 5.1.1. Hardware initialization .......................................................... 10 5.1.2. Global Initialization .............................................................. 10 5.1.3. Node Definition ................................................................... 10 5.1.4. Synchronization ................................................................... 11 5.1.5. Connection creation .............................................................. 11 5.1.6. Wait for the connections to be established ................................. 11 5.1.7. Main loop ........................................................................... 12 5.1.8. Using the codecs .................................................................. 13 6. How to... ......................................................................................... 14 6.1. Use my own CRC function than the one provided with the library .... 14 6.2. Increase the size of the connection-specific incoming FIFO's ........... 14 6.3. Increase the size of the global outgoing FIFO's ............................. 14

iv

Chapter 1. Introduction
1.1. What this document is...
This document describes the FFFisCom library V1.0, its underlying concepts and important properties. It does:

• • •

Explain the properties that are relevant for a developer who considers using the library: its relationship to threading, timing considerations, interfaces to hardware, etc. Explain the mapping between the subset 56, 57 and 58 concepts and their representation in the library Provide a complete explanation of the protocol one must follow to use the library, the meaning of the important parameters, and the sequence in which the various functions must be called.

1.2. What this document is not...
On the other hand, this document is also restricted in a number of ways:

• •

It is not a tutorial about the subset 56, 57 and 58. At least a basic knowledge of these standards and their practical implications is assumed. It is not a tutorial about C either: the language, its constructs, their semantics and idiomatic uses (such as header files, conditional compilation, etc.) are considered as prerequisite knowledge to use this document proficiently. It is a user guide as opposed to a source navigation document: its aims is to explain how one can use the library proficiently, not to provide a detailed description of the internals. It is not an exhaustive descriptive document on the API and its underlying data types, which are better and more accurately explained in the documentation derived from the implementation, in HTML form accessible from $INSTALLDIR/doc/html/index.html. Would this online documentation contradict the current document in any way, the former is to consider more relevant, as it is generated automatically from the source code, and hence, is to be considered a better description of its actual behaviour.

• •

1

Chapter 2. Installation
2.1. Missing section title
The library comes in the form of a single .tgz file, which must be expanded in an ad hoc directory. It contains two subdirectories: • • src contains the source code doc contains the documentation, that is, this document and an html subdirectory which contains the documentation generated automatically from the source code

The src directory contains two subdirectories of its own: • • src/lib contains the library'ssource code src/test contains a number of test programs

2

Chapter 3. The basic concepts
3.1. A pure library
This library implements the UNISIG subsets 56, 57 and 58 (hereafter referred to as the standard) so that a developer can write applications that communicate with other compliant equipements without having to care for all the low-level technicalities described in the standards. The entire issue of communication is addressed by a number of high-level functions only. The library provides ultimate flexibility, by being self-contained. It does not call any standard library function, and furthermore, it does not perform explicit calls to a timing function, nor to hardware access functions to actually send and receive data on the ProfiBus. Basically, it is the user's code's responsibility to: • Read the hardware bus, by means of interrupt function, polling or any other mechanism supported by his ProfiBus hardware and supporting computing platform, and provide the raw incoming message(s) to the library Notify the library often enough to allow time-related functions (timeouts, idle messages, etc.) to perform appropriately. Please note that this implies that the current time must be provided by the user as parameter to a number of the functions of the public API. Query the library for any incoming message that has been identified as user-data Provide the library with application-level outgoing data that must be sent on the bus Send the outgoing telegrams on the ProfiBus hardware at hand when, as a result of one of the actions listed above, one or more outgoing telegrams must be sent.

• • •

3.2. Layers
The standard is divided in three layers:

• • •

The STL (Safe time layer), defined in the subset 56 The SLL (Safe link layer) defined in the subset 57 The Application layer defined in the subset 58

The two former deal with the safe transmission of sequences of bytes; the latter with the representation of meaningful data out of such sequences of bytes. The FFFisCom library supports all three layers, but without introducing excessive coupling: application programmers can use it to send proprietary trafic on the SLL and STL without being restricted to what the application layer allows. More specifically, this means that even if it makes little sense in practice, it is perfectly poossible to use the SLL and the STL to send information of a totally different nature from what the application layer recognizes, and conversely, the application layer could be used to decode traffic that has been sent through entirely different means. Since these two parts of the library are entirely decoupled, the related deliverables will be decoupled accordingly: test, documentation, etc.

3

The basic concepts

These layers are easy to track down in the code: every item related to the STL has a "STL", "__STL__" or "Stl" prefix attached to it, every item attached to the SLL has a "SLL", "__SLL__" or "Sll" prefix attached to it, and quite predictably, every item attached to the application layer has a "APP", "__APP__" or "App" prefix attached to it.

3.2.1. Decomposing the functionality of the application layer
The application layer - sometimes referred to as the “codec's” - is responsible for coding, namely, taking application-level data structure and turning them into sequences of bytes according to the standard, and decoding, namely, taking a sequence of bytes, and turning it into an application-level data structure. It is intuitively clear that decoding involves a form of validation: of all the possible sequences of bytes, of all lengths and contents, only a tiny fraction is valid for decoding. What is less clear, is the fact that the application layer of this library will distinguish between two forms of validity checks to be performed: • • It will first ensure that messages are structurally correct, in the sense that it can interpret the entire sequence of bytes and explode it into messages, etc. It will then ensure that atomic - non-composite - values are valid, that is, they lie between the corresponding validity bounds defined in the standard.

The two levels of validations are separate, implemented as separate functions, so that the decoding process does not stop when an invalid value has been found, thereby allowing for more fine-grained control on the process.

3.3. Configuration structures
The library defines a ESSL_Config_Struct structure, which is passed as parameter to the various functions used to initialize nodes and connections. This structure is made of three sub-structures: • STL_Config, of the type ESSL_STL_Config_Struct specifies the STL-level behaviour, including startup and restart intervals, etc. Please refer to the online documentation for a detailed field per field description of the structure. SLL_Config, of the type ESSL_SLL_Config_Struct specifies the SLL-level behaviour, including acknowledgement interval, idle cycle interval, etc. Node_Config, of the type ESSL_Node_Config_Struct specifies the node-level behaviour, including the local clock inaccuracy, dynamic bus transfer time, etc.

• •

When provided to a function, arguments of the ESSL_Config_Struct structure are always passed by value, thereby reflecting the fact that all the relevant information is copied into the node and/or connection if required. In other words, after having been passed as parameter, the ESSL_Config_Struct can be changed, discarded if stored as a local variable, etc. without altering the subsequent behaviour of the nodes and connections that have been initialized before.

3.4. Nodes
3.4.1. The data structure
4

The basic concepts

The node on the network is represented by a C structure named ESSL_Node_Struct This structure defines the equipment where the library runs, its behaviour in terms of the various degrees of liberty supported by the standard, and its internal state at all time. It must be given as parameter to virtually every function of the library, as the library is stateless; it contains no global information of its own. The internal structure of a node is opaque: at no point should the application programmer access the structure's internals directly 1. Access functions are provided instead. Except for extreme cases, where a single process should communicate on two disjoint ProfiBus networks (not just a Dual bus), every process should hold only one instance of such node structure.

3.4.2. Initializing the structure
This structure is initialized by a call to the function: const ESSL_Status_Struct* ESSL_Init_Node (const fsTIME Now, const fsUINT32 Random_Number, ESSL_Node_Struct *const Node, const ESSL_Config_Struct Config, const fsUINT8 Address, const fsBOOL Dual_Bus, const ESSL_Safety_Level_Enum Clock_Safety_Level, const fsUINT8 Clock_Address, const fsUINT8 Clock_Sap)

The Random_Number parameter is used to initialize the random number generator used by the library. If you wish to have a strictly reproducible sequence of random number for simulation purposes, you may just provide a constant value for this parameter. However, in production environments, it is probably more appropriate to provide a value which is more genuinely random, by provide the time - or any time-derived value - as seed for the random number generator. A FFFis network must contain a reference clock node, which is responsible for maintaining the reference time against which the others must measure. Drifts with regard to this reference time must be measured, and threshold violations must induce appropriate action.

3.4.3. The clock reference node
The reference node address must be given as the Clock_Address parameter to the ESSL_Init_Node function. By providing the node's own address as this parameter (that is, providing the same value to the Address and Clock_Address parameters), one can define the newly created node as the reference clock node for the network, thereby inducing a different behaviour: it will broadcast SyncAndRefTime messages.

3.4.4. Dealing with functions returning pointers to structures
The library performs no dynamic allocations. Hence, the ESSL_Init_Node function's return value is not on the heap, but points to a private field of the ESSL_Node_Struct passed as parameter. This implies that: • The user should never even try to deallocate this return value

There is no formal way to ensure that the structure is never accessed directly, as C provide no such protection mechanism. However, since the internals of the data strutures might change in non reverse compatible ways, any piece of code which refers to the data structure's field directly might not compile with future versions of the library.
1

5

The basic concepts

The content of this private field might change due to subsequent calls to library functions. Any value which should be retained for long amounts of time should be copied elsewhere.

3.5. Connections
Connections are represented by id's only, which receive value when connections are open. Connections can be of two kinds:

Point to point (P2P) where two actors send each other private informations the other devices do not handle. When using a connection in this mode, each node has a different role: • • One node must act as master node and initiate the connection The other node must act as slave node and does very little, as it relies on the master node for the initiation

Multicast, where one sender node sends broadcast data to any receiver node caring to listen, thereby defining two roles.

Separate functions are used to open a connection of each of these kinds, depending on the role of the current node2: const const const const ESSL_Status_Struct* ESSL_Status_Struct* ESSL_Status_Struct* ESSL_Status_Struct* ESSL_Open_PTP_Master(...) ESSL_Open_PTP_Slave(...) ESSL_Open_MCast_Sender(...) ESSL_Open_MCast_Receiver(...)

Connection id's are not global entities: they are related to nodes. In other words, whenever a connection will have to be referred to, for instance when passing parameters to a function, both the node (in the form of a pointer to a ESSL_Node_Struct) and the connection id must be specified. At any time, a connection is in one of three states: • • • Disconnected. This is the initial state. The only operation valid in this state is to attempt to connect Connecting. This is a transient state when a connection operation has been initiated, waiting for the prologue to complete. The only operation that can be performed in this state is a disconnect. Connected. This is the state where all preconditions for the connection to function have been met. One can receive data, send data or disconnect when in this state.

Some severe error conditions can cause the library to close the connection. One can then distinguish between a connection which is diconnected because it has never been connected; and connection which has been disconnected by an external condition by calling the: const Sll_Disconnect_Context_Struct * ESSL_Get_Disconnect_Context ( const ESSL_Node_Struct *const Node, const ESSL_Connection_Id Connection_Id)

We shall refer to the current node as the node on which the library runs, described by the ESSL_Node_Struct* given as parameter to these connection initiation function.
2

6

The basic concepts

function. If it returns NULL, the connection has never been opened. If it returns any non-NULL value, the connection has been opened, and closed due to some condition detailed in the returned Sll_Disconnect_Context_Struct Similarly to what was described in Section 3.4.4, “Dealing with functions returning pointers to structures”, the structure returned by the ESSL_Get_Disconnect_Context function is not allocated on the heap, and must therefore not be deallocated explicitly.

3.6. Timing
The library has no internal clock, nor does it access an external clock behind the scenes. The only source for timing information it will ever use is the Now parameter declared in most public functions except for the application layer which only provides time-insensitive coding and decoding services. The Now parameter is a 32-bit unsiged integer, representing the amount of miliseconds elapsed since the start of the system using the library. It is the user's responsibility to ensure that the time value given to the library is monotonous and accurate. It is also the user's responsibility to ensure the library is called often enough to guarantee that all time-related behaviour is correct (time outs, idle messages, etc.) For instance, if an idle message must be sent at most every 500 milliseconds, the system is configured to send it a bit faster for security, say, every 400 ms; the library must be called at least once every 100 ms and preferably, twice as fast, to ensure that outgoing idle messages are not retained for longer than acceptable.

3.7. Threading
The library is stateless in the sense that all the information it maintains across function calls is stored in the node structure. Hence, multi-threaded accesses to separate nodes is perfectly safe. On the other hands, if various function calls related to the same node must be performed from different threads, access must be protected to avoid reentrance. The library does not provide any of such protection mechanism. It is the user's responsibility to protect access to a node's data structure using semaphores, critical sections, mutexes or any semantically equivalent protection mechanism. These locks will only hold for very limited amounts of time, as the library performs no I/O nor polling. Thereby, the time span between every function entry and exit is bounded.

3.8. Error-detecting codes
The FFFis library is extremely robust, and makes very conservative use of the facilities provided by the C language in order to reduce the risk of software failure as much as possible. However, this does not prevent the library from being potentially vulnerable to third party code linked into the same application, and hence, the same address space. In order to address this issue, the libray provides two optional facilities that can be enabled or disabled by simple compilation directives, and which can be used depending on the criticalness of the application at hand as well as the available computing power. These two facilities are mutually exclusive, since computing hashes will detect undesired memory overwrite more accurately than barriers would.

3.8.1. Redundant hashes
If this facility is enabled, hash function is computed on every connection after performing any operation on that connection, and this hash value is checked before performing the next operation. The 7

The basic concepts

idea is to detect a memory corruption as early as possible - as even a minor change would cause the hash value to be invalidated, ensuring that the process would not continue in case of a memory corruption. A similar scheme computes a hash on the node data structure stripped from the connections it contains. This option is of course fairly computationally intensive, since the connection data structures contain FIFO's, and computing a hash, even a very simplistic one, requires that the entire data structure is scanned on every function call that deals with the connection. To enable this facility, the ESSL_ENABLE_REDUNDANT_HASHES macro should be defined in the essl_user.h file.

3.8.2. Barriers
Barriers are integer fields inserted at the beginning and at the end of every connection structure. For the connection to be valid, the two barriers must be the negated values of each other. Every time a function is called, the barriers are checked against this negation property. In case of failure, the library is stopped, as it indicates that the data struture has been overwritten from neighbouring memory areas. Barriers do not protect the library from random alterations inside the connection data structures, since only the extremities - the barriers - are actually checked for validity. However, they detect buffer overruns that cause memory to be overwritten beyond its intended area. To enable this facility, the ESSL_ENABLE_BARRIERS macro should be defined in the essl_user.h file.

8

Chapter 4. The source files
4.1. The header files to include
In an application module which must interact with the library, depending on the library is used, the following files must be included: • essl_api.h contains the prototypes for the functions required to create nodes and connections, to send and receive data on connections, etc. It is required by all application that use the library's implementation of the STL and the SLL. essl_app.h contains the application-level codecs prototypes. If you wich to use the library for the two lower layers only, using your own application messages rather than the standard subset 58 messages, you do not need to include this file.

Including any of these header files will result in including other header files - including essl_user.h, of course (see below) - but these two are basically all you need from an application point of view.

4.2. The header file to update
Every file of the library includes a file named essl_user.h. This is the only file the user is supposed to alter. It should contain macro definitions for all the types, constants where the default behaviour is not considered appropriate for a specific environment. Any alteration of any file of the library, other than essl_user.h and which is not endorsed explictly by ERTMS Solutions instantly voids any of our support obligations, would you have a ongoing maintenance contract. Please bear in mind that any change performed on this file will be lost whenever you install a new version of the library, unless you carefully save it beforehand. You might consider saving it on a version control system, as it is, in fact, one of your own source files rather than a component of the library per se.

9

Chapter 5. Typical usage
This chapter lists the steps that your application program should follow in order to interact gracefully with the library. Please refer to the sample application example_master.c available in the HTML documentation for a more detailed explanation, as this chapter and this sample application are direct reflections of each other. This chapter assumes that three utility functions are provided by the user: • • • Initialize_Hardware performs any one-time initialization required for the ProfiBus hardware at hand to work appropriately.. Receive_From_Bus attempt to read an incoming telegram from the hardware, and returns true to indicate that a telegram was read, false if no such telegram could be read. Send_Over_Bus which sends a telegram over the profibus.

The two latter of these functions must take a pointer to a ESSL_FDL_Telegram_Struct as parameter. This structure contains the addressing information (source address, target address, etc.) in addition to the actual data being read or written.

5.1. Using the protocol layers (STL and SLL)
5.1.1. Hardware initialization
This step is entirely under the user's responsibility, but it is essential that this step is performed before the library is called, because such initialization can induce a performance penalty that might interfere with the library's proper behaviour if it occurs on demand, when the first message is read or written. This step is just a call to the Initialize_Hardware function.

5.1.2. Global Initialization
The function: void ESSL_Init (const fsTIME Now);

must be the first function of the library to be called. It must be called once only. At the time of this writing, this function does nothing, since the library is entirely stateless, and maintains all the persistent information it needs in the node structures. However, it is to be considered good practice to still call this initialization function as the stateless property of the library might change in future versions.

5.1.3. Node Definition
First, the node must be initialized, by calling ESSL_Init_Node providing the node as parameter, as in: Status = ESSL_Init_Node (FSMG_Time() FSMG_Time() &Node Config 10 , , , , /* /* /* /* Current time Random number (seed) Node structure Configuration structure */ */ */ */

Typical usage

STM_ADDRESS , FALSE , ESSL_SAFETY_LEVEL_4, CLOCK_ADDRESS , CLOCK_SAP);

/* /* /* /* /*

Node 's address No dual bus Clock safety level Clock address Clock 's SAP

*/ */ */ */ */

Please note that the Config parameter is passed by value, as its relevant content is copied into the node data structure rather than referred to by a pointer.

5.1.4. Synchronization
Before starting the true mainloop where messages can be sent and received, one must first wait for the node to be synchronized. This can be checked for by calling the ESSL_Clock_Is_Synchronized function repeatedly until it returns true or until a time out condition occurs. This function always returns true if the node was initialized as being the master clock. While waiting for the node to be synchronized, one must: • • Read any incoming message from the hardware bus and pass it to the node, by means of the ESSL_Handle_Incoming_Telegram function. Update the node's internal state by calling the ESSL_Update_Node function. When it will have received the appropriate synchronization messages, it will set its status to synchronized, and exit the loop.

5.1.5. Connection creation
When the node has been created and synchronized, the connections must be created one by one. Depending on the kind of connection at hand, different functions must be called. For instance, below, a point to point connection is opened to an equipment with the address EVC_ADDRESS, under the service access point SUPERVISION_SAP which are constants or variables that must have been defined. Status = ESSL_Open_PTP_Master (FSMG_Time() , &Node , Config , ESSL_SAFETY_LEVEL_4, EVC_ADDRESS , SUPERVISION_SAP); if (Status->Operation_Status == ESSL_OPSTATUS_OK) { /* Register the connection id */ Supervision_Id = Status->Connection_Id; ... /* /* /* /* /* /* Current time Node Configuration Safety level Slave 's address Connection 's SAP */ */ */ */ */ */

As shown in the example above, if opening the connection is successful, the corresponding connection id can be retrieved from the resulting status structure. Please note that this connection creation is purely logical, the underlying hardware connection must have been initialized previously as part of hardware initialization phase under the user's responsibility.

5.1.6. Wait for the connections to be established
If the node is the master of the connection, it must first send the original connect message, by a call to the ESSL_Connect function. Please note that this function does not actually send the message over the network, it merely puts the connect message on the outgoing FIFO attached to the node. 11

Typical usage

The actual message will only be sent when querying for any outgoing message to be sent on the ProfiBus network. Then, both if it the master and the slave of the connection, it must wait for the connection to be established, by means of a loop which reads incoming messages from the hardware, update the node and the connection, and send outgoing messages if necessary. When the appropriate messages will have been exchanged, the connection's status will move to active automatically. In the example above, sending data if available must be represented by a loop such as: Status = ESSL_Get_Outgoing_Telegram (&Node); while (Status->Operation_Status == ESSL_OPSTATUS_OUTGOING_DATA) { Send_Over_Bus (Status->Outgoing_Telegram); Status = ESSL_Get_Outgoing_Telegram (&Node); } which flushes the output FIFO, and sends the telegrams it contains over the bus.

5.1.7. Main loop
When the node(s) and connection(s) are initialized, synchronized and connected, one must enter a loop where one will be able to send and receive actual data on the ProfiBus network. The following sections list the actions that must be followed within that loop.

5.1.7.1. Check for clock being ok
Whenever the node desynchronizes, it disconnects all its connections automatically. One can thus detect whether the node is synchronized by calling the ESSL_Get_Connection_Status function.

5.1.7.2. Collect incoming telegrams
This is where the user must take any incoming telegram he or she receives from the hardware, and provide them to the library so that its internal state will be update accordingly. Every connection's FIFO will be populated with the corresponding incoming application data telegrams.

5.1.7.3. Update node
This operation notifies the node with the current time, so that time-related behaviour can be triggered if appropriate. This might imply message's having to be sent.

5.1.7.4. Update every active connection
This operation notifies the connection with the current time, so that time-related behaviour can be triggered if appropriate. This operation is separate from the update node as described above, to allow for connection-specific error reporting if necessary.

5.1.7.5. Connect/disconnect/send/receive
Depending on whether the connection is a P2P or multicast one, depending on its status (disconnected, connected or connecting), the user can perform several operations: • • • Connect, if currently disconnected, thereby enabling the connection protocol Disconnect, if currently connected Send messages if currently connected. The message will be enclosed in the appropriate envel12

Typical usage

oppe (status information, checksums, etc...) and stored in the node's outgoing FIFO. Check Section 5.1.8, “Using the codecs” for more information on how to encode application-level data into telegrams. • Receive application messages, by polling every connection's incoming FIFO. In fact, these messages will have been received earlier (in the sense of being transmitted from the hardware), when collecting incoming messages, but the receive operation as described here will only deal with application messages, protocol messages (idle, synchronization, etc.) are thus not propagated through the incoming FIFO's. Check Section 5.1.8, “Using the codecs” for more information on how to encode application-level data into telegrams.

5.1.7.6. Transmit outgoing telegrams
This is where the user must take every outgoing telegram produce by the operations above from the outgoing FIFO, and send it appropriately on the target hardware. This will include application data telegram with their enveloppe, as well as idle and multicast startup messages produced automatically by the library without any explicit user intervention.

5.1.8. Using the codecs

13

Chapter 6. How to...
6.1. Use my own CRC function than the one provided with the library
This can be provided by redefining the ESSL_CALCULATE_CRC macro in essl_user.h to call you own function rather than the default behaviour. This is the only header file in the library which is meant to be altered directly by the user to tune the library's behaviour to environment-specific constraints.

6.2. Increase the size of the connection-specific incoming FIFO's
This can be achieved by defining the ESSL_CAPACITY_APPDATA_FIFO in the essl_user.h file. This value should be set high enough to accomodate at least the number of incoming application messages that can received on every logical connection between two polling cycles.

6.3. Increase the size of the global outgoing FIFO's
This can be achieved by defining the ESSL_CAPACITY_OUTGOING_FIFO in the essl_user.h file. This value should be set high enough to accomodate at least the number of incoming application messages that can received on every logical connection between two polling cycles.

14