The computer you never see
Count the computers in the room you're sitting in. Most people say one — the laptop — and miss the other thirty. The microwave that counts down to zero is a computer. So is the thermostat on the wall, the remote on the sofa, the toothbrush charger, and the key fob in your pocket. They have no screen, no keyboard, no Windows logo at boot. They just *do their one job* — heat, regulate, transmit — from the moment power arrives until the day they die. These are embedded systems: computers buried inside a product, dedicated to a single task.
The contrast with your laptop is the whole point. A PC is a general-purpose machine: today it edits video, tomorrow it plays games, next week it runs spreadsheets — you keep loading new software. An embedded system is the opposite. Its software is fixed at the factory and almost never changes; a microwave will *never* learn to play chess. That single-mindedness is a feature, not a limitation. Because it does only one thing, it can be tiny, cheap, sip almost no power, switch on instantly, and run untouched for ten years.
The microcontroller: a whole computer on one chip
Open a desktop PC and you find a whole city: a processor here, sticks of memory there, a separate disk, a graphics card, a tangle of cables between them. The brain of a typical embedded system is far humbler — it's a single chip the size of a fingernail called a microcontroller, or MCU. The trick of the MCU is integration: it crams the processor *and* the memory *and* the input/output circuitry all onto one piece of silicon, so it's a self-contained little computer that needs almost nothing else to run.
A PC (parts spread across a board) A MICROCONTROLLER (one chip)
┌──────────────────────────────────┐ ┌──────────────────────────────┐
│ CPU ──── RAM (DRAM sticks) │ │ CPU core │
│ │ ──── Disk (SSD, separate) │ │ Flash (program lives here) │
│ │ ──── GPU card │ │ RAM (scratch memory) │
│ │ ──── I/O chips on board │ │ Peripherals: GPIO, timers, │
│ many chips, big board, ~watts │ │ UART, I2C, SPI, ADC... │
└──────────────────────────────────┘ │ ~a few mW, ~$0.50–$5 │
└──────────────────────────────┘
General purpose, runs ANY software One job, runs ITS firmwareThree ingredients matter. The CPU is the part that actually executes instructions — fetch, decode, do the arithmetic — but in an MCU it's modest, often running at a few megahertz to a couple of hundred, versus the gigahertz of a laptop. There are two kinds of memory: a small block of RAM for scratch work that vanishes when power is cut, and a larger block of flash where the program is stored permanently. And finally the peripherals — the built-in circuits that let the chip touch the outside world: pins it can switch on and off, timers, and serial buses with names like UART, I²C, and SPI. The peripherals are what turn a calculator into a *controller*.
Firmware: the program baked into the chip
On a PC, software lives on a disk and you launch it when you like. On a microcontroller there is no disk and no 'launching' — the program lives in the chip's flash memory and starts running the *instant* power arrives. Because this software sits so close to the hardware, half firm and half soft, we call it firmware. It's the one program the chip will ever run, and it stays put even with the battery removed, because flash is non-volatile — it remembers without power, the way a written note survives a power cut but a thought in your head does not.
How does your code, written in C on a laptop, end up frozen inside a chip? Through a short, unchanging ritual every embedded engineer repeats hundreds of times a day — build, flash, run. You write source code, a tool called a *compiler* translates it into the raw machine instructions the CPU understands, you copy those instructions into the chip's flash over a cable, and then the chip resets and runs them. Change one line and you go around the loop again.
- Write — author your firmware in a language like C, describing exactly what each pin and peripheral should do.
- Build (compile) — a compiler turns your human-readable code into a binary of machine instructions sized to fit the flash.
- Flash (program) — a programmer tool copies that binary into the chip's flash memory over a USB or debug cable.
- Run — the chip resets; on power-up it jumps to the start of your program and runs it forever, with no operating system needed.
Hello, world: blinking an LED
Every field has its first ritual. For web developers it's printing 'hello, world'; for embedded engineers it's blinking an LED. There's no screen to print to, so the chip's very first words to the world are a flashing light. To make it blink, the MCU uses one of its general-purpose pins, a GPIO — 'general-purpose input/output'. Configured as an output, a GPIO pin is a switch the firmware can flip: drive it HIGH and the pin pushes out the chip's supply voltage (say 3.3 V); drive it LOW and the pin sits at 0 V. Toggle it on and off and a connected LED winks.
MCU 3.3 V ┌──────────┐ │ │ │ R = 100 Ω ──┴── battery / supply │ GPIO ──┼───[ ▭▭▭ ]───►|───┐ ───── │ (pin) │ resistor LED │ │ │ │ (~2V) │ │ │ GND ───┼────────────────────┴─────────┘ └──────────┘ Pin HIGH (3.3 V) → current flows → LED ON Pin LOW (0 V) → no current → LED OFF The series resistor is NOT optional — it limits the current so the LED (and the pin) don't burn out.
Here's the beautiful part: lighting that LED is exactly the voltage and current story from the circuits track, now driven by software. The pin supplies 3.3 V. The LED itself drops about 2 V across it once lit, so the resistor sees the leftover 3.3 − 2 = 1.3 V. Apply Ohm's law and the resistor sets the current flowing through the whole branch:
Pin drives HIGH = 3.3 V LED forward drop ≈ 2.0 V (typical red LED) Voltage left for the resistor: V_R = 3.3 V − 2.0 V = 1.3 V Choose R = 100 Ω. Current through the LED: I = V_R / R = 1.3 V / 100 Ω = 0.013 A = 13 mA 13 mA is a healthy, bright, SAFE LED current. (A GPIO pin can usually source up to ~20 mA — stay under it.) Leave out the resistor (R ≈ 0) and I shoots toward hundreds of mA — the LED and the pin cook. The resistor is what keeps everything civilised.
Look closely at the LED symbol — the little triangle with a bar. That arrow means current is allowed through one way only; an LED is a kind of one-way valve for current, a cousin of the transistor and the diode built from the same semiconductor magic. The firmware doesn't care about any of that. It just writes a 1 or a 0 to the pin and lets physics do the rest. That hand-off — a line of software commanding a flow of electrons through a real device — is the entire essence of embedded systems, captured in a single blinking light.
Putting it together: the forever loop
So what does the actual firmware look like? Almost every embedded program shares one shape: a tiny bit of setup that runs once when power arrives, followed by an infinite loop that runs until the power is cut. The microwave's loop checks the keypad and updates the clock; the LED's loop simply turns the pin on, waits, turns it off, waits, and repeats. There is no 'exit', no 'quit' — an embedded program is designed to run *forever*.
// Blink an LED on a GPIO pin — the embedded 'hello, world'
int main(void) {
gpio_set_output(PIN13); // SETUP: runs once at power-up
while (1) { // LOOP: runs forever
gpio_write(PIN13, HIGH); // pin = 3.3 V → LED on
delay_ms(500); // wait half a second
gpio_write(PIN13, LOW); // pin = 0 V → LED off
delay_ms(500); // wait half a second
} // ...and back to the top, forever
}Where this track is going
You now hold the four ideas the rest of this track stands on: an embedded system is a fixed-purpose computer inside a product; a microcontroller is that computer fused onto a single chip — CPU, memory, and peripherals together; firmware is the one program living permanently in its flash; and a GPIO pin is the simplest way for that firmware to reach out and move real current in the world, governed by the same Ohm's law you already know.
From here the track adds one peripheral at a time. You'll learn to dim that LED smoothly instead of just on/off (pulse-width modulation), to react to a button the instant it's pressed without wasting power polling for it (interrupts), to keep precise time (timers), and to let your chip *talk* — sending data to sensors and other chips over serial buses. Each new peripheral is another way the firmware touches the physical world. But all of it rests on this one rung: a program, a pin, and a current you can predict.