Skip to content

Commit

Permalink
Documentation for UDS' dispatcher and connection parts
Browse files Browse the repository at this point in the history
resovles BS-2651

Change-Id: Ic73fcca523827f62002b283fee297400c710c349
  • Loading branch information
kirill-brezhnyev authored and marcmo committed Jan 20, 2025
1 parent e3d5991 commit c4c5cf0
Show file tree
Hide file tree
Showing 7 changed files with 225 additions and 9 deletions.
5 changes: 0 additions & 5 deletions libs/bsw/uds/doc/application_config_example.rst

This file was deleted.

7 changes: 3 additions & 4 deletions libs/bsw/uds/doc/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,14 @@
uds - Unified Diagnostic Services
=================================

Overview
--------
An implementation of the ISO-14229 specification.

Unified Diagnostic Services (UDS) is a protocol that allows diagnostic systems
to communicate with Electronic Control Units (ECUs) in vehicles. It is used to
diagnose errors, debug and reprogram ECUs.

.. toctree::
:hidden:
:maxdepth: 1
:glob:

application_config_example
*/index
71 changes: 71 additions & 0 deletions libs/bsw/uds/doc/user/connection.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
.. _connections:

Connections
===========

Incoming and outgoing connections
---------------------------------

There are two types of connections: incoming and outgoing. As the names suggest,
an incoming connection establishes a link between an incoming **request**
and corresponding UDS job. Conversely, an outgoing connection links an outgoing **request**
to its corresponding job. **Typically ECU functions as server, processing
incoming requests**. Both incoming and outgoing connections may receive and send out messages,
the prefixes "in" and "out" refer to the direction of **requests** relative to the ECU:

* Incoming connections handle requests sent to the ECU and transmit its responses.
* Outgoing connections send requests from the ECU and receive responses sent back.

All incoming messages (requests or responses to requests) are queued in the
dispatcher (see ``DiagDispatcher``). Depending on the template parameters of
``DiagnosisConfiguration``, there may be multiple incoming and outgoing connections.
Whenever a new message is added to the queue, it is processed asynchronously.
This allows multiple incoming connections, selected from a connection pool, to establish
the message-job connection and process the corresponding job.

When a job is completed (see the concrete implementation of the ``process()`` function of a job),
the algorithm identifies the corresponding connection in the list of active **incoming** connections
and sends the response.

DiagConnectionManager
---------------------

The class implements specific logic to manage incoming and outgoing connections
upon request. It uses the underlying ``DiagnosisConfiguration`` as a structure containing the
allocated connections.


Nested Request
--------------

It is possible to pack multiple requests into a single request message. The ``NestedDiagRequest``
class provides an interface, including the ``prepareNextRequest()`` and ``processNextRequest()``
functions, to be implemented in derived classes. These derived classes define the specific logic
for extracting individual requests from the monolithic block of grouped requests.
An example of a class that can process nested requests is
``MultipleReadDataByIdentifier``. As the name suggests, this class can handle multiple
read-by-identifier (`SID` 0x22) requests within a single nested request.

Examples
++++++++

.. code-block:: cpp
ReadIdentifierFromMemory _read22Cf01;
ReadIdentifierFromNvStorage _read22Cf02;
void addMultiReader(DiagDispatcher2 & udsDispatcher,
MultipleReadDataByIdentifier & _readMulti)
{
udsDispatcher.addAbstractDiagJob(_readMulti);
udsDispatcher.addAbstractDiagJob(_read22Cf01);
udsDispatcher.addAbstractDiagJob(_read22Cf02);
}
When the CAN communication is properly configured, the ECU will respond to the message
by decomposing the nested request into two requests: `CF01` and `CF02`.
It is important to correctly specify the length of the request (5 in our example):

.. code-block:: shell
cansend vcan0 02A#0522CF01CF020000
85 changes: 85 additions & 0 deletions libs/bsw/uds/doc/user/dispatcher.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
.. _dispatcher:

Diagnostic dispatcher
=====================

Overview
--------

The ``DiagDispatcher2`` class manages UDS jobs and handles the dispatching of incoming and outgoing
requests and responses. Messages are dispatched by calling the ``send()`` function with the
corresponding message as an argument. This approach ensures that incoming and outgoing messages are
queued for sequential processing.

For the dispatcher to function properly, the order in which jobs are added is important.
This ensures that the jobs are organized correctly to build the intended job hierarchy.
The following diagram illustrates an example of such a hierarchy, where the ``DiagJobRoot``
node is positioned at the top of the hierarchy:

.. uml:: ./runtime_diag_tree.puml

In the example provided, there are two direct children of the root job:

* `ReadDataByIdentifier` (`SID` 0x22)
* `RoutineControl` (`SID` 0x31)

with their corresponding children on lower levels of hierarchy. When processing an incoming message
(e.g., a request from a tester), the children are traversed until the child with the corresponding
`SID` is found.

Examples
++++++++

As mentioned earlier, the order in which jobs are added to the dispatcher is crucial: the parent
must be added first, followed by the children, and then the grandchildren, and so on.
**It is still possible to start adding children to a different branch of the hierarchy**;
however, it is important to ensure that the **order of adding parents and children
within the same branch of the hierarchy is maintained**.

.. code-block:: cpp
ReadDataByIdentifier readDataByIdentifier;
ReadIdentifierFromMemory _read22Cf01;
ReadIdentifierFromNvStorage _read22Cf02;
void createDispatcher(AbstractDiagnosisConfiguration& configuration,
IDiagSessionManager& sessionManager,
DiagJobRoot& jobRoot,
::async::ContextType context)
{
static DiagDispatcher2 udsDispatcher(configuration, sessionManager, jobRoot, context);
// to properly add _read22Cf01 it must be added after readDataByIdentifier!
udsDispatcher.addAbstractDiagJob(_read22Cf01); // will not be added
udsDispatcher.addAbstractDiagJob(readDataByIdentifier);
udsDispatcher.addAbstractDiagJob(_read22Cf01);
}
Properly setting up the CAN communication the ECU will respond to the messages:

.. code-block:: shell
cansend vcan0 02A#0322CF0100000000
cansend vcan0 02A#0322CF0200000000
Diagnostics Configuration
-------------------------

The ``DiagnosisConfiguration`` class is passed to the ``DiagDispatcher`` and stores key information,
including:

* The number of incoming connections
* The number of outgoing connections (usually 1)
* The maximum number of incoming messages that can be held in the queue
* The UDS address of the server (ECU)
* The bus ID
* Other important details, including boolean flags

Connection Manager
------------------

The connection manager of type ``DiagnosticSessionControl`` is another essential parameter passed to
the ``DiagDispatcher`` during its construction. This manager handles the following tasks:

* Switching between sessions
* Managing timeouts for extended sessions
* Monitoring the "Tester Present" heartbeat
9 changes: 9 additions & 0 deletions libs/bsw/uds/doc/user/index.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
User Documentation
==================

.. toctree::
:maxdepth: 1

dispatcher
connection
sessions
27 changes: 27 additions & 0 deletions libs/bsw/uds/doc/user/runtime_diag_tree.puml
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
@startwbs
' Diagnostic Tree
' Length: request_length so far
' Prefix-length: bytes checked by ancestor nodes
' cn: Node checks n-bytes
' Prefix of child node == Request length of parent node (SID bytes match)
* DiagJobRoot
** ReadDataByIdentifier 0x22
*** ReadIdentifierFromMemory 0x22
' different obj instances = different DIDs are checked;
*** ReadIdentifierFromNvStorage 0x22
' ** WriteDataByIdentifier 0x2E
' *** WriteIdentifierToMemory
' *** WriteIdentifierToNvStorage
' ** TesterPresent 0x3E
** RoutineControl 0x31
*** StartRoutine 0x31 0x01
**** RoutineControlJob 0x31 0x01 xx xx

*** StopRoutine 0x31 0x02
**** RoutineControlJobNode 0x31 0x02 xx xx
' Instance returned by RoutineControlJob::getStopRoutine();
*** RequestRoutineResults 0x31 0x03
**** RoutineControlJobNode 0x31 0x03 xx xx
' Instance returned by RoutineControlJob::getRequestRoutineResults();

@endwbs
30 changes: 30 additions & 0 deletions libs/bsw/uds/doc/user/sessions.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
.. _sessions:

Sessions
========

UDS operates through diagnostic sessions, which are states in which the ECU operates to
perform specific diagnostic or service functions.
Each session provides a different level of access to the ECU's functionality.
The ECU starts in a default session, but diagnostic tools can request transitions
to other sessions to perform specialized operations.

Types of UDS Sessions

1. Default Session (0x01), class ``ApplicationDefaultSession``.

- **Description:** This is the basic session active upon ECU startup.
- **Functionality:** Limited diagnostic services are available, primarily for querying information (e.g., ID requests, DTCs).
- **Typical Use Cases:** Basic diagnostics, reading fault codes.

2. Programming Session (0x02), class ``ProgrammingSession``.

- **Description:** Used for reprogramming the ECU firmware.
- **Functionality:** Enables downloading new software or calibration data into the ECU.
- **Typical Use Cases:** ECU flashing, firmware updates.

3. Extended Diagnostic Session (0x03), class ``ApplicationExtendedSession``.

- **Description:** Provides enhanced diagnostic functionality beyond the default session.
- **Functionality:** Includes advanced capabilities like actuator testing, detailed fault code analysis, and special function testing.
- **Typical Use Cases:** In-depth diagnostics, calibration, and testing.

0 comments on commit c4c5cf0

Please sign in to comment.