First personal computers followed microcontrollers in the begining of 70s. Their capacities were far behind modern computers, but it was possible to know EVERYTHING that was included in your maching and how it worked.

Moore's law

Empirical Moore's law establishes that transistors density in computers doubles about every two years for the same budget.

Technological progress leaded to current situation where abstraction blocks were stacked, allowing us to enjoy a rich and easy to use environment.

However, modern computer scientists are less aware of hardware and low-level considerations.

Wirth's law

Software is getting slower more rapidly than hardware becomes faster.

Loi de May

Software efficiency halves every 18 months, compensating Moore's law.

Software disenchantment

Full blog post

  • Software is slow
    • Windows 10 can take 30 minutes for an update...
    • ... in the same time budget, we can rewrite 5 times the full SSD
    • Why a smartphone takes 30 to 60 seconds to even boot ?
  • Software is huge
    • Windows 95 size was 30 Mo ...
    • ... the android Google keyboard now used 150 Mo of RAM
  • Software is quickly obsolete

What is an embedded system?

In this lecture, embedded system will be:

  • A system containing at least something we can program
  • Having some constraints:
    • Size
    • Power
    • Performance
    • Real-time

Silicium to program

Integrated circuits is the base technology of all embedded system. They are engraved on silicium disks called wafers:

Those disks are engraved using photolitography process using optical masks to duplicate a pattern forming components (transistors, diodes, resistors...)

Those silicium dices are then encased in packages that can be assembled in electronics boards


There are several types of integrated circuits:

  • Computer processing unit (CPU)
  • Microcontrollers (MCU)
  • DSP
  • FPGA

For our work, we will focus on ICs we can program, but we will communicate with other ICs.

Programming a microcontroller


There are different types of memory:

  • RAM
  • Flash (ROM)


In the memory, some address are used as registers, that can be used to change the processor and hardware behaviour.

Those registers are available just like any other memory address.

Binary instruction, assembly

Processor core read sequentially instructions and executes actions.

Those instructions are the machine language.

To represent those operations visually, we use the so-called mnemonics: this is the assembly language.

Loading a program

Microcontrollers are generally featuring several ways to program them (JTAG, SPI, usart, USB...); thus are bootloaders.

Developing boards are usually provided with programs allowing to reprogram them using more convenient ways (like ethernet, over-the-air...), we call them software bootloaders.

C compiling


We can build binaries for another architecture than the computer we are currently working on, this process is known as cross-compilation.

For this, we need the proper compilation toolchain. (For example, the compiler itself is running on an x86_64 computer and producing avr bytecodes).


To program a microcontroller, we need to output a raw binary, and not an ELF-like file, the one we run using Linux for example.

On the target, there are no operating system (unless we bring one), which means no scheduling, no kernel/user space, no system call etc.


It is really necessary to enable compilers optimisations to work on microcontrollers. Typically -Os:

gcc -Os code.c

This option asks the compiler to produce the smallest possible output


You can meet this notation:

#define REG (*(volatile uint8_t *)(0xf00))

int main(void) {
    REG = 123;

To access a register. The volatile keyword tell the compiler that this memory address should be written (especially, it should not be optimized out).

Binary operations

You should become familiar to bitwise operators:

&Logical "and"
|Logical "or"
~Negation (invert)
<<Left shift
>>Right shift

Warning, of course, do not confuse && operator with &, and do not confuse || with |.

Those are respectively boolean operators and binary operators.

For example: if (1 & 1) will be executed, but if (1 & 2) will not.


What is the result of this macro?

#define _BV(n) (1<<(n))

And this snippet?

PORTD |= _BV(3);

And this one?

PORTD &= ~_BV(3);

And this one?

PORTD &= ~(_BV(3) | _BV(4));

And this one?

if (PORTD & _BV(3)) {
    // ...

It is important to master binary operators to be able to work on registers on a bitwise level.

Example: pins of ATmega

In official documentation, we can find specification of how to drive pins:

Tri-state / Hi-Z here refers to high impedance

Here is an example of form factor:

It is then possible to drive PB2 pin like this:

// AVR headers
#include <avr/io.h>

int main() {
    // Pin is output (low impedance)
    DDRB |= _BV(PB5);
    // The pin is "high" level (eg 5V)
    PORTB |= _BV(PB5);

Here is the produced assembly code matching those instructions:

25 9a           sbi     0x04, 5 ; 4
2d 9a           sbi     0x05, 5 ; 5
08 95           ret

The compiler will add this preamble:

11 24           eor     r1, r1
1f be           out     0x3f, r1        ; 63
cf ef           ldi     r28, 0xFF       ; 255
d8 e0           ldi     r29, 0x08       ; 8
de bf           out     0x3e, r29       ; 62
cd bf           out     0x3d, r28       ; 61
0e 94 40 00     call    0x80    ; 0x80 <main>
0c 94 43 00     jmp     0x86    ; 0x86 <_exit>

And postamble:

86 <_exit>:
  f8 94           cli
88 <__stop_program>:
  ff cf           rjmp    .-2             ; 0x88 <__stop_program>


GPIOs (General Purpose Input/Outputs) are pins that we can drive as input/output for any general purpose.

Here, we can see the logical schematics of one pin in the ATmega, it is possible to enable the pin as output and drive it to high or low level (line buffer is in the center of schematics), or setting it as input and sample it (bottom of schematics), optionally with a pull-up (top of schematics).

All pins are generally usable as GPIOs and can be switched to alternative function (AF) mode, meaning that is will then be managed by hardware (think for instance of UART).