Connected device architecture
Reminder: computer architecture
Von Neumann architecture
- Memory stores data and instructions
- Same bus for data and instructions
Harvard architecture
- Separate memory for data and for instructions
- Bus for data and bus for instructions
Variants exist: same memory but separate buses, etc.
Reminder: computer boot process
- The CPU starts executing a short program in ROM: the bootstrap
- The bootstrap loads the boot loader from a disk
- The bootloader loads the Operating System (OS) from a disk
Of course, variants exist!
For a PC running Linux:
- bootstrap: BIOS
- bootloading:
- a first-stage bootloader is read from the Master Boot Record (MBR)
- the first-stage bootloader loads a second-stage bootloader
- the second-stage bootloader loads the Linux kernel
Reminder: virtual memory
Main functions of virtual memory:
- Provide each process with its own address space
- Ensure process isolation
- Ensure OS isolation
- Provide more memory than physical memory
Microcontroller
- A computer in a chip:
- Central Processing Unit (CPU)
- Read-only memory (Flash memory)
- Read/write memory (RAM - Random Access Memory)
- Peripherals and interfaces:
- Analog I/O
- Digital I/O
- Timers
- Serial links
- Serial buses
- Watchdog
- etc.
Read-only memory
- Formerly:
- ROM - Read-Only Memory
- PROM - Programmable Read-Only Memory
- EPROM - Erasable Programmable Read-Only Memory
- EEPROM - Electrically Erasable Programmable Read-Only Memory
- Flash memory: a type of EEPROM
- Erase: by block
- Write: by byte
Microcontroller memory
Bootloader
- Allows easy software update
- Waits for binary data, usually provided on a serial link
- Is active only under specific conditions (pins set to some levels)
Note: depending on the µC, a software update may also be performed Over the Air (OTA)
Architecture of a connected device
- Microcontroller
- CPU + memory
- Some peripherals (e.g. timers, watchdog, etc.)
- Interfaces (serial links, serial buses, GPIO, etc.)
- Communication (may be hosted by the microcontroller)
- Optionally:
- Additional interfaces
- Peripherals (sensors, etc.)
- Positioning
- User interface
- Power supply management
- Data storage
- Not depicted: optional, additional memory, outside of the microcontroller
Important device/microcontroller characteristics?
- Depend on the application!
- Example:
- General Purpose Input/Output (GPIO)
- Serial links
- Serial buses (SPI, I2C, etc.)
- Analog to Digital Converters (ADC), Digital to Analog Converters (DAC)
- Analog blocks
- Instruction cycle time
- Memory (size, type, expandable...)
- Registers size (8/16/32 bits)
- Packaging
- etc.
IoT important characteristics
- Integrated communication (Wi-Fi, Bluetooth, LoRaWAN, cellular...)
- Security (secure element, hardware encryption...)
- Sleep modes
- Low cost
- Ecosystem
- etc.
Software tools
- Cross-compilation toolchain
- Integrated Development Environment (IDE)
- Open source software
See Software
Development part
Support
- Professional support
- Active community (forums, examples...)
Some common microcontroller families used in IoT systems
- Microcontrollers with Arm cores
- ESP8266/ESP32
- Cellular modules
- PSoC
- RISC-V
- PIC
- AVR
- MIPS32
- etc.
Arm
- UK company created in 1990
- there isn't any Arm microcontroller
- Arm provides Intellectual Property (IP) blocks, under a licensing agreement
- among these blocks: RISC microcontrollers cores
- for the IoT (low power, low cost): Cortex-M family
RISC: Reduced Instruction Set Computer
Shipped processors
- end 2020: 180 billions
- including 6.7 billions in Q4 2020
- including 4.4 billions of Cortex-M in Q4 2020
- Sep-2022: more than 250 billions
Arm processor architecture is more popular than any other architecture.
Arm cores
Diagram a little bit old (2017) - new models are available
Instruction sets
Provided elements
Example: STMicroelectronics - STM32 family
- Price: US$6.95 (unit) - US$2.66 (10,000)
Development board
Price: US$13
- price: US$9.25 (unit) - US$4.54 (10,000)
Development board
US$42
Example: Cypress PSoC 4200 family
Microcontroller block:
- Cortex-M0 core
- Clock: up to 48 MHz
- Memory: up to 256 KB Flash, 32 KB RAM
- USB, CAN
Analog blocks:
- Up to 4 op amp
- A/D converter, up to 1 mega samples/s on 12 bits
- Up to 6 comparators
- Up to 4 D/A converters
- Capacitive sensing
Digital blocks:
- Up to 8 universal digital blocks
- Up to 8 timers/counters/PWM blocks
- Up to 4 serial communication blocks (UART, I2C, SPI)
- Segment LCD drive
Development board
Price: US$19.94
Espressif - ESP family
First, a definition
Soc - System on a Chip
An integrated circuit containing a whole system: for instance, a microcontroller +
additional memory + a radio module
Espressif SoC family
- ESP32-S Series
- ESP32-C Series
- ESP32-H Series
- ESP32 Series
- ESP8266 Series
- Announced: ESP32-P Series
Main characteristics (depend on series)
- Single-core or dual-core (Tensilica Xtensa LX7 / Tensilica L106 / RISC-V)
- Wi-Fi 2.4 GHz / Wi-Fi 6 / Bluetooth / Bluetooth Low Energy / IEEE 802.15.4 (Thread / Zigbee)
- Many peripherals
- Vector instructions ⇒ neural network and digital signal processing
- Security
- Low power
- Software Development Kits (IoT, AI, audio, etc.)
- Low cost
Price:
- ESP32-C3FH4 - 4MB Flash - Wi-Fi + Bluetooth LE: US$1.30
Development boards
ESP32-C3-DevKitC-02 - US$8.00
ESP32-EYE - US$19.90
mangOH Yellow:
- Programmable cellular communication module
- Design: Sierra Wireless
- Open source schematics
- 2G, 4G, LTE-M/NB-IoT
- GNSS
- Wi-Fi, Bluetooth 5.0
Sensors:
- Accelerometer
- Gyroscope
- Magnetometer
- Pressure, humidity, temperature
- Air quality
- Light
Miscellaneous:
- Battery management
- Expansion card conncetor
- etc.
Software environment:
- Linux
- Very complete library
- Advanced cloud integration (Octave)
Price (unit): around US$ 165
Cross development
With the computer:
- Edit source-code
- Cross build (cross compile and link)
- Emulate and debug
With the computer and the microcontroller board:
- Program the Flash memory
- Debug
- Every microcontroller manufacturer: full development environnement
- Often free
- Often based on Open Source software (Eclipse, gcc, etc.)
Operating System - OS
- Mainly: Linux
- Similar to a desktop computer:
- Package manager
- Graphical user interface is possible
Minimum required memory:
- RAM: a few MB or a few tens of MBs
- Depends on applications
Usually:
- RAM: from 512 MB to 8 GB
- Flash card: from 1 GB to 8 GB
- Linux typically requires an MMU (Memory Management Unit) ⇒ virtual memory
- The kernel can be configured to work without one
- Thanks to μClinux project
- Beware about applications compatibility
Sources:
Larry Ewing,
YP,
Legato,
Arch Linux ARM,
OpenWrt Project,
balenaOS,
Wind
River,
Digi Embedded,
MontaVista,
LYNX MOSA.ic,
This type of environment targets boards similar to desktop computer motherboards.
Real-Time Operating System (RTOS)
- Allows for a deterministic response time
- Uses very little memory
- No way to add a new application without rebuilding and reflashing
Minimum required memory:
- RAM: a few KB
- Flash: a few KB
- Depends on the application
Sources:
FreeRTOS,
eCos,
Contiki-NG,
RIOT,
QNX,
Mbed OS,
RT-Thread,
Zephyr,
ThreadX,
µC/OS,
OS-9,
Mynewt,
VxWorks,
Nucleus,
LiteOS,
LynxOS,
Zerynth OS,
NuttX
- FreeRTOS acquired by Amazon
- ThreadX acquired by Microsoft
- Google and Facebook support Zephyr
Available services:
- Threads/tasks
- Synchronization and communication:
- Messages and queues
- Semaphores
- Events groups
- etc.
- Timers
- Memory allocation
- etc.
(Similar to those provided by an OS)
(Very) important difference with an OS: no virtual memory.
- A task may crash another task
- A task may crash the whole application
Provided by the RTOS, or provided as additional services, and (often) required by a connected device:
- Connectivity
- Security
- Storage
- Device management
- Machine learning
Bare metal
- No OS, no RTOS, directly on the microcontroller
- There may be an abstraction layer:
- ⇒ compatibility over a family of microcontrollers
- Arm: CMSIS
- ST: HAL, LL
- etc.
Question: what does the microcontroller do when there is nothing to do?
Answer:
- It loops
- It can also enter a sleep mode (see further below)
Question: and when there is something to do?
Answer: interruptions and background task
Interruption
- The code being executed is interrupted
- Part of the execution context is saved
- A specific code is executed to service the interruption
- The saved context is restored
- The interrupted execution is resumed
Vocabulary
- Code servicing the interrupt: Interrupt Handler, Interrupt Service Routine (ISR)
Question: when is an interruption generated?
Input:
- Input signal goes from a low level to a high level
- Input signal goes from a high level to a low level
Timer:
- A preconfigured duration is reached
- An input signal level changes ⇒ duration provided
- etc.
UART:
- A byte is received
- A byte has been sent
- Parity error for received byte
- A predefined byte is received
- etc.
A/D conversion:
- Ready to convert
- Conversion done
- etc.
Question: what happens if an interruption occurs while an ISR is active?
- Every interrupt may have a priority level (possibly configurable)
- An interrupt of a higher priority interrupts an ISR servicing a lower priority interrupt
- An interrupt of lower or equal level does not interrupt the ISR; it is saved for later servicing
Usual architecture of an application
- ISR with short execution time
- An ISR stores interrupt information in a dedicated memory zone:
- Interrupt identity
- Values specific to the interrupt (e.g. for the UART: received byte - for the
A/D conversion: digital value - etc.)
- An endless loop goes through the memory zones and acts accordingly
Question: why ISR with short execution time?
Answer:
- During ISR execution, one lower-level interrupt will be saved
- If several additional ones occur, they will be lost
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
- Entering a sleep mode is important for devices without external power supply
- Usually, several different sleep modes
- The part(s) generating events must be kept active
Example: receiving bytes on a serial link
Global variables
bool rec_byte_event = false;
uint8_t rec_byte;
ISR for "byte received" interrupt
rec_byte = get_byte_from_uart();
rec_byte_event = true;
Background task
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:
- The ISR stores received bytes into a buffer
- When it can, the background task processes the contents of the buffer
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)
Finite Sate Automaton (FSA) or Finite State Machine (FSM)
- abstract machine having a finite number of states
- at a given time, is in one state
- entering a new state (transition) is caused by an event
- a condition may guard a transition
- processing is performed when transitioning
A way to depict an FSM:
FSM example: decoding NMEA 0183 GNSS messages
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.
Ring buffer (or circular buffer)
- Array used as an interface between a data producer and a data consumer
- Allows to decouple producer and consumer
- When the producer is more rapid than the consumer: we can choose
to loose either the oldest data or the newest data
Typical use case: receiving bytes from a serial link
- a pointer to next data to be read
- a pointer to next available place
- when the end of the array is reached: wrap to start of the array
- ⇒ ring/circular buffer
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.
Hands-on Lab: STM32
Hands-on Lab: ESP32
Our example
- Which device to choose?
- Processing power
- Memory size
- Interfaces
- Peripherals
- Software?
- OS / RTOS / bare metal
- Remote software update
- etc.
- Detailed information is required
- On peripherals to be handled
- On business functions to be implemented
- Keep some flexibility
- Beware: reducing device and peripherals cost can be expensive later on (see later)