refactor: start fixup for error handling
This commit is contained in:
parent
f3fae2686f
commit
53a9597fe8
|
@ -1,27 +1,36 @@
|
||||||
#ifndef ADBMS_DRIVER_H
|
#ifndef ADBMS_DRIVER_H
|
||||||
#define ADBMS_DRIVER_H
|
#define ADBMS_DRIVER_H
|
||||||
|
|
||||||
#include <stdint.h>
|
|
||||||
#include "stm32h7xx_hal.h"
|
#include "stm32h7xx_hal.h"
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
#define ERROR_TIME_THRESH 150 // ms
|
#define ERROR_TIME_THRESH 150 // ms
|
||||||
|
|
||||||
typedef enum {
|
typedef enum : uint16_t {
|
||||||
SEK_OVERTEMP,
|
ADBMS_OK = 0x00, // same as STM32 HAL status
|
||||||
SEK_UNDERTEMP,
|
ADBMS_ERROR = 0x01, //
|
||||||
SEK_OVERVOLT,
|
ADBMS_BUSY = 0x02, //
|
||||||
SEK_UNDERVOLT,
|
ADBMS_TIMEOUT = 0x03 //
|
||||||
SEK_TOO_FEW_TEMPS,
|
} ADBMS_StatusTypeDef;
|
||||||
SEK_OPENWIRE,
|
|
||||||
SEK_EEPROM_ERR,
|
typedef enum : uint16_t {
|
||||||
SEK_INTERNAL_BMS_TIMEOUT,
|
ADBMS_NONE = 0,
|
||||||
SEK_INTERNAL_BMS_CHECKSUM_FAIL,
|
ADBMS_OVERTEMP,
|
||||||
SEK_INTERNAL_BMS_OVERTEMP,
|
ADBMS_UNDERTEMP,
|
||||||
SEK_INTERNAL_BMS_FAULT,
|
ADBMS_OVERVOLT,
|
||||||
SEK_1WIRE_ERR,
|
ADBMS_UNDERVOLT,
|
||||||
SEK_DS18B20_TIMEOUT,
|
ADBMS_OPENWIRE,
|
||||||
|
ADBMS_INTERNAL_BMS_TIMEOUT,
|
||||||
|
ADBMS_INTERNAL_BMS_CHECKSUM_FAIL,
|
||||||
|
ADBMS_INTERNAL_BMS_OVERTEMP,
|
||||||
|
ADBMS_INTERNAL_BMS_FAULT,
|
||||||
NUM_ERROR_KINDS
|
NUM_ERROR_KINDS
|
||||||
} SlaveErrorKind;
|
} ADBMS_ErrorKind;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
ADBMS_StatusTypeDef status : 16;
|
||||||
|
ADBMS_ErrorKind error : 16; // zero if status is ADBMS_OK
|
||||||
|
} ADBMS_DetailedStatus;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
uint8_t data[4];
|
uint8_t data[4];
|
||||||
|
@ -75,10 +84,9 @@ typedef struct {
|
||||||
extern uint32_t error_sources; // Bitfield of error sources
|
extern uint32_t error_sources; // Bitfield of error sources
|
||||||
extern SlaveErrorData error_data[NUM_ERROR_KINDS];
|
extern SlaveErrorData error_data[NUM_ERROR_KINDS];
|
||||||
|
|
||||||
[[gnu::nonnull]]
|
[[gnu::nonnull]] ADBMS_DetailedStatus AMS_Init(SPI_HandleTypeDef* hspi);
|
||||||
void AMS_Init(SPI_HandleTypeDef* hspi);
|
|
||||||
|
|
||||||
uint8_t AMS_Idle_Loop();
|
ADBMS_DetailedStatus AMS_Idle_Loop();
|
||||||
|
|
||||||
#undef MAXIMUM_CELL_VOLTAGES
|
#undef MAXIMUM_CELL_VOLTAGES
|
||||||
#undef MAXIMUM_AUX_VOLTAGES
|
#undef MAXIMUM_AUX_VOLTAGES
|
||||||
|
|
|
@ -11,8 +11,8 @@
|
||||||
static_assert(sizeof(error_sources) * CHAR_BIT >= NUM_ERROR_KINDS,
|
static_assert(sizeof(error_sources) * CHAR_BIT >= NUM_ERROR_KINDS,
|
||||||
"error_sources is too small to hold all error sources");
|
"error_sources is too small to hold all error sources");
|
||||||
|
|
||||||
void set_error_source(SlaveErrorKind source);
|
void set_error_source(ADBMS_ErrorKind source);
|
||||||
void clear_error_source(SlaveErrorKind source);
|
void clear_error_source(ADBMS_ErrorKind source);
|
||||||
|
|
||||||
|
|
||||||
#endif //AMS_MASTER_CODE_ADBMS_ERROR_H
|
#endif //AMS_MASTER_CODE_ADBMS_ERROR_H
|
||||||
|
|
|
@ -4,14 +4,14 @@
|
||||||
SlaveErrorData error_data[NUM_ERROR_KINDS] = {};
|
SlaveErrorData error_data[NUM_ERROR_KINDS] = {};
|
||||||
uint32_t error_sources = 0;
|
uint32_t error_sources = 0;
|
||||||
|
|
||||||
void set_error_source(SlaveErrorKind source) {
|
void set_error_source(ADBMS_ErrorKind source) {
|
||||||
if (!(error_sources & (1 << source))) {
|
if (!(error_sources & (1 << source))) {
|
||||||
error_data[source].errors_since = HAL_GetTick();
|
error_data[source].errors_since = HAL_GetTick();
|
||||||
}
|
}
|
||||||
error_sources |= (1 << source);
|
error_sources |= (1 << source);
|
||||||
}
|
}
|
||||||
|
|
||||||
void clear_error_source(SlaveErrorKind source) {
|
void clear_error_source(ADBMS_ErrorKind source) {
|
||||||
error_data[source].errors_since = 0;
|
error_data[source].errors_since = 0;
|
||||||
error_sources &= ~(1 << source);
|
error_sources &= ~(1 << source);
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,10 +7,10 @@
|
||||||
|
|
||||||
#include "ADBMS_HighLevel.h"
|
#include "ADBMS_HighLevel.h"
|
||||||
#include "ADBMS_Abstraction.h"
|
#include "ADBMS_Abstraction.h"
|
||||||
|
#include "ADBMS_Driver.h"
|
||||||
|
#include "ADBMS_Error.h"
|
||||||
#include "ADBMS_LL_Driver.h"
|
#include "ADBMS_LL_Driver.h"
|
||||||
#include "config_ADBMS6830.h"
|
#include "config_ADBMS6830.h"
|
||||||
#include "ADBMS_Error.h"
|
|
||||||
#include "ADBMS_Driver.h"
|
|
||||||
#include "stm32h7xx_hal.h"
|
#include "stm32h7xx_hal.h"
|
||||||
#include "swo_log.h"
|
#include "swo_log.h"
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
@ -35,26 +35,32 @@ struct pollingTimes {
|
||||||
|
|
||||||
struct pollingTimes pollingTimes = {0, 0};
|
struct pollingTimes pollingTimes = {0, 0};
|
||||||
|
|
||||||
void AMS_Init(SPI_HandleTypeDef* hspi) {
|
static constexpr ADBMS_DetailedStatus NO_ERROR = {ADBMS_OK, ADBMS_NONE};
|
||||||
debug_log(LOG_LEVEL_INFO, "ADBMS6830B HAL - configured for %d controllers and %d cells per controller...", N_BMS, numberofCells);
|
|
||||||
|
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) {
|
if (initAMS(hspi) != HAL_OK) {
|
||||||
debug_log(LOG_LEVEL_ERROR, "ADBMS6830B HAL - initialization failed");
|
debug_log(LOG_LEVEL_ERROR, "ADBMS6830B HAL - initialization failed");
|
||||||
|
return (ADBMS_DetailedStatus){ADBMS_ERROR, ADBMS_INTERNAL_BMS_FAULT};
|
||||||
}
|
}
|
||||||
|
|
||||||
pollingTimes = (struct pollingTimes){HAL_GetTick(), HAL_GetTick()};
|
pollingTimes = (struct pollingTimes){HAL_GetTick(), HAL_GetTick()};
|
||||||
|
return NO_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
#define any(x) ({ \
|
#define any(x) \
|
||||||
bool any = false; \
|
({ \
|
||||||
|
uint32_t any = false; \
|
||||||
|
static_assert(sizeof(any) * CHAR_BIT >= N_BMS, "any datatype needs to be larger!"); \
|
||||||
for (size_t __any_intern_i = 0; __any_intern_i < N_BMS; __any_intern_i++) { \
|
for (size_t __any_intern_i = 0; __any_intern_i < N_BMS; __any_intern_i++) { \
|
||||||
Cell_Module module = modules[__any_intern_i]; \
|
Cell_Module module = modules[__any_intern_i]; \
|
||||||
any |= (x); \
|
any |= ((x) ? 1 : 0) << __any_intern_i; \
|
||||||
} \
|
} \
|
||||||
any; \
|
any; \
|
||||||
})
|
})
|
||||||
|
|
||||||
|
ADBMS_DetailedStatus AMS_Idle_Loop() {
|
||||||
uint8_t AMS_Idle_Loop() {
|
|
||||||
if (!amsWakeUp()) {
|
if (!amsWakeUp()) {
|
||||||
// error_data.data_kind = SEK_INTERNAL_BMS_TIMEOUT; //we don't receive data for the wakeup command
|
// error_data.data_kind = SEK_INTERNAL_BMS_TIMEOUT; //we don't receive data for the wakeup command
|
||||||
// set_error_source(ERROR_SOURCE_INTERNAL); //so we can't tell if we timed out
|
// set_error_source(ERROR_SOURCE_INTERNAL); //so we can't tell if we timed out
|
||||||
|
@ -65,7 +71,7 @@ uint8_t AMS_Idle_Loop() {
|
||||||
if (any(module.status.SLEEP)) {
|
if (any(module.status.SLEEP)) {
|
||||||
deviceSleeps++;
|
deviceSleeps++;
|
||||||
if (deviceSleeps > MAX_DEVICE_SLEEP) {
|
if (deviceSleeps > MAX_DEVICE_SLEEP) {
|
||||||
set_error_source(SEK_INTERNAL_BMS_TIMEOUT);
|
return (ADBMS_DetailedStatus){ADBMS_ERROR, ADBMS_INTERNAL_BMS_TIMEOUT};
|
||||||
} else {
|
} else {
|
||||||
amsReset();
|
amsReset();
|
||||||
}
|
}
|
||||||
|
@ -74,26 +80,24 @@ uint8_t AMS_Idle_Loop() {
|
||||||
if (any(module.status.CS_FLT || module.status.SPIFLT || module.status.CMED || module.status.SMED ||
|
if (any(module.status.CS_FLT || module.status.SPIFLT || module.status.CMED || module.status.SMED ||
|
||||||
module.status.VDE || module.status.VDEL || module.status.OSCCHK || module.status.TMODCHK)) {
|
module.status.VDE || module.status.VDEL || module.status.OSCCHK || module.status.TMODCHK)) {
|
||||||
|
|
||||||
// TODO: handle errors
|
const uint8_t* ptr = ((uint8_t*)&modules[0].status) + 4; // skip conversion counter
|
||||||
|
error_data[ADBMS_INTERNAL_BMS_FAULT].data[2] = ptr[1];
|
||||||
// ftcan_marshal_unsigned(&error_data[SEK_INTERNAL_BMS_FAULT].data[0], module.status.CS_FLT, 2);
|
error_data[ADBMS_INTERNAL_BMS_FAULT].data[3] = ptr[0];
|
||||||
/* const uint8_t* ptr = ((uint8_t*)&modules.status) + 4; //skip conversion counter
|
|
||||||
error_data[SEK_INTERNAL_BMS_FAULT].data[2] = ptr[1];
|
|
||||||
error_data[SEK_INTERNAL_BMS_FAULT].data[3] = ptr[0];
|
|
||||||
set_error_source(SEK_INTERNAL_BMS_FAULT); */
|
|
||||||
|
|
||||||
// Fault bits are latched -- clear them so we can check again next
|
// Fault bits are latched -- clear them so we can check again next
|
||||||
// iteration.
|
// iteration.
|
||||||
amsClearFlag();
|
amsClearFlag();
|
||||||
|
|
||||||
|
return (ADBMS_DetailedStatus){ADBMS_ERROR, ADBMS_INTERNAL_BMS_FAULT};
|
||||||
} else {
|
} else {
|
||||||
clear_error_source(SEK_INTERNAL_BMS_FAULT);
|
// clear_error_source(SEK_INTERNAL_BMS_FAULT);
|
||||||
}
|
}
|
||||||
|
|
||||||
packetChecksumFails += amsCellMeasurement(&modules);
|
packetChecksumFails += amsCellMeasurement(&modules);
|
||||||
packetChecksumFails += amsCheckUnderOverVoltage(&modules);
|
packetChecksumFails += amsCheckUnderOverVoltage(&modules);
|
||||||
|
|
||||||
if (packetChecksumFails > MAX_PACKET_CHECKSUM_FAILS) {
|
if (packetChecksumFails > MAX_PACKET_CHECKSUM_FAILS) {
|
||||||
set_error_source(SEK_INTERNAL_BMS_CHECKSUM_FAIL);
|
set_error_source(ADBMS_INTERNAL_BMS_CHECKSUM_FAIL);
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: temperature measurement
|
// TODO: temperature measurement
|
||||||
|
@ -103,13 +107,13 @@ uint8_t AMS_Idle_Loop() {
|
||||||
for (size_t i = 0; i < numberofCells; i++) {
|
for (size_t i = 0; i < numberofCells; i++) {
|
||||||
if (any(module.cellVoltages[i] < 2500)) {
|
if (any(module.cellVoltages[i] < 2500)) {
|
||||||
undervolt = true;
|
undervolt = true;
|
||||||
error_data[SEK_UNDERVOLT].data[0] = i;
|
error_data[ADBMS_UNDERVOLT].data[0] = i;
|
||||||
uint8_t* ptr = &error_data[SEK_UNDERVOLT].data[1];
|
uint8_t* ptr = &error_data[ADBMS_UNDERVOLT].data[1];
|
||||||
// ftcan_marshal_unsigned(ptr, module.cellVoltages[i], 2);
|
// ftcan_marshal_unsigned(ptr, module.cellVoltages[i], 2);
|
||||||
} else if (any(module.cellVoltages[i] > 4200)) {
|
} else if (any(module.cellVoltages[i] > 4200)) {
|
||||||
overvolt = true;
|
overvolt = true;
|
||||||
error_data[SEK_OVERVOLT].data[0] = i;
|
error_data[ADBMS_OVERVOLT].data[0] = i;
|
||||||
uint8_t* ptr = &error_data[SEK_OVERVOLT].data[1];
|
uint8_t* ptr = &error_data[ADBMS_OVERVOLT].data[1];
|
||||||
// ftcan_marshal_unsigned(ptr, module.cellVoltages[i], 2);
|
// ftcan_marshal_unsigned(ptr, module.cellVoltages[i], 2);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -117,24 +121,24 @@ uint8_t AMS_Idle_Loop() {
|
||||||
if (any(module.internalDieTemp > 28000 || module.status.THSD)) { // TODO: change to correct value
|
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);
|
// ftcan_marshal_unsigned(&error_data[SEK_INTERNAL_BMS_OVERTEMP].data[0], module.internalDieTemp, 2);
|
||||||
|
|
||||||
set_error_source(SEK_INTERNAL_BMS_OVERTEMP);
|
set_error_source(ADBMS_INTERNAL_BMS_OVERTEMP);
|
||||||
} else {
|
} else {
|
||||||
clear_error_source(SEK_INTERNAL_BMS_OVERTEMP);
|
clear_error_source(ADBMS_INTERNAL_BMS_OVERTEMP);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (overvolt) {
|
if (overvolt) {
|
||||||
set_error_source(SEK_OVERVOLT);
|
set_error_source(ADBMS_OVERVOLT);
|
||||||
} else {
|
} else {
|
||||||
clear_error_source(SEK_OVERVOLT);
|
clear_error_source(ADBMS_OVERVOLT);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (undervolt) {
|
if (undervolt) {
|
||||||
set_error_source(SEK_UNDERVOLT);
|
set_error_source(ADBMS_UNDERVOLT);
|
||||||
} else {
|
} else {
|
||||||
clear_error_source(SEK_UNDERVOLT);
|
clear_error_source(ADBMS_UNDERVOLT);
|
||||||
}
|
}
|
||||||
|
|
||||||
mcuDelay(10);
|
mcuDelay(10);
|
||||||
|
|
||||||
return 0;
|
return NO_ERROR;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue