The problem
Many automotive suppliers, including Indian tier-2 companies, have legacy ECU code that must move to AUTOSAR to meet customer requirements. Migration is expensive and its overheads, RTE indirection, extra layers, memory and timing, are often argued from opinion. A careful empirical study of migration strategies on a real, if small, ECU code base gives evidence for these decisions.
Objectives
- Select and characterise a legacy EV ECU firmware as the baseline.
- Define migration strategies and the target AUTOSAR architecture.
- Carry out three migrations with careful effort logging.
- Measure memory, CPU, timing and functional equivalence for each.
- Analyse which factors drive migration effort and overhead.
What you need
Tools and toolboxes
- AUTOSAR Blockset — Defining components, interfaces and runnables and exporting ARXML for the migrated architecture.
- Embedded Coder — Generating code for re-modelled components.
- Simulink and Stateflow — Re-modelling legacy functions in the full re-modelling strategy.
- STM32CubeIDE with Embedded C — Legacy code, wrapped components, hand-written RTE and basic software layers.
- Python with lizard and python-can — Code metrics such as size and complexity, and back-to-back tests over CAN.
- Git — Tracking every change so code churn and effort can be measured per strategy.
From the EV Embedded Development Kit
- STM32F103C8T6 microcontroller unit (Arm Cortex-M3)
- CAN bus interface with screw terminal
- Analog potentiometer input
- 16×2 LCD
- RGB LEDs and a buzzer
- Serial UART interface
Software
- STM32CubeIDE with STM32 HAL and arm-none-eabi tools
- MATLAB, Simulink, Stateflow, AUTOSAR Blockset and Embedded Coder
- Python 3 with lizard, python-can and pandas
- Git
Extra parts and data
- USB-CAN adapter — Drives identical CAN test inputs and records outputs for back-to-back comparison between legacy and migrated builds.
Key concepts
- Wrapping
- Placing legacy code inside one or a few AUTOSAR components or a complex device driver, with only its external interface adapted to RTE calls. Fast, but little architectural benefit.
- Partial refactoring
- Splitting legacy code into several components along functional lines, replacing global variables with ports, while keeping most of the algorithm code.
- Full re-modelling
- Re-implementing functions as models from the requirements and generating code, keeping the legacy code only as a reference for back-to-back tests.
- Back-to-back equivalence
- Running legacy and migrated builds with identical inputs and comparing outputs and timing to show the migration did not change behaviour.
Step-by-step guide
- 1
Select and baseline the legacy firmware
Choose a realistic legacy firmware of a few thousand lines on the STM32 kit, such as a CAN-based vehicle control or dashboard ECU with sensor inputs, state machines, CAN messages and a display, written in a typical bare-metal style with global variables and a super-loop or timer interrupts. Freeze it in Git. Measure size, cyclomatic complexity with lizard, global variable count, flash and RAM from the map file, and task timing.
Checkpoint: A baseline report with code metrics, memory use and timing of the legacy firmware.
- 2
Build the reference test suite
Write a back-to-back test suite that drives the ECU through CAN inputs and the potentiometer, using a scripted profile, and records CAN outputs, LCD states via UART and timing. Cover normal operation, mode changes, fault reactions and boundary values. Run it on the legacy build to create reference outputs. Measure statement coverage on a PC build of the legacy code if you can, to know what the suite exercises.
Checkpoint: A reference output set and a coverage figure for the test suite on the legacy build.
- 3
Design the target architecture
Define the AUTOSAR Classic target: application components by function, interfaces replacing global variables, runnables with timing events, and a thin basic software layer of COM, CanIf, a CAN driver and an OS based on FreeRTOS or a time-triggered scheduler. Write a mapping from legacy modules and globals to components and ports. Since a commercial stack is not used, document exactly what your hand-written RTE and BSW layers do.
Checkpoint: A target architecture with component diagram, ARXML exported from AUTOSAR Blockset and a legacy-to-target mapping.
- 4
Define the effort and overhead protocol
Before migrating, define how you measure effort: hours logged per task category, such as analysis, coding, configuration, testing and debugging, with a daily log. Define code churn from Git as lines added, changed and removed. Define overhead metrics: flash, RAM, CPU load per task, RTE call counts and end-to-end latency for two signal chains. Decide the order of migrations and discuss learning effects, which carry over from one migration to the next.
Checkpoint: A written measurement protocol and an effort log template, agreed before migration starts.
- 5
Migration A: wrapping
Wrap the legacy application as a single component or a small number of components, replacing direct accesses to the CAN driver and I/O with RTE calls at the boundary while the legacy code inside stays largely unchanged. Integrate with the RTE glue, COM and OS layers. Run the back-to-back suite and fix differences. Record effort, churn, memory, CPU load and latency.
Checkpoint: Wrapped build passes the back-to-back suite with all metrics recorded.
- 6
Migration B: partial refactoring
Starting from the legacy code again, split it into components along the target architecture, replace global variables with ports and inter-runnable variables, and assign runnables to timing events. Keep algorithm code where possible. Generate RTE headers from the component descriptions or write them to match the ARXML. Run the back-to-back suite, fix differences and record all metrics, including the number of legacy globals removed.
Checkpoint: Refactored build passes the back-to-back suite with all metrics recorded.
- 7
Migration C: full re-modelling
Re-implement the main functions as Simulink and Stateflow models from the requirements, configured as AUTOSAR components with AUTOSAR Blockset, and generate code with Embedded Coder. Use the legacy behaviour only to resolve ambiguous requirements. Integrate with the same BSW layers and run the back-to-back suite. Record differences that reveal undocumented legacy behaviour, which often appears in such migrations, and all metrics.
Checkpoint: Re-modelled build passes the suite, with a list of discovered undocumented legacy behaviours.
- 8
Measure overheads precisely
For each build, measure flash and RAM by section from the map file, CPU load per task with the DWT cycle counter and GPIO traces, the cost of each RTE call type, and end-to-end latency for two chains using CAN timestamps from the PC. Repeat measurements to report variation. Attribute overhead to its sources: RTE copies, extra layers, OS overhead and generated code style.
Checkpoint: An overhead table per build with attribution to RTE, BSW, OS and application code.
- 9
Analyse effort and quality
Compare strategies on effort by category, churn, defects found during migration, test pass rate and maintainability indicators such as complexity per function, global variable count and coupling between components. Relate effort to characteristics of the legacy modules, such as global variable use and complexity, to see which drive cost. Discuss threats to validity: one developer, one code base, learning effects and the small scale.
Checkpoint: An effort and quality comparison with an analysis of which legacy characteristics drive cost.
- 10
Generalise and write up
Propose a decision guide for choosing a migration strategy per module, based on your measurements, for example wrap stable low-complexity drivers, refactor modules with heavy global coupling and re-model functions with unclear behaviour. If possible, test the guide on a second small legacy code base. Write the thesis chapters and release the code, logs and measurement scripts where permitted. Present results per module as well as per build, so readers can see where the decision guide comes from.
Checkpoint: A decision guide supported by measurements, and thesis chapters with released artefacts.
Testing & validation
- Back-to-back equivalence of every migrated build with the legacy reference.
- Effort logged by category against a predefined protocol.
- Flash, RAM, CPU and latency overheads attributed to their sources.
- Code quality metrics before and after migration.
- Decision guide checked on a second code base where possible.
Expected results
An empirical comparison of three AUTOSAR Classic migration strategies on a real ECU firmware, with measured effort, overheads and quality effects and a decision guide for choosing a strategy.
Research angle for your PhD
Research questions: how do wrapping, partial refactoring and full re-modelling compare in effort, overhead and resulting code quality when moving legacy ECU firmware to AUTOSAR Classic, and which code characteristics predict migration cost? Metrics: logged effort by category, code churn, flash, RAM, CPU and latency overhead, defects found and maintainability metrics. Published evidence on AUTOSAR migration is mostly anecdotal; a careful, reproducible case study with a predefined protocol, explicit threats to validity and a tested decision guide is a credible doctoral contribution and suitable for software engineering venues.
Take it further
- Repeat the study with a commercial AUTOSAR stack in an industry partnership.
- Measure migration effort with several developers to reduce individual bias.
- Add a functional safety partitioning step and measure its cost.
- Study migration from Classic to Adaptive for a service-oriented function.
Viva and review questions
Why measure effort with a protocol defined before migration?
Defining categories and metrics first avoids choosing measurements after the fact that favour one strategy, and makes the comparison repeatable.
Where does AUTOSAR overhead come from?
Mainly from RTE indirection and data copies, extra basic software layers and OS scheduling, plus the style of generated code. Measuring each separately shows which matters.
How did you deal with learning effects across the three migrations?
Each migration started from the frozen legacy code, the order was recorded, and the analysis discusses how experience from earlier migrations may have reduced later effort.
Why did full re-modelling reveal undocumented behaviour?
Re-implementing from requirements exposes behaviour the legacy code had that the requirements did not describe, which back-to-back tests then show as differences.
Learn it at DIYguru
These DIYguru courses and programmes teach what this project needs.
