a47e0aed3e
Phase 1 of full English translation: - generate_doorstop_items.py: all 55 items (SG/SYS/SWE/SA/SWA) rewritten in English - generate_landing_page.py: full UI labels, KPI cards, section headings in English - traceability.py: docstring, error messages, HTML headers in English - generate_test_report.py: report content + table headers in English - All 55 markdown items in safety/sg/, reqs/, arch/ regenerated in English Still to come: - demo-epb filled Word docs (PID, plans, safety, manuals, audit artefacts) - Code comments + test names + CI workflow step names - README + dev-process repo templates
892 lines
31 KiB
Python
892 lines
31 KiB
Python
#!/usr/bin/env python3
|
|
"""
|
|
Generate Doorstop-compatible Markdown items for the EPB demo.
|
|
|
|
Source of truth: the dicts below.
|
|
Outputs to: safety/sg/, reqs/sys/, reqs/swe/, arch/sys/, arch/swe/
|
|
|
|
Each output file uses Doorstop's Markdown mode (YAML frontmatter + body).
|
|
|
|
Run: python3 tools/generate_doorstop_items.py
|
|
"""
|
|
from __future__ import annotations
|
|
|
|
import textwrap
|
|
from pathlib import Path
|
|
|
|
REPO = Path(__file__).resolve().parent.parent
|
|
|
|
|
|
# ---------------------------------------------------------------------------
|
|
# Safety Goals (ISO 26262, derived from HARA)
|
|
# ---------------------------------------------------------------------------
|
|
|
|
SG_GOALS = [
|
|
{
|
|
"id": "SG-001", "asil": "D",
|
|
"title": "No unintended release of the parking brake during standstill",
|
|
"text": (
|
|
"The EPB shall not unintentionally release while the vehicle is at "
|
|
"a standstill. Derived from HARA hazards H-01 (unintended release "
|
|
"during parking) and H-04 (clamping force loss in hold state).\n\n"
|
|
"**FTTI:** 5 s (H-01) / 30 s (H-04).\n"
|
|
"**Safe state:** APPLIED (maintain clamping force)."
|
|
),
|
|
},
|
|
{
|
|
"id": "SG-002", "asil": "D",
|
|
"title": "No unintended clamping while driving",
|
|
"text": (
|
|
"The EPB shall not unintentionally clamp while the vehicle is "
|
|
"moving. Derived from HARA hazard H-02.\n\n"
|
|
"**FTTI:** 100 ms.\n"
|
|
"**Safe state:** Actuator stop (do not initiate apply)."
|
|
),
|
|
},
|
|
{
|
|
"id": "SG-003", "asil": "A",
|
|
"title": "Protection against actuator overload",
|
|
"text": (
|
|
"The system shall prevent actuator motor damage due to overcurrent. "
|
|
"Derived from HARA hazard H-05.\n\n"
|
|
"**FTTI:** 100 ms.\n"
|
|
"**Safe state:** Disable actuator, set DTC."
|
|
),
|
|
},
|
|
{
|
|
"id": "SG-004", "asil": "C",
|
|
"title": "Reliable hill-hold handover",
|
|
"text": (
|
|
"When the driver releases the brake pedal on an incline, the EPB "
|
|
"shall take over the braking force before the vehicle starts "
|
|
"rolling. Derived from HARA hazard H-06.\n\n"
|
|
"**FTTI:** 500 ms.\n"
|
|
"**Safe state:** Initiate apply."
|
|
),
|
|
},
|
|
{
|
|
"id": "SG-005", "asil": "B",
|
|
"title": "Response to driver requests",
|
|
"text": (
|
|
"The system shall respond to driver apply and release requests "
|
|
"within specified times. Derived from HARA hazards H-03 and H-07.\n\n"
|
|
"**Response time:** apply <= 800 ms, release <= 1500 ms."
|
|
),
|
|
},
|
|
]
|
|
|
|
|
|
# ---------------------------------------------------------------------------
|
|
# System Requirements (link upward to SG)
|
|
# ---------------------------------------------------------------------------
|
|
|
|
SYS_REQS = [
|
|
{
|
|
"id": "SYS-001", "asil": "D",
|
|
"links": ["SG-001"],
|
|
"title": "Holding the parking brake at standstill",
|
|
"text": (
|
|
"When the parking brake is engaged and the vehicle is at a "
|
|
"standstill, the EPB system must maintain the mechanical clamping "
|
|
"force on both rear callipers until a release is explicitly "
|
|
"requested. Safety goal: SG-001.\n\n"
|
|
"**Verification:** SiL test with up/down grade scenarios, "
|
|
"clamping force measurement."
|
|
),
|
|
},
|
|
{
|
|
"id": "SYS-002", "asil": "D",
|
|
"links": ["SG-002", "SG-005"],
|
|
"title": "Apply on driver request",
|
|
"text": (
|
|
"On apply-direction actuation of the EPB switch, the system must "
|
|
"engage the parking brake within 800 ms, provided the "
|
|
"preconditions are met (standstill or vehicle speed below 5 km/h). "
|
|
"Safety goal: SG-002."
|
|
),
|
|
},
|
|
{
|
|
"id": "SYS-003", "asil": "B",
|
|
"links": ["SG-005"],
|
|
"title": "Release on driver request",
|
|
"text": (
|
|
"On release-direction actuation of the EPB switch, the system "
|
|
"must release the parking brake provided the following "
|
|
"preconditions are met: engine running, driver pressing the brake "
|
|
"pedal, a gear is engaged. Maximum release time: 1500 ms."
|
|
),
|
|
},
|
|
{
|
|
"id": "SYS-004", "asil": "D",
|
|
"links": ["SG-001"],
|
|
"title": "Auto-apply on engine off",
|
|
"text": (
|
|
"When the engine is switched off and the vehicle is at a "
|
|
"standstill, and the parking brake is not yet engaged, the system "
|
|
"must automatically engage the parking brake at the latest 2 s "
|
|
"after detecting engine-off. Safety goal: SG-001."
|
|
),
|
|
},
|
|
{
|
|
"id": "SYS-005", "asil": "D",
|
|
"links": ["SG-002", "SG-004"],
|
|
"title": "Hill-hold on an incline",
|
|
"text": (
|
|
"When hill-hold is active (vehicle on a slope with grade > 5%, "
|
|
"driver pressing the brake pedal), the EPB system shall take over "
|
|
"the brake force when the brake pedal is released and shall "
|
|
"maintain it until drive-away is detected. Safety goal: SG-002."
|
|
),
|
|
},
|
|
{
|
|
"id": "SYS-006", "asil": "B",
|
|
"links": ["SG-004"],
|
|
"title": "Auto-release on drive-away (Drive-Away Assist)",
|
|
"text": (
|
|
"When the parking brake is engaged and the driver shows intent "
|
|
"to drive away (throttle actuation with gear engaged), the "
|
|
"system must release the parking brake within 500 ms. "
|
|
"Precondition: all safety criteria (driver door closed, seatbelt "
|
|
"fastened) are met."
|
|
),
|
|
},
|
|
{
|
|
"id": "SYS-007", "asil": "B",
|
|
"links": ["SG-003"],
|
|
"title": "Actuator current monitoring",
|
|
"text": (
|
|
"The system must monitor the motor current of each actuator at "
|
|
"at least 1 kHz and, on exceeding 8 A for more than 100 ms, "
|
|
"shut down the actuator and set a DTC. Safety goal: SG-003."
|
|
),
|
|
},
|
|
{
|
|
"id": "SYS-008", "asil": "QM",
|
|
"title": "Service mode for the workshop",
|
|
"text": (
|
|
"The system must provide a service mode via UDS RoutineControl "
|
|
"(service 0x31) in which the actuators can be moved manually "
|
|
"into maintenance position (e.g. for brake pad replacement)."
|
|
),
|
|
},
|
|
{
|
|
"id": "SYS-009", "asil": "QM",
|
|
"title": "UDS diagnostics",
|
|
"text": (
|
|
"The system must provide UDS diagnostics per ISO 14229: "
|
|
"ReadDTC (0x19), ReadDataByIdentifier (0x22), RoutineControl "
|
|
"(0x31), ECUReset (0x11). Tester address 0x712, response "
|
|
"address 0x71A."
|
|
),
|
|
},
|
|
{
|
|
"id": "SYS-010", "asil": "QM",
|
|
"title": "HMI status display",
|
|
"text": (
|
|
"The EPB status must be signalled to the driver: LED on the "
|
|
"switch (on = applied, off = released, blinking = error) and a "
|
|
"text in the instrument cluster via CAN bus (frame ID 0x3A0, "
|
|
"50 Hz)."
|
|
),
|
|
},
|
|
]
|
|
|
|
|
|
# ---------------------------------------------------------------------------
|
|
# Software Requirements (each links to one or more SYS reqs)
|
|
# ---------------------------------------------------------------------------
|
|
|
|
SWE_REQS = [
|
|
# SYS-001 — hold
|
|
{"id": "SWE-001", "asil": "D", "links": ["SYS-001"],
|
|
"title": "Apply controller maintains clamping force",
|
|
"text": "The apply controller must verify the clamping force in the hold "
|
|
"state every 50 ms and re-apply when the deviation exceeds 10%."},
|
|
|
|
{"id": "SWE-002", "asil": "D", "links": ["SYS-001"],
|
|
"title": "Watchdog monitors the apply controller",
|
|
"text": "An independent watchdog must monitor the liveness of the apply "
|
|
"controller with a 100 ms timeout and, on failure to respond, "
|
|
"transition to the safe state (apply)."},
|
|
|
|
# SYS-002 — apply
|
|
{"id": "SWE-003", "asil": "D", "links": ["SYS-002"],
|
|
"title": "Forward switch apply signal to the apply controller",
|
|
"text": "The Switch Debouncer software module must deliver a debounced "
|
|
"apply signal to the apply controller within 50 ms."},
|
|
|
|
{"id": "SWE-004", "asil": "D", "links": ["SYS-002"],
|
|
"title": "Confirm target clamping force reached",
|
|
"text": "The apply controller must detect that the target clamping force "
|
|
"has been reached via current measurement and set a status flag."},
|
|
|
|
# SYS-003 — release
|
|
{"id": "SWE-005", "asil": "B", "links": ["SYS-003"],
|
|
"title": "Check release preconditions",
|
|
"text": "Before any release, the apply controller must verify: engine "
|
|
"running, brake pedal pressed, gear engaged. Otherwise reject "
|
|
"the release."},
|
|
|
|
{"id": "SWE-006", "asil": "B", "links": ["SYS-003"],
|
|
"title": "Drive actuators into release position",
|
|
"text": "The Actuator Driver must drive both actuators in parallel into "
|
|
"the release position. Maximum time: 1200 ms. On timeout, set a "
|
|
"DTC."},
|
|
|
|
# SYS-004 — auto-apply
|
|
{"id": "SWE-007", "asil": "D", "links": ["SYS-004"],
|
|
"title": "Detect engine-off condition",
|
|
"text": "The Safety Manager must detect: engine status = off, vehicle "
|
|
"speed < 0.5 km/h. Sampling period 50 ms."},
|
|
|
|
{"id": "SWE-008", "asil": "D", "links": ["SYS-004"],
|
|
"title": "Auto-apply after 2 s delay",
|
|
"text": "If the engine-off condition is stable for 2 s and the parking "
|
|
"brake is not yet active, the Safety Manager must send an apply "
|
|
"request to the apply controller."},
|
|
|
|
# SYS-005 — hill-hold
|
|
{"id": "SWE-009", "asil": "D", "links": ["SYS-005"],
|
|
"title": "Hill-hold activation condition",
|
|
"text": "The Safety Manager must activate hill-hold when grade "
|
|
"(filtered) > 5%, vehicle speed < 0.5 km/h and the brake pedal "
|
|
"is pressed."},
|
|
|
|
{"id": "SWE-010", "asil": "D", "links": ["SYS-005"],
|
|
"title": "Hill-hold handover to the apply controller",
|
|
"text": "If the brake pedal is released while hill-hold is active, the "
|
|
"Safety Manager must immediately send an apply request to the "
|
|
"apply controller before the vehicle can start to roll."},
|
|
|
|
# SYS-006 — auto-release
|
|
{"id": "SWE-011", "asil": "B", "links": ["SYS-006"],
|
|
"title": "Detect drive-away intent",
|
|
"text": "Drive-away intent is detected when: throttle > 10%, gear in "
|
|
"forward or reverse, engine running."},
|
|
|
|
{"id": "SWE-012", "asil": "B", "links": ["SYS-006"],
|
|
"title": "Safety check before auto-release",
|
|
"text": "Before auto-release, the following must be satisfied: driver "
|
|
"door closed, seatbelt fastened. Otherwise warn and do not "
|
|
"release."},
|
|
|
|
# SYS-007 — actuator current
|
|
{"id": "SWE-013", "asil": "B", "links": ["SYS-007"],
|
|
"title": "Current sampling at 1 kHz",
|
|
"text": "The Actuator Driver must sample the motor current of each "
|
|
"actuator at at least 1 kHz. Accuracy +/- 100 mA."},
|
|
|
|
{"id": "SWE-014", "asil": "B", "links": ["SYS-007"],
|
|
"title": "Overcurrent cutoff",
|
|
"text": "On motor current > 8 A for longer than 100 ms, the Actuator "
|
|
"Driver must shut down the motor and set DTC P0xxx."},
|
|
|
|
{"id": "SWE-015", "asil": "B", "links": ["SYS-007"],
|
|
"title": "Clamping force estimation from current profile",
|
|
"text": "The Actuator Driver must estimate the achieved clamping force "
|
|
"from the current waveform during apply (model: F = k * I_peak)."},
|
|
|
|
# SYS-008 — service mode
|
|
{"id": "SWE-016", "asil": "QM", "links": ["SYS-008"],
|
|
"title": "UDS RoutineControl 0x31 for service release",
|
|
"text": "Service mode is activated via UDS RoutineControl service 0x31, "
|
|
"routine ID 0x0301. Precondition: vehicle must be at standstill."},
|
|
|
|
{"id": "SWE-017", "asil": "QM", "links": ["SYS-008"],
|
|
"title": "Service mode indicator",
|
|
"text": "While in service mode, the EPB LED on the switch must blink "
|
|
"at 2 Hz."},
|
|
|
|
# SYS-009 — UDS
|
|
{"id": "SWE-018", "asil": "QM", "links": ["SYS-009"],
|
|
"title": "UDS service 0x19 ReadDTC",
|
|
"text": "The system must output all stored DTCs via service 0x19 "
|
|
"(sub-function 0x02 reportDTCByStatusMask)."},
|
|
|
|
{"id": "SWE-019", "asil": "QM", "links": ["SYS-009"],
|
|
"title": "UDS service 0x22 ReadDataByIdentifier",
|
|
"text": "The following DIDs must be readable: 0xF187 (SW version), "
|
|
"0x0301 (clamping force left), 0x0302 (clamping force right)."},
|
|
|
|
# SYS-010 — HMI
|
|
{"id": "SWE-020", "asil": "QM", "links": ["SYS-010"],
|
|
"title": "LED control",
|
|
"text": "Apply active: LED solid. Release: LED off. Fault: LED blinks "
|
|
"at 4 Hz. Service mode: LED blinks at 2 Hz."},
|
|
|
|
{"id": "SWE-021", "asil": "QM", "links": ["SYS-010"],
|
|
"title": "CAN status frame",
|
|
"text": "Status frame 0x3A0 at 50 Hz: byte 0 = status (0=released, "
|
|
"1=applied, 2=applying, 3=releasing, 0xFF=error), byte 1-2 = "
|
|
"left clamping force, byte 3-4 = right clamping force."},
|
|
|
|
# Sensors & plausibilisation
|
|
{"id": "SWE-022", "asil": "B", "links": ["SYS-001", "SYS-002", "SYS-006"],
|
|
"title": "Standstill detection from wheel speeds",
|
|
"text": "Standstill is detected when all 4 wheel-speed signals stay "
|
|
"below 0.5 km/h for at least 200 ms."},
|
|
|
|
{"id": "SWE-023", "asil": "B", "links": ["SYS-007"],
|
|
"title": "Wheel-speed plausibilisation",
|
|
"text": "Spread of the wheel-speed signals: when driving straight, the "
|
|
"difference must not exceed 3 km/h. Otherwise set a sensor "
|
|
"fault DTC."},
|
|
|
|
{"id": "SWE-024", "asil": "B", "links": ["SYS-005"],
|
|
"title": "Inclinometer low-pass filter",
|
|
"text": "The raw inclinometer signal must be filtered with a first-"
|
|
"order low-pass (time constant 200 ms) before being used for "
|
|
"hill-hold evaluation."},
|
|
|
|
{"id": "SWE-025", "asil": "QM", "links": ["SYS-002", "SYS-003"],
|
|
"title": "Switch debouncing",
|
|
"text": "The EPB switch must be debounced with a debounce time of "
|
|
"50 ms. Stable level = input signal for the apply controller."},
|
|
]
|
|
|
|
|
|
# ---------------------------------------------------------------------------
|
|
# System Architecture Elements
|
|
# ---------------------------------------------------------------------------
|
|
|
|
SA_ELEMENTS = [
|
|
{
|
|
"id": "SA-001", "links": ["SYS-001", "SYS-002", "SYS-003", "SYS-004",
|
|
"SYS-005", "SYS-006", "SYS-007", "SYS-008",
|
|
"SYS-009", "SYS-010"],
|
|
"title": "EPB ECU",
|
|
"asil": "D",
|
|
"text": textwrap.dedent("""
|
|
## Responsibility
|
|
|
|
Central control unit of the electric parking brake. Contains all
|
|
software components and the electronic actuation of the actuators.
|
|
|
|
## System context
|
|
|
|
```plantuml
|
|
@startuml
|
|
node "EPB ECU" as ECU
|
|
node "Actuator left" as AL
|
|
node "Actuator right" as AR
|
|
node "Wheel-speed sensors (x4)" as WS
|
|
node "Inclinometer" as IN
|
|
node "EPB switch + LED" as SW
|
|
node "CAN bus" as CAN
|
|
node "Instrument cluster" as DI
|
|
node "OBD tester" as OBD
|
|
|
|
ECU --> AL : PWM, I-meas
|
|
ECU --> AR : PWM, I-meas
|
|
WS --> ECU : pulses
|
|
IN --> ECU : SPI
|
|
SW --> ECU : GPIO
|
|
ECU --> SW : LED
|
|
ECU <-> CAN
|
|
CAN <-> DI
|
|
CAN <-> OBD
|
|
@enduml
|
|
```
|
|
|
|
## Interfaces
|
|
|
|
| Interface | Type | Direction |
|
|
|---------------|------------------|-----------|
|
|
| Actuator L/R | PWM + shunt | I/O |
|
|
| Wheel speed | Hall pulses | in |
|
|
| Inclinometer | SPI | in |
|
|
| Switch | GPIO debounced | in |
|
|
| LED | GPIO | out |
|
|
| CAN | ISO 11898 | I/O |
|
|
|
|
## Subcomponents (allocated to software)
|
|
|
|
Realised in software: all SWA elements SWA-001..SWA-010.
|
|
|
|
## Non-functional properties
|
|
|
|
- Worst-case reaction time (switch to actuator motion): 250 ms
|
|
- Flash demand: < 256 KB
|
|
- RAM demand: < 32 KB
|
|
- Current: < 200 mA (standby) / < 30 A (actuator peak)
|
|
""").strip(),
|
|
},
|
|
{
|
|
"id": "SA-002", "links": ["SYS-001", "SYS-002", "SYS-003", "SYS-007"],
|
|
"title": "Actuators (calliper motors)",
|
|
"asil": "D",
|
|
"text": textwrap.dedent("""
|
|
## Responsibility
|
|
|
|
Two electromechanical actuators on the rear callipers clamp and
|
|
release the brake pads. Supplied (assumption): commercial component
|
|
from a Tier-1 supplier.
|
|
|
|
## Interfaces
|
|
|
|
| Interface | Type | Notes |
|
|
|---------------|--------------|---------------------------------|
|
|
| Power | 12 V, PWM | bidirectional for apply/release |
|
|
| Current shunt | analog | sampled inside the ECU |
|
|
|
|
## Non-functional properties
|
|
|
|
- Max clamping force: 20 kN
|
|
- Apply time (0 → max): 600 ms
|
|
- Nominal current: 4 A
|
|
- Peak current: 30 A (brief)
|
|
- Temperature range: -40 °C to +85 °C
|
|
""").strip(),
|
|
},
|
|
{
|
|
"id": "SA-003", "links": ["SYS-005", "SYS-006", "SYS-007"],
|
|
"title": "Sensor cluster",
|
|
"asil": "B",
|
|
"text": textwrap.dedent("""
|
|
## Responsibility
|
|
|
|
Summary of all input signals required by the EPB: wheel-speed
|
|
sensors (4x), inclinometer (1x), EPB switch, brake-pedal status,
|
|
gear position, door open, seatbelt — the last four via CAN.
|
|
|
|
## Interfaces
|
|
|
|
| Sensor | Type | Source |
|
|
|-----------------|--------------|------------|
|
|
| Wheel speed x4 | Hall pulses | direct |
|
|
| Inclinometer | SPI 1 kHz | direct |
|
|
| EPB switch | GPIO | direct |
|
|
| Brake pedal | CAN 0x100 | from BCM |
|
|
| Gear | CAN 0x110 | from TCU |
|
|
| Door / belt | CAN 0x120 | from BCM |
|
|
|
|
## Non-functional properties
|
|
|
|
- Wheel-speed accuracy: +/- 0.1 km/h above 1 km/h
|
|
- Inclinometer accuracy: +/- 0.5°
|
|
- Inclinometer sampling rate: 100 Hz
|
|
""").strip(),
|
|
},
|
|
{
|
|
"id": "SA-004", "links": ["SYS-008", "SYS-010"],
|
|
"title": "HMI (switch, LED, display)",
|
|
"asil": "QM",
|
|
"text": textwrap.dedent("""
|
|
## Responsibility
|
|
|
|
Driver interaction and information: tap switch with integrated LED,
|
|
status display in the instrument cluster via CAN.
|
|
|
|
## Interfaces
|
|
|
|
| Element | Type | Behaviour |
|
|
|---------------|----------|-------------------------------------------|
|
|
| Tap switch | GPIO | apply direction / release direction |
|
|
| LED | GPIO | off / on / blink 2 Hz / blink 4 Hz |
|
|
| Display | CAN 0x3A0| 50 Hz status frame |
|
|
""").strip(),
|
|
},
|
|
{
|
|
"id": "SA-005", "links": ["SYS-009", "SYS-010"],
|
|
"title": "CAN bus",
|
|
"asil": "QM",
|
|
"text": textwrap.dedent("""
|
|
## Responsibility
|
|
|
|
Communication backbone for input data (brake pedal, gear, door,
|
|
belt), output (status frame to the display) and diagnostics (UDS
|
|
on the tester address).
|
|
|
|
## Interfaces
|
|
|
|
- Baud rate: 500 kbit/s, CAN 2.0B
|
|
- Received frames: 0x100 (brake pedal), 0x110 (gear),
|
|
0x120 (door/belt), 0x712 (UDS request)
|
|
- Sent frames: 0x3A0 (status 50 Hz), 0x71A (UDS response)
|
|
""").strip(),
|
|
},
|
|
]
|
|
|
|
|
|
# ---------------------------------------------------------------------------
|
|
# Software Architecture Elements
|
|
# ---------------------------------------------------------------------------
|
|
|
|
SWA_ELEMENTS = [
|
|
{
|
|
"id": "SWA-001", "asil": "D",
|
|
"links": ["SWE-007", "SWE-008", "SWE-009", "SWE-010", "SWE-011", "SWE-012"],
|
|
"title": "Safety Manager",
|
|
"text": textwrap.dedent("""
|
|
## Responsibility
|
|
|
|
Highest safety layer. Detects engine-off, activates hill-hold,
|
|
triggers auto-apply. Life-critical logic with redundant checks.
|
|
|
|
## Static view
|
|
|
|
```plantuml
|
|
@startuml
|
|
package "Safety Manager" {
|
|
[Engine State Monitor]
|
|
[Hill-Hold Logic]
|
|
[Auto-Apply Logic]
|
|
}
|
|
[Safety Manager] ..> [Apply Controller] : apply request
|
|
[Wheel Speed Plausi] --> [Safety Manager] : v_vehicle
|
|
[Inclinometer Filter] --> [Safety Manager] : grade
|
|
@enduml
|
|
```
|
|
|
|
## Provided interfaces
|
|
|
|
```c
|
|
Status safety_mgr_init(void);
|
|
void safety_mgr_step_50ms(const SafetyInputs* in);
|
|
```
|
|
|
|
## Dynamic behaviour
|
|
|
|
```plantuml
|
|
@startuml
|
|
[*] --> Idle
|
|
Idle --> HillHoldArmed : grade>5% & v=0 & brake
|
|
HillHoldArmed --> HillHoldActive : brake released
|
|
HillHoldActive --> Idle : v>2 km/h
|
|
Idle --> AutoApplyArmed : engine_off & v=0
|
|
AutoApplyArmed --> AutoApplyTriggered : t>=2s
|
|
AutoApplyTriggered --> Idle : applied
|
|
@enduml
|
|
```
|
|
|
|
## Resources
|
|
|
|
- Stack: <= 256 B
|
|
- Worst-case timing: 200 us per call
|
|
|
|
## Mapping to requirements
|
|
|
|
| Requirement | How covered |
|
|
|-------------|-------------|
|
|
| SWE-007 | engine_off + v<0.5 in step_50ms |
|
|
| SWE-008 | 2 s filter and trigger |
|
|
| SWE-009 | hill-hold activation |
|
|
| SWE-010 | brake-released detection |
|
|
""").strip(),
|
|
},
|
|
{
|
|
"id": "SWA-002", "asil": "D",
|
|
"links": ["SWE-001", "SWE-002", "SWE-003", "SWE-004", "SWE-005"],
|
|
"title": "Apply Controller",
|
|
"text": textwrap.dedent("""
|
|
## Responsibility
|
|
|
|
Central controller for apply, hold and release of the parking brake.
|
|
ASIL-D core of the EPB software. Implemented in
|
|
`src/apply_controller.c`.
|
|
|
|
## Static view
|
|
|
|
```plantuml
|
|
@startuml
|
|
[Apply Controller] --> [Actuator Driver L] : apply/release
|
|
[Apply Controller] --> [Actuator Driver R] : apply/release
|
|
[Switch Debouncer] --> [Apply Controller] : sw_apply, sw_release
|
|
[Safety Manager] --> [Apply Controller] : auto_apply, hill_hold_request
|
|
[Apply Controller] --> [Display Manager] : status
|
|
[Apply Controller] <-- [Watchdog] : alive_check
|
|
@enduml
|
|
```
|
|
|
|
## Provided interfaces
|
|
|
|
```c
|
|
Status apply_ctrl_init(void);
|
|
void apply_ctrl_step_50ms(const ApplyInputs* in);
|
|
EpbStatus apply_ctrl_get_status(void);
|
|
```
|
|
|
|
## Dynamic behaviour
|
|
|
|
```plantuml
|
|
@startuml
|
|
[*] --> Released
|
|
Released --> Applying : apply_request & v_low
|
|
Applying --> Applied : current_target_reached
|
|
Applied --> Releasing : release_request & preconditions_ok
|
|
Applied --> Applied : 50ms hold check (re-clamp if needed)
|
|
Releasing --> Released : release_complete
|
|
Applying --> Error : timeout > 1500ms
|
|
Releasing --> Error : timeout > 1200ms
|
|
Error --> Released : reset & no fault
|
|
@enduml
|
|
```
|
|
|
|
## Resources
|
|
|
|
- Stack: <= 384 B
|
|
- Worst-case timing: 350 us per call
|
|
|
|
## Design decisions
|
|
|
|
| Decision | Rationale |
|
|
|----------|-----------|
|
|
| Static allocation, no heap | Determinism, MISRA C 21.3 |
|
|
| State machine | Easier to verify, deterministic |
|
|
| 50 ms step function | Synchronous with inclinometer sample rate |
|
|
|
|
## Mapping to requirements
|
|
|
|
| Requirement | How covered |
|
|
|-------------|-------------|
|
|
| SWE-001 | Hold state with periodic clamping-force check |
|
|
| SWE-002 | Watchdog pet in step_50ms |
|
|
| SWE-003 | sw_apply input is evaluated immediately |
|
|
| SWE-004 | current-target detection via actuator-driver feedback |
|
|
""").strip(),
|
|
},
|
|
{
|
|
"id": "SWA-003", "asil": "B",
|
|
"links": ["SWE-006", "SWE-013", "SWE-014", "SWE-015"],
|
|
"title": "Actuator Driver",
|
|
"text": textwrap.dedent("""
|
|
## Responsibility
|
|
|
|
Low-level control of the two actuator motors. PWM generation,
|
|
current measurement, overcurrent cutoff, clamping-force estimation.
|
|
Implemented in `src/actuator_driver.c`.
|
|
|
|
## Static view
|
|
|
|
```plantuml
|
|
@startuml
|
|
[Apply Controller] --> [Actuator Driver]
|
|
[Actuator Driver] --> [Hardware PWM] : pwm_set
|
|
[Actuator Driver] <-- [Hardware ADC] : current_sample
|
|
[Actuator Driver] --> [Diagnostic Manager] : DTC
|
|
@enduml
|
|
```
|
|
|
|
## Provided interfaces
|
|
|
|
```c
|
|
Status actuator_init(void);
|
|
void actuator_apply(ActuatorId id, uint8_t pwm_percent);
|
|
void actuator_release(ActuatorId id, uint8_t pwm_percent);
|
|
void actuator_stop(ActuatorId id);
|
|
ActuatorStatus actuator_get_status(ActuatorId id);
|
|
void actuator_isr_1khz(void); // Current sampling
|
|
```
|
|
|
|
## Resources
|
|
|
|
- Stack: <= 256 B
|
|
- Worst-case timing: 50 us per ISR
|
|
- Static RAM: 64 B per actuator
|
|
|
|
## Mapping to requirements
|
|
|
|
| Requirement | How covered |
|
|
|-------------|-------------|
|
|
| SWE-006 | actuator_release for both actuators in parallel |
|
|
| SWE-013 | actuator_isr_1khz |
|
|
| SWE-014 | overcurrent detector in ISR |
|
|
| SWE-015 | peak-current tracking + linear clamping-force estimate |
|
|
""").strip(),
|
|
},
|
|
{
|
|
"id": "SWA-004", "asil": "B",
|
|
"links": ["SWE-022", "SWE-023"],
|
|
"title": "Wheel Speed Plausibilisation",
|
|
"text": textwrap.dedent("""
|
|
## Responsibility
|
|
|
|
Conditioning and plausibilisation of the four wheel-speed signals.
|
|
Detects standstill and cross-checks the wheels.
|
|
|
|
## Provided interfaces
|
|
|
|
```c
|
|
Status wheel_speed_init(void);
|
|
void wheel_speed_step_10ms(const WheelInputs* in);
|
|
bool wheel_speed_is_standstill(void);
|
|
float wheel_speed_get_vehicle(void);
|
|
```
|
|
""").strip(),
|
|
},
|
|
{
|
|
"id": "SWA-005", "asil": "B",
|
|
"links": ["SWE-024"],
|
|
"title": "Inclinometer Filter",
|
|
"text": textwrap.dedent("""
|
|
## Responsibility
|
|
|
|
Low-pass filtering of the raw inclinometer signal for hill-hold
|
|
evaluation.
|
|
|
|
## Provided interfaces
|
|
|
|
```c
|
|
Status inclino_init(void);
|
|
void inclino_step_10ms(int16_t raw_mdeg);
|
|
float inclino_get_grade_percent(void);
|
|
```
|
|
""").strip(),
|
|
},
|
|
{
|
|
"id": "SWA-006", "asil": "QM",
|
|
"links": ["SWE-025"],
|
|
"title": "Switch Debouncer",
|
|
"text": textwrap.dedent("""
|
|
## Responsibility
|
|
|
|
Software debouncing of the EPB switch. Provides a stable apply /
|
|
release signal to the apply controller. Implemented in
|
|
`src/switch_debouncer.c`.
|
|
|
|
## Provided interfaces
|
|
|
|
```c
|
|
Status switch_init(void);
|
|
void switch_step_10ms(SwitchRaw raw);
|
|
SwitchState switch_get_state(void);
|
|
```
|
|
|
|
## Mapping to requirements
|
|
|
|
| Requirement | How covered |
|
|
|-------------|-------------|
|
|
| SWE-025 | 50 ms debounce logic |
|
|
""").strip(),
|
|
},
|
|
{
|
|
"id": "SWA-007", "asil": "QM",
|
|
"links": ["SWE-020", "SWE-021"],
|
|
"title": "Display Manager",
|
|
"text": textwrap.dedent("""
|
|
## Responsibility
|
|
|
|
Drives the LED on the EPB switch and the CAN status frame to the
|
|
instrument cluster. Receives status from the apply controller.
|
|
|
|
## Provided interfaces
|
|
|
|
```c
|
|
Status display_init(void);
|
|
void display_set_status(EpbStatus s);
|
|
void display_step_20ms(void); // 50 Hz CAN frame
|
|
```
|
|
""").strip(),
|
|
},
|
|
{
|
|
"id": "SWA-008", "asil": "QM",
|
|
"links": ["SWE-018", "SWE-019"],
|
|
"title": "Diagnostic Manager",
|
|
"text": textwrap.dedent("""
|
|
## Responsibility
|
|
|
|
UDS diagnostics per ISO 14229: ReadDTC, ReadDataByIdentifier,
|
|
RoutineControl.
|
|
|
|
## Provided interfaces
|
|
|
|
```c
|
|
Status diag_init(void);
|
|
void diag_handle_request(const uint8_t* data, uint16_t len);
|
|
void diag_set_dtc(uint16_t dtc_id);
|
|
```
|
|
""").strip(),
|
|
},
|
|
{
|
|
"id": "SWA-009", "asil": "QM",
|
|
"links": ["SWE-016", "SWE-017"],
|
|
"title": "Service Mode",
|
|
"text": textwrap.dedent("""
|
|
## Responsibility
|
|
|
|
Service mode for the workshop. Activated via UDS RoutineControl
|
|
0x31, routine ID 0x0301. Drives the actuators into maintenance
|
|
position.
|
|
""").strip(),
|
|
},
|
|
{
|
|
"id": "SWA-010", "asil": "QM",
|
|
"links": ["SWE-018", "SWE-019"],
|
|
"title": "Logger",
|
|
"text": textwrap.dedent("""
|
|
## Responsibility
|
|
|
|
Logging for development and service. Ring buffer in RAM (1 KB)
|
|
plus persistence in EEPROM on critical events.
|
|
|
|
## Provided interfaces
|
|
|
|
```c
|
|
Status log_init(void);
|
|
void log_event(LogLevel lvl, uint16_t event_id, uint32_t param);
|
|
```
|
|
""").strip(),
|
|
},
|
|
]
|
|
|
|
|
|
# ---------------------------------------------------------------------------
|
|
# Generation
|
|
# ---------------------------------------------------------------------------
|
|
|
|
REQ_FRONTMATTER = textwrap.dedent("""
|
|
---
|
|
active: true
|
|
derived: false
|
|
header: '{title}'
|
|
level: 1.{level}
|
|
normative: true
|
|
reviewed: null
|
|
links:{links_yaml}
|
|
asil: {asil}
|
|
---
|
|
|
|
# {id}: {title}
|
|
|
|
{text}
|
|
""").strip() + "\n"
|
|
|
|
|
|
def emit_links(links):
|
|
if not links:
|
|
return " []"
|
|
parts = ["\n - {}".format(link) for link in links]
|
|
return "".join(parts)
|
|
|
|
|
|
def write_items(items, target_dir: Path, with_links=True):
|
|
target_dir.mkdir(parents=True, exist_ok=True)
|
|
for i, item in enumerate(items, start=1):
|
|
path = target_dir / f"{item['id']}.md"
|
|
links_yaml = emit_links(item.get("links", []))
|
|
content = REQ_FRONTMATTER.format(
|
|
title=item["title"],
|
|
level=i,
|
|
links_yaml=links_yaml,
|
|
asil=item["asil"],
|
|
id=item["id"],
|
|
text=item["text"],
|
|
)
|
|
path.write_text(content)
|
|
print(f"Wrote {len(items)} items to {target_dir.relative_to(REPO)}/")
|
|
|
|
|
|
def main():
|
|
write_items(SG_GOALS, REPO / "safety" / "sg")
|
|
write_items(SYS_REQS, REPO / "reqs" / "sys")
|
|
write_items(SWE_REQS, REPO / "reqs" / "swe")
|
|
write_items(SA_ELEMENTS, REPO / "arch" / "sys")
|
|
write_items(SWA_ELEMENTS, REPO / "arch" / "swe")
|
|
print("\nTotal: {} reqs/arch items.".format(
|
|
len(SG_GOALS) + len(SYS_REQS) + len(SWE_REQS) + len(SA_ELEMENTS) + len(SWA_ELEMENTS)
|
|
))
|
|
|
|
|
|
if __name__ == "__main__":
|
|
main()
|