Initial commit: demo-epb v1.0 — Elektrische Parkbremse Demo

Vollstaendige Demo des slohmaier Dev Process anhand einer EPB-Steuergeraet-
Software. Zeigt ASPICE 4.0 / ISO 26262-konforme Entwicklung im Monorepo.

Inhalte:
- 5 Plaene (PID, PM-, QA-, SWE-, Test-Plan) in Word, ausgefuellt mit
  EPB-spezifischen Inhalten
- 10 System-Anforderungen + 25 Software-Anforderungen (Doorstop-MD)
- 5 System-Architektur-Elemente + 10 Software-Architektur-Elemente
  mit PlantUML-Diagrammen und vollstaendigem Mapping
- 3 implementierte Komponenten (Apply Controller D, Actuator Driver B,
  Switch Debouncer QM) plus 7 Header-Stubs
- 28 Unit-Tests, alle gruen, mit Coverage- und MISRA-Build-Targets
- Audit-Artefakte: 1 Review-Protokoll, 1 Non-Conformity, 1 MISRA-Record
- Gitea-Actions-CI-Pipeline (validate.yml)
- Doorstop-Konfiguration fuer bidirektionale Traceability
- Generator-Skript fuer alle 50 Reqs/Arch-Elemente aus Strukturdaten
- README mit gefuehrter Tour fuer Prospects
This commit is contained in:
Stefan Lohmaier
2026-05-11 13:51:02 -07:00
commit 1855162e6d
92 changed files with 4116 additions and 0 deletions
+157
View File
@@ -0,0 +1,157 @@
/**
* @file test_actuator_driver.c
* @brief Unit-Tests fuer den Actuator-Driver.
*
* @reqs SWE-006 SWE-013 SWE-014 SWE-015
* @arch SWA-003
*/
#include "../unit_test_framework.h"
#include "../../src/actuator_driver.h"
TestStats g_test_stats = {0, 0};
static void test_init(void)
{
TEST_BEGIN("init -> beide Aktoren STOP, 0 mA");
ASSERT_EQ(actuator_init(), EPB_OK);
ActuatorStatus l = actuator_get_status(ACTUATOR_LEFT);
ActuatorStatus r = actuator_get_status(ACTUATOR_RIGHT);
ASSERT_EQ(l.direction, ACT_DIR_STOP);
ASSERT_EQ(r.direction, ACT_DIR_STOP);
ASSERT_EQ(l.current_ma, 0);
TEST_END();
}
static void test_apply_invalid_id(void)
{
TEST_BEGIN("apply: invalid ID -> EINVAL");
(void)actuator_init();
ASSERT_EQ(actuator_apply((ActuatorId)42, 50), EPB_EINVAL);
TEST_END();
}
static void test_apply_pwm_out_of_range(void)
{
TEST_BEGIN("apply: PWM > 100% -> EINVAL");
(void)actuator_init();
ASSERT_EQ(actuator_apply(ACTUATOR_LEFT, 101), EPB_EINVAL);
TEST_END();
}
static void test_apply_normal(void)
{
TEST_BEGIN("apply normal -> direction=APPLY, pwm=80");
(void)actuator_init();
ASSERT_EQ(actuator_apply(ACTUATOR_LEFT, 80), EPB_OK);
ActuatorStatus s = actuator_get_status(ACTUATOR_LEFT);
ASSERT_EQ(s.direction, ACT_DIR_APPLY);
ASSERT_EQ(s.pwm_percent, 80);
TEST_END();
}
static void test_release_normal(void)
{
TEST_BEGIN("release normal -> direction=RELEASE");
(void)actuator_init();
ASSERT_EQ(actuator_release(ACTUATOR_LEFT, 70), EPB_OK);
ActuatorStatus s = actuator_get_status(ACTUATOR_LEFT);
ASSERT_EQ(s.direction, ACT_DIR_RELEASE);
TEST_END();
}
static void test_isr_samples_current(void)
{
TEST_BEGIN("ISR-Sample setzt current_ma und peak");
(void)actuator_init();
(void)actuator_apply(ACTUATOR_LEFT, 80);
actuator_isr_1khz(ACTUATOR_LEFT, 3000);
ActuatorStatus s = actuator_get_status(ACTUATOR_LEFT);
ASSERT_EQ(s.current_ma, 3000);
ASSERT_EQ(s.peak_current_ma, 3000);
TEST_END();
}
static void test_overcurrent_cutoff_after_100ms(void)
{
TEST_BEGIN("Overcurrent > 8 A fuer 100 ms -> STOP + overcurrent flag");
(void)actuator_init();
(void)actuator_apply(ACTUATOR_LEFT, 80);
/* 100 Samples (= 100 ms bei 1 kHz) ueber 8 A */
for (int i = 0; i < 100; ++i) {
actuator_isr_1khz(ACTUATOR_LEFT, 8500);
}
ActuatorStatus s = actuator_get_status(ACTUATOR_LEFT);
ASSERT_EQ(s.direction, ACT_DIR_STOP);
ASSERT_TRUE(s.overcurrent);
ASSERT_EQ(s.last_error, EPB_EOVERCURRENT);
TEST_END();
}
static void test_overcurrent_below_window_no_cutoff(void)
{
TEST_BEGIN("Overcurrent < 100 ms loest noch nicht aus");
(void)actuator_init();
(void)actuator_apply(ACTUATOR_LEFT, 80);
for (int i = 0; i < 50; ++i) {
actuator_isr_1khz(ACTUATOR_LEFT, 8500);
}
ActuatorStatus s = actuator_get_status(ACTUATOR_LEFT);
ASSERT_EQ(s.direction, ACT_DIR_APPLY);
ASSERT_TRUE(!s.overcurrent);
TEST_END();
}
static void test_overcurrent_blocks_subsequent_apply(void)
{
TEST_BEGIN("nach Overcurrent: weiterer apply -> EOVERCURRENT");
(void)actuator_init();
(void)actuator_apply(ACTUATOR_LEFT, 80);
for (int i = 0; i < 120; ++i) {
actuator_isr_1khz(ACTUATOR_LEFT, 9000);
}
EpbStatus rc = actuator_apply(ACTUATOR_LEFT, 80);
ASSERT_EQ(rc, EPB_EOVERCURRENT);
TEST_END();
}
static void test_clamping_force_estimate(void)
{
TEST_BEGIN("Klemmkraft-Schaetzung aus Peak-Strom (SWE-015)");
(void)actuator_init();
(void)actuator_apply(ACTUATOR_LEFT, 80);
actuator_isr_1khz(ACTUATOR_LEFT, 4000); /* 4 A Peak */
actuator_isr_1khz(ACTUATOR_LEFT, 3500); /* danach niedriger */
ActuatorStatus s = actuator_get_status(ACTUATOR_LEFT);
/* F = (4000 * 2500) / 1000 = 10000 N */
ASSERT_EQ(s.clamping_force_n, 10000);
TEST_END();
}
static void test_stop_clears_pwm(void)
{
TEST_BEGIN("stop -> direction=STOP, pwm=0");
(void)actuator_init();
(void)actuator_apply(ACTUATOR_LEFT, 80);
(void)actuator_stop(ACTUATOR_LEFT);
ActuatorStatus s = actuator_get_status(ACTUATOR_LEFT);
ASSERT_EQ(s.direction, ACT_DIR_STOP);
ASSERT_EQ(s.pwm_percent, 0);
TEST_END();
}
int main(void)
{
printf("== test_actuator_driver ==\n");
test_init();
test_apply_invalid_id();
test_apply_pwm_out_of_range();
test_apply_normal();
test_release_normal();
test_isr_samples_current();
test_overcurrent_cutoff_after_100ms();
test_overcurrent_below_window_no_cutoff();
test_overcurrent_blocks_subsequent_apply();
test_clamping_force_estimate();
test_stop_clears_pwm();
TEST_SUMMARY();
}