3bdaf1847d4c1f79031761a4c7f943a32b1d750d
[phd-thesis.git] / top / 4iot.tex
1 \documentclass[../thesis.tex]{subfiles}
2
3 \input{subfilepreamble}
4
5 \setcounter{chapter}{3}
6
7 \begin{document}
8 \input{subfileprefix}
9 \chapter{Task-oriented programming for the internet of things}%
10 \label{chp:top4iot}
11 \begin{chapterabstract}
12 This chapter introduces the monograph. It 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 cooperative multitasking, uncovering problems using \gls{ARDUINO} that do not exist in \gls{MTASK};
17 \item and providing a reading guide for the remainder of the monograph.
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.
23 They differ significantly from regular computers in many aspects.
24 For example, they are much smaller; only have a fraction of the memory and processor speed; and run on different architectures.
25 Furthermore, they have much more energy-efficient sleep modes, and support connecting and interfacing with peripherals such as sensors and actuators.
26 To illustrate the difference in characteristics, \cref{tbl:mcu_laptop} compares the hardware properties of a typical laptop with two popular microcontrollers.
27 As a consequence of these differences, development for microcontrollers is also unlike development for traditional computers.
28 Usually, programming microcontrollers requires an elaborate multistep toolchain of compilation, linkage, binary image creation, and burning this image onto the flash memory of the microcontroller in order to run a program.
29 The software is usually a cyclic executive instead of tasks that run in an \gls{OS}.
30 Hence, all tasks must be manually combined into a single program.
31
32 \begin{table}
33 \centering
34 \caption{Hardware characteristics of a laptop and two typical microcontrollers.}%
35 \label{tbl:mcu_laptop}
36 \begin{tabular}{llll}
37 \toprule
38 & Laptop & Atmega328P & ESP8266\\
39 \midrule
40 CPU speed & \qtyrange{2}{4}{\giga\hertz} & \qty{16}{\mega\hertz} & \qty{80}{\mega\hertz} or \qty{160}{\mega\hertz}\\
41 \textnumero{} cores & \numrange{4}{8} & 1 & 1\\
42 Storage & \qty{1}{\tebi\byte} & \qty{32}{\kibi\byte} & \qtyrange{0.5}{4}{\mebi\byte}\\
43 \Gls{RAM} & \qtyrange{4}{16}{\gibi\byte} & \qty{2}{\kibi\byte} & \qty{160}{\kibi\byte}\\
44 Power & \qtyrange{50}{100}{\watt} & \qtyrange{0.13}{250}{\milli\watt} & \qtyrange{0.1}{350}{\milli\watt}\\
45 Size & $\pm$\qty{1060}{\cubic\cm} & $\pm$\qty{7.5}{\cubic\cm} & $\pm$\qty{1.1}{\cubic\cm}\\
46 Display & \numproduct{1920x1080x24} & \numproduct{1x1x1} & \numproduct{1x1x1}\\ %chktex 29
47 Price & \euro{1500} & \euro{3} & \euro{4}\\
48 \bottomrule
49 \end{tabular}
50 \end{table}
51
52 All microcontroller models require their own vendor-provided drivers, hardware abstraction layer, compilers and \glspl{RTS}.
53 To structure this jungle of tools, platforms exist that provide an abstraction layer over the low-level toolchains.
54 An example of this is the \gls{ARDUINO} environment\footnote{\refurl{https://www.arduino.cc}{\formatdate{19}{12}{2022}}}.
55 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}.
56 This set of tools is specifically designed for education and prototyping and hence used here to illustrate traditional microcontroller programming.
57 It consists of an \gls{IDE} containing toolchain automation, a dialect of \ccpp{}, and libraries providing an abstraction layer for microcontroller behaviour.
58 With \gls{ARDUINO}, the programmer can program multiple types of microcontrollers using a single language.
59 Using the \gls{IDE} and toolchain automation, code can be executed easily on many types of microcontrollers with a single press of a button.
60
61 \section{TOP for the IoT}
62 \Gls{TOP} is a programming paradigm that allows multi-tier interactive systems to be generated from a single declarative source (see \cref{sec:back_top}).
63 An example of a \gls{TOP} system is \gls{ITASK}, a general-purpose \gls{TOP} language for programming interactive distributed web applications.
64 Such web applications often form the core of the topmost two layers of \gls{IOT} applications: the presentation and application layer.
65 Furthermore, \gls{IOT} edge devices are typically programmed with similar workflow-like programs for which \gls{TOP} is very suitable.
66 Directly incorporating the perception layer, and thus edge devices, in \gls{ITASK} however is not straightforward.
67 All \gls{ITASK} applications carry the weigth of multi-user \gls{TOP} programs that can generically generate webpages, communication, and storage for all data types in the program.
68 As a result, the \gls{ITASK} system targetting relatively fast and hence energy-hungry systems with large amounts of \gls{RAM} and a speedy connection.
69 Edge devices in \gls{IOT} systems are typically slow but energy efficient and do not have the memory to run the naturally heap-heavy feature-packed functional programs that \gls{ITASK} programs are.
70 The \gls{MTASK} system bridges this gap by providing a domain-specific \gls{TOP} language for \gls{IOT} edge devices.
71 Domain-specific knowledge is embedded in the language and execution platform and unnecessary features for edge devices are removed to drastically lower the hardware requirements.
72 Programs in \gls{MTASK} are written in the \gls{MTASK} \gls{DSL}, a \gls{TOP} language that offers a similar abstraction level as \gls{ITASK}.
73 Tasks in \gls{MTASK} operate as if they are \gls{ITASK} tasks, their task value is observable by other tasks, and they can share data using \gls{ITASK} \glspl{SDS}.
74 This allows for programming entire \gls{IOT} systems from a single abstraction level, source code, and programming paradigm.
75
76 \section{Hello world!}
77 Traditionally, the first program that one writes when trying a new language is the so-called \emph{Hello World!} program.
78 This program has the single task of printing the text \emph{Hello World!} to the screen and exiting again.
79 It helps the programmer to become familiarised with the syntax of the language and to verify that the toolchain and runtime environment are working.
80 Microcontrollers usually do not come with screens in the traditional sense.
81 Nevertheless, almost always there is a built-in 1 pixel screen with a \qty{1}{\bit} color depth, namely the on-board \gls{LED}.
82 The \emph{Hello World!} equivalent on microcontrollers blinks this \gls{LED}.
83
84 Creating a blink program using \ccpp{} and the \gls{ARDUINO} libraries result in the code seen in \cref{lst:arduinoBlink}.
85 \Gls{ARDUINO} programs are implemented as cyclic executives and hence, each program defines a \arduinoinline{setup} and a \arduinoinline{loop} function.
86 The \arduinoinline{setup} function is executed only once on boot, the \arduinoinline{loop} function is continuously called afterwards and contains the event loop.
87 In between the executions of the \arduinoinline{loop} function, system and maintenance code is executed.
88 In the blink example, the \arduinoinline{setup} function only contains code for setting the \gls{GPIO} pin to the correct mode.
89 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.
90 In between, it waits \qty{500}{\ms} so that the blinking is actually visible for the human eye.
91
92 \begin{lstArduino}[caption={Blinking an \gls{LED}.},label={lst:arduinoBlink}]
93 void setup() {
94 pinMode(D2, OUTPUT);
95 }
96 void loop() {
97 digitalWrite(D2, HIGH);
98 delay(500);
99 digitalWrite(D2, LOW);
100 delay(500);
101 }\end{lstArduino}
102
103 \subsection{Blinking the LED in mTask}
104 Naively translating the traditional blink program to \gls{MTASK} can be done by simply substituting syntax as seen in \cref{lst:blinkImp}.
105 E.g.\ \arduinoinline{digitalWrite} becomes \cleaninline{writeD}, literals are prefixed with \cleaninline{lit}, and \arduinoinline{pinMode} becomes \arduinoinline{declarePin}.
106 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.
107 The task is not the single cyclic executive and therefore consists of just a main expression.
108 The task resulting from the main expression is continuously executed by the \gls{RTS}.
109 To simulate a loop, the \cleaninline{rpeat} task combinator is used as this task combinator executes the argument task and, when stable, reinstates it.
110 The body of the \cleaninline{rpeat} task contains a task that writes to the pins and waits in between.
111 The tasks are connected using the sequential \cleaninline{>>\|.} combinator that for all current intents and purposes executes the tasks after each other.
112
113 \begin{lstClean}[caption={Blinking the \gls{LED} using the \cleaninline{rpeat} combinator.},label={lst:blinkImp}]
114 blinkTask :: Main (MTask v ()) | mtask v
115 blinkTask = declarePin D2 PMOutput \ledPin->
116 {main = rpeat (
117 writeD ledPin true
118 >>|. delay (lit 500)
119 >>|. writeD ledPin false
120 >>|. delay (lit 500))
121 }
122 \end{lstClean}
123
124 The \gls{MTASK} \gls{DSL} is hosted in a full-fledged \gls{FP} language.
125 It is therefore also possible to define the blinking behaviour as a function.
126 \Cref{lst:blinkFun} shows this more natural translation.
127 The \cleaninline{main} expression is a call to the \cleaninline{blink} \gls{MTASK} function parametrised with the state.
128 The \cleaninline{blink} function first writes the current state to the \gls{LED}, waits for the specific time, and calls itself recursively with the inverse of the state, resulting in the blinking behaviour.
129 Creating recursive functions like this is not possible in the \gls{ARDUINO} language because the program would run out of stack quickly and combining multiple tasks defined like this would be very difficult.
130
131 \begin{lstClean}[caption={Blinking the \gls{LED} using a function.},label={lst:blinkFun}]
132 blinkTask :: Main (MTask v ()) | mtask v
133 blinkTask = declarePin D2 PMOutput \ledPin->
134 fun \blink=(\st->
135 writeD ledPin st
136 >>|. delay (lit 500)
137 >>|. blink (Not st))
138 In {main = blink true}
139 \end{lstClean}
140
141 \section{Multitasking}
142 Now say that we want to blink multiple blinking patterns on different \glspl{LED} concurrently.
143 For example, blink three \glspl{LED} connected to \gls{GPIO} pins $1,2$ and $3$ at intervals of \qtylist{500;300;800}{\ms}.
144 Intuitively, you would want to lift the blinking behaviour to a function in order to minimise duplicate code, and increase modularity by calling this function three times with different parameters as shown in \cref{lst:blinkthreadno}.
145
146 \begin{lstArduino}[caption={Naive approach to multiple blinking patterns.},label={lst:blinkthreadno}]
147 void setup () { ... }
148 void blink(int pin, int wait) {
149 digitalWrite(pin, HIGH);
150 delay(wait);
151 digitalWrite(pin, LOW);
152 delay(wait);
153 }
154 void loop() {
155 blink (D1, 500);
156 blink (D2, 300);
157 blink (D3, 800);
158 }\end{lstArduino}
159
160 Unfortunately, this does not work because the \arduinoinline{delay} function blocks all other execution.
161 The resulting program blinks the \glspl{LED} after each other instead of at the same time.
162 To overcome this, it is necessary to slice up the blinking behaviour in small fragments and interleave it manually \citep{feijs_multi-tasking_2013}.
163 \Cref{lst:blinkthread} shows how three different blinking patterns could be implemented in \gls{ARDUINO} using the slicing method.
164 If we want the blink function to be a separate parametrisable function we need to explicitly provide all references to the required global state.
165 Furthermore, the \arduinoinline{delay} function can not be used and polling \arduinoinline{millis} is required.
166 The \arduinoinline{millis} function returns the number of milliseconds that have passed since the boot of the microcontroller.
167 If the delay passed to the \arduinoinline{delay} function is long enough, the firmware may decide to put the processor in sleep mode, reducing the power consumption drastically.
168 When polling \arduinoinline{millis} is used, this therefore potentially affects power consumption since the processor is busy looping all the time, not knowing when to go to sleep.
169 Manually combining tasks into a single modular program is very error-prone, requires a lot of pointer juggling, and generally results into spaghetti code.
170 Furthermore, it is very difficult to represent dependencies between threads.
171 Often state machines have to be explicitly programmed and merged by hand to achieve this.
172 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.
173 Unfortunately, this is very hard when for example the blinking patterns are determined at runtime.
174
175 \begin{lstArduino}[label={lst:blinkthread},caption={Threading three blinking patterns.}]
176 long led1 = 0, led2 = 0, led3 = 0;
177 bool st1 = false, st2 = false, st3 = false;
178
179 void setup () { ... }
180 void blink(int pin, int interval, long *lastrun, bool *st) {
181 if (millis() - *lastrun > interval) {
182 digitalWrite(pin, *st = !*st);
183 *lastrun += interval;
184 }
185 }
186 void loop() {
187 blink(D1, 500, &led1, &st1);
188 blink(D2, 300, &led2, &st1);
189 blink(D3, 800, &led3, &st1);
190 }\end{lstArduino}
191
192 \subsection{Multitasking in mTask}
193 In \gls{MTASK}, expressions are eagerly evaluated in an interpreter and tasks are executed by small-step rewrite rules.
194 In between these rewrite steps, other tasks are be executed and communication is handled.
195 Consequently, and in contrast to \gls{ARDUINO}, the \cleaninline{delay} task in \gls{MTASK} does not block the execution.
196 It has no observable value until the target waiting time has passed, and is thence \emph{stable}.
197 As there is no global state, the function is parametrised with the current status, the pin to blink and the waiting time.
198 With a parallel combinator, tasks are executed seamingly at the same time, i.e.\ their very short small-step reduction steps are interleaved.
199 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}.
200
201 % VimTeX: SynIgnore on
202 \begin{lstClean}[label={lst:blinkthreadmtask},caption={Threading three blinking patterns.}]
203 blinktask :: MTask v () | mtask v
204 blinktask =
205 declarePin D1 PMOutput \d1->
206 declarePin D2 PMOutput \d2->
207 declarePin D3 PMOutput \d3->
208 fun \blink=(\(st, pin, wait)->
209 delay wait
210 >>|. writeD pin st
211 >>|. blink (Not st, pin, wait))
212 In {main = blink (true, d1, lit 500)
213 .||. blink (true, d2, lit 300)
214 .||. blink (true, d3, lit 800)
215 }
216 \end{lstClean}
217 % VimTeX: SynIgnore off
218
219 \section{Conclusion and reading guide}
220 \todo[inline]{Reading guide noemen ipv conclusion omdat:
221 Veel van wat hier staat is geen conclusie van het voorgaande. Kun je dit niet beter reading guide noemen?}
222 This chapter introduced traditional edge device programming and programming edge devices using \gls{MTASK}.
223 \todo[inline]{Anders dan de titel van dit hoofdstuk suggereert, geeft dit maar een heel beperkt overzicht van TOP in mTask.
224
225 Zou je niet expliciet noemen dat je task resulten kunt gebruiken, conditionals en een step combinator hebt etc. Voorbeelden van alles lijkt me niet nodig.
226
227 Ook zou ik de SDS en integratie met iTask nog eens noemen te verwijzen naar de introductie.
228 Iets over semantiek zeggen?}
229 The edge layer of \gls{IOT} systems is powered by microcontrollers.
230 Microcontrollers have significantly different characteristics to regular computers.
231 Programming them happens through compiled firmwares using low-level imperative programming languages.
232 Due to the lack of an \gls{OS}, writing applications that perform multiple tasks at the same time is error-prone, becomes complex, and requires a lot of boilerplate such as manual scheduling code.
233 With the \gls{MTASK} system, a \gls{TOP} programming language for \gls{IOT} edge devices, this limitation can be overcome.
234 Since a lot domain-specific knowledge is built into the language and \gls{RTS}, the hardware requirements can be kept relatively low while maintaining a high abstraction level.
235 Furthermore, the programs are automatically integrated with \gls{ITASK}, a \gls{TOP} system for creating interactive distributed web applications, allowing for data sharing, task coordination, and dynamic construction of tasks.
236 \todo[inline]{
237 This makes it easy to create interactive applications modelling collaboration between end-users and edge devices.
238 }
239
240 The following chapters of this monograph thoroughly introduce all aspects of the \gls{MTASK} system.
241 First, the language setup and interface are shown in \cref{chp:mtask_dsl}.
242 \Cref{chp:integration_with_itask} shows the integration of \gls{MTASK} and \gls{ITASK}.
243 Then, \cref{chp:implementation} provides the implementation of the \gls{DSL}, the compilation schemes, instruction set, and details on the interpreter.
244 \Cref{chp:green_computing_mtask} explains all green computing aspects of \gls{MTASK}, i.e.\ task scheduling and processor interrupts.
245 Finally, \cref{chp:finale} concludes, shows related work, and provides a short history of \gls{MTASK}.
246
247 \input{subfilepostamble}
248 \end{document}