Milestone map
Milestone map
3 milestones
Set up the embedded development environment and implement a hardware abstraction layer
2–3 weeks (environment setup + HAL implementation + test)
Set up a working embedded development environment for a real microcontroller board or a free online simulator. Acceptable platforms: Arduino Uno/Nano/Mega (free Arduino IDE), Raspberry Pi Pico (free MicroPython or C SDK), STM32 Nucleo (free STM32CubeIDE), ESP32/ESP8266 (free Arduino IDE or ESP-IDF), or — with no hardware available — Wokwi (free browser-based simulator supporting Arduino, ESP32, and Raspberry Pi Pico). Implement a hardware abstraction layer (HAL) for at least two peripherals required by the firmware system you plan to build in M2: write driver functions for the peripheral (e.g. `led_init()`, `led_set(state)`, `uart_send(byte)`, `sensor_read_raw()`) that expose a clean interface hiding the register-level or library-level details. Confirm the HAL works by running a simple test for each peripheral (e.g. LED blinks at 1 Hz, UART sends a known byte sequence, sensor returns a value in the expected range).
Proof required
Submit: (1) a brief system overview (100–150 words) stating the target platform, the two peripherals your HAL covers, and the firmware system you plan to build in M2; (2) the HAL source code for both peripherals (in a public GitHub repository or Wokwi project link); (3) a short video or GIF (30–60 seconds) or Wokwi simulation link showing the HAL test running — each peripheral demonstrating its expected behaviour; (4) a confirmation that the development environment compiles and uploads without errors (screenshot of the IDE/terminal with a clean build output).
What gets checked
- HAL functions expose a clean interface with no hardware-specific constants or register names visible to the caller — a function called `sensor_read_raw()` that returns an integer is a valid HAL function; a function that requires the caller to pass a GPIO pin number and an ADC channel number is register-level code exposed to the caller, not a HAL
- Each peripheral has at least two HAL functions (init and at least one operation function) — a HAL with only one function per peripheral has not separated initialisation from operation
- The test proof shows the expected behaviour in real time — a static photo of the hardware is not sufficient; video, GIF, or Wokwi simulation link showing the peripheral operating is required
Common mistakes
- Using Arduino library functions directly in the application code rather than wrapping them in HAL functions — `digitalWrite(LED_PIN, HIGH)` in main application logic is not abstracted; the HAL wraps this into `led_set(LED_ON)` so the application is hardware-independent
- Selecting a firmware system for M2 that uses only one peripheral — the firmware must justify the two-peripheral HAL; a system that only blinks an LED does not demonstrate HAL design principles
Resources
Foundationstart here
Depthgo deeper
Masteryfor the dedicated
What a verifier looks for
- Engineering Design Triad: M1 produces a design artifact (HAL source code with clean interface) and an analysis artifact (test demonstration showing each peripheral's correct behaviour) — both must be present.
- HAL interface must hide hardware details — check that application-level code never passes GPIO pin numbers, register addresses, or ADC channel numbers; only semantic function names and values.
- Test proof must show real-time behaviour — static photos are not sufficient; video, GIF, or Wokwi simulation link required.
- Clean build output must be shown — a compilation error in the screenshot fails M1.
- Reviewer must be a software or electrical engineer with embedded systems development experience — HAL design quality and peripheral driver correctness require domain expertise.
Implement and test a complete firmware application using the HAL
3–4 weeks (firmware implementation + FSM + testing)
Implement a complete firmware application using the HAL from Milestone 1. The application must: use both peripherals from the HAL; implement a finite state machine (FSM) or event-driven architecture with at least three distinct states or event types; and meet at least one real-time constraint (e.g. sensor sampled at a fixed interval, LED pattern with precise timing, UART response within a bounded delay). Examples of complete applications: a temperature-monitored fan controller (temperature sensor HAL + PWM fan HAL + UART status reporting; FSM states: idle, cooling, alert); a door access controller (keypad HAL + LED/buzzer HAL; FSM states: locked, entering code, unlocked, alarm); a data logger (sensor HAL + SD card/UART HAL; event loop: sample, format, transmit). Write at least five unit tests or integration tests that verify the FSM transitions and the real-time constraint. Free tools: Wokwi for simulation; Unity Test Framework (free) for C firmware tests; or Arduino's own `assert()` for simple test cases.
Proof required
Submit: (1) the complete firmware application source code in a public GitHub repository or Wokwi project; (2) the FSM diagram (state diagram with states, transitions, and trigger conditions — draw.io is free); (3) the five test cases with expected and actual outputs (as code with assertion statements, or as a documented test log); (4) a video or Wokwi simulation link showing the application running through at least two FSM state transitions.
What gets checked
- FSM is implemented as an explicit state variable and a transition table or switch statement — an implicit FSM (a series of if/else blocks with no named states) does not demonstrate FSM design; the state enum or constant names must appear in the code
- Real-time constraint is verified in the test cases — if the design requires 100 ms sensor sampling, a test case must confirm this (e.g. measure the actual interval using the system timer and assert it is within ±10%)
- Five test cases exercise distinct behaviour — five tests that all check the LED state in the idle state are not five distinct tests; tests must cover at least three different FSM states or event types
Common mistakes
- Implementing the application without using the HAL — calling `digitalWrite()` or hardware library functions directly in the application layer defeats the purpose of the M1 HAL; all hardware access must go through the HAL functions
- Writing tests that only verify compilation rather than behaviour — a test that calls `led_init()` and checks that it returns without crashing is not a behavioural test; tests must check observable outputs against expected values
Resources
Foundationstart here
Depthgo deeper
Masteryfor the dedicated
What a verifier looks for
- FSM must be explicit — check that state names appear as enum values or named constants in the code, not as implicit flags or boolean combinations.
- All hardware access must go through HAL functions — check that the application layer contains no direct GPIO, ADC, or UART register/library calls.
- Real-time constraint must be verified in a test case — check that the timing requirement from the design brief appears as an assertion in the test log.
- Five test cases must cover distinct FSM states or event types — check that the tests are not all testing the same state.
- Reviewer must have embedded systems firmware development experience — FSM design quality, HAL boundary correctness, and real-time constraint verification require domain expertise.
Produce a firmware design document and conduct a code review
1–2 weeks (document + code review session + code update)
Produce a firmware design document covering the complete system from Milestone 1 and Milestone 2. The document must include: a system architecture section (block diagram showing HAL layer, application layer, and peripheral hardware; from M1); the FSM specification (state diagram + state/transition table; from M2); the real-time constraints and how they are met (timing analysis); a known limitations section (at least two limitations of the current implementation — e.g. no error recovery if sensor disconnected, timer interrupt not used so timing is approximate); and a future improvements section (at least two specific improvements, each with a brief technical rationale). Present the firmware code and design document to a qualified reviewer (software or electrical engineer with embedded systems experience) in a structured code review session of 30–45 minutes. The reviewer must identify at least two specific code issues (style, correctness, or robustness concerns) that the author must address.
Proof required
Submit: (1) the firmware design document (all sections above, 600–900 words); (2) the code review record — the reviewer's two specific issues (with file name and line number or function name), the author's response, and whether each issue was addressed in a code update (200 words minimum, attributing reviewer by professional role); (3) the updated code with the two issues addressed (GitHub commit link showing the changes).
What gets checked
- Known limitations are specific and technical — 'if the temperature sensor is disconnected, the ADC returns a floating value that the FSM interprets as a temperature of −40°C and enters the cooling state indefinitely' is a valid limitation; 'could be improved' is not
- Code review record includes file/line or function references — 'the reviewer identified that `sensor_read_raw()` has no bounds check on the return value (sensor.c line 34), which could cause the FSM to enter an invalid state if the ADC returns a value above 1023' is a valid record entry
- Code updates are visible in a GitHub commit — the reviewer's issues must map to traceable changes in the repository; verbal claims that issues were fixed without visible code changes cannot be verified
Common mistakes
- Presenting to a reviewer who has not read the code before the review session — a code review requires the reviewer to have read the code before the meeting; a first-read during the session is a walkthrough, not a review
- Addressing reviewer issues by adding comments rather than fixing the code — a comment that says 'TODO: add bounds check here' is not a fix; the bounds check must be implemented
Resources
Foundationstart here
What a verifier looks for
- Engineering Design Triad check: M1–M3 together produce a design artifact (HAL source code + FSM diagram + system architecture diagram), an analysis artifact (test cases with expected/actual outputs + timing analysis), and a documentation artifact (firmware design document + code review record with addressed issues) — confirm all three types are present.
- Known limitations must be specific and technical — check that each limitation describes a specific failure mode, not a general area for improvement.
- Code review record must include file/line references — check that the issues are locatable in the submitted code.
- Code updates must be visible as a GitHub commit — the commit must be traceable to the reviewer's specific issues.
- Reviewer must have embedded systems firmware development experience — code review quality for embedded firmware requires domain-specific knowledge of memory management, interrupt safety, and real-time constraints.
- The Proof Accessibility Rule applies — Wokwi, Arduino IDE, PlatformIO, Unity, and draw.io are all free.