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,153 @@
|
||||
/**
|
||||
* @file apply_controller.c
|
||||
* @brief Apply/Hold/Release State Machine.
|
||||
*
|
||||
* @arch SWA-002
|
||||
* @reqs SWE-001 SWE-002 SWE-003 SWE-004
|
||||
*
|
||||
* ASIL: D. Diese Komponente ist die sicherheitskritische Kernlogik.
|
||||
* Aenderungen erfordern Technical Review mit 2 Approvals.
|
||||
*/
|
||||
#include <stddef.h>
|
||||
|
||||
#include "apply_controller.h"
|
||||
#include "actuator_driver.h"
|
||||
|
||||
typedef struct {
|
||||
EpbState state;
|
||||
uint8_t step_in_state; /* 50ms-Ticks im aktuellen State */
|
||||
EpbStatus last_error;
|
||||
uint32_t step_count; /* Watchdog-Alive-Counter */
|
||||
} ApplyCtx;
|
||||
|
||||
static ApplyCtx s_ctx;
|
||||
|
||||
static void enter_state(EpbState new_state)
|
||||
{
|
||||
s_ctx.state = new_state;
|
||||
s_ctx.step_in_state = 0U;
|
||||
}
|
||||
|
||||
static bool release_preconditions_ok(const ApplyInputs* in)
|
||||
{
|
||||
/* @reqs SWE-005 (Release-Voraussetzungen) — hier konsumiert */
|
||||
return in->engine_running
|
||||
&& in->brake_pedal_pressed
|
||||
&& in->gear_engaged;
|
||||
}
|
||||
|
||||
static bool apply_request_present(const ApplyInputs* in)
|
||||
{
|
||||
return (in->sw_state == SWITCH_APPLY) || in->safety_apply_request;
|
||||
}
|
||||
|
||||
static bool release_request_present(const ApplyInputs* in)
|
||||
{
|
||||
return in->sw_state == SWITCH_RELEASE;
|
||||
}
|
||||
|
||||
static uint16_t min_force(const ApplyInputs* in)
|
||||
{
|
||||
return (in->left_force_n < in->right_force_n)
|
||||
? in->left_force_n : in->right_force_n;
|
||||
}
|
||||
|
||||
EpbStatus apply_ctrl_init(void)
|
||||
{
|
||||
s_ctx.state = EPB_STATE_RELEASED;
|
||||
s_ctx.step_in_state = 0U;
|
||||
s_ctx.last_error = EPB_OK;
|
||||
s_ctx.step_count = 0U;
|
||||
return EPB_OK;
|
||||
}
|
||||
|
||||
void apply_ctrl_step_50ms(const ApplyInputs* in)
|
||||
{
|
||||
if (in == NULL) {
|
||||
s_ctx.last_error = EPB_EINVAL;
|
||||
return;
|
||||
}
|
||||
|
||||
/* SWE-002: Watchdog-Alive-Counter erhoehen */
|
||||
++s_ctx.step_count;
|
||||
|
||||
if (s_ctx.step_in_state < UINT8_MAX) {
|
||||
++s_ctx.step_in_state;
|
||||
}
|
||||
|
||||
switch (s_ctx.state) {
|
||||
case EPB_STATE_RELEASED:
|
||||
if (apply_request_present(in) && in->standstill) {
|
||||
(void)actuator_apply(ACTUATOR_LEFT, 80U);
|
||||
(void)actuator_apply(ACTUATOR_RIGHT, 80U);
|
||||
enter_state(EPB_STATE_APPLYING);
|
||||
}
|
||||
break;
|
||||
|
||||
case EPB_STATE_APPLYING:
|
||||
/* SWE-004: Klemmkraft-Erreichen pruefen */
|
||||
if (min_force(in) >= APPLY_TARGET_FORCE_N) {
|
||||
(void)actuator_stop(ACTUATOR_LEFT);
|
||||
(void)actuator_stop(ACTUATOR_RIGHT);
|
||||
enter_state(EPB_STATE_APPLIED);
|
||||
} else if (s_ctx.step_in_state >= APPLY_TIMEOUT_50MS) {
|
||||
s_ctx.last_error = EPB_ETIMEOUT;
|
||||
(void)actuator_stop(ACTUATOR_LEFT);
|
||||
(void)actuator_stop(ACTUATOR_RIGHT);
|
||||
enter_state(EPB_STATE_ERROR);
|
||||
}
|
||||
break;
|
||||
|
||||
case EPB_STATE_APPLIED:
|
||||
/* SWE-001: Klemmkraft halten — bei Unterschreitung nachregeln */
|
||||
if (min_force(in) < (APPLY_TARGET_FORCE_N - HOLD_TOLERANCE_N)) {
|
||||
(void)actuator_apply(ACTUATOR_LEFT, 60U);
|
||||
(void)actuator_apply(ACTUATOR_RIGHT, 60U);
|
||||
enter_state(EPB_STATE_APPLYING);
|
||||
break;
|
||||
}
|
||||
if (release_request_present(in) && release_preconditions_ok(in)) {
|
||||
(void)actuator_release(ACTUATOR_LEFT, 80U);
|
||||
(void)actuator_release(ACTUATOR_RIGHT, 80U);
|
||||
enter_state(EPB_STATE_RELEASING);
|
||||
}
|
||||
break;
|
||||
|
||||
case EPB_STATE_RELEASING:
|
||||
if (min_force(in) < HOLD_TOLERANCE_N) {
|
||||
(void)actuator_stop(ACTUATOR_LEFT);
|
||||
(void)actuator_stop(ACTUATOR_RIGHT);
|
||||
enter_state(EPB_STATE_RELEASED);
|
||||
} else if (s_ctx.step_in_state >= (APPLY_TIMEOUT_50MS - 6U)) {
|
||||
s_ctx.last_error = EPB_ETIMEOUT;
|
||||
(void)actuator_stop(ACTUATOR_LEFT);
|
||||
(void)actuator_stop(ACTUATOR_RIGHT);
|
||||
enter_state(EPB_STATE_ERROR);
|
||||
}
|
||||
break;
|
||||
|
||||
case EPB_STATE_ERROR:
|
||||
default:
|
||||
/* Auf Reset warten; sicherer Zustand ist Apply, also kein Release */
|
||||
if (!apply_request_present(in) && !release_request_present(in)) {
|
||||
s_ctx.last_error = EPB_OK;
|
||||
enter_state(EPB_STATE_RELEASED);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
EpbState apply_ctrl_get_state(void)
|
||||
{
|
||||
return s_ctx.state;
|
||||
}
|
||||
|
||||
EpbStatus apply_ctrl_last_error(void)
|
||||
{
|
||||
return s_ctx.last_error;
|
||||
}
|
||||
|
||||
uint32_t apply_ctrl_get_step_count(void)
|
||||
{
|
||||
return s_ctx.step_count;
|
||||
}
|
||||
Reference in New Issue
Block a user