The problem
Vehicle makers want to consolidate functions onto fewer ECUs, but a BMS protection task and a dashboard animation have very different safety requirements. If they share a processor, an overrun in a low-criticality task must never cause a high-criticality deadline miss, and the system should still give as much low-criticality service as possible.
Objectives
- Define a dual-criticality task set from EV functions with LO and HI execution-time budgets.
- Implement budget monitoring and a criticality mode switch on top of FreeRTOS.
- Implement at least two policies: drop LO tasks, and degrade LO tasks (longer periods or reduced work).
- Add CAN traffic as a real interrupt load and measure its effect on mode switches.
- Compare against plain rate-monotonic scheduling on deadline misses, mode-switch latency and LO-task quality of service.
What you need
From the EV Embedded Development Kit
- STM32F103C8T6 microcontroller unit (Arm Cortex-M3)
- 1S battery with connector and T-sense input
- Charge/discharge control relay
- Load section: three switchable resistive loads with LEDs
- CAN bus interface
- 16×2 LCD
- 4×3 matrix keypad
- SPI flash memory
- Serial UART interface
Software
- STM32CubeIDE
- Embedded C with HAL drivers
- FreeRTOS
- Python with python-can, pandas and matplotlib
- Python schedulability analysis scripts
Extra parts
- A USB-CAN adapter — To act as the other vehicle nodes: it receives the ECU's frames and injects controlled bursts of CAN traffic that raise interrupt load during experiments.
This project uses the kit's lithium cell. Respect polarity, never short the terminals, and don't leave the cell charging unattended.
Key concepts
- Mixed-criticality system
- A system where tasks of different assurance levels share hardware. Each task has a criticality level and, in the Vestal model, a separate execution-time budget per level.
- Criticality mode switch
- When a HI task exceeds its LO budget, the system enters HI mode and stops guaranteeing LO tasks so that HI tasks can use their larger, more pessimistic budgets.
- AMC (Adaptive Mixed Criticality)
- A fixed-priority response-time analysis for mixed-criticality systems that checks LO mode, HI mode and the transition between them.
- Budget enforcement
- Monitoring each job's consumed CPU time at run time and acting when it exceeds its allowance, here using the DWT cycle counter and FreeRTOS context-switch hooks.
- Temporal isolation
- The guarantee that one task's timing behaviour cannot disturb another's. Without memory protection on the F103, this project addresses time only, not memory isolation.
Step-by-step guide
- 1
Specify the task set and criticality levels
Choose HI tasks: cell voltage and temperature sampling, over-voltage, under-voltage and over-temperature protection acting on the charge/discharge relay, and a CAN safety heartbeat. Choose LO tasks: LCD dashboard, keypad menu, logging to SPI flash and a diagnostic UART console. For each HI task define a LO budget (measured typical worst) and a HI budget (a safe upper bound). Write the deadlines from the physics: protection must open the relay within a stated time of a limit being crossed.
Checkpoint: A task table with criticality, period, deadline and C(LO) and C(HI) for every task, reviewed against the EV function each represents.
- 2
Set up the board and FreeRTOS
Configure the main STM32 for 72 MHz, ADC with DMA on the battery and T-sense channels, CAN at 500 kbit/s (prescaler 4, 18 time quanta at APB1 36 MHz), SPI for the flash, the LCD and keypad GPIOs and a UART for logging. Enable only the DIP switches of the blocks you use. Use FreeRTOS with static allocation and a 1 kHz tick. Connect the USB-CAN adapter to the CAN screw terminal with 120 ohm termination at both ends. Handle the cell carefully: check polarity and never short the terminals.
Checkpoint: All tasks run under plain FreeRTOS fixed priorities, CAN frames appear on the PC, and the relay responds to a protection threshold.
- 3
Measure execution budgets
Instrument each task with the DWT cycle counter (enable TRCENA, then CYCCNTENA) and log per-job execution time while exercising all inputs: loads switched, potentiometer swept, keypad active and CAN bursts arriving. Use the high-water mark plus margin as C(LO). For C(HI) use either a static bound for short HI tasks or a larger margin you justify. Keep the raw distributions, as reviewers will ask how budgets were chosen.
Checkpoint: Execution-time histograms per task, with C(LO) and C(HI) marked and justified.
- 4
Analyse the task set offline
Implement in Python plain response-time analysis and AMC-rtb (the response-time bound variant of Adaptive Mixed Criticality). Check whether the set is schedulable in LO mode, in HI mode and across the switch. Use the analysis to set priorities, for example Audsley's optimal priority assignment, and to find the largest LO workload the system can carry. This gives the prediction the hardware experiment will test.
Checkpoint: The analysis states which task sets are schedulable under RM and under AMC, with predicted worst response times per task and mode.
- 5
Implement budget monitoring
Use traceTASK_SWITCHED_IN and traceTASK_SWITCHED_OUT hooks to accumulate each job's consumed cycles. Arm a hardware timer (for example TIM2 in one-shot mode) when a HI task starts, set to expire at its remaining C(LO), so an overrun is detected at the instant it happens rather than at the next tick. In the timer ISR, signal a high-priority mode-manager task through a task notification. Keep the ISR short and constant-time.
Checkpoint: An injected overrun in a HI task (a calibrated busy loop enabled by a keypad key) is detected within a measured, bounded time.
- 6
Implement mode-switch policies
In the mode-manager, implement policy A: suspend all LO tasks with vTaskSuspend and record the switch time. Implement policy B: keep LO tasks but stretch their periods and reduce their work, for example the LCD refreshes once a second and logging writes summaries only. Implement a return-to-LO rule, such as switching back at the next idle instant when no HI job is pending. Show the current mode on the RGB LED and log every transition with an RTC-free cycle timestamp.
Checkpoint: Mode switches and returns work repeatedly under injected overruns, with the mode visible on the LED and logged over UART.
- 7
Add CAN interrupt load
From the PC, use python-can to send CAN bursts at increasing rates, from a few frames per second up to near saturation at 500 kbit/s. Each received frame enters the CAN RX ISR and a filter bank, which steals CPU time from every task. Measure ISR cost and include it as interference in the analysis. Check whether high bus load alone can trigger spurious mode switches, which is an important practical result.
Checkpoint: A plot of CPU time spent in CAN ISRs versus bus load, and the bus load at which the first spurious mode switch occurs, if any.
- 8
Run the comparison experiments
Run the same scenarios under three schedulers: plain rate-monotonic, AMC with policy A and AMC with policy B. Scenarios combine overrun probability, overrun size and CAN load. Each run lasts long enough to collect thousands of jobs per task. Record deadline misses per task, worst response times, the latency from overrun to switch, and the fraction of LO jobs completed. Repeat each scenario at least five times.
Checkpoint: No HI deadline misses under either AMC policy in any run, and a quantified LO service level for each policy.
- 9
Compare analysis with hardware
Plot predicted against observed worst response times for each task and mode. Any observed value above the prediction means the analysis model is missing an effect, such as CAN interrupts, tick overhead or the cost of vTaskSuspend, and must be fixed before conclusions are drawn. Report the pessimism of the analysis as a ratio. Also check the mode-switch transition itself, where carry-over jobs from LO mode can produce the worst response times of all, and record which scenario produced each task's maximum.
Checkpoint: Every observed response time is at or below the prediction, with pessimism ratios tabulated.
- 10
Document the study
Write up the task model, the budget-selection method, the scheduler implementation and its overheads, the experiments and the results with confidence intervals. Discuss limits honestly: no MPU means a faulty LO task can still corrupt memory, so this is temporal isolation only. Package the firmware and scripts so every figure can be regenerated. Include a table of scheduler overheads in cycles and bytes of RAM so other researchers can judge whether the method fits their own controllers, and list every parameter used in each experiment.
Checkpoint: A complete chapter draft and a repository that rebuilds the firmware and reproduces the plots from logged data.
Testing & validation
- Zero HI-criticality deadline misses across all AMC runs with injected overruns.
- Overrun-to-switch latency measured and bounded below a stated value.
- Observed response times never exceed AMC-predicted values.
- LO-task completion rate reported for each policy and load level.
Expected results
A working mixed-criticality FreeRTOS extension on the STM32F103, an analysis tool that predicts its behaviour, and measured evidence of how each policy protects BMS safety tasks and how much dashboard and logging service it preserves.
Research angle for your PhD
Research questions: how well do mixed-criticality models from scheduling theory hold on a real low-end MCU with interrupt-driven CAN traffic and kernel overheads? Which degradation policy maximises LO service without risking HI deadlines? Metrics: HI deadline-miss rate (target zero), overrun-to-switch latency, LO job completion ratio, scheduler overhead in cycles and memory, analysis pessimism. Baselines: plain rate-monotonic, AMC-rtb with task dropping, and degradation policies from the literature. Publishable contributions would be measured evidence that existing analysis misses a practical effect (for example interrupt interference during the mode switch) together with a corrected analysis, or a lightweight open-source implementation with characterised overheads on a Cortex-M3.
Take it further
- Add a third criticality level for CAN diagnostics.
- Port the scheduler to run on the second STM32 (Smart BMS unit) and study end-to-end timing between the two controllers.
- Evaluate elastic task models where LO periods stretch continuously rather than in steps.
- Measure energy or CPU idle time saved by the degraded modes.
Viva and review questions
Why have two execution budgets for a HI task?
C(LO) is a realistic estimate used for normal operation, and C(HI) is a pessimistic bound the safety case needs. Designing everything to C(HI) wastes capacity, so the system runs on C(LO) and switches mode only if a HI task actually exceeds it.
How do you detect an overrun at the exact moment it happens?
A hardware timer is armed with the remaining LO budget when the HI job is scheduled in, and paused when it is switched out. Its interrupt fires at the instant the budget is exhausted.
Does your design isolate a faulty dashboard task from the BMS?
Only in time. The STM32F103 has no memory protection unit, so a LO task with a pointer bug could still corrupt HI data; that would need an MPU-equipped part or separate controllers.
Why did CAN traffic matter?
Every received frame runs an ISR above all tasks, so heavy bus load is interference that the basic task model ignores. We measured it and added it to the analysis.