GEX thesis source code, full text, references
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
gex-thesis/ch.fw_structure.tex

122 lines
11 KiB

6 years ago
\chapter{Internal Application Structure} \label{sec:coreframework}
6 years ago
6 years ago
The firmware is built around a \textit{core framework} which provides services to units, such as the settings storage, resource allocation, message delivery, and periodic updates. In this chapter, we will focus on the structure of this framework and the services provided by it.
6 years ago
\begin{figure}[h]
\centering
\includegraphics[width=\textwidth] {img/gex-internal.pdf}
\caption{\label{fig:gex_internal}Block diagram showing the internal logic in the GEX firmware}
6 years ago
\end{figure}
6 years ago
\section{Internal Structure Block Diagram}
The data flows and other internal logic of the firmware are depicted in \cref{fig:gex_internal}, with more explanation following in this chapter. The interchangeable role of the three communication interfaces can be clearly seen in the diagram, as well as the central role of the message queue, which decouples interrupts from the processing thread.
6 years ago
\noindent
The framework provides the following services to units:
6 years ago
\begin{itemize}[itemsep=0pt]
6 years ago
\item Hardware resource allocation (\cref{sec:res_allocation})
\item Settings storage and loading (\cref{sec:settings_storage})
\item Unit life cycle management (\cref{sec:units_function})
6 years ago
\item Message sending and delivery (\cref{sec:message_passing})
6 years ago
\item Interrupt routing (\cref{sec:irq_routing})
6 years ago
\end{itemize}
6 years ago
\section{Unit Life Cycle and Internal Structure} \label{sec:units_function}
GEX's user-facing functions, units, are implemented in \textit{unit drivers}. These are independent modules in the firmware that the user can enable and configure, in one or more instances. In practice, we are limited by hardware constraints: i.e., there may be only one \gls{ADC} peripheral, or two \gls{SPI} ports. The assignment of those hardware resources to units is handled by the \textit{resource registry} (\cref{sec:res_allocation}).
6 years ago
Each unit is identified by a name and a \textit{callsign}, which is a number that serves as an address for message delivery. A unit is internally stored as a data object with the following structure:
\begin{itemize}[itemsep=0pt]
\item Name
6 years ago
\item Callsign (one byte)
\item Configuration parameters loaded from the unit settings
\item State variables updated at run-time by user commands or internal functions
\item A reference to the unit driver
\end{itemize}
6 years ago
The unit driver handles commands sent from the host \gls{PC}, initializes and de-initializes the unit based on its settings, and implements other aspects of its function, such as periodic updates and interrupt handling.
6 years ago
6 years ago
When the units configuration file is modified, all units are de-initialized and removed. The binary settings are then updated based on the new values, verifying that the requested resources are available, and the units that can be enabled are subsequently initialized and made available to the user.
6 years ago
6 years ago
\section{Resource Allocation} \label{sec:res_allocation}
6 years ago
\begin{figure}[h]
\centering
\includegraphics[scale=1] {img/resource-repository.pdf}
6 years ago
\caption{\label{fig:resource_repository}An example allocation in the resource registry}
\end{figure}
6 years ago
6 years ago
The microcontroller provides a number of hardware resources that require exclusive access: GPIO pins, peripheral blocks (\gls{SPI}, \gls{I2C}, \gls{UART}\textellipsis), and \gls{DMA} channels. If two units tried to control the same pin, the results would be unpredictable; similarly, the output of a multiply-accessed serial port could become a useless mix of the different data streams.
6 years ago
6 years ago
To prevent multiple access, the firmware includes a \textit{resource registry} (\cref{fig:resource_repository}). Each individual resource is represented by a field in a resource table together with its owner's callsign. Initially all resources are free, except for those not available on the particular platform (e.g., a \gls{GPIO} pin PD1 may be disabled if not present on the microcontroller's package).
6 years ago
The resources used by the core framework are taken by a virtual unit \verb|SYSTEM| on start-up to prevent conflicts with the user's units. This is the case of the status \gls{LED}, the Lock button, \gls{USB} pins, the communication \gls{UART}, the pins and an \gls{SPI} peripheral connecting the wireless module, pins used for the crystal oscillator, and the timer/counter which provides the system timebase.
6 years ago
\section{Settings Storage} \label{sec:settings_storage}
6 years ago
\begin{figure}[h]
\centering
6 years ago
\includegraphics[scale=1.2] {img/settings-storage.pdf}
\caption{\label{fig:settings_storage}Structure of the settings subsystem}
\end{figure}
6 years ago
The system and unit settings are stored, in a binary form, in designated pages of the microcontroller's flash memory. The serialization and parsing of unit settings is implemented by the respective unit drivers. \Cref{fig:settings_storage} shows the organization of the settings subsystem; note that the ``Settings manager'' block has been omitted in \cref{fig:gex_internal} for clarity, to better represent the data flows.
6 years ago
The settings persist in the flash memory even after a firmware update, which might add or remove some data fields, or otherwise rearrange the binary structure. Assuming the general layout remains unchanged, this mainly concerns the data areas holding unit (and system) settings. Backward compatibility is achieved by prefixing each storage area with its version number. When the settings are loaded by an updated firmware, it always first checks the version field and decides which format to use to parse the saved data.
6 years ago
6 years ago
\iffalse
The INI files, which can be edited through the communication \gls{API} or using a text editor through the virtual mass storage, are parsed and generated on demand and are never stored in the Flash or \gls{RAM}, other than in short temporary buffers. The INI parser processes the byte stream on-the-fly as it is received, and a similar method is used to build a INI file from the configured units and system settings. \fi % said elsewhere
6 years ago
6 years ago
\section{Message Passing} \label{sec:message_passing}
6 years ago
One of the key functions of the core framework is to deliver messages from the host \gls{PC} to the right units. The \textit{TinyFrame} protocol is used, described in detail in \cref{sec:tinyframe}; it is represented by the ``TinyFrame Parser'' and ``TinyFrame Builder'' blocks in \cref{fig:gex_internal}\footnote{The framing library is not split into those two blocks in the source code, but the parts are functionally independent}.
6 years ago
6 years ago
Two groups of messages exist: \textit{system messages} and \textit{unit messages}. System messages can, for instance, access the INI files, or request a list of available units. Unit messages are addressed to a particular unit, and their payload format is defined by the unit's driver. An incoming message is inspected and delivered to the appropriate recipient, or responded to with an error message.
6 years ago
6 years ago
In addition to message delivery, the core framework also provides event reporting. Events are messages generated by units and sent to the host to notify it about asynchronous events.
6 years ago
6 years ago
This high-level functionality resides above the framing protocol, which will be described in \cref{sec:tinyframe}. The message format is shown in \cref{sec:unit_requests_reports}.
6 years ago
6 years ago
\section{Interrupt Routing} \label{sec:irq_routing}
6 years ago
6 years ago
Interrupts are an important part of almost any embedded application. They provide a way to rapidly react to asynchronous external or internal events, temporarily leaving the main program, jumping to an interrupt handler routine, and then returning back after the event is handled. Interrupts are also the way FreeRTOS implements multitasking without a multi-core processor.
6 years ago
6 years ago
In \arm Cortex-M0 the interrupt handlers table, defining which routine is called for which interrupt, is stored in the program memory and cannot be changed at run-time. This is a complication for the modular structure of GEX where different unit drivers may use the same peripheral, and we would want to dynamically assign the interrupt handlers based on the active configuration.
6 years ago
Let us have a look at a sample interrupt handler, in this case serving four different \gls{DMA} channels, as is common in STM32 microcontrollers:
6 years ago
\begin{ccode}
void DMA1_Channel4_5_6_7_IRQHandler(void)
{
if (LL_DMA_IsActiveFlag_GI4(DMA1)) { /* handle DMA1 channel 4 */ }
if (LL_DMA_IsActiveFlag_GI5(DMA1)) { /* handle DMA1 channel 5 */ }
if (LL_DMA_IsActiveFlag_GI6(DMA1)) { /* handle DMA1 channel 6 */ }
if (LL_DMA_IsActiveFlag_GI7(DMA1)) { /* handle DMA1 channel 7 */ }
}
6 years ago
\end{ccode}
It is evident that multiple units might need to use the same handler, even at the same time, since each \gls{DMA} channel is configured, and works, independently. GEX implements a redirection scheme to accomplish such interrupt sharing: all interrupt handlers are defined in one place, accompanied by a table of function pointers. When a unit driver wants to register an interrupt handler, it stores a pointer to it in this redirection table. Then, once an interrupt is invoked, the common handler checks the corresponding entry in the table and calls the referenced routine, if any. Conversely, when a unit driver de-initializes a unit, it removes all interrupt handlers it used, freeing the redirection table slots for other use.
6 years ago
6 years ago
\section{FreeRTOS Synchronization Objects Usage} \label{sec:rtos_in_gex}
The firmware is built around FreeRTOS (\cref{sec:freertos}) and uses a number of its synchronization objects and patterns to make the operation more robust.
\subsection{Message and Job Queue}
The message and job queue, shown in \cref{fig:gex_internal}, is used to decouple asynchronous interrupts from message transmission. All three communication interfaces use interrupts for the asynchronous handling of incoming messages. The same interrupt handler receives an event after a transmission was completed. The queue ensures that messages can be received during the transmission of a large response that demands the use of multiple messages.
\subsection{Lock Objects}
6 years ago
The ``transmission complete'' interrupt signals the readiness to transmit more data to the message-sending task using a binary semaphore. This semaphore is taken by the task before sending a block of data, and released by the \gls{ISR}, ensuring that the task waits for the transmission to complete before attempting to send more data.
6 years ago
Two mutexes are used in the firmware: one that guards access to the TinyFrame Builder until the previous message was fully transmitted, and one to guard a shared memory buffer (reused in several places to save memory and avoid its re-allocation). The hardware resource registry (explained in \cref{sec:res_allocation}) does not need mutexes for individual resources, as concurrent access to those fields can never happen thanks to the way the system is organized; resources are always taken or released sequentially by the same task.