proc 0-3
[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 This chapter compares traditional edge device programming to \gls{TOP} by:
13 \begin{itemize}
14 \item introducing edge device programming;
15 \item showing how to create the \emph{Hello World!} application for microcontrollers using \gls{ARDUINO} and \gls{MTASK};
16 \item extending the idea to multithreading, uncovering problems using \gls{ARDUINO};
17 \item and demonstrating that upgrading to a multi-tasking variant is straightforward using \gls{MTASK}.
18 \end{itemize}
19 \end{chapterabstract}
20
21 The edge layer of \gls{IOT} systems predominantly consists of microcontrollers.
22 Microcontrollers are tiny computers designed specifically for embedded applications that much from regular computers in all aspects.
23 They are much smaller; only have a fraction of the memory and processor speed; and run on different architectures.
24 However, they have much more energy-efficient sleep modes, and support connecting and interfacing with peripherals such as sensors and actuators.
25 \Cref{tbl:mcu_laptop} compares the hardware properties of a typical laptop with two very popular microcontrollers.
26 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 run a program.
27 The programs are usually cyclic executives instead of tasks running in an \gls{OS}, i.e.\ there is only a single all-encompassing task that continuously runs on the bare metal.
28 Hence, all tasks must be manually combined into a single program.
29
30 \begin{table}
31 \caption{Hardware characteristics of typical microcontrollers and a laptop.}%
32 \label{tbl:mcu_laptop}
33 \centering
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 To structure this jungle of tools, platforms exist that provide abstraction layers over the low-level toolchains such as \gls{ARDUINO}.
51 It is specifically designed for education and prototyping and hence used here to illustrate traditional microcontroller programming.
52 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.
53 Originally it was designed for the in-house developed open-source hardware with the same name but the setup allows porting to many architectures by vendor-provided \emph{cores}.
54 It provides an \gls{IDE} and toolchain automation to perform all steps of the toolchain with a single command.
55
56 \section{\texorpdfstring{\Glsxtrshort{TOP} for the \glsxtrshort{IOT}}{TOP for the IoT}}
57 \Gls{TOP} is a programming paradigm that allows multi-tier interactive systems to be generated from a single declarative source.
58 \Gls{ITASK} is a general-purpose \gls{TOP} system for programming interactive distributed web applications.
59 These distributed web applications often form the core of the top two layers of \gls{IOT} applications.
60 Integrating the perception layer, the edge devices, in \gls{ITASK} also is not straightforward.
61 \Gls{ITASK} targets relatively fast but energy-hungry systems with large amounts of \gls{RAM} and a speedy connection.
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.
64 Domain-specific knowledge is embedded in the language and execution platform, drastically lowering the hardware requirements.
65 The following sections compare traditional microcontroller programming with programming the devices using \gls{MTASK}.
66
67 \section{Hello world!}
68 Traditionally, the first program that one writes when trying a new language is the so-called \emph{Hello World!} program.
69 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.
70 Microcontrollers usually do not come with screens in the traditional sense.
71 Nevertheless, almost always there is a built-in monochrome \numproduct{1x1} pixel screen, namely the built-in \gls{LED}. %chktex 29
72 The \emph{Hello World!} equivalent on microcontrollers blinks this \gls{LED}.
73
74 Using \gls{ARDUINO}'s \ccpp{} dialect to create the blink program results in the code seen in \citelisting{\ref{lst:arduinoBlink}}.
75 \Gls{ARDUINO} programs are implemented as cyclic executives and hence, each program defines a \arduinoinline{setup} and a \arduinoinline{loop} function.
76 The \arduinoinline{setup} function is executed only once on boot, the \arduinoinline{loop} function is continuously called afterwards and contains the event loop.
77 In the blink example, the \arduinoinline{setup} function only contains code for setting the \gls{GPIO} pin to the correct mode.
78 The \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.
79 In between, it waits \qty{500}{\ms} so that the blinking is actually visible for the human eye.
80
81 \begin{lstArduino}[caption={Blinking an \gls{LED}.},label={lst:arduinoBlink}]
82 void setup() {
83 pinMode(D2, OUTPUT);
84 }
85
86 void loop() {
87 digitalWrite(D2, HIGH);
88 delay(500);
89 digitalWrite(D2, LOW);
90 delay(500);
91 }\end{lstArduino}
92
93 \subsection{Blinking the \texorpdfstring{\glsxtrshort{LED}}{LED} in \texorpdfstring{\gls{MTASK}}{mTask}.}
94 Naively translating the traditional blink program to \gls{MTASK} can be done by simply substituting some syntax as seen in \citelisting{\ref{lst:blinkImp}}.
95 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.
96 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.
97 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.
98 The body of the \cleaninline{rpeat} contains similarly named tasks to write to the pins and to wait in between.
99 The tasks are connected using the sequential \cleaninline{>>|.} combinator that for all current intents and purposes executes the tasks after each other.
100 \begin{lstClean}[caption={Blinking the \gls{LED}.},label={lst:blinkImp}]
101 blink :: Main (MTask v ()) | mtask v
102 blink =
103 declarePin D2 PMOutput \d2->
104 {main = rpeat (
105 writeD d2 true
106 >>|. delay (lit 500)
107 >>|. writeD d2 false
108 >>|. delay (lit 500))
109 }
110 \end{lstClean}
111
112 \section{Multi tasking}
113 Now say that we want to blink multiple blinking patterns on different \glspl{LED} concurrently.
114 For example, blink three \glspl{LED} connected to \gls{GPIO} pins $1,2$ and $3$ at intervals of \qtylist{500;300;800}{\ms}.
115 Intuitively you would want to lift the blinking behaviour to a function and call this function three times with different parameters as shown in \cref{lst:blinkthreadno}.
116
117 \begin{lstArduino}[caption={Naive approach to multiple blinking patterns.},label={lst:blinkthreadno}]
118 void setup () { ... }
119
120 void blink (int pin, int wait) {
121 digitalWrite(pin, HIGH);
122 delay(wait);
123 digitalWrite(pin, LOW);
124 delay(wait);
125 }
126
127 void loop() {
128 blink (D1, 500);
129 blink (D2, 300);
130 blink (D3, 800);
131 }\end{lstArduino}
132
133 Unfortunately, this does not work because the \arduinoinline{delay} function blocks all further execution.
134 The resulting program blinks the \glspl{LED} after each other instead of at the same time.
135 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}.
136 \Cref{lst:blinkthread} shows how three different blinking patterns could be implemented in \gls{ARDUINO} using the slicing method.
137 If we want the blink function to be a separate parametrisable function we need to explicitly provide all references to the required global state.
138 Furthermore, the \arduinoinline{delay} function can not be used and polling \arduinoinline{millis} is required.
139 The \arduinoinline{millis} function returns the number of milliseconds that have passed since the boot of the microcontroller.
140 If the delay is long enough, it may also be possible to put the processor in sleep mode, reducing the power consumption drastically.
141 Hence, using \arduinoinline{millis} potentially affects power consumption since the processor is basically busy looping all the time.
142 Manually combining tasks into a single program is very error prone, requires a lot of pointer juggling, and generally results into spaghetti code.
143 Furthermore, it is very difficult to represent dependencies between threads, often state machines have to be explicitly programmed by hand to achieve this.
144 In the simple case of blinking three \glspl{LED} according to fixed intervals, it is possible to calculate the delays in advance using static analysis and generate the appropriate \arduinoinline{delay} calls.
145 Unfortunately, this is very hard when for example the blinking patterns are determined at runtime.
146
147 \begin{lstArduino}[label={lst:blinkthread},caption={Threading three blinking patterns.}]
148 long led1 = 0, led2 = 0, led3 = 0;
149 bool st1 = false, st2 = false, st3 = false;
150
151 void blink(int pin, int interval, long *lastrun, bool *st) {
152 if (millis() - *lastrun > interval) {
153 digitalWrite(pin, *st = !*st);
154 *lastrun += interval;
155 }
156 }
157
158 void loop() {
159 blink(D1, 500, &led1, &st1);
160 blink(D2, 300, &led2, &st1);
161 blink(D3, 800, &led3, &st1);
162 }\end{lstArduino}
163
164 \subsection{Multi tasking in \texorpdfstring{\gls{MTASK}}{mTask}}
165 In contrast to the \arduinoinline{delay} function in \gls{ARDUINO}, \gls{MTASK}'s \cleaninline{delay} \emph{task} does not block the execution.
166 It has no observable value until the target waiting time has passed, and thence is \emph{stable}.
167 To make code reuse possible and make the implementation more intuitive, the blinking behaviour is lifted to a recursive function instead of using the imperatively looking \cleaninline{rpeat} task combinator.
168 There is no global state, the function is parametrized with the current status, the pin to blink and the waiting time.
169 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.
170 With a parallel combinator, tasks are executed in an interleaved fashion.
171 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}.
172
173 % VimTeX: SynIgnore on
174 \begin{lstClean}[label={lst:blinkthreadmtask},caption={Threading three blinking patterns.}]
175 blinktask :: MTask v () | mtask v
176 blinktask =
177 declarePin D1 PMOutput \d1->
178 declarePin D2 PMOutput \d2->
179 declarePin D3 PMOutput \d3->
180 fun \blink=(\(st, pin, wait)->
181 delay wait
182 >>|. writeD d13 st
183 >>|. blink (Not st, pin, wait))
184 In {main =
185 blink (true, d1, lit 500)
186 .||. blink (true, d2, lit 300)
187 .||. blink (true, d3, lit 800)
188 }
189 \end{lstClean}
190 % VimTeX: SynIgnore off
191
192 \section{Conclusion}
193 The edge layer of \gls{IOT} systems is powered by microcontrollers.
194 Microcontrollers have significantly different characteristics to regular computers.
195 Programming them happens through compiled firmwares using low-level imperative programming languages.
196 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.
197 With the \gls{MTASK} system, a \gls{TOP} programming language for \gls{IOT} edge devices, this limitation can be overcome.
198 As much domain-specific knowledge is built into the language and the \gls{RTS}, the hardware requirements can be kept relatively low while maintaining a high abstraction level.
199 \todo{moet dit uitgebreider?}
200
201 \input{subfilepostamble}
202 \end{document}