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:
@@ -0,0 +1,240 @@
|
||||
/**
|
||||
* @file test_apply_controller.c
|
||||
* @brief Unit-Tests fuer den Apply-Controller (ASIL-D Kern).
|
||||
*
|
||||
* @reqs SWE-001 SWE-002 SWE-003 SWE-004
|
||||
* @arch SWA-002
|
||||
*/
|
||||
#include "../unit_test_framework.h"
|
||||
#include "../../src/apply_controller.h"
|
||||
#include "../../src/actuator_driver.h"
|
||||
|
||||
TestStats g_test_stats = {0, 0};
|
||||
|
||||
static ApplyInputs make_idle_inputs(void)
|
||||
{
|
||||
ApplyInputs in = {0};
|
||||
in.sw_state = SWITCH_NEUTRAL;
|
||||
in.standstill = true;
|
||||
in.engine_running = true;
|
||||
in.brake_pedal_pressed = true;
|
||||
in.gear_engaged = true;
|
||||
in.safety_apply_request = false;
|
||||
in.left_force_n = 0;
|
||||
in.right_force_n = 0;
|
||||
return in;
|
||||
}
|
||||
|
||||
static void apply_full_cycle_until_state(ApplyInputs* in, EpbState target, int max_steps)
|
||||
{
|
||||
for (int i = 0; i < max_steps; ++i) {
|
||||
apply_ctrl_step_50ms(in);
|
||||
if (apply_ctrl_get_state() == target) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void test_init(void)
|
||||
{
|
||||
TEST_BEGIN("init -> RELEASED");
|
||||
(void)actuator_init();
|
||||
ASSERT_EQ(apply_ctrl_init(), EPB_OK);
|
||||
ASSERT_EQ(apply_ctrl_get_state(), EPB_STATE_RELEASED);
|
||||
TEST_END();
|
||||
}
|
||||
|
||||
static void test_null_input(void)
|
||||
{
|
||||
TEST_BEGIN("step_50ms(NULL) -> last_error=EINVAL");
|
||||
(void)actuator_init();
|
||||
(void)apply_ctrl_init();
|
||||
apply_ctrl_step_50ms(NULL);
|
||||
ASSERT_EQ(apply_ctrl_last_error(), EPB_EINVAL);
|
||||
TEST_END();
|
||||
}
|
||||
|
||||
static void test_apply_request_starts_applying(void)
|
||||
{
|
||||
TEST_BEGIN("Apply-Request bei Stillstand -> APPLYING");
|
||||
(void)actuator_init();
|
||||
(void)apply_ctrl_init();
|
||||
ApplyInputs in = make_idle_inputs();
|
||||
in.sw_state = SWITCH_APPLY;
|
||||
apply_ctrl_step_50ms(&in);
|
||||
ASSERT_EQ(apply_ctrl_get_state(), EPB_STATE_APPLYING);
|
||||
TEST_END();
|
||||
}
|
||||
|
||||
static void test_no_apply_without_standstill(void)
|
||||
{
|
||||
TEST_BEGIN("Apply-Request ohne Stillstand wird ignoriert");
|
||||
(void)actuator_init();
|
||||
(void)apply_ctrl_init();
|
||||
ApplyInputs in = make_idle_inputs();
|
||||
in.standstill = false;
|
||||
in.sw_state = SWITCH_APPLY;
|
||||
apply_ctrl_step_50ms(&in);
|
||||
ASSERT_EQ(apply_ctrl_get_state(), EPB_STATE_RELEASED);
|
||||
TEST_END();
|
||||
}
|
||||
|
||||
static void test_applying_reaches_applied_on_target_force(void)
|
||||
{
|
||||
TEST_BEGIN("APPLYING -> APPLIED wenn beide Klemmkraefte >= Target");
|
||||
(void)actuator_init();
|
||||
(void)apply_ctrl_init();
|
||||
ApplyInputs in = make_idle_inputs();
|
||||
in.sw_state = SWITCH_APPLY;
|
||||
apply_ctrl_step_50ms(&in); /* -> APPLYING */
|
||||
in.sw_state = SWITCH_NEUTRAL;
|
||||
in.left_force_n = 12000;
|
||||
in.right_force_n = 12000;
|
||||
apply_ctrl_step_50ms(&in);
|
||||
ASSERT_EQ(apply_ctrl_get_state(), EPB_STATE_APPLIED);
|
||||
TEST_END();
|
||||
}
|
||||
|
||||
static void test_applying_timeout_to_error(void)
|
||||
{
|
||||
TEST_BEGIN("APPLYING-Timeout (>30 Steps) -> ERROR");
|
||||
(void)actuator_init();
|
||||
(void)apply_ctrl_init();
|
||||
ApplyInputs in = make_idle_inputs();
|
||||
in.sw_state = SWITCH_APPLY;
|
||||
apply_ctrl_step_50ms(&in); /* -> APPLYING */
|
||||
in.sw_state = SWITCH_NEUTRAL;
|
||||
/* Klemmkraefte bleiben bei 0 -> Timeout nach 30 Steps */
|
||||
apply_full_cycle_until_state(&in, EPB_STATE_ERROR, 35);
|
||||
ASSERT_EQ(apply_ctrl_get_state(), EPB_STATE_ERROR);
|
||||
ASSERT_EQ(apply_ctrl_last_error(), EPB_ETIMEOUT);
|
||||
TEST_END();
|
||||
}
|
||||
|
||||
static void test_applied_holds_force(void)
|
||||
{
|
||||
TEST_BEGIN("APPLIED haelt Klemmkraft (SWE-001)");
|
||||
(void)actuator_init();
|
||||
(void)apply_ctrl_init();
|
||||
ApplyInputs in = make_idle_inputs();
|
||||
in.sw_state = SWITCH_APPLY;
|
||||
apply_ctrl_step_50ms(&in);
|
||||
in.sw_state = SWITCH_NEUTRAL;
|
||||
in.left_force_n = 12000;
|
||||
in.right_force_n = 12000;
|
||||
apply_ctrl_step_50ms(&in); /* -> APPLIED */
|
||||
|
||||
/* Klemmkraft sinkt auf 10000 (unter Toleranz-Schwelle 10800) */
|
||||
in.left_force_n = 10000;
|
||||
in.right_force_n = 10000;
|
||||
apply_ctrl_step_50ms(&in);
|
||||
/* Apply-Controller muss nachregeln -> APPLYING */
|
||||
ASSERT_EQ(apply_ctrl_get_state(), EPB_STATE_APPLYING);
|
||||
TEST_END();
|
||||
}
|
||||
|
||||
static void test_release_requires_preconditions(void)
|
||||
{
|
||||
TEST_BEGIN("Release ohne Engine wird abgelehnt");
|
||||
(void)actuator_init();
|
||||
(void)apply_ctrl_init();
|
||||
ApplyInputs in = make_idle_inputs();
|
||||
in.sw_state = SWITCH_APPLY;
|
||||
apply_ctrl_step_50ms(&in);
|
||||
in.sw_state = SWITCH_NEUTRAL;
|
||||
in.left_force_n = 12000;
|
||||
in.right_force_n = 12000;
|
||||
apply_ctrl_step_50ms(&in); /* -> APPLIED */
|
||||
|
||||
in.sw_state = SWITCH_RELEASE;
|
||||
in.engine_running = false;
|
||||
apply_ctrl_step_50ms(&in);
|
||||
ASSERT_EQ(apply_ctrl_get_state(), EPB_STATE_APPLIED);
|
||||
TEST_END();
|
||||
}
|
||||
|
||||
static void test_release_with_preconditions(void)
|
||||
{
|
||||
TEST_BEGIN("Release mit allen Voraussetzungen -> RELEASING -> RELEASED");
|
||||
(void)actuator_init();
|
||||
(void)apply_ctrl_init();
|
||||
ApplyInputs in = make_idle_inputs();
|
||||
in.sw_state = SWITCH_APPLY;
|
||||
apply_ctrl_step_50ms(&in);
|
||||
in.sw_state = SWITCH_NEUTRAL;
|
||||
in.left_force_n = 12000;
|
||||
in.right_force_n = 12000;
|
||||
apply_ctrl_step_50ms(&in); /* APPLIED */
|
||||
|
||||
in.sw_state = SWITCH_RELEASE;
|
||||
apply_ctrl_step_50ms(&in);
|
||||
ASSERT_EQ(apply_ctrl_get_state(), EPB_STATE_RELEASING);
|
||||
|
||||
in.sw_state = SWITCH_NEUTRAL;
|
||||
in.left_force_n = 0;
|
||||
in.right_force_n = 0;
|
||||
apply_ctrl_step_50ms(&in);
|
||||
ASSERT_EQ(apply_ctrl_get_state(), EPB_STATE_RELEASED);
|
||||
TEST_END();
|
||||
}
|
||||
|
||||
static void test_safety_apply_request(void)
|
||||
{
|
||||
TEST_BEGIN("Safety-Manager Apply-Request (Hill-Hold/Auto-Apply)");
|
||||
(void)actuator_init();
|
||||
(void)apply_ctrl_init();
|
||||
ApplyInputs in = make_idle_inputs();
|
||||
in.sw_state = SWITCH_NEUTRAL;
|
||||
in.safety_apply_request = true;
|
||||
apply_ctrl_step_50ms(&in);
|
||||
ASSERT_EQ(apply_ctrl_get_state(), EPB_STATE_APPLYING);
|
||||
TEST_END();
|
||||
}
|
||||
|
||||
static void test_watchdog_alive_counter(void)
|
||||
{
|
||||
TEST_BEGIN("Step-Counter steigt monoton (SWE-002 Watchdog-Alive)");
|
||||
(void)actuator_init();
|
||||
(void)apply_ctrl_init();
|
||||
ApplyInputs in = make_idle_inputs();
|
||||
uint32_t before = apply_ctrl_get_step_count();
|
||||
apply_ctrl_step_50ms(&in);
|
||||
apply_ctrl_step_50ms(&in);
|
||||
apply_ctrl_step_50ms(&in);
|
||||
ASSERT_EQ(apply_ctrl_get_step_count(), before + 3);
|
||||
TEST_END();
|
||||
}
|
||||
|
||||
static void test_error_state_recoverable(void)
|
||||
{
|
||||
TEST_BEGIN("ERROR -> RELEASED bei neutralem Switch");
|
||||
(void)actuator_init();
|
||||
(void)apply_ctrl_init();
|
||||
ApplyInputs in = make_idle_inputs();
|
||||
in.sw_state = SWITCH_APPLY;
|
||||
apply_ctrl_step_50ms(&in);
|
||||
in.sw_state = SWITCH_NEUTRAL;
|
||||
apply_full_cycle_until_state(&in, EPB_STATE_ERROR, 35);
|
||||
ASSERT_EQ(apply_ctrl_get_state(), EPB_STATE_ERROR);
|
||||
apply_ctrl_step_50ms(&in);
|
||||
ASSERT_EQ(apply_ctrl_get_state(), EPB_STATE_RELEASED);
|
||||
TEST_END();
|
||||
}
|
||||
|
||||
int main(void)
|
||||
{
|
||||
printf("== test_apply_controller ==\n");
|
||||
test_init();
|
||||
test_null_input();
|
||||
test_apply_request_starts_applying();
|
||||
test_no_apply_without_standstill();
|
||||
test_applying_reaches_applied_on_target_force();
|
||||
test_applying_timeout_to_error();
|
||||
test_applied_holds_force();
|
||||
test_release_requires_preconditions();
|
||||
test_release_with_preconditions();
|
||||
test_safety_apply_request();
|
||||
test_watchdog_alive_counter();
|
||||
test_error_state_recoverable();
|
||||
TEST_SUMMARY();
|
||||
}
|
||||
Reference in New Issue
Block a user