Embedded System Design 2 - Project
documentation.h
Go to the documentation of this file.
1 /***************************************************************************//**
2  * @file documentation.h
3  * @brief This file contains useful documentation about the project.
4  * @version 3.1
5  * @author Brecht Van Eeckhoudt
6  *
7  * ******************************************************************************
8  *
9  * @mainpage Important documentation
10  *
11  * In the following sections you can find some important warnings, notes and overall
12  * documentation gathered during the creation of this project. This includes, for example,
13  * info about settings done with `#define` statements or certain things found out
14  * during debugging. *Please read them!*
15  *
16  * ******************************************************************************
17  *
18  * @section Doxygen
19  *
20  * This C-project has been made with [**Doxygen**](www.doxygen.org) comments above
21  * all methods to generate documentation. A combination of **Doxygen-specific tags**
22  * (preceded with an `@` symbol) and **markdown syntax** are supported to generate,
23  * for example, HTML-files.
24  *
25  * ******************************************************************************
26  *
27  * @section SETTINGS Settings using definitions in dbprint and delay functionality
28  *
29  * In the file `debug_dbprint.h` **dbprint UART functionality can be enabled/disabled**
30  * with the definition `#define DEBUG_DBPRINT`. If it's value is `0`, all dbprint statements
31  * are disabled throughout the source code because they're all surrounded with
32  * `#if DEBUG_DBPRINT == 1 ... #endif` checks.
33  *
34  * In the file `delay.h` one can **choose between SysTicks or RTC sleep functionality**
35  * for delays. This can be selected with the definition `#define SYSTICKDELAY`.
36  * If it's value is `0`, the RTC compare sleep functionality is used. if it's value
37  * is `1`, delays are generated using SysTicks.
38  *
39  * In the file `delay.h` one can also **choose between the use of the ultra low-frequency
40  * RC oscillator (ULFRCO) or the low-frequency crystal oscillator (LFXO)** when being
41  * in a delay or sleeping. If the ULFRCO is selected, the MCU sleeps in EM3 and if
42  * the LFXO is selected the MCU sleeps in EM2. This can be selected with the definition
43  * `#define ULFRCO`. If it's value is `0`, the LFXO is used as the clock source. If
44  * it's value is `1` the ULFRCO is used.
45  *
46  * @note Check the section @ref CLOCKS1 "Crystals and RC oscillators" for more info about this.
47  *
48  * In the file `util.h` one can **enable or disable error forwarding to the cloud using
49  * LoRaWAN**. This can be selected with the definition `#define ERROR_FORWARDING`. If
50  * it's value is `0`, the MCU will display a UART debug message (if enabled, see
51  * `debug_dbprint.h`) and enter a `while(true)` loop if the `error` method is called
52  * where the LED will flash indicating that an error has occurred. If it's value is `1`,
53  * a UART debug message will be displayed (if enabled) and the error number (if not
54  * corresponding to an error call in LoRaWAN functionality) will be forwarded to the
55  * cloud using LoRaWAN. After this, the code execution will be resumed. The MCU doesn't
56  * get put in a `while(true)` loop.
57  *
58  * ******************************************************************************
59  *
60  * @section Initializations
61  *
62  * @warning Initializations for the methods `led(bool enabled)`, `delay(uint32_t msDelay)`
63  * and `sleep(uint32_t sSleep)` happen automatically. This is why their first call
64  * sometimes takes longer to finish than later ones.
65  *
66  * ******************************************************************************
67  *
68  * @section DEBUG Debug mode, Energy monitor and VCOM
69  *
70  * @warning When in debug mode, the MCU will not really go below EM1. This can cause
71  * some weird behavior. Exit debug mode and reset the MCU after flashing it for it
72  * to go in the correct sleep modes and consume the "expected" power. The Energy
73  * profiler can also be used to program the MCU but it's also necessary to reset
74  * the MCU after flashing it.
75  *
76  * Leaving the debugger connected when issuing a `WFI` or `WFE` to enter EM2 or
77  * EM3 will make the system enter a special EM2. This mode differs from regular
78  * EM2 and EM3 in that the high frequency clocks are still enabled, and certain
79  * core functionality is still powered in order to maintain debug-functionality.
80  * Because of this, the current consumption in this mode is closer to EM1 and
81  * it is therefore important to disconnect the debugger before doing current
82  * consumption measurements.
83  *
84  * The Energy profiler in Simplicity Studio seems to use VCOM (on-board UART
85  * to USB converter) somehow, change to using an external UART adapter if both
86  * the energy profiler and UART debugging are necessary at the same time!
87  *
88  * If the energy profiler was used and the code functionality was switched,
89  * physically re-plug the board to make sure VCOM UART starts working again!
90  *
91  * ******************************************************************************
92  *
93  * @section GPIO GPIO/DATA/BUS pins and sleep mode
94  *
95  * @warning It's necessary to disable the GPIO pins of, for example, an SPI bus
96  * before going to sleep to get the *correct* sleep currents.
97  *
98  * Otherwise, some unwanted currents might flow out of these pins even though
99  * the data bus isn't active. This behavior caused confusion multiple times
100  * during the development phase. It was observed that for example that a 10k
101  * pull-up resistor pulled about 320 µA of unwanted current if the corresponding
102  * MCU pins weren't disabled.
103  *
104  * @warning It's also necessary to disable the GPIO pins for data pins (like for
105  * example in the case of the SPI bus) if an external sensor should be powered down.
106  *
107  * Because of the low current usage of these energy-efficient sensors,
108  * it's possible they can still be parasitically powered through the data bus
109  * even though it's supply pins are powered off using GPIO pins of the MCU. This
110  * also caused confusion bugs during the development phase.
111  *
112  * ******************************************************************************
113  *
114  * @section CLOCKS1 Crystals and RC oscillators (delay.c)
115  *
116  * Normally using an external oscillator/crystal uses less energy than the internal
117  * one. This external oscillator/crystal can however be omitted if the design goal
118  * is to reduce the BOM count as much as possible.
119  *
120  * In the delay logic, it's possible to select the use of the ultra low-frequency
121  * RC oscillator (ULFRCO) or the low-frequency crystal oscillator (LFXO) when being
122  * in a delay or sleeping. If the ULFRCO is selected, the MCU sleeps in EM3 and if
123  * the LFXO is selected the MCU sleeps in EM2.
124  *
125  * @warning After testing it was noted that the ULFRCO uses less power than the
126  * LFXO but was less precise for the wake-up times. Take not of this when selecting
127  * the necessary logic!
128  *
129  * For the development of the code for the RN2483 shield from DRAMCO, it's possible
130  * they chose to use the LFXO instead of the ULFRCO in sleep because the crystal was
131  * more stable for high baudrate communication using the LEUART peripheral.
132  *
133  * @note For low-power development it's advised to consistently enable peripherals and
134  * oscillators/clocks when needed and disable them afterwards. For some methods it can
135  * be useful to provide a boolean argument so that in the case of sending more bytes
136  * the clock can be disabled only after sending the latest one. Perhaps this can be
137  * used in combination with static variables in the method so they keep their value
138  * between calls and recursion can be used.
139  *
140  * ******************************************************************************
141  *
142  * @section CLOCKS2 GPIO clock (cmuClock_GPIO)
143  *
144  * At one point in the development phase the clock to the GPIO peripheral was
145  * always enabled when necessary and disabled afterwards. Because the GPIO
146  * clock needs to be enabled for almost everything, even during EM2 so the MCU
147  * can react (and not only log) pin interrupts, this behavior was later scrapped.
148  *
149  * `cmuClock_GPIO` is however just in case enabled in INIT methods where GPIO
150  * functionality is necessary.
151  *
152  * @note Alongside this peripheral clock, `cmuClock_HFPER` is also always enabled
153  * since GPIO is a High Frequency Peripheral.
154  *
155  * ******************************************************************************
156  *
157  * @section WATCHDOG Watchdog and while loops
158  *
159  * At the start of this project it was the plan to also implement a *watchdog* timer
160  * to make sure the MCU wouldn't get stuck in some logic and waste unnecessary power.
161  * `RMU_ResetCauseGet` and `RMU_ResetCauseClear` also seemed interesting methods to use.
162  * However, because of the relatively short time this watchdog can handle (9 - 256 000 cycles,
163  * max 256 seconds) it would only be able to be active when the MCU was awake, and because
164  * implementing this would take extra time it was opted to just focus on writing
165  * code which couldn't get stuck anywhere.
166  *
167  * This was done by carefully **making sure that the MCU couldn't get stuck in a WHILE
168  * loop anywhere**, by also **incrementing a counter and checking it's value against a
169  * *timeout* value**, defined at the top of each file.
170  *
171  * @warning `While` loops can pose problems if for some reason the thing they are waiting
172  * for doesn't happen (for example a bit doesn't get set). Because of this it's necessary
173  * to also implement another way to exit them. `For` loops don't have this possible problem.
174  *
175  * ******************************************************************************
176  *
177  * @section OPTIMALISATIONS Optimizing code
178  *
179  * @note The following info was found in *AN0007: 2.8 Optimizing Code*.
180  *
181  * Optimizing code usually leads to lower energy consumption by increasing the program speed and
182  * efficiency. A faster program spends less time in active mode, and each task in a more efficient
183  * program takes fewer instructions to execute.
184  *
185  * A simple way to optimize your code is to **build it with the highest optimization settings**
186  * in release mode** rather than in debug mode. In the [Development Perspective] of Simplicity Studio,
187  * go to [Project]>[Build Configurations]>[Set Active] and select [Release] for your compiler.
188  *
189  * Compiler selection can also have an impact on energy efficiency. For example, the **IAR compiler
190  * tends to generate more efficient code than GCC**. To use the IAR toolchain in Simplicity Studio,
191  * make sure IAR Embedded Workbench is installed on your computer. In the [Development Perspective] of
192  * Simplicity Studio, go to [Project]>[Properties]>[C/C++ Build]>[Settings]. Under the [Configuration:]
193  * drop down menu, select [IAR ARM - Release]. If you do not see this option, click
194  * [Manage Configurations...]>[New...], select the [IAR ARM - Release], and click [OK] twice.
195  * Next, increase IAR's optimization settings, under [Tool Settings]>[IAR C/C++ Compiler for ARM]>[Optimizations],
196  * select [High, Balance] for the [Optimization level:]. Under [IAR Linker for ARM]>[Optimizations],
197  * check all options ([Inline..., Merge..., Perform..., Even...]), and then click [OK].
198  *
199  * @note As a starting point, this should lower energy consumption, but it may not be the most optimized
200  * setting for a given project. Try different optimization settings such as [High, Speed], [High, Balance],
201  * other optimization option combinations, even other compilers, and compare the results.
202  *
203  * ******************************************************************************
204  *
205  * @section RTCC RTCC (RTC calendar)
206  *
207  * At another point in the development phase there was looked into using
208  * the RTCC (RTC calendar) to wake up the MCU every hour. This peripheral can
209  * run down to EM4H when using LFRCO, LFXO or ULFRCO. Unfortunately the Happy
210  * Gecko doesn't have this functionality so it can't be implemented in this case.
211  *
212  * ******************************************************************************
213  *
214  * @section EM Energy modes (EM1 and EM3)
215  *
216  * At one point a method was developed to go in EM1 when waiting in a delay.
217  * This however didn't seem to work as intended and EM2 would also be fine.
218  * Because of this, development for this EM1 delay method was halted.
219  * EM1 is sometimes used when waiting on bits to be set.
220  *
221  * When the MCU is in EM1, the clock to the CPU is disabled. All peripherals,
222  * as well as RAM and flash, are available.
223  *
224  * @attention In EM3, high and low frequency clocks are disabled. No oscillator (except
225  * the ULFRCO) is running. Furthermore, all unwanted oscillators are disabled
226  * in EM3. **This means that nothing needs to be manually disabled before
227  * the statement `EMU_EnterEM3(true);`.**
228 
229  * The following modules/functions are are generally still available in EM3:
230  * @li I2C address check
231  * @li Watchdog
232  * @li Asynchronous pin interrupt
233  * @li Analog comparator (ACMP)
234  * @li Voltage comparator (VCMP)
235  *
236  * ******************************************************************************
237  *
238  * @section UART Alternate UART Functionality Pinout
239  *
240  * | Location | `#0` | `#1` | `#2` | `#3` | `#4` | `#5` | `#6` |
241  * | ---------- | ------ | ------ | ------ | ------ | ------ | ------ | ------ |
242  * | `US0_RX` | `PE11` | | `PC10` | `PE12` | `PB08` | `PC01` | `PC01` |
243  * | `US0_TX` | `PE10` | | | `PE13` | `PB07` | `PC00` | `PC00` |
244  * | | | | | | | | |
245  * | `US1_RX` | `PC01` | | `PD06` | `PD06` | `PA00` | `PC02` | |
246  * | `US1_TX` | `PC00` | | `PD07` | `PD07` | `PF02` | `PC01` | |
247  *
248  * VCOM:
249  * - USART1 #4 (USART0 can't be used)
250  * - RX - `PA0`
251  * - TX - `PF2`
252  *
253  * ******************************************************************************
254  *
255  * @section DBPRINT More info about `dbprint`
256  *
257  * When using `dbprint` functionality, the following settings are used:
258  * - Baudrate = 115200
259  * - 8 databits
260  * - 1 stopbit
261  * - No parity
262  *
263  * When you want to debug using VCOM with interrupt functionality disabled, you
264  * can use the following initialization settings: `dbprint_INIT(USART1, 4, true, false);`
265  *
266  * ******************************************************************************
267  *
268  * @section Keywords
269  *
270  * @subsection Volatile
271  *
272  * The `volatile` type indicates to the compiler that the data is not normal memory,
273  * and could change at unexpected times. Hardware registers are often volatile,
274  * and so are variables which get changed in interrupts.@n
275  * Volatile variables are stored in *RAM*.
276  *
277  * @subsection Static
278  *
279  * @subsubsection VARIABLE Static variable
280  *
281  * During compile time (this is why we can't use variable length array's) memory
282  * gets reserved for this variable. The data itself gets put in the *data* segment
283  * of the memory (regular variables are put in the *stack* segment).@n
284  * It's best to keep the use of `static` variables to a minimum. One should ask
285  * himself the question if it's necessary to keep the variable constantly in the
286  * memory. If the answer is yes, a `static` variable is acceptable.@n
287  * A **static variable inside a function** keeps its value between invocations.
288  *
289  * @subsubsection FUNCTION Static global function
290  *
291  * The function is only "seen" in the file it's declared in. This means `static`
292  * can be used for methods the same way `private` is used for certain methods in C++.
293  *
294  * ******************************************************************************
295  *
296  * @section DATA Bits, bytes, nibbles and unsigned/signed integer value ranges
297  *
298  * - 1 nibble = 4 bits (`0b1111` = `0xF` )
299  * - 1 byte = 8 bits (`0b1111 1111` = `0xFF`)
300  *
301  * | Type | Alias | Size | Minimum value | Maximum value |
302  * | ---------- | ---------------- | ------- | -------------- | ----------------------------- |
303  * | `uint8_t` | `unsigned char` | 1 byte | 0 | 255 (`0xFF`) |
304  * | `uint16_t` | `unsigned short` | 2 bytes | 0 | 65 535 (`0xFFFF`) |
305  * | `uint32_t` | `unsigned int` | 4 bytes | 0 | 4 294 967 295 (`0xFFFF FFFF`) |
306  * | | | | | |
307  * | `int8_t` | `signed char` | 1 byte | -128 | 127 |
308  * | `int16_t` | `signed short` | 2 bytes | -32 768 | 32 767 |
309  * | `int32_t` | `signed int` | 4 bytes | -2 147 483 648 | 2 147 483 647 |
310  *
311  ******************************************************************************/