From ebab80fc256101c7c9e4b51f3c5d12c1763d21d7 Mon Sep 17 00:00:00 2001 From: Mart Lubbers Date: Fri, 23 Jun 2017 17:28:27 +0200 Subject: [PATCH] Sweeping through the archg --- results.arch.tex | 162 +++++++++++++++++++++++++++++++++-------------- 1 file changed, 116 insertions(+), 46 deletions(-) diff --git a/results.arch.tex b/results.arch.tex index dda1247..0573033 100644 --- a/results.arch.tex +++ b/results.arch.tex @@ -1,81 +1,151 @@ -\section{Overview \& Terminology} -The goal of the architecture is to facilitate an ecosystem in which an +The goal of the total system is to facilitate an ecosystem in which an \gls{iTasks}-system can add, change and remove devices at runtime. Moreover, the \gls{iTasks}-system can send \glspl{mTask} --- compiled at runtime to -bytecode --- to the device. The device runs an interpreter which can execute -the \gls{Task}'s bytecode. Devices are persistent during reboots of the -\gls{iTasks}-system. The methods of interacting with \glspl{mTask} is analogous -to interacting with \gls{iTasks}-\glspl{Task} and programmers can access the -\glspl{SDS} made for a device in the same way as a regular \glspl{SDS}. The -following terms will be used throughout the architecture description. - +bytecode by the \gls{mTask}-view --- to the device. The device runs an +interpreter which can execute the \gls{Task}'s bytecode. Device profiles should +be persistent during reboots of the \gls{iTasks}-system. The methods of +interacting with \glspl{mTask} should be analogous to interacting with +\gls{iTasks}-\glspl{Task}. Meaning that programmers can access the \glspl{SDS} +made for a device in the same way as a regular \gls{SDS} and they can execute +\glspl{mTask} as if it where a normal \gls{iTasks}-\gls{Task}. + +The following terms will be used throughout the following chapter: \begin{itemize} \item Device, Client - This is the actual device connected to the system. This can be a real - device such as a microcontroller but it can also just be a program on - the same machine as the server. + This denotes the actual device connected to the system. This can be a + real device such as a microcontroller but it can also just be a program + on the same machine as the server functioning as a client. \item Server, \gls{iTasks}-System - The actual executable serving the \gls{iTasks} application. The system - will contain \glspl{Task} taking care of the communication with the + This is the actual executable serving the \gls{iTasks} application. The + system contains \glspl{Task} taking care of the communication with the clients. \item System - The complete ecosystem, thus containing both the server and client - programs. + The system describes the complete ecosystem, containing both the server + and the clients including the communication between them. \item Engine - The runtime system of the client. This program handles the - communication with the server and interprets the \glspl{Task}. + The runtime system of the client is called the engine. This program + handles communicating with the server and runs the interpreter for the + \glspl{Task} on the client. \end{itemize} \section{Devices} -The engine for the devices is compiled from one codebase. For a device to -be eligible for \glspl{mTask}, it must be able to compile the shared codebase -and implement (part of) the device specific interface. The shared codebase only -uses standard \gls{C} and no special libraries or tricks are used. Therefore -the code is compilable for almost any device or system. Note that it is not -needed to implement a full interface. The full interface --- excluding the -device specific settings --- is listed in Appendix~\ref{app:device-interface}. -The interface works in a similar fashion as the \gls{EDSL}. Devices do not have -to implement all functionality, this is analogous to the fact that views do not -have to implement all type classes in the \gls{EDSL}. When the device connects -for the first time with a server the specifications of what is implemented is +A device is suitable for the system if it can run the engine. +The engine is compiled from one codebase and devices implement (part of) the +device specific interface. The shared codebase only uses standard \gls{C} and +no special libraries or tricks are used. Therefore, the code is compilable for +almost any device or system. Note that it is not needed to implement a full +interface. The full interface --- excluding the device specific settings --- is +listed in Appendix~\ref{app:device-interface}. The interface works in a +similar fashion as the \gls{EDSL}. Devices do not have to implement all +functionality, this is analogous to the fact that views do not have to +implement all type classes in the \gls{EDSL}. When the device connects for the +first time with a server the specifications of what is implemented is communicated. At the time of writing the following device families are supported and can run the device software. \begin{itemize} - \item \texttt{POSIX} compatible systems + \item \texttt{POSIX} compatible systems connected via \gls{TCP}. This includes systems running \emph{Linux} and \emph{MacOS}. - \item \texttt{STM32} family microcontrollers supported by \texttt{ChibiOS}. + \item \texttt{STM32} family microcontrollers supported by \texttt{ChibiOS} + connected via serial communication. This is tested in particular on the \texttt{STM32f7x} series \gls{ARM} development board. - \item Microcontrollers who are programmable in the \gls{Arduino} \gls{IDE}.\\ + \item Microcontrollers who are programmable in the \gls{Arduino} \gls{IDE} + connected via serial communication or via \gls{TCP} over WiFi. This does not only include \gls{Arduino} compatible boards but also - other boards capable of running \gls{Arduino} code. The code - has been found working on the \texttt{ESP8266} powered \emph{NodeMCU}. - It is tested on devices as small as the regular \gls{Arduino} - \emph{UNO} board that only boasts a meager \emph{2K} of \emph{RAM}. + other boards capable of running \gls{Arduino} code. A port of the + client has been made for the \texttt{ESP8266} powered \emph{NodeMCU} + that is connected via \gls{TCP} over WiFi. A port also has been made + for the regular \gls{Arduino} \emph{UNO} board which only boasts a + meager \emph{2K} of \emph{RAM}. The stack size and storage for such + small amount of \emph{RAM} have to be smaller than default but it still + suitable to hold a hand full of \glspl{Task}. \end{itemize} -\subsection{Interpreter} -\todo{Structuur} -The client contains an interpreter to execute a \gls{Task}'s bytecode. +\subsection{Client} +\subsubsection*{Engine} +The client is in a constant loop listening for input and waiting to execute +\gls{Task}. The pseudocode for this is shown in Algorithm~\ref{alg:client}. + +\todo{make algorithm} +\begin{algorithm}[H] + \KwData{\textbf{stack} stack, \textbf{time} $t, t_p$} + + $t\leftarrow\text{now}()$\; + \Begin{ + \While{true}{ + $t_p\leftarrow t$\; + $t\leftarrow\text{now}()$\; + \If{notEmpty$($queue$)$}{ + $task\leftarrow \text{queue.pop}()$\; + $task$.wait $\leftarrow task$.wait $-(t-t_p)$\; + \eIf{$task.wait>t_0$}{ + queue.append$(task)$\; + }{ + run\_task$(task)$\; + } + } + } + } + \caption{Engine pseudocode}\label{alg:client} +\end{algorithm} + +\subsubsection*{Storage} +\glspl{Task} and \glspl{SDS} are stored on the client in one big memory space +that is fully allocated at the start of the program. The space could also have +been dynamically allocated but that would require using the heap which is +unwanted in small memory environments. \Glspl{Task} grow from the bottom up +and \glspl{SDS} grow from the top down. When a \gls{Task} or \gls{SDS} is +removed, all \glspl{Task} are relocated in the memory space to not leave +holes. Both \glspl{Task} and \glspl{SDS} are stored as structs and helper +functions are available to loop through them without having to fiddle in the +memory space. The instance for \glspl{Task} and \glspl{SDS} are shown in +Listing~\ref{lst:structs} accompanied by the helper functions for \glspl{Task}. +\Glspl{Task} consist the length, interval, last run time, id and the bytecode. +\Glspl{SDS} consist just of an id, value and type. The pointer to the bytecode +of the \gls{Task} always points to the location in the memory space. + +\begin{lstlisting}[language=C,label={lst:structs},% + caption={The data type storing the \glspl{Task}}] +struct task { + uint16_t tasklength; + uint16_t interval; + unsigned long lastrun; + uint8_t taskid; + uint8_t *bc; +}; + +struct task *task_head(void); +struct task *task_next(struct task *t); + +struct sds { + int id; + int value; + char type; +}; + +struct sds *sds_head(void); +struct sds *sds_next(struct sds *s); +\end{lstlisting} -Before execution some preparatory work is done. The stack will be initialized -and the program counter and stack pointer are set to zero and the bottom -respectively. Then, the interpreter executes one step at the time while the -program counter is smaller than the program length. The code for this is listed -in Listing~\ref{lst:interpr}. One execution step is basically a big switch +\subsubsection*{Interpretation} +Execution of a \gls{Task} always start with prepared the stack and the program +counter and stack pointer are set to zero and the bottom respectively. When +finished, the interpreter executes one step at the time while the program +counter is smaller than the program length. The code for this is listed in +Listing~\ref{lst:interpr}. One execution step is basically a big switch statement going over all possible bytecode instructions. Some instructions are detailed upon in the listing. The \CI{BCPush} instruction is a little more -complicated in real life because some decoding will take place as not all -\CI{BCValue}'s are of the same length. +complicated in the real code because some decoding will take place as not all +\CI{BCValue}'s are of the same length and are encoded. \begin{lstlisting}[language=C,label={lst:interpr},% caption={Rough code outline for interpretation}] -- 2.20.1