refactor: more work on error handling

This commit is contained in:
Kilian Bracher 2025-02-20 23:49:08 +01:00
parent 53a9597fe8
commit 522ef539be
Signed by: k.bracher
SSH Key Fingerprint: SHA256:mXpyZkK7RDiJ7qeHCKJX108woM0cl5TrCvNBJASu6lM
4 changed files with 28 additions and 57 deletions

View File

@ -7,14 +7,7 @@
#define ERROR_TIME_THRESH 150 // ms
typedef enum : uint16_t {
ADBMS_OK = 0x00, // same as STM32 HAL status
ADBMS_ERROR = 0x01, //
ADBMS_BUSY = 0x02, //
ADBMS_TIMEOUT = 0x03 //
} ADBMS_StatusTypeDef;
typedef enum : uint16_t {
ADBMS_NONE = 0,
ADBMS_NO_ERROR = 0,
ADBMS_OVERTEMP,
ADBMS_UNDERTEMP,
ADBMS_OVERVOLT,
@ -25,11 +18,11 @@ typedef enum : uint16_t {
ADBMS_INTERNAL_BMS_OVERTEMP,
ADBMS_INTERNAL_BMS_FAULT,
NUM_ERROR_KINDS
} ADBMS_ErrorKind;
} ADBMS_Status;
typedef struct {
ADBMS_StatusTypeDef status : 16;
ADBMS_ErrorKind error : 16; // zero if status is ADBMS_OK
ADBMS_Status status : 16;
int16_t bms_id : 16; // the BMS that caused the error, zero if no error, -1 if unknown BMS
} ADBMS_DetailedStatus;
typedef struct {

View File

@ -11,8 +11,8 @@
static_assert(sizeof(error_sources) * CHAR_BIT >= NUM_ERROR_KINDS,
"error_sources is too small to hold all error sources");
void set_error_source(ADBMS_ErrorKind source);
void clear_error_source(ADBMS_ErrorKind source);
void set_error_source(ADBMS_Status source);
void clear_error_source(ADBMS_Status source);
#endif //AMS_MASTER_CODE_ADBMS_ERROR_H

View File

@ -4,14 +4,14 @@
SlaveErrorData error_data[NUM_ERROR_KINDS] = {};
uint32_t error_sources = 0;
void set_error_source(ADBMS_ErrorKind source) {
void set_error_source(ADBMS_Status source) {
if (!(error_sources & (1 << source))) {
error_data[source].errors_since = HAL_GetTick();
}
error_sources |= (1 << source);
}
void clear_error_source(ADBMS_ErrorKind source) {
void clear_error_source(ADBMS_Status source) {
error_data[source].errors_since = 0;
error_sources &= ~(1 << source);
}

View File

@ -35,14 +35,14 @@ struct pollingTimes {
struct pollingTimes pollingTimes = {0, 0};
static constexpr ADBMS_DetailedStatus NO_ERROR = {ADBMS_OK, ADBMS_NONE};
static constexpr ADBMS_DetailedStatus NO_ERROR = {ADBMS_NO_ERROR};
ADBMS_DetailedStatus AMS_Init(SPI_HandleTypeDef* hspi) {
debug_log(LOG_LEVEL_INFO, "ADBMS6830B HAL - configured for %d controllers and %d cells per controller...", N_BMS,
numberofCells);
if (initAMS(hspi) != HAL_OK) {
debug_log(LOG_LEVEL_ERROR, "ADBMS6830B HAL - initialization failed");
return (ADBMS_DetailedStatus){ADBMS_ERROR, ADBMS_INTERNAL_BMS_FAULT};
return (ADBMS_DetailedStatus){ADBMS_INTERNAL_BMS_FAULT};
}
pollingTimes = (struct pollingTimes){HAL_GetTick(), HAL_GetTick()};
@ -51,13 +51,15 @@ ADBMS_DetailedStatus AMS_Init(SPI_HandleTypeDef* hspi) {
#define any(x) \
({ \
uint32_t any = false; \
static_assert(sizeof(any) * CHAR_BIT >= N_BMS, "any datatype needs to be larger!"); \
int first_match = -1; \
for (size_t __any_intern_i = 0; __any_intern_i < N_BMS; __any_intern_i++) { \
Cell_Module module = modules[__any_intern_i]; \
any |= ((x) ? 1 : 0) << __any_intern_i; \
if (x) { \
first_match = __any_intern_i; \
break; \
} \
} \
any; \
first_match; \
})
ADBMS_DetailedStatus AMS_Idle_Loop() {
@ -68,10 +70,11 @@ ADBMS_DetailedStatus AMS_Idle_Loop() {
packetChecksumFails += amsAuxAndStatusMeasurement(&modules);
if (any(module.status.SLEEP)) {
static int match = 0;
if ((match = any(module.status.SLEEP))) {
deviceSleeps++;
if (deviceSleeps > MAX_DEVICE_SLEEP) {
return (ADBMS_DetailedStatus){ADBMS_ERROR, ADBMS_INTERNAL_BMS_TIMEOUT};
return (ADBMS_DetailedStatus){ADBMS_INTERNAL_BMS_TIMEOUT, match};
} else {
amsReset();
}
@ -88,54 +91,29 @@ ADBMS_DetailedStatus AMS_Idle_Loop() {
// iteration.
amsClearFlag();
return (ADBMS_DetailedStatus){ADBMS_ERROR, ADBMS_INTERNAL_BMS_FAULT};
} else {
// clear_error_source(SEK_INTERNAL_BMS_FAULT);
return (ADBMS_DetailedStatus){ADBMS_INTERNAL_BMS_FAULT, match};
}
packetChecksumFails += amsCellMeasurement(&modules);
packetChecksumFails += amsCheckUnderOverVoltage(&modules);
if (packetChecksumFails > MAX_PACKET_CHECKSUM_FAILS) {
set_error_source(ADBMS_INTERNAL_BMS_CHECKSUM_FAIL);
return (ADBMS_DetailedStatus){ADBMS_INTERNAL_BMS_CHECKSUM_FAIL, -1};
}
// TODO: temperature measurement
bool overvolt = false;
bool undervolt = false;
for (size_t i = 0; i < numberofCells; i++) {
if (any(module.cellVoltages[i] < 2500)) {
undervolt = true;
if ((match = any(module.cellVoltages[i] < 2500))) {
error_data[ADBMS_UNDERVOLT].data[0] = i;
uint8_t* ptr = &error_data[ADBMS_UNDERVOLT].data[1];
// ftcan_marshal_unsigned(ptr, module.cellVoltages[i], 2);
} else if (any(module.cellVoltages[i] > 4200)) {
overvolt = true;
return (ADBMS_DetailedStatus){ADBMS_UNDERVOLT, match};
} else if ((match = any(module.cellVoltages[i] > 4200))) {
error_data[ADBMS_OVERVOLT].data[0] = i;
uint8_t* ptr = &error_data[ADBMS_OVERVOLT].data[1];
// ftcan_marshal_unsigned(ptr, module.cellVoltages[i], 2);
return (ADBMS_DetailedStatus){ADBMS_OVERVOLT, match};
}
}
if (any(module.internalDieTemp > 28000 || module.status.THSD)) { // TODO: change to correct value
// ftcan_marshal_unsigned(&error_data[SEK_INTERNAL_BMS_OVERTEMP].data[0], module.internalDieTemp, 2);
set_error_source(ADBMS_INTERNAL_BMS_OVERTEMP);
} else {
clear_error_source(ADBMS_INTERNAL_BMS_OVERTEMP);
}
if (overvolt) {
set_error_source(ADBMS_OVERVOLT);
} else {
clear_error_source(ADBMS_OVERVOLT);
}
if (undervolt) {
set_error_source(ADBMS_UNDERVOLT);
} else {
clear_error_source(ADBMS_UNDERVOLT);
// TODO: replace with the correct threshold for the internal die temperature
if ((match = any(module.internalDieTemp > 28000 || module.status.THSD))) {
return (ADBMS_DetailedStatus){ADBMS_INTERNAL_BMS_OVERTEMP, match};
}
mcuDelay(10);