Architecture

This document describes the basic ideas behind the uSherpa firmware
architecture.

1. High-level Overview

+--------+           +-------+
|        |   PROTO   |       |
| CLIENT |<--------->|  MCU  |
|        |           |       |
+--------+           +-------+

The above figure shows the basic concept behind uSherpa. A micro-controller
(MCU) which is running the uSherpa firmware offers a defined set of
functionality to a client (CLIENT). The functionality offered are typical
things a MCU could perform. E.g. drive a digital output high/low. Read a
digital or analog input, or drive a PWM on an output.

The protocol used between the CLIENT and the MCU is by default not
depended on a particular transport. But since the first implementation of
the uSherpa firmware is based on a TI Launchpad which comes with a build
in USB-2-serial converter, using the serial line was here was obvious.

To keep the overhead for the protocol minimal, but safe at the same time a
frame based binary protocol with checksum is used. This protocol could be
implemented by different clients in different languages. By the time of
writing, a basic client implementation for Processing [TODO|link] and
Java is available. In the next sections we will have a more detailed look
on the firmware architecture. For details on the client architectures, have
a look at the documents provided by a specific client implementation.

2. Firmware Layers

+-------------------------------------------------+
|                   Firmware                      |                   
+-------------+-----------------------------------+
|             |           |                       |
|             |           +---+                   |
|transport lib| libsherpacore | special func. lib |
|             |         +-----+-----+             |
| e.g. serial |         | libpacket |             | 
+-------------------------------------------------+
|     Register definitions, Vendor APIs, ...      |
+-------------------------------------------------+
|                    Hardware                     |
+-------------------------------------------------+

The above picture shows the general layers which build a uSherpa firmware.
The base for all the layers is the hardware. On top of the hardware
a (vendor) specific library or API is used to access the registers and stuff
of a particular hardware.

1. packet

On the next level, a bunch of base libraries is located. The “libpacket”
library provides the functionality to build packets for communication with a
client. “libpacket” does not yet define, how the payload is to be build, but
it defines the packet framing (like start-byte, length, checksum).

2. core

The payload for the core uSherpa functionality then is defined by
“libsherpacore”. This library provides the core functionality provided by
every uSherpa firmware (e.g. digital read/write, PWM, …).
“libsherpacore” implements that core functionality and thus talks to the
hardware by using the layer below (register definitions, vendor APIs), and
it also knows how to expose this functionality through the uSherpa protocol
by using “libpacket” for the framing, and filling the payload according to
the provided functionality.

3. special function libraries

Beside the core functionality there other libraries may provide additional
“special” functionality (e.g. to drive a display, or a motor controller).
This “special” function libraries are also going to use “libpacket” to
provide their functionally as extension to the uSherpa protocol. If a
“special” function library is going to extend core functionality, it may
also use “libsherpacore”.

4. transport

Beside the libraries providing the functionality, there is a library
handling the protocols transport. This could e.g. be a library like
“libserial” which uses the serial line for physical transport, or library
using a Ethernet shield or a wifi shield.

5. firmware

All the parts described earlier are “glued” together by the firmware-layer.

3. Firmware Re-mixes

Since memory is limited on small devices, the idea is, that later there
will be a whole set of different firmware. Each firmware may then differ
by the transport it uses, or in the functionality it provides.

E.g. one firmware may use the serial line as transport, and offer core
functionality like digital IO, ADC and PWM. An other firmware could also use
the serial line for transport, but offer to drive a display shield through
the uSherpa protocol. Again an other firmware uses a WiFi shield connected
to SPI for communication and offers just motor control as functionality.

Thus, by using a modular (or library) based approach as described before, it
would be easy to come up with firmware “re-mixes” serving a special purpose.

4. Supporting Different Hardware

An other goal of the architecture is to clearly separate the hardware
dependent parts form the commonly usable parts. By doing so, porting the
firmware to a different hardware platform should be a fairly easy task. Thus,
each library that has hardware dependent parts separates them by providing
an isolated implementation (e.g. in a separate C file ending with the HW
arch). Then, at compile time it could be decided, which HW dependent parts
to compile and link for a particular platform.

5. Client Bindings

A client may be bound to a MCU running uSherpa firmware by implementing the
uSherpa protocol and the transport provided by that particular firmware.
Each client binding should at least implement the core functionality of the
protocol. Since the core protocol could be enhanced by “special” function
libraries, a client must always check for “unsupported function” errors
returned by the firmware if a particular functionality is not provided by that
firmware.

NOTE: While this approach works in terms of error-handling, it may not be
convenient to the client or the end-user. Thus, it may be help full to include
a command to the uSherpa core protocol which allows a client to query all
supported functions by this firmware, but this needs further thinking.

6. uSherpa Protocol

1. General Considerations

The uSherpa core protocol allows to configure a PIN into various modes
(PIN_FUNCTION). E.g. a PIN could be configured through uSherpa to be a digital
output, a digital input, a analog input, a PWM output and so on. While in
theories each PIN is able to perform each function, in reality, this is not
true. In fact, what functions a PIN is able to perform is highly hardware
dependent. For example on the MSP430G2553, not every PIN is able to perform
hardware based PWM or ADC.

An other limitation often introduced by the hardware is, that a certain function
could only be performed on a certain number of pins. Again, the hardware PWM of
the MSP4302553 is tight to the MCUs timers. By having two timers, only to
independent hardware PWM signals could be generated at a time. Anyway, this
might look different on a Cortex-M3 based MCU.

Also due to the fact, that some of the MCU resources are limited, it may happen,
that two different functions need the same resource, and thus only one of this
functions is possible at a time. For an example, we could look again at our
timers: if we offer the functionality for software UART, then this functionality
will need both timers to bit-bang the RX and TX data. Thus, when software UART
function is configured, hardware PWM is not possible at that time since the timers
are already used.

At last, there may be some PINs on the MCU which in general could perform a
certain function but are reserved for internal use. An example for this are the RX
and TX PINs used on the hardware UART when the protocol uses the serial line for
transport.

2. Requirements to the Implementation

Beside the requirement, that the function requested through the protocol is
carried out, the issues described in the section before lead to some more
requirements the protocol implementation has to fulfill:

  • The implementation MUST know which PINs are able to carry out which functions. We will call this the PIN CAPABILITIES. By knowing a PINs capabilities, the firmware then could respond with an error message (unsupported PIN function) in case a client requests a configuration for a PIN which is not possible.
  • The firmware MUST know, which resources are limited, and when they are reserved because of a requested function. We will call this the LIMITED RESOURCES. By knowing about the limited resources, and knowing which function consumes which limited resource, the firmware will be able to respond with an error (invalid PIN function) if a requested functions requires a limited resource which is already taken.
  • The firmware MUST know, which PINs are reserved for internal use. We will call this the RESERVED PINs. By knowing which PINs are reserved, the firmware could report an error (unsupported PIN function) if a client trys to configure a PIN which is not available.

Since the above requirements are highly hardware and firmware dependent, they
need to be defined individually.

NOTE: the above requirements are firmware dependent, since e.g. the reserved
PINs may change when a firmware chooses to use e.g. SPI for communication
(and not UART).

The above requirements are implemented in the firmware (and not in the client)
for the following reasons:

  • One firmware may be used by a number of clients (written in different languages). If the checkings ware done on the client side, each client needs to implement the checks again (and no two would be the same).
  • A firmware for a new hardware has to be tailored anyway. But a client library should not need to be tailored because of a new hardware.

3. Message Xfer

The normal way of communication between a client and a MCU is the xfer pattern.
When using this pattern, the client sends a uSherpa packet to the MCU, and
receives a response packet:

+--------+         +-----+
| Client |         | MCU |
+--------+         +-----+
    |    req. pkt.    |
   [|]-------------->[|]
   [|]               [|]
   [|]<--------------[|]
    |    res. pkt.    |

An example for an xfer would be a client which sends a configuration request
for PIN1.0 to be an digital output. It assembles the corresponding request
packet for that and sends it to the MCU. After that, it waits until the MCU
sends a response packet indicating success or failure.

A client using the xfer pattern needs to handle the situation where no response
comes back from the MCU. The popper way of client to handle this would be
using a timeout. I client may also consider doing a number of retrys if no
response was received:

                        (START)
                            |
                           \|/ 
                    -----------------       Yes
       +---------> /  retrys > mRT   \------------+
       |           \                 /            |
       |            -----------------             |
       |                    | No                  |
       |                   \|/                    |
       |            +----------------+            |
       |            | Send req. pkt. |            |
       |            +----------------+            |
       |                    |                     |
       |                   \|/                    |
       |      +--------------------------+        |
       |      | Wait until res. pkt.     |        |
       |      | pkt. or waited-time > wT |        |
       |      +--------------------------+        |
       |                    |                     |
       |                   \|/                    |
       |   YES      -----------------             |
       +-----------/  wait-time > wt \            |
                   \                 /            |
                    -----------------             |
                            |                     |
                           \|/                    |
                          (END)<------------------+

Using the synchronous xfer pattern makes it easy for a client to know which
response belongs to a request. Thus, it is highly recommended that a client
implementation provides functionality for this pattern.

4. Eventing

The xfer pattern described above is not suitable for all communication. For
example a client needs to know when a digital input on the MCU goes high. By
using the xfer method, the client needs to poll the MCU for the PIN state over
and over again. In the case that the high period on the PIN was very short
(shorter then the poll cycle), the client will not notice the state change.
Thus, some kind of event pattern is needed. Here, the client enables eventing
for certain events of interest on the MCU (e.g. state change on a digital input),
and then receives a event packet from the MCU at the moment the event of
interest happened. A client will only miss an event, if they occur very fast and
very often so that the buffer overflows on the MCU (which should be rarely
the case).

+--------+         +-----+
| Client |         | MCU |
+--------+         +-----+
    |    req. pkt.    |
   [|]-------------->[|]  1) Client requests to receive
   [|]               [|]     events if a certain condition 
   [|]<--------------[|]     is true on the MCU
    |    res. pkt.    |
    |                 |
    |                [|]  2) MCU reached condition
   [|]<--------------[|]     Event is fired
   [|]  event pkt.    |
    |                 |
    |                 |
    |                [|]                          
   [|]<--------------[|]                    
   [|]  event pkt.    |
    |                 |
    |                 |
    |    req. pkt.    |
   [|]-------------->[|]  3) Client requests to end 
   [|]               [|]     events for a certain condition 
   [|]<--------------[|]                        
    |    res. pkt.    |

5. Streaming

While the xfer and eventing method may suite most of the needs, there is one
more situation to consider. For example we have some kind of accelerometer
which we like to read out continuously on the client side. If we used xfer
for that, this would produce a lot of overhead since each next value from the
accelerometer needs to be requested by a new client message. Enabling events
for the accelerometer to occur every n milli-seconds would save some overhead since
the request packet will not be needed, but still has plenty of overhead as
each single value from the accelerometer is wrapped in a packet. Thus, a
streaming mode is needed. When enabled for a certain value of interest, it
will continuously send a data stream containing only that value of interest.
The stream will end at the moment a client is sending any kind of
request to the MCU.

While in streaming mode, event receiving would not be possible, since there
would be no chance to distinct between an event and the data stream.

+--------+         +-----+
| Client |         | MCU |
+--------+         +-----+
    |    req. pkt.    |
   [|]-------------->[|]  1) Client requests to receive
   [|]               [|]     a certain value as data stream 
   [|]<--------------[|]     
    |    res. pkt.    |
    |                 |
    |   data stream  [|]  2) MCU sends data stream 
   [|]<--------------[|]     
   [|]<--------------[|]
   [|]<--------------[|]
   [|]<--------------[|]
    |                [|]
    |    req. pkt.   [|]  3) Client ends stream by                         
   [|]-------------->[|]     sending request               
   [|]               [|]
   [|]<--------------[|]     
    |    res. pkt.    |

Leave a Reply

You must be logged in to post a comment.