25e04ad730f11f092a7155b6b1d68f6625684ece
[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 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};
17 \item demonstrating that upgrading to a multitasking variant is straightforward using \gls{MTASK};
18 \item elaborating on integrating an edge device program with a server;
19 \item and providing a reading guide for the remainder of the monograph.
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 that differ much from regular computers.
25 They are much smaller; only have a fraction of the memory and processor speed; and run on different architectures.
26 However, they have much more energy-efficient sleep modes, and support connecting and interfacing with peripherals such as sensors and actuators.
27 To illustrate the difference in characteristics, \cref{tbl:mcu_laptop} compares the hardware properties of a typical laptop with two popular microcontrollers.
28 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.
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 \caption{Hardware characteristics of a laptop and two typical microcontrollers.}%
34 \label{tbl:mcu_laptop}
35 \centering
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 models of microcontrollers require their own vendor-provided drivers, hardware abstraction layer, compilers and \glspl{RTS}.
53 To structure this jungle of tools, platforms exist that provide abstraction layers over the low-level toolchains.
54 An example of this is \gls{ARDUINO}\footnote{\refurl{https://www.arduino.cc}{\formatdate{19}{12}{2022}}}.
55 It is specifically designed for education and prototyping and hence used here to illustrate traditional microcontroller programming.
56 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.
57 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}.
58 It provides an \gls{IDE} and toolchain automation to easily run code with a single press of a button.
59
60 \section{\texorpdfstring{\Glsxtrshort{TOP} for the \glsxtrshort{IOT}}{TOP for the IoT}}
61 \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}).
62 An example of a \gls{TOP} system is \gls{ITASK}, a general-purpose \gls{TOP} language for programming interactive distributed web applications.
63 Such web applications often form the core of the top two layers of an \gls{IOT} application.
64 \Gls{IOT} edge devices are typically programmed with similar workflow-like programs for which \gls{TOP} is very suitable.
65 Directly incorporating the perception layer, and thus edge devices, in \gls{ITASK} however is not straightforward.
66 The \gls{ITASK} system is targetting relatively fast and hence energy-hungry systems with large amounts of \gls{RAM} and a speedy connection.
67 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.
68 The \gls{MTASK} system bridges this gap by providing a domain-specific \gls{TOP} language for \gls{IOT} edge devices.
69 Domain-specific knowledge is embedded in the language and execution platform; and unnecessary features for edge devices are removed to drastically lowere the hardware requirements.
70
71 \section{Hello world!}
72 Traditionally, the first program that one writes when trying a new language is the so-called \emph{Hello World!} program.
73 This program has the single task of printing the text \emph{Hello World!} to the screen and exiting again.
74 It helps the programmer to become familiarised with the syntax of the language and to verify that the toolchain and runtime environment are working.
75 Microcontrollers usually do not come with screens in the traditional sense.
76 Nevertheless, almost always there is a built-in 1 pixel screen with a \qty{1}{\bit} color depth, namely the on-board \gls{LED}.
77 The \emph{Hello World!} equivalent on microcontrollers blinks this \gls{LED}.
78
79 Using \gls{ARDUINO}'s \ccpp{} dialect to create the blink program, results in the code seen in \cref{lst:arduinoBlink}.
80 \Gls{ARDUINO} programs are implemented as cyclic executives and hence, each program defines a \arduinoinline{setup} and a \arduinoinline{loop} function.
81 The \arduinoinline{setup} function is executed only once on boot, the \arduinoinline{loop} function is continuously called afterwards and contains the event loop.
82 In the blink example, the \arduinoinline{setup} function only contains code for setting the \gls{GPIO} pin to the correct mode.
83 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.
84 In between, it waits \qty{500}{\ms} so that the blinking is actually visible for the human eye.
85
86 \begin{lstArduino}[caption={Blinking an \gls{LED}.},label={lst:arduinoBlink}]
87 void setup() {
88 pinMode(D2, OUTPUT);
89 }
90 void loop() {
91 digitalWrite(D2, HIGH);
92 delay(500);
93 digitalWrite(D2, LOW);
94 delay(500);
95 }\end{lstArduino}
96
97 \subsection{Blinking the \texorpdfstring{\glsxtrshort{LED}}{LED} in \texorpdfstring{\gls{MTASK}}{mTask}.}
98 Naively translating the traditional blink program to \gls{MTASK} can be done by simply substituting some syntax as seen in \cref{lst:blinkImp}.
99 E.g.\ \arduinoinline{digitalWrite} becomes \cleaninline{writeD}, literals are prefixed with \cleaninline{lit}, and \arduinoinline{pinMode} becomes \arduinoinline{declarePin}.
100 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.
101 The task is not the single cyclic executive and therefore consists of just a main expression.
102 The task resulting from the main expression is continuously executed by the \gls{RTS}.
103 To simulate a loop, the \cleaninline{rpeat} task combinator is used as this task combinator executes the argument task and, when stable, reinstates it.
104 The body of the \cleaninline{rpeat} task contanis a task that writes to the pins and waits in between.
105 The tasks are connected using the sequential \cleaninline{>>|.} combinator that for all current intents and purposes executes the tasks after each other.
106
107 \begin{lstClean}[float=ht,caption={Blinking the \gls{LED} using the \cleaninline{rpeat} combinator.},label={lst:blinkImp}]
108 blinkTask :: Main (MTask v ()) | mtask v
109 blinkTask = declarePin D2 PMOutput \ledPin->
110 {main = rpeat (
111 writeD ledPin true
112 >>|. delay (lit 500)
113 >>|. writeD ledPin false
114 >>|. delay (lit 500))
115 }
116 \end{lstClean}
117
118 The \gls{MTASK} \gls{DSL} is hosted in a full fledged \gls{FP} language.
119 It is therefore also possible to define the blinking behaviour as a function.
120 \Cref{lst:blinkFun} shows this more natural translation.
121 The \cleaninline{main} expression is just a call to the \cleaninline{blink} function parametrised with the state.
122 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.
123 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.
124
125 \begin{lstClean}[caption={Blinking the \gls{LED} using a function.},label={lst:blinkFun}]
126 blinkTask :: Main (MTask v ()) | mtask v
127 blinkTask = declarePin D2 PMOutput \ledPin->
128 fun \blink=(\st->
129 writeD ledPin st
130 >>|. delay (lit 500)
131 >>|. blink (Not st))
132 In {main = blink true}
133 \end{lstClean}
134
135 \section{Multitasking}
136 Now say that we want to blink multiple blinking patterns on different \glspl{LED} concurrently.
137 For example, blink three \glspl{LED} connected to \gls{GPIO} pins $1,2$ and $3$ at intervals of \qtylist{500;300;800}{\ms}.
138 Intuitively you would want to lift the blinking behaviour to a function in order to minimise duplicate code and increase modularity and call this function three times with different parameters as shown in \cref{lst:blinkthreadno}.
139
140 \begin{lstArduino}[float=ht,caption={Naive approach to multiple blinking patterns.},label={lst:blinkthreadno}]
141 void setup () { ... }
142 void blink(int pin, int wait) {
143 digitalWrite(pin, HIGH);
144 delay(wait);
145 digitalWrite(pin, LOW);
146 delay(wait);
147 }
148 void loop() {
149 blink (D1, 500);
150 blink (D2, 300);
151 blink (D3, 800);
152 }\end{lstArduino}
153
154 Unfortunately, this does not work because the \arduinoinline{delay} function blocks all further execution.
155 The resulting program blinks the \glspl{LED} after each other instead of at the same time.
156 To overcome this, it is necessary to slice up the blinking behaviour in very small fragments and interleave it manually \citep{feijs_multi-tasking_2013}.
157 \Cref{lst:blinkthread} shows how three different blinking patterns could be implemented in \gls{ARDUINO} using the slicing method.
158 If we want the blink function to be a separate parametrisable function we need to explicitly provide all references to the required global state.
159 Furthermore, the \arduinoinline{delay} function can not be used and polling \arduinoinline{millis} is required.
160 The \arduinoinline{millis} function returns the number of \unit{\ms} that have passed since the boot of the microcontroller.
161 If the delay is long enough, it may also be possible to put the processor in sleep mode, reducing the power consumption drastically.
162 Hence, using \arduinoinline{millis} potentially affects power consumption since the processor is busy looping all the time.
163 Manually combining tasks into a single modular program is very error prone, requires a lot of pointer juggling, and generally results into spaghetti code.
164 Furthermore, it is very difficult to represent dependencies between threads.
165 Often state machines have to be explicitly programmed and merged by hand to achieve this.
166 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.
167 Unfortunately, this is very hard when for example the blinking patterns are determined at runtime.
168
169 \begin{lstArduino}[label={lst:blinkthread},caption={Threading three blinking patterns.}]
170 long led1 = 0, led2 = 0, led3 = 0;
171 bool st1 = false, st2 = false, st3 = false;
172
173 void setup () { ... }
174 void blink(int pin, int interval, long *lastrun, bool *st) {
175 if (millis() - *lastrun > interval) {
176 digitalWrite(pin, *st = !*st);
177 *lastrun += interval;
178 }
179 }
180 void loop() {
181 blink(D1, 500, &led1, &st1);
182 blink(D2, 300, &led2, &st1);
183 blink(D3, 800, &led3, &st1);
184 }\end{lstArduino}
185
186 \subsection{Multitasking in \texorpdfstring{\gls{MTASK}}{mTask}}
187 In contrast to the \arduinoinline{delay} function in \gls{ARDUINO}, \gls{MTASK}'s \cleaninline{delay} \emph{task} does not block the execution.
188 It has no observable value until the target waiting time has passed, and thence is \emph{stable}.
189 To make code reuse possible and make the implementation more intuitive, the blinking behaviour is lifted to a recursive function as well instead of using the imperatively looking \cleaninline{rpeat} task combinator.
190 There is no global state, the function is parametrized with the current status, the pin to blink and the waiting time.
191 With a parallel combinator, tasks are executed in an interleaved fashion.
192 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}.
193
194 % VimTeX: SynIgnore on
195 \begin{lstClean}[label={lst:blinkthreadmtask},caption={Threading three blinking patterns.}]
196 blinktask :: MTask v () | mtask v
197 blinktask = declarePin D1 PMOutput \d1->
198 declarePin D2 PMOutput \d2->
199 declarePin D3 PMOutput \d3->
200 fun \blink=(\(st, pin, wait)->
201 delay wait
202 >>|. writeD d13 st
203 >>|. blink (Not st, pin, wait))
204 In {main = blink (true, d1, lit 500)
205 .||. blink (true, d2, lit 300)
206 .||. blink (true, d3, lit 800)
207 }
208 \end{lstClean}
209 % VimTeX: SynIgnore off
210
211 \section{Conclusion and reading guide}
212 The edge layer of \gls{IOT} systems is powered by microcontrollers.
213 Microcontrollers have significantly different characteristics to regular computers.
214 Programming them happens through compiled firmwares using low-level imperative programming languages.
215 Due to the lack of an \gls{OS}, writing applications that perform multiple tasks at the same time is error prone, becomes complex, requires a lot of boilerplate, and needs manual scheduling code.
216 With the \gls{MTASK} system, a \gls{TOP} programming language for \gls{IOT} edge devices, this limitation can be overcome.
217 Since much 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.
218 Furthermore, the programs are automatically integrated with \gls{ITASK}, allowing for data sharing, task coordination, and dynamic construction of tasks.
219
220 The following chapters thoroughly introduce all aspects of the \gls{MTASK} system.
221 First the language setup and interface is shown in \cref{chp:mtask_dsl}.
222 Then, \cref{chp:implementation} provides the implementation of the \gls{DSL}, the compilation schemes, instruction set and details on the interpreter.
223 \Cref{chp:integration_with_itask} shows the integration of \gls{MTASK} and \gls{ITASK}.
224 \Cref{chp:green_computing_mtask} explains all green computing aspects of \gls{MTASK}, i.e.\ task scheduling and processor interrupts.
225 Finally, \cref{chp:finale} concludes and shows related work together with a short history of \gls{MTASK}.
226
227 \input{subfilepostamble}
228 \end{document}