2. C, learned properly¶
Time: 3 to 4 weeks · Board: none, your computer · Prerequisites: none
Why this matters¶
C is still the language of firmware. It is small, which is why you can learn it in a month, and unforgiving, which is why people who half-learn it spend years chasing bugs. Embedded C in particular leans on the parts general programming courses skip: pointers to fixed addresses, bit manipulation, integer widths, and the idea that a variable can change without your code touching it.
Do this module without AI assistance
This is the one place we ask you to turn the assistants off. Write every exercise yourself, read every compiler error yourself, and use the debugger instead of print statements when something is wrong. The point is not the exercises. The point is building the mental model of memory that makes everything after this possible. You get the tools back in Module 3.
You will be able to¶
- Set up a C compiler and debugger on your own machine and use them from the command line.
- Write programs with functions, structs, arrays, and pointers, and explain what each one looks like in memory.
- Use bitwise operators to set, clear, toggle, and test individual bits, and explain integer promotion.
- Say what
volatile,static,const, and fixed-width types likeuint32_tmean and when each is needed. - Recognize undefined behavior and know why the compiler is allowed to surprise you.
Learn¶
Pick one main course from the first two. Do all of the "then" items.
- Book Beej's Guide to C Programming by Brian "Beej" Hall ~25 h, free
Friendly, complete, current (C11 and later), and it does not skip pointers or memory. Our default recommendation. - Course CS50x by Harvard Weeks 1 to 5, ~40 h, free
If you prefer lectures and graded problem sets. Weeks 1 through 5 are C. Stop before Python.
Then, in this order:
- Interactive Exercism C track ~10 h, free
Small exercises with automated tests. Do at least 15. Mentoring is free too. - Video Jacob Sorber's channel Pick 5 to 10 videos, ~3 h
A CS professor explaining C, pointers, memory, and systems programming in 10-minute pieces. Search his channel for "pointers", "bit fields", "volatile", "memory layout". - Video Bit Fields in C. What are they, and how do I use them? by Jacob Sorber ~12 min
Because registers are bit fields, and you will use them constantly. - Article C Keywords to Use Often in Embedded Systems by Barr Group ~15 min
static,volatile,const: what each really does and when firmware needs it. - Article How to Use C's volatile Keyword by Barr Group ~15 min
The keyword that makes hardware registers work. Read it twice. - Article A Guide to Undefined Behavior in C and C++ by John Regehr ~30 min
Why the compiler is allowed to delete your null check, and how to stop writing code that invites it. - Interactive Compiler Explorer ~30 min to explore
Paste C, see the assembly. Try-O0vs-O2on a loop that toggles avolatilevariable and one that toggles a plain one. You will understandvolatilefor life.
The embedded-specific bits¶
- Article Important Programming Concepts (Even on Embedded Systems), Parts I to VI by Jason Sachs ~3 h total
Idempotence, immutability, volatility, singletons, state machines, abstraction. Six essays that will make you a better engineer in any language. Parts: I, II, III, IV, V, VI. - Docs cppreference: C language Reference
The precise answer to "what does this do." Bookmark it. Look upstdint.h, integer promotion, and therestrictkeyword.
Do¶
Use GCC or Clang from a terminal, and GDB or LLDB to debug. On Windows, use WSL or MSYS2 so your commands match Linux; the firmware toolchain in Module 3 will feel identical.
- Checkpoint 2.1: Bit toolkit. Write
bits.hwith functions or macros to set, clear, toggle, and test bit n of auint32_t, plus one to insert a value into a bit field given a shift and width. Write amain()that tests every one and prints the results in binary. Compile with-Wall -Wextra -Werrorand fix every warning. - Checkpoint 2.2: A fake peripheral. Define a
structthat mirrors a made-up hardware register block: a control register, a status register, and a 16-byte data buffer. Create one instance, take avolatilepointer to it, and write a "driver" with functions likeperiph_enable(),periph_write_byte(), andperiph_is_busy()that only touch the hardware through that pointer. This is exactly how real drivers work. - Checkpoint 2.3: Debugger, not printf. Introduce a deliberate off-by-one bug in the buffer code from 2.2. Find it using only the debugger: breakpoints, watch a variable, step through, inspect memory. Then write down what you saw.
Check yourself¶
- What is the difference between
char *pandchar p[]as function parameters? As global definitions? - Why does
uint8_t a = 200, b = 100; uint8_t c = a + b;not overflow the way you might expect? What is the type ofa + b? - What does
volatilepromise, and what does it not promise about concurrency? - Why is
inta bad choice for a value that must be exactly 32 bits on every platform? - Give one example of undefined behavior and one of implementation-defined behavior.
Go deeper¶
Optional extras
- Book Modern C by Jens Gustedt Free PDF
The best second book on C. Rigorous, current, and honest about the language's sharp edges. - Book Paid Effective C, 2nd Edition by Robert Seacord
By a member of the C standards committee. Excellent on undefined behavior and security. - Article Scope Regions in C and C++ by Dan Saks ~20 min
Scope, storage duration, and linkage are three different things. Saks untangles them. - Docs GCC attributes: syntax, function attributes, variable attributes and Pragmas
__attribute__((section(".vectors"))),aligned,packed,weak,naked: you will meet all of these in startup code. - Article Inline Functions in C by Richard Kettlewell ~15 min
inlinemeans something different in C than most people think. - Course The Missing Semester of Your CS Education by MIT ~10 h
Shell, editors, version control, debugging tools. The stuff nobody teaches and everyone needs.