HALO Workshop – Implementation Task Sheet

Scenario: AMP Battery Charging Supervision System

Objective

Implement a battery charging supervision application on the provided AMP QEMU platform using both a classical approach and a HALO-based approach.

What is already provided

Hart is alias for Core in RISC-V terminology. The platform has 4 harts/cores, each running a different OS or bare-metal code.

What you must implement

Hart1 / Zephyr — SensorFusion

Hart2 / FreeRTOS — ChargeController

Hart3 / Bare-metal — SafetyMonitor

Hart4 / Linux — Supervisor

Interfaces you must use

Interface Write by Read by Purpose Physical Address Range Virtual Address Range (Linux OS)
SensorFrameIfSensorFusionChargeControllerperiodic measurements0x80340000 - 0x80340200 (512 bytes)/
ChargeCommandIfChargeControllerSafetyMonitorcharging command0x80341000 - 0x80341200 (512 bytes)/
ChargeStatusIfChargeControllerSupervisorcontroller status0x80342000 - 0x80342040 (64 bytes)get_external_buffer(offset)
SafetyStateIfSafetyMonitorSupervisorsafety state0x80343000 - 0x80343040 (64 bytes)get_external_buffer(offset)
OperatorCommandIfSupervisorChargeControllerstructured internal command0x80344000 - 0x80344010 (16 bytes) get_external_buffer(offset)

Minimum interface contents

SensorFrameIf


    unsigned int battery_voltage_mv = 0;
    int charge_current_ma = 0;
    float battery_temp_c = 0.0;
    bool breaker_closed = false;
    unsigned int fault_flags = 0;
    

fault_flags definition (bitmask, uint32):

Multiple faults can be set at once using bitwise OR. Example: fault_flags = 0x03 means over-temperature and over-current.

ChargeCommandIf

Allowed values for charging_mode: "normal", "fast".


    bool enable_charging = False
    unsigned int current_limit_ma = 0
    unsigned int voltage_limit_mv = 0
    string charging_mode = "normal"
    

ChargeStatusIf

Allowed values for charger_state: "idle", "charging", "complete", "fault".


    string charger_state = "idle"        
    unsigned int requested_current_ma = 0
    unsigned int requested_voltage_mv = 0
    unsigned int fault_state = 0         
    

SafetyStateIf


    bool safe_mode = False            
    bool breaker_open = False         
    bool charging_allowed = False     
    unsigned int heartbeat_counter = 0
    

OperatorCommandIf


    unsigned int command_id = 0
    int command_param = 0      
    

Allowed values for command_id:

For unknown command_id values, ignore the command and set an appropriate fault or log entry.

Example commands

Required scenarios

Nominal scenario

  1. Zephyr reads virtual sensor values
  2. Zephyr publishes SensorFrameIf
  3. FreeRTOS computes charging decision
  4. FreeRTOS publishes ChargeCommandIf and ChargeStatusIf
  5. Bare-metal updates SafetyStateIf
  6. Linux displays current controller and safety state
  7. User sends a UART command
  8. Linux parses it and forwards OperatorCommandIf
  9. FreeRTOS applies the command and updates status

Workshop Group Allocation

  1. Five groups as G1 through G5.
  2. Group will either start with the classical implementation or the HALO-based implementation first depending on the slip drawn, then switch to the other approach after a fixed time:
    • Two slips: Classical -> HALO
    • Three slips: HALO -> Classical
  3. Slips will be shuffled thoroughly in view of participants.
  4. One representative from each group will draw exactly one slip.
  5. Allocation will be immediately recorded in a log table with the following fields:
    • Group ID
    • Assigned order
    • Time

Implementation Guidelines

Using TODO Tree Extension (Classical & HALO Workshops)

To effectively track and manage your implementation tasks, you must use the TODO Tree extension in VS Code. This extension helps you organize and monitor your work across the codebase.

Interacting with BMS Simulation via PTY Terminal

Once your implementation is built and running, you can interact with the BMS (Battery Management System) simulation through the console PTY. Use the PTY terminal in VS Code when selecting the task QEMU Sys Run.

Acceptance checklist

Classical Approach

In the classical approach, you are responsible for implementing all Inter-Process Communication (IPC), synchronization mechanisms, and middleware infrastructure yourself. This approach provides complete control and flexibility but requires careful management of low-level communication details.

Your Responsibilities

Example Structure

A typical classical implementation workflow:

  1. Define data structures for each interface (matching the specifications in this task sheet)
  2. Implement a simple shared memory protocol (e.g., producer writes, consumer reads with a flag or counter)
  3. Add synchronization (e.g., spinlocks or semaphores for critical sections)
  4. Implement the application logic for each hart using TODO markers
  5. Test individual components first, then verify end-to-end communication
  6. Delete TODO markers as you complete each task

HALO system description (HADL)

HALO participants must create/update their HADL system description files in /workspaces/PhdHaloRSG/halo_dist/hadls. After adding or updating HADL files, compose and generate the HALO framework packages using the VS Code tasks named Halo: Compose and Halo: Generate (available in the workspace Tasks menu).

Guidance: When creating a new HALO system, follow this recommended naming for consistency with other groups:
  1. ADL file: battery_charging_system.adl — Define your system architecture and components first.
  2. IDDL file: battery_charging_system.iddl — Specify your interface data types and structures.
  3. IDL file: battery_charging_system.idl — Define the interface contracts (read and integrity are not needed) that you outlined in ADL description.
  4. HML file: battery_charging_system.hml — Add profiles that you outlined in ADL description.

ADL Component Platform & Connection Profile Guidelines

Use code snippets to speed up development and ensure consistency by typing ADL when you are in an ADL file, IDL when you are in an IDL file, etc.

Component Platform Names

When defining components, use the following platform names and functions:

Connections, Interfaces and Profiles naming conventions

You can name your connections, interfaces, and profiles as you like, but for consistency and clarity, I recommend using the following names that match the task sheet specifications:

HALO Profiles

Profiles are built-in — use the following directly in your HML connection definitions.

Important: Make sure to set the atributes which are not given explicitly in example for BlackBoard and EventChannel profiles correctly with sizes corresponding to the 64-bit RISC-V (RV64) architecture.

Important: You can set attributes on your own, but recommended attribute values for BlackBoard and EventChannel profiles for the workshop:

Incorrect attribute values can lead to runtime errors or incorrect behavior of your HALO system. See the HALO Guide for details and examples of attribute usage: HALO Guide — Profiles.

HALO Compose

After defining your HADL files, use the Halo: Compose task in VS Code to compose your system. This will check for consistency and generate the necessary code artifacts for your HALO system.

HALO Generate

After successful composition, use the Halo: Generate task to generate the HALO framework packages. This will create the necessary code and configuration files for your system based on the HADL descriptions.

Tip: HALO-specific code snippets are available in VS Code. Just type hml in a HML file or IDL in IDL file etc. Snippets are defined in .vscode/hadl.code-snippets in this workspace.

See an example HADL workflow in the Getting Started guide: Getting Started — example.

Appendix: Diagrams

System overview

System design diagram

Communication flow

Normal communication flow diagram