Differences

This shows you the differences between two versions of the page.

Link to this comparison view

rasb:lab:02 [2026/06/04 19:27]
ciprian.popescu0411 created
rasb:lab:02 [2026/06/24 18:34] (current)
cezar.zlatea [Exercise 1: Identify The Renode Scenario]
Line 1: Line 1:
-===== Lab 2: =====+===== Lab 2: Renode for MCU Emulation and Validation ​===== 
 + 
 +===== Duration ===== 
 + 
 +2 hours: 
 + 
 +  * 0h30 guided introduction to Renode and the digital-twin workflow; 
 +  * 1h30 practical firmware exercise using a virtual sensor stream. 
 + 
 +===== Learning Objectives ===== 
 + 
 +After this laboratory, students should be able to: 
 + 
 +  * explain the role of Renode in embedded firmware development and testing; 
 +  * distinguish between ''​.resc''​ Renode scripts and ''​.repl''​ platform descriptions;​ 
 +  * run Raspberry Pi Pico firmware in Renode without physical hardware; 
 +  * attach a custom virtual I2C peripheral to an emulated board; 
 +  * validate firmware behavior through UART output and generated reports; 
 +  * implement and compare a naive threshold filter with a tiny fixed-point model. 
 + 
 +===== Laboratory Scenario ===== 
 + 
 +The lab uses a Raspberry Pi Pico firmware project running in a Renode digital twin. Renode provides the RP2040 board model, UART capture, and a deterministic virtual I2C sensor. No physical Pico board or sensor is required. 
 + 
 +<​code>​ 
 +[Virtual I2C sensor @ 0x52] -> sample stream -> [RP2040 firmware] 
 +</​code>​ 
 + 
 +Each virtual sensor sample contains: 
 + 
 +  * ''​seq'':​ sample number; 
 +  * ''​value'':​ signed sensor reading. 
 + 
 +The firmware must classify every sample with two methods: 
 + 
 +  * **Threshold filter**: simple hand-written ''​if''/''​else''​ logic using minimum value, maximum value, and maximum jump thresholds. 
 +  * **TinyML-style filter**: a small fixed-point linear model using weights from ''​firmware/​model_weights.h''​. 
 + 
 +The goal is not to train a model during the lab. The model weights are already provided. Students focus on running firmware in a digital twin, reading the virtual sensor, implementing the inference formula, and comparing the two filtering methods. 
 + 
 +===== Project Layout ===== 
 + 
 +The important files are: 
 + 
 +<​code>​ 
 +firmware/​main.c 
 +firmware/​model_weights.h 
 +renode/​run_test.resc 
 +renode/​run_metrics.resc 
 +renode/​sensor_i2c.repl 
 +renode/​peripherals/​VirtualSensorStream.cs 
 +docker/​scripts/​build_firmware.sh 
 +docker/​scripts/​run_test.sh 
 +docker/​scripts/​generate_report.py 
 +docs/​renode_primer.md 
 +docs/​exercise_guide.md 
 +reference/​firmware/​main.c 
 +output/​report.html 
 +</​code>​ 
 + 
 +Short description:​ 
 + 
 +  * ''​firmware/​main.c''​ contains the student TODOs. 
 +  * ''​firmware/​model_weights.h''​ contains the fixed-point model constants. 
 +  * ''​renode/​run_test.resc''​ creates the Renode scenario, loads firmware, and captures UART output. 
 +  * ''​renode/​sensor_i2c.repl''​ connects the virtual sensor to the Pico I2C bus. 
 +  * ''​renode/​peripherals/​VirtualSensorStream.cs''​ implements the deterministic I2C sensor stream. 
 +  * ''​docker/​scripts/​run_test.sh''​ validates the UART output and final summary. 
 +  * ''​docker/​scripts/​generate_report.py''​ creates ''​output/​report.html''​. 
 +  * ''​reference/​firmware/​main.c''​ contains the completed instructor reference implementation. 
 + 
 +===== Part 1: Renode Theory ===== 
 + 
 +==== What Renode Is ==== 
 + 
 +Renode is an emulator for embedded systems. It can run firmware built for a microcontroller or SoC inside a virtual machine that includes CPUs, buses, memories, UARTs, timers, and peripherals. 
 + 
 +For this laboratory, Renode gives us a repeatable digital twin: 
 + 
 +  * the same Pico firmware is loaded every run; 
 +  * the same deterministic virtual sensor samples are produced every run; 
 +  * the same validation script checks the UART output every run. 
 + 
 +This makes the exercise independent of physical boards, USB cables, sensor availability,​ and lab hardware differences. 
 + 
 +==== Digital Twin Mental Model ==== 
 + 
 +A Renode lab scenario has three layers: 
 + 
 +  * firmware: the compiled application,​ here ''​firmware.elf'';​ 
 +  * virtual hardware: the Raspberry Pi Pico plus a custom I2C sensor; 
 +  * automation: the ''​.resc''​ script that creates, wires, runs, and observes the machine. 
 + 
 +In this lab: 
 + 
 +<​code>​ 
 +firmware/​main.c ​                     -> compiled to firmware.elf 
 +renode/​peripherals/​VirtualSensorStream.cs -> custom I2C peripheral 
 +renode/​sensor_i2c.repl ​              -> virtual wiring overlay 
 +renode/​run_test.resc ​                -> Renode automation script 
 +</​code>​ 
 + 
 +==== RESC Files ==== 
 + 
 +''​.resc''​ files are Renode monitor scripts. They automate what an instructor could otherwise type manually in the Renode monitor. 
 + 
 +The lab script is ''​renode/​run_test.resc''​. It performs these jobs: 
 + 
 +  * makes the RP2040 Renode support visible; 
 +  * loads the custom C# sensor peripheral;​ 
 +  * creates a Raspberry Pi Pico machine; 
 +  * applies the I2C wiring overlay; 
 +  * loads the compiled firmware; 
 +  * captures UART output; 
 +  * runs the emulation for a fixed time. 
 + 
 +Typical commands in this scenario: 
 + 
 +<​code>​ 
 +path add @/​opt/​renode-rp2040 
 +include @/​workspace/​renode/​peripherals/​VirtualSensorStream.cs 
 +EnsureTypeIsLoaded "​Antmicro.Renode.Peripherals.I2C.VirtualSensorStream"​ 
 +include @boards/​initialize_raspberry_pico.resc 
 +machine LoadPlatformDescription @/​workspace/​renode/​sensor_i2c.repl 
 +sysbus LoadELF @/​workspace/​build/​firmware.elf 
 +sysbus.uart0 CreateFileBackend @/​workspace/​output/​uart_output.txt true 
 +emulation RunFor "​00:​00:​05"​ 
 +</​code>​ 
 + 
 +Key idea: ''​.resc''​ files describe the experiment procedure. 
 + 
 +==== REPL Files ==== 
 + 
 +''​.repl''​ files describe platform topology: which peripherals exist and where they are connected. 
 + 
 +This lab uses a small overlay instead of redefining the whole Pico: 
 + 
 +<​code>​ 
 +sensor: I2C.VirtualSensorStream @ i2c0 0x52 
 +</​code>​ 
 + 
 +Read it as: 
 + 
 +  * create a peripheral instance named ''​sensor'';​ 
 +  * instantiate the Renode type ''​I2C.VirtualSensorStream'';​ 
 +  * attach it to bus ''​i2c0'';​ 
 +  * expose it at I2C address ''​0x52''​. 
 + 
 +Key idea: ''​.repl''​ files describe the virtual wires. 
 + 
 +==== Custom Virtual Peripheral ==== 
 + 
 +''​VirtualSensorStream.cs''​ is a minimal Renode I2C peripheral. It models only the behavior needed by this lab: 
 + 
 +  * firmware writes register ''​0x00'';​ 
 +  * firmware reads four bytes; 
 +  * the sensor returns a frame: ''​seq:​uint16_be''​ and ''​value:​int16_be'';​ 
 +  * each complete frame advances to the next sample. 
 + 
 +The component implements the Renode I2C peripheral interface. It is intentionally not a complete real sensor. For this exercise, deterministic behavior is more important than detailed physical realism. 
 + 
 +The virtual wiring path is: 
 + 
 +<​code>​ 
 +run_test.resc 
 +  loads VirtualSensorStream.cs 
 +  initializes Raspberry Pi Pico 
 +  applies sensor_i2c.repl 
 + 
 +sensor_i2c.repl 
 +  connects VirtualSensorStream to i2c0 address 0x52 
 + 
 +firmware/​main.c 
 +  initializes i2c0 on the Pico pins 
 +  writes register 0x00 
 +  reads 4-byte sample frames 
 +</​code>​ 
 + 
 +==== Validation Surface ==== 
 + 
 +The validation harness does not inspect C variables directly. It checks the observable firmware behavior through UART output. 
 + 
 +Important UART lines: 
 + 
 +<​code>​ 
 +SAMPLE seq=... value=... 
 +THRESHOLD seq=... decision=... 
 +MODEL seq=... decision=... score=... 
 +DISAGREE seq=... 
 +SUMMARY threshold_keep=... threshold_drop=... model_keep=... model_drop=... disagreements=... 
 +</​code>​ 
 + 
 +This is close to a real board workflow: the observable interface is serial output plus emulator logs and generated reports. 
 + 
 +===== Part 2: Running The Starter ===== 
 + 
 +From the browser IDE, press **Run** in the side panel. 
 + 
 +From a shell: 
 + 
 +<code bash> 
 +./run.sh up --build digital-twin 
 +</​code>​ 
 + 
 +The starter code should build and read the sensor stream. The filter checks fail until students implement the TODO functions. 
 + 
 +Expected final passing summary after implementation:​ 
 + 
 +<​code>​ 
 +SUMMARY threshold_keep=8 threshold_drop=2 model_keep=6 model_drop=4 disagreements=2 
 +>>>​ ALL CHECKS PASSED - sensor filters behave as expected <<<​ 
 +</​code>​ 
 + 
 +The HTML report is written to: 
 + 
 +<​code>​ 
 +output/​report.html 
 +</​code>​ 
 + 
 +===== Part 3: Exercise Data ===== 
 + 
 +The virtual sensor emits this deterministic stream: 
 + 
 +^ Seq ^ Value ^ Intended role ^ 
 +| 0 | 500 | normal baseline | 
 +| 1 | 506 | small normal movement | 
 +| 2 | 612 | borderline jump | 
 +| 3 | 520 | return to normal | 
 +| 4 | 785 | high outlier | 
 +| 5 | 532 | normal | 
 +| 6 | 340 | low outlier | 
 +| 7 | 650 | borderline jump | 
 +| 8 | 545 | normal | 
 +| 9 | 498 | normal | 
 + 
 +The threshold filter should reject only the gross high and low outliers: 
 + 
 +<​code>​ 
 +seq=4 
 +seq=6 
 +</​code>​ 
 + 
 +The tiny model should reject the two gross outliers and two borderline jumps: 
 + 
 +<​code>​ 
 +seq=2 
 +seq=4 
 +seq=6 
 +seq=7 
 +</​code>​ 
 + 
 +Therefore, the two methods disagree at: 
 + 
 +<​code>​ 
 +seq=2 
 +seq=7 
 +</​code>​ 
 + 
 +===== Part 4: Exercises ===== 
 + 
 +==== Exercise 1: Identify The Renode Scenario ==== 
 + 
 +Open ''​renode/​run_test.resc''​. 
 + 
 +Tasks: 
 + 
 +  - Find the command that loads ''​VirtualSensorStream.cs''​. 
 +  - Find the command that initializes the Raspberry Pi Pico machine. 
 +  - Find the command that applies ''​sensor_i2c.repl''​. 
 +  - Find the command that loads ''​firmware.elf''​. 
 +  - Find where UART output is written. 
 + 
 +Questions:​ 
 + 
 +  - Which file describes the virtual sensor wiring? 
 +  - Which bus is the sensor attached to? 
 +  - What I2C address does the sensor use? 
 +  - Which output file contains firmware UART logs? 
 + 
 +hints: 
 + 
 +  * wiring file: ''​renode/​sensor_i2c.repl'';​ 
 +  * bus: ''​i2c0'';​ 
 +  * I2C address: ''​0x52'';​ 
 +  * UART output: ''/​workspace/​output/​uart_output.txt''​. 
 + 
 +==== Exercise 2: Follow One Sensor Sample End To End ==== 
 + 
 +Files to inspect: 
 + 
 +<​code>​ 
 +renode/​peripherals/​VirtualSensorStream.cs 
 +renode/​sensor_i2c.repl 
 +firmware/​main.c 
 +</​code>​ 
 + 
 +Tasks: 
 + 
 +  - In ''​VirtualSensorStream.cs'',​ find the deterministic sample table. 
 +  - Find the code that returns a 4-byte sample frame. 
 +  - In ''​firmware/​main.c'',​ find the code that reads one sample from I2C. 
 +  - Run the validation and locate the UART line for ''​seq=0''​. 
 + 
 +Fill the table: 
 + 
 +^ Step ^ File ^ Evidence ^ 
 +| Sensor provides sample table |  |  | 
 +| REPL connects sensor to I2C |  |  | 
 +| Firmware reads sample frame |  |  | 
 +| Firmware prints sample |  |  | 
 +| Harness validates sample count |  |  | 
 + 
 +==== Exercise 3: Implement The Threshold Filter ==== 
 + 
 +Open ''​firmware/​main.c''​ and implement:​ 
 + 
 +<code c> 
 +threshold_filter_should_keep 
 +</​code>​ 
 + 
 +Rules: 
 + 
 +  * drop values below ''​THRESHOLD_MIN_VALUE'';​ 
 +  * drop values above ''​THRESHOLD_MAX_VALUE'';​ 
 +  * drop values whose absolute jump from ''​previous_kept''​ is greater than ''​THRESHOLD_MAX_JUMP'';​ 
 +  * keep all other values. 
 + 
 +Expected threshold drops: 
 + 
 +<​code>​ 
 +seq=4 
 +seq=6 
 +</​code>​ 
 + 
 +After this exercise, some checks may still fail because the model filter is not implemented yet. 
 + 
 +==== Exercise 4: Implement The Tiny Fixed-Point Model Score ==== 
 + 
 +Open: 
 + 
 +<​code>​ 
 +firmware/​main.c 
 +firmware/​model_weights.h 
 +</​code>​ 
 + 
 +Implement:​ 
 + 
 +<code c> 
 +model_filter_score 
 +</​code>​ 
 + 
 +The model uses two features: 
 + 
 +<​code>​ 
 +abs_center = abs(value - MODEL_CENTER_VALUE) 
 +abs_jump ​  = abs(value - previous_kept) 
 +</​code>​ 
 + 
 +The score formula is: 
 + 
 +<code c> 
 +score = MODEL_BIAS_Q0 
 +      + MODEL_WEIGHT_ABS_CENTER_Q0 * abs_center 
 +      + MODEL_WEIGHT_ABS_JUMP_Q0 * abs_jump; 
 +</​code>​ 
 + 
 +This model is intentionally tiny: 
 + 
 +  * it uses integer arithmetic;​ 
 +  * there is no runtime training; 
 +  * all weights are already provided; 
 +  * the goal is to understand how a compact model can replace hand-written thresholds. 
 + 
 +==== Exercise 5: Implement The TinyML Keep/Drop Decision ==== 
 + 
 +Implement:​ 
 + 
 +<code c> 
 +model_filter_should_keep 
 +</​code>​ 
 + 
 +Rule: 
 + 
 +  * keep the sample if ''​score >= MODEL_KEEP_THRESHOLD_Q0'';​ 
 +  * drop it otherwise. 
 + 
 +Expected model drops: 
 + 
 +<​code>​ 
 +seq=2 
 +seq=4 
 +seq=6 
 +seq=7 
 +</​code>​ 
 + 
 +Run the validation again. The final summary should be: 
 + 
 +<​code>​ 
 +SUMMARY threshold_keep=8 threshold_drop=2 model_keep=6 model_drop=4 disagreements=2 
 +</​code>​ 
 + 
 +==== Exercise 6: Compare The Two Methods ==== 
 + 
 +Use ''​output/​report.html''​ and UART output to answer: 
 + 
 +  - Which samples are rejected by both methods? 
 +  - Which samples are accepted by the threshold filter but rejected by the model? 
 +  - Why do the two methods disagree at ''​seq=2''​ and ''​seq=7''?​ 
 +  - Which method is easier to explain? 
 +  - Which method is easier to tune if the data distribution changes? 
 + 
 +hint: 
 + 
 +  * the threshold filter catches large absolute outliers and large immediate jumps; 
 +  * the model uses both distance from a learned center and distance from the previous accepted model value; 
 +  * the model is stricter on borderline jump samples because both features contribute to the score. 
 + 
 +==== Exercise 7: Optional Extension ==== 
 + 
 +Choose one: 
 + 
 +  * change one threshold constant and explain how the final summary changes; 
 +  * add one more sample to ''​VirtualSensorStream.cs''​ and update the expected summary; 
 +  * change one model weight and explain which samples become more or less likely to be kept; 
 +  * update ''​docker/​scripts/​generate_report.py''​ to make disagreements easier to inspect in the HTML report. 
 + 
 + 
 + 
 +===== Common Problems ===== 
 + 
 +==== Docker Socket Errors ==== 
 + 
 +If Docker cannot connect to the daemon, try: 
 + 
 +<code bash> 
 +DOCKER_HOST=unix:///​var/​run/​docker.sock ./run.sh up --build digital-twin 
 +</​code>​ 
 + 
 +If group membership was just changed and the current shell has not picked it up, use: 
 + 
 +<code bash> 
 +sg docker -c '​DOCKER_HOST=unix:///​var/​run/​docker.sock ./run.sh up --build digital-twin'​ 
 +</​code>​ 
 + 
 +==== Firmware Builds But Samples Are Wrong ==== 
 + 
 +Check: 
 + 
 +  * ''​renode/​sensor_i2c.repl''​ connects the sensor to ''​i2c0''​ at ''​0x52'';​ 
 +  * firmware uses the same I2C address; 
 +  * the virtual sensor preserves a whole sample frame across byte-wise reads. 
 + 
 +==== Validation Fails After Editing ==== 
 + 
 +Use evidence in this order: 
 + 
 +  - ''​output/​report.html''​ for the high-level failing check; 
 +  - ''​output/​uart_output.txt''​ for firmware-side behavior; 
 +  - ''​renode/​run_test.resc''​ and ''​renode/​sensor_i2c.repl''​ for wiring issues; 
 +  - ''​VirtualSensorStream.cs''​ for sample stream issues. 
 + 
 +==== Starter Code Fails Filter Checks ==== 
 + 
 +This is expected. The starter code reads the sensor but does not yet implement the threshold and model decisions correctly. 
 + 
rasb/lab/02.1780590459.txt.gz · Last modified: 2026/06/04 19:27 by ciprian.popescu0411
CC Attribution-Share Alike 3.0 Unported
www.chimeric.de Valid CSS Driven by DokuWiki do yourself a favour and use a real browser - get firefox!! Recent changes RSS feed Valid XHTML 1.0