#!/usr/bin/env python3 """ Generate Doorstop-compatible Markdown items for the EPB demo. Source of truth: the dict EPB_DATA below. Outputs to: 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, abgeleitet aus HARA) # --------------------------------------------------------------------------- SG_GOALS = [ { "id": "SG-001", "asil": "D", "title": "Kein ungewolltes Loesen der Parkbremse im Stillstand", "text": ( "Die EPB darf sich im Stillstand des Fahrzeugs nicht ungewollt loesen. " "Abgeleitet aus HARA-Hazards H-01 (ungewolltes Loesen, Parkphase) und " "H-04 (Klemmkraftverlust im Hold).\n\n" "**FTTI:** 5 s (H-01) / 30 s (H-04).\n" "**Safe State:** APPLIED (Klemmkraft halten)." ), }, { "id": "SG-002", "asil": "D", "title": "Kein ungewolltes Festklemmen waehrend der Fahrt", "text": ( "Die EPB darf nicht waehrend der Fahrt ungewollt festklemmen. " "Abgeleitet aus HARA-Hazard H-02.\n\n" "**FTTI:** 100 ms.\n" "**Safe State:** Aktor stop (kein Apply einleiten)." ), }, { "id": "SG-003", "asil": "A", "title": "Schutz gegen Aktor-Ueberlast", "text": ( "Das System muss Aktor-Motorschaeden durch Ueberstrom verhindern. " "Abgeleitet aus HARA-Hazard H-05.\n\n" "**FTTI:** 100 ms.\n" "**Safe State:** Aktor abschalten, DTC setzen." ), }, { "id": "SG-004", "asil": "C", "title": "Zuverlaessige Hill-Hold-Uebergabe", "text": ( "Beim Loslassen des Bremspedals an einem Hang muss die EPB die " "Bremskraft uebernehmen, bevor das Fahrzeug zu rollen beginnt. " "Abgeleitet aus HARA-Hazard H-06.\n\n" "**FTTI:** 500 ms.\n" "**Safe State:** Apply einleiten." ), }, { "id": "SG-005", "asil": "B", "title": "Reaktion auf Fahreranforderung", "text": ( "Das System muss in spezifizierter Zeit auf Fahrer-Apply- und Release-" "Anforderungen reagieren. Abgeleitet aus HARA-Hazards H-03 und H-07.\n\n" "**Reaktionszeit:** Apply <= 800 ms, Release <= 1500 ms." ), }, ] # --------------------------------------------------------------------------- # System Requirements (linken nach oben auf SG) # --------------------------------------------------------------------------- SYS_REQS = [ { "id": "SYS-001", "asil": "D", "links": ["SG-001"], "title": "Halten der Parkbremse im Stillstand", "text": ( "Wenn die Parkbremse aktiviert ist und das Fahrzeug stillsteht, " "muss das EPB-System die mechanische Klemmkraft an beiden hinteren " "Bremssaetteln aufrecht erhalten, bis ein Loesen ausdruecklich " "angefordert wird. Sicherheitsziel: SG-01.\n\n" "**Verifikation:** SiL-Test mit Auf-/Ab-Hangelung, Klemmkraftmessung." ), }, { "id": "SYS-002", "asil": "D", "links": ["SG-002", "SG-005"], "title": "Apply auf Fahrer-Anforderung", "text": ( "Bei Betaetigung des EPB-Schalters in Apply-Richtung muss das " "System innerhalb von 800 ms die Parkbremse anlegen, sofern die " "Voraussetzungen erfuellt sind (Stillstand oder Geschwindigkeit " "unter 5 km/h). Sicherheitsziel: SG-01." ), }, { "id": "SYS-003", "asil": "B", "links": ["SG-005"], "title": "Release auf Fahrer-Anforderung", "text": ( "Bei Betaetigung des EPB-Schalters in Release-Richtung muss das " "System die Parkbremse loesen, sofern die folgenden Voraussetzungen " "erfuellt sind: Motor laeuft, Fahrer betaetigt Bremspedal, Gang " "ist eingelegt. Maximalzeit fuer Loesen: 1500 ms." ), }, { "id": "SYS-004", "asil": "D", "links": ["SG-001"], "title": "Auto-Apply bei Motor-Aus", "text": ( "Wenn der Motor ausgeschaltet wird und das Fahrzeug stillsteht " "und keine Parkbremse aktiv ist, muss das System die Parkbremse " "spaetestens 2 s nach Erkennung Motor-Aus automatisch anlegen. " "Sicherheitsziel: SG-01." ), }, { "id": "SYS-005", "asil": "D", "links": ["SG-002", "SG-004"], "title": "Hill-Hold am Berg", "text": ( "Bei aktivem Hill-Hold (Fahrzeug steht am Hang mit Neigung > 5%, " "Fahrer betaetigt Bremspedal) uebernimmt das EPB-System die " "Bremskraft beim Loesen des Bremspedals und haelt diese, bis die " "Anfahrt erkannt wird. Sicherheitsziel: SG-01." ), }, { "id": "SYS-006", "asil": "B", "links": ["SG-004"], "title": "Auto-Release beim Anfahren (Drive-Away-Assist)", "text": ( "Wenn die Parkbremse aktiv ist und der Fahrer Anfahrabsicht zeigt " "(Gaspedal-Betaetigung bei eingelegtem Gang), muss das System die " "Parkbremse innerhalb von 500 ms loesen. Voraussetzung: alle " "Sicherheitskriterien (Fahrertuer geschlossen, Sicherheitsgurt) " "erfuellt." ), }, { "id": "SYS-007", "asil": "B", "links": ["SG-003"], "title": "Aktor-Stromueberwachung", "text": ( "Das System muss den Motorstrom jedes Aktors mit mindestens 1 kHz " "ueberwachen und bei Ueberschreitung von 8 A fuer mehr als 100 ms " "den Aktor abschalten und einen DTC setzen. Sicherheitsziel: SG-03." ), }, { "id": "SYS-008", "asil": "QM", "title": "Service-Modus fuer Werkstatt", "text": ( "Das System muss ueber UDS RoutineControl (Service 0x31) einen " "Service-Modus bereitstellen, in dem die Aktoren manuell in " "Wartungs-Position gefahren werden koennen (z.B. fuer Bremsbelag-" "Wechsel)." ), }, { "id": "SYS-009", "asil": "QM", "title": "UDS-Diagnose", "text": ( "Das System muss UDS-Diagnose nach ISO 14229 bereitstellen: " "ReadDTC (0x19), ReadDataByIdentifier (0x22), RoutineControl (0x31), " "ECUReset (0x11). Tester-Adresse 0x712, Antwort-Adresse 0x71A." ), }, { "id": "SYS-010", "asil": "QM", "title": "HMI-Statusanzeige", "text": ( "Der EPB-Status muss dem Fahrer signalisiert werden: LED am " "Schalter (an = Apply, aus = Release, blinkend = Fehler) sowie " "Text im Kombi-Display via CAN-Bus (Frame-ID 0x3A0, 50 Hz)." ), }, ] # --------------------------------------------------------------------------- # Software Requirements (each links to one or more SYS reqs) # --------------------------------------------------------------------------- SWE_REQS = [ # SYS-001 — Halten {"id": "SWE-001", "asil": "D", "links": ["SYS-001"], "title": "Apply-Controller haelt Klemmkraft", "text": "Der Apply-Controller muss die Klemmkraft im Hold-Zustand alle 50 ms " "verifizieren und bei Abweichung > 10% nachregeln."}, {"id": "SWE-002", "asil": "D", "links": ["SYS-001"], "title": "Watchdog ueberwacht Apply-Controller", "text": "Ein unabhaengiger Watchdog muss die Liveness des Apply-Controllers " "mit 100 ms Timeout ueberwachen und bei Ausbleiben in den sicheren " "Zustand (Apply) gehen."}, # SYS-002 — Apply {"id": "SWE-003", "asil": "D", "links": ["SYS-002"], "title": "Schalter-Apply-Signal an Apply-Controller weiterleiten", "text": "Das Software-Modul Switch-Debouncer muss ein entprelltes " "Apply-Signal innerhalb von 50 ms an den Apply-Controller liefern."}, {"id": "SWE-004", "asil": "D", "links": ["SYS-002"], "title": "Klemmkraft-Erreichen bestaetigen", "text": "Der Apply-Controller muss das Erreichen der Ziel-Klemmkraft via " "Strommessung erkennen und ein Status-Flag setzen."}, # SYS-003 — Release {"id": "SWE-005", "asil": "B", "links": ["SYS-003"], "title": "Release-Voraussetzungen pruefen", "text": "Vor jedem Release muss der Apply-Controller pruefen: Motor laeuft, " "Bremspedal betaetigt, Gang ist eingelegt. Andernfalls Release abweisen."}, {"id": "SWE-006", "asil": "B", "links": ["SYS-003"], "title": "Aktoren in Release-Position fahren", "text": "Der Actuator-Driver muss beide Aktoren parallel in Release-Position " "fahren. Maximalzeit: 1200 ms. Bei Timeout DTC setzen."}, # SYS-004 — Auto-Apply {"id": "SWE-007", "asil": "D", "links": ["SYS-004"], "title": "Motor-Aus-Bedingung erkennen", "text": "Der Safety-Manager muss erkennen: Motor-Status = aus, " "Geschwindigkeit < 0.5 km/h. Auswertezyklus 50 ms."}, {"id": "SWE-008", "asil": "D", "links": ["SYS-004"], "title": "Auto-Apply nach 2 s Verzoegerung", "text": "Ist die Motor-Aus-Bedingung 2 s stabil erfuellt und Parkbremse " "noch nicht aktiv, muss der Safety-Manager Apply-Anforderung an " "den Apply-Controller senden."}, # SYS-005 — Hill-Hold {"id": "SWE-009", "asil": "D", "links": ["SYS-005"], "title": "Hill-Hold-Aktivierungsbedingung", "text": "Der Safety-Manager muss Hill-Hold aktivieren, wenn Neigung " "(gefiltert) > 5%, Geschwindigkeit < 0.5 km/h und Bremspedal " "betaetigt sind."}, {"id": "SWE-010", "asil": "D", "links": ["SYS-005"], "title": "Hill-Hold-Uebergabe an Apply-Controller", "text": "Wird das Bremspedal bei aktivem Hill-Hold losgelassen, muss der " "Safety-Manager unmittelbar Apply-Anforderung an den Apply-" "Controller senden, bevor das Fahrzeug zu rollen beginnen kann."}, # SYS-006 — Auto-Release {"id": "SWE-011", "asil": "B", "links": ["SYS-006"], "title": "Anfahrabsicht erkennen", "text": "Anfahrabsicht ist erkannt, wenn: Gaspedal > 10%, Gang in Vorwaerts " "oder Rueckwaerts, Motor laeuft."}, {"id": "SWE-012", "asil": "B", "links": ["SYS-006"], "title": "Sicherheits-Check vor Auto-Release", "text": "Vor Auto-Release muessen erfuellt sein: Fahrertuer geschlossen, " "Sicherheitsgurt angelegt. Andernfalls warnen und nicht loesen."}, # SYS-007 — Aktor-Strom {"id": "SWE-013", "asil": "B", "links": ["SYS-007"], "title": "Strommessung mit 1 kHz", "text": "Der Actuator-Driver muss den Motorstrom jedes Aktors mit " "mindestens 1 kHz abtasten. Genauigkeit +/- 100 mA."}, {"id": "SWE-014", "asil": "B", "links": ["SYS-007"], "title": "Overcurrent-Cutoff", "text": "Bei Motorstrom > 8 A laenger als 100 ms muss der Actuator-Driver " "den Motor abschalten und einen DTC P0xxx setzen."}, {"id": "SWE-015", "asil": "B", "links": ["SYS-007"], "title": "Klemmkraft-Schaetzung aus Strom-Profil", "text": "Der Actuator-Driver muss die erreichte Klemmkraft aus dem " "Stromverlauf bei Apply schaetzen (Modell: F = k * I_peak)."}, # SYS-008 — Service-Modus {"id": "SWE-016", "asil": "QM", "links": ["SYS-008"], "title": "UDS RoutineControl 0x31 fuer Service-Release", "text": "Service-Mode wird ueber UDS RoutineControl Service 0x31, " "Routine-ID 0x0301 aktiviert. Bedingung: Fahrzeug muss stillstehen."}, {"id": "SWE-017", "asil": "QM", "links": ["SYS-008"], "title": "Service-Mode-Indikator", "text": "Im Service-Mode muss die EPB-LED am Schalter mit 2 Hz blinken."}, # SYS-009 — UDS {"id": "SWE-018", "asil": "QM", "links": ["SYS-009"], "title": "UDS Service 0x19 ReadDTC", "text": "Das System muss alle gespeicherten DTCs ueber Service 0x19 " "(Subfunktion 0x02 reportDTCByStatusMask) ausgeben."}, {"id": "SWE-019", "asil": "QM", "links": ["SYS-009"], "title": "UDS Service 0x22 ReadDataByIdentifier", "text": "Folgende DIDs muessen lesbar sein: 0xF187 (SW-Version), " "0x0301 (Klemmkraft links), 0x0302 (Klemmkraft rechts)."}, # SYS-010 — HMI {"id": "SWE-020", "asil": "QM", "links": ["SYS-010"], "title": "LED-Steuerung", "text": "Apply-aktiv: LED dauerleuchtend. Release: LED aus. Fehler: " "LED blinkt 4 Hz. Service-Mode: LED blinkt 2 Hz."}, {"id": "SWE-021", "asil": "QM", "links": ["SYS-010"], "title": "CAN-Status-Frame", "text": "Status-Frame 0x3A0 mit 50 Hz: Byte 0 = Status (0=Released, 1=Applied, " "2=Applying, 3=Releasing, 0xFF=Error), Byte 1-2 = Klemmkraft links, " "Byte 3-4 = Klemmkraft rechts."}, # Sensorik & Plausibilisierung {"id": "SWE-022", "asil": "B", "links": ["SYS-001", "SYS-002", "SYS-006"], "title": "Stillstands-Erkennung aus Wheel Speeds", "text": "Stillstand ist erkannt, wenn alle 4 Wheel-Speed-Signale fuer " "mindestens 200 ms unter 0.5 km/h liegen."}, {"id": "SWE-023", "asil": "B", "links": ["SYS-007"], "title": "Wheel Speed Plausibilisierung", "text": "Spreizung der Wheel-Speed-Signale: bei Geradeaus-Fahrt darf die " "Differenz nicht > 3 km/h sein. Andernfalls Sensor-Fehler-DTC."}, {"id": "SWE-024", "asil": "B", "links": ["SYS-005"], "title": "Inclinometer Tiefpass-Filter", "text": "Das Roh-Neigungssignal muss mit einem Tiefpass 1. Ordnung " "(Zeitkonstante 200 ms) gefiltert werden, bevor es zur Hill-Hold-" "Bewertung verwendet wird."}, {"id": "SWE-025", "asil": "QM", "links": ["SYS-002", "SYS-003"], "title": "Switch-Debouncing", "text": "Der EPB-Schalter muss mit einer Entprell-Zeit von 50 ms " "entprellt werden. Stabiler Pegel = Eingangssignal fuer " "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(""" ## Verantwortung Zentrales Steuergeraet der elektrischen Parkbremse. Beinhaltet alle Software- Komponenten und die elektronische Ansteuerung der Aktoren. ## System-Kontext ```plantuml @startuml node "EPB ECU" as ECU node "Aktor links" as AL node "Aktor rechts" as AR node "Wheel Speed Sensoren (x4)" as WS node "Inclinometer" as IN node "EPB-Schalter + LED" as SW node "CAN-Bus" as CAN node "Kombi-Display" as DI node "OBD-Tester" as OBD ECU --> AL : PWM, I-Mess ECU --> AR : PWM, I-Mess WS --> ECU : Pulse IN --> ECU : SPI SW --> ECU : GPIO ECU --> SW : LED ECU <-> CAN CAN <-> DI CAN <-> OBD @enduml ``` ## Schnittstellen | Schnittstelle | Typ | Richtung | |---------------|----------------|----------| | Aktor L/R | PWM + Shunt | I/O | | Wheel Speed | Hall-Pulse | In | | Inclinometer | SPI | In | | Schalter | GPIO debounced | In | | LED | GPIO | Out | | CAN | ISO 11898 | I/O | ## Subkomponenten (Aufteilung auf SW) Realisiert in Software: alle SWA-Elemente SWA-001..SWA-010. ## Nichtfunktionale Eigenschaften - Worst-Case Reaktionszeit (Schalter → Aktor-Bewegung): 250 ms - Flash-Bedarf: < 256 KB - RAM-Bedarf: < 32 KB - Stromaufnahme: < 200 mA (Standby) / < 30 A (Aktor-Spitze) """).strip(), }, { "id": "SA-002", "links": ["SYS-001", "SYS-002", "SYS-003", "SYS-007"], "title": "Aktoren (Caliper-Motoren)", "asil": "D", "text": textwrap.dedent(""" ## Verantwortung Zwei elektromechanische Aktoren an den hinteren Bremssaetteln klemmen und loesen die Bremsbelaege. Geliefert (Annahme): kommerzielles Bauteil eines Tier-1-Lieferanten. ## Schnittstellen | Schnittstelle | Typ | Bemerkung | |---------------|--------------|-----------------------------------| | Power | 12 V, PWM | bidirektional fuer Apply/Release | | Strom-Shunt | Analog | wird in der ECU abgegriffen | ## Nichtfunktionale Eigenschaften - Max. Klemmkraft: 20 kN - Apply-Zeit (0 → max): 600 ms - Strom (nominal): 4 A - Strom (Spitze): 30 A (kurzzeitig) - Temperaturbereich: -40°C bis +85°C """).strip(), }, { "id": "SA-003", "links": ["SYS-005", "SYS-006", "SYS-007"], "title": "Sensor-Cluster", "asil": "B", "text": textwrap.dedent(""" ## Verantwortung Zusammenfassung aller fuer die EPB benoetigten Eingangssignale: Wheel-Speed-Sensoren (4x), Inclinometer (1x), EPB-Schalter, Bremspedal- Status, Gear-Position, Door-Open, Seat-Belt — die letzten vier per CAN. ## Schnittstellen | Sensor | Typ | Quelle | |-----------------|------------------|--------------| | Wheel Speed x4 | Hall-Pulse | direkt | | Inclinometer | SPI 1 kHz | direkt | | EPB-Schalter | GPIO | direkt | | Bremspedal | CAN 0x100 | aus BCM | | Gear | CAN 0x110 | aus TCU | | Door / Belt | CAN 0x120 | aus BCM | ## Nichtfunktionale Eigenschaften - Wheel-Speed-Genauigkeit: +/- 0.1 km/h ab 1 km/h - Inclinometer-Genauigkeit: +/- 0.5° - Sampling-Frequenz Inclinometer: 100 Hz """).strip(), }, { "id": "SA-004", "links": ["SYS-008", "SYS-010"], "title": "HMI (Schalter, LED, Display)", "asil": "QM", "text": textwrap.dedent(""" ## Verantwortung Fahrer-Interaktion und -Information: Tippschalter mit integrierter LED, Statusanzeige im Kombi-Display via CAN. ## Schnittstellen | Element | Typ | Verhalten | |---------------|----------|--------------------------------------------| | Tippschalter | GPIO | Apply-Richtung / Release-Richtung | | LED | GPIO | aus / an / 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(""" ## Verantwortung Kommunikations-Backbone fuer Eingangsdaten (Bremspedal, Gang, Tuer, Gurt), Ausgabe (Status-Frame an Display) und Diagnose (UDS auf Tester-Adresse). ## Schnittstellen - Baudrate: 500 kbit/s, CAN 2.0B - Empfangene Frames: 0x100 (Bremspedal), 0x110 (Gang), 0x120 (Door/Belt), 0x712 (UDS-Request) - Gesendete 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(""" ## Verantwortung Hoechste Sicherheitsschicht. Erkennt Motor-Aus, aktiviert Hill-Hold, triggert Auto-Apply. Lebenswichtige Logik mit redundanter Pruefung. ## Statische Sicht ```plantuml @startuml package "Safety Manager" { [Engine State Monitor] [Hill-Hold Logic] [Auto-Apply Logic] } [Safety Manager] ..> [Apply Controller] : Apply-Anforderung [Wheel Speed Plausi] --> [Safety Manager] : v_vehicle [Inclinometer Filter] --> [Safety Manager] : grade @enduml ``` ## Schnittstellen (Provided) ```c Status safety_mgr_init(void); void safety_mgr_step_50ms(const SafetyInputs* in); ``` ## Dynamisches Verhalten ```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 ``` ## Ressourcen - Stack: <= 256 B - Worst-Case Timing: 200 us / Aufruf ## Mapping auf Anforderungen | Anforderung | Wie abgedeckt | |-------------|---------------| | SWE-007 | engine_off + v<0.5 in step_50ms | | SWE-008 | 2s-Filter und Trigger | | SWE-009 | Hill-Hold-Aktivierung | | SWE-010 | Brake-Released-Detektion | """).strip(), }, { "id": "SWA-002", "asil": "D", "links": ["SWE-001", "SWE-002", "SWE-003", "SWE-004", "SWE-005"], "title": "Apply Controller", "text": textwrap.dedent(""" ## Verantwortung Zentraler Controller fuer Apply, Hold und Release der Parkbremse. ASIL-D-Kern der EPB-Software. Implementiert in `src/apply_controller.c`. ## Statische Sicht ```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 ``` ## Schnittstellen (Provided) ```c Status apply_ctrl_init(void); void apply_ctrl_step_50ms(const ApplyInputs* in); EpbStatus apply_ctrl_get_status(void); ``` ## Dynamisches Verhalten ```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 ``` ## Ressourcen - Stack: <= 384 B - Worst-Case Timing: 350 us / Aufruf ## Designentscheidungen | Entscheidung | Begruendung | |--------------|-------------| | Statische Allokation, kein Heap | Determinismus, MISRA C 21.3 | | State Machine | Einfacher zu verifizieren, deterministisch | | 50ms Step-Funktion | Synchron zur Inclinometer-Abtastung | ## Mapping auf Anforderungen | Anforderung | Wie abgedeckt | |-------------|---------------| | SWE-001 | Hold-Zustand mit periodischer Klemmkraft-Pruefung | | SWE-002 | Watchdog-Pet im step_50ms | | SWE-003 | sw_apply Input wird sofort ausgewertet | | SWE-004 | Current-Target-Detektion 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(""" ## Verantwortung Low-Level-Ansteuerung der beiden Aktor-Motoren. PWM-Generierung, Strom-Messung, Overcurrent-Cutoff, Klemmkraft-Schaetzung. Implementiert in `src/actuator_driver.c`. ## Statische Sicht ```plantuml @startuml [Apply Controller] --> [Actuator Driver] [Actuator Driver] --> [Hardware PWM] : pwm_set [Actuator Driver] <-- [Hardware ADC] : current_sample [Actuator Driver] --> [Diagnostic Manager] : DTC @enduml ``` ## Schnittstellen (Provided) ```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); // Strom-Sampling ``` ## Ressourcen - Stack: <= 256 B - Worst-Case Timing: 50 us / ISR - Static RAM: 64 B pro Aktor ## Mapping auf Anforderungen | Anforderung | Wie abgedeckt | |-------------|---------------| | SWE-006 | actuator_release fuer beide Aktoren parallel | | SWE-013 | actuator_isr_1khz | | SWE-014 | Overcurrent-Detektor in ISR | | SWE-015 | Peak-Current-Tracking + lineare Klemmkraft-Schaetzung | """).strip(), }, { "id": "SWA-004", "asil": "B", "links": ["SWE-022", "SWE-023"], "title": "Wheel Speed Plausibilisierung", "text": textwrap.dedent(""" ## Verantwortung Aufbereitung und Plausibilisierung der 4 Wheel-Speed-Signale. Erkennt Stillstand und plausibilisiert untereinander. ## Schnittstellen (Provided) ```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(""" ## Verantwortung Tiefpass-Filterung des Inclinometer-Roh-Signals fuer die Hill-Hold-Bewertung. ## Schnittstellen (Provided) ```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(""" ## Verantwortung Software-Entprellung des EPB-Schalters. Liefert stabiles Apply / Release Signal an den Apply-Controller. Implementiert in `src/switch_debouncer.c`. ## Schnittstellen (Provided) ```c Status switch_init(void); void switch_step_10ms(SwitchRaw raw); SwitchState switch_get_state(void); ``` ## Mapping auf Anforderungen | Anforderung | Wie abgedeckt | |-------------|---------------| | SWE-025 | 50ms Debounce-Logik | """).strip(), }, { "id": "SWA-007", "asil": "QM", "links": ["SWE-020", "SWE-021"], "title": "Display Manager", "text": textwrap.dedent(""" ## Verantwortung Steuert LED am EPB-Schalter und CAN-Status-Frame an das Kombi-Display. Empfaengt Status vom Apply-Controller. ## Schnittstellen (Provided) ```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(""" ## Verantwortung UDS-Diagnose nach ISO 14229: ReadDTC, ReadDataByIdentifier, RoutineControl. ## Schnittstellen (Provided) ```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(""" ## Verantwortung Service-Modus fuer Werkstatt. Wird ueber UDS RoutineControl 0x31, Routine-ID 0x0301 aktiviert. Steuert Aktoren in Wartungsposition. """).strip(), }, { "id": "SWA-010", "asil": "QM", "links": ["SWE-018", "SWE-019"], "title": "Logger", "text": textwrap.dedent(""" ## Verantwortung Logging fuer Entwicklung und Service. Ringpuffer im RAM (1 KB) sowie Persistenz im EEPROM bei kritischen Ereignissen. ## Schnittstellen (Provided) ```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(l) for l 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(SYS_REQS) + len(SWE_REQS) + len(SA_ELEMENTS) + len(SWA_ELEMENTS) )) if __name__ == "__main__": main()