All outcomes
Skills

Embedded Firmware Implementation

8 weeks · 0 milestones

Implement firmware for a real or simulated embedded system, demonstrating correct hardware control and documented test coverage. The firmware must: control at least 2 distinct hardware peripherals (e.g. read a sensor over I2C and drive an actuator over PWM), handle at least one interrupt-driven event (timer, external interrupt, or serial receive) with documented rationale for the interrupt strategy, implement a defined state machine with at least 4 states and documented transition conditions, and include a documented unit test or hardware-in-the-loop test for each peripheral driver with pass/fail criteria. Code must be readable and documented — variable names, function names, and inline comments must enable a reviewer to follow the logic without running the code. Preferred proof: firmware running on physical hardware (Arduino, ESP32, STM32, or equivalent) with oscilloscope or serial monitor evidence of correct operation. Accessible alternative: firmware implementation and simulation in Wokwi (free, browser-based) with simulation waveform or serial output evidence of correct operation; GitHub public repository with commit history. Proof artifacts: the firmware source code with state machine implementation (design artifact) and the test results or simulation evidence (analysis artifact). Verification: an embedded firmware engineer reviews 'what happens if this interrupt fires while the state machine is in state X?' and 'how does this driver behave if the hardware does not respond to the I2C address?' — requiring you to reason about your own interrupt and error-handling logic.

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.

We use analytics to improve Powstik. No ads, ever.