More generally:
⇒ A computer!
Vocabulary used hereafter:
In 40 years:
What do the years to come have in store?!
Compared to current configurations:
Yet it allowed to bring human beings to the Moon
Embedded software engineers can make a lot with only a few resources 🙂
A modern microcontroller with similar processing power:
Variants exist: same memory but separate buses, etc.
Of course, variants exist!
For a PC running Linux:
Main functions of virtual memory:
Note: depending on the µC, a software update may also be performed Over the Air (OTA)
RISC: Reduced Instruction Set Computer
Arm processor architecture is more popular than any other architecture.
Some Cortex-M licensees:
Price: US$13
US$42
Microcontroller block:
Analog blocks:
Digital blocks:
Price: US$19.94
Soc - System on a Chip
An integrated circuit containing a whole system: for instance, a microcontroller + additional memory + a radio module
Price:
ESP32-C3-DevKitC-02 - US$8.00
ESP32-EYE - US$19.90
Update: do not seem supported anymore. A side-effect of the acquisition of Sierra Wireless by Semtech?
mangOH Yellow:
Sensors:
Miscellaneous:
Software environment:
Price (unit): around US$ 165
It may be required to add:
Our example:
Our example:
Our example:
Electrical levels:
V.28 and RS232 connectors: DB9 or DB25 D-subminiature connectors
For current computers, serial-USB adapters
Data transfer:
Important:
Our example:
Our example:
Write operation:
Read operation:
See Communications section
n bits:
-2n-1 — 2n-1 - 10 — 2n - 1-128 — 1270 — 255-2,147,483,648 — 2,147,483,6470 — 4,294,967,2962/3...)?...)?e...)?sign x significand x baseexponent21
and less than 2. Leading 1
is assumed and not encoded ⇒ actually 24 or 53 bits127 or 1024Floating-point library:
Example: calculating a short distance on Earth's surface (up to a few 10s of km)
With the computer:
With the computer and the microcontroller board:
Minimum required memory:
Usually:
This type of environment targets boards similar to desktop computer motherboards.
Minimum required memory:
Available services:
(Similar to those provided by an OS)
(Very) important difference with an OS: no virtual memory.
Provided by the RTOS, or provided as additional services, and (often) required by a connected device:
Question: what does the microcontroller do when there is nothing to do?
Answer:
Question: and when there is something to do?
Answer: interruptions and background task
Question: when is an interruption generated?
Input:
Timer:
UART:
A/D conversion:
etc.
Question: what happens if an interruption occurs while an ISR is active?
Answer: it depends 🙂
Question: why ISR with short execution time?
Answer:
More detailed view:
In many applications, there are not a lot of events
Question: how can energy be saved?
Answer: enter a sleep mode between two events
Example: receiving bytes on a serial link
bool rec_byte_event = false;
uint8_t rec_byte;
rec_byte = get_byte_from_uart();
rec_byte_event = true;
while (true) {
...
if (rec_byte_event) {
rec_byte_event = false;
// Process rec_byte.
...
}
...
}
What if the background task has sometimes too many things to do, and can't check often enough if a byte has been received?
Some bytes may be lost.
Usual solution:
Beware: the buffer is modified by the ISR (when a byte is received), and by the backgroud task (when bytes are extracted from the buffer)
A good way to handle this: a circular buffer, with atomic access (see further below)
A way to depict an FSM:
Message format:
Decoding:
A possible implementation:
current_state = WAIT_DOLLAR;
while (true) {
c = get_character();
switch (current_state) {
case WAIT_DOLLAR:
if (c == '$') {
current_state = WAIT_G;
break;
}
// Other character, stay in this state.
break;
case WAIT_G:
if (c = 'G') {
current_state = WAIT_P;
break;
}
// Other character, go back to initial state.
current_state = WAIT_DOLLAR;
break;
case WAIT_P:
if (c = 'P') {
msg_length = 0;
current_state = WAIT_CR;
break;
}
// Other character, go back to initial state.
current_state = WAIT_DOLLAR;
break;
case WAIT_CR:
if (c == CR) {
current_state = WAIT_LF;
break;
}
// Other character, store into message.
add_to_message(c);
msg_length++;
break;
case WAIT_LF:
if (c == LF) {
process_message(msg_length);
current_state = WAIT_DOLLAR;
break;
}
// Other character, go back to initial state.
current_state = WAIT_DOLLAR;
break;
default:
signal_error(UNKNOWN_STATE);
current_state = WAIT_DOLLAR;
}
}
A real example: handling the connection to a Wi-Fi AP for the ESP32:
Several transitions not drawn, for simplicity sake.
Typical use case: receiving bytes from a serial link
A possible implementation:
#define BUFFER_LENGTH 64
#define BUFFER_EMPTY -1
uint16_t inIndex;
uint16_t outIndex;
uint16_t dataLength;
uint8_t ringBuffer[BUFFER_LENGTH];
void initBuffer(void) {
inIndex = 0;
outIndex = 0;
dataLength = 0;
}
void putData(uint8_t data) {
ringBuffer[inIndex] = data;
// Move inIndex forward.
inIndex++;
if (inIndex == BUFFER_LENGTH) {
inIndex = 0;
}
dataLength++;
if (dataLength == BUFFER_LENGTH + 1) {
// Overflow. Move outIndex forward.
outIndex++;
if (outIndex == BUFFER_LENGTH) {
outIndex = 0;
}
dataLength--;
}
}
int getData(void) {
if (dataLength == 0) {
return BUFFER_EMPTY;
}
uint8_t dataToReturn = ringBuffer[outIndex];
dataLength--;
// Move outIndex forward.
outIndex++;
if (outIndex == BUFFER_LENGTH) {
outIndex = 0;
}
return dataToReturn;
}
Beware: if the circular buffer is shared between an ISR and the background task, every modification of the circular buffer (array, pointers) must be atomic.
Example: GNSS messages decoding
Of course, FSM and circular buffers may be used with an RTOS or an OS.