aa78efbb5eedf64560accfb88aa42978eb5aedff
[phd-thesis.git] / top / 4iot.tex
1 \documentclass[../thesis.tex]{subfiles}
2
3 \input{subfilepreamble}
4
5 \setcounter{chapter}{2}
6
7 \begin{document}
8 \input{subfileprefix}
9 \chapter{\texorpdfstring{\Glsxtrlong{TOP} for the \glsxtrlong{IOT}}{Task-oriented programming for the internet of things}}%
10 \label{chp:top4iot}
11 \begin{chapterabstract}
12 \noindent This chapter:
13 \begin{itemize}
14 \item introduces the problems with \gls{TOP} for the \gls{IOT}.
15 \item shows how to create the \emph{Hello World!} application for microcontrollers using \gls{ARDUINO};
16 \item extends this idea with multithreading, demonstrating the difficulty programming multi-tasking applications;
17 \item describes a comparative variant in \gls{MTASK} and shows that upgrading to a multi-tasking variant is straightforward
18 \item demonstrates that the complexity of running multiple tasks;
19 \item and concludes with the history of \gls{MTASK}'s development.
20 \end{itemize}
21 \end{chapterabstract}
22
23 The edge layer of \gls{IOT} systems predominantly consists of microcontrollers.
24 Microcontrollers are tiny computers designed specifically for embedded applications.
25 They therefore only have a soup\c{c}on of memory and have a slow processor.
26 However, they also come with energy efficient sleep modes and have a lot of peripheral support such as \gls{GPIO} pins.
27 Usually, programming microcontrollers requires an elaborate multi-step toolchain of compilation, linkage, binary image creation, and burning this image onto the flash memory of the microcontroller in order to compile and run a program.
28 The programs are usually cyclic executives instead of tasks running in an operating system, i.e.\ there is only a single task that continuously runs on the bare metal.
29 \Cref{tbl:mcu_laptop} compares the hardware properties of a typical laptop with two very popular microcontrollers.
30
31 \begin{table}
32 \caption{Hardware characteristics of typical microcontrollers compared to laptops.}%
33 \label{tbl:mcu_laptop}
34 \begin{tabular}{llll}
35 \toprule
36 & Laptop & Atmega328P & ESP8266\\
37 \midrule
38 CPU speed & \qtyrange{2}{4}{\giga\hertz} & \qty{16}{\mega\hertz} & \qty{80}{\mega\hertz} or \qty{160}{\mega\hertz}\\
39 \textnumero{} cores & \numrange{4}{8} & 1 & 1\\
40 Storage & \qty{1}{\tebi\byte} & \qty{32}{\kibi\byte} & \qtyrange{0.5}{4}{\mebi\byte}\\
41 \gls{RAM} & \qtyrange{4}{16}{\gibi\byte} & \qty{2}{\kibi\byte} & \qty{160}{\kibi\byte}\\
42 Power & \qtyrange{50}{100}{\watt} & \qtyrange{0.13}{250}{\milli\watt} & \qtyrange{0.1}{350}{\milli\watt}\\
43 Size & $\pm$\qty{1060}{\cubic\cm} & $\pm$\qty{7.5}{\cubic\cm} & $\pm$\qty{1.1}{\cubic\cm}\\
44 Price & \euro{1500} & \euro{3} & \euro{4}\\
45 \bottomrule
46 \end{tabular}
47 \end{table}
48
49 Different models of microcontrollers require their own vendor-provided drivers, hardware abstraction layer, compilers and \glspl{RTS}.
50 There are many platforms that abstract away from this such as \gls{MBED} and \gls{ARDUINO}.
51 \Gls{ARDUINO} is specifically designed for education and prototyping and hence used here to show traditional microcontroller programming.
52
53 The popular \gls{ARDUINO} \ccpp{} dialect and accompanying libraries provide an abstraction layer for common microcontroller behaviour allowing the programmer to program multiple types of microcontrollers using a single language.
54 Originally it was designed for the in-house developed open-source hardware with the same name but the setup allows porting to many architectures.
55 It provides an \gls{IDE} and toolchain automation to perform all steps of the toolchain with a single command.
56
57 \section{\texorpdfstring{\Glsxtrshort{TOP} for the \glsxtrshort{IOT}}{TOP for the IoT}}
58 \Gls{TOP} is a programming paradigm that allows multi-tier systems to be generated from a single declarative source.
59 \Gls{ITASK} is a general-purpose \gls{TOP} system for programming distributed web applications.
60 These distributed web applications often form the core of \gls{IOT} applications as well but integrating these devices in \gls{ITASK} is not straightforward.
61 \Gls{ITASK} targets relatively fast but energy-hungry systems with large amounts of \gls{RAM} and a speedy connections.
62 Edge devices in \gls{IOT} systems are typically slow but energy efficient and do not have the memory to run the naturally heap-heavy functional programs that \gls{ITASK} programs are.
63 \Gls{MTASK} bridges this gap by providing a \gls{TOP} \gls{DSL} for \gls{IOT} edge devices that can, because domain-specific knowledge is embedded in the language and execution platform, run on hardware with much less memory and processor speed.
64 The following sections compare traditional microcontroller programming with programming the devices using \gls{MTASK}.
65
66 \section{Hello world!}
67 Traditionally, the first program that one writes when trying a new language is the so-called \emph{Hello World!} program.
68 This program has the single task of printing the text \emph{Hello World!} to the screen and exiting again, useful to become familiarised with the syntax and verify that the toolchain and runtime environment is working.
69 On microcontrollers, there usually is no screen for displaying text.
70 Nevertheless, almost always there is a built-in monochrome $1\times1$ pixel screen, namely \pgls{LED}.
71 The \emph{Hello World!} equivalent on microcontrollers blinks this \gls{LED}.
72
73 \Cref{lst:arduinoBlink} shows how the logic of a blink program might look when using \gls{ARDUINO}'s \ccpp{} dialect.
74 Every \gls{ARDUINO} program contains a \arduinoinline{setup} and a \arduinoinline{loop} function.
75 The \arduinoinline{setup} function is executed only once on boot, the \arduinoinline{loop} function is continuously called afterwards and contains the event loop.
76 After setting the \gls{GPIO} pin to the correct mode, blink's \arduinoinline{loop} function alternates the state of the pin representing the \gls{LED} between \arduinoinline{HIGH} and \arduinoinline{LOW}, turning the \gls{LED} off and on respectively.
77 In between it waits for \qty{500}{\ms} so that the blinking is actually visible for the human eye.
78
79 Translating the traditional blink program to \gls{MTASK} can almost be done by simply substituting some syntax as seen in \cref{lst:blinkImp}.
80 E.g.\ \arduinoinline{digitalWrite} becomes \cleaninline{writeD}, literals are prefixed with \cleaninline{lit} and the pin to blink is changed to represent the actual pin for the builtin \gls{LED} of the device used in the exercises.
81 In contrast to the imperative \gls{CPP} dialect, \gls{MTASK} is a \gls{TOP} language and therefore there is no such thing as a loop, only task combinators to combine tasks.
82 To simulate a loop, the \cleaninline{rpeat} task combinator can be used as this task combinator executes the argument task and, when stable, reinstates it.
83 The body of the \cleaninline{rpeat} contains similarly named tasks to write to the pins and to wait in between.
84 The tasks are connected using the sequential \cleaninline{>>|.} combinator that for all current intents and purposes executes the tasks after each other.
85
86 \begin{figure}[ht]
87 \begin{subfigure}[b]{.5\linewidth}
88 \begin{lstArduino}[caption={Blink program.},label={lst:arduinoBlink}]
89 void setup() {
90 pinMode(D2, OUTPUT);
91 }
92
93 void loop() {
94 digitalWrite(D2, HIGH);
95 delay(500);
96 digitalWrite(D2, LOW);
97 delay(500);
98 }\end{lstArduino}
99 \end{subfigure}%
100 \begin{subfigure}[b]{.5\linewidth}
101 \begin{lstClean}[caption={Blink program.},label={lst:blinkImp}]
102 blink :: Main (MTask v ()) | mtask v
103 blink =
104 declarePin D2 PMOutput \d2->
105 {main = rpeat (
106 writeD d2 true
107 >>|. delay (lit 500)
108 >>|. writeD d2 false
109 >>|. delay (lit 500)
110 )
111 }\end{lstClean}
112 \end{subfigure}
113 \end{figure}
114
115 \section{Multi tasking}
116 Now say that we want to blink multiple blinking patterns on different \glspl{LED} concurrently.
117 For example, blink three \glspl{LED} connected to \gls{GPIO} pins $1,2$ and $3$ at intervals of \qtylist{500;300;800}{\ms}.
118 Intuitively you want to lift the blinking behaviour to a function and call this function three times with different parameters as done in \cref{lst:blinkthreadno}
119
120 \begin{lstArduino}[caption={Naive approach to multiple blinking patterns.},label={lst:blinkthreadno}]
121 void setup () { ... }
122
123 void blink (int pin, int wait) {
124 digitalWrite(pin, HIGH);
125 delay(wait);
126 digitalWrite(pin, LOW);
127 delay(wait);
128 }
129
130 void loop() {
131 blink (D1, 500);
132 blink (D2, 300);
133 blink (D3, 800);
134 }\end{lstArduino}
135
136 Unfortunately, this does not work because the \arduinoinline{delay} function blocks all further execution.
137 The resulting program will blink the \glspl{LED} after each other instead of at the same time.
138 To overcome this, it is necessary to slice up the blinking behaviour in very small fragments so it can be manually interleaved \citep{feijs_multi-tasking_2013}.
139 Listing~\ref{lst:blinkthread} shows how three different blinking patterns might be achieved in \gls{ARDUINO} using the slicing method.
140 If we want the blink function to be a separate parametrizable function we need to explicitly provide all references to the required state.
141 Furthermore, the \arduinoinline{delay} function can not be used and polling \arduinoinline{millis} is required.
142 The \arduinoinline{millis} function returns the number of milliseconds that have passed since the boot of the microcontroller.
143 Some devices use very little energy when in \arduinoinline{delay} or sleep state.
144 Resulting in \arduinoinline{millis} potentially affects power consumption since the processor is basically busy looping all the time.
145 In the simple case of blinking three \glspl{LED} on fixed intervals, it might be possible to calculate the delays in advance using static analysis and generate the appropriate \arduinoinline{delay} code.
146 Unfortunately, this is very hard when for example the blinking patterns are determined at runtime.
147
148 \begin{lstArduino}[label={lst:blinkthread},caption={Threading three blinking patterns.}]
149 long led1 = 0, led2 = 0, led3 = 0;
150 bool st1 = false, st2 = false, st3 = false;
151
152 void blink(int pin, int interval, long *lastrun, bool *st) {
153 if (millis() - *lastrun > interval) {
154 digitalWrite(pin, *st = !*st);
155 *lastrun += interval;
156 }
157 }
158
159 void loop() {
160 blink(D1, 500, &led1, &st1);
161 blink(D2, 300, &led2, &st1);
162 blink(D3, 800, &led3, &st1);
163 }\end{lstArduino}
164
165 This method is very error prone, requires a lot of pointer juggling and generally results into spaghetti code.
166 Furthermore, it is very difficult to represent dependencies between threads, often state machines have to be explicitly programmed by hand to achieve this.
167
168 \subsection{Multi tasking in \texorpdfstring{\gls{MTASK}}{mTask}}
169 The \cleaninline{delay} \emph{task} does not block the execution but \emph{just} emits no value when the target waiting time has not yet passed and emits a stable value when the time is met.
170 In contrast, the \arduinoinline{delay()} \emph{function} on the \gls{ARDUINO} is blocking which prohibits interleaving.
171 To make code reuse possible and make the implementation more intuitive, the blinking behaviour is lifted to a recursive function instead of using the imperative \cleaninline{rpeat} construct.
172 The function is parametrized with the current state, the pin to blink and the waiting time.
173 Creating recursive functions like this is not possible in the \gls{ARDUINO} language because the program would run out of stack in an instant and nothing can be interleaved.
174 With a parallel combinator, tasks can be executed in an interleaved fashion.
175 Therefore, blinking three different blinking patterns is as simple as combining the three calls to the \cleaninline{blink} function with their arguments as seen in \cref{lst:blinkthreadmtask}.
176
177 % VimTeX: SynIgnore on
178 \begin{lstClean}[label={lst:blinkthreadmtask},caption={Threaded blinking.}]
179 blinktask :: MTask v () | mtask v
180 blinktask =
181 declarePin D1 PMOutput \d1->
182 declarePin D2 PMOutput \d2->
183 declarePin D3 PMOutput \d3->
184 fun \blink=(\(st, pin, wait)->
185 delay wait
186 >>|. writeD d13 st
187 >>|. blink (Not st, pin, wait))
188 In {main =
189 blink (true, d1, lit 500)
190 .||. blink (true, d2, lit 300)
191 .||. blink (true, d3, lit 800)
192 }
193 \end{lstClean}
194 % VimTeX: SynIgnore off
195
196 \section{Conclusion}
197 The edge layer of \gls{IOT} systems is powered by microcontrollers.
198 Programming them happens through compiled firmwares using low-level imperative programming languages.
199 Due to the lack of an \gls{OS}, writing applications that perform multiple tasks at the same time is error prone, and complex; and requires a lot of boilerplate and manual scheduling code.
200 With the \gls{MTASK} system, a \gls{TOP} programming language for \gls{IOT} edge devices, this limitation can be overcome.
201 \todo{uit\-breiden}
202
203 \begin{subappendices}
204 \section{History of \texorpdfstring{\gls{MTASK}}{mTask}}
205 The development of \gls{MTASK} or its predecessors has been going on for almost seven years now though it really set off during my master's thesis.
206 This section provides an exhaustive overview of the work on \gls{MTASK} and its predecessors.
207
208 \subsection*{Generating \texorpdfstring{\ccpp{}}{\ccpp{}} code}
209 A first throw at a class-based shallowly \gls{EDSL} for microcontrollers was made by \citet{plasmeijer_shallow_2016}.
210 The language was called \gls{ARDSL} and offered a type safe interface to \gls{ARDUINO} \gls{CPP} dialect.
211 A \gls{CPP} code generation backend was available together with an \gls{ITASK} simulation backend.
212 There was no support for tasks nor even functions.
213 Some time later in the 2015 \gls{CEFP} summer school, an extended version was created that allowed the creation of imperative tasks, local \glspl{SDS} and the usage of functions \citep{koopman_type-safe_2019}.
214 The name then changed from \gls{ARDSL} to \gls{MTASK}.
215
216 \subsection*{Integration with \texorpdfstring{\gls{ITASK}}{iTask}}
217 \Citet{lubbers_task_2017} extended this in his Master's Thesis by adding integration with \gls{ITASK} and a bytecode compiler to the language.
218 \Gls{SDS} in \gls{MTASK} could be accessed on the \gls{ITASK} server.
219 In this way, entire \gls{IOT} systems could be programmed from a single source.
220 However, this version used a simplified version of \gls{MTASK} without functions.
221 This was later improved upon by creating a simplified interface where \glspl{SDS} from \gls{ITASK} could be used in \gls{MTASK} and the other way around \citep{lubbers_task_2018}.
222 It was shown by \citet{amazonas_cabral_de_andrade_developing_2018} that it was possible to build real-life \gls{IOT} systems with this integration.
223 Moreover, a course on the \gls{MTASK} simulator was provided at the 2018 \gls{CEFP}\slash\gls{3COWS} winter school in Ko\v{s}ice, Slovakia \citep{koopman_simulation_2018}.
224
225 \subsection*{Transition to \texorpdfstring{\gls{TOP}}{TOP}}
226 The \gls{MTASK} language as it is now was introduced in 2018 \citep{koopman_task-based_2018}.
227 This paper updated the language to support functions, simple tasks, and \glspl{SDS} but still compiled to \gls{ARDUINO} \gls{CPP} code.
228 Later the byte code compiler and \gls{ITASK} integration was added to the language \citep{lubbers_interpreting_2019}.
229 Moreover, it was shown that it is very intuitive to write microcontroller applications in a \gls{TOP} language \citep{lubbers_multitasking_2019}.
230 One reason for this is that a lot of design patterns that are difficult using standard means are for free in \gls{TOP} (e.g.\ multithreading).
231 In 2019, the \gls{CEFP}\slash\gls{3COWS} summer school in Budapest, Hungary hosted a course on developing \gls{IOT} applications with \gls{MTASK} as well \citep{lubbers_writing_2019}.
232
233 \subsection*{\texorpdfstring{\Glsxtrshort{TOP}}{TOP}}
234 In 2022, the SusTrainable summer school in Rijeka, Croatia hosted a course on developing greener \gls{IOT} applications using \gls{MTASK} as well \citep{lubbers_green_2022}.
235 Several students worked on extending \gls{MTASK} with many useful features:
236 \Citet{van_der_veen_mutable_2020} did preliminary work on a green computing analysis, built a simulator, and explored the possibilities for adding bounded datatypes; \citet{de_boer_secure_2020} investigated the possibilities for secure communication channels; \citeauthor{crooijmans_reducing_2021} \citeyearpar{crooijmans_reducing_2021,crooijmans_reducing_2022} added abstractions for low-power operation to \gls{MTASK} such as hardware interrupts and power efficient scheduling; and \citet{antonova_mtask_2022} defined a preliminary formal semantics for a subset of \gls{MTASK}.
237
238 \subsection*{\texorpdfstring{\gls{MTASK}}{mTask} in practise}
239 Funded by the Radboud-Glasgow Collaboration Fund, collaborative work was executed with Phil Trinder, Jeremy Singer, and Adrian Ravi Kishore Ramsingh.
240 An existing smart campus application was developed using \gls{MTASK} and quantitively and qualitatively compared to the original application that was developed using a traditional \gls{IOT} stack \citep{lubbers_tiered_2020}.
241 This research was later extended to include a four-way comparison: \gls{PYTHON}, \gls{MICROPYTHON}, \gls{ITASK}, and \gls{MTASK} \citep{lubbers_could_2022}.
242 Currently, power efficiency behaviour of traditional versus \gls{TOP} \gls{IOT} stacks is being compared as well adding a \gls{FREERTOS} implementation to the mix as well.
243
244 \subsection*{Future work}
245 Plans for extensions and improvements include exploring integrating \gls{TINYML} into \gls{MTASK}; adding intermittent computing support to \gls{MTASK}; and extending the formal semantics to cover the entirety of the language.
246 In 2023, the SusTrainable summer school in Coimbra, Portugal will host a course on \gls{MTASK} as well.
247
248 \end{subappendices}
249
250 \input{subfilepostamble}
251 \end{document}