1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
/**
 * @file actuator_driver.c
 * @brief Implementierung der EPB-Aktor-Ansteuerung.
 *
 * @arch SWA-003
 * @reqs SWE-006 SWE-013 SWE-014 SWE-015
 *
 * ASIL: B.
 */
#include "actuator_driver.h"

typedef struct {
    ActuatorStatus status;
    uint16_t       over_ms;  /* Milliseconds above current limit (counts in 1 kHz ISR) */
} ActuatorCtx;

static ActuatorCtx s_ctx[ACTUATOR_COUNT];

static bool is_valid_id(ActuatorId id)
{
    return (id == ACTUATOR_LEFT) || (id == ACTUATOR_RIGHT);
}

EpbStatus actuator_init(void)<--- The function 'actuator_init' is never used.
{
    for (uint8_t i = 0U; i < ACTUATOR_COUNT; ++i) {
        s_ctx[i].status.direction        = ACT_DIR_STOP;
        s_ctx[i].status.pwm_percent      = 0U;
        s_ctx[i].status.current_ma       = 0U;
        s_ctx[i].status.peak_current_ma  = 0U;
        s_ctx[i].status.clamping_force_n = 0U;
        s_ctx[i].status.overcurrent      = false;
        s_ctx[i].status.last_error       = EPB_OK;
        s_ctx[i].over_ms                 = 0U;
    }
    return EPB_OK;
}

EpbStatus actuator_apply(ActuatorId id, uint8_t pwm_percent)
{
    if (!is_valid_id(id)) {
        return EPB_EINVAL;
    }
    if (pwm_percent > 100U) {
        return EPB_EINVAL;
    }
    if (s_ctx[id].status.overcurrent) {
        return EPB_EOVERCURRENT;
    }
    s_ctx[id].status.direction       = ACT_DIR_APPLY;
    s_ctx[id].status.pwm_percent     = pwm_percent;
    s_ctx[id].status.peak_current_ma = 0U;
    return EPB_OK;
}

EpbStatus actuator_release(ActuatorId id, uint8_t pwm_percent)
{
    if (!is_valid_id(id)) {
        return EPB_EINVAL;
    }
    if (pwm_percent > 100U) {
        return EPB_EINVAL;
    }
    if (s_ctx[id].status.overcurrent) {
        return EPB_EOVERCURRENT;
    }
    s_ctx[id].status.direction   = ACT_DIR_RELEASE;
    s_ctx[id].status.pwm_percent = pwm_percent;
    return EPB_OK;
}

EpbStatus actuator_stop(ActuatorId id)
{
    if (!is_valid_id(id)) {
        return EPB_EINVAL;
    }
    s_ctx[id].status.direction   = ACT_DIR_STOP;
    s_ctx[id].status.pwm_percent = 0U;
    return EPB_OK;
}

ActuatorStatus actuator_get_status(ActuatorId id)<--- The function 'actuator_get_status' is never used.
{
    if (!is_valid_id(id)) {
        ActuatorStatus empty = {0};
        empty.last_error = EPB_EINVAL;
        return empty;
    }
    return s_ctx[id].status;
}

void actuator_isr_1khz(ActuatorId id, uint16_t current_sample_ma)<--- The function 'actuator_isr_1khz' is never used.
{
    if (!is_valid_id(id)) {
        return;
    }

    s_ctx[id].status.current_ma = current_sample_ma;
    if (current_sample_ma > s_ctx[id].status.peak_current_ma) {
        s_ctx[id].status.peak_current_ma = current_sample_ma;
    }

    /* SWE-014: Overcurrent cutoff at > 8 A for > 100 ms */
    if (current_sample_ma > ACT_OVERCURRENT_LIMIT_MA) {
        if (s_ctx[id].over_ms < UINT16_MAX) {
            ++s_ctx[id].over_ms;
        }
        if (s_ctx[id].over_ms >= ACT_OVERCURRENT_WINDOW_MS) {
            s_ctx[id].status.direction   = ACT_DIR_STOP;
            s_ctx[id].status.pwm_percent = 0U;
            s_ctx[id].status.overcurrent = true;
            s_ctx[id].status.last_error  = EPB_EOVERCURRENT;
        }
    } else {
        s_ctx[id].over_ms = 0U;
    }

    /* SWE-015: Estimate clamping force from peak current (only on apply). */
    if (s_ctx[id].status.direction == ACT_DIR_APPLY) {
        const uint32_t force = ((uint32_t)s_ctx[id].status.peak_current_ma
                                 * ACT_FORCE_PER_AMP_N) / 1000U;
        s_ctx[id].status.clamping_force_n =
            (force > UINT16_MAX) ? UINT16_MAX : (uint16_t)force;
    }
}