diff --git a/AMS_Master_Code/Core/Inc/config_ADBMS6830.h b/AMS_Master_Code/Core/Inc/config_ADBMS6830.h index f1f52eb..7813fd3 100644 --- a/AMS_Master_Code/Core/Inc/config_ADBMS6830.h +++ b/AMS_Master_Code/Core/Inc/config_ADBMS6830.h @@ -2,15 +2,16 @@ #ifndef __CONFIG_ADBMS6830_H #define __CONFIG_ADBMS6830_H #include "main.h" -#define N_BMS 2 -[[maybe_unused]] static void mcuAdbmsCSLow() { +#define N_BMS 2 +#define ADBMS_SPI_TIMEOUT 100 // Timeout in ms + +[[maybe_unused]] static inline void mcuAdbmsCSLow() { HAL_GPIO_WritePin(AMS_CS_GPIO_Port, AMS_CS_Pin, GPIO_PIN_RESET); } -[[maybe_unused]] static void mcuAdbmsCSHigh() { +[[maybe_unused]] static inline void mcuAdbmsCSHigh() { HAL_GPIO_WritePin(AMS_CS_GPIO_Port, AMS_CS_Pin, GPIO_PIN_SET); } - + #endif //__CONFIG_ADBMS6830_H - \ No newline at end of file diff --git a/AMS_Master_Code/Core/Inc/swo_log.h b/AMS_Master_Code/Core/Inc/swo_log.h index ca24905..6368f67 100644 --- a/AMS_Master_Code/Core/Inc/swo_log.h +++ b/AMS_Master_Code/Core/Inc/swo_log.h @@ -52,10 +52,11 @@ static inline uint32_t __swo_putc(uint32_t c, unsigned int channel) { return (c); } -#define DEBUG_CHANNEL_ENABLED(channel) ({ \ - unsigned int ch = (channel); \ - (ch < 32) ? __ITM_channel_enabled(ch) : false; \ -}) +#define DEBUG_CHANNEL_ENABLED(channel) \ + ({ \ + unsigned int ch = (channel); \ + (ch < 32) ? __ITM_channel_enabled(ch) : false; \ + }) [[gnu::nonnull(2), gnu::null_terminated_string_arg(2)]] static inline void __swo_print(unsigned int channel, const char *str) { @@ -67,31 +68,31 @@ static inline void __swo_print(unsigned int channel, const char *str) { } } -#define debug_log(level, msg, ...) \ - do { \ - if (DEBUG_CHANNEL_ENABLED(level)) { \ - char buffer[MAX_MESSAGE_LENGTH]; \ - size_t len = snprintf(buffer, sizeof(buffer), msg, ##__VA_ARGS__); \ - __swo_putc('\n', level); \ - __swo_print(level, log_level_names[level]); \ - __swo_print(level, buffer); \ - if (len >= sizeof(buffer)) { \ - __swo_print(level, " [message length exceeded] "); \ - } \ - } \ +#define debug_log(level, msg, ...) \ + do { \ + if (DEBUG_CHANNEL_ENABLED(level)) { \ + char buffer[MAX_MESSAGE_LENGTH]; \ + size_t len = snprintf(buffer, sizeof(buffer), msg, ##__VA_ARGS__); \ + __swo_putc('\n', level); \ + __swo_print(level, log_level_names[level]); \ + __swo_print(level, buffer); \ + if (len >= sizeof(buffer)) { \ + __swo_print(level, " [message length exceeded] "); \ + } \ + } \ } while (0) -#define debug_log_cont(level, msg, ...) \ - do { \ - if (DEBUG_CHANNEL_ENABLED(level)) { \ - char buffer[MAX_MESSAGE_LENGTH]; \ - size_t len = snprintf(buffer, sizeof(buffer), msg, ##__VA_ARGS__); \ - __swo_print(level, buffer); \ - if (len >= sizeof(buffer)) { \ - __swo_print(level, " [message length exceeded] "); \ - } \ - __swo_putc('\n', level); \ - } \ +#define debug_log_cont(level, msg, ...) \ + do { \ + if (DEBUG_CHANNEL_ENABLED(level)) { \ + char buffer[MAX_MESSAGE_LENGTH]; \ + size_t len = snprintf(buffer, sizeof(buffer), msg, ##__VA_ARGS__); \ + __swo_print(level, buffer); \ + if (len >= sizeof(buffer)) { \ + __swo_print(level, " [message length exceeded] "); \ + } \ + __swo_putc('\n', level); \ + } \ } while (0) #endif /* __SWO_LOG_H */ diff --git a/AMS_Master_Code/Core/Lib/ADBMS6830B_Driver/Core/Inc/ADBMS_Abstraction.h b/AMS_Master_Code/Core/Lib/ADBMS6830B_Driver/Core/Inc/ADBMS_Abstraction.h index 9e147ad..11daf11 100644 --- a/AMS_Master_Code/Core/Lib/ADBMS6830B_Driver/Core/Inc/ADBMS_Abstraction.h +++ b/AMS_Master_Code/Core/Lib/ADBMS6830B_Driver/Core/Inc/ADBMS_Abstraction.h @@ -9,15 +9,16 @@ #define INC_ADBMS_ABSTRACTION_H_ #include "ADBMS_CMD_MAKROS.h" -#include "ADBMS_LL_Driver.h" #include "ADBMS_Driver.h" +#include "ADBMS_LL_Driver.h" #include "main.h" -//see table 103 in datasheet (page 71) -#define DEFAULT_UV 417 //VUV * 16 * 150 uV + 1.5 V Default Setting 2.5V -#define DEFAULT_OV 1125 //VOV * 16 * 150 uV + 1.5 V Default Setting 4.2V -#define mV_from_ADBMS6830(x) (((((int16_t) (x))) * 0.150) + 1500) +// see table 103 in datasheet (page 71) +#define DEFAULT_UV 417 // VUV * 16 * 150 uV + 1.5 V Default Setting 2.5V +#define DEFAULT_OV 1125 // VOV * 16 * 150 uV + 1.5 V Default Setting 4.2V + +#define mV_from_ADBMS6830(x) (((((int16_t)(x))) * 0.150) + 1500) HAL_StatusTypeDef amsReset(); diff --git a/AMS_Master_Code/Core/Lib/ADBMS6830B_Driver/Core/Inc/ADBMS_Driver.h b/AMS_Master_Code/Core/Lib/ADBMS6830B_Driver/Core/Inc/ADBMS_Driver.h index 3db67c5..5bb9307 100644 --- a/AMS_Master_Code/Core/Lib/ADBMS6830B_Driver/Core/Inc/ADBMS_Driver.h +++ b/AMS_Master_Code/Core/Lib/ADBMS6830B_Driver/Core/Inc/ADBMS_Driver.h @@ -1,7 +1,7 @@ #ifndef ADBMS_DRIVER_H #define ADBMS_DRIVER_H -#include "stm32h7xx_hal.h" +#include "config_ADBMS6830.h" #include #define ERROR_TIME_THRESH 150 // ms @@ -13,8 +13,8 @@ typedef enum : uint16_t { ADBMS_OVERVOLT, ADBMS_UNDERVOLT, ADBMS_OPENWIRE, - ADBMS_INTERNAL_BMS_TIMEOUT, - ADBMS_INTERNAL_BMS_CHECKSUM_FAIL, + ADBMS_INTERNAL_BMS_TIMEOUT, // BMS went to sleep too many times + ADBMS_INTERNAL_BMS_CHECKSUM_FAIL, // BMS CRC failed too many times ADBMS_INTERNAL_BMS_OVERTEMP, ADBMS_INTERNAL_BMS_FAULT, NUM_ERROR_KINDS @@ -76,6 +76,7 @@ typedef struct { extern uint32_t error_sources; // Bitfield of error sources extern SlaveErrorData error_data[NUM_ERROR_KINDS]; +extern Cell_Module modules[N_BMS]; [[gnu::nonnull]] ADBMS_DetailedStatus AMS_Init(SPI_HandleTypeDef* hspi); diff --git a/AMS_Master_Code/Core/Lib/ADBMS6830B_Driver/Core/Src/ADBMS_Abstraction.c b/AMS_Master_Code/Core/Lib/ADBMS6830B_Driver/Core/Src/ADBMS_Abstraction.c index cb31a96..1f370b2 100644 --- a/AMS_Master_Code/Core/Lib/ADBMS6830B_Driver/Core/Src/ADBMS_Abstraction.c +++ b/AMS_Master_Code/Core/Lib/ADBMS6830B_Driver/Core/Src/ADBMS_Abstraction.c @@ -14,38 +14,58 @@ extern uint8_t numberofCells; -#define CHECK_RETURN(x) \ - do { \ - HAL_StatusTypeDef status = x; \ - if (status != 0) \ - return status; \ - } while (0) +static const char* const HAL_Statuses[] = {"HAL_OK", "HAL_ERROR", "HAL_BUSY", "HAL_TIMEOUT"}; + +#define CHECK_RETURN(x) \ + do { \ + HAL_StatusTypeDef status = x; \ + if (status != 0) { \ + debug_log(LOG_LEVEL_ERROR, "@%s:%s:%d: %s failed with status %d (%s)", __FILE_NAME__, __func__, __LINE__, \ + #x, status, \ + (status < (sizeof(HAL_Statuses) / sizeof(HAL_Statuses[0]))) ? HAL_Statuses[status] : "Unknown"); \ + return status; \ + } \ + } while (0) HAL_StatusTypeDef amsReset() { - amsWakeUp(); - readCMD(SRST, CMD_EMPTY_BUFFER, 0); + amsWakeUp(); + readCMD(SRST, CMD_EMPTY_BUFFER, 0); - uint8_t sidbuffer[CMD_BUFFER_SIZE(SID_GROUP_SIZE)] = {}; - CHECK_RETURN(readCMD(RDSID, sidbuffer, SID_GROUP_SIZE)); - - debug_log(LOG_LEVEL_INFO, "BMS reset complete"); - - if (DEBUG_CHANNEL_ENABLED(LOG_LEVEL_INFO)) { - debug_log(LOG_LEVEL_INFO, "Found IDs: "); - for (size_t i = 0; i < N_BMS; i++) { - uint64_t id = 0; - for (size_t j = 0; j < SID_GROUP_SIZE; j++) { - id |= sidbuffer[BUFFER_BMS_OFFSET(i, SID_GROUP_SIZE) + j] << (j * 8); - } - debug_log_cont(LOG_LEVEL_INFO, "0x%llx ", id); + uint8_t sidbuffer[CMD_BUFFER_SIZE(SID_GROUP_SIZE)] = {}; + if (readCMD(RDSID, sidbuffer, SID_GROUP_SIZE) != HAL_OK) { + bool nonzero = false; + for (size_t i = 0; i < N_BMS; i++) { + if (sidbuffer[BUFFER_BMS_OFFSET(i, SID_GROUP_SIZE)] != 0) { + nonzero = true; + } + } + if (nonzero) { + debug_log(LOG_LEVEL_ERROR, + "CRC failure when reading BMS IDs, but some IDs are nonzero. --- Intermittent connection?"); + } else { + debug_log(LOG_LEVEL_ERROR, "CRC failure when reading BMS IDs, all IDs are zero. --- No connection?"); + } + return HAL_ERROR; } - debug_log_cont(LOG_LEVEL_INFO, "\n"); - } - mcuDelay(10); - amsWakeUp(); - amsStopBalancing(); - amsConfigOverUnderVoltage(DEFAULT_OV, DEFAULT_UV); + debug_log(LOG_LEVEL_INFO, "BMS reset complete"); + + if (DEBUG_CHANNEL_ENABLED(LOG_LEVEL_INFO)) { + debug_log(LOG_LEVEL_INFO, "Found IDs: "); + for (size_t i = 0; i < N_BMS; i++) { + uint64_t id = 0; + for (size_t j = 0; j < SID_GROUP_SIZE; j++) { + id |= sidbuffer[BUFFER_BMS_OFFSET(i, SID_GROUP_SIZE) + j] << (j * 8); + } + debug_log_cont(LOG_LEVEL_INFO, "0x%llx ", id); + } + debug_log_cont(LOG_LEVEL_INFO, "\n"); + } + + mcuDelay(10); + amsWakeUp(); + amsStopBalancing(); + amsConfigOverUnderVoltage(DEFAULT_OV, DEFAULT_UV); uint8_t flagsbuffer[CMD_BUFFER_SIZE(6)] = {[0 ... CMD_BUFFER_SIZE(6) - 1] = 0xFF}; //technically not all 6 bytes are used, but it's easier to just set all to 0xFF //see page 27 of the datasheet for the memory map @@ -55,31 +75,31 @@ HAL_StatusTypeDef amsReset() { CHECK_RETURN(writeCMD(ADCV | ADCV_CONT | ADCV_RD, flagsbuffer, 0)); //start continuous cell voltage measurement with redundancy CHECK_RETURN(writeCMD(ADAX | ADAX_CONV_ALL, flagsbuffer, 0)); //start aux measurement - return 0; + return 0; } HAL_StatusTypeDef initAMS(SPI_HandleTypeDef* hspi) { - adbmsDriverInit(hspi); - return amsReset(); + adbmsDriverInit(hspi); + return amsReset(); } HAL_StatusTypeDef amsWakeUp() { - uint8_t buffer[CMD_BUFFER_SIZE(CFG_GROUP_A_SIZE)] = {0}; - return readCMD(RDCFGA, buffer, CFG_GROUP_A_SIZE); + uint8_t buffer[CMD_BUFFER_SIZE(CFG_GROUP_A_SIZE)] = {0}; + return readCMD(RDCFGA, buffer, CFG_GROUP_A_SIZE); } HAL_StatusTypeDef amsCellMeasurement(Cell_Module (*module)[N_BMS]) { - #warning check conversion counter to ensure that continous conversion has not been stopped - #warning check for OW conditions: ADSV | ADSV_OW_0 / ADSV_OW_1 - return amsReadCellVoltages(module); + #warning check conversion counter to ensure that continuous conversion has not been stopped + #warning check for OW conditions: ADSV | ADSV_OW_0 / ADSV_OW_1 + return amsReadCellVoltages(module); } HAL_StatusTypeDef amsAuxAndStatusMeasurement(Cell_Module (*module)[N_BMS]) { - uint8_t rxbuf[CMD_BUFFER_SIZE(STATUS_GROUP_C_SIZE)] = {}; + uint8_t rxbuf[CMD_BUFFER_SIZE(STATUS_GROUP_C_SIZE)] = {}; - CHECK_RETURN(readCMD(RDSTATC, rxbuf, STATUS_GROUP_C_SIZE)); - for (size_t i = 0; i < N_BMS; i++) { - size_t offset = BUFFER_BMS_OFFSET(i, STATUS_GROUP_C_SIZE); + CHECK_RETURN(readCMD(RDSTATC, rxbuf, STATUS_GROUP_C_SIZE)); + for (size_t i = 0; i < N_BMS; i++) { + size_t offset = BUFFER_BMS_OFFSET(i, STATUS_GROUP_C_SIZE); module[i]->status.CS_FLT = rxbuf[offset + 0] | (rxbuf[offset + 1] << 8); module[i]->status.CCTS = rxbuf[offset + 2] | (rxbuf[offset + 3] << 8); module[i]->status.VA_OV = (rxbuf[offset + 4] >> 7) & 0x01; @@ -98,105 +118,105 @@ HAL_StatusTypeDef amsAuxAndStatusMeasurement(Cell_Module (*module)[N_BMS]) { module[i]->status.THSD = (rxbuf[offset + 5] >> 2) & 0x01; module[i]->status.TMODCHK= (rxbuf[offset + 5] >> 1) & 0x01; module[i]->status.OSCCHK = (rxbuf[offset + 5] >> 0) & 0x01; - } + } - if (pollCMD(PLAUX) == HAL_BUSY) { - return HAL_BUSY; - } + if (pollCMD(PLAUX) == HAL_BUSY) { + return HAL_BUSY; + } CHECK_RETURN(readCMD(RDAUXA, rxbuf, AUX_GROUP_A_SIZE)); //STATUS_GROUP_C_SIZE is the same as AUX_GROUP_A_SIZE, so we can reuse the buffer - for (size_t i = 0; i < N_BMS; i++) { - size_t offset = BUFFER_BMS_OFFSET(i, AUX_GROUP_A_SIZE); + for (size_t i = 0; i < N_BMS; i++) { + size_t offset = BUFFER_BMS_OFFSET(i, AUX_GROUP_A_SIZE); module[i]->auxVoltages[0] = mV_from_ADBMS6830(rxbuf[offset + 0] | (rxbuf[offset + 1] << 8)); module[i]->auxVoltages[1] = mV_from_ADBMS6830(rxbuf[offset + 2] | (rxbuf[offset + 3] << 8)); module[i]->auxVoltages[2] = mV_from_ADBMS6830(rxbuf[offset + 4] | (rxbuf[offset + 5] << 8)); - } + } - CHECK_RETURN(readCMD(RDAUXB, rxbuf, AUX_GROUP_B_SIZE)); - for (size_t i = 0; i < N_BMS; i++) { - size_t offset = BUFFER_BMS_OFFSET(i, AUX_GROUP_B_SIZE); + CHECK_RETURN(readCMD(RDAUXB, rxbuf, AUX_GROUP_B_SIZE)); + for (size_t i = 0; i < N_BMS; i++) { + size_t offset = BUFFER_BMS_OFFSET(i, AUX_GROUP_B_SIZE); module[i]->auxVoltages[3] = mV_from_ADBMS6830(rxbuf[offset + 0] | (rxbuf[offset + 1] << 8)); module[i]->auxVoltages[4] = mV_from_ADBMS6830(rxbuf[offset + 2] | (rxbuf[offset + 3] << 8)); module[i]->auxVoltages[5] = mV_from_ADBMS6830(rxbuf[offset + 4] | (rxbuf[offset + 5] << 8)); - } + } - CHECK_RETURN(readCMD(RDAUXC, rxbuf, AUX_GROUP_C_SIZE)); - for (size_t i = 0; i < N_BMS; i++) { - size_t offset = BUFFER_BMS_OFFSET(i, AUX_GROUP_C_SIZE); + CHECK_RETURN(readCMD(RDAUXC, rxbuf, AUX_GROUP_C_SIZE)); + for (size_t i = 0; i < N_BMS; i++) { + size_t offset = BUFFER_BMS_OFFSET(i, AUX_GROUP_C_SIZE); module[i]->auxVoltages[6] = mV_from_ADBMS6830(rxbuf[offset + 0] | (rxbuf[offset + 1] << 8)); module[i]->auxVoltages[7] = mV_from_ADBMS6830(rxbuf[offset + 2] | (rxbuf[offset + 3] << 8)); module[i]->auxVoltages[8] = mV_from_ADBMS6830(rxbuf[offset + 4] | (rxbuf[offset + 5] << 8)); - } + } - CHECK_RETURN(readCMD(RDAUXD, rxbuf, AUX_GROUP_D_SIZE)); - for (size_t i = 0; i < N_BMS; i++) { - size_t offset = BUFFER_BMS_OFFSET(i, AUX_GROUP_D_SIZE); + CHECK_RETURN(readCMD(RDAUXD, rxbuf, AUX_GROUP_D_SIZE)); + for (size_t i = 0; i < N_BMS; i++) { + size_t offset = BUFFER_BMS_OFFSET(i, AUX_GROUP_D_SIZE); module[i]->auxVoltages[9] = mV_from_ADBMS6830(rxbuf[offset + 0] | (rxbuf[offset + 1] << 8)); - } + } - CHECK_RETURN(readCMD(RDSTATA, rxbuf, STATUS_GROUP_A_SIZE)); - for (size_t i = 0; i < N_BMS; i++) { - size_t offset = BUFFER_BMS_OFFSET(i, STATUS_GROUP_A_SIZE); + CHECK_RETURN(readCMD(RDSTATA, rxbuf, STATUS_GROUP_A_SIZE)); + for (size_t i = 0; i < N_BMS; i++) { + size_t offset = BUFFER_BMS_OFFSET(i, STATUS_GROUP_A_SIZE); module[i]->internalDieTemp = rxbuf[offset + 2] | (rxbuf[offset + 3] << 8); - } + } - CHECK_RETURN(readCMD(RDSTATB, rxbuf, STATUS_GROUP_B_SIZE)); - for (size_t i = 0; i < N_BMS; i++) { - size_t offset = BUFFER_BMS_OFFSET(i, STATUS_GROUP_B_SIZE); + CHECK_RETURN(readCMD(RDSTATB, rxbuf, STATUS_GROUP_B_SIZE)); + for (size_t i = 0; i < N_BMS; i++) { + size_t offset = BUFFER_BMS_OFFSET(i, STATUS_GROUP_B_SIZE); module[i]->digitalSupplyVoltage = mV_from_ADBMS6830(rxbuf[offset + 0] | (rxbuf[offset + 1] << 8)); module[i]->analogSupplyVoltage = mV_from_ADBMS6830(rxbuf[offset + 2] | (rxbuf[offset + 3] << 8)); module[i]->refVoltage = mV_from_ADBMS6830(rxbuf[offset + 4] | (rxbuf[offset + 5] << 8)); - } + } CHECK_RETURN(writeCMD(ADAX | ADAX_CONV_ALL, rxbuf, 0)); //start aux conversion for next iteration - return HAL_OK; + return HAL_OK; } HAL_StatusTypeDef amsConfigBalancing(const uint32_t channels[static N_BMS], uint8_t dutyCycle) { - if (dutyCycle > 0x0F) { - return HAL_ERROR; // only 4 bits are allowed for dutyCycle - } + if (dutyCycle > 0x0F) { + return HAL_ERROR; // only 4 bits are allowed for dutyCycle + } - uint8_t rxbufA[CMD_BUFFER_SIZE(PWM_GROUP_A_SIZE)] = {}; - uint8_t rxbufB[CMD_BUFFER_SIZE(PWM_GROUP_B_SIZE)] = {}; + uint8_t rxbufA[CMD_BUFFER_SIZE(PWM_GROUP_A_SIZE)] = {}; + uint8_t rxbufB[CMD_BUFFER_SIZE(PWM_GROUP_B_SIZE)] = {}; - CHECK_RETURN(readCMD(RDPWMA, rxbufA, PWM_GROUP_A_SIZE)); - CHECK_RETURN(readCMD(RDPWMB, rxbufB, PWM_GROUP_B_SIZE)); + CHECK_RETURN(readCMD(RDPWMA, rxbufA, PWM_GROUP_A_SIZE)); + CHECK_RETURN(readCMD(RDPWMB, rxbufB, PWM_GROUP_B_SIZE)); - for (size_t i = 0; i < N_BMS; i++) { - size_t offsetA = BUFFER_BMS_OFFSET(i, PWM_GROUP_A_SIZE); - size_t offsetB = BUFFER_BMS_OFFSET(i, PWM_GROUP_B_SIZE); + for (size_t i = 0; i < N_BMS; i++) { + size_t offsetA = BUFFER_BMS_OFFSET(i, PWM_GROUP_A_SIZE); + size_t offsetB = BUFFER_BMS_OFFSET(i, PWM_GROUP_B_SIZE); - for (size_t c = 0; c < 16; c += 2) { - uint8_t high = (channels[i] & (1 << (c + 1))) ? (dutyCycle << 4) : 0; + for (size_t c = 0; c < 16; c += 2) { + uint8_t high = (channels[i] & (1 << (c + 1))) ? (dutyCycle << 4) : 0; uint8_t low = (channels[i] & (1 << c)) ? dutyCycle : 0; - if (c < 12) { - rxbufA[offsetA + (c / 2)] = high | low; - } else { - rxbufB[offsetB + ((c - 12) / 2)] = high | low; - } - } + if (c < 12) { + rxbufA[offsetA + (c / 2)] = high | low; + } else { + rxbufB[offsetB + ((c - 12) / 2)] = high | low; + } + } //log the new PWM settings //output is: PWM - [BMS_ID]: [PWM0] ... [PWM16] - if (DEBUG_CHANNEL_ENABLED(LOG_LEVEL_DEBUG)) { - debug_log(LOG_LEVEL_DEBUG, "PWM - %d: ", i); - for (size_t j = 0; j < 6; j++) { - debug_log_cont(LOG_LEVEL_DEBUG, "%x %x ", rxbufA[offsetA + j] & 0x0F, rxbufA[offsetA + j] >> 4); - } - for (size_t j = 0; j < 2; j++) { - debug_log_cont(LOG_LEVEL_DEBUG, "%x %x ", rxbufB[offsetB + j] & 0x0F, rxbufB[offsetB + j] >> 4); - } - debug_log_cont(LOG_LEVEL_DEBUG, "\n"); + if (DEBUG_CHANNEL_ENABLED(LOG_LEVEL_DEBUG)) { + debug_log(LOG_LEVEL_DEBUG, "PWM - %d: ", i); + for (size_t j = 0; j < 6; j++) { + debug_log_cont(LOG_LEVEL_DEBUG, "%x %x ", rxbufA[offsetA + j] & 0x0F, rxbufA[offsetA + j] >> 4); + } + for (size_t j = 0; j < 2; j++) { + debug_log_cont(LOG_LEVEL_DEBUG, "%x %x ", rxbufB[offsetB + j] & 0x0F, rxbufB[offsetB + j] >> 4); + } + debug_log_cont(LOG_LEVEL_DEBUG, "\n"); + } } - } - CHECK_RETURN(writeCMD(WRPWMA, rxbufA, PWM_GROUP_A_SIZE)); - CHECK_RETURN(writeCMD(WRPWMB, rxbufB, PWM_GROUP_B_SIZE)); + CHECK_RETURN(writeCMD(WRPWMA, rxbufA, PWM_GROUP_A_SIZE)); + CHECK_RETURN(writeCMD(WRPWMB, rxbufB, PWM_GROUP_B_SIZE)); - return HAL_OK; + return HAL_OK; } HAL_StatusTypeDef amsStartBalancing(uint8_t dutyCycle) { return writeCMD(UNMUTE, CMD_EMPTY_BUFFER, 0); } @@ -206,59 +226,59 @@ HAL_StatusTypeDef amsStopBalancing() { return writeCMD(MUTE, CMD_EMPTY_BUFFER, 0 HAL_StatusTypeDef amsSelfTest() { return 0; } HAL_StatusTypeDef amsConfigOverUnderVoltage(uint16_t overVoltage, uint16_t underVoltage) { - uint8_t buffer[CMD_BUFFER_SIZE(CFG_GROUP_B_SIZE)] = {}; + uint8_t buffer[CMD_BUFFER_SIZE(CFG_GROUP_B_SIZE)] = {}; - if (underVoltage & 0xF000 || overVoltage & 0xF000) { // only 12 bits allowed - return HAL_ERROR; - } + if (underVoltage & 0xF000 || overVoltage & 0xF000) { // only 12 bits allowed + return HAL_ERROR; + } debug_log(LOG_LEVEL_INFO, "Configuring OV/UV thresholds to %f/%f", mV_from_ADBMS6830(overVoltage), mV_from_ADBMS6830(underVoltage)); - CHECK_RETURN(readCMD(RDCFGB, buffer, CFG_GROUP_B_SIZE)); + CHECK_RETURN(readCMD(RDCFGB, buffer, CFG_GROUP_B_SIZE)); - for (size_t i = 0; i < N_BMS; i++) { - size_t offset = BUFFER_BMS_OFFSET(i, CFG_GROUP_B_SIZE); + for (size_t i = 0; i < N_BMS; i++) { + size_t offset = BUFFER_BMS_OFFSET(i, CFG_GROUP_B_SIZE); //UV - buffer[offset + 0] = (uint8_t)(underVoltage & 0xFF); - buffer[offset + 1] &= 0xF0; - buffer[offset + 1] |= (uint8_t)((underVoltage >> 8) & 0x0F); + buffer[offset + 0] = (uint8_t)(underVoltage & 0xFF); + buffer[offset + 1] &= 0xF0; + buffer[offset + 1] |= (uint8_t)((underVoltage >> 8) & 0x0F); //OV - buffer[offset + 1] &= 0x0F; - buffer[offset + 1] |= (uint8_t)(overVoltage << 4); - buffer[offset + 2] = (uint8_t)(overVoltage >> 4); - } + buffer[offset + 1] &= 0x0F; + buffer[offset + 1] |= (uint8_t)(overVoltage << 4); + buffer[offset + 2] = (uint8_t)(overVoltage >> 4); + } - return writeCMD(WRCFGB, buffer, CFG_GROUP_B_SIZE); + return writeCMD(WRCFGB, buffer, CFG_GROUP_B_SIZE); } HAL_StatusTypeDef amsCheckUnderOverVoltage(Cell_Module (*module)[N_BMS]) { - uint8_t regbuffer[CMD_BUFFER_SIZE(STATUS_GROUP_D_SIZE)] = {}; - - CHECK_RETURN(readCMD(RDSTATD, regbuffer, STATUS_GROUP_D_SIZE)); + uint8_t regbuffer[CMD_BUFFER_SIZE(STATUS_GROUP_D_SIZE)] = {}; - for (size_t i = 0; i < N_BMS; i++) { - size_t offset = BUFFER_BMS_OFFSET(i, STATUS_GROUP_D_SIZE); - uint32_t ov_uv_data = 0; + CHECK_RETURN(readCMD(RDSTATD, regbuffer, STATUS_GROUP_D_SIZE)); + + for (size_t i = 0; i < N_BMS; i++) { + size_t offset = BUFFER_BMS_OFFSET(i, STATUS_GROUP_D_SIZE); + uint32_t ov_uv_data = 0; ov_uv_data = (regbuffer[offset + 0] << 0) | (regbuffer[offset + 1] << 8) | (regbuffer[offset + 2] << 16) | (regbuffer[offset + 3] << 24); module[i]->overVoltage = 0; module[i]->underVoltage = 0; - + for (size_t j = 0; j < numberofCells; j++) { // ov/uv flags are 1-bit flags for each cell C0UV, C0OV, C1UV, C1OV, ... module[i]->underVoltage |= (ov_uv_data >> (j * 2)) & 0x01; module[i]->overVoltage |= (ov_uv_data >> (j * 2 + 1)) & 0x01; + } } - } - return HAL_OK; + return HAL_OK; } HAL_StatusTypeDef amsClearFlag() { - uint8_t buffer[CMD_BUFFER_SIZE(6)] = {[0 ... CMD_BUFFER_SIZE(6) - 1] = 0xFF}; - return writeCMD(CLRFLAG, buffer, 6); + uint8_t buffer[CMD_BUFFER_SIZE(6)] = {[0 ... CMD_BUFFER_SIZE(6) - 1] = 0xFF}; + return writeCMD(CLRFLAG, buffer, 6); } HAL_StatusTypeDef amsClearAux() { @@ -266,233 +286,238 @@ HAL_StatusTypeDef amsClearAux() { } HAL_StatusTypeDef amsReadCellVoltages(Cell_Module (*module)[N_BMS]) { - uint8_t rxbuffer[CMD_BUFFER_SIZE(CV_GROUP_A_SIZE)] = {}; + uint8_t rxbuffer[CMD_BUFFER_SIZE(CV_GROUP_A_SIZE)] = {}; - CHECK_RETURN(readCMD(RDCVA, rxbuffer, CV_GROUP_A_SIZE)); - for (size_t i = 0; i < N_BMS; i++) { - size_t offset = BUFFER_BMS_OFFSET(i, CV_GROUP_A_SIZE); + CHECK_RETURN(readCMD(RDCVA, rxbuffer, CV_GROUP_A_SIZE)); + for (size_t i = 0; i < N_BMS; i++) { + size_t offset = BUFFER_BMS_OFFSET(i, CV_GROUP_A_SIZE); module[i]->cellVoltages[0] = mV_from_ADBMS6830(rxbuffer[offset + 0] | (rxbuffer[offset + 1] << 8)); module[i]->cellVoltages[1] = mV_from_ADBMS6830(rxbuffer[offset + 2] | (rxbuffer[offset + 3] << 8)); module[i]->cellVoltages[2] = mV_from_ADBMS6830(rxbuffer[offset + 4] | (rxbuffer[offset + 5] << 8)); - } + } - CHECK_RETURN(readCMD(RDCVB, rxbuffer, CV_GROUP_A_SIZE)); - for (size_t i = 0; i < N_BMS; i++) { - size_t offset = BUFFER_BMS_OFFSET(i, CV_GROUP_A_SIZE); + CHECK_RETURN(readCMD(RDCVB, rxbuffer, CV_GROUP_A_SIZE)); + for (size_t i = 0; i < N_BMS; i++) { + size_t offset = BUFFER_BMS_OFFSET(i, CV_GROUP_A_SIZE); module[i]->cellVoltages[3] = mV_from_ADBMS6830(rxbuffer[offset + 0] | (rxbuffer[offset + 1] << 8)); module[i]->cellVoltages[4] = mV_from_ADBMS6830(rxbuffer[offset + 2] | (rxbuffer[offset + 3] << 8)); module[i]->cellVoltages[5] = mV_from_ADBMS6830(rxbuffer[offset + 4] | (rxbuffer[offset + 5] << 8)); - } + } - CHECK_RETURN(readCMD(RDCVC, rxbuffer, CV_GROUP_A_SIZE)); - for (size_t i = 0; i < N_BMS; i++) { - size_t offset = BUFFER_BMS_OFFSET(i, CV_GROUP_A_SIZE); + CHECK_RETURN(readCMD(RDCVC, rxbuffer, CV_GROUP_A_SIZE)); + for (size_t i = 0; i < N_BMS; i++) { + size_t offset = BUFFER_BMS_OFFSET(i, CV_GROUP_A_SIZE); module[i]->cellVoltages[6] = mV_from_ADBMS6830(rxbuffer[offset + 0] | (rxbuffer[offset + 1] << 8)); module[i]->cellVoltages[7] = mV_from_ADBMS6830(rxbuffer[offset + 2] | (rxbuffer[offset + 3] << 8)); module[i]->cellVoltages[8] = mV_from_ADBMS6830(rxbuffer[offset + 4] | (rxbuffer[offset + 5] << 8)); - } + } - CHECK_RETURN(readCMD(RDCVD, rxbuffer, CV_GROUP_A_SIZE)); - for (size_t i = 0; i < N_BMS; i++) { - size_t offset = BUFFER_BMS_OFFSET(i, CV_GROUP_A_SIZE); + CHECK_RETURN(readCMD(RDCVD, rxbuffer, CV_GROUP_A_SIZE)); + for (size_t i = 0; i < N_BMS; i++) { + size_t offset = BUFFER_BMS_OFFSET(i, CV_GROUP_A_SIZE); module[i]->cellVoltages[9] = mV_from_ADBMS6830(rxbuffer[offset + 0] | (rxbuffer[offset + 1] << 8)); module[i]->cellVoltages[10] = mV_from_ADBMS6830(rxbuffer[offset + 2] | (rxbuffer[offset + 3] << 8)); module[i]->cellVoltages[11] = mV_from_ADBMS6830(rxbuffer[offset + 4] | (rxbuffer[offset + 5] << 8)); - } + } - CHECK_RETURN(readCMD(RDCVE, rxbuffer, CV_GROUP_A_SIZE)); - for (size_t i = 0; i < N_BMS; i++) { - size_t offset = BUFFER_BMS_OFFSET(i, CV_GROUP_A_SIZE); + CHECK_RETURN(readCMD(RDCVE, rxbuffer, CV_GROUP_A_SIZE)); + for (size_t i = 0; i < N_BMS; i++) { + size_t offset = BUFFER_BMS_OFFSET(i, CV_GROUP_A_SIZE); module[i]->cellVoltages[12] = mV_from_ADBMS6830(rxbuffer[offset + 0] | (rxbuffer[offset + 1] << 8)); module[i]->cellVoltages[13] = mV_from_ADBMS6830(rxbuffer[offset + 2] | (rxbuffer[offset + 3] << 8)); module[i]->cellVoltages[14] = mV_from_ADBMS6830(rxbuffer[offset + 4] | (rxbuffer[offset + 5] << 8)); - } + } - CHECK_RETURN(readCMD(RDCVF, rxbuffer, CV_GROUP_A_SIZE)); - for (size_t i = 0; i < N_BMS; i++) { - size_t offset = BUFFER_BMS_OFFSET(i, CV_GROUP_A_SIZE); + CHECK_RETURN(readCMD(RDCVF, rxbuffer, CV_GROUP_A_SIZE)); + for (size_t i = 0; i < N_BMS; i++) { + size_t offset = BUFFER_BMS_OFFSET(i, CV_GROUP_A_SIZE); module[i]->cellVoltages[15] = mV_from_ADBMS6830(rxbuffer[offset + 0] | (rxbuffer[offset + 1] << 8)); - } + } - return HAL_OK; + return HAL_OK; } -//Each selected BMS must have a corresponding address, and the data array for that BMS must be at least datalens[i] bytes long -HAL_StatusTypeDef amsSendI2C(const uint8_t addresses[static N_BMS], uint8_t * data[static N_BMS], const uint8_t datalens[static N_BMS], uint32_t bms_mask) { - uint8_t buffer[CMD_BUFFER_SIZE(COMM_GROUP_SIZE)] = {}; +// Each selected BMS must have a corresponding address, and the data array for that BMS must be at least datalens[i] +// bytes long +HAL_StatusTypeDef amsSendI2C(const uint8_t addresses[static N_BMS], uint8_t* data[static N_BMS], + const uint8_t datalens[static N_BMS], uint32_t bms_mask) { + uint8_t buffer[CMD_BUFFER_SIZE(COMM_GROUP_SIZE)] = {}; - //COMM register works in 3 bytes max per go, interleaved with control information + // COMM register works in 3 bytes max per go, interleaved with control information - uint8_t max_datalen = 0; - for (size_t i = 0; i < N_BMS; i++) { - if (datalens[i] > max_datalen) { - max_datalen = datalens[i]; + uint8_t max_datalen = 0; + for (size_t i = 0; i < N_BMS; i++) { + if (datalens[i] > max_datalen) { + max_datalen = datalens[i]; + } } - } - for (size_t i = 0; i < N_BMS; i++) { - size_t offset = BUFFER_BMS_OFFSET(i, COMM_GROUP_SIZE); + for (size_t i = 0; i < N_BMS; i++) { + size_t offset = BUFFER_BMS_OFFSET(i, COMM_GROUP_SIZE); - if (!(bms_mask & (1 << i))) { - buffer[offset + 0] = I2C_SEND_NOTRANSFER; - buffer[offset + 2] = I2C_SEND_NOTRANSFER; - buffer[offset + 4] = I2C_SEND_NOTRANSFER; - continue; - } - } + if (!(bms_mask & (1 << i))) { + buffer[offset + 0] = I2C_SEND_NOTRANSFER; + buffer[offset + 2] = I2C_SEND_NOTRANSFER; + buffer[offset + 4] = I2C_SEND_NOTRANSFER; + continue; + } + } - size_t packet_count = ((max_datalen + 1) / 3) + ((max_datalen + 1) % 3 != 0); //number of 3 byte packets needed to send all data + size_t packet_count = + ((max_datalen + 1) / 3) + ((max_datalen + 1) % 3 != 0); // number of 3 byte packets needed to send all data for (size_t i = 0; i < (packet_count * 3); i++) { //i - 1 is the number of data bytes sent so far (1 byte for the address) - for (size_t j = 0; j < N_BMS; j++) { - size_t offset = BUFFER_BMS_OFFSET(j, COMM_GROUP_SIZE); - if (!(bms_mask & (1 << j))) - continue; //skip BMS that are not selected - - if (i == 0) { - buffer[offset + 0] = I2C_SEND_START; - buffer[offset + 1] = addresses[j] << 1; //shift the address left by 1 to make space for the R/W bit - continue; - } + for (size_t j = 0; j < N_BMS; j++) { + size_t offset = BUFFER_BMS_OFFSET(j, COMM_GROUP_SIZE); + if (!(bms_mask & (1 << j))) + continue; // skip BMS that are not selected - //add data to the buffer + if (i == 0) { + buffer[offset + 0] = I2C_SEND_START; + buffer[offset + 1] = addresses[j] << 1; // shift the address left by 1 to make space for the R/W bit + continue; + } - //case 1: the last group of 3 bytes contained the last data byte, so we need to send a stop - if (datalens[j] - (int)i == -1) { - buffer[offset + ((i % 3) * 2)] = I2C_SEND_STOP; - continue; - } + // add data to the buffer - //case 2: we are more than one byte past the end, so we don't need to send any data - if (datalens[j] - (int)i < -1) { - buffer[offset + ((i % 3) * 2)] = I2C_SEND_NOTRANSFER; - continue; - } + // case 1: the last group of 3 bytes contained the last data byte, so we need to send a stop + if (datalens[j] - (int)i == -1) { + buffer[offset + ((i % 3) * 2)] = I2C_SEND_STOP; + continue; + } - //case 3: we are still sending data - buffer[offset + ((i % 3) * 2)] = I2C_SEND; - buffer[offset + ((i % 3) * 2) + 1] = data[j][i - 1]; + // case 2: we are more than one byte past the end, so we don't need to send any data + if (datalens[j] - (int)i < -1) { + buffer[offset + ((i % 3) * 2)] = I2C_SEND_NOTRANSFER; + continue; + } + + // case 3: we are still sending data + buffer[offset + ((i % 3) * 2)] = I2C_SEND; + buffer[offset + ((i % 3) * 2) + 1] = data[j][i - 1]; + } + + // send the data + if (i % 3 == 0 && i != 0) { + CHECK_RETURN(writeCMD(WRCOMM, buffer, COMM_GROUP_SIZE)); + + __pollCMD(STCOMM, 72); // wait 72 cycles for the I2C transfer to complete (datasheet page 43) + // TODO: not sure if this is correct for a daisy chain + } } - //send the data - if (i % 3 == 0 && i != 0) { - CHECK_RETURN(writeCMD(WRCOMM, buffer, COMM_GROUP_SIZE)); + // send the last packet + CHECK_RETURN(writeCMD(WRCOMM, buffer, COMM_GROUP_SIZE)); + __pollCMD(STCOMM, 72); - __pollCMD(STCOMM, 72); //wait 72 cycles for the I2C transfer to complete (datasheet page 43) - //TODO: not sure if this is correct for a daisy chain - } - } - - //send the last packet - CHECK_RETURN(writeCMD(WRCOMM, buffer, COMM_GROUP_SIZE)); - __pollCMD(STCOMM, 72); - - return HAL_OK; + return HAL_OK; } -//Each selected BMS must have a corresponding address, and the data array for that BMS must be at least datalens[i] bytes long -HAL_StatusTypeDef amsReadI2C(const uint8_t addresses[static N_BMS], uint8_t * data[static N_BMS], const uint8_t datalens[static N_BMS], uint32_t bms_mask) { - uint8_t buffer[CMD_BUFFER_SIZE(COMM_GROUP_SIZE)] = {}; +// Each selected BMS must have a corresponding address, and the data array for that BMS must be at least datalens[i] +// bytes long +HAL_StatusTypeDef amsReadI2C(const uint8_t addresses[static N_BMS], uint8_t* data[static N_BMS], + const uint8_t datalens[static N_BMS], uint32_t bms_mask) { + uint8_t buffer[CMD_BUFFER_SIZE(COMM_GROUP_SIZE)] = {}; - uint8_t max_datalen = 0; - for (size_t i = 0; i < N_BMS; i++) { - if (datalens[i] > max_datalen) { - max_datalen = datalens[i]; + uint8_t max_datalen = 0; + for (size_t i = 0; i < N_BMS; i++) { + if (datalens[i] > max_datalen) { + max_datalen = datalens[i]; + } } - } - for (size_t i = 0; i < N_BMS; i++) { - size_t offset = BUFFER_BMS_OFFSET(i, COMM_GROUP_SIZE); + for (size_t i = 0; i < N_BMS; i++) { + size_t offset = BUFFER_BMS_OFFSET(i, COMM_GROUP_SIZE); - if (!(bms_mask & (1 << i))) { - buffer[offset + 0] = I2C_SEND_NOTRANSFER; - buffer[offset + 2] = I2C_SEND_NOTRANSFER; - buffer[offset + 4] = I2C_SEND_NOTRANSFER; - continue; - } - } + if (!(bms_mask & (1 << i))) { + buffer[offset + 0] = I2C_SEND_NOTRANSFER; + buffer[offset + 2] = I2C_SEND_NOTRANSFER; + buffer[offset + 4] = I2C_SEND_NOTRANSFER; + continue; + } + } - size_t packet_count = ((max_datalen + 1) / 3) + ((max_datalen + 1) % 3 != 0); + size_t packet_count = ((max_datalen + 1) / 3) + ((max_datalen + 1) % 3 != 0); - for (size_t i = 0; i < (packet_count * 3); - i++) { // i - 1 is the number of data bytes sent so far (1 byte for the address) - for (size_t j = 0; j < N_BMS; j++) { - size_t offset = BUFFER_BMS_OFFSET(j, COMM_GROUP_SIZE); - if (!(bms_mask & (1 << j))) - continue; // skip BMS that are not selected + for (size_t i = 0; i < (packet_count * 3); + i++) { // i - 1 is the number of data bytes sent so far (1 byte for the address) + for (size_t j = 0; j < N_BMS; j++) { + size_t offset = BUFFER_BMS_OFFSET(j, COMM_GROUP_SIZE); + if (!(bms_mask & (1 << j))) + continue; // skip BMS that are not selected - if (i == 0) { - buffer[offset + 0] = I2C_SEND_START; + if (i == 0) { + buffer[offset + 0] = I2C_SEND_START; buffer[offset + 1] = addresses[j] << 1 | 0x01; // shift the address left by 1 to make space for the R/W bit - continue; - } + continue; + } - // add data to the buffer + // add data to the buffer - // case 1: the last group of 3 bytes contained the last data byte, so we need to send a stop - if (datalens[j] - (int)i == -1) { - buffer[offset + ((i % 3) * 2)] = I2C_SEND_STOP; - continue; - } + // case 1: the last group of 3 bytes contained the last data byte, so we need to send a stop + if (datalens[j] - (int)i == -1) { + buffer[offset + ((i % 3) * 2)] = I2C_SEND_STOP; + continue; + } - // case 2: we are more than one byte past the end, so we don't need to receive any data - if (datalens[j] - (int)i < -1) { - buffer[offset + ((i % 3) * 2)] = I2C_SEND_NOTRANSFER; - continue; - } + // case 2: we are more than one byte past the end, so we don't need to receive any data + if (datalens[j] - (int)i < -1) { + buffer[offset + ((i % 3) * 2)] = I2C_SEND_NOTRANSFER; + continue; + } - // case 3: we are still receiving data - buffer[offset + ((i % 3) * 2)] = I2C_SEND_ACK; - } + // case 3: we are still receiving data + buffer[offset + ((i % 3) * 2)] = I2C_SEND_ACK; + } - // send the command data - if (i % 3 == 0 && i != 0) { - CHECK_RETURN(writeCMD(WRCOMM, buffer, COMM_GROUP_SIZE)); + // send the command data + if (i % 3 == 0 && i != 0) { + CHECK_RETURN(writeCMD(WRCOMM, buffer, COMM_GROUP_SIZE)); - __pollCMD(STCOMM, 72); // wait 72 cycles for the I2C transfer to complete (datasheet page 43) - // TODO: not sure if this is correct for a daisy chain + __pollCMD(STCOMM, 72); // wait 72 cycles for the I2C transfer to complete (datasheet page 43) + // TODO: not sure if this is correct for a daisy chain - // read the data - CHECK_RETURN(readCMD(RDCOMM, buffer, COMM_GROUP_SIZE)); + // read the data + CHECK_RETURN(readCMD(RDCOMM, buffer, COMM_GROUP_SIZE)); - for (size_t j = 0; j < N_BMS; j++) { - size_t offset = BUFFER_BMS_OFFSET(j, COMM_GROUP_SIZE); + for (size_t j = 0; j < N_BMS; j++) { + size_t offset = BUFFER_BMS_OFFSET(j, COMM_GROUP_SIZE); - if (!(bms_mask & (1 << j))) - continue; // skip BMS that are not selected + if (!(bms_mask & (1 << j))) + continue; // skip BMS that are not selected - for (size_t k = 0; k < 3; k++) { - if (datalens[j] - (int)i < -1) { - continue; - } + for (size_t k = 0; k < 3; k++) { + if (datalens[j] - (int)i < -1) { + continue; + } - data[j][i - 1 + k] = buffer[offset + (k * 2) + 1]; - } - } - } - } + data[j][i - 1 + k] = buffer[offset + (k * 2) + 1]; + } + } + } + } - // send the last packet - CHECK_RETURN(writeCMD(WRCOMM, buffer, COMM_GROUP_SIZE)); - __pollCMD(STCOMM, 72); + // send the last packet + CHECK_RETURN(writeCMD(WRCOMM, buffer, COMM_GROUP_SIZE)); + __pollCMD(STCOMM, 72); - // read the data - CHECK_RETURN(readCMD(RDCOMM, buffer, COMM_GROUP_SIZE)); + // read the data + CHECK_RETURN(readCMD(RDCOMM, buffer, COMM_GROUP_SIZE)); - for (size_t j = 0; j < N_BMS; j++) { - size_t offset = BUFFER_BMS_OFFSET(j, COMM_GROUP_SIZE); + for (size_t j = 0; j < N_BMS; j++) { + size_t offset = BUFFER_BMS_OFFSET(j, COMM_GROUP_SIZE); - if (!(bms_mask & (1 << j))) - continue; // skip BMS that are not selected + if (!(bms_mask & (1 << j))) + continue; // skip BMS that are not selected - for (size_t k = 0; k < 3; k++) { - if (datalens[j] - (int)max_datalen < -1) { - continue; - } + for (size_t k = 0; k < 3; k++) { + if (datalens[j] - (int)max_datalen < -1) { + continue; + } - data[j][max_datalen - 1 + k] = buffer[offset + (k * 2) + 1]; - } - } + data[j][max_datalen - 1 + k] = buffer[offset + (k * 2) + 1]; + } + } - return HAL_OK; + return HAL_OK; } \ No newline at end of file diff --git a/AMS_Master_Code/Core/Lib/ADBMS6830B_Driver/Core/Src/ADBMS_HighLevel.c b/AMS_Master_Code/Core/Lib/ADBMS6830B_Driver/Core/Src/ADBMS_HighLevel.c index c15c922..4a1adb0 100644 --- a/AMS_Master_Code/Core/Lib/ADBMS6830B_Driver/Core/Src/ADBMS_HighLevel.c +++ b/AMS_Master_Code/Core/Lib/ADBMS6830B_Driver/Core/Src/ADBMS_HighLevel.c @@ -54,7 +54,7 @@ ADBMS_DetailedStatus AMS_Init(SPI_HandleTypeDef* hspi) { 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]; \ - if (x) { \ + if ((x)) { \ first_match = __any_intern_i; \ break; \ } \ @@ -68,7 +68,7 @@ ADBMS_DetailedStatus AMS_Idle_Loop() { // set_error_source(ERROR_SOURCE_INTERNAL); //so we can't tell if we timed out } - packetChecksumFails += amsAuxAndStatusMeasurement(&modules); + packetChecksumFails += (amsAuxAndStatusMeasurement(&modules) == HAL_ERROR); static int match = 0; if ((match = any(module.status.SLEEP))) { @@ -94,8 +94,8 @@ ADBMS_DetailedStatus AMS_Idle_Loop() { return (ADBMS_DetailedStatus){ADBMS_INTERNAL_BMS_FAULT, match}; } - packetChecksumFails += amsCellMeasurement(&modules); - packetChecksumFails += amsCheckUnderOverVoltage(&modules); + packetChecksumFails += (amsCellMeasurement(&modules) == HAL_ERROR); + packetChecksumFails += (amsCheckUnderOverVoltage(&modules) == HAL_ERROR); if (packetChecksumFails > MAX_PACKET_CHECKSUM_FAILS) { return (ADBMS_DetailedStatus){ADBMS_INTERNAL_BMS_CHECKSUM_FAIL, -1}; diff --git a/AMS_Master_Code/Core/Lib/ADBMS6830B_Driver/Core/Src/ADBMS_LL_Driver.c b/AMS_Master_Code/Core/Lib/ADBMS6830B_Driver/Core/Src/ADBMS_LL_Driver.c index 87a866f..243a34c 100644 --- a/AMS_Master_Code/Core/Lib/ADBMS6830B_Driver/Core/Src/ADBMS_LL_Driver.c +++ b/AMS_Master_Code/Core/Lib/ADBMS6830B_Driver/Core/Src/ADBMS_LL_Driver.c @@ -15,8 +15,6 @@ #define INITIAL_COMMAND_PEC 0x0010 #define INITIAL_DATA_PEC 0x0010 -#define ADBMS_SPI_TIMEOUT 100 // Timeout in ms -#warning ask about the timeout value SPI_HandleTypeDef* adbmsspi; diff --git a/AMS_Master_Code/STM32-for-VSCode.config.yaml b/AMS_Master_Code/STM32-for-VSCode.config.yaml index f83fb55..7e7ba5b 100644 --- a/AMS_Master_Code/STM32-for-VSCode.config.yaml +++ b/AMS_Master_Code/STM32-for-VSCode.config.yaml @@ -10,7 +10,7 @@ target: AMS Master Nucleo # Can be C or C++ language: C -optimization: Og +optimization: O2 # MCU settings targetMCU: stm32h7x @@ -43,6 +43,7 @@ cFlags: - -ffunction-sections - -std=gnu23 - -flto +# - -fanalyzer assemblyFlags: - -Wall