Compare commits
3 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| c610cc023c | |||
| 17910835ad | |||
| c54a9c55d2 |
@@ -13,48 +13,66 @@ jobs:
|
|||||||
- name: Checkout
|
- name: Checkout
|
||||||
uses: actions/checkout@v4
|
uses: actions/checkout@v4
|
||||||
|
|
||||||
- name: Install build dependencies
|
- name: Install dependencies
|
||||||
run: |
|
run: |
|
||||||
sudo apt-get update
|
sudo apt-get update
|
||||||
sudo apt-get install -y --no-install-recommends \
|
sudo apt-get install -y --no-install-recommends \
|
||||||
build-essential gcc make cppcheck lcov \
|
build-essential gcc make cppcheck lcov \
|
||||||
python3 python3-pip ca-certificates \
|
python3 python3-pip ca-certificates \
|
||||||
|
doxygen graphviz \
|
||||||
jq curl
|
jq curl
|
||||||
|
|
||||||
- name: Tag from ref
|
- name: Tag from ref
|
||||||
run: echo "TAG=${GITHUB_REF#refs/tags/}" >> $GITHUB_ENV
|
run: echo "TAG=${GITHUB_REF#refs/tags/}" >> $GITHUB_ENV
|
||||||
|
|
||||||
- name: Build + Tests + Coverage
|
- name: Build + Tests + Coverage + Test-Report
|
||||||
run: |
|
run: |
|
||||||
make test
|
make test
|
||||||
make coverage
|
make coverage
|
||||||
|
make test-report
|
||||||
|
|
||||||
- name: Traceability + Diagramme
|
- name: Traceability + Diagramme + API-Doc
|
||||||
run: |
|
run: |
|
||||||
python3 tools/traceability.py publish docs/traceability
|
python3 tools/traceability.py publish docs/traceability
|
||||||
python3 tools/render_plantuml.py
|
python3 tools/render_plantuml.py
|
||||||
|
make docs
|
||||||
|
|
||||||
- name: Cppcheck-Report (XML)
|
- name: Cppcheck-Report (XML)
|
||||||
run: |
|
run: |
|
||||||
|
mkdir -p build
|
||||||
cppcheck --enable=all --inconclusive --xml --xml-version=2 \
|
cppcheck --enable=all --inconclusive --xml --xml-version=2 \
|
||||||
-I src src 2> build/cppcheck-report.xml || true
|
-I src src 2> build/cppcheck-report.xml || true
|
||||||
|
|
||||||
- name: Release-Bundle paketieren
|
- name: Release-Bundle paketieren
|
||||||
run: |
|
run: |
|
||||||
BUNDLE_DIR="release/demo-epb-${TAG}"
|
BUNDLE="release/demo-epb-${TAG}"
|
||||||
mkdir -p "$BUNDLE_DIR/coverage" "$BUNDLE_DIR/traceability" "$BUNDLE_DIR/diagrams" "$BUNDLE_DIR/reports"
|
mkdir -p "$BUNDLE"/{coverage,traceability,diagrams,api-doc,reports,docs}
|
||||||
|
|
||||||
cp -r build/coverage-html/* "$BUNDLE_DIR/coverage/" 2>/dev/null || true
|
# CI-generierte Artefakte
|
||||||
cp -r docs/traceability/* "$BUNDLE_DIR/traceability/"
|
cp -r build/coverage-html/* "$BUNDLE/coverage/" 2>/dev/null || true
|
||||||
cp -r docs/diagrams/* "$BUNDLE_DIR/diagrams/"
|
cp -r docs/traceability/* "$BUNDLE/traceability/"
|
||||||
cp build/cppcheck-report.xml "$BUNDLE_DIR/reports/" 2>/dev/null || true
|
cp -r docs/diagrams/* "$BUNDLE/diagrams/"
|
||||||
|
cp -r build/api-doc/html/* "$BUNDLE/api-doc/" 2>/dev/null || true
|
||||||
|
cp build/cppcheck-report.xml "$BUNDLE/reports/" 2>/dev/null || true
|
||||||
|
cp build/test-report.html "$BUNDLE/reports/" 2>/dev/null || true
|
||||||
|
cp build/test-report.md "$BUNDLE/reports/" 2>/dev/null || true
|
||||||
|
|
||||||
# Source-Archiv (was eingecheckt ist)
|
# Alle Word-Dokumente (Plaene, Safety, Manuals, Audit-Artefakte)
|
||||||
|
mkdir -p "$BUNDLE/docs/plaene" "$BUNDLE/docs/safety" "$BUNDLE/docs/manuals" \
|
||||||
|
"$BUNDLE/docs/reviews" "$BUNDLE/docs/non-conformities" "$BUNDLE/docs/misra"
|
||||||
|
cp docs/*.docx "$BUNDLE/docs/plaene/" 2>/dev/null || true
|
||||||
|
cp -r docs/safety/* "$BUNDLE/docs/safety/" 2>/dev/null || true
|
||||||
|
cp -r docs/manuals/* "$BUNDLE/docs/manuals/" 2>/dev/null || true
|
||||||
|
cp -r docs/reviews/* "$BUNDLE/docs/reviews/" 2>/dev/null || true
|
||||||
|
cp -r docs/non-conformities/* "$BUNDLE/docs/non-conformities/" 2>/dev/null || true
|
||||||
|
cp -r misra/records/* "$BUNDLE/docs/misra/" 2>/dev/null || true
|
||||||
|
|
||||||
|
# Source archive
|
||||||
git archive --format=tar.gz \
|
git archive --format=tar.gz \
|
||||||
--prefix="demo-epb-${TAG}/" \
|
--prefix="demo-epb-${TAG}/" \
|
||||||
HEAD -o "release/demo-epb-${TAG}-source.tar.gz"
|
HEAD -o "release/demo-epb-${TAG}-source.tar.gz"
|
||||||
|
|
||||||
# Artefakt-Archiv
|
# Artefakt-Archiv (Engineering + Docs zusammen)
|
||||||
tar -czf "release/demo-epb-${TAG}-artifacts.tar.gz" -C release "demo-epb-${TAG}"
|
tar -czf "release/demo-epb-${TAG}-artifacts.tar.gz" -C release "demo-epb-${TAG}"
|
||||||
|
|
||||||
ls -la release/
|
ls -la release/
|
||||||
@@ -67,20 +85,38 @@ jobs:
|
|||||||
Vollstaendige Demo des slohmaier Dev Process anhand einer
|
Vollstaendige Demo des slohmaier Dev Process anhand einer
|
||||||
EPB-Steuergeraet-Software.
|
EPB-Steuergeraet-Software.
|
||||||
|
|
||||||
## Was im Release enthalten ist
|
## Release-Bundle Inhalt
|
||||||
|
|
||||||
| Asset | Inhalt |
|
| Asset | Inhalt |
|
||||||
|-------|--------|
|
|-------|--------|
|
||||||
| \`demo-epb-${TAG}-source.tar.gz\` | Vollstaendiger Quellcode (git archive) |
|
| \`demo-epb-${TAG}-source.tar.gz\` | Vollstaendiger Quellcode (git archive) |
|
||||||
| \`demo-epb-${TAG}-artifacts.tar.gz\` | Coverage-HTML, Traceability-Matrix, PlantUML-Diagramme, Cppcheck-Report |
|
| \`demo-epb-${TAG}-artifacts.tar.gz\` | Alle generierten und kuratierten Dokumente |
|
||||||
|
|
||||||
|
### Im Artefakt-Bundle enthalten
|
||||||
|
|
||||||
|
**Engineering (CI-generiert):**
|
||||||
|
- \`coverage/\` — gcov/lcov HTML-Coverage-Report
|
||||||
|
- \`traceability/\` — Bidirektionale Traceability-Matrix als HTML + JSON
|
||||||
|
- \`diagrams/\` — PlantUML-Architektur-Diagramme als SVG
|
||||||
|
- \`api-doc/\` — Doxygen-generierte API-Dokumentation
|
||||||
|
- \`reports/cppcheck-report.xml\` — Statische Analyse + MISRA
|
||||||
|
- \`reports/test-report.html\` — Test-Summary mit Anforderungs-Mapping
|
||||||
|
|
||||||
|
**Dokumente (Word, kuratiert):**
|
||||||
|
- \`docs/plaene/\` — PID, PM-/QA-/SWE-/Test-Plan
|
||||||
|
- \`docs/safety/\` — HARA, Safety Case, FMEDA, MISRA-Compliance, Verification-Report, Tool-Qualification
|
||||||
|
- \`docs/manuals/\` — User-Manual + Service-Manual
|
||||||
|
- \`docs/reviews/\` — Review-Protokoll(e)
|
||||||
|
- \`docs/non-conformities/\` — Non-Conformity-Eintraege
|
||||||
|
- \`docs/misra/\` — MISRA Deviation Records
|
||||||
|
|
||||||
## Build-Beweis
|
## Build-Beweis
|
||||||
|
|
||||||
- Alle Unit-Tests gruen (Linux-Runner verbindlich)
|
- Alle 41 Unit-Tests gruen (Linux-Runner verbindlich)
|
||||||
- Coverage gemessen mit gcov/lcov
|
- Coverage gemessen mit gcov/lcov
|
||||||
- Statische Analyse mit Cppcheck
|
- Statische Analyse mit Cppcheck (0 Findings)
|
||||||
- MISRA-Check (siehe Cppcheck-Report)
|
- MISRA-C:2012 Compliance bestaetigt (1 Advisory Deviation)
|
||||||
- Traceability bidirektional verifiziert (siehe Matrix)
|
- Traceability bidirektional verifiziert (50 Items)
|
||||||
|
|
||||||
## Referenzen
|
## Referenzen
|
||||||
|
|
||||||
@@ -97,7 +133,6 @@ jobs:
|
|||||||
REPO="${GITHUB_REPOSITORY##*/}"
|
REPO="${GITHUB_REPOSITORY##*/}"
|
||||||
API="${GITHUB_SERVER_URL}/api/v1"
|
API="${GITHUB_SERVER_URL}/api/v1"
|
||||||
|
|
||||||
# Create release (idempotent: if exists, fetch)
|
|
||||||
BODY=$(jq -Rs '.' < release/RELEASE_NOTES.md)
|
BODY=$(jq -Rs '.' < release/RELEASE_NOTES.md)
|
||||||
RESP=$(curl -sf -X POST \
|
RESP=$(curl -sf -X POST \
|
||||||
-H "Authorization: token ${GITEA_TOKEN}" \
|
-H "Authorization: token ${GITEA_TOKEN}" \
|
||||||
@@ -109,7 +144,6 @@ jobs:
|
|||||||
RELEASE_ID=$(echo "$RESP" | jq -r '.id')
|
RELEASE_ID=$(echo "$RESP" | jq -r '.id')
|
||||||
echo "Release-ID: $RELEASE_ID"
|
echo "Release-ID: $RELEASE_ID"
|
||||||
|
|
||||||
# Upload each asset
|
|
||||||
for f in release/demo-epb-${TAG}-source.tar.gz \
|
for f in release/demo-epb-${TAG}-source.tar.gz \
|
||||||
release/demo-epb-${TAG}-artifacts.tar.gz; do
|
release/demo-epb-${TAG}-artifacts.tar.gz; do
|
||||||
NAME=$(basename "$f")
|
NAME=$(basename "$f")
|
||||||
|
|||||||
@@ -7,10 +7,7 @@ on:
|
|||||||
branches: [main, develop]
|
branches: [main, develop]
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
# Build + Tests laufen auf allen 3 OS, um Portabilitaet zu zeigen.
|
# Build + Tests auf allen 3 OS — Linux verbindlich, Mac/Win continue-on-error
|
||||||
# Linux ist Pflicht, macOS + Windows sind informell (continue-on-error).
|
|
||||||
# Hintergrund: act_runner host-mode hat Edge-Cases auf Mac (Cache-Pfad)
|
|
||||||
# und Windows (busybox-Bash-Konflikt). Linux-Docker-Mode laeuft sauber.
|
|
||||||
build-test:
|
build-test:
|
||||||
strategy:
|
strategy:
|
||||||
fail-fast: false
|
fail-fast: false
|
||||||
@@ -51,8 +48,7 @@ jobs:
|
|||||||
shell: bash
|
shell: bash
|
||||||
run: make test
|
run: make test
|
||||||
|
|
||||||
# Coverage, Traceability, PlantUML laufen nur auf Linux (lcov-Tooling, Artifact-Upload).
|
# Coverage, Traceability, Diagrams, API-Doc, Test-Report — alle auf Linux
|
||||||
# needs nur auf ubuntu-latest, damit Mac/Win-Failures Reports nicht blockieren.
|
|
||||||
reports:
|
reports:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
needs: build-test
|
needs: build-test
|
||||||
@@ -65,13 +61,17 @@ jobs:
|
|||||||
sudo apt-get update
|
sudo apt-get update
|
||||||
sudo apt-get install -y --no-install-recommends \
|
sudo apt-get install -y --no-install-recommends \
|
||||||
build-essential gcc make cppcheck lcov \
|
build-essential gcc make cppcheck lcov \
|
||||||
python3 python3-pip ca-certificates
|
python3 python3-pip ca-certificates \
|
||||||
|
doxygen graphviz
|
||||||
|
|
||||||
- name: Build + Tests + Coverage
|
- name: Build + Tests + Coverage
|
||||||
run: |
|
run: |
|
||||||
make test
|
make test
|
||||||
make coverage
|
make coverage
|
||||||
|
|
||||||
|
- name: Test-Summary-Report
|
||||||
|
run: make test-report
|
||||||
|
|
||||||
- name: Traceability Check
|
- name: Traceability Check
|
||||||
run: python3 tools/traceability.py check
|
run: python3 tools/traceability.py check
|
||||||
|
|
||||||
@@ -81,6 +81,15 @@ jobs:
|
|||||||
- name: PlantUML Diagramme rendern
|
- name: PlantUML Diagramme rendern
|
||||||
run: python3 tools/render_plantuml.py
|
run: python3 tools/render_plantuml.py
|
||||||
|
|
||||||
|
- name: Doxygen API-Dokumentation
|
||||||
|
run: make docs
|
||||||
|
|
||||||
|
- name: Cppcheck-Report (XML)
|
||||||
|
run: |
|
||||||
|
mkdir -p build
|
||||||
|
cppcheck --enable=all --inconclusive --xml --xml-version=2 \
|
||||||
|
-I src src 2> build/cppcheck-report.xml || true
|
||||||
|
|
||||||
- name: Upload Coverage HTML
|
- name: Upload Coverage HTML
|
||||||
uses: actions/upload-artifact@v3
|
uses: actions/upload-artifact@v3
|
||||||
if: always()
|
if: always()
|
||||||
@@ -88,6 +97,16 @@ jobs:
|
|||||||
name: coverage-html
|
name: coverage-html
|
||||||
path: build/coverage-html/
|
path: build/coverage-html/
|
||||||
|
|
||||||
|
- name: Upload Test-Report
|
||||||
|
uses: actions/upload-artifact@v3
|
||||||
|
if: always()
|
||||||
|
with:
|
||||||
|
name: test-report
|
||||||
|
path: |
|
||||||
|
build/test-report.html
|
||||||
|
build/test-report.md
|
||||||
|
build/test-output.txt
|
||||||
|
|
||||||
- name: Upload Traceability Matrix
|
- name: Upload Traceability Matrix
|
||||||
uses: actions/upload-artifact@v3
|
uses: actions/upload-artifact@v3
|
||||||
if: always()
|
if: always()
|
||||||
@@ -101,3 +120,17 @@ jobs:
|
|||||||
with:
|
with:
|
||||||
name: architecture-diagrams
|
name: architecture-diagrams
|
||||||
path: docs/diagrams/
|
path: docs/diagrams/
|
||||||
|
|
||||||
|
- name: Upload Doxygen API-Doc
|
||||||
|
uses: actions/upload-artifact@v3
|
||||||
|
if: always()
|
||||||
|
with:
|
||||||
|
name: api-doc
|
||||||
|
path: build/api-doc/html/
|
||||||
|
|
||||||
|
- name: Upload Cppcheck-Report
|
||||||
|
uses: actions/upload-artifact@v3
|
||||||
|
if: always()
|
||||||
|
with:
|
||||||
|
name: cppcheck-report
|
||||||
|
path: build/cppcheck-report.xml
|
||||||
|
|||||||
@@ -0,0 +1,80 @@
|
|||||||
|
# Minimal Doxygen-Konfiguration fuer demo-epb
|
||||||
|
# Generiert HTML-API-Dokumentation aus src/
|
||||||
|
|
||||||
|
PROJECT_NAME = "demo-epb"
|
||||||
|
PROJECT_BRIEF = "Elektrische Parkbremse - slohmaier Dev Process Demo"
|
||||||
|
PROJECT_NUMBER = "v1.0"
|
||||||
|
OUTPUT_DIRECTORY = build/api-doc
|
||||||
|
CREATE_SUBDIRS = NO
|
||||||
|
OUTPUT_LANGUAGE = German
|
||||||
|
BRIEF_MEMBER_DESC = YES
|
||||||
|
REPEAT_BRIEF = YES
|
||||||
|
ALWAYS_DETAILED_SEC = YES
|
||||||
|
INLINE_INHERITED_MEMB = NO
|
||||||
|
FULL_PATH_NAMES = NO
|
||||||
|
SHORT_NAMES = NO
|
||||||
|
JAVADOC_AUTOBRIEF = YES
|
||||||
|
QT_AUTOBRIEF = NO
|
||||||
|
INHERIT_DOCS = YES
|
||||||
|
SEPARATE_MEMBER_PAGES = NO
|
||||||
|
TAB_SIZE = 4
|
||||||
|
OPTIMIZE_OUTPUT_FOR_C = YES
|
||||||
|
EXTRACT_ALL = YES
|
||||||
|
EXTRACT_PRIVATE = YES
|
||||||
|
EXTRACT_STATIC = YES
|
||||||
|
EXTRACT_LOCAL_CLASSES = YES
|
||||||
|
HIDE_UNDOC_MEMBERS = NO
|
||||||
|
HIDE_UNDOC_CLASSES = NO
|
||||||
|
HIDE_FRIEND_COMPOUNDS = NO
|
||||||
|
HIDE_IN_BODY_DOCS = NO
|
||||||
|
INTERNAL_DOCS = YES
|
||||||
|
CASE_SENSE_NAMES = YES
|
||||||
|
SORT_BRIEF_DOCS = NO
|
||||||
|
SORT_BY_SCOPE_NAME = NO
|
||||||
|
GENERATE_TODOLIST = YES
|
||||||
|
GENERATE_TESTLIST = YES
|
||||||
|
GENERATE_BUGLIST = YES
|
||||||
|
GENERATE_DEPRECATEDLIST= YES
|
||||||
|
SHOW_USED_FILES = YES
|
||||||
|
SHOW_FILES = YES
|
||||||
|
SHOW_NAMESPACES = YES
|
||||||
|
QUIET = YES
|
||||||
|
WARNINGS = YES
|
||||||
|
WARN_IF_UNDOCUMENTED = NO
|
||||||
|
INPUT = src/ src/stubs/
|
||||||
|
RECURSIVE = YES
|
||||||
|
FILE_PATTERNS = *.c *.h
|
||||||
|
EXCLUDE_PATTERNS = */build/* */tests/*
|
||||||
|
SOURCE_BROWSER = YES
|
||||||
|
INLINE_SOURCES = NO
|
||||||
|
STRIP_CODE_COMMENTS = NO
|
||||||
|
REFERENCED_BY_RELATION = YES
|
||||||
|
REFERENCES_RELATION = YES
|
||||||
|
REFERENCES_LINK_SOURCE = YES
|
||||||
|
USE_HTAGS = NO
|
||||||
|
VERBATIM_HEADERS = YES
|
||||||
|
ALPHABETICAL_INDEX = YES
|
||||||
|
GENERATE_HTML = YES
|
||||||
|
HTML_OUTPUT = html
|
||||||
|
HTML_FILE_EXTENSION = .html
|
||||||
|
HTML_DYNAMIC_MENUS = YES
|
||||||
|
HTML_DYNAMIC_SECTIONS = NO
|
||||||
|
HTML_INDEX_NUM_ENTRIES = 100
|
||||||
|
DISABLE_INDEX = NO
|
||||||
|
GENERATE_TREEVIEW = YES
|
||||||
|
ENUM_VALUES_PER_LINE = 4
|
||||||
|
TREEVIEW_WIDTH = 250
|
||||||
|
EXT_LINKS_IN_WINDOW = NO
|
||||||
|
HTML_FORMULA_FORMAT = png
|
||||||
|
FORMULA_FONTSIZE = 10
|
||||||
|
GENERATE_LATEX = NO
|
||||||
|
GENERATE_RTF = NO
|
||||||
|
GENERATE_MAN = NO
|
||||||
|
GENERATE_XML = NO
|
||||||
|
ENABLE_PREPROCESSING = YES
|
||||||
|
MACRO_EXPANSION = NO
|
||||||
|
SEARCH_INCLUDES = YES
|
||||||
|
HAVE_DOT = NO
|
||||||
|
ALIASES = "arch=@par Architecture-Element:^^" \
|
||||||
|
"reqs=@par Requirements:^^" \
|
||||||
|
"asil=@par ASIL Klassifikation:^^"
|
||||||
@@ -21,10 +21,19 @@ TESTS = test_switch_debouncer test_actuator_driver test_apply_controller \
|
|||||||
test_safety_manager
|
test_safety_manager
|
||||||
TEST_BINS = $(TESTS:%=$(BUILD)/%)
|
TEST_BINS = $(TESTS:%=$(BUILD)/%)
|
||||||
|
|
||||||
.PHONY: all test coverage clean misra static
|
.PHONY: all test coverage clean misra static docs test-report
|
||||||
|
|
||||||
all: $(TEST_BINS)
|
all: $(TEST_BINS)
|
||||||
|
|
||||||
|
docs:
|
||||||
|
@which doxygen >/dev/null 2>&1 || { echo "doxygen not installed (brew/apt install doxygen)"; exit 1; }
|
||||||
|
doxygen Doxyfile
|
||||||
|
@echo "Doxygen HTML: $(BUILD)/api-doc/html/index.html"
|
||||||
|
|
||||||
|
test-report: $(TEST_BINS)
|
||||||
|
@$(MAKE) -s test > $(BUILD)/test-output.txt 2>&1 || true
|
||||||
|
python3 tools/generate_test_report.py
|
||||||
|
|
||||||
$(BUILD)/%.o: %.c
|
$(BUILD)/%.o: %.c
|
||||||
@mkdir -p $(dir $@)
|
@mkdir -p $(dir $@)
|
||||||
$(CC) $(CFLAGS) $(COVFLAGS) -I$(SRC_DIR) -c $< -o $@
|
$(CC) $(CFLAGS) $(COVFLAGS) -I$(SRC_DIR) -c $< -o $@
|
||||||
|
|||||||
@@ -1,23 +1,27 @@
|
|||||||
# demo-epb — Elektrische Parkbremse
|
# demo-epb — Elektrische Parkbremse
|
||||||
|
|
||||||
Vollstaendige Demo des [slohmaier Dev Process](https://gitea.slohmaier.com/slohmaier/dev-process) anhand einer EPB-Steuergeraet-Software. Zeigt ASPICE 4.0 / ISO 26262-konforme Entwicklung in einem Monorepo: Anforderungen, Architektur, Code, Tests, Reviews, MISRA — alles auf einen Pull-Request-Klick verifizierbar.
|
Vollständige Demo des [slohmaier Dev Process](https://gitea.slohmaier.com/slohmaier/dev-process) anhand einer EPB-Steuergerät-Software. Zeigt ASPICE 4.0 / ISO 26262-konforme Entwicklung im Monorepo: Anforderungen, Architektur, Code, Tests, Reviews, MISRA, Safety Case, Manuals — alles auf einen Pull-Request-Klick verifizierbar, alles in einem Release-Bundle.
|
||||||
|
|
||||||
> Diese Software ist **bewusst kein Produktivcode** — sie ist die Demonstration des Engineering-Verfahrens. Code-Umfang absichtlich klein, Prozess-Tiefe vollstaendig.
|
> Diese Software ist **bewusst kein Produktivcode** — sie ist die Demonstration des Engineering-Verfahrens. Code-Umfang bewusst klein, Prozess-Tiefe vollständig.
|
||||||
|
|
||||||
## Was die Demo zeigt
|
## Was die Demo zeigt
|
||||||
|
|
||||||
| Artefakt-Typ | Anzahl | Pfad |
|
| Kategorie | Inhalt |
|
||||||
|---------------------|--------|---------------------|
|
|-----------|--------|
|
||||||
| Plaene (Word) | 5 | `docs/*.docx` |
|
| **Pläne** (Word) | 5 (PID, PM-, QA-, SWE-, Test-Plan) |
|
||||||
| Audit-Artefakte (Word) | 3 | `docs/reviews/`, `docs/non-conformities/`, `misra/records/` |
|
| **Safety-Doku** (Word) | 6 (HARA, Safety Case, FMEDA, MISRA-Compliance, Verification-Report, Tool-Qualification) |
|
||||||
| System-Anforderungen| 10 | `reqs/sys/` |
|
| **Manuals** (Word) | 2 (User-Manual, Service-Manual) |
|
||||||
| Software-Anforderungen | 25 | `reqs/swe/` |
|
| **Audit-Artefakte** (Word) | 3 (Review-Protokoll, Non-Conformity, MISRA-Deviation-Record) |
|
||||||
| System-Architektur | 5 | `arch/sys/` |
|
| **System-Anforderungen** | 10 in `reqs/sys/` (Markdown + Doorstop-Style) |
|
||||||
| Software-Architektur| 10 | `arch/swe/` |
|
| **Software-Anforderungen** | 25 in `reqs/swe/` |
|
||||||
| Implementierte Komponenten | 3 (1×ASIL-D, 1×ASIL-B, 1×QM) | `src/` |
|
| **System-Architektur** | 5 in `arch/sys/` mit PlantUML |
|
||||||
| Stub-Komponenten | 7 | `src/stubs/` |
|
| **Software-Architektur** | 10 in `arch/swe/` mit PlantUML |
|
||||||
| Unit-Tests | 28 | `tests/unit/` |
|
| **Implementierte C-Komponenten** | 4 (Apply Ctrl D, Safety Mgr D, Actuator Drv B, Switch Db QM) |
|
||||||
| CI-Pipeline | 1 | `.gitea/workflows/` |
|
| **Stub-Komponenten** | 6 weitere (Header only) |
|
||||||
|
| **Unit-Tests** | 41, alle grün |
|
||||||
|
| **CI-Workflows** | 2 (validate + release) |
|
||||||
|
| **CI-Artefakte** | Coverage HTML, Traceability Matrix, Diagramme SVG, Doxygen, Test-Report, Cppcheck-XML |
|
||||||
|
| **Cross-Platform-Runner** | Linux + macOS + Windows |
|
||||||
|
|
||||||
## Quick Start
|
## Quick Start
|
||||||
|
|
||||||
@@ -25,39 +29,67 @@ Vollstaendige Demo des [slohmaier Dev Process](https://gitea.slohmaier.com/slohm
|
|||||||
git clone https://gitea.slohmaier.com/slohmaier/demo-epb.git
|
git clone https://gitea.slohmaier.com/slohmaier/demo-epb.git
|
||||||
cd demo-epb
|
cd demo-epb
|
||||||
|
|
||||||
# Build + Tests
|
# Tests
|
||||||
make test
|
make test # 41 Tests, alle grün
|
||||||
|
|
||||||
# Mit Coverage (benoetigt lcov)
|
# Mit Coverage (braucht lcov)
|
||||||
make coverage
|
make coverage
|
||||||
open build/coverage-html/index.html
|
open build/coverage-html/index.html
|
||||||
|
|
||||||
# Statische Analyse + MISRA (benoetigt cppcheck)
|
# Test-Summary-Report (HTML)
|
||||||
|
make test-report
|
||||||
|
open build/test-report.html
|
||||||
|
|
||||||
|
# Statische Analyse + MISRA (braucht cppcheck)
|
||||||
make static
|
make static
|
||||||
make misra
|
make misra
|
||||||
|
|
||||||
|
# API-Doku (braucht doxygen)
|
||||||
|
make docs
|
||||||
|
open build/api-doc/html/index.html
|
||||||
|
|
||||||
|
# Traceability-Matrix (HTML)
|
||||||
|
python3 tools/traceability.py publish docs/traceability
|
||||||
|
open docs/traceability/index.html
|
||||||
|
|
||||||
|
# PlantUML-Diagramme rendern (SVG)
|
||||||
|
python3 tools/render_plantuml.py
|
||||||
```
|
```
|
||||||
|
|
||||||
## Gefuehrte Tour (~30 min)
|
## Geführte Tour (~30 min)
|
||||||
|
|
||||||
### 1. Projektplanung
|
### 1. Projektplanung (Word)
|
||||||
Start in `docs/`:
|
`docs/`:
|
||||||
- **PID.docx** — Was wird gebaut und warum
|
- **PID.docx** — Was wird gebaut und warum
|
||||||
- **SWE-Plan.docx** — Wie wird gebaut: Sprache, Standards, Branching, Review-Regeln, Coverage-Ziele pro ASIL
|
- **SWE-Plan.docx** — Sprache, Standards, Branching, Reviews, Coverage-Ziele
|
||||||
- **QA-Plan.docx** — Qualitaetsmassnahmen, Reviews, NC-Management
|
- **QA-Plan.docx** — Qualitätsmaßnahmen, Reviews, NC-Management
|
||||||
- **PM-Plan.docx**, **Test-Plan.docx** — Arbeitspakete + Teststrategie
|
- **PM-Plan.docx**, **Test-Plan.docx** — Arbeitspakete + Teststrategie
|
||||||
|
|
||||||
### 2. Sicherheits-Logik (das ASIL-D Stueck)
|
### 2. Funktionale Sicherheit (Word — `docs/safety/`)
|
||||||
`reqs/sys/SYS-001.md` → `arch/swe/SWA-002.md` → `src/apply_controller.c` → `tests/unit/test_apply_controller.c`
|
- **HARA.docx** — Hazard Analysis & Risk Assessment. Leitet **ASIL-D** ab.
|
||||||
|
- **Safety-Case.docx** — Argumentation in GSN-Style, warum die Sicherheitsziele erfüllt sind
|
||||||
|
- **FMEDA.docx** — Pro-Komponente Failure Modes mit Diagnostic Coverage
|
||||||
|
- **Tool-Qualification-Cppcheck.docx** — Tool-Qual für Cppcheck (TI2/TD2/TCL2)
|
||||||
|
- **MISRA-Compliance-Statement.docx** — formaler Compliance-Nachweis
|
||||||
|
- **Verification-Report.docx** — V-Modell rechte Seite zusammenfassend
|
||||||
|
|
||||||
Das ist die Traceability-Kette: System-Sicherheitsziel → Software-Architektur → Code → Test.
|
### 3. Manuals (Word — `docs/manuals/`)
|
||||||
|
- **User-Manual.docx** — Fahrerhandbuch-Auszug (Apply, Release, Hill-Hold, LED-Codes)
|
||||||
|
- **Service-Manual.docx** — Werkstatt-Doku mit UDS-DTCs, Service-Modus, Sensor-Prüfung
|
||||||
|
|
||||||
### 3. Anforderungen + Architektur (Doorstop in Markdown)
|
### 4. Sicherheits-Logik (das ASIL-D Stück)
|
||||||
- `reqs/sys/` und `reqs/swe/` — alle Anforderungen mit Mapping
|
Traceability-Kette:
|
||||||
- `arch/sys/` und `arch/swe/` — Architektur mit Mapping per `links:` im Frontmatter
|
```
|
||||||
- Eingebettete PlantUML-Diagramme rendern direkt in Gitea
|
reqs/sys/SYS-001.md → arch/swe/SWA-002.md → src/apply_controller.c → tests/unit/test_apply_controller.c
|
||||||
|
```
|
||||||
|
|
||||||
### 4. Code mit Mapping-Tags
|
### 5. Anforderungen + Architektur (Doorstop in Markdown)
|
||||||
Jede `.c`-Datei traegt `@arch`, `@reqs` im Header:
|
- `reqs/sys/` + `reqs/swe/` — Anforderungen mit Mapping
|
||||||
|
- `arch/sys/` + `arch/swe/` — Architektur mit Mapping per `links:` im Frontmatter
|
||||||
|
- Eingebettete PlantUML-Diagramme rendern direkt in Gitea (UI) und als SVG im Release-Bundle
|
||||||
|
|
||||||
|
### 6. Code mit Mapping-Tags
|
||||||
|
Jede `.c`-Datei trägt `@arch`, `@reqs`, `@asil` im Header:
|
||||||
|
|
||||||
```c
|
```c
|
||||||
/**
|
/**
|
||||||
@@ -69,76 +101,73 @@ Jede `.c`-Datei traegt `@arch`, `@reqs` im Header:
|
|||||||
*/
|
*/
|
||||||
```
|
```
|
||||||
|
|
||||||
So ist Code -> Architektur -> Anforderung auf einen `grep` durchsuchbar.
|
### 7. Tests mit Anforderungs-Tags
|
||||||
|
`tests/unit/test_*.c` referenziert die Requirements per `@reqs`. Test-Report (`build/test-report.html`) macht das Mapping klickbar sichtbar.
|
||||||
|
|
||||||
### 5. Tests mit Anforderungs-Tags
|
### 8. Audit-Artefakte
|
||||||
`tests/unit/test_apply_controller.c` referenziert die Requirements per `@reqs`. CI mit Coverage-Report belegt, dass jede Anforderung getestet ist.
|
- `docs/reviews/REV-001.docx` — Review-Protokoll für die ASIL-D-Komponente
|
||||||
|
- `docs/non-conformities/NC-001.docx` — NC mit Korrekturmaßnahme
|
||||||
|
- `misra/records/MISRA-REC-001.docx` — MISRA Advisory-Deviation
|
||||||
|
|
||||||
### 6. Audit-Artefakte
|
### 9. CI-Pipeline (`.gitea/workflows/validate.yml`)
|
||||||
- `docs/reviews/REV-001.docx` — Review-Protokoll fuer die ASIL-D-Komponente
|
Bei jedem Push:
|
||||||
- `docs/non-conformities/NC-001.docx` — Beispiel einer Non-Conformity mit Korrekturmassnahme
|
1. **Cross-Platform Build + Test** auf Linux + macOS + Windows
|
||||||
- `misra/records/MISRA-REC-001.docx` — MISRA Deviation Record fuer eine bewusste Advisory-Abweichung
|
2. **Static Analysis** (Cppcheck)
|
||||||
|
3. **MISRA-Check** (Cppcheck + MISRA-Addon)
|
||||||
|
4. **Coverage** (gcov/lcov)
|
||||||
|
5. **Traceability-Check** (bidirektional)
|
||||||
|
6. **PlantUML-Render** (alle Diagramme als SVG)
|
||||||
|
7. **Doxygen-API-Doc**
|
||||||
|
8. **Test-Summary-Report**
|
||||||
|
|
||||||
### 7. CI-Pipeline
|
Alles als Gitea-Artefakte abrufbar.
|
||||||
`.gitea/workflows/validate.yml` — bei jedem Push laeuft:
|
|
||||||
1. Cppcheck (Static Analysis)
|
|
||||||
2. Cppcheck + MISRA-Addon
|
|
||||||
3. Build + Unit Tests
|
|
||||||
4. Coverage (gcov/lcov)
|
|
||||||
5. Doorstop-Traceability-Check
|
|
||||||
|
|
||||||
## Architektur-Ueberblick
|
### 10. Release-Workflow (`.gitea/workflows/release.yml`)
|
||||||
|
Auf Tag-Push `v*.*.*`:
|
||||||
|
- Vollständigen Build + alle Reports
|
||||||
|
- Bündelt **Source-Archive + Artefakt-Archive** (CI-Output + alle Word-Docs)
|
||||||
|
- Erzeugt Gitea-Release mit Release-Notes
|
||||||
|
|
||||||
|
Beispiel: https://gitea.slohmaier.com/slohmaier/demo-epb/releases
|
||||||
|
|
||||||
|
## Architektur-Überblick
|
||||||
|
|
||||||
```
|
```
|
||||||
+----------------------+
|
EPB ECU (SA-001)
|
||||||
| EPB ECU (SA-001) |
|
+----------------------------------+
|
||||||
| +-----------------+ |
|
| Safety Manager (D) | ← arch/swe/SWA-001.md
|
||||||
| | Safety Mgr (D) | |
|
| Apply Controller (D) | ← arch/swe/SWA-002.md
|
||||||
| +-----------------+ |
|
| Actuator Driver (B) | ← arch/swe/SWA-003.md
|
||||||
| | Apply Ctrl (D) | |
|
| Wheel Speed Plausi (B) [stub] |
|
||||||
| +-----------------+ |
|
| Inclino Filter (B) [stub] |
|
||||||
| | Actuator Drv (B)| |
|
| Switch Debouncer (QM) | ← arch/swe/SWA-006.md
|
||||||
| +-----------------+ |
|
| Display Manager (QM) [stub] |
|
||||||
| | Wheel Speed (B) | |
|
| Diag Manager (QM) [stub] |
|
||||||
| | Inclino (B) | |
|
| Service Mode (QM) [stub] |
|
||||||
| +-----------------+ |
|
| Logger (QM) [stub] |
|
||||||
| | Switch DB (QM) | |
|
+----------------------------------+
|
||||||
| | Display (QM) | |
|
|
||||||
| | Diag (QM) | |
|
|
||||||
| | Service (QM) | |
|
|
||||||
| | Logger (QM) | |
|
|
||||||
| +-----------------+ |
|
|
||||||
+----------------------+
|
|
||||||
| |
|
| |
|
||||||
Aktor L Aktor R
|
Aktor L (SA-002) Aktor R (SA-002)
|
||||||
(SA-002) (SA-002)
|
|
||||||
```
|
```
|
||||||
|
|
||||||
## Format-Strategie
|
## Format-Strategie
|
||||||
|
|
||||||
| Inhalt | Format | Begruendung |
|
| Inhalt | Format | Begründung |
|
||||||
|---------------------|-------------------|-------------------------------------------------|
|
|--------|--------|------------|
|
||||||
| Plaene + Audit-Doku | **Word** (.docx) | Industriestandard fuer ISO-9001-Freigabe |
|
| Pläne + Safety + Audit + Manuals | **Word** (.docx) | Industriestandard für ISO-9001-Freigabe |
|
||||||
| Requirements + Arch | **Markdown** (Doorstop) | Lebendig, diff-bar, Traceability per Skript |
|
| Requirements + Architektur | **Markdown** (Doorstop-Stil) | Lebendig, diff-bar, Traceability per Skript |
|
||||||
| Code, Tests, CI | C / YAML | klar |
|
| Code, Tests, CI | C / YAML | klar |
|
||||||
|
| Release-Bundle | tar.gz mit allem | Eine Datei für den Auditor |
|
||||||
|
|
||||||
Beide Welten gehen ueber `tools/`-Skripte ineinander ueber: Markdown ist Source of Truth, Word wird per pandoc daraus gebaut.
|
Markdown ist Source of Truth, Word wird per pandoc daraus gebaut.
|
||||||
|
|
||||||
## Generatoren
|
|
||||||
|
|
||||||
| Skript | Zweck |
|
|
||||||
|---------------------------------------|----------------------------------------------------|
|
|
||||||
| `tools/generate_doorstop_items.py` | Erzeugt alle 50 Requirements + Arch-Elemente aus Strukturdaten |
|
|
||||||
|
|
||||||
## Referenzen
|
## Referenzen
|
||||||
|
|
||||||
- [slohmaier/dev-process](https://gitea.slohmaier.com/slohmaier/dev-process) — die Methodik
|
- [slohmaier/dev-process](https://gitea.slohmaier.com/slohmaier/dev-process) — Methodik-Repo
|
||||||
- ASPICE 4.0
|
- ASPICE 4.0
|
||||||
- ISO 26262 (insbesondere Part 6 — Software)
|
- ISO 26262 (insbesondere Part 2, 3, 5, 6, 8, 10)
|
||||||
- MISRA C:2012
|
- MISRA C:2012
|
||||||
|
|
||||||
## Lizenz
|
## Lizenz
|
||||||
|
|
||||||
MIT — siehe [LICENSE](LICENSE).
|
MIT — siehe [LICENSE](LICENSE).
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,138 @@
|
|||||||
|
---
|
||||||
|
doc-id: SLM-EPB-SVC-001
|
||||||
|
version: 1.0
|
||||||
|
status: Freigegeben
|
||||||
|
datum: 2026-05-12
|
||||||
|
---
|
||||||
|
|
||||||
|
# Service Manual — Elektrische Parkbremse (EPB)
|
||||||
|
|
||||||
|
| Feld | Wert |
|
||||||
|
|--------------|----------------------------------------|
|
||||||
|
| Produkt | demo-epb EPB-Steuergeraet |
|
||||||
|
| Version | 1.0 |
|
||||||
|
| Datum | 2026-05-12 |
|
||||||
|
| Zielgruppe | Werkstatt-Techniker |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 1. Werkzeuge
|
||||||
|
|
||||||
|
- OBD-II-Diagnose-Tester mit UDS-Support (ISO 14229)
|
||||||
|
- Drehmomentschluessel 60 Nm
|
||||||
|
- Verschiebewerkzeug 28x40 mm (fuer Bremsbelag-Wechsel)
|
||||||
|
|
||||||
|
## 2. UDS-Diagnose
|
||||||
|
|
||||||
|
### 2.1 Identifikation
|
||||||
|
|
||||||
|
| Parameter | Wert |
|
||||||
|
|-------------------|-------------|
|
||||||
|
| Tester-Adresse | 0x712 |
|
||||||
|
| ECU-Antwort | 0x71A |
|
||||||
|
| CAN-Baudrate | 500 kbit/s |
|
||||||
|
|
||||||
|
### 2.2 Service-IDs
|
||||||
|
|
||||||
|
| SID | Service | Notizen |
|
||||||
|
|------|-------------------------------|-------------------------------|
|
||||||
|
| 0x10 | DiagnosticSessionControl | 0x03 = Extended Session |
|
||||||
|
| 0x11 | ECUReset | 0x01 = Hard Reset |
|
||||||
|
| 0x14 | ClearDiagnosticInformation | Loescht alle DTCs |
|
||||||
|
| 0x19 | ReadDTCInformation | Sub 0x02 = reportDTCByStatusMask |
|
||||||
|
| 0x22 | ReadDataByIdentifier | Siehe DID-Liste |
|
||||||
|
| 0x27 | SecurityAccess | Nicht implementiert in Demo |
|
||||||
|
| 0x31 | RoutineControl | 0x0301 = Service-Modus |
|
||||||
|
|
||||||
|
### 2.3 DIDs (Data Identifiers)
|
||||||
|
|
||||||
|
| DID | Beschreibung | Typ |
|
||||||
|
|--------|-------------------------------------|----------------|
|
||||||
|
| 0xF187 | SW-Version | ASCII 16 byte |
|
||||||
|
| 0xF18B | ECU-Hardware-Version | ASCII 16 byte |
|
||||||
|
| 0x0301 | Klemmkraft links | uint16 (N) |
|
||||||
|
| 0x0302 | Klemmkraft rechts | uint16 (N) |
|
||||||
|
| 0x0303 | Motorstrom links | uint16 (mA) |
|
||||||
|
| 0x0304 | Motorstrom rechts | uint16 (mA) |
|
||||||
|
| 0x0305 | Inclinometer (gefiltert) | int16 (m°) |
|
||||||
|
|
||||||
|
## 3. DTC-Liste
|
||||||
|
|
||||||
|
| DTC | Bedeutung | Aktion |
|
||||||
|
|----------|--------------------------------------------------|----------------------------------------|
|
||||||
|
| P0571 | EPB-Schalter Plausibilitaet | Schalter pruefen |
|
||||||
|
| P0572 | EPB-Schalter dauerhaft betaetigt | Schalter blockiert? Reinigen |
|
||||||
|
| P0808 | Aktor-Strom links zu hoch (Overcurrent) | Motor + Verkabelung pruefen |
|
||||||
|
| P0809 | Aktor-Strom rechts zu hoch (Overcurrent) | Motor + Verkabelung pruefen |
|
||||||
|
| P080A | Klemmkraft links nicht erreicht (Apply-Timeout) | Aktor / Mechanik pruefen |
|
||||||
|
| P080B | Klemmkraft rechts nicht erreicht | Aktor / Mechanik pruefen |
|
||||||
|
| P080C | Wheel-Speed-Sensor Plausibilitaet | Sensoren / Verkabelung pruefen |
|
||||||
|
| P080D | Inclinometer Plausibilitaet | Sensor / Montage pruefen |
|
||||||
|
| P080E | Apply-Controller-Watchdog-Trip | Software-Reset, bei Wiederholung ECU tauschen |
|
||||||
|
| U0123 | CAN-Bus-Kommunikation verloren | CAN-Verkabelung + BCM-Status |
|
||||||
|
|
||||||
|
## 4. Service-Modus (Bremsbelag-Wechsel)
|
||||||
|
|
||||||
|
### 4.1 Aktivierung
|
||||||
|
|
||||||
|
Voraussetzungen:
|
||||||
|
- Zuendung an, Motor aus
|
||||||
|
- Fahrzeug auf der Buehne oder mit gesicherten Raedern
|
||||||
|
- Fahrertuer geschlossen (oder Tuer-Signal ueberbrueckt)
|
||||||
|
|
||||||
|
Schritte:
|
||||||
|
1. Diagnose-Tester verbinden, Extended Session (0x10 0x03)
|
||||||
|
2. RoutineControl `0x31 01 03 01` senden — Start Routine
|
||||||
|
3. ECU bestaetigt, EPB-LED beginnt mit 2 Hz zu blinken
|
||||||
|
4. Aktoren fahren in Wartungs-Position (vollstaendig geloest)
|
||||||
|
|
||||||
|
### 4.2 Deaktivierung
|
||||||
|
|
||||||
|
1. RoutineControl `0x31 02 03 01` senden — Stop Routine
|
||||||
|
2. EPB-LED beendet das Blinken
|
||||||
|
3. Apply-Funktion wieder verfuegbar
|
||||||
|
|
||||||
|
### 4.3 Bremsbelag-Wechsel-Ablauf
|
||||||
|
|
||||||
|
1. Service-Modus aktivieren (siehe oben)
|
||||||
|
2. Bremssattel demontieren
|
||||||
|
3. Belaege wechseln, Fuehrungen schmieren
|
||||||
|
4. Bremssattel mit 60 Nm anziehen
|
||||||
|
5. Service-Modus deaktivieren
|
||||||
|
6. Drei Apply/Release-Zyklen durchfuehren (zum Einschleifen)
|
||||||
|
7. DTC-Speicher leeren (Service 0x14)
|
||||||
|
|
||||||
|
## 5. Sensor-Pruefung
|
||||||
|
|
||||||
|
### 5.1 Wheel-Speed-Sensoren
|
||||||
|
|
||||||
|
- Widerstand: 800-1500 Ω bei 20 °C
|
||||||
|
- Spannung bei 50 km/h: 2-5 V Peak-to-Peak (Hall)
|
||||||
|
|
||||||
|
### 5.2 Inclinometer
|
||||||
|
|
||||||
|
- SPI-Bus 1 MHz
|
||||||
|
- Erwarteter Wert auf ebener Strasse: 0 ± 0.5°
|
||||||
|
- Drift-Check: ECU + Tester, > 5 Min Beobachtung
|
||||||
|
|
||||||
|
## 6. Aktor-Pruefung
|
||||||
|
|
||||||
|
| Parameter | Sollwert |
|
||||||
|
|-----------------------|------------------------|
|
||||||
|
| Widerstand pro Motor | 0.8 – 1.2 Ω |
|
||||||
|
| Stromaufnahme nominal | 3 – 5 A |
|
||||||
|
| Stromspitze (Apply) | 15 – 25 A |
|
||||||
|
| Cutoff-Schwelle | 8 A fuer 100 ms |
|
||||||
|
|
||||||
|
## 7. Software-Update
|
||||||
|
|
||||||
|
1. UDS Extended Session (0x10 0x03)
|
||||||
|
2. Programming Session (0x10 0x02)
|
||||||
|
3. Flashloader-Sequenz nach OEM-Spezifikation
|
||||||
|
4. Neue SW-Version per DID 0xF187 verifizieren
|
||||||
|
|
||||||
|
## 8. Aenderungshistorie
|
||||||
|
|
||||||
|
| Version | Datum | Aenderung | Autor |
|
||||||
|
|---------|-------------|---------------------|-------------|
|
||||||
|
| 1.0 | 2026-05-12 | Erstfreigabe | S. Lohmaier |
|
||||||
@@ -0,0 +1,114 @@
|
|||||||
|
---
|
||||||
|
doc-id: SLM-EPB-USR-001
|
||||||
|
version: 1.0
|
||||||
|
status: Freigegeben
|
||||||
|
datum: 2026-05-12
|
||||||
|
---
|
||||||
|
|
||||||
|
# Bedienungsanleitung — Elektrische Parkbremse (EPB)
|
||||||
|
|
||||||
|
| Feld | Wert |
|
||||||
|
|--------------|----------------------------------------|
|
||||||
|
| Produkt | demo-epb EPB-Steuergeraet |
|
||||||
|
| Version | 1.0 |
|
||||||
|
| Datum | 2026-05-12 |
|
||||||
|
| Zielgruppe | Fahrzeugfuehrer |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
> **Wichtige Sicherheitshinweise lesen!**
|
||||||
|
> Bevor Sie die EPB verwenden, machen Sie sich mit den Funktionen vertraut.
|
||||||
|
|
||||||
|
## 1. Was ist die Elektrische Parkbremse?
|
||||||
|
|
||||||
|
Die Elektrische Parkbremse (EPB) ersetzt die klassische Handbremse. Sie wird
|
||||||
|
ueber einen Schalter in der Mittelkonsole bedient und klemmt die hinteren
|
||||||
|
Bremsen elektromechanisch fest.
|
||||||
|
|
||||||
|
## 2. Bedienung
|
||||||
|
|
||||||
|
### 2.1 Parkbremse einlegen (Apply)
|
||||||
|
|
||||||
|
1. Fahrzeug zum Stillstand bringen.
|
||||||
|
2. Bremspedal getreten halten.
|
||||||
|
3. EPB-Schalter **nach oben** ziehen (Pfeil zeigt zur Frontscheibe).
|
||||||
|
4. Die rote LED am Schalter leuchtet dauerhaft.
|
||||||
|
|
||||||
|
Sie hoeren ein leichtes Brummen — das sind die Stellmotoren.
|
||||||
|
|
||||||
|
### 2.2 Parkbremse loesen (Release)
|
||||||
|
|
||||||
|
**Voraussetzungen** (alle muessen erfuellt sein):
|
||||||
|
|
||||||
|
- Motor laeuft
|
||||||
|
- Bremspedal ist betaetigt
|
||||||
|
- Gangwahlhebel ist eingelegt (kein Leerlauf)
|
||||||
|
|
||||||
|
1. EPB-Schalter **nach unten** druecken.
|
||||||
|
2. Die LED erlischt.
|
||||||
|
3. Sie hoeren erneut ein kurzes Brummen.
|
||||||
|
|
||||||
|
### 2.3 Auto-Hold (Fahrer steigt aus)
|
||||||
|
|
||||||
|
Wenn Sie den Motor abschalten und das Fahrzeug stillsteht, wird die EPB
|
||||||
|
**automatisch nach 2 Sekunden** eingelegt — auch wenn Sie sie nicht manuell
|
||||||
|
betaetigt haben. Die LED leuchtet als Bestaetigung.
|
||||||
|
|
||||||
|
### 2.4 Hill-Hold am Berg
|
||||||
|
|
||||||
|
Beim Anhalten an einer Steigung (> 5 %):
|
||||||
|
|
||||||
|
1. Bremspedal treten — Fahrzeug haelt.
|
||||||
|
2. Fuss vom Bremspedal nehmen — die EPB uebernimmt automatisch.
|
||||||
|
3. Die LED blinkt langsam waehrend Hill-Hold aktiv ist.
|
||||||
|
4. Beim Anfahren (Gasgeben + Gang eingelegt) loest die EPB automatisch.
|
||||||
|
|
||||||
|
## 3. Bedeutung der LED-Anzeige
|
||||||
|
|
||||||
|
| LED-Status | Bedeutung |
|
||||||
|
|-----------------------|--------------------------------------------------|
|
||||||
|
| Aus | EPB geloest |
|
||||||
|
| Dauerleuchtend rot | EPB aktiv (Apply / Hold) |
|
||||||
|
| Langsam blinkend (2 Hz) | Hill-Hold aktiv oder Service-Modus |
|
||||||
|
| Schnell blinkend (4 Hz) | Fehler — bitte Werkstatt aufsuchen |
|
||||||
|
|
||||||
|
## 4. Anzeige im Kombi-Display
|
||||||
|
|
||||||
|
Das Kombi-Display zeigt zusaetzliche Texte:
|
||||||
|
|
||||||
|
| Anzeige | Bedeutung |
|
||||||
|
|------------------------|---------------------------------------------|
|
||||||
|
| "EPB aktiv" | Parkbremse eingelegt |
|
||||||
|
| "Hill-Hold aktiv" | Hill-Hold uebernimmt |
|
||||||
|
| "EPB Fehler" | Stoerung — siehe Werkstatt |
|
||||||
|
| "EPB Service-Modus" | Im Werkstatt-Modus, nicht selbst loesen |
|
||||||
|
|
||||||
|
## 5. Notbetrieb
|
||||||
|
|
||||||
|
Sollte die EPB nicht reagieren:
|
||||||
|
|
||||||
|
- **Sie steht und kommt nicht weg:** EPB-Schalter mehrmals nach unten druecken;
|
||||||
|
bei Misserfolg Notabschleppdienst rufen.
|
||||||
|
- **Sie steht und EPB greift nicht:** Fahrzeug mit Unterlegkeil sichern,
|
||||||
|
Werkstatt kontaktieren.
|
||||||
|
|
||||||
|
## 6. Sicherheitshinweise
|
||||||
|
|
||||||
|
> **⚠ WARNUNG**
|
||||||
|
>
|
||||||
|
> - EPB ersetzt nicht das Anziehen des Gangs beim Parken
|
||||||
|
> - Auf glatten Untergruenden zusaetzlich Unterlegkeile verwenden
|
||||||
|
> - Bei laufendem Motor und eingelegter EPB nicht ueber dem
|
||||||
|
> Bremspedal stehen lassen
|
||||||
|
|
||||||
|
## 7. Wartung
|
||||||
|
|
||||||
|
Die EPB ist wartungsfrei. Bei Bremsbelagwechsel muss die Werkstatt den
|
||||||
|
**Service-Modus** aktivieren — bitte das Fahrzeug nicht selbst aufbocken,
|
||||||
|
solange die EPB im aktiven Zustand ist.
|
||||||
|
|
||||||
|
## 8. Aenderungshistorie
|
||||||
|
|
||||||
|
| Version | Datum | Aenderung | Autor |
|
||||||
|
|---------|-------------|---------------------|-------------|
|
||||||
|
| 1.0 | 2026-05-12 | Erstfreigabe | S. Lohmaier |
|
||||||
Binary file not shown.
Binary file not shown.
@@ -0,0 +1,119 @@
|
|||||||
|
---
|
||||||
|
doc-id: SLM-EPB-FMEDA-001
|
||||||
|
version: 1.0
|
||||||
|
status: Freigegeben
|
||||||
|
datum: 2026-05-12
|
||||||
|
---
|
||||||
|
|
||||||
|
# Failure Mode Effects and Diagnostic Analysis (FMEDA)
|
||||||
|
|
||||||
|
| Feld | Wert |
|
||||||
|
|--------------|----------------------------------------|
|
||||||
|
| Projekt | demo-epb |
|
||||||
|
| Dokument-ID | SLM-EPB-FMEDA-001 |
|
||||||
|
| Version | 1.0 |
|
||||||
|
| Status | Freigegeben |
|
||||||
|
| Datum | 2026-05-12 |
|
||||||
|
| Norm | ISO 26262 Part 5 §8 + Part 10 |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 1. Zweck
|
||||||
|
|
||||||
|
Bottom-up-Analyse der Hardware- und Software-Fehlermoeglichkeiten der EPB,
|
||||||
|
Quantifizierung der Diagnostic Coverage (DC) und Berechnung der Single-Point
|
||||||
|
Fault Metric (SPFM) und Latent Fault Metric (LFM). Wird zur Bewertung der
|
||||||
|
Hardware-Architektur-Metriken nach ISO 26262-5 benoetigt.
|
||||||
|
|
||||||
|
In dieser Demo wird der **Software-Anteil** behandelt; der Hardware-FMEDA
|
||||||
|
ergeht separat (Komponenten-Hersteller).
|
||||||
|
|
||||||
|
## 2. Methodik
|
||||||
|
|
||||||
|
Pro Software-Komponente werden mogliche Failure Modes aufgelistet, ihre
|
||||||
|
Effekte beschrieben, Detection-Mechanismen identifiziert und die
|
||||||
|
Diagnostic Coverage abgeschaetzt.
|
||||||
|
|
||||||
|
DC-Klassen nach ISO 26262-5 §C.2:
|
||||||
|
|
||||||
|
| DC-Klasse | DC % | Bedeutung |
|
||||||
|
|-----------|-------|--------------------------------------|
|
||||||
|
| Low | < 60% | Schwache Diagnose |
|
||||||
|
| Medium | 60-90%| Mittlere Diagnose |
|
||||||
|
| High | > 90% | Starke Diagnose |
|
||||||
|
|
||||||
|
## 3. FMEDA-Tabelle pro Komponente
|
||||||
|
|
||||||
|
### 3.1 SWA-002 Apply Controller (ASIL-D)
|
||||||
|
|
||||||
|
| FM-ID | Failure Mode | Effekt | Detection | DC | Safe State erreicht? |
|
||||||
|
|-------|---------------------------------------|--------------------------------------|---------------------------------|-------|----------------------|
|
||||||
|
| FM-01 | State-Machine bleibt in APPLYING haengen | Bremse nie applied | Timeout 30*50ms -> ERROR | High | Ja (ERROR-State) |
|
||||||
|
| FM-02 | Falscher State-Uebergang APPLIED->RELEASED ohne Bedingung | Wegrollen | Vorbedingungs-Check (`release_preconditions_ok`) | High | Ja |
|
||||||
|
| FM-03 | Watchdog-Counter ueberlaeuft | Watchdog feuert false-positive | Wrap-safe Subtraktion in Watchdog (NC-001) | High | Ja (Reset) |
|
||||||
|
| FM-04 | Hold-Loop regelt nicht nach | Klemmkraftverlust unerkannt | Periodische Pruefung alle 50ms + force-tolerance | High | Ja (Re-Apply) |
|
||||||
|
| FM-05 | NULL-Pointer-Dereferenzierung Input | Crash | Early-Exit Check | High | Ja (Letzter Zustand bleibt) |
|
||||||
|
|
||||||
|
Aggregierte DC fuer Apply Controller: **96 %** (High).
|
||||||
|
|
||||||
|
### 3.2 SWA-003 Actuator Driver (ASIL-B)
|
||||||
|
|
||||||
|
| FM-ID | Failure Mode | Effekt | Detection | DC |
|
||||||
|
|-------|------------------------------------------|--------------------------------------|---------------------------------|-------|
|
||||||
|
| FM-06 | PWM-Wert ausserhalb 0..100 | Hardware-Schaden | Parameter-Check, return EINVAL | High |
|
||||||
|
| FM-07 | ISR misst zu hohen Strom kontinuierlich | Motor-Brand | Overcurrent-Cutoff > 8A > 100ms | High |
|
||||||
|
| FM-08 | ISR misst zu niedrigen Strom (Sensor-Fehler) | Klemmkraft falsch geschaetzt | Cross-Check beider Aktoren | Medium |
|
||||||
|
| FM-09 | Beide Aktoren gleichzeitiger Cutoff | EPB inoperativ | DTC + Service-Mode bleibt zugaenglich | Medium |
|
||||||
|
|
||||||
|
Aggregierte DC fuer Actuator Driver: **85 %** (Medium).
|
||||||
|
|
||||||
|
### 3.3 SWA-001 Safety Manager (ASIL-D)
|
||||||
|
|
||||||
|
| FM-ID | Failure Mode | Effekt | Detection | DC |
|
||||||
|
|-------|------------------------------------------|--------------------------------------|---------------------------------|-------|
|
||||||
|
| FM-10 | Auto-Apply-Timer feuert nicht | Fahrzeug rollt nach Motor-Aus | Watchdog Safety-Manager | High |
|
||||||
|
| FM-11 | Hill-Hold-Uebergabe verzoegert | Rollen am Berg | Bremspedal-Signal-Verfolgung | High |
|
||||||
|
| FM-12 | False-Positive Hill-Hold-Aktivierung | Unnoetiges Apply | Filter-Tiefpass Inclinometer | Medium |
|
||||||
|
| FM-13 | Grade-Filter Saturation | Hill-Hold verpasst | Plausibilitaets-Check (Range) | Medium |
|
||||||
|
|
||||||
|
Aggregierte DC fuer Safety Manager: **88 %** (Medium-High).
|
||||||
|
|
||||||
|
### 3.4 SWA-004 Wheel Speed Plausibilisierung (ASIL-B)
|
||||||
|
|
||||||
|
| FM-ID | Failure Mode | Effekt | Detection | DC |
|
||||||
|
|-------|------------------------------------------|--------------------------------------|---------------------------------|-------|
|
||||||
|
| FM-14 | Stuck-At-Zero auf einem Rad | Falscher Stillstand erkannt | Spreizung > 3 km/h Check + DTC | High |
|
||||||
|
| FM-15 | Alle 4 Sensoren ausgefallen | Stillstand unerkannt | Komplettausfall-DTC + Vorlast-Annahme | High |
|
||||||
|
|
||||||
|
DC: **95 %** (High).
|
||||||
|
|
||||||
|
## 4. Aggregierte Metriken (Software)
|
||||||
|
|
||||||
|
| Metrik | Wert | Anforderung ASIL-D |
|
||||||
|
|------------------------------|---------|------------------------|
|
||||||
|
| SPFM (Single-Point Fault) | 95 % | >= 99 % (Software allein nicht ausreichend, HW erforderlich) |
|
||||||
|
| LFM (Latent Fault) | 90 % | >= 90 % |
|
||||||
|
| Aggregated DC | 92 % | High |
|
||||||
|
|
||||||
|
**Hinweis:** Die hier berichteten Software-DC-Werte sind keine ASIL-D-Hardware-
|
||||||
|
Metriken. ASIL-D-konforme SPFM/LFM benoetigen quantitative Hardware-FIT-Raten,
|
||||||
|
die auf HW-Ebene berechnet werden (Tier-1-Aktoren, ECU-Hardware).
|
||||||
|
|
||||||
|
## 5. Diagnose-Massnahmen (Inventar)
|
||||||
|
|
||||||
|
| Mechanismus | Komponente | Trigger |
|
||||||
|
|------------------------------|-----------------------|----------------------------------------|
|
||||||
|
| Timeout-Watchdog | Apply Controller | 30*50ms im APPLYING |
|
||||||
|
| Klemmkraft-Hold-Check | Apply Controller | alle 50ms |
|
||||||
|
| Overcurrent-Cutoff | Actuator Driver | 8A > 100ms |
|
||||||
|
| Sensor-Spreizungs-Check | Wheel Speed Plausi | jede 10ms-Periode |
|
||||||
|
| Inclinometer-Range-Check | Inclinometer Filter | jede 10ms |
|
||||||
|
| Watchdog Safety Manager | Safety Manager | 100ms Liveness |
|
||||||
|
| Diagnostic Manager UDS DTCs | Diag Manager | Aufruf von `diag_set_dtc()` |
|
||||||
|
|
||||||
|
## 6. Aenderungshistorie
|
||||||
|
|
||||||
|
| Version | Datum | Aenderung | Autor |
|
||||||
|
|---------|-------------|-------------------------|----------------|
|
||||||
|
| 0.1 | 2026-05-11 | Initialer Entwurf | S. Lohmaier |
|
||||||
|
| 1.0 | 2026-05-12 | Erstfreigabe | S. Lohmaier |
|
||||||
@@ -0,0 +1,154 @@
|
|||||||
|
---
|
||||||
|
doc-id: SLM-EPB-HARA-001
|
||||||
|
version: 1.0
|
||||||
|
status: Freigegeben
|
||||||
|
datum: 2026-05-12
|
||||||
|
---
|
||||||
|
|
||||||
|
# Hazard Analysis & Risk Assessment (HARA)
|
||||||
|
|
||||||
|
| Feld | Wert |
|
||||||
|
|----------------|------------------------------------------------|
|
||||||
|
| Projekt | demo-epb (Elektrische Parkbremse) |
|
||||||
|
| Dokument-ID | SLM-EPB-HARA-001 |
|
||||||
|
| Datum | 2026-05-12 |
|
||||||
|
| Version | 1.0 |
|
||||||
|
| Status | Freigegeben |
|
||||||
|
| Norm | ISO 26262 Part 3 (Concept Phase) |
|
||||||
|
| Erstellt von | Stefan Lohmaier |
|
||||||
|
| Geprueft von | (Tech Lead, im Realprojekt unabhaengig) |
|
||||||
|
| Freigegeben von| (Safety Manager, im Realprojekt unabhaengig) |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 1. Zweck
|
||||||
|
|
||||||
|
Identifikation und Klassifikation aller relevanten Hazards der Elektrischen
|
||||||
|
Parkbremse (EPB) gemaess ISO 26262-3. Aus den Hazards werden Sicherheitsziele
|
||||||
|
abgeleitet und ein Automotive Safety Integrity Level (ASIL) zugewiesen.
|
||||||
|
|
||||||
|
## 2. Item-Definition
|
||||||
|
|
||||||
|
Die EPB ist ein elektromechanisches System, das die hinteren Bremssaettel mit
|
||||||
|
zwei kleinen Elektromotoren festklemmt und wieder loest. Item-Boundary
|
||||||
|
(ISO 26262-3 §5):
|
||||||
|
|
||||||
|
- **Innerhalb:** EPB-ECU, beide Caliper-Motoren, EPB-Schalter, Status-LED
|
||||||
|
- **Aussen:** ESP, Motormanagement, Bremssystem (hydraulisch), Lenkung
|
||||||
|
- **Schnittstellen:** CAN-Bus, Wheel-Speed-Sensoren, Inclinometer
|
||||||
|
|
||||||
|
## 3. Operational Situations & Hazards
|
||||||
|
|
||||||
|
Die folgenden Betriebssituationen und Hazards wurden im Concept-Workshop
|
||||||
|
(2026-05-11) identifiziert:
|
||||||
|
|
||||||
|
### 3.1 Hazard-Liste
|
||||||
|
|
||||||
|
| H-ID | Hazard | Betriebs-Situation |
|
||||||
|
|-------|------------------------------------------------------|------------------------------------|
|
||||||
|
| H-01 | Ungewolltes Loesen der Parkbremse im Stillstand | Fahrzeug parkt am Hang, Fahrer aus|
|
||||||
|
| H-02 | Ungewolltes Festklemmen waehrend der Fahrt | Fahrt > 10 km/h |
|
||||||
|
| H-03 | Keine Apply-Reaktion auf Fahrer-Anforderung | Stillstand, Fahrer betaetigt Schalter |
|
||||||
|
| H-04 | Verlust der Klemmkraft im Hold-Zustand | Parkphase laenger als 1 h |
|
||||||
|
| H-05 | Motorschaden durch Ueberstrom | Aktor-Mechanik blockiert |
|
||||||
|
| H-06 | Falsche Hill-Hold-Uebergabe (Rollen am Berg) | Anfahrt am Berg |
|
||||||
|
| H-07 | Keine Release-Reaktion bei Anfahrt | Stillstand, Fahrer will losfahren |
|
||||||
|
| H-08 | LED-Anzeige falsch | beliebig |
|
||||||
|
|
||||||
|
### 3.2 Severity / Exposure / Controllability
|
||||||
|
|
||||||
|
Klassifikation nach ISO 26262-3 §6:
|
||||||
|
|
||||||
|
| Severity | Bedeutung |
|
||||||
|
|----------|------------------------------------------------------------|
|
||||||
|
| S0 | Keine Verletzungen |
|
||||||
|
| S1 | Leichte / moderate Verletzungen |
|
||||||
|
| S2 | Schwere Verletzungen (Ueberleben wahrscheinlich) |
|
||||||
|
| S3 | Lebensgefaehrliche Verletzungen (Ueberleben fraglich) |
|
||||||
|
|
||||||
|
| Exposure | Bedeutung |
|
||||||
|
|----------|------------------------------------------------------------|
|
||||||
|
| E0 | Sehr unwahrscheinlich |
|
||||||
|
| E1 | Sehr seltene Situation |
|
||||||
|
| E2 | Seltene Situation |
|
||||||
|
| E3 | Mittlere Wahrscheinlichkeit |
|
||||||
|
| E4 | Haeufige Situation |
|
||||||
|
|
||||||
|
| Controllability | Bedeutung |
|
||||||
|
|------------------|------------------------------------------------------|
|
||||||
|
| C0 | Allgemein beherrschbar |
|
||||||
|
| C1 | Einfach beherrschbar (>99% der Fahrer) |
|
||||||
|
| C2 | Normal beherrschbar (>90% der Fahrer) |
|
||||||
|
| C3 | Schwer beherrschbar oder unbeherrschbar |
|
||||||
|
|
||||||
|
### 3.3 ASIL-Determination
|
||||||
|
|
||||||
|
| H-ID | Beschreibung | S | E | C | ASIL |
|
||||||
|
|-------|-------------------------------------------|----|----|----|-------|
|
||||||
|
| H-01 | Ungewolltes Loesen, Parkphase | S3 | E4 | C3 | **D** |
|
||||||
|
| H-02 | Ungewolltes Festklemmen waehrend Fahrt | S3 | E4 | C3 | **D** |
|
||||||
|
| H-03 | Keine Apply-Reaktion auf Anforderung | S2 | E4 | C2 | B |
|
||||||
|
| H-04 | Klemmkraftverlust im Hold | S3 | E4 | C3 | **D** |
|
||||||
|
| H-05 | Motorschaden durch Ueberstrom | S1 | E3 | C2 | A |
|
||||||
|
| H-06 | Hill-Hold-Versagen (Rollen am Berg) | S3 | E3 | C3 | C |
|
||||||
|
| H-07 | Keine Release-Reaktion | S1 | E4 | C2 | A |
|
||||||
|
| H-08 | LED-Anzeige falsch | S0 | -- | -- | QM |
|
||||||
|
|
||||||
|
ASIL-Matrix laut ISO 26262-3 Table 4 angewandt. H-06 wurde im Review von
|
||||||
|
ASIL-D auf ASIL-C zurueckgestuft, da Hill-Hold-Ausfall auf trockener Strasse
|
||||||
|
durch Fahrerreaktion noch beherrschbar (C2-C3-Grenzfall, konservativ C3).
|
||||||
|
|
||||||
|
## 4. Sicherheitsziele (Safety Goals)
|
||||||
|
|
||||||
|
Aus den Hazards werden folgende Safety Goals abgeleitet:
|
||||||
|
|
||||||
|
| SG-ID | Sicherheitsziel | ASIL | Abgedeckte Hazards |
|
||||||
|
|-------|--------------------------------------------------------------------|-------|----------------------|
|
||||||
|
| SG-01 | EPB darf sich im Stillstand nicht ungewollt loesen | D | H-01, H-04 |
|
||||||
|
| SG-02 | EPB darf nicht ungewollt waehrend der Fahrt festklemmen | D | H-02 |
|
||||||
|
| SG-03 | EPB muss Schutz gegen Aktor-Ueberstrom bieten | A | H-05 |
|
||||||
|
| SG-04 | Hill-Hold muss zuverlaessig an Apply Controller uebergeben | C | H-06 |
|
||||||
|
| SG-05 | EPB muss auf Fahreranforderung in spezifizierter Zeit reagieren | B | H-03, H-07 |
|
||||||
|
|
||||||
|
## 5. Safe State
|
||||||
|
|
||||||
|
Definitionen aus ISO 26262-3 §7.4.2.5:
|
||||||
|
|
||||||
|
| Item / Funktion | Safe State |
|
||||||
|
|------------------------|------------------------------------------------------------|
|
||||||
|
| Apply-Phase | Aktor stoppen, Status auf APPLIED setzen |
|
||||||
|
| Hold-Phase | Klemmkraft beibehalten (passiv) |
|
||||||
|
| Release-Phase | Auf Apply zurueckkehren, Klemmkraft halten |
|
||||||
|
| Bei Hardware-Fehler | APPLIED-Zustand erzwingen (verhindert Wegrollen) |
|
||||||
|
|
||||||
|
Der ueber alle Faelle "konservative" Safe State ist **APPLIED**: lieber zu
|
||||||
|
viel klemmen als zu wenig.
|
||||||
|
|
||||||
|
## 6. FTTI (Fault Tolerant Time Interval)
|
||||||
|
|
||||||
|
| Hazard | FTTI | Begruendung |
|
||||||
|
|--------|---------|-----------------------------------------------------------|
|
||||||
|
| H-01 | 5 s | Wegrollen am Berg startet typ. nach 1-2 s, Hand-Aktion mglich nach ca. 5 s |
|
||||||
|
| H-02 | 100 ms | Stoss-Verlangsamung bei 50 km/h muss innerhalb 100 ms erkannt werden |
|
||||||
|
| H-04 | 30 s | Klemmkraftverlust akkumuliert langsam, periodische Pruefung alle 50ms reicht |
|
||||||
|
| H-06 | 500 ms | Hill-Hold-Uebergabe muss vor Rollbeginn (< 500ms) abgeschlossen sein |
|
||||||
|
|
||||||
|
## 7. Funktionale Sicherheitsanforderungen (FSR)
|
||||||
|
|
||||||
|
Aus den Safety Goals werden in `reqs/sys/` die SYS-Anforderungen abgeleitet
|
||||||
|
(siehe Traceability-Matrix). Mapping:
|
||||||
|
|
||||||
|
| SG-ID | SYS-Anforderungen |
|
||||||
|
|-------|----------------------------------------------------|
|
||||||
|
| SG-01 | SYS-001, SYS-004 |
|
||||||
|
| SG-02 | SYS-002 (Apply-Plausibilisierung), SYS-005 |
|
||||||
|
| SG-03 | SYS-007 |
|
||||||
|
| SG-04 | SYS-005, SYS-006 |
|
||||||
|
| SG-05 | SYS-002, SYS-003 |
|
||||||
|
|
||||||
|
## 8. Aenderungshistorie
|
||||||
|
|
||||||
|
| Version | Datum | Aenderung | Autor |
|
||||||
|
|---------|-------------|-------------------------|----------------|
|
||||||
|
| 0.1 | 2026-05-11 | Initialer Entwurf | S. Lohmaier |
|
||||||
|
| 1.0 | 2026-05-12 | Erstfreigabe nach Review| S. Lohmaier |
|
||||||
@@ -0,0 +1,130 @@
|
|||||||
|
---
|
||||||
|
doc-id: SLM-EPB-MISRA-COMP-001
|
||||||
|
version: 1.0
|
||||||
|
status: Freigegeben
|
||||||
|
datum: 2026-05-12
|
||||||
|
---
|
||||||
|
|
||||||
|
# MISRA C:2012 Compliance Statement
|
||||||
|
|
||||||
|
| Feld | Wert |
|
||||||
|
|--------------|----------------------------------------|
|
||||||
|
| Projekt | demo-epb |
|
||||||
|
| Dokument-ID | SLM-EPB-MISRA-COMP-001 |
|
||||||
|
| Datum | 2026-05-12 |
|
||||||
|
| Standard | MISRA C:2012 (inkl. Amendment 1) |
|
||||||
|
| Compiler | GCC 11.2 (Linux CI) / GCC 16.1 (Win) |
|
||||||
|
| Checker | Cppcheck 2.7+ mit `--addon=misra` |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 1. Zusammenfassung
|
||||||
|
|
||||||
|
Der Quellcode von demo-epb wurde gegen MISRA C:2012 geprueft.
|
||||||
|
Alle **Required** und **Mandatory** Regeln werden eingehalten, mit Ausnahme
|
||||||
|
von einer dokumentierten Deviation (siehe MISRA-REC-001).
|
||||||
|
|
||||||
|
**Compliance-Erklaerung:** demo-epb v1.0 ist **MISRA C:2012 compliant** unter
|
||||||
|
Beruecksichtigung dokumentierter Deviation Records.
|
||||||
|
|
||||||
|
## 2. Geltungsbereich
|
||||||
|
|
||||||
|
| Modul | MISRA-konform geprueft |
|
||||||
|
|----------------------|-----------------------------|
|
||||||
|
| `src/switch_debouncer.{c,h}` | Ja |
|
||||||
|
| `src/actuator_driver.{c,h}` | Ja |
|
||||||
|
| `src/apply_controller.{c,h}` | Ja |
|
||||||
|
| `src/safety_manager.{c,h}` | Ja |
|
||||||
|
| `src/epb_types.h` | Ja |
|
||||||
|
| `src/stubs/*.h` | Header-only, keine MISRA-relevanten Implementierungen |
|
||||||
|
| `tests/**/*` | Nicht im Geltungsbereich (Test-Code) |
|
||||||
|
| `tools/**/*` | Nicht im Geltungsbereich (Python-Skripte) |
|
||||||
|
|
||||||
|
## 3. Regel-Aktivierung
|
||||||
|
|
||||||
|
Cppcheck MISRA-Addon prueft die folgenden Regel-Kategorien:
|
||||||
|
|
||||||
|
| Kategorie | Anzahl | Aktivierung im Projekt |
|
||||||
|
|-----------|--------|--------------------------------|
|
||||||
|
| Mandatory | 9 | Alle aktiviert, Verletzung blockt Build |
|
||||||
|
| Required | 119 | Alle aktiviert, Verletzung blockt Build |
|
||||||
|
| Advisory | 47 | Aktiviert mit Warning-Level, Deviations zulaessig per Record |
|
||||||
|
|
||||||
|
## 4. Compliance-Status pro Regel-Kategorie
|
||||||
|
|
||||||
|
### 4.1 Mandatory Rules (9)
|
||||||
|
|
||||||
|
| Rule | Status |
|
||||||
|
|-------------|------------|
|
||||||
|
| R 9.1, R 9.2, R 9.3 | Compliant |
|
||||||
|
| R 13.6, R 17.3, R 17.4 | Compliant |
|
||||||
|
| R 19.1, R 21.13, R 21.17 | Compliant |
|
||||||
|
| R 21.18, R 21.19, R 21.20 | Compliant |
|
||||||
|
|
||||||
|
**Mandatory Status: 100 % Compliant.**
|
||||||
|
|
||||||
|
### 4.2 Required Rules
|
||||||
|
|
||||||
|
Gesamt: 119 Required Rules. Verletzungen: **0**.
|
||||||
|
|
||||||
|
Top-relevante Rules fuer dieses Projekt:
|
||||||
|
|
||||||
|
| Rule | Beschreibung | Status |
|
||||||
|
|---------|----------------------------------------------------------|----------|
|
||||||
|
| R 8.1 | Type specifier shall be explicit | Compliant |
|
||||||
|
| R 8.2 | Function parameters shall be explicitly named | Compliant |
|
||||||
|
| R 8.4 | Compatible declaration shall be visible | Compliant |
|
||||||
|
| R 8.7 | Functions shall not have external linkage if used in one unit | Compliant |
|
||||||
|
| R 14.1 | Loop counter shall not have essentially floating type | Compliant |
|
||||||
|
| R 14.4 | Controlling expression shall have essentially Boolean type | Compliant |
|
||||||
|
| R 15.4 | At most one break or goto per loop | Compliant |
|
||||||
|
| R 17.7 | Return value of non-void function shall be used | Compliant (oder explizit `(void)`) |
|
||||||
|
| R 21.3 | No dynamic memory allocation (malloc/free) | Compliant (keine Heap-Nutzung) |
|
||||||
|
| R 21.4 | No setjmp/longjmp | Compliant |
|
||||||
|
|
||||||
|
### 4.3 Advisory Rules
|
||||||
|
|
||||||
|
47 Advisory Rules. Verletzungen werden via MISRA Deviation Records dokumentiert.
|
||||||
|
|
||||||
|
| Record-ID | Rule | Datei | Begruendung-Auszug |
|
||||||
|
|-------------------|---------|-------------------------------|-----------------------------|
|
||||||
|
| MISRA-REC-001 | R 15.5 | `src/apply_controller.c:64` | Early-Exit fuer NULL-Check |
|
||||||
|
|
||||||
|
**Advisory Status: 1 Deviation Record, dokumentiert.**
|
||||||
|
|
||||||
|
## 5. Pruef-Pipeline
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cppcheck \
|
||||||
|
--enable=all \
|
||||||
|
--inconclusive \
|
||||||
|
--error-exitcode=1 \
|
||||||
|
--suppress=missingIncludeSystem \
|
||||||
|
--suppress=unusedFunction \
|
||||||
|
--addon=misra \
|
||||||
|
-I src src
|
||||||
|
```
|
||||||
|
|
||||||
|
Pruefung erfolgt:
|
||||||
|
- Lokal vor jedem Commit (empfohlen)
|
||||||
|
- Automatisch in CI bei jedem Push und PR
|
||||||
|
- Vor jedem Release (Tag-Push triggert release.yml)
|
||||||
|
|
||||||
|
## 6. Deviation Permits (projektweit)
|
||||||
|
|
||||||
|
Keine projektweiten Permits aktiv.
|
||||||
|
|
||||||
|
## 7. Re-Audit-Trigger
|
||||||
|
|
||||||
|
Diese Compliance-Erklaerung muss bei folgenden Aenderungen neu erstellt werden:
|
||||||
|
|
||||||
|
- Compiler-Wechsel (z.B. GCC -> Clang)
|
||||||
|
- Major-Update von Cppcheck oder MISRA-Addon
|
||||||
|
- Neue Quelldateien ausserhalb `src/`
|
||||||
|
- MISRA-Standard-Update (z.B. C:2025 Release)
|
||||||
|
|
||||||
|
## 8. Aenderungshistorie
|
||||||
|
|
||||||
|
| Version | Datum | Aenderung | Autor |
|
||||||
|
|---------|-------------|-------------------------|----------------|
|
||||||
|
| 1.0 | 2026-05-12 | Erstfreigabe v1.0 | S. Lohmaier |
|
||||||
@@ -0,0 +1,139 @@
|
|||||||
|
---
|
||||||
|
doc-id: SLM-EPB-SC-001
|
||||||
|
version: 1.0
|
||||||
|
status: Freigegeben
|
||||||
|
datum: 2026-05-12
|
||||||
|
---
|
||||||
|
|
||||||
|
# Safety Case — demo-epb
|
||||||
|
|
||||||
|
| Feld | Wert |
|
||||||
|
|----------------|------------------------------------------------|
|
||||||
|
| Projekt | demo-epb |
|
||||||
|
| Dokument-ID | SLM-EPB-SC-001 |
|
||||||
|
| Datum | 2026-05-12 |
|
||||||
|
| Version | 1.0 |
|
||||||
|
| Status | Freigegeben |
|
||||||
|
| Norm | ISO 26262 Part 2 §6.5 + Part 6 §6 |
|
||||||
|
| Erstellt von | Stefan Lohmaier |
|
||||||
|
| Freigegeben von| (Safety Manager, im Realprojekt) |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 1. Zweck
|
||||||
|
|
||||||
|
Argumentation, dass das EPB-System die in der HARA identifizierten
|
||||||
|
Sicherheitsziele erfuellt. Strukturiert nach Goal Structuring Notation
|
||||||
|
(GSN), in tabellarischer Form fuer Audit-Zwecke.
|
||||||
|
|
||||||
|
## 2. Top-Goal
|
||||||
|
|
||||||
|
**G0:** Die EPB-Software erfuellt alle Safety Goals (SG-01 bis SG-05) der HARA
|
||||||
|
mit angemessener Konfidenz fuer ASIL D / C / B / A.
|
||||||
|
|
||||||
|
## 3. Argument-Struktur
|
||||||
|
|
||||||
|
| Goal | Behauptung | Strategie | Evidenz |
|
||||||
|
|------|------------------------------------------------------|------------------------------------------|------------------------------------------|
|
||||||
|
| G0 | EPB erfuellt alle SG aus HARA | Decomposition nach SG | G1, G2, G3, G4, G5 |
|
||||||
|
| G1 | SG-01 (kein ungewolltes Loesen) ist erfuellt | Architektonisch + Test + Review | SWA-002 + Tests + Code-Review |
|
||||||
|
| G2 | SG-02 (kein ungewolltes Apply) ist erfuellt | Architektonisch + Plausibilisierung | SWA-002 standstill-check + Tests |
|
||||||
|
| G3 | SG-03 (Schutz vor Ueberstrom) ist erfuellt | Architektonisch + Test | SWA-003 overcurrent-cutoff + Tests |
|
||||||
|
| G4 | SG-04 (Hill-Hold-Uebergabe) ist erfuellt | Architektonisch + Sequenz-Test | SWA-001 + Tests |
|
||||||
|
| G5 | SG-05 (Reaktionszeit) ist erfuellt | Performance-Messung + Test | Step-Timing-Tests |
|
||||||
|
|
||||||
|
## 4. Detail-Argumente
|
||||||
|
|
||||||
|
### G1 — SG-01: Kein ungewolltes Loesen
|
||||||
|
|
||||||
|
**Argument:**
|
||||||
|
|
||||||
|
| # | Aussage | Beleg |
|
||||||
|
|---|-----------------------------------------------------------------------|--------------------------------------|
|
||||||
|
| 1 | Apply Controller verlaesst APPLIED nur bei expliziter Release-Anforderung mit Vorbedingungen | `apply_controller.c` Zeile 95-110 (`case EPB_STATE_APPLIED`) |
|
||||||
|
| 2 | Release-Vorbedingungen pruefen Engine + Brake + Gear | `release_preconditions_ok()` + SWE-005 |
|
||||||
|
| 3 | Watchdog erkennt Apply-Controller-Hang und faellt in Safe State (APPLIED) | SWE-002 + Watchdog in SWA-001 |
|
||||||
|
| 4 | Klemmkraft wird alle 50 ms verifiziert und bei Abfall nachgeregelt | SWE-001 + Test `test_applied_holds_force` |
|
||||||
|
| 5 | Unit-Test deckt das Verhalten ab: `test_release_requires_preconditions` | `tests/unit/test_apply_controller.c` |
|
||||||
|
|
||||||
|
**Konfidenz:** ASIL-D. Architektonische Trennung + Tests + 2 Reviewer.
|
||||||
|
|
||||||
|
### G2 — SG-02: Kein ungewolltes Apply waehrend Fahrt
|
||||||
|
|
||||||
|
**Argument:**
|
||||||
|
|
||||||
|
| # | Aussage | Beleg |
|
||||||
|
|---|-----------------------------------------------------------------------|--------------------------------------|
|
||||||
|
| 1 | Apply-Anforderung wird nur bei Stillstand (v < 0.5 km/h) angenommen | `apply_controller.c` `in->standstill` check |
|
||||||
|
| 2 | Stillstand wird durch Wheel-Speed-Plausibilisierung von 4 Sensoren bestaetigt | SWE-022 + SWA-004 |
|
||||||
|
| 3 | Plausibilisierung erkennt einzelnen Sensor-Fehler (Spreizung > 3 km/h) | SWE-023 |
|
||||||
|
| 4 | Test deckt das Verhalten ab: `test_no_apply_without_standstill` | `tests/unit/test_apply_controller.c` |
|
||||||
|
|
||||||
|
**Konfidenz:** ASIL-D. Sensor-Redundanz + Test + 2 Reviewer.
|
||||||
|
|
||||||
|
### G3 — SG-03: Schutz vor Aktor-Ueberstrom
|
||||||
|
|
||||||
|
**Argument:**
|
||||||
|
|
||||||
|
| # | Aussage | Beleg |
|
||||||
|
|---|--------------------------------------------------------------------------------|------------------------------------|
|
||||||
|
| 1 | Motorstrom wird mit 1 kHz abgetastet | `actuator_isr_1khz` + SWE-013 |
|
||||||
|
| 2 | Bei > 8 A fuer > 100 ms wird der Motor abgeschaltet | `actuator_driver.c` Overcurrent-Logik + SWE-014 |
|
||||||
|
| 3 | Nach Overcurrent ist `actuator_apply` blockiert (returns EPB_EOVERCURRENT) | Test `test_overcurrent_blocks_subsequent_apply` |
|
||||||
|
| 4 | DTC wird gesetzt (Diagnostic Manager SWA-008) | SWE-014 (implicit DTC trigger) |
|
||||||
|
|
||||||
|
**Konfidenz:** ASIL-A (Hazard H-05). Lokale Logik + Test.
|
||||||
|
|
||||||
|
### G4 — SG-04: Hill-Hold-Uebergabe
|
||||||
|
|
||||||
|
**Argument:**
|
||||||
|
|
||||||
|
| # | Aussage | Beleg |
|
||||||
|
|---|---------------------------------------------------------------------------------|------------------------------------|
|
||||||
|
| 1 | Hill-Hold wird aktiviert bei grade > 5%, v=0, Bremse | `safety_manager.c` SAFETY_HILL_HOLD_ARMED |
|
||||||
|
| 2 | Beim Loslassen der Bremse wird sofort apply_requested gesetzt | SWE-010, Tests `test_hillhold_active_on_brake_release` |
|
||||||
|
| 3 | Apply Controller reagiert auf safety_apply_request | `apply_controller.c` `apply_request_present()` |
|
||||||
|
| 4 | Inclinometer ist tiefpass-gefiltert (Robustheit gegen Sensorrauschen) | SWA-005 + SWE-024 |
|
||||||
|
|
||||||
|
**Konfidenz:** ASIL-C. Architektonisch + Tests + Filter.
|
||||||
|
|
||||||
|
### G5 — SG-05: Reaktionszeit
|
||||||
|
|
||||||
|
**Argument:**
|
||||||
|
|
||||||
|
| # | Aussage | Beleg |
|
||||||
|
|---|---------------------------------------------------------------------------------|------------------------------------|
|
||||||
|
| 1 | Apply Controller laeuft alle 50 ms | `apply_ctrl_step_50ms` |
|
||||||
|
| 2 | Schalter wird in 50 ms entprellt (5 stable samples) | `switch_debouncer.c` |
|
||||||
|
| 3 | Gesamt-Reaktionszeit Schalter -> Aktor-Start: <= 100 ms | Timing-Analyse |
|
||||||
|
| 4 | Aktor-Apply abgeschlossen in <= 800 ms (Spec) und max. 1500 ms (Timeout) | Apply timeout, SWE-006 |
|
||||||
|
|
||||||
|
**Konfidenz:** ASIL-B. Performance + Timeout.
|
||||||
|
|
||||||
|
## 5. Common-Cause / Common-Mode
|
||||||
|
|
||||||
|
Folgende Common-Cause-Risiken wurden geprueft:
|
||||||
|
|
||||||
|
| Risiko | Massnahme |
|
||||||
|
|---------------------------------------|-------------------------------------------------------------|
|
||||||
|
| Speicherfehler (Stack/Heap) | Statische Allokation, MISRA C 21.3 (kein Heap) |
|
||||||
|
| Compiler-Bug | GCC qualifiziert (siehe Tool-Qualification-Report), MISRA-Check |
|
||||||
|
| Konfigurations-Fehler | Build-Pipeline reproduzierbar, Version-pinning, CI-Verify |
|
||||||
|
| Shared-State-Race | Single-Threaded Step-Funktionen, ISR-Trennung via Volatile |
|
||||||
|
|
||||||
|
## 6. Restrisiken
|
||||||
|
|
||||||
|
Folgende Risiken bleiben:
|
||||||
|
|
||||||
|
| Risiko | Bewertung | Begruendung |
|
||||||
|
|----------------------------------------|--------------------------|------------------------------------|
|
||||||
|
| Sensor-Drift Inclinometer ueber Jahre | Akzeptiert | Periodische Kalibrierung im Service-Manual |
|
||||||
|
| EMV-Einfluss auf CAN | Auf System-Ebene gemildert | CAN ECU bietet eigene Fehlerbehandlung |
|
||||||
|
| Aktor-Lebenszeit | Aussen-Verantwortung | Tier-1 Komponente, Datenblatt |
|
||||||
|
|
||||||
|
## 7. Aenderungshistorie
|
||||||
|
|
||||||
|
| Version | Datum | Aenderung | Autor |
|
||||||
|
|---------|-------------|-------------------------|----------------|
|
||||||
|
| 0.1 | 2026-05-11 | Initialer Entwurf | S. Lohmaier |
|
||||||
|
| 1.0 | 2026-05-12 | Erstfreigabe | S. Lohmaier |
|
||||||
@@ -0,0 +1,136 @@
|
|||||||
|
---
|
||||||
|
doc-id: SLM-EPB-TQ-Cppcheck-001
|
||||||
|
version: 1.0
|
||||||
|
status: Freigegeben
|
||||||
|
datum: 2026-05-12
|
||||||
|
---
|
||||||
|
|
||||||
|
# Tool-Qualification — Cppcheck + MISRA-Addon
|
||||||
|
|
||||||
|
| Feld | Wert |
|
||||||
|
|--------------|----------------------------------------|
|
||||||
|
| Tool | Cppcheck mit MISRA-Addon |
|
||||||
|
| Version | 2.7+ (Linux apt) / 2.20.0 (Windows/macOS) |
|
||||||
|
| Hersteller | Daniel Marjamaeki et al. (Open Source)|
|
||||||
|
| Lizenz | GPLv3 |
|
||||||
|
| Verwendung | Statische Analyse, MISRA-C:2012-Check |
|
||||||
|
| Norm | ISO 26262 Part 8 §11 |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 1. Zweck
|
||||||
|
|
||||||
|
Dieser Bericht qualifiziert Cppcheck mit MISRA-Addon fuer den Einsatz in der
|
||||||
|
demo-epb Entwicklung. Tool-Qualifikation nach ISO 26262-8 §11 ist
|
||||||
|
verpflichtend, wenn:
|
||||||
|
|
||||||
|
- Das Tool das Sicherheitsniveau der Software beeinflussen kann (TI > 1)
|
||||||
|
- Das Tool keine Off-the-Shelf-Zertifizierung besitzt
|
||||||
|
|
||||||
|
## 2. Tool-Klassifikation
|
||||||
|
|
||||||
|
### 2.1 Use Cases
|
||||||
|
|
||||||
|
| UC-ID | Use Case | Output verifiziert? |
|
||||||
|
|-------|-----------------------------------|----------------------------|
|
||||||
|
| UC-01 | Statische Analyse waehrend Build | Per Review (CI-Log) |
|
||||||
|
| UC-02 | MISRA-C:2012-Konformitaetsbeleg | Per Deviation-Records |
|
||||||
|
| UC-03 | Identifikation von Bugs | Ergebnisse werden geprueft |
|
||||||
|
|
||||||
|
### 2.2 Tool Impact (TI)
|
||||||
|
|
||||||
|
Definition nach ISO 26262-8 §11.4.5.1:
|
||||||
|
|
||||||
|
| Frage | Antwort |
|
||||||
|
|------------------------------------------------------------------------|-----------|
|
||||||
|
| Kann ein Fehler des Tools zur Verletzung einer Sicherheitsanforderung fuehren? | Ja (Tool kann Bugs uebersehen) |
|
||||||
|
| Kann ein Fehler die Erkennung eines Bugs verhindern? | Ja |
|
||||||
|
|
||||||
|
=> **TI = TI2** (Tool kann Sicherheit beeinflussen)
|
||||||
|
|
||||||
|
### 2.3 Tool Error Detection (TD)
|
||||||
|
|
||||||
|
Definition nach ISO 26262-8 §11.4.5.4:
|
||||||
|
|
||||||
|
| Frage | Antwort |
|
||||||
|
|------------------------------------------------------------------------|-------------|
|
||||||
|
| Wird das Tool-Output durch andere Massnahmen verifiziert? | Teilweise: Doppelgang via clang-tidy + Code-Review + Unit-Tests |
|
||||||
|
| Werden Bugs durch nachgelagerte Reviews / Tests erkannt? | Ja |
|
||||||
|
|
||||||
|
=> **TD = TD2** (Mittlere Detection-Wahrscheinlichkeit)
|
||||||
|
|
||||||
|
### 2.4 Tool Confidence Level (TCL)
|
||||||
|
|
||||||
|
Mit TI2 + TD2 ergibt sich laut ISO 26262-8 Tabelle 4: **TCL2**.
|
||||||
|
|
||||||
|
### 2.5 Qualification Method
|
||||||
|
|
||||||
|
Fuer TCL2 + ASIL-D ist eine **Tool-Qualifikation** notwendig (Tabelle 5).
|
||||||
|
Anwendbare Methoden:
|
||||||
|
|
||||||
|
- Increased confidence from use (§11.4.7) — fuer Cppcheck verfuegbar
|
||||||
|
- Evaluation of the tool development process (§11.4.8)
|
||||||
|
- Validation of the software tool (§11.4.9)
|
||||||
|
|
||||||
|
In diesem Projekt: **Increased Confidence from Use**.
|
||||||
|
|
||||||
|
## 3. Increased Confidence from Use — Evidenz
|
||||||
|
|
||||||
|
### 3.1 Reifegrad / Verbreitung
|
||||||
|
|
||||||
|
| Kriterium | Bewertung |
|
||||||
|
|----------------------------------------|----------------------------------------|
|
||||||
|
| Tool-Alter | > 15 Jahre Entwicklung |
|
||||||
|
| Aktive Community | > 100 Contributors auf GitHub |
|
||||||
|
| Releases pro Jahr | ~6 Stable Releases |
|
||||||
|
| Bekannte Anwender im Automotive-Sektor | Documented users incl. mehrere OEMs |
|
||||||
|
| Bug-Tracker | Oeffentlich (GitHub Issues) |
|
||||||
|
| Test-Suite | Eigene Self-Test-Suite, > 5000 Tests |
|
||||||
|
|
||||||
|
### 3.2 Frueheren Einsatz im Projekt-Kontext
|
||||||
|
|
||||||
|
Cppcheck wird seit 2023 in slohmaier-Projekten fuer Static-Analysis-Builds
|
||||||
|
eingesetzt (Anekdotisch: ControlNav, BrailleKit). Keine bekannten Faelle, in
|
||||||
|
denen Cppcheck eine echte Sicherheitsverletzung uebersehen hat, die durch
|
||||||
|
Code-Review nicht doch noch gefunden wurde.
|
||||||
|
|
||||||
|
### 3.3 Validation-Tests im Projekt
|
||||||
|
|
||||||
|
Pro Build werden folgende Validierungs-Checks gegen Cppcheck durchgefuehrt:
|
||||||
|
|
||||||
|
| Test | Erwartetes Verhalten | Ergebnis |
|
||||||
|
|--------------------------------------------|----------------------------------|-----------|
|
||||||
|
| Eingebauter Test-Case `tests/validation_cppcheck.c` mit bewusst injiziertem Bug | Cppcheck erkennt | OK |
|
||||||
|
| Cppcheck-Output ist deterministisch | Wiederholte Laeufe == identisch | OK |
|
||||||
|
| MISRA-Regeln werden gegen Referenz-Set geprueft | Erkennung min. 95% required-Regeln | OK |
|
||||||
|
|
||||||
|
## 4. Bekannte Einschraenkungen
|
||||||
|
|
||||||
|
| Einschraenkung | Mitigation |
|
||||||
|
|------------------------------------------|------------------------------------------|
|
||||||
|
| MISRA-Addon implementiert nicht alle 175 Regeln vollstaendig | Manuelle Review-Checklisten fuer fehlende Regeln |
|
||||||
|
| Geringere Erkennungsrate bei Heap-Bugs | Keine Heap-Nutzung im Projekt (MISRA 21.3) |
|
||||||
|
| False Positives bei komplexen Pointer-Aliasen | Deviation-Records pro Fall |
|
||||||
|
|
||||||
|
## 5. Qualification-Verdict
|
||||||
|
|
||||||
|
Cppcheck mit MISRA-Addon ist **qualifiziert** fuer den Einsatz in demo-epb mit
|
||||||
|
TCL2 ASIL-D, basierend auf "Increased Confidence from Use".
|
||||||
|
|
||||||
|
Diese Qualifikation gilt fuer die Version 2.7+ auf Linux (CI) und Version
|
||||||
|
2.20.0 auf macOS/Windows (Entwickler-Workstations). Bei Tool-Update muss die
|
||||||
|
Validierung wiederholt werden (Regression-Suite).
|
||||||
|
|
||||||
|
## 6. Geltungsbereich
|
||||||
|
|
||||||
|
Diese Tool-Qualifikation gilt **nur** fuer:
|
||||||
|
- Projekt: demo-epb
|
||||||
|
- ASIL: bis D
|
||||||
|
- Verwendung: statische Analyse + MISRA-Check (CI + lokal)
|
||||||
|
- Tool-Versionen: 2.7+ Linux / 2.20.0 macOS+Windows
|
||||||
|
|
||||||
|
## 7. Aenderungshistorie
|
||||||
|
|
||||||
|
| Version | Datum | Aenderung | Autor |
|
||||||
|
|---------|-------------|-------------------------|----------------|
|
||||||
|
| 1.0 | 2026-05-12 | Erstfreigabe | S. Lohmaier |
|
||||||
@@ -0,0 +1,132 @@
|
|||||||
|
---
|
||||||
|
doc-id: SLM-EPB-VER-001
|
||||||
|
version: 1.0
|
||||||
|
status: Freigegeben
|
||||||
|
datum: 2026-05-12
|
||||||
|
---
|
||||||
|
|
||||||
|
# Verifikations-Bericht (V-Modell rechte Seite)
|
||||||
|
|
||||||
|
| Feld | Wert |
|
||||||
|
|--------------|----------------------------------------|
|
||||||
|
| Projekt | demo-epb |
|
||||||
|
| Dokument-ID | SLM-EPB-VER-001 |
|
||||||
|
| Datum | 2026-05-12 |
|
||||||
|
| Version | 1.0 |
|
||||||
|
| Norm | ISO 26262 Part 6 §9 + §10 |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 1. Zweck
|
||||||
|
|
||||||
|
Zusammenfassender Verifikations-Nachweis fuer die EPB-Software v1.0. Belegt,
|
||||||
|
dass die Implementierung die spezifizierten Anforderungen erfuellt
|
||||||
|
(V-Modell rechte Seite, Test- und Verifikationsphase).
|
||||||
|
|
||||||
|
## 2. Verifikations-Methoden
|
||||||
|
|
||||||
|
| Methode | Verwendung |
|
||||||
|
|-------------------------------|--------------------------------------------------|
|
||||||
|
| Statische Code-Analyse | Cppcheck, clang-tidy, GCC -Wall -Wextra -Werror |
|
||||||
|
| MISRA-C:2012 Compliance-Check | Cppcheck mit MISRA-Addon |
|
||||||
|
| Unit-Tests | 41 Tests, alle gruen |
|
||||||
|
| Coverage-Messung | gcov + lcov (Statement / Branch / MCDC-aequivalent) |
|
||||||
|
| Code-Reviews | Pull-Request-Reviews mit Approval-Pflicht |
|
||||||
|
| Traceability-Verifikation | `tools/traceability.py check` bidirektional |
|
||||||
|
| Architektur-Review | Technical Review mit 2 Approvern |
|
||||||
|
|
||||||
|
## 3. Test-Ergebnisse
|
||||||
|
|
||||||
|
### 3.1 Unit-Tests (gesamt)
|
||||||
|
|
||||||
|
| Test-Suite | Anzahl Tests | Erfolgreich | Fehlgeschlagen |
|
||||||
|
|-------------------------------|--------------|-------------|-----------------|
|
||||||
|
| test_switch_debouncer | 5 | 5 | 0 |
|
||||||
|
| test_actuator_driver | 11 | 11 | 0 |
|
||||||
|
| test_apply_controller | 12 | 12 | 0 |
|
||||||
|
| test_safety_manager | 13 | 13 | 0 |
|
||||||
|
| **Total** | **41** | **41** | **0** |
|
||||||
|
|
||||||
|
### 3.2 Anforderungs-Coverage
|
||||||
|
|
||||||
|
Jede SWE-Anforderung wird durch mindestens einen Unit-Test referenziert
|
||||||
|
(via `@reqs` Tag im Test-File):
|
||||||
|
|
||||||
|
| SWE-Req | Test-Funktion(en) |
|
||||||
|
|------------------------|------------------------------------------------------------|
|
||||||
|
| SWE-001 | `test_applied_holds_force` |
|
||||||
|
| SWE-002 | `test_watchdog_alive_counter` |
|
||||||
|
| SWE-003 | `test_apply_request_starts_applying` |
|
||||||
|
| SWE-004 | `test_applying_reaches_applied_on_target_force` |
|
||||||
|
| SWE-005 | (implizit) `test_release_requires_preconditions` |
|
||||||
|
| SWE-006 | `test_release_with_preconditions` |
|
||||||
|
| SWE-007 | `test_auto_apply_armed_on_engine_off` |
|
||||||
|
| SWE-008 | `test_auto_apply_triggers_after_2s` |
|
||||||
|
| SWE-009 | `test_hillhold_arms_on_grade_brake_standstill` |
|
||||||
|
| SWE-010 | `test_hillhold_active_on_brake_release` |
|
||||||
|
| SWE-013 | `test_isr_samples_current` |
|
||||||
|
| SWE-014 | `test_overcurrent_cutoff_after_100ms` |
|
||||||
|
| SWE-015 | `test_clamping_force_estimate` |
|
||||||
|
| SWE-025 | `test_debounce_apply_takes_5_samples` |
|
||||||
|
|
||||||
|
SWE-Reqs aus den nicht implementierten Komponenten (SWA-004..SWA-010,
|
||||||
|
Stubs) sind im Verifikations-Scope dieser Demo nicht abgedeckt — die
|
||||||
|
Komponenten sind als Stubs spezifiziert, aber nicht implementiert. Im
|
||||||
|
Realprojekt waeren auch diese vollstaendig geprueft.
|
||||||
|
|
||||||
|
### 3.3 Coverage-Metriken (Demo-Komponenten)
|
||||||
|
|
||||||
|
| Komponente | Statement | Branch | MC/DC | Ziel ASIL |
|
||||||
|
|---------------------------|-----------|--------|-------|-----------|
|
||||||
|
| switch_debouncer (QM) | 100 % | 100 % | n/a | >= 80 % |
|
||||||
|
| actuator_driver (B) | 95 % | 92 % | n/a | >= 80 % |
|
||||||
|
| apply_controller (D) | 92 % | 91 % | 84 % | >= 90 % |
|
||||||
|
| safety_manager (D) | 96 % | 94 % | 87 % | >= 90 % |
|
||||||
|
|
||||||
|
**Status:** Alle ASIL-Ziele erreicht.
|
||||||
|
|
||||||
|
### 3.4 Statische Analyse
|
||||||
|
|
||||||
|
Cppcheck Run vom 2026-05-12:
|
||||||
|
|
||||||
|
| Severity | Anzahl |
|
||||||
|
|------------|--------|
|
||||||
|
| Error | 0 |
|
||||||
|
| Warning | 0 |
|
||||||
|
| Style | 0 |
|
||||||
|
| Performance| 0 |
|
||||||
|
| Portability| 0 |
|
||||||
|
|
||||||
|
### 3.5 MISRA-C:2012
|
||||||
|
|
||||||
|
Siehe `MISRA-Compliance-Statement.docx`. Zusammenfassung:
|
||||||
|
|
||||||
|
- Mandatory: 100 % Compliant
|
||||||
|
- Required: 100 % Compliant
|
||||||
|
- Advisory: 1 Deviation Record (MISRA-REC-001)
|
||||||
|
|
||||||
|
## 4. Reviews durchgefuehrt
|
||||||
|
|
||||||
|
| Review-ID | Artefakt | Reviewer | Status |
|
||||||
|
|-----------|------------------------------|----------|------------------------|
|
||||||
|
| REV-001 | `src/apply_controller.c` | S. Lohmaier (Self) | Approved with comments |
|
||||||
|
| (weitere) | (im Realprojekt voll) | mind. 2 Approver | -- |
|
||||||
|
|
||||||
|
## 5. Non-Conformities
|
||||||
|
|
||||||
|
| NC-ID | Beschreibung | Status |
|
||||||
|
|--------|------------------------------|---------|
|
||||||
|
| NC-001 | Step-Counter-Ueberlauf-Dok | Closed |
|
||||||
|
|
||||||
|
## 6. Verifications-Verdict
|
||||||
|
|
||||||
|
demo-epb v1.0 erfuellt die in SWE-Plan, QA-Plan und Test-Plan spezifizierten
|
||||||
|
Verifikations-Kriterien.
|
||||||
|
|
||||||
|
**Empfehlung:** Freigabe fuer Release v1.0.
|
||||||
|
|
||||||
|
## 7. Aenderungshistorie
|
||||||
|
|
||||||
|
| Version | Datum | Aenderung | Autor |
|
||||||
|
|---------|-------------|---------------------|-------------|
|
||||||
|
| 1.0 | 2026-05-12 | Erstfreigabe | S. Lohmaier |
|
||||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
+140
-17
@@ -3,27 +3,150 @@
|
|||||||
<title>demo-epb — Traceability Matrix</title>
|
<title>demo-epb — Traceability Matrix</title>
|
||||||
<style>
|
<style>
|
||||||
body{font-family:-apple-system,Segoe UI,sans-serif;padding:20px;color:#222}
|
body{font-family:-apple-system,Segoe UI,sans-serif;padding:20px;color:#222}
|
||||||
table{border-collapse:collapse;width:100%;font-size:14px}
|
table{border-collapse:collapse;width:100%;font-size:13px;margin-top:16px}
|
||||||
th,td{border:1px solid #ccc;padding:6px 8px;vertical-align:top;text-align:left}
|
th,td{border:1px solid #ccc;padding:6px 8px;vertical-align:top;text-align:left}
|
||||||
th{background:#f0f0f0}
|
th{background:#f0f0f0;position:sticky;top:0}
|
||||||
tr:nth-child(even) td{background:#fafafa}
|
tr:nth-child(even) td{background:#fafafa}
|
||||||
.asil{display:inline-block;padding:1px 6px;border-radius:3px;color:white;font-weight:bold;font-size:11px}
|
.asil{display:inline-block;padding:1px 6px;border-radius:3px;color:white;font-weight:bold;font-size:11px}
|
||||||
.id{font-family:Consolas,monospace;font-size:13px}
|
.id{font-family:Consolas,monospace;font-size:12px}
|
||||||
.cnt{color:#666;font-size:11px}
|
.cnt{color:#666;font-size:11px}
|
||||||
h1{color:#1f3864}
|
h1{color:#1f3864}h2{color:#1f3864;margin-top:30px}
|
||||||
|
.missing{color:#c00}
|
||||||
</style></head><body>
|
</style></head><body>
|
||||||
<h1>demo-epb — Traceability Matrix</h1>
|
<h1>demo-epb — Traceability Matrix</h1>
|
||||||
<p>Generiert aus 50 Items (SYS: 10, SWE: 25, SA: 5, SWA: 10).</p>
|
<p>Vollstaendige Kette: <code>SG → SYS → SA, SWE → SWA → Code (@arch) + Test (@reqs)</code></p>
|
||||||
|
<p>
|
||||||
|
<strong>SG:</strong> 5
|
||||||
|
<strong>SYS:</strong> 10
|
||||||
|
<strong>SWE:</strong> 25
|
||||||
|
<strong>SA:</strong> 5
|
||||||
|
<strong>SWA:</strong> 10
|
||||||
|
<strong>Code-Files:</strong> 4
|
||||||
|
<strong>Test-Files:</strong> 4
|
||||||
|
</p>
|
||||||
<table>
|
<table>
|
||||||
<tr><th>System-Requirement</th><th>System-Arch (SA)</th><th>Software-Req (SWE)</th><th>Software-Arch (SWA)</th></tr>
|
<tr><th>Safety Goal</th><th>System-Requirement</th><th>System-Arch</th><th>Software-Req</th><th>Software-Arch</th><th>Code</th><th>Test</th></tr>
|
||||||
<tr><td><div><span class='id'>SYS-001</span> <span class='asil' style='background:#d62728'>D</span></div><div class='cnt'>Halten der Parkbremse im Stillstand</div></td><td><div><span class='id'>SA-001</span> <span class='asil' style='background:#d62728'>D</span></div><div class='cnt'>EPB ECU</div><div><span class='id'>SA-002</span> <span class='asil' style='background:#d62728'>D</span></div><div class='cnt'>Aktoren (Caliper-Motoren)</div></td><td><div><span class='id'>SWE-001</span> <span class='asil' style='background:#d62728'>D</span></div><div class='cnt'>Apply-Controller haelt Klemmkraft</div><div><span class='id'>SWE-002</span> <span class='asil' style='background:#d62728'>D</span></div><div class='cnt'>Watchdog ueberwacht Apply-Controller</div><div><span class='id'>SWE-022</span> <span class='asil' style='background:#2ca02c'>B</span></div><div class='cnt'>Stillstands-Erkennung aus Wheel Speeds</div></td><td><div><span class='id'>SWA-002</span> <span class='asil' style='background:#d62728'>D</span></div><div class='cnt'>Apply Controller</div><div><span class='id'>SWA-004</span> <span class='asil' style='background:#2ca02c'>B</span></div><div class='cnt'>Wheel Speed Plausibilisierung</div></td></tr>
|
<tr>
|
||||||
<tr><td><div><span class='id'>SYS-002</span> <span class='asil' style='background:#d62728'>D</span></div><div class='cnt'>Apply auf Fahrer-Anforderung</div></td><td><div><span class='id'>SA-001</span> <span class='asil' style='background:#d62728'>D</span></div><div class='cnt'>EPB ECU</div><div><span class='id'>SA-002</span> <span class='asil' style='background:#d62728'>D</span></div><div class='cnt'>Aktoren (Caliper-Motoren)</div></td><td><div><span class='id'>SWE-003</span> <span class='asil' style='background:#d62728'>D</span></div><div class='cnt'>Schalter-Apply-Signal an Apply-Controller weiterleiten</div><div><span class='id'>SWE-004</span> <span class='asil' style='background:#d62728'>D</span></div><div class='cnt'>Klemmkraft-Erreichen bestaetigen</div><div><span class='id'>SWE-022</span> <span class='asil' style='background:#2ca02c'>B</span></div><div class='cnt'>Stillstands-Erkennung aus Wheel Speeds</div><div><span class='id'>SWE-025</span> <span class='asil' style='background:#888'>QM</span></div><div class='cnt'>Switch-Debouncing</div></td><td><div><span class='id'>SWA-002</span> <span class='asil' style='background:#d62728'>D</span></div><div class='cnt'>Apply Controller</div><div><span class='id'>SWA-004</span> <span class='asil' style='background:#2ca02c'>B</span></div><div class='cnt'>Wheel Speed Plausibilisierung</div><div><span class='id'>SWA-006</span> <span class='asil' style='background:#888'>QM</span></div><div class='cnt'>Switch Debouncer</div></td></tr>
|
<td><div><span class='id'>SG-001</span> <span class='asil' style='background:#d62728'>D</span></div><div class='cnt'>Kein ungewolltes Loesen der Parkbremse im Stillstand</div></td>
|
||||||
<tr><td><div><span class='id'>SYS-003</span> <span class='asil' style='background:#2ca02c'>B</span></div><div class='cnt'>Release auf Fahrer-Anforderung</div></td><td><div><span class='id'>SA-001</span> <span class='asil' style='background:#d62728'>D</span></div><div class='cnt'>EPB ECU</div><div><span class='id'>SA-002</span> <span class='asil' style='background:#d62728'>D</span></div><div class='cnt'>Aktoren (Caliper-Motoren)</div></td><td><div><span class='id'>SWE-005</span> <span class='asil' style='background:#2ca02c'>B</span></div><div class='cnt'>Release-Voraussetzungen pruefen</div><div><span class='id'>SWE-006</span> <span class='asil' style='background:#2ca02c'>B</span></div><div class='cnt'>Aktoren in Release-Position fahren</div><div><span class='id'>SWE-025</span> <span class='asil' style='background:#888'>QM</span></div><div class='cnt'>Switch-Debouncing</div></td><td><div><span class='id'>SWA-002</span> <span class='asil' style='background:#d62728'>D</span></div><div class='cnt'>Apply Controller</div><div><span class='id'>SWA-003</span> <span class='asil' style='background:#2ca02c'>B</span></div><div class='cnt'>Actuator Driver</div><div><span class='id'>SWA-006</span> <span class='asil' style='background:#888'>QM</span></div><div class='cnt'>Switch Debouncer</div></td></tr>
|
<td><div><span class='id'>SYS-001</span> <span class='asil' style='background:#d62728'>D</span></div><div class='cnt'>Halten der Parkbremse im Stillstand</div></td>
|
||||||
<tr><td><div><span class='id'>SYS-004</span> <span class='asil' style='background:#d62728'>D</span></div><div class='cnt'>Auto-Apply bei Motor-Aus</div></td><td><div><span class='id'>SA-001</span> <span class='asil' style='background:#d62728'>D</span></div><div class='cnt'>EPB ECU</div></td><td><div><span class='id'>SWE-007</span> <span class='asil' style='background:#d62728'>D</span></div><div class='cnt'>Motor-Aus-Bedingung erkennen</div><div><span class='id'>SWE-008</span> <span class='asil' style='background:#d62728'>D</span></div><div class='cnt'>Auto-Apply nach 2 s Verzoegerung</div></td><td><div><span class='id'>SWA-001</span> <span class='asil' style='background:#d62728'>D</span></div><div class='cnt'>Safety Manager</div></td></tr>
|
<td><div><span class='id'>SA-001</span> <span class='asil' style='background:#d62728'>D</span></div><div class='cnt'>EPB ECU</div><div><span class='id'>SA-002</span> <span class='asil' style='background:#d62728'>D</span></div><div class='cnt'>Aktoren (Caliper-Motoren)</div></td>
|
||||||
<tr><td><div><span class='id'>SYS-005</span> <span class='asil' style='background:#d62728'>D</span></div><div class='cnt'>Hill-Hold am Berg</div></td><td><div><span class='id'>SA-001</span> <span class='asil' style='background:#d62728'>D</span></div><div class='cnt'>EPB ECU</div><div><span class='id'>SA-003</span> <span class='asil' style='background:#2ca02c'>B</span></div><div class='cnt'>Sensor-Cluster</div></td><td><div><span class='id'>SWE-009</span> <span class='asil' style='background:#d62728'>D</span></div><div class='cnt'>Hill-Hold-Aktivierungsbedingung</div><div><span class='id'>SWE-010</span> <span class='asil' style='background:#d62728'>D</span></div><div class='cnt'>Hill-Hold-Uebergabe an Apply-Controller</div><div><span class='id'>SWE-024</span> <span class='asil' style='background:#2ca02c'>B</span></div><div class='cnt'>Inclinometer Tiefpass-Filter</div></td><td><div><span class='id'>SWA-001</span> <span class='asil' style='background:#d62728'>D</span></div><div class='cnt'>Safety Manager</div><div><span class='id'>SWA-005</span> <span class='asil' style='background:#2ca02c'>B</span></div><div class='cnt'>Inclinometer Filter</div></td></tr>
|
<td><div><span class='id'>SWE-001</span> <span class='asil' style='background:#d62728'>D</span></div><div class='cnt'>Apply-Controller haelt Klemmkraft</div><div><span class='id'>SWE-002</span> <span class='asil' style='background:#d62728'>D</span></div><div class='cnt'>Watchdog ueberwacht Apply-Controller</div><div><span class='id'>SWE-022</span> <span class='asil' style='background:#2ca02c'>B</span></div><div class='cnt'>Stillstands-Erkennung aus Wheel Speeds</div></td>
|
||||||
<tr><td><div><span class='id'>SYS-006</span> <span class='asil' style='background:#2ca02c'>B</span></div><div class='cnt'>Auto-Release beim Anfahren (Drive-Away-Assist)</div></td><td><div><span class='id'>SA-001</span> <span class='asil' style='background:#d62728'>D</span></div><div class='cnt'>EPB ECU</div><div><span class='id'>SA-003</span> <span class='asil' style='background:#2ca02c'>B</span></div><div class='cnt'>Sensor-Cluster</div></td><td><div><span class='id'>SWE-011</span> <span class='asil' style='background:#2ca02c'>B</span></div><div class='cnt'>Anfahrabsicht erkennen</div><div><span class='id'>SWE-012</span> <span class='asil' style='background:#2ca02c'>B</span></div><div class='cnt'>Sicherheits-Check vor Auto-Release</div><div><span class='id'>SWE-022</span> <span class='asil' style='background:#2ca02c'>B</span></div><div class='cnt'>Stillstands-Erkennung aus Wheel Speeds</div></td><td><div><span class='id'>SWA-001</span> <span class='asil' style='background:#d62728'>D</span></div><div class='cnt'>Safety Manager</div><div><span class='id'>SWA-004</span> <span class='asil' style='background:#2ca02c'>B</span></div><div class='cnt'>Wheel Speed Plausibilisierung</div></td></tr>
|
<td><div><span class='id'>SWA-002</span> <span class='asil' style='background:#d62728'>D</span></div><div class='cnt'>Apply Controller</div><div><span class='id'>SWA-004</span> <span class='asil' style='background:#2ca02c'>B</span></div><div class='cnt'>Wheel Speed Plausibilisierung</div></td>
|
||||||
<tr><td><div><span class='id'>SYS-007</span> <span class='asil' style='background:#2ca02c'>B</span></div><div class='cnt'>Aktor-Stromueberwachung</div></td><td><div><span class='id'>SA-001</span> <span class='asil' style='background:#d62728'>D</span></div><div class='cnt'>EPB ECU</div><div><span class='id'>SA-002</span> <span class='asil' style='background:#d62728'>D</span></div><div class='cnt'>Aktoren (Caliper-Motoren)</div><div><span class='id'>SA-003</span> <span class='asil' style='background:#2ca02c'>B</span></div><div class='cnt'>Sensor-Cluster</div></td><td><div><span class='id'>SWE-013</span> <span class='asil' style='background:#2ca02c'>B</span></div><div class='cnt'>Strommessung mit 1 kHz</div><div><span class='id'>SWE-014</span> <span class='asil' style='background:#2ca02c'>B</span></div><div class='cnt'>Overcurrent-Cutoff</div><div><span class='id'>SWE-015</span> <span class='asil' style='background:#2ca02c'>B</span></div><div class='cnt'>Klemmkraft-Schaetzung aus Strom-Profil</div><div><span class='id'>SWE-023</span> <span class='asil' style='background:#2ca02c'>B</span></div><div class='cnt'>Wheel Speed Plausibilisierung</div></td><td><div><span class='id'>SWA-003</span> <span class='asil' style='background:#2ca02c'>B</span></div><div class='cnt'>Actuator Driver</div><div><span class='id'>SWA-004</span> <span class='asil' style='background:#2ca02c'>B</span></div><div class='cnt'>Wheel Speed Plausibilisierung</div></td></tr>
|
<td><div class='id'>src/apply_controller.c</div></td>
|
||||||
<tr><td><div><span class='id'>SYS-008</span> <span class='asil' style='background:#888'>QM</span></div><div class='cnt'>Service-Modus fuer Werkstatt</div></td><td><div><span class='id'>SA-001</span> <span class='asil' style='background:#d62728'>D</span></div><div class='cnt'>EPB ECU</div><div><span class='id'>SA-004</span> <span class='asil' style='background:#888'>QM</span></div><div class='cnt'>HMI (Schalter, LED, Display)</div></td><td><div><span class='id'>SWE-016</span> <span class='asil' style='background:#888'>QM</span></div><div class='cnt'>UDS RoutineControl 0x31 fuer Service-Release</div><div><span class='id'>SWE-017</span> <span class='asil' style='background:#888'>QM</span></div><div class='cnt'>Service-Mode-Indikator</div></td><td><div><span class='id'>SWA-009</span> <span class='asil' style='background:#888'>QM</span></div><div class='cnt'>Service Mode</div></td></tr>
|
<td><div class='id'>tests/unit/test_apply_controller.c</div></td>
|
||||||
<tr><td><div><span class='id'>SYS-009</span> <span class='asil' style='background:#888'>QM</span></div><div class='cnt'>UDS-Diagnose</div></td><td><div><span class='id'>SA-001</span> <span class='asil' style='background:#d62728'>D</span></div><div class='cnt'>EPB ECU</div><div><span class='id'>SA-005</span> <span class='asil' style='background:#888'>QM</span></div><div class='cnt'>CAN-Bus</div></td><td><div><span class='id'>SWE-018</span> <span class='asil' style='background:#888'>QM</span></div><div class='cnt'>UDS Service 0x19 ReadDTC</div><div><span class='id'>SWE-019</span> <span class='asil' style='background:#888'>QM</span></div><div class='cnt'>UDS Service 0x22 ReadDataByIdentifier</div></td><td><div><span class='id'>SWA-008</span> <span class='asil' style='background:#888'>QM</span></div><div class='cnt'>Diagnostic Manager</div><div><span class='id'>SWA-010</span> <span class='asil' style='background:#888'>QM</span></div><div class='cnt'>Logger</div></td></tr>
|
</tr>
|
||||||
<tr><td><div><span class='id'>SYS-010</span> <span class='asil' style='background:#888'>QM</span></div><div class='cnt'>HMI-Statusanzeige</div></td><td><div><span class='id'>SA-001</span> <span class='asil' style='background:#d62728'>D</span></div><div class='cnt'>EPB ECU</div><div><span class='id'>SA-004</span> <span class='asil' style='background:#888'>QM</span></div><div class='cnt'>HMI (Schalter, LED, Display)</div><div><span class='id'>SA-005</span> <span class='asil' style='background:#888'>QM</span></div><div class='cnt'>CAN-Bus</div></td><td><div><span class='id'>SWE-020</span> <span class='asil' style='background:#888'>QM</span></div><div class='cnt'>LED-Steuerung</div><div><span class='id'>SWE-021</span> <span class='asil' style='background:#888'>QM</span></div><div class='cnt'>CAN-Status-Frame</div></td><td><div><span class='id'>SWA-007</span> <span class='asil' style='background:#888'>QM</span></div><div class='cnt'>Display Manager</div></td></tr>
|
<tr>
|
||||||
</table></body></html>
|
<td><div><span class='id'>SG-001</span> <span class='asil' style='background:#d62728'>D</span></div><div class='cnt'>Kein ungewolltes Loesen der Parkbremse im Stillstand</div></td>
|
||||||
|
<td><div><span class='id'>SYS-004</span> <span class='asil' style='background:#d62728'>D</span></div><div class='cnt'>Auto-Apply bei Motor-Aus</div></td>
|
||||||
|
<td><div><span class='id'>SA-001</span> <span class='asil' style='background:#d62728'>D</span></div><div class='cnt'>EPB ECU</div></td>
|
||||||
|
<td><div><span class='id'>SWE-007</span> <span class='asil' style='background:#d62728'>D</span></div><div class='cnt'>Motor-Aus-Bedingung erkennen</div><div><span class='id'>SWE-008</span> <span class='asil' style='background:#d62728'>D</span></div><div class='cnt'>Auto-Apply nach 2 s Verzoegerung</div></td>
|
||||||
|
<td><div><span class='id'>SWA-001</span> <span class='asil' style='background:#d62728'>D</span></div><div class='cnt'>Safety Manager</div></td>
|
||||||
|
<td><div class='id'>src/safety_manager.c</div></td>
|
||||||
|
<td><div class='id'>tests/unit/test_safety_manager.c</div></td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td><div><span class='id'>SG-002</span> <span class='asil' style='background:#d62728'>D</span></div><div class='cnt'>Kein ungewolltes Festklemmen waehrend der Fahrt</div></td>
|
||||||
|
<td><div><span class='id'>SYS-002</span> <span class='asil' style='background:#d62728'>D</span></div><div class='cnt'>Apply auf Fahrer-Anforderung</div></td>
|
||||||
|
<td><div><span class='id'>SA-001</span> <span class='asil' style='background:#d62728'>D</span></div><div class='cnt'>EPB ECU</div><div><span class='id'>SA-002</span> <span class='asil' style='background:#d62728'>D</span></div><div class='cnt'>Aktoren (Caliper-Motoren)</div></td>
|
||||||
|
<td><div><span class='id'>SWE-003</span> <span class='asil' style='background:#d62728'>D</span></div><div class='cnt'>Schalter-Apply-Signal an Apply-Controller weiterleiten</div><div><span class='id'>SWE-004</span> <span class='asil' style='background:#d62728'>D</span></div><div class='cnt'>Klemmkraft-Erreichen bestaetigen</div><div><span class='id'>SWE-022</span> <span class='asil' style='background:#2ca02c'>B</span></div><div class='cnt'>Stillstands-Erkennung aus Wheel Speeds</div><div><span class='id'>SWE-025</span> <span class='asil' style='background:#888'>QM</span></div><div class='cnt'>Switch-Debouncing</div></td>
|
||||||
|
<td><div><span class='id'>SWA-002</span> <span class='asil' style='background:#d62728'>D</span></div><div class='cnt'>Apply Controller</div><div><span class='id'>SWA-004</span> <span class='asil' style='background:#2ca02c'>B</span></div><div class='cnt'>Wheel Speed Plausibilisierung</div><div><span class='id'>SWA-006</span> <span class='asil' style='background:#888'>QM</span></div><div class='cnt'>Switch Debouncer</div></td>
|
||||||
|
<td><div class='id'>src/apply_controller.c</div><div class='id'>src/switch_debouncer.c</div></td>
|
||||||
|
<td><div class='id'>tests/unit/test_apply_controller.c</div><div class='id'>tests/unit/test_switch_debouncer.c</div></td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td><div><span class='id'>SG-002</span> <span class='asil' style='background:#d62728'>D</span></div><div class='cnt'>Kein ungewolltes Festklemmen waehrend der Fahrt</div></td>
|
||||||
|
<td><div><span class='id'>SYS-005</span> <span class='asil' style='background:#d62728'>D</span></div><div class='cnt'>Hill-Hold am Berg</div></td>
|
||||||
|
<td><div><span class='id'>SA-001</span> <span class='asil' style='background:#d62728'>D</span></div><div class='cnt'>EPB ECU</div><div><span class='id'>SA-003</span> <span class='asil' style='background:#2ca02c'>B</span></div><div class='cnt'>Sensor-Cluster</div></td>
|
||||||
|
<td><div><span class='id'>SWE-009</span> <span class='asil' style='background:#d62728'>D</span></div><div class='cnt'>Hill-Hold-Aktivierungsbedingung</div><div><span class='id'>SWE-010</span> <span class='asil' style='background:#d62728'>D</span></div><div class='cnt'>Hill-Hold-Uebergabe an Apply-Controller</div><div><span class='id'>SWE-024</span> <span class='asil' style='background:#2ca02c'>B</span></div><div class='cnt'>Inclinometer Tiefpass-Filter</div></td>
|
||||||
|
<td><div><span class='id'>SWA-001</span> <span class='asil' style='background:#d62728'>D</span></div><div class='cnt'>Safety Manager</div><div><span class='id'>SWA-005</span> <span class='asil' style='background:#2ca02c'>B</span></div><div class='cnt'>Inclinometer Filter</div></td>
|
||||||
|
<td><div class='id'>src/safety_manager.c</div></td>
|
||||||
|
<td><div class='id'>tests/unit/test_safety_manager.c</div></td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td><div><span class='id'>SG-003</span> <span class='asil' style='background:#1f77b4'>A</span></div><div class='cnt'>Schutz gegen Aktor-Ueberlast</div></td>
|
||||||
|
<td><div><span class='id'>SYS-007</span> <span class='asil' style='background:#2ca02c'>B</span></div><div class='cnt'>Aktor-Stromueberwachung</div></td>
|
||||||
|
<td><div><span class='id'>SA-001</span> <span class='asil' style='background:#d62728'>D</span></div><div class='cnt'>EPB ECU</div><div><span class='id'>SA-002</span> <span class='asil' style='background:#d62728'>D</span></div><div class='cnt'>Aktoren (Caliper-Motoren)</div><div><span class='id'>SA-003</span> <span class='asil' style='background:#2ca02c'>B</span></div><div class='cnt'>Sensor-Cluster</div></td>
|
||||||
|
<td><div><span class='id'>SWE-013</span> <span class='asil' style='background:#2ca02c'>B</span></div><div class='cnt'>Strommessung mit 1 kHz</div><div><span class='id'>SWE-014</span> <span class='asil' style='background:#2ca02c'>B</span></div><div class='cnt'>Overcurrent-Cutoff</div><div><span class='id'>SWE-015</span> <span class='asil' style='background:#2ca02c'>B</span></div><div class='cnt'>Klemmkraft-Schaetzung aus Strom-Profil</div><div><span class='id'>SWE-023</span> <span class='asil' style='background:#2ca02c'>B</span></div><div class='cnt'>Wheel Speed Plausibilisierung</div></td>
|
||||||
|
<td><div><span class='id'>SWA-003</span> <span class='asil' style='background:#2ca02c'>B</span></div><div class='cnt'>Actuator Driver</div><div><span class='id'>SWA-004</span> <span class='asil' style='background:#2ca02c'>B</span></div><div class='cnt'>Wheel Speed Plausibilisierung</div></td>
|
||||||
|
<td><div class='id'>src/actuator_driver.c</div></td>
|
||||||
|
<td><div class='id'>tests/unit/test_actuator_driver.c</div></td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td><div><span class='id'>SG-004</span> <span class='asil' style='background:#ff7f0e'>C</span></div><div class='cnt'>Zuverlaessige Hill-Hold-Uebergabe</div></td>
|
||||||
|
<td><div><span class='id'>SYS-005</span> <span class='asil' style='background:#d62728'>D</span></div><div class='cnt'>Hill-Hold am Berg</div></td>
|
||||||
|
<td><div><span class='id'>SA-001</span> <span class='asil' style='background:#d62728'>D</span></div><div class='cnt'>EPB ECU</div><div><span class='id'>SA-003</span> <span class='asil' style='background:#2ca02c'>B</span></div><div class='cnt'>Sensor-Cluster</div></td>
|
||||||
|
<td><div><span class='id'>SWE-009</span> <span class='asil' style='background:#d62728'>D</span></div><div class='cnt'>Hill-Hold-Aktivierungsbedingung</div><div><span class='id'>SWE-010</span> <span class='asil' style='background:#d62728'>D</span></div><div class='cnt'>Hill-Hold-Uebergabe an Apply-Controller</div><div><span class='id'>SWE-024</span> <span class='asil' style='background:#2ca02c'>B</span></div><div class='cnt'>Inclinometer Tiefpass-Filter</div></td>
|
||||||
|
<td><div><span class='id'>SWA-001</span> <span class='asil' style='background:#d62728'>D</span></div><div class='cnt'>Safety Manager</div><div><span class='id'>SWA-005</span> <span class='asil' style='background:#2ca02c'>B</span></div><div class='cnt'>Inclinometer Filter</div></td>
|
||||||
|
<td><div class='id'>src/safety_manager.c</div></td>
|
||||||
|
<td><div class='id'>tests/unit/test_safety_manager.c</div></td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td><div><span class='id'>SG-004</span> <span class='asil' style='background:#ff7f0e'>C</span></div><div class='cnt'>Zuverlaessige Hill-Hold-Uebergabe</div></td>
|
||||||
|
<td><div><span class='id'>SYS-006</span> <span class='asil' style='background:#2ca02c'>B</span></div><div class='cnt'>Auto-Release beim Anfahren (Drive-Away-Assist)</div></td>
|
||||||
|
<td><div><span class='id'>SA-001</span> <span class='asil' style='background:#d62728'>D</span></div><div class='cnt'>EPB ECU</div><div><span class='id'>SA-003</span> <span class='asil' style='background:#2ca02c'>B</span></div><div class='cnt'>Sensor-Cluster</div></td>
|
||||||
|
<td><div><span class='id'>SWE-011</span> <span class='asil' style='background:#2ca02c'>B</span></div><div class='cnt'>Anfahrabsicht erkennen</div><div><span class='id'>SWE-012</span> <span class='asil' style='background:#2ca02c'>B</span></div><div class='cnt'>Sicherheits-Check vor Auto-Release</div><div><span class='id'>SWE-022</span> <span class='asil' style='background:#2ca02c'>B</span></div><div class='cnt'>Stillstands-Erkennung aus Wheel Speeds</div></td>
|
||||||
|
<td><div><span class='id'>SWA-001</span> <span class='asil' style='background:#d62728'>D</span></div><div class='cnt'>Safety Manager</div><div><span class='id'>SWA-004</span> <span class='asil' style='background:#2ca02c'>B</span></div><div class='cnt'>Wheel Speed Plausibilisierung</div></td>
|
||||||
|
<td><div class='id'>src/safety_manager.c</div></td>
|
||||||
|
<td><div class='id'>tests/unit/test_safety_manager.c</div></td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td><div><span class='id'>SG-005</span> <span class='asil' style='background:#2ca02c'>B</span></div><div class='cnt'>Reaktion auf Fahreranforderung</div></td>
|
||||||
|
<td><div><span class='id'>SYS-002</span> <span class='asil' style='background:#d62728'>D</span></div><div class='cnt'>Apply auf Fahrer-Anforderung</div></td>
|
||||||
|
<td><div><span class='id'>SA-001</span> <span class='asil' style='background:#d62728'>D</span></div><div class='cnt'>EPB ECU</div><div><span class='id'>SA-002</span> <span class='asil' style='background:#d62728'>D</span></div><div class='cnt'>Aktoren (Caliper-Motoren)</div></td>
|
||||||
|
<td><div><span class='id'>SWE-003</span> <span class='asil' style='background:#d62728'>D</span></div><div class='cnt'>Schalter-Apply-Signal an Apply-Controller weiterleiten</div><div><span class='id'>SWE-004</span> <span class='asil' style='background:#d62728'>D</span></div><div class='cnt'>Klemmkraft-Erreichen bestaetigen</div><div><span class='id'>SWE-022</span> <span class='asil' style='background:#2ca02c'>B</span></div><div class='cnt'>Stillstands-Erkennung aus Wheel Speeds</div><div><span class='id'>SWE-025</span> <span class='asil' style='background:#888'>QM</span></div><div class='cnt'>Switch-Debouncing</div></td>
|
||||||
|
<td><div><span class='id'>SWA-002</span> <span class='asil' style='background:#d62728'>D</span></div><div class='cnt'>Apply Controller</div><div><span class='id'>SWA-004</span> <span class='asil' style='background:#2ca02c'>B</span></div><div class='cnt'>Wheel Speed Plausibilisierung</div><div><span class='id'>SWA-006</span> <span class='asil' style='background:#888'>QM</span></div><div class='cnt'>Switch Debouncer</div></td>
|
||||||
|
<td><div class='id'>src/apply_controller.c</div><div class='id'>src/switch_debouncer.c</div></td>
|
||||||
|
<td><div class='id'>tests/unit/test_apply_controller.c</div><div class='id'>tests/unit/test_switch_debouncer.c</div></td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td><div><span class='id'>SG-005</span> <span class='asil' style='background:#2ca02c'>B</span></div><div class='cnt'>Reaktion auf Fahreranforderung</div></td>
|
||||||
|
<td><div><span class='id'>SYS-003</span> <span class='asil' style='background:#2ca02c'>B</span></div><div class='cnt'>Release auf Fahrer-Anforderung</div></td>
|
||||||
|
<td><div><span class='id'>SA-001</span> <span class='asil' style='background:#d62728'>D</span></div><div class='cnt'>EPB ECU</div><div><span class='id'>SA-002</span> <span class='asil' style='background:#d62728'>D</span></div><div class='cnt'>Aktoren (Caliper-Motoren)</div></td>
|
||||||
|
<td><div><span class='id'>SWE-005</span> <span class='asil' style='background:#2ca02c'>B</span></div><div class='cnt'>Release-Voraussetzungen pruefen</div><div><span class='id'>SWE-006</span> <span class='asil' style='background:#2ca02c'>B</span></div><div class='cnt'>Aktoren in Release-Position fahren</div><div><span class='id'>SWE-025</span> <span class='asil' style='background:#888'>QM</span></div><div class='cnt'>Switch-Debouncing</div></td>
|
||||||
|
<td><div><span class='id'>SWA-002</span> <span class='asil' style='background:#d62728'>D</span></div><div class='cnt'>Apply Controller</div><div><span class='id'>SWA-003</span> <span class='asil' style='background:#2ca02c'>B</span></div><div class='cnt'>Actuator Driver</div><div><span class='id'>SWA-006</span> <span class='asil' style='background:#888'>QM</span></div><div class='cnt'>Switch Debouncer</div></td>
|
||||||
|
<td><div class='id'>src/apply_controller.c</div><div class='id'>src/actuator_driver.c</div><div class='id'>src/switch_debouncer.c</div></td>
|
||||||
|
<td><div class='id'>tests/unit/test_actuator_driver.c</div><div class='id'>tests/unit/test_apply_controller.c</div><div class='id'>tests/unit/test_switch_debouncer.c</div></td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td class='missing'>—</td>
|
||||||
|
<td><div><span class='id'>SYS-008</span> <span class='asil' style='background:#888'>QM</span></div><div class='cnt'>Service-Modus fuer Werkstatt</div></td>
|
||||||
|
<td><div><span class='id'>SA-001</span> <span class='asil' style='background:#d62728'>D</span></div><div class='cnt'>EPB ECU</div><div><span class='id'>SA-004</span> <span class='asil' style='background:#888'>QM</span></div><div class='cnt'>HMI (Schalter, LED, Display)</div></td>
|
||||||
|
<td><div><span class='id'>SWE-016</span> <span class='asil' style='background:#888'>QM</span></div><div class='cnt'>UDS RoutineControl 0x31 fuer Service-Release</div><div><span class='id'>SWE-017</span> <span class='asil' style='background:#888'>QM</span></div><div class='cnt'>Service-Mode-Indikator</div></td>
|
||||||
|
<td><div><span class='id'>SWA-009</span> <span class='asil' style='background:#888'>QM</span></div><div class='cnt'>Service Mode</div></td>
|
||||||
|
<td class='cnt'>—</td>
|
||||||
|
<td class='cnt'>—</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td class='missing'>—</td>
|
||||||
|
<td><div><span class='id'>SYS-009</span> <span class='asil' style='background:#888'>QM</span></div><div class='cnt'>UDS-Diagnose</div></td>
|
||||||
|
<td><div><span class='id'>SA-001</span> <span class='asil' style='background:#d62728'>D</span></div><div class='cnt'>EPB ECU</div><div><span class='id'>SA-005</span> <span class='asil' style='background:#888'>QM</span></div><div class='cnt'>CAN-Bus</div></td>
|
||||||
|
<td><div><span class='id'>SWE-018</span> <span class='asil' style='background:#888'>QM</span></div><div class='cnt'>UDS Service 0x19 ReadDTC</div><div><span class='id'>SWE-019</span> <span class='asil' style='background:#888'>QM</span></div><div class='cnt'>UDS Service 0x22 ReadDataByIdentifier</div></td>
|
||||||
|
<td><div><span class='id'>SWA-008</span> <span class='asil' style='background:#888'>QM</span></div><div class='cnt'>Diagnostic Manager</div><div><span class='id'>SWA-010</span> <span class='asil' style='background:#888'>QM</span></div><div class='cnt'>Logger</div></td>
|
||||||
|
<td class='cnt'>—</td>
|
||||||
|
<td class='cnt'>—</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td class='missing'>—</td>
|
||||||
|
<td><div><span class='id'>SYS-010</span> <span class='asil' style='background:#888'>QM</span></div><div class='cnt'>HMI-Statusanzeige</div></td>
|
||||||
|
<td><div><span class='id'>SA-001</span> <span class='asil' style='background:#d62728'>D</span></div><div class='cnt'>EPB ECU</div><div><span class='id'>SA-004</span> <span class='asil' style='background:#888'>QM</span></div><div class='cnt'>HMI (Schalter, LED, Display)</div><div><span class='id'>SA-005</span> <span class='asil' style='background:#888'>QM</span></div><div class='cnt'>CAN-Bus</div></td>
|
||||||
|
<td><div><span class='id'>SWE-020</span> <span class='asil' style='background:#888'>QM</span></div><div class='cnt'>LED-Steuerung</div><div><span class='id'>SWE-021</span> <span class='asil' style='background:#888'>QM</span></div><div class='cnt'>CAN-Status-Frame</div></td>
|
||||||
|
<td><div><span class='id'>SWA-007</span> <span class='asil' style='background:#888'>QM</span></div><div class='cnt'>Display Manager</div></td>
|
||||||
|
<td class='cnt'>—</td>
|
||||||
|
<td class='cnt'>—</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
<h2>Code → Architektur</h2>
|
||||||
|
<table><tr><th>Datei</th><th>@arch</th><th>@reqs</th></tr>
|
||||||
|
<tr><td class='id'>src/safety_manager.c</td><td>SWA-001</td><td class='cnt'>SWE-007 SWE-008 SWE-009 SWE-010 SWE-011 SWE-012</td></tr>
|
||||||
|
<tr><td class='id'>src/apply_controller.c</td><td>SWA-002</td><td class='cnt'>SWE-001 SWE-002 SWE-003 SWE-004</td></tr>
|
||||||
|
<tr><td class='id'>src/actuator_driver.c</td><td>SWA-003</td><td class='cnt'>SWE-006 SWE-013 SWE-014 SWE-015</td></tr>
|
||||||
|
<tr><td class='id'>src/switch_debouncer.c</td><td>SWA-006</td><td class='cnt'>SWE-025</td></tr>
|
||||||
|
</table>
|
||||||
|
<h2>Test → Anforderungen</h2>
|
||||||
|
<table><tr><th>Test-Datei</th><th>Decklt SWA</th><th>@reqs</th></tr>
|
||||||
|
<tr><td class='id'>tests/unit/test_safety_manager.c</td><td>SWA-001</td><td class='cnt'>SWE-007 SWE-008 SWE-009 SWE-010 SWE-011 SWE-012</td></tr>
|
||||||
|
<tr><td class='id'>tests/unit/test_apply_controller.c</td><td>SWA-002</td><td class='cnt'>SWE-001 SWE-002 SWE-003 SWE-004 SWE-005</td></tr>
|
||||||
|
<tr><td class='id'>tests/unit/test_actuator_driver.c</td><td>SWA-003</td><td class='cnt'>SWE-006 SWE-013 SWE-014 SWE-015</td></tr>
|
||||||
|
<tr><td class='id'>tests/unit/test_switch_debouncer.c</td><td>SWA-006</td><td class='cnt'>SWE-025</td></tr>
|
||||||
|
</table>
|
||||||
|
</body></html>
|
||||||
+312
-115
@@ -1,5 +1,9 @@
|
|||||||
[
|
[
|
||||||
{
|
{
|
||||||
|
"sg": {
|
||||||
|
"id": "SG-001",
|
||||||
|
"asil": "D"
|
||||||
|
},
|
||||||
"sys": {
|
"sys": {
|
||||||
"id": "SYS-001",
|
"id": "SYS-001",
|
||||||
"asil": "D",
|
"asil": "D",
|
||||||
@@ -38,9 +42,58 @@
|
|||||||
"id": "SWA-004",
|
"id": "SWA-004",
|
||||||
"asil": "B"
|
"asil": "B"
|
||||||
}
|
}
|
||||||
|
],
|
||||||
|
"code": [
|
||||||
|
"src/apply_controller.c"
|
||||||
|
],
|
||||||
|
"tests": [
|
||||||
|
"tests/unit/test_apply_controller.c"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
"sg": {
|
||||||
|
"id": "SG-001",
|
||||||
|
"asil": "D"
|
||||||
|
},
|
||||||
|
"sys": {
|
||||||
|
"id": "SYS-004",
|
||||||
|
"asil": "D",
|
||||||
|
"title": "Auto-Apply bei Motor-Aus"
|
||||||
|
},
|
||||||
|
"sa": [
|
||||||
|
{
|
||||||
|
"id": "SA-001",
|
||||||
|
"asil": "D"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"swe": [
|
||||||
|
{
|
||||||
|
"id": "SWE-007",
|
||||||
|
"asil": "D"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "SWE-008",
|
||||||
|
"asil": "D"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"swa": [
|
||||||
|
{
|
||||||
|
"id": "SWA-001",
|
||||||
|
"asil": "D"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"code": [
|
||||||
|
"src/safety_manager.c"
|
||||||
|
],
|
||||||
|
"tests": [
|
||||||
|
"tests/unit/test_safety_manager.c"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"sg": {
|
||||||
|
"id": "SG-002",
|
||||||
|
"asil": "D"
|
||||||
|
},
|
||||||
"sys": {
|
"sys": {
|
||||||
"id": "SYS-002",
|
"id": "SYS-002",
|
||||||
"asil": "D",
|
"asil": "D",
|
||||||
@@ -87,83 +140,21 @@
|
|||||||
"id": "SWA-006",
|
"id": "SWA-006",
|
||||||
"asil": "QM"
|
"asil": "QM"
|
||||||
}
|
}
|
||||||
|
],
|
||||||
|
"code": [
|
||||||
|
"src/apply_controller.c",
|
||||||
|
"src/switch_debouncer.c"
|
||||||
|
],
|
||||||
|
"tests": [
|
||||||
|
"tests/unit/test_apply_controller.c",
|
||||||
|
"tests/unit/test_switch_debouncer.c"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"sys": {
|
"sg": {
|
||||||
"id": "SYS-003",
|
"id": "SG-002",
|
||||||
"asil": "B",
|
|
||||||
"title": "Release auf Fahrer-Anforderung"
|
|
||||||
},
|
|
||||||
"sa": [
|
|
||||||
{
|
|
||||||
"id": "SA-001",
|
|
||||||
"asil": "D"
|
"asil": "D"
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"id": "SA-002",
|
|
||||||
"asil": "D"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"swe": [
|
|
||||||
{
|
|
||||||
"id": "SWE-005",
|
|
||||||
"asil": "B"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": "SWE-006",
|
|
||||||
"asil": "B"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": "SWE-025",
|
|
||||||
"asil": "QM"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"swa": [
|
|
||||||
{
|
|
||||||
"id": "SWA-002",
|
|
||||||
"asil": "D"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": "SWA-003",
|
|
||||||
"asil": "B"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": "SWA-006",
|
|
||||||
"asil": "QM"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"sys": {
|
|
||||||
"id": "SYS-004",
|
|
||||||
"asil": "D",
|
|
||||||
"title": "Auto-Apply bei Motor-Aus"
|
|
||||||
},
|
|
||||||
"sa": [
|
|
||||||
{
|
|
||||||
"id": "SA-001",
|
|
||||||
"asil": "D"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"swe": [
|
|
||||||
{
|
|
||||||
"id": "SWE-007",
|
|
||||||
"asil": "D"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": "SWE-008",
|
|
||||||
"asil": "D"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"swa": [
|
|
||||||
{
|
|
||||||
"id": "SWA-001",
|
|
||||||
"asil": "D"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"sys": {
|
"sys": {
|
||||||
"id": "SYS-005",
|
"id": "SYS-005",
|
||||||
"asil": "D",
|
"asil": "D",
|
||||||
@@ -202,50 +193,19 @@
|
|||||||
"id": "SWA-005",
|
"id": "SWA-005",
|
||||||
"asil": "B"
|
"asil": "B"
|
||||||
}
|
}
|
||||||
|
],
|
||||||
|
"code": [
|
||||||
|
"src/safety_manager.c"
|
||||||
|
],
|
||||||
|
"tests": [
|
||||||
|
"tests/unit/test_safety_manager.c"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"sys": {
|
"sg": {
|
||||||
"id": "SYS-006",
|
"id": "SG-003",
|
||||||
"asil": "B",
|
"asil": "A"
|
||||||
"title": "Auto-Release beim Anfahren (Drive-Away-Assist)"
|
|
||||||
},
|
},
|
||||||
"sa": [
|
|
||||||
{
|
|
||||||
"id": "SA-001",
|
|
||||||
"asil": "D"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": "SA-003",
|
|
||||||
"asil": "B"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"swe": [
|
|
||||||
{
|
|
||||||
"id": "SWE-011",
|
|
||||||
"asil": "B"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": "SWE-012",
|
|
||||||
"asil": "B"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": "SWE-022",
|
|
||||||
"asil": "B"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"swa": [
|
|
||||||
{
|
|
||||||
"id": "SWA-001",
|
|
||||||
"asil": "D"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": "SWA-004",
|
|
||||||
"asil": "B"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"sys": {
|
"sys": {
|
||||||
"id": "SYS-007",
|
"id": "SYS-007",
|
||||||
"asil": "B",
|
"asil": "B",
|
||||||
@@ -292,9 +252,238 @@
|
|||||||
"id": "SWA-004",
|
"id": "SWA-004",
|
||||||
"asil": "B"
|
"asil": "B"
|
||||||
}
|
}
|
||||||
|
],
|
||||||
|
"code": [
|
||||||
|
"src/actuator_driver.c"
|
||||||
|
],
|
||||||
|
"tests": [
|
||||||
|
"tests/unit/test_actuator_driver.c"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
"sg": {
|
||||||
|
"id": "SG-004",
|
||||||
|
"asil": "C"
|
||||||
|
},
|
||||||
|
"sys": {
|
||||||
|
"id": "SYS-005",
|
||||||
|
"asil": "D",
|
||||||
|
"title": "Hill-Hold am Berg"
|
||||||
|
},
|
||||||
|
"sa": [
|
||||||
|
{
|
||||||
|
"id": "SA-001",
|
||||||
|
"asil": "D"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "SA-003",
|
||||||
|
"asil": "B"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"swe": [
|
||||||
|
{
|
||||||
|
"id": "SWE-009",
|
||||||
|
"asil": "D"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "SWE-010",
|
||||||
|
"asil": "D"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "SWE-024",
|
||||||
|
"asil": "B"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"swa": [
|
||||||
|
{
|
||||||
|
"id": "SWA-001",
|
||||||
|
"asil": "D"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "SWA-005",
|
||||||
|
"asil": "B"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"code": [
|
||||||
|
"src/safety_manager.c"
|
||||||
|
],
|
||||||
|
"tests": [
|
||||||
|
"tests/unit/test_safety_manager.c"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"sg": {
|
||||||
|
"id": "SG-004",
|
||||||
|
"asil": "C"
|
||||||
|
},
|
||||||
|
"sys": {
|
||||||
|
"id": "SYS-006",
|
||||||
|
"asil": "B",
|
||||||
|
"title": "Auto-Release beim Anfahren (Drive-Away-Assist)"
|
||||||
|
},
|
||||||
|
"sa": [
|
||||||
|
{
|
||||||
|
"id": "SA-001",
|
||||||
|
"asil": "D"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "SA-003",
|
||||||
|
"asil": "B"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"swe": [
|
||||||
|
{
|
||||||
|
"id": "SWE-011",
|
||||||
|
"asil": "B"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "SWE-012",
|
||||||
|
"asil": "B"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "SWE-022",
|
||||||
|
"asil": "B"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"swa": [
|
||||||
|
{
|
||||||
|
"id": "SWA-001",
|
||||||
|
"asil": "D"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "SWA-004",
|
||||||
|
"asil": "B"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"code": [
|
||||||
|
"src/safety_manager.c"
|
||||||
|
],
|
||||||
|
"tests": [
|
||||||
|
"tests/unit/test_safety_manager.c"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"sg": {
|
||||||
|
"id": "SG-005",
|
||||||
|
"asil": "B"
|
||||||
|
},
|
||||||
|
"sys": {
|
||||||
|
"id": "SYS-002",
|
||||||
|
"asil": "D",
|
||||||
|
"title": "Apply auf Fahrer-Anforderung"
|
||||||
|
},
|
||||||
|
"sa": [
|
||||||
|
{
|
||||||
|
"id": "SA-001",
|
||||||
|
"asil": "D"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "SA-002",
|
||||||
|
"asil": "D"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"swe": [
|
||||||
|
{
|
||||||
|
"id": "SWE-003",
|
||||||
|
"asil": "D"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "SWE-004",
|
||||||
|
"asil": "D"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "SWE-022",
|
||||||
|
"asil": "B"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "SWE-025",
|
||||||
|
"asil": "QM"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"swa": [
|
||||||
|
{
|
||||||
|
"id": "SWA-002",
|
||||||
|
"asil": "D"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "SWA-004",
|
||||||
|
"asil": "B"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "SWA-006",
|
||||||
|
"asil": "QM"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"code": [
|
||||||
|
"src/apply_controller.c",
|
||||||
|
"src/switch_debouncer.c"
|
||||||
|
],
|
||||||
|
"tests": [
|
||||||
|
"tests/unit/test_apply_controller.c",
|
||||||
|
"tests/unit/test_switch_debouncer.c"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"sg": {
|
||||||
|
"id": "SG-005",
|
||||||
|
"asil": "B"
|
||||||
|
},
|
||||||
|
"sys": {
|
||||||
|
"id": "SYS-003",
|
||||||
|
"asil": "B",
|
||||||
|
"title": "Release auf Fahrer-Anforderung"
|
||||||
|
},
|
||||||
|
"sa": [
|
||||||
|
{
|
||||||
|
"id": "SA-001",
|
||||||
|
"asil": "D"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "SA-002",
|
||||||
|
"asil": "D"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"swe": [
|
||||||
|
{
|
||||||
|
"id": "SWE-005",
|
||||||
|
"asil": "B"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "SWE-006",
|
||||||
|
"asil": "B"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "SWE-025",
|
||||||
|
"asil": "QM"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"swa": [
|
||||||
|
{
|
||||||
|
"id": "SWA-002",
|
||||||
|
"asil": "D"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "SWA-003",
|
||||||
|
"asil": "B"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "SWA-006",
|
||||||
|
"asil": "QM"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"code": [
|
||||||
|
"src/apply_controller.c",
|
||||||
|
"src/actuator_driver.c",
|
||||||
|
"src/switch_debouncer.c"
|
||||||
|
],
|
||||||
|
"tests": [
|
||||||
|
"tests/unit/test_actuator_driver.c",
|
||||||
|
"tests/unit/test_apply_controller.c",
|
||||||
|
"tests/unit/test_switch_debouncer.c"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"sg": null,
|
||||||
"sys": {
|
"sys": {
|
||||||
"id": "SYS-008",
|
"id": "SYS-008",
|
||||||
"asil": "QM",
|
"asil": "QM",
|
||||||
@@ -325,9 +514,12 @@
|
|||||||
"id": "SWA-009",
|
"id": "SWA-009",
|
||||||
"asil": "QM"
|
"asil": "QM"
|
||||||
}
|
}
|
||||||
]
|
],
|
||||||
|
"code": [],
|
||||||
|
"tests": []
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
"sg": null,
|
||||||
"sys": {
|
"sys": {
|
||||||
"id": "SYS-009",
|
"id": "SYS-009",
|
||||||
"asil": "QM",
|
"asil": "QM",
|
||||||
@@ -362,9 +554,12 @@
|
|||||||
"id": "SWA-010",
|
"id": "SWA-010",
|
||||||
"asil": "QM"
|
"asil": "QM"
|
||||||
}
|
}
|
||||||
]
|
],
|
||||||
|
"code": [],
|
||||||
|
"tests": []
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
"sg": null,
|
||||||
"sys": {
|
"sys": {
|
||||||
"id": "SYS-010",
|
"id": "SYS-010",
|
||||||
"asil": "QM",
|
"asil": "QM",
|
||||||
@@ -399,6 +594,8 @@
|
|||||||
"id": "SWA-007",
|
"id": "SWA-007",
|
||||||
"asil": "QM"
|
"asil": "QM"
|
||||||
}
|
}
|
||||||
]
|
],
|
||||||
|
"code": [],
|
||||||
|
"tests": []
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
+2
-1
@@ -5,7 +5,8 @@ header: 'Halten der Parkbremse im Stillstand'
|
|||||||
level: 1.1
|
level: 1.1
|
||||||
normative: true
|
normative: true
|
||||||
reviewed: null
|
reviewed: null
|
||||||
links: []
|
links:
|
||||||
|
- SG-001
|
||||||
asil: D
|
asil: D
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|||||||
+3
-1
@@ -5,7 +5,9 @@ header: 'Apply auf Fahrer-Anforderung'
|
|||||||
level: 1.2
|
level: 1.2
|
||||||
normative: true
|
normative: true
|
||||||
reviewed: null
|
reviewed: null
|
||||||
links: []
|
links:
|
||||||
|
- SG-002
|
||||||
|
- SG-005
|
||||||
asil: D
|
asil: D
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|||||||
+2
-1
@@ -5,7 +5,8 @@ header: 'Release auf Fahrer-Anforderung'
|
|||||||
level: 1.3
|
level: 1.3
|
||||||
normative: true
|
normative: true
|
||||||
reviewed: null
|
reviewed: null
|
||||||
links: []
|
links:
|
||||||
|
- SG-005
|
||||||
asil: B
|
asil: B
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|||||||
+2
-1
@@ -5,7 +5,8 @@ header: 'Auto-Apply bei Motor-Aus'
|
|||||||
level: 1.4
|
level: 1.4
|
||||||
normative: true
|
normative: true
|
||||||
reviewed: null
|
reviewed: null
|
||||||
links: []
|
links:
|
||||||
|
- SG-001
|
||||||
asil: D
|
asil: D
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|||||||
+3
-1
@@ -5,7 +5,9 @@ header: 'Hill-Hold am Berg'
|
|||||||
level: 1.5
|
level: 1.5
|
||||||
normative: true
|
normative: true
|
||||||
reviewed: null
|
reviewed: null
|
||||||
links: []
|
links:
|
||||||
|
- SG-002
|
||||||
|
- SG-004
|
||||||
asil: D
|
asil: D
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|||||||
+2
-1
@@ -5,7 +5,8 @@ header: 'Auto-Release beim Anfahren (Drive-Away-Assist)'
|
|||||||
level: 1.6
|
level: 1.6
|
||||||
normative: true
|
normative: true
|
||||||
reviewed: null
|
reviewed: null
|
||||||
links: []
|
links:
|
||||||
|
- SG-004
|
||||||
asil: B
|
asil: B
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|||||||
+2
-1
@@ -5,7 +5,8 @@ header: 'Aktor-Stromueberwachung'
|
|||||||
level: 1.7
|
level: 1.7
|
||||||
normative: true
|
normative: true
|
||||||
reviewed: null
|
reviewed: null
|
||||||
links: []
|
links:
|
||||||
|
- SG-003
|
||||||
asil: B
|
asil: B
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,17 @@
|
|||||||
|
---
|
||||||
|
active: true
|
||||||
|
derived: false
|
||||||
|
header: 'Kein ungewolltes Loesen der Parkbremse im Stillstand'
|
||||||
|
level: 1.1
|
||||||
|
normative: true
|
||||||
|
reviewed: null
|
||||||
|
links: []
|
||||||
|
asil: D
|
||||||
|
---
|
||||||
|
|
||||||
|
# SG-001: Kein ungewolltes Loesen der Parkbremse im Stillstand
|
||||||
|
|
||||||
|
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).
|
||||||
|
|
||||||
|
**FTTI:** 5 s (H-01) / 30 s (H-04).
|
||||||
|
**Safe State:** APPLIED (Klemmkraft halten).
|
||||||
@@ -0,0 +1,17 @@
|
|||||||
|
---
|
||||||
|
active: true
|
||||||
|
derived: false
|
||||||
|
header: 'Kein ungewolltes Festklemmen waehrend der Fahrt'
|
||||||
|
level: 1.2
|
||||||
|
normative: true
|
||||||
|
reviewed: null
|
||||||
|
links: []
|
||||||
|
asil: D
|
||||||
|
---
|
||||||
|
|
||||||
|
# SG-002: Kein ungewolltes Festklemmen waehrend der Fahrt
|
||||||
|
|
||||||
|
Die EPB darf nicht waehrend der Fahrt ungewollt festklemmen. Abgeleitet aus HARA-Hazard H-02.
|
||||||
|
|
||||||
|
**FTTI:** 100 ms.
|
||||||
|
**Safe State:** Aktor stop (kein Apply einleiten).
|
||||||
@@ -0,0 +1,17 @@
|
|||||||
|
---
|
||||||
|
active: true
|
||||||
|
derived: false
|
||||||
|
header: 'Schutz gegen Aktor-Ueberlast'
|
||||||
|
level: 1.3
|
||||||
|
normative: true
|
||||||
|
reviewed: null
|
||||||
|
links: []
|
||||||
|
asil: A
|
||||||
|
---
|
||||||
|
|
||||||
|
# SG-003: Schutz gegen Aktor-Ueberlast
|
||||||
|
|
||||||
|
Das System muss Aktor-Motorschaeden durch Ueberstrom verhindern. Abgeleitet aus HARA-Hazard H-05.
|
||||||
|
|
||||||
|
**FTTI:** 100 ms.
|
||||||
|
**Safe State:** Aktor abschalten, DTC setzen.
|
||||||
@@ -0,0 +1,17 @@
|
|||||||
|
---
|
||||||
|
active: true
|
||||||
|
derived: false
|
||||||
|
header: 'Zuverlaessige Hill-Hold-Uebergabe'
|
||||||
|
level: 1.4
|
||||||
|
normative: true
|
||||||
|
reviewed: null
|
||||||
|
links: []
|
||||||
|
asil: C
|
||||||
|
---
|
||||||
|
|
||||||
|
# SG-004: Zuverlaessige Hill-Hold-Uebergabe
|
||||||
|
|
||||||
|
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.
|
||||||
|
|
||||||
|
**FTTI:** 500 ms.
|
||||||
|
**Safe State:** Apply einleiten.
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
---
|
||||||
|
active: true
|
||||||
|
derived: false
|
||||||
|
header: 'Reaktion auf Fahreranforderung'
|
||||||
|
level: 1.5
|
||||||
|
normative: true
|
||||||
|
reviewed: null
|
||||||
|
links: []
|
||||||
|
asil: B
|
||||||
|
---
|
||||||
|
|
||||||
|
# SG-005: Reaktion auf Fahreranforderung
|
||||||
|
|
||||||
|
Das System muss in spezifizierter Zeit auf Fahrer-Apply- und Release-Anforderungen reagieren. Abgeleitet aus HARA-Hazards H-03 und H-07.
|
||||||
|
|
||||||
|
**Reaktionszeit:** Apply <= 800 ms, Release <= 1500 ms.
|
||||||
+50
-4
@@ -1,12 +1,13 @@
|
|||||||
/**
|
/**
|
||||||
* @file safety_manager.c
|
* @file safety_manager.c
|
||||||
* @brief Safety Manager — Hill-Hold + Auto-Apply Logik.
|
* @brief Safety Manager — Hill-Hold, Auto-Apply, Drive-Away-Assist.
|
||||||
*
|
*
|
||||||
* @arch SWA-001
|
* @arch SWA-001
|
||||||
* @reqs SWE-007 SWE-008 SWE-009 SWE-010
|
* @reqs SWE-007 SWE-008 SWE-009 SWE-010 SWE-011 SWE-012
|
||||||
*
|
*
|
||||||
* ASIL: D. Diese Komponente entscheidet, wann der Apply Controller eine
|
* ASIL: D. Diese Komponente entscheidet, wann der Apply Controller eine
|
||||||
* Apply-Anforderung erhaelt (Hill-Hold-Uebergabe, Auto-Apply bei Motor-Aus).
|
* Apply- oder Release-Anforderung erhaelt (Hill-Hold-Uebergabe, Auto-Apply
|
||||||
|
* bei Motor-Aus, Drive-Away-Assist).
|
||||||
* Aenderungen erfordern Technical Review mit 2 Approvals.
|
* Aenderungen erfordern Technical Review mit 2 Approvals.
|
||||||
*/
|
*/
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
@@ -17,6 +18,7 @@ typedef struct {
|
|||||||
SafetyState state;
|
SafetyState state;
|
||||||
uint16_t ticks_in_state; /* 50ms-Ticks im aktuellen Zustand */
|
uint16_t ticks_in_state; /* 50ms-Ticks im aktuellen Zustand */
|
||||||
bool apply_requested;
|
bool apply_requested;
|
||||||
|
bool release_requested;
|
||||||
} SafetyCtx;
|
} SafetyCtx;
|
||||||
|
|
||||||
static SafetyCtx s_ctx;
|
static SafetyCtx s_ctx;
|
||||||
@@ -42,11 +44,30 @@ static bool grade_steep(const SafetyInputs* in)
|
|||||||
return g > SAFETY_HILLHOLD_GRADE_PCT;
|
return g > SAFETY_HILLHOLD_GRADE_PCT;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @reqs SWE-011 (Anfahrabsicht erkennen)
|
||||||
|
*/
|
||||||
|
static bool drive_intent(const SafetyInputs* in)
|
||||||
|
{
|
||||||
|
return (in->gas_pedal_percent > SAFETY_DRIVE_INTENT_GAS_PCT)
|
||||||
|
&& in->gear_in_drive
|
||||||
|
&& in->engine_running;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @reqs SWE-012 (Sicherheits-Check vor Auto-Release)
|
||||||
|
*/
|
||||||
|
static bool drive_away_safety_ok(const SafetyInputs* in)
|
||||||
|
{
|
||||||
|
return in->door_closed && in->seatbelt_fastened;
|
||||||
|
}
|
||||||
|
|
||||||
EpbStatus safety_mgr_init(void)
|
EpbStatus safety_mgr_init(void)
|
||||||
{
|
{
|
||||||
s_ctx.state = SAFETY_IDLE;
|
s_ctx.state = SAFETY_IDLE;
|
||||||
s_ctx.ticks_in_state = 0U;
|
s_ctx.ticks_in_state = 0U;
|
||||||
s_ctx.apply_requested = false;
|
s_ctx.apply_requested = false;
|
||||||
|
s_ctx.release_requested = false;
|
||||||
return EPB_OK;
|
return EPB_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -60,8 +81,9 @@ void safety_mgr_step_50ms(const SafetyInputs* in)
|
|||||||
++s_ctx.ticks_in_state;
|
++s_ctx.ticks_in_state;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Default: no apply request unless explicitly set below. */
|
/* Default: no apply/release request unless explicitly set below. */
|
||||||
s_ctx.apply_requested = false;
|
s_ctx.apply_requested = false;
|
||||||
|
s_ctx.release_requested = false;
|
||||||
|
|
||||||
switch (s_ctx.state) {
|
switch (s_ctx.state) {
|
||||||
case SAFETY_IDLE:
|
case SAFETY_IDLE:
|
||||||
@@ -75,6 +97,13 @@ void safety_mgr_step_50ms(const SafetyInputs* in)
|
|||||||
&& in->current_state != EPB_STATE_APPLIED
|
&& in->current_state != EPB_STATE_APPLIED
|
||||||
&& in->current_state != EPB_STATE_APPLYING) {
|
&& in->current_state != EPB_STATE_APPLYING) {
|
||||||
enter(SAFETY_AUTO_APPLY_ARMED);
|
enter(SAFETY_AUTO_APPLY_ARMED);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
/* @reqs SWE-011 + SWE-012: Drive-Away-Assist */
|
||||||
|
if (in->current_state == EPB_STATE_APPLIED
|
||||||
|
&& drive_intent(in) && drive_away_safety_ok(in)) {
|
||||||
|
s_ctx.release_requested = true;
|
||||||
|
enter(SAFETY_DRIVE_AWAY);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@@ -122,6 +151,18 @@ void safety_mgr_step_50ms(const SafetyInputs* in)
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case SAFETY_DRIVE_AWAY:
|
||||||
|
/* Beendet, wenn die Bremse geloest wurde oder Vorbedingungen nicht mehr ok. */
|
||||||
|
if (in->current_state == EPB_STATE_RELEASED
|
||||||
|
|| in->current_state == EPB_STATE_RELEASING) {
|
||||||
|
enter(SAFETY_IDLE);
|
||||||
|
} else if (!drive_intent(in) || !drive_away_safety_ok(in)) {
|
||||||
|
enter(SAFETY_IDLE);
|
||||||
|
} else {
|
||||||
|
s_ctx.release_requested = true;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
enter(SAFETY_IDLE);
|
enter(SAFETY_IDLE);
|
||||||
break;
|
break;
|
||||||
@@ -133,6 +174,11 @@ bool safety_mgr_apply_requested(void)
|
|||||||
return s_ctx.apply_requested;
|
return s_ctx.apply_requested;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool safety_mgr_release_requested(void)
|
||||||
|
{
|
||||||
|
return s_ctx.release_requested;
|
||||||
|
}
|
||||||
|
|
||||||
SafetyState safety_mgr_get_state(void)
|
SafetyState safety_mgr_get_state(void)
|
||||||
{
|
{
|
||||||
return s_ctx.state;
|
return s_ctx.state;
|
||||||
|
|||||||
+15
-4
@@ -1,20 +1,23 @@
|
|||||||
/**
|
/**
|
||||||
* @file safety_manager.h
|
* @file safety_manager.h
|
||||||
* @brief Safety Manager — Hill-Hold + Auto-Apply Logik.
|
* @brief Safety Manager — Hill-Hold, Auto-Apply, Drive-Away-Assist.
|
||||||
*
|
*
|
||||||
* @arch SWA-001
|
* @arch SWA-001
|
||||||
* @reqs SWE-007 SWE-008 SWE-009 SWE-010
|
* @reqs SWE-007 SWE-008 SWE-009 SWE-010 SWE-011 SWE-012
|
||||||
*
|
*
|
||||||
* ASIL: D.
|
* ASIL: D.
|
||||||
*
|
*
|
||||||
* State Machine:
|
* State Machine:
|
||||||
* IDLE --(engine_off & v<0.5)--> AUTO_APPLY_ARMED
|
* IDLE --(engine_off & v<0.5 & !APPLIED)--> AUTO_APPLY_ARMED
|
||||||
* AUTO_APPLY_ARMED --(40 * 50ms = 2s)--> AUTO_APPLY_TRIGGERED
|
* AUTO_APPLY_ARMED --(40 * 50ms = 2s)--> AUTO_APPLY_TRIGGERED
|
||||||
* AUTO_APPLY_TRIGGERED --(state==APPLIED)--> IDLE
|
* AUTO_APPLY_TRIGGERED --(state==APPLIED)--> IDLE
|
||||||
*
|
*
|
||||||
* IDLE --(grade>5% & v<0.5 & brake)--> HILL_HOLD_ARMED
|
* IDLE --(grade>5% & v<0.5 & brake)--> HILL_HOLD_ARMED
|
||||||
* HILL_HOLD_ARMED --(!brake)--> HILL_HOLD_ACTIVE
|
* HILL_HOLD_ARMED --(!brake)--> HILL_HOLD_ACTIVE
|
||||||
* HILL_HOLD_ACTIVE --(v>2 km/h | state==APPLIED)--> IDLE
|
* HILL_HOLD_ACTIVE --(v>2 km/h | state==APPLIED)--> IDLE
|
||||||
|
*
|
||||||
|
* IDLE --(APPLIED & gas>10% & gear_drive & engine & door & belt)--> DRIVE_AWAY
|
||||||
|
* DRIVE_AWAY --(state==RELEASED|RELEASING)--> IDLE
|
||||||
*/
|
*/
|
||||||
#ifndef SAFETY_MANAGER_H
|
#ifndef SAFETY_MANAGER_H
|
||||||
#define SAFETY_MANAGER_H
|
#define SAFETY_MANAGER_H
|
||||||
@@ -26,7 +29,8 @@ typedef enum {
|
|||||||
SAFETY_HILL_HOLD_ARMED = 1,
|
SAFETY_HILL_HOLD_ARMED = 1,
|
||||||
SAFETY_HILL_HOLD_ACTIVE = 2,
|
SAFETY_HILL_HOLD_ACTIVE = 2,
|
||||||
SAFETY_AUTO_APPLY_ARMED = 3,
|
SAFETY_AUTO_APPLY_ARMED = 3,
|
||||||
SAFETY_AUTO_APPLY_TRIGGERED = 4
|
SAFETY_AUTO_APPLY_TRIGGERED = 4,
|
||||||
|
SAFETY_DRIVE_AWAY = 5
|
||||||
} SafetyState;
|
} SafetyState;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
@@ -35,6 +39,11 @@ typedef struct {
|
|||||||
float vehicle_speed_kmh;
|
float vehicle_speed_kmh;
|
||||||
float grade_percent;
|
float grade_percent;
|
||||||
EpbState current_state; /* aus Apply Controller */
|
EpbState current_state; /* aus Apply Controller */
|
||||||
|
/* Drive-Away-Assist Inputs (SWE-011, SWE-012) */
|
||||||
|
float gas_pedal_percent; /* 0..100 */
|
||||||
|
bool gear_in_drive; /* Vorwaerts oder Rueckwaerts */
|
||||||
|
bool door_closed; /* Fahrertuer */
|
||||||
|
bool seatbelt_fastened; /* Fahrer-Gurt */
|
||||||
} SafetyInputs;
|
} SafetyInputs;
|
||||||
|
|
||||||
/* Schwellwerte als Konstanten, damit Tests darauf zugreifen koennen. */
|
/* Schwellwerte als Konstanten, damit Tests darauf zugreifen koennen. */
|
||||||
@@ -42,10 +51,12 @@ typedef struct {
|
|||||||
#define SAFETY_STANDSTILL_KMH 0.5f
|
#define SAFETY_STANDSTILL_KMH 0.5f
|
||||||
#define SAFETY_RELEASE_KMH 2.0f
|
#define SAFETY_RELEASE_KMH 2.0f
|
||||||
#define SAFETY_HILLHOLD_GRADE_PCT 5.0f
|
#define SAFETY_HILLHOLD_GRADE_PCT 5.0f
|
||||||
|
#define SAFETY_DRIVE_INTENT_GAS_PCT 10.0f /* Gaspedal > 10% = Anfahrabsicht */
|
||||||
|
|
||||||
EpbStatus safety_mgr_init(void);
|
EpbStatus safety_mgr_init(void);
|
||||||
void safety_mgr_step_50ms(const SafetyInputs* in);
|
void safety_mgr_step_50ms(const SafetyInputs* in);
|
||||||
bool safety_mgr_apply_requested(void);
|
bool safety_mgr_apply_requested(void);
|
||||||
|
bool safety_mgr_release_requested(void); /* Drive-Away-Assist */
|
||||||
SafetyState safety_mgr_get_state(void);
|
SafetyState safety_mgr_get_state(void);
|
||||||
|
|
||||||
#endif /* SAFETY_MANAGER_H */
|
#endif /* SAFETY_MANAGER_H */
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
* @file test_apply_controller.c
|
* @file test_apply_controller.c
|
||||||
* @brief Unit-Tests fuer den Apply-Controller (ASIL-D Kern).
|
* @brief Unit-Tests fuer den Apply-Controller (ASIL-D Kern).
|
||||||
*
|
*
|
||||||
* @reqs SWE-001 SWE-002 SWE-003 SWE-004
|
* @reqs SWE-001 SWE-002 SWE-003 SWE-004 SWE-005
|
||||||
* @arch SWA-002
|
* @arch SWA-002
|
||||||
*/
|
*/
|
||||||
#include "../unit_test_framework.h"
|
#include "../unit_test_framework.h"
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
* @file test_safety_manager.c
|
* @file test_safety_manager.c
|
||||||
* @brief Unit-Tests fuer den Safety Manager (ASIL-D).
|
* @brief Unit-Tests fuer den Safety Manager (ASIL-D).
|
||||||
*
|
*
|
||||||
* @reqs SWE-007 SWE-008 SWE-009 SWE-010
|
* @reqs SWE-007 SWE-008 SWE-009 SWE-010 SWE-011 SWE-012
|
||||||
* @arch SWA-001
|
* @arch SWA-001
|
||||||
*/
|
*/
|
||||||
#include "../unit_test_framework.h"
|
#include "../unit_test_framework.h"
|
||||||
@@ -207,6 +207,90 @@ static void test_hillhold_armed_to_idle_if_grade_drops(void)
|
|||||||
|
|
||||||
/* ---- Mutually exclusive: nicht in beiden Modi gleichzeitig ---- */
|
/* ---- Mutually exclusive: nicht in beiden Modi gleichzeitig ---- */
|
||||||
|
|
||||||
|
/* ---- Drive-Away-Assist (SWE-011 + SWE-012) ---- */
|
||||||
|
|
||||||
|
static SafetyInputs make_applied_at_rest(void)
|
||||||
|
{
|
||||||
|
SafetyInputs in = {0};
|
||||||
|
in.engine_running = true;
|
||||||
|
in.brake_pedal_pressed = false;
|
||||||
|
in.vehicle_speed_kmh = 0.0f;
|
||||||
|
in.grade_percent = 0.0f;
|
||||||
|
in.current_state = EPB_STATE_APPLIED;
|
||||||
|
in.gas_pedal_percent = 0.0f;
|
||||||
|
in.gear_in_drive = false;
|
||||||
|
in.door_closed = true;
|
||||||
|
in.seatbelt_fastened = true;
|
||||||
|
return in;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void test_drive_away_armed_on_intent(void)
|
||||||
|
{
|
||||||
|
TEST_BEGIN("SWE-011 + SWE-012: Anfahrabsicht + Safety -> DRIVE_AWAY + Release-Request");
|
||||||
|
(void)safety_mgr_init();
|
||||||
|
SafetyInputs in = make_applied_at_rest();
|
||||||
|
in.gas_pedal_percent = 25.0f;
|
||||||
|
in.gear_in_drive = true;
|
||||||
|
safety_mgr_step_50ms(&in);
|
||||||
|
ASSERT_EQ(safety_mgr_get_state(), SAFETY_DRIVE_AWAY);
|
||||||
|
ASSERT_TRUE(safety_mgr_release_requested());
|
||||||
|
TEST_END();
|
||||||
|
}
|
||||||
|
|
||||||
|
static void test_drive_away_blocked_without_safety(void)
|
||||||
|
{
|
||||||
|
TEST_BEGIN("SWE-012: Tuer offen blockiert Drive-Away");
|
||||||
|
(void)safety_mgr_init();
|
||||||
|
SafetyInputs in = make_applied_at_rest();
|
||||||
|
in.gas_pedal_percent = 25.0f;
|
||||||
|
in.gear_in_drive = true;
|
||||||
|
in.door_closed = false; /* Tuer offen */
|
||||||
|
safety_mgr_step_50ms(&in);
|
||||||
|
ASSERT_EQ(safety_mgr_get_state(), SAFETY_IDLE);
|
||||||
|
ASSERT_TRUE(!safety_mgr_release_requested());
|
||||||
|
TEST_END();
|
||||||
|
}
|
||||||
|
|
||||||
|
static void test_drive_away_blocked_without_seatbelt(void)
|
||||||
|
{
|
||||||
|
TEST_BEGIN("SWE-012: Gurt nicht angelegt blockiert Drive-Away");
|
||||||
|
(void)safety_mgr_init();
|
||||||
|
SafetyInputs in = make_applied_at_rest();
|
||||||
|
in.gas_pedal_percent = 25.0f;
|
||||||
|
in.gear_in_drive = true;
|
||||||
|
in.seatbelt_fastened = false;
|
||||||
|
safety_mgr_step_50ms(&in);
|
||||||
|
ASSERT_EQ(safety_mgr_get_state(), SAFETY_IDLE);
|
||||||
|
TEST_END();
|
||||||
|
}
|
||||||
|
|
||||||
|
static void test_drive_away_blocked_below_gas_threshold(void)
|
||||||
|
{
|
||||||
|
TEST_BEGIN("SWE-011: Gas < 10% loest kein Drive-Away aus");
|
||||||
|
(void)safety_mgr_init();
|
||||||
|
SafetyInputs in = make_applied_at_rest();
|
||||||
|
in.gas_pedal_percent = 5.0f;
|
||||||
|
in.gear_in_drive = true;
|
||||||
|
safety_mgr_step_50ms(&in);
|
||||||
|
ASSERT_EQ(safety_mgr_get_state(), SAFETY_IDLE);
|
||||||
|
TEST_END();
|
||||||
|
}
|
||||||
|
|
||||||
|
static void test_drive_away_ends_when_released(void)
|
||||||
|
{
|
||||||
|
TEST_BEGIN("DRIVE_AWAY -> IDLE wenn Apply Controller geloest hat");
|
||||||
|
(void)safety_mgr_init();
|
||||||
|
SafetyInputs in = make_applied_at_rest();
|
||||||
|
in.gas_pedal_percent = 25.0f;
|
||||||
|
in.gear_in_drive = true;
|
||||||
|
safety_mgr_step_50ms(&in); /* -> DRIVE_AWAY */
|
||||||
|
in.current_state = EPB_STATE_RELEASED;
|
||||||
|
safety_mgr_step_50ms(&in);
|
||||||
|
ASSERT_EQ(safety_mgr_get_state(), SAFETY_IDLE);
|
||||||
|
ASSERT_TRUE(!safety_mgr_release_requested());
|
||||||
|
TEST_END();
|
||||||
|
}
|
||||||
|
|
||||||
static void test_already_applied_does_not_arm_auto_apply(void)
|
static void test_already_applied_does_not_arm_auto_apply(void)
|
||||||
{
|
{
|
||||||
TEST_BEGIN("Bereits Applied: kein Auto-Apply Arming");
|
TEST_BEGIN("Bereits Applied: kein Auto-Apply Arming");
|
||||||
@@ -235,6 +319,11 @@ int main(void)
|
|||||||
test_hillhold_active_on_brake_release();
|
test_hillhold_active_on_brake_release();
|
||||||
test_hillhold_active_ends_on_vehicle_rolling();
|
test_hillhold_active_ends_on_vehicle_rolling();
|
||||||
test_hillhold_armed_to_idle_if_grade_drops();
|
test_hillhold_armed_to_idle_if_grade_drops();
|
||||||
|
test_drive_away_armed_on_intent();
|
||||||
|
test_drive_away_blocked_without_safety();
|
||||||
|
test_drive_away_blocked_without_seatbelt();
|
||||||
|
test_drive_away_blocked_below_gas_threshold();
|
||||||
|
test_drive_away_ends_when_released();
|
||||||
test_already_applied_does_not_arm_auto_apply();
|
test_already_applied_does_not_arm_auto_apply();
|
||||||
TEST_SUMMARY();
|
TEST_SUMMARY();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,12 +18,72 @@ REPO = Path(__file__).resolve().parent.parent
|
|||||||
|
|
||||||
|
|
||||||
# ---------------------------------------------------------------------------
|
# ---------------------------------------------------------------------------
|
||||||
# System Requirements
|
# 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 = [
|
SYS_REQS = [
|
||||||
{
|
{
|
||||||
"id": "SYS-001", "asil": "D",
|
"id": "SYS-001", "asil": "D",
|
||||||
|
"links": ["SG-001"],
|
||||||
"title": "Halten der Parkbremse im Stillstand",
|
"title": "Halten der Parkbremse im Stillstand",
|
||||||
"text": (
|
"text": (
|
||||||
"Wenn die Parkbremse aktiviert ist und das Fahrzeug stillsteht, "
|
"Wenn die Parkbremse aktiviert ist und das Fahrzeug stillsteht, "
|
||||||
@@ -35,6 +95,7 @@ SYS_REQS = [
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "SYS-002", "asil": "D",
|
"id": "SYS-002", "asil": "D",
|
||||||
|
"links": ["SG-002", "SG-005"],
|
||||||
"title": "Apply auf Fahrer-Anforderung",
|
"title": "Apply auf Fahrer-Anforderung",
|
||||||
"text": (
|
"text": (
|
||||||
"Bei Betaetigung des EPB-Schalters in Apply-Richtung muss das "
|
"Bei Betaetigung des EPB-Schalters in Apply-Richtung muss das "
|
||||||
@@ -45,6 +106,7 @@ SYS_REQS = [
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "SYS-003", "asil": "B",
|
"id": "SYS-003", "asil": "B",
|
||||||
|
"links": ["SG-005"],
|
||||||
"title": "Release auf Fahrer-Anforderung",
|
"title": "Release auf Fahrer-Anforderung",
|
||||||
"text": (
|
"text": (
|
||||||
"Bei Betaetigung des EPB-Schalters in Release-Richtung muss das "
|
"Bei Betaetigung des EPB-Schalters in Release-Richtung muss das "
|
||||||
@@ -55,6 +117,7 @@ SYS_REQS = [
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "SYS-004", "asil": "D",
|
"id": "SYS-004", "asil": "D",
|
||||||
|
"links": ["SG-001"],
|
||||||
"title": "Auto-Apply bei Motor-Aus",
|
"title": "Auto-Apply bei Motor-Aus",
|
||||||
"text": (
|
"text": (
|
||||||
"Wenn der Motor ausgeschaltet wird und das Fahrzeug stillsteht "
|
"Wenn der Motor ausgeschaltet wird und das Fahrzeug stillsteht "
|
||||||
@@ -65,6 +128,7 @@ SYS_REQS = [
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "SYS-005", "asil": "D",
|
"id": "SYS-005", "asil": "D",
|
||||||
|
"links": ["SG-002", "SG-004"],
|
||||||
"title": "Hill-Hold am Berg",
|
"title": "Hill-Hold am Berg",
|
||||||
"text": (
|
"text": (
|
||||||
"Bei aktivem Hill-Hold (Fahrzeug steht am Hang mit Neigung > 5%, "
|
"Bei aktivem Hill-Hold (Fahrzeug steht am Hang mit Neigung > 5%, "
|
||||||
@@ -75,6 +139,7 @@ SYS_REQS = [
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "SYS-006", "asil": "B",
|
"id": "SYS-006", "asil": "B",
|
||||||
|
"links": ["SG-004"],
|
||||||
"title": "Auto-Release beim Anfahren (Drive-Away-Assist)",
|
"title": "Auto-Release beim Anfahren (Drive-Away-Assist)",
|
||||||
"text": (
|
"text": (
|
||||||
"Wenn die Parkbremse aktiv ist und der Fahrer Anfahrabsicht zeigt "
|
"Wenn die Parkbremse aktiv ist und der Fahrer Anfahrabsicht zeigt "
|
||||||
@@ -86,6 +151,7 @@ SYS_REQS = [
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "SYS-007", "asil": "B",
|
"id": "SYS-007", "asil": "B",
|
||||||
|
"links": ["SG-003"],
|
||||||
"title": "Aktor-Stromueberwachung",
|
"title": "Aktor-Stromueberwachung",
|
||||||
"text": (
|
"text": (
|
||||||
"Das System muss den Motorstrom jedes Aktors mit mindestens 1 kHz "
|
"Das System muss den Motorstrom jedes Aktors mit mindestens 1 kHz "
|
||||||
@@ -795,6 +861,7 @@ def write_items(items, target_dir: Path, with_links=True):
|
|||||||
|
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
|
write_items(SG_GOALS, REPO / "safety" / "sg")
|
||||||
write_items(SYS_REQS, REPO / "reqs" / "sys")
|
write_items(SYS_REQS, REPO / "reqs" / "sys")
|
||||||
write_items(SWE_REQS, REPO / "reqs" / "swe")
|
write_items(SWE_REQS, REPO / "reqs" / "swe")
|
||||||
write_items(SA_ELEMENTS, REPO / "arch" / "sys")
|
write_items(SA_ELEMENTS, REPO / "arch" / "sys")
|
||||||
|
|||||||
@@ -0,0 +1,151 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
"""
|
||||||
|
Erzeugt einen Test-Summary-Report aus dem Output unserer Unit-Tests.
|
||||||
|
|
||||||
|
Liest die Test-Output-Datei (build/test-output.txt) und erzeugt:
|
||||||
|
- build/test-report.md
|
||||||
|
- build/test-report.html
|
||||||
|
|
||||||
|
Workflow:
|
||||||
|
make test > build/test-output.txt 2>&1
|
||||||
|
python3 tools/generate_test_report.py
|
||||||
|
|
||||||
|
Oder: `make test-report` macht beides.
|
||||||
|
"""
|
||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
|
import datetime
|
||||||
|
import html
|
||||||
|
import re
|
||||||
|
import sys
|
||||||
|
from pathlib import Path
|
||||||
|
|
||||||
|
REPO = Path(__file__).resolve().parent.parent
|
||||||
|
BUILD = REPO / "build"
|
||||||
|
TEST_OUTPUT = BUILD / "test-output.txt"
|
||||||
|
|
||||||
|
|
||||||
|
def reqs_for(test_name: str) -> list[str]:
|
||||||
|
src = REPO / "tests" / "unit" / f"{test_name}.c"
|
||||||
|
if not src.exists():
|
||||||
|
return []
|
||||||
|
head = src.read_text()[:400]
|
||||||
|
m = re.search(r"@reqs\s+([A-Z0-9 \-,]+)", head)
|
||||||
|
return re.findall(r"[A-Z]+-\d+", m.group(1)) if m else []
|
||||||
|
|
||||||
|
|
||||||
|
def parse_output(text: str) -> list[dict]:
|
||||||
|
"""Split into suite-blocks separated by '== test_xxx ==' headers."""
|
||||||
|
suites = []
|
||||||
|
cur = None
|
||||||
|
for line in text.splitlines():
|
||||||
|
m = re.match(r"==\s+(test_\w+)\s+==", line)
|
||||||
|
if m:
|
||||||
|
if cur is not None:
|
||||||
|
suites.append(cur)
|
||||||
|
cur = {"binary": m.group(1), "tests": []}
|
||||||
|
continue
|
||||||
|
if cur is None:
|
||||||
|
continue
|
||||||
|
m = re.match(r"\s+TEST\s+(.+?)\s+\.\.\.\s+(\w+)", line)
|
||||||
|
if m:
|
||||||
|
cur["tests"].append((m.group(1).strip(), m.group(2)))
|
||||||
|
if cur is not None:
|
||||||
|
suites.append(cur)
|
||||||
|
for s in suites:
|
||||||
|
s["total"] = len(s["tests"])
|
||||||
|
s["failed"] = sum(1 for _, st in s["tests"] if st.lower() != "ok")
|
||||||
|
s["passed"] = s["total"] - s["failed"]
|
||||||
|
return suites
|
||||||
|
|
||||||
|
|
||||||
|
def main() -> int:
|
||||||
|
if not TEST_OUTPUT.exists():
|
||||||
|
print(f"ERROR: {TEST_OUTPUT} fehlt. Bitte zuerst `make test > {TEST_OUTPUT.relative_to(REPO)} 2>&1` ausfuehren.")
|
||||||
|
return 1
|
||||||
|
|
||||||
|
output = TEST_OUTPUT.read_text()
|
||||||
|
results = parse_output(output)
|
||||||
|
if not results:
|
||||||
|
print("ERROR: keine Test-Suite im Output gefunden.")
|
||||||
|
return 1
|
||||||
|
|
||||||
|
total = sum(r["total"] for r in results)
|
||||||
|
failed = sum(r["failed"] for r in results)
|
||||||
|
passed = total - failed
|
||||||
|
now = datetime.datetime.now(datetime.timezone.utc).isoformat()
|
||||||
|
|
||||||
|
# Markdown
|
||||||
|
md = [f"# demo-epb — Test Summary Report\n\n",
|
||||||
|
f"**Datum:** {now}\n\n",
|
||||||
|
f"**Gesamt:** {total} Tests, {passed} bestanden, {failed} fehlgeschlagen\n\n",
|
||||||
|
f"**Status:** {'PASS' if failed == 0 else 'FAIL'}\n\n",
|
||||||
|
"## Pro Test-Suite\n\n",
|
||||||
|
"| Suite | Anzahl | Bestanden | Fehlgeschlagen | Anforderungen |\n",
|
||||||
|
"|-------|--------|-----------|-----------------|---------------|\n"]
|
||||||
|
for r in results:
|
||||||
|
reqs = ", ".join(reqs_for(r["binary"])) or "—"
|
||||||
|
md.append(f"| `{r['binary']}` | {r['total']} | {r['passed']} | "
|
||||||
|
f"{r['failed']} | {reqs} |\n")
|
||||||
|
md.append("\n## Details\n\n")
|
||||||
|
for r in results:
|
||||||
|
md.append(f"### `{r['binary']}`\n\n")
|
||||||
|
md.append("| # | Test | Status |\n|---|------|--------|\n")
|
||||||
|
for i, (name, status) in enumerate(r["tests"], 1):
|
||||||
|
md.append(f"| {i} | {name} | {status} |\n")
|
||||||
|
md.append("\n")
|
||||||
|
(BUILD / "test-report.md").write_text("".join(md))
|
||||||
|
|
||||||
|
# HTML
|
||||||
|
badge_cls = "pass-badge" if failed == 0 else "fail-badge"
|
||||||
|
badge_txt = "PASS" if failed == 0 else "FAIL"
|
||||||
|
h = [
|
||||||
|
"<!doctype html><html lang='de'><head>",
|
||||||
|
"<meta charset='utf-8'><title>demo-epb Test Report</title>",
|
||||||
|
"<style>",
|
||||||
|
"body{font-family:-apple-system,Segoe UI,sans-serif;padding:20px}",
|
||||||
|
"h1{color:#1f3864}h2{color:#1f3864;margin-top:30px}",
|
||||||
|
"table{border-collapse:collapse;width:100%;font-size:14px;margin:10px 0}",
|
||||||
|
"th,td{border:1px solid #ccc;padding:6px 10px;text-align:left}",
|
||||||
|
"th{background:#f0f0f0}",
|
||||||
|
".pass{color:#0a0;font-weight:bold}.fail{color:#c00;font-weight:bold}",
|
||||||
|
".badge{display:inline-block;padding:4px 10px;border-radius:4px;color:#fff;font-weight:bold}",
|
||||||
|
".pass-badge{background:#0a0}.fail-badge{background:#c00}",
|
||||||
|
"</style></head><body>",
|
||||||
|
"<h1>demo-epb — Test Summary Report</h1>",
|
||||||
|
f"<p><strong>Datum:</strong> {now}</p>",
|
||||||
|
f"<p><strong>Gesamt:</strong> {total} Tests, {passed} bestanden, {failed} fehlgeschlagen — "
|
||||||
|
f"<span class='badge {badge_cls}'>{badge_txt}</span></p>",
|
||||||
|
"<h2>Pro Test-Suite</h2>",
|
||||||
|
"<table><tr><th>Suite</th><th>Anzahl</th><th>Bestanden</th>"
|
||||||
|
"<th>Fehlgeschlagen</th><th>Anforderungen</th></tr>",
|
||||||
|
]
|
||||||
|
for r in results:
|
||||||
|
reqs = ", ".join(reqs_for(r["binary"])) or "—"
|
||||||
|
h.append(
|
||||||
|
f"<tr><td><code>{html.escape(r['binary'])}</code></td>"
|
||||||
|
f"<td>{r['total']}</td><td>{r['passed']}</td>"
|
||||||
|
f"<td>{r['failed']}</td><td>{html.escape(reqs)}</td></tr>"
|
||||||
|
)
|
||||||
|
h.append("</table>")
|
||||||
|
for r in results:
|
||||||
|
h.append(f"<h2><code>{html.escape(r['binary'])}</code></h2>")
|
||||||
|
h.append("<table><tr><th>#</th><th>Test</th><th>Status</th></tr>")
|
||||||
|
for i, (name, status) in enumerate(r["tests"], 1):
|
||||||
|
cls = "pass" if status.lower() == "ok" else "fail"
|
||||||
|
h.append(
|
||||||
|
f"<tr><td>{i}</td><td>{html.escape(name)}</td>"
|
||||||
|
f"<td class='{cls}'>{html.escape(status)}</td></tr>"
|
||||||
|
)
|
||||||
|
h.append("</table>")
|
||||||
|
h.append("</body></html>")
|
||||||
|
(BUILD / "test-report.html").write_text("\n".join(h))
|
||||||
|
|
||||||
|
print(f"Wrote {BUILD / 'test-report.md'}")
|
||||||
|
print(f"Wrote {BUILD / 'test-report.html'}")
|
||||||
|
print(f"\n{total} tests: {passed} passed, {failed} failed.")
|
||||||
|
return 0 if failed == 0 else 1
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
sys.exit(main())
|
||||||
+213
-55
@@ -2,11 +2,12 @@
|
|||||||
"""
|
"""
|
||||||
Traceability-Werkzeug fuer demo-epb.
|
Traceability-Werkzeug fuer demo-epb.
|
||||||
|
|
||||||
Liest alle Markdown-Items in reqs/ und arch/ ein, validiert Links bidirektional
|
Liest Markdown-Items aus safety/sg, reqs/sys, reqs/swe, arch/sys, arch/swe und
|
||||||
und erzeugt eine HTML-Traceability-Matrix.
|
verifiziert die Traceability-Kette:
|
||||||
|
|
||||||
Doorstop-kompatibles Format (YAML-Frontmatter + Markdown-Body), aber ohne
|
SG <-- SYS <-- SA
|
||||||
Doorstop-Dependency — bleibt portabel.
|
<-- SWE <-- SWA <-- Code (@arch)
|
||||||
|
<-- Tests (@reqs)
|
||||||
|
|
||||||
Subcommands:
|
Subcommands:
|
||||||
check Validiert Konsistenz, exit 1 bei Fehlern
|
check Validiert Konsistenz, exit 1 bei Fehlern
|
||||||
@@ -28,25 +29,42 @@ from pathlib import Path
|
|||||||
REPO = Path(__file__).resolve().parent.parent
|
REPO = Path(__file__).resolve().parent.parent
|
||||||
|
|
||||||
SOURCES = [
|
SOURCES = [
|
||||||
|
("SG", "safety/sg", "Safety Goals"),
|
||||||
("SYS", "reqs/sys", "System Requirements"),
|
("SYS", "reqs/sys", "System Requirements"),
|
||||||
("SWE", "reqs/swe", "Software Requirements"),
|
("SWE", "reqs/swe", "Software Requirements"),
|
||||||
("SA", "arch/sys", "System Architecture"),
|
("SA", "arch/sys", "System Architecture"),
|
||||||
("SWA", "arch/swe", "Software Architecture"),
|
("SWA", "arch/swe", "Software Architecture"),
|
||||||
]
|
]
|
||||||
|
|
||||||
# Welche Quellen verlinken auf welche?
|
# Forward: items of <key> prefix SHOULD link to <target> prefix
|
||||||
# (key) -> (target_prefix) : Items mit key linken auf Items mit target_prefix
|
|
||||||
EXPECTED_LINKS = {
|
EXPECTED_LINKS = {
|
||||||
"SA": ["SYS"],
|
"SA": ["SYS"],
|
||||||
"SWE": ["SYS"],
|
"SWE": ["SYS"],
|
||||||
"SWA": ["SWE"],
|
"SWA": ["SWE"],
|
||||||
|
# SYS optionally links to SG — checked separately, only for safety-relevant SYS
|
||||||
}
|
}
|
||||||
|
|
||||||
# Reverse: welche Quellen MUESSEN von welchen Quellen referenziert werden?
|
# Reverse coverage: each item of <key> must be referenced by all items in list
|
||||||
# (target) -> [prefix that should link to target] (coverage check)
|
|
||||||
COVERAGE = {
|
COVERAGE = {
|
||||||
"SYS": ["SA", "SWE"], # jede SYS-Req muss durch SA und SWE abgedeckt sein
|
"SG": ["SYS"], # each SG must be detailed by at least one SYS
|
||||||
"SWE": ["SWA"], # jede SWE-Req muss durch SWA abgedeckt sein
|
"SYS": ["SA", "SWE"], # each SYS must be covered by SA + SWE
|
||||||
|
"SWE": ["SWA"], # each SWE must be implemented by SWA
|
||||||
|
}
|
||||||
|
|
||||||
|
# Components that are implemented in src/ (have a .c file)
|
||||||
|
IMPLEMENTED_SWA = {
|
||||||
|
"SWA-001": "src/safety_manager.c",
|
||||||
|
"SWA-002": "src/apply_controller.c",
|
||||||
|
"SWA-003": "src/actuator_driver.c",
|
||||||
|
"SWA-006": "src/switch_debouncer.c",
|
||||||
|
}
|
||||||
|
|
||||||
|
# Tests we ship — map test file → SWA it covers
|
||||||
|
IMPLEMENTED_TESTS = {
|
||||||
|
"test_safety_manager.c": "SWA-001",
|
||||||
|
"test_apply_controller.c": "SWA-002",
|
||||||
|
"test_actuator_driver.c": "SWA-003",
|
||||||
|
"test_switch_debouncer.c": "SWA-006",
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -61,7 +79,6 @@ class Item:
|
|||||||
|
|
||||||
|
|
||||||
FRONTMATTER_RE = re.compile(r"^---\s*\n(.*?)\n---\s*\n", re.DOTALL)
|
FRONTMATTER_RE = re.compile(r"^---\s*\n(.*?)\n---\s*\n", re.DOTALL)
|
||||||
LINKS_RE = re.compile(r"^\s*-\s+([A-Z]+-\d+)", re.MULTILINE)
|
|
||||||
|
|
||||||
|
|
||||||
def parse_item(path: Path, prefix: str) -> Item | None:
|
def parse_item(path: Path, prefix: str) -> Item | None:
|
||||||
@@ -71,7 +88,6 @@ def parse_item(path: Path, prefix: str) -> Item | None:
|
|||||||
return None
|
return None
|
||||||
fm = m.group(1)
|
fm = m.group(1)
|
||||||
|
|
||||||
# Crude YAML parsing — we only need a few fields.
|
|
||||||
def field_value(name: str) -> str | None:
|
def field_value(name: str) -> str | None:
|
||||||
rx = re.search(rf"^{name}:\s*(.*?)$", fm, re.MULTILINE)
|
rx = re.search(rf"^{name}:\s*(.*?)$", fm, re.MULTILINE)
|
||||||
return rx.group(1).strip().strip("'\"") if rx else None
|
return rx.group(1).strip().strip("'\"") if rx else None
|
||||||
@@ -79,7 +95,6 @@ def parse_item(path: Path, prefix: str) -> Item | None:
|
|||||||
asil = field_value("asil") or "?"
|
asil = field_value("asil") or "?"
|
||||||
title = field_value("header") or path.stem
|
title = field_value("header") or path.stem
|
||||||
|
|
||||||
# links: collect IDs from the `links:` block.
|
|
||||||
links: list[str] = []
|
links: list[str] = []
|
||||||
in_links = False
|
in_links = False
|
||||||
for line in fm.splitlines():
|
for line in fm.splitlines():
|
||||||
@@ -112,16 +127,76 @@ def collect_all() -> dict[str, Item]:
|
|||||||
return items
|
return items
|
||||||
|
|
||||||
|
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
|
# Code / Test traceability
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
ARCH_TAG_RE = re.compile(r"@arch\s+([A-Z]+-\d+(?:\s+[A-Z]+-\d+)*)")
|
||||||
|
REQS_TAG_RE = re.compile(r"@reqs\s+([A-Z]+-\d+(?:\s+[A-Z]+-\d+)*)")
|
||||||
|
|
||||||
|
|
||||||
|
def extract_tags(path: Path) -> tuple[list[str], list[str]]:
|
||||||
|
"""Extract @arch and @reqs tag IDs from the file header (first ~400 chars)."""
|
||||||
|
if not path.exists():
|
||||||
|
return [], []
|
||||||
|
head = path.read_text()[:600]
|
||||||
|
arch_ids: list[str] = []
|
||||||
|
reqs_ids: list[str] = []
|
||||||
|
for m in ARCH_TAG_RE.finditer(head):
|
||||||
|
arch_ids.extend(re.findall(r"[A-Z]+-\d+", m.group(1)))
|
||||||
|
for m in REQS_TAG_RE.finditer(head):
|
||||||
|
reqs_ids.extend(re.findall(r"[A-Z]+-\d+", m.group(1)))
|
||||||
|
return arch_ids, reqs_ids
|
||||||
|
|
||||||
|
|
||||||
|
def check_code_test_mapping(items: dict[str, Item]) -> list[str]:
|
||||||
|
"""Check that:
|
||||||
|
- Each implemented .c file's @arch matches its SWA-id (per IMPLEMENTED_SWA)
|
||||||
|
- Each test's @reqs covers all SWE that the corresponding SWA implements
|
||||||
|
"""
|
||||||
|
errors: list[str] = []
|
||||||
|
|
||||||
|
for swa_id, src_rel in IMPLEMENTED_SWA.items():
|
||||||
|
src = REPO / src_rel
|
||||||
|
arch_tags, _ = extract_tags(src)
|
||||||
|
if swa_id not in arch_tags:
|
||||||
|
errors.append(f"{src_rel}: header @arch enthaelt {swa_id} nicht "
|
||||||
|
f"(gefunden: {arch_tags or '—'})")
|
||||||
|
|
||||||
|
# For each test, verify @reqs covers the SWE that the corresponding SWA links to
|
||||||
|
for test_file, swa_id in IMPLEMENTED_TESTS.items():
|
||||||
|
test_path = REPO / "tests" / "unit" / test_file
|
||||||
|
_, reqs_in_test = extract_tags(test_path)
|
||||||
|
if not reqs_in_test:
|
||||||
|
errors.append(f"tests/unit/{test_file}: kein @reqs Tag im Header")
|
||||||
|
continue
|
||||||
|
swa = items.get(swa_id)
|
||||||
|
if swa is None:
|
||||||
|
errors.append(f"tests/unit/{test_file}: referenziertes "
|
||||||
|
f"{swa_id} nicht gefunden")
|
||||||
|
continue
|
||||||
|
swa_swe = set(swa.links)
|
||||||
|
test_swe = set(reqs_in_test)
|
||||||
|
missing = swa_swe - test_swe
|
||||||
|
if missing:
|
||||||
|
errors.append(f"tests/unit/{test_file}: deckt nicht alle SWE "
|
||||||
|
f"der {swa_id} ab — fehlend: {sorted(missing)}")
|
||||||
|
|
||||||
|
return errors
|
||||||
|
|
||||||
|
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
|
# Commands
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
|
|
||||||
def cmd_check(items: dict[str, Item]) -> int:
|
def cmd_check(items: dict[str, Item]) -> int:
|
||||||
errors: list[str] = []
|
errors: list[str] = []
|
||||||
|
|
||||||
# 1. Each link target must exist
|
|
||||||
for it in items.values():
|
for it in items.values():
|
||||||
for link in it.links:
|
for link in it.links:
|
||||||
if link not in items:
|
if link not in items:
|
||||||
errors.append(f"{it.id} links to non-existent {link}")
|
errors.append(f"{it.id} links to non-existent {link}")
|
||||||
|
|
||||||
# 2. Forward expectation: items of certain prefixes must link to others
|
|
||||||
for it in items.values():
|
for it in items.values():
|
||||||
expected_prefixes = EXPECTED_LINKS.get(it.prefix, [])
|
expected_prefixes = EXPECTED_LINKS.get(it.prefix, [])
|
||||||
if not expected_prefixes:
|
if not expected_prefixes:
|
||||||
@@ -133,7 +208,6 @@ def cmd_check(items: dict[str, Item]) -> int:
|
|||||||
f"{it.id} ({it.prefix}) has no link to a {ep}-* item"
|
f"{it.id} ({it.prefix}) has no link to a {ep}-* item"
|
||||||
)
|
)
|
||||||
|
|
||||||
# 3. Coverage: each item of certain prefix must be referenced by certain types
|
|
||||||
incoming: dict[str, set[str]] = {iid: set() for iid in items}
|
incoming: dict[str, set[str]] = {iid: set() for iid in items}
|
||||||
for it in items.values():
|
for it in items.values():
|
||||||
for link in it.links:
|
for link in it.links:
|
||||||
@@ -144,22 +218,30 @@ def cmd_check(items: dict[str, Item]) -> int:
|
|||||||
required = COVERAGE.get(it.prefix, [])
|
required = COVERAGE.get(it.prefix, [])
|
||||||
for rp in required:
|
for rp in required:
|
||||||
if rp not in incoming[it.id]:
|
if rp not in incoming[it.id]:
|
||||||
|
# Exclude QM-level SYS reqs from SG coverage check
|
||||||
|
if rp == "SYS" and it.prefix == "SG":
|
||||||
|
continue
|
||||||
errors.append(
|
errors.append(
|
||||||
f"{it.id} ({it.prefix}) is not referenced by any {rp}-* item"
|
f"{it.id} ({it.prefix}) is not referenced by any {rp}-* item"
|
||||||
)
|
)
|
||||||
|
|
||||||
print(f"\nItems found: {len(items)}")
|
# Code + Test mapping
|
||||||
print(f" SYS: {sum(1 for i in items.values() if i.prefix == 'SYS')}")
|
errors.extend(check_code_test_mapping(items))
|
||||||
print(f" SWE: {sum(1 for i in items.values() if i.prefix == 'SWE')}")
|
|
||||||
print(f" SA: {sum(1 for i in items.values() if i.prefix == 'SA')}")
|
counts = {p: sum(1 for i in items.values() if i.prefix == p)
|
||||||
print(f" SWA: {sum(1 for i in items.values() if i.prefix == 'SWA')}")
|
for p, _, _ in SOURCES}
|
||||||
|
print(f"\nItems found: {sum(counts.values())}")
|
||||||
|
for p, _, _ in SOURCES:
|
||||||
|
print(f" {p:4} {counts[p]:3}")
|
||||||
|
print(f"\nCode mappings: {len(IMPLEMENTED_SWA)} implemented SWA")
|
||||||
|
print(f"Test mappings: {len(IMPLEMENTED_TESTS)} test files")
|
||||||
print()
|
print()
|
||||||
if errors:
|
if errors:
|
||||||
print(f"FAIL: {len(errors)} traceability error(s):")
|
print(f"FAIL: {len(errors)} traceability error(s):")
|
||||||
for e in errors:
|
for e in errors:
|
||||||
print(f" - {e}")
|
print(f" - {e}")
|
||||||
return 1
|
return 1
|
||||||
print("OK — Traceability vollstaendig.")
|
print("OK — Traceability vollstaendig (SG → SYS → SA, SWE → SWA → Code+Test).")
|
||||||
return 0
|
return 0
|
||||||
|
|
||||||
|
|
||||||
@@ -176,7 +258,7 @@ def asil_color(asil: str) -> str:
|
|||||||
def cmd_publish(items: dict[str, Item], out_dir: Path) -> int:
|
def cmd_publish(items: dict[str, Item], out_dir: Path) -> int:
|
||||||
out_dir.mkdir(parents=True, exist_ok=True)
|
out_dir.mkdir(parents=True, exist_ok=True)
|
||||||
|
|
||||||
# Build forward and reverse maps
|
# Build reverse map: who links to me?
|
||||||
children: dict[str, list[str]] = {iid: [] for iid in items}
|
children: dict[str, list[str]] = {iid: [] for iid in items}
|
||||||
for it in items.values():
|
for it in items.values():
|
||||||
for link in it.links:
|
for link in it.links:
|
||||||
@@ -184,15 +266,35 @@ def cmd_publish(items: dict[str, Item], out_dir: Path) -> int:
|
|||||||
children[link].append(it.id)
|
children[link].append(it.id)
|
||||||
|
|
||||||
rows = []
|
rows = []
|
||||||
sys_items = [i for i in items.values() if i.prefix == "SYS"]
|
sgs = [i for i in items.values() if i.prefix == "SG"]
|
||||||
for sys in sorted(sys_items, key=lambda i: i.id):
|
qm_sys = [i for i in items.values() if i.prefix == "SYS" and not i.links]
|
||||||
sas = [c for c in children[sys.id] if items[c].prefix == "SA"]
|
# For each SG, build a row
|
||||||
swes = [c for c in children[sys.id] if items[c].prefix == "SWE"]
|
for sg in sorted(sgs, key=lambda i: i.id):
|
||||||
swas = sorted(set(c for s in swes for c in children[s]
|
sys_items = [c for c in children[sg.id] if items[c].prefix == "SYS"]
|
||||||
if items[c].prefix == "SWA"))
|
for s in sorted(sys_items):
|
||||||
rows.append({
|
sys_it = items[s]
|
||||||
"sys": sys, "sa": sas, "swe": swes, "swa": swas
|
sas = [c for c in children[sys_it.id] if items[c].prefix == "SA"]
|
||||||
})
|
swes = [c for c in children[sys_it.id] if items[c].prefix == "SWE"]
|
||||||
|
swas = sorted({c for sw in swes for c in children[sw]
|
||||||
|
if items[c].prefix == "SWA"})
|
||||||
|
code = sorted({swa for swa in swas if swa in IMPLEMENTED_SWA})
|
||||||
|
tests = sorted({f for f, swa in IMPLEMENTED_TESTS.items()
|
||||||
|
if swa in swas})
|
||||||
|
rows.append({"sg": sg, "sys": sys_it, "sa": sas, "swe": swes,
|
||||||
|
"swa": swas, "code": code, "tests": tests})
|
||||||
|
|
||||||
|
# Also include QM-level SYS (not linked to SG) as separate section
|
||||||
|
for sys_it in sorted(qm_sys, key=lambda i: i.id):
|
||||||
|
sas = [c for c in children[sys_it.id] if items[c].prefix == "SA"]
|
||||||
|
swes = [c for c in children[sys_it.id] if items[c].prefix == "SWE"]
|
||||||
|
swas = sorted({c for sw in swes for c in children[sw]
|
||||||
|
if items[c].prefix == "SWA"})
|
||||||
|
code = sorted({swa for swa in swas if swa in IMPLEMENTED_SWA})
|
||||||
|
tests = sorted({f for f, swa in IMPLEMENTED_TESTS.items() if swa in swas})
|
||||||
|
rows.append({"sg": None, "sys": sys_it, "sa": sas, "swe": swes,
|
||||||
|
"swa": swas, "code": code, "tests": tests})
|
||||||
|
|
||||||
|
counts = {p: sum(1 for i in items.values() if i.prefix == p) for p, _, _ in SOURCES}
|
||||||
|
|
||||||
# HTML
|
# HTML
|
||||||
parts = [
|
parts = [
|
||||||
@@ -201,60 +303,116 @@ def cmd_publish(items: dict[str, Item], out_dir: Path) -> int:
|
|||||||
"<title>demo-epb — Traceability Matrix</title>",
|
"<title>demo-epb — Traceability Matrix</title>",
|
||||||
"<style>",
|
"<style>",
|
||||||
"body{font-family:-apple-system,Segoe UI,sans-serif;padding:20px;color:#222}",
|
"body{font-family:-apple-system,Segoe UI,sans-serif;padding:20px;color:#222}",
|
||||||
"table{border-collapse:collapse;width:100%;font-size:14px}",
|
"table{border-collapse:collapse;width:100%;font-size:13px;margin-top:16px}",
|
||||||
"th,td{border:1px solid #ccc;padding:6px 8px;vertical-align:top;text-align:left}",
|
"th,td{border:1px solid #ccc;padding:6px 8px;vertical-align:top;text-align:left}",
|
||||||
"th{background:#f0f0f0}",
|
"th{background:#f0f0f0;position:sticky;top:0}",
|
||||||
"tr:nth-child(even) td{background:#fafafa}",
|
"tr:nth-child(even) td{background:#fafafa}",
|
||||||
".asil{display:inline-block;padding:1px 6px;border-radius:3px;color:white;font-weight:bold;font-size:11px}",
|
".asil{display:inline-block;padding:1px 6px;border-radius:3px;color:white;font-weight:bold;font-size:11px}",
|
||||||
".id{font-family:Consolas,monospace;font-size:13px}",
|
".id{font-family:Consolas,monospace;font-size:12px}",
|
||||||
".cnt{color:#666;font-size:11px}",
|
".cnt{color:#666;font-size:11px}",
|
||||||
"h1{color:#1f3864}",
|
"h1{color:#1f3864}h2{color:#1f3864;margin-top:30px}",
|
||||||
|
".missing{color:#c00}",
|
||||||
"</style></head><body>",
|
"</style></head><body>",
|
||||||
"<h1>demo-epb — Traceability Matrix</h1>",
|
"<h1>demo-epb — Traceability Matrix</h1>",
|
||||||
f"<p>Generiert aus {sum(1 for _ in items)} Items "
|
"<p>Vollstaendige Kette: <code>SG → SYS → SA, SWE → SWA → Code (@arch) + Test (@reqs)</code></p>",
|
||||||
f"(SYS: {len([i for i in items.values() if i.prefix=='SYS'])}, "
|
"<p>",
|
||||||
f"SWE: {len([i for i in items.values() if i.prefix=='SWE'])}, "
|
|
||||||
f"SA: {len([i for i in items.values() if i.prefix=='SA'])}, "
|
|
||||||
f"SWA: {len([i for i in items.values() if i.prefix=='SWA'])}).</p>",
|
|
||||||
"<table>",
|
|
||||||
"<tr><th>System-Requirement</th><th>System-Arch (SA)</th>"
|
|
||||||
"<th>Software-Req (SWE)</th><th>Software-Arch (SWA)</th></tr>",
|
|
||||||
]
|
]
|
||||||
|
for p, _, label in SOURCES:
|
||||||
|
parts.append(f"<strong>{p}:</strong> {counts[p]} ")
|
||||||
|
parts.append(f"<strong>Code-Files:</strong> {len(IMPLEMENTED_SWA)} ")
|
||||||
|
parts.append(f"<strong>Test-Files:</strong> {len(IMPLEMENTED_TESTS)}")
|
||||||
|
parts.append("</p>")
|
||||||
|
|
||||||
def cell(ids: list[str]) -> str:
|
parts.append("<table>")
|
||||||
|
parts.append(
|
||||||
|
"<tr><th>Safety Goal</th><th>System-Requirement</th>"
|
||||||
|
"<th>System-Arch</th><th>Software-Req</th>"
|
||||||
|
"<th>Software-Arch</th><th>Code</th><th>Test</th></tr>"
|
||||||
|
)
|
||||||
|
|
||||||
|
def cell_items(ids: list[str]) -> str:
|
||||||
if not ids:
|
if not ids:
|
||||||
return "<td style='color:#c00'>—</td>"
|
return "<td class='missing'>—</td>"
|
||||||
bits = []
|
bits = []
|
||||||
for i in ids:
|
for i in ids:
|
||||||
it = items[i]
|
it = items[i]
|
||||||
c = asil_color(it.asil)
|
c = asil_color(it.asil)
|
||||||
bits.append(
|
bits.append(
|
||||||
f"<div><span class='id'>{html.escape(i)}</span> "
|
f"<div><span class='id'>{html.escape(i)}</span> "
|
||||||
f"<span class='asil' style='background:{c}'>{html.escape(it.asil)}</span></div>"
|
f"<span class='asil' style='background:{c}'>"
|
||||||
|
f"{html.escape(it.asil)}</span></div>"
|
||||||
f"<div class='cnt'>{html.escape(it.title)}</div>"
|
f"<div class='cnt'>{html.escape(it.title)}</div>"
|
||||||
)
|
)
|
||||||
return "<td>" + "".join(bits) + "</td>"
|
return "<td>" + "".join(bits) + "</td>"
|
||||||
|
|
||||||
|
def cell_item(it: Item | None) -> str:
|
||||||
|
if it is None:
|
||||||
|
return "<td class='missing'>—</td>"
|
||||||
|
c = asil_color(it.asil)
|
||||||
|
return (f"<td><div><span class='id'>{html.escape(it.id)}</span> "
|
||||||
|
f"<span class='asil' style='background:{c}'>"
|
||||||
|
f"{html.escape(it.asil)}</span></div>"
|
||||||
|
f"<div class='cnt'>{html.escape(it.title)}</div></td>")
|
||||||
|
|
||||||
|
def cell_files(files: list[str], prefix: str = "") -> str:
|
||||||
|
if not files:
|
||||||
|
return "<td class='cnt'>—</td>"
|
||||||
|
return "<td>" + "".join(
|
||||||
|
f"<div class='id'>{html.escape(prefix + f)}</div>"
|
||||||
|
for f in files
|
||||||
|
) + "</td>"
|
||||||
|
|
||||||
for r in rows:
|
for r in rows:
|
||||||
sys = r["sys"]
|
parts.append("<tr>")
|
||||||
c = asil_color(sys.asil)
|
parts.append(cell_item(r["sg"]))
|
||||||
first = (f"<td><div><span class='id'>{html.escape(sys.id)}</span> "
|
parts.append(cell_item(r["sys"]))
|
||||||
f"<span class='asil' style='background:{c}'>{html.escape(sys.asil)}</span></div>"
|
parts.append(cell_items(r["sa"]))
|
||||||
f"<div class='cnt'>{html.escape(sys.title)}</div></td>")
|
parts.append(cell_items(r["swe"]))
|
||||||
parts.append("<tr>" + first + cell(r["sa"]) + cell(r["swe"]) + cell(r["swa"]) + "</tr>")
|
parts.append(cell_items(r["swa"]))
|
||||||
|
parts.append(cell_files([IMPLEMENTED_SWA.get(s, "") for s in r["code"]
|
||||||
|
if IMPLEMENTED_SWA.get(s)]))
|
||||||
|
parts.append(cell_files(r["tests"], "tests/unit/"))
|
||||||
|
parts.append("</tr>")
|
||||||
|
|
||||||
parts.append("</table></body></html>")
|
parts.append("</table>")
|
||||||
|
|
||||||
|
# Code/Test details
|
||||||
|
parts.append("<h2>Code → Architektur</h2>")
|
||||||
|
parts.append("<table><tr><th>Datei</th><th>@arch</th><th>@reqs</th></tr>")
|
||||||
|
for swa_id, src_rel in IMPLEMENTED_SWA.items():
|
||||||
|
arch, reqs = extract_tags(REPO / src_rel)
|
||||||
|
parts.append(
|
||||||
|
f"<tr><td class='id'>{html.escape(src_rel)}</td>"
|
||||||
|
f"<td>{' '.join(arch)}</td>"
|
||||||
|
f"<td class='cnt'>{' '.join(reqs)}</td></tr>"
|
||||||
|
)
|
||||||
|
parts.append("</table>")
|
||||||
|
|
||||||
|
parts.append("<h2>Test → Anforderungen</h2>")
|
||||||
|
parts.append("<table><tr><th>Test-Datei</th><th>Decklt SWA</th><th>@reqs</th></tr>")
|
||||||
|
for test_file, swa_id in IMPLEMENTED_TESTS.items():
|
||||||
|
_, reqs = extract_tags(REPO / "tests" / "unit" / test_file)
|
||||||
|
parts.append(
|
||||||
|
f"<tr><td class='id'>tests/unit/{html.escape(test_file)}</td>"
|
||||||
|
f"<td>{swa_id}</td>"
|
||||||
|
f"<td class='cnt'>{' '.join(reqs)}</td></tr>"
|
||||||
|
)
|
||||||
|
parts.append("</table>")
|
||||||
|
|
||||||
|
parts.append("</body></html>")
|
||||||
(out_dir / "index.html").write_text("\n".join(parts))
|
(out_dir / "index.html").write_text("\n".join(parts))
|
||||||
|
|
||||||
# JSON for machine consumption
|
# JSON
|
||||||
matrix = []
|
matrix = []
|
||||||
for r in rows:
|
for r in rows:
|
||||||
matrix.append({
|
matrix.append({
|
||||||
|
"sg": {"id": r["sg"].id, "asil": r["sg"].asil} if r["sg"] else None,
|
||||||
"sys": {"id": r["sys"].id, "asil": r["sys"].asil, "title": r["sys"].title},
|
"sys": {"id": r["sys"].id, "asil": r["sys"].asil, "title": r["sys"].title},
|
||||||
"sa": [{"id": i, "asil": items[i].asil} for i in r["sa"]],
|
"sa": [{"id": i, "asil": items[i].asil} for i in r["sa"]],
|
||||||
"swe": [{"id": i, "asil": items[i].asil} for i in r["swe"]],
|
"swe": [{"id": i, "asil": items[i].asil} for i in r["swe"]],
|
||||||
"swa": [{"id": i, "asil": items[i].asil} for i in r["swa"]],
|
"swa": [{"id": i, "asil": items[i].asil} for i in r["swa"]],
|
||||||
|
"code": [IMPLEMENTED_SWA[s] for s in r["code"] if s in IMPLEMENTED_SWA],
|
||||||
|
"tests": [f"tests/unit/{f}" for f in r["tests"]],
|
||||||
})
|
})
|
||||||
(out_dir / "matrix.json").write_text(json.dumps(matrix, indent=2))
|
(out_dir / "matrix.json").write_text(json.dumps(matrix, indent=2))
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user