cleanup part 3

This commit is contained in:
Kilian Bracher 2025-05-09 02:08:11 +02:00
parent 686e26b609
commit d4dc7e4533
Signed by: k.bracher
SSH Key Fingerprint: SHA256:mXpyZkK7RDiJ7qeHCKJX108woM0cl5TrCvNBJASu6lM
18 changed files with 273 additions and 11445 deletions

View File

@ -1,7 +1,6 @@
#pragma once #pragma once
#ifndef __CONFIG_ADBMS6830_H #ifndef __CONFIG_ADBMS6830_H
#define __CONFIG_ADBMS6830_H #define __CONFIG_ADBMS6830_H
#include "main.h"
#define N_BMS 1 #define N_BMS 1
#define N_CELLS 16 #define N_CELLS 16
@ -9,15 +8,6 @@
#define ADBMS_SPI_TIMEOUT 50 // Timeout in ms #define ADBMS_SPI_TIMEOUT 50 // Timeout in ms
#define DEFAULT_UV 3000 // mV #define DEFAULT_UV 3000 // mV
#define DEFAULT_OV 4200 // mV #define DEFAULT_OV 4200 // mV
#define ERROR_TIME_THRESH 150 // ms
[[maybe_unused, gnu::always_inline]]
static inline void mcuAdbmsCSLow() {
HAL_GPIO_WritePin(AMS_CS_GPIO_Port, AMS_CS_Pin, GPIO_PIN_RESET);
}
[[maybe_unused, gnu::always_inline]]
static inline void mcuAdbmsCSHigh() {
HAL_GPIO_WritePin(AMS_CS_GPIO_Port, AMS_CS_Pin, GPIO_PIN_SET);
}
#endif //__CONFIG_ADBMS6830_H #endif //__CONFIG_ADBMS6830_H

View File

@ -1,216 +0,0 @@
---
Language: Cpp
# BasedOnStyle: LLVM
AccessModifierOffset: -2
AlignAfterOpenBracket: Align
AlignArrayOfStructures: None
AlignConsecutiveAssignments:
Enabled: false
AcrossEmptyLines: false
AcrossComments: false
AlignCompound: false
PadOperators: true
AlignConsecutiveBitFields:
Enabled: false
AcrossEmptyLines: false
AcrossComments: false
AlignCompound: false
PadOperators: false
AlignConsecutiveDeclarations:
Enabled: false
AcrossEmptyLines: false
AcrossComments: false
AlignCompound: false
PadOperators: false
AlignConsecutiveMacros:
Enabled: true
AcrossEmptyLines: false
AcrossComments: true
AlignCompound: false
PadOperators: false
AlignEscapedNewlines: Right
AlignOperands: Align
AlignTrailingComments: true
AllowAllArgumentsOnNextLine: true
AllowAllParametersOfDeclarationOnNextLine: true
AllowShortEnumsOnASingleLine: true
AllowShortBlocksOnASingleLine: Never
AllowShortCaseLabelsOnASingleLine: false
AllowShortFunctionsOnASingleLine: All
AllowShortLambdasOnASingleLine: All
AllowShortIfStatementsOnASingleLine: Never
AllowShortLoopsOnASingleLine: false
AlwaysBreakAfterDefinitionReturnType: None
AlwaysBreakAfterReturnType: None
AlwaysBreakBeforeMultilineStrings: false
AlwaysBreakTemplateDeclarations: MultiLine
AttributeMacros:
- __capability
BinPackArguments: true
BinPackParameters: true
BraceWrapping:
AfterCaseLabel: false
AfterClass: false
AfterControlStatement: Never
AfterEnum: false
AfterFunction: false
AfterNamespace: false
AfterObjCDeclaration: false
AfterStruct: false
AfterUnion: false
AfterExternBlock: false
BeforeCatch: false
BeforeElse: false
BeforeLambdaBody: false
BeforeWhile: false
IndentBraces: false
SplitEmptyFunction: true
SplitEmptyRecord: true
SplitEmptyNamespace: true
BreakBeforeBinaryOperators: None
BreakBeforeConceptDeclarations: Always
BreakBeforeBraces: Attach
BreakBeforeInheritanceComma: false
BreakInheritanceList: BeforeColon
BreakBeforeTernaryOperators: true
BreakConstructorInitializersBeforeComma: false
BreakConstructorInitializers: BeforeColon
BreakAfterJavaFieldAnnotations: false
BreakStringLiterals: true
ColumnLimit: 120
CommentPragmas: "^ IWYU pragma:"
QualifierAlignment: Leave
CompactNamespaces: false
ConstructorInitializerIndentWidth: 4
ContinuationIndentWidth: 4
Cpp11BracedListStyle: true
DeriveLineEnding: true
DerivePointerAlignment: false
DisableFormat: false
EmptyLineAfterAccessModifier: Never
EmptyLineBeforeAccessModifier: LogicalBlock
ExperimentalAutoDetectBinPacking: false
PackConstructorInitializers: BinPack
BasedOnStyle: ""
ConstructorInitializerAllOnOneLineOrOnePerLine: false
AllowAllConstructorInitializersOnNextLine: true
FixNamespaceComments: true
ForEachMacros:
- foreach
- Q_FOREACH
- BOOST_FOREACH
IfMacros:
- KJ_IF_MAYBE
IncludeBlocks: Preserve
IncludeCategories:
- Regex: '^"(llvm|llvm-c|clang|clang-c)/'
Priority: 2
SortPriority: 0
CaseSensitive: false
- Regex: '^(<|"(gtest|gmock|isl|json)/)'
Priority: 3
SortPriority: 0
CaseSensitive: false
- Regex: ".*"
Priority: 1
SortPriority: 0
CaseSensitive: false
IncludeIsMainRegex: "(Test)?$"
IncludeIsMainSourceRegex: ""
IndentAccessModifiers: false
IndentCaseLabels: false
IndentCaseBlocks: false
IndentGotoLabels: true
IndentPPDirectives: None
IndentExternBlock: AfterExternBlock
IndentRequiresClause: true
IndentWidth: 4
IndentWrappedFunctionNames: false
InsertBraces: false
InsertTrailingCommas: None
JavaScriptQuotes: Leave
JavaScriptWrapImports: true
KeepEmptyLinesAtTheStartOfBlocks: true
LambdaBodyIndentation: Signature
MacroBlockBegin: ""
MacroBlockEnd: ""
MaxEmptyLinesToKeep: 1
NamespaceIndentation: None
ObjCBinPackProtocolList: Auto
ObjCBlockIndentWidth: 2
ObjCBreakBeforeNestedBlockParam: true
ObjCSpaceAfterProperty: false
ObjCSpaceBeforeProtocolList: true
PenaltyBreakAssignment: 2
PenaltyBreakBeforeFirstCallParameter: 19
PenaltyBreakComment: 300
PenaltyBreakFirstLessLess: 120
PenaltyBreakOpenParenthesis: 0
PenaltyBreakString: 1000
PenaltyBreakTemplateDeclaration: 10
PenaltyExcessCharacter: 1000000
PenaltyReturnTypeOnItsOwnLine: 60
PenaltyIndentedWhitespace: 0
PointerAlignment: Left
PPIndentWidth: -1
ReferenceAlignment: Pointer
ReflowComments: true
RemoveBracesLLVM: false
RequiresClausePosition: OwnLine
SeparateDefinitionBlocks: Leave
ShortNamespaceLines: 1
SortIncludes: CaseSensitive
SortJavaStaticImport: Before
SortUsingDeclarations: true
SpaceAfterCStyleCast: false
SpaceAfterLogicalNot: false
SpaceAfterTemplateKeyword: true
SpaceBeforeAssignmentOperators: true
SpaceBeforeCaseColon: false
SpaceBeforeCpp11BracedList: false
SpaceBeforeCtorInitializerColon: true
SpaceBeforeInheritanceColon: true
SpaceBeforeParens: ControlStatements
SpaceBeforeParensOptions:
AfterControlStatements: true
AfterForeachMacros: true
AfterFunctionDefinitionName: false
AfterFunctionDeclarationName: false
AfterIfMacros: true
AfterOverloadedOperator: false
AfterRequiresInClause: false
AfterRequiresInExpression: false
BeforeNonEmptyParentheses: false
SpaceAroundPointerQualifiers: Default
SpaceBeforeRangeBasedForLoopColon: true
SpaceInEmptyBlock: false
SpaceInEmptyParentheses: false
SpacesBeforeTrailingComments: 1
SpacesInAngles: Never
SpacesInConditionalStatement: false
SpacesInContainerLiterals: true
SpacesInCStyleCastParentheses: false
SpacesInLineCommentPrefix:
Minimum: 1
Maximum: -1
SpacesInParentheses: false
SpacesInSquareBrackets: false
SpaceBeforeSquareBrackets: false
BitFieldColonSpacing: Both
Standard: Latest
StatementAttributeLikeMacros:
- Q_EMIT
StatementMacros:
- Q_UNUSED
- QT_REQUIRE_VERSION
TabWidth: 8
UseCRLF: false
UseTab: Never
WhitespaceSensitiveMacros:
- STRINGIZE
- PP_STRINGIZE
- BOOST_PP_STRINGIZE
- NS_SWIFT_NAME
- CF_SWIFT_NAME
---

View File

@ -1,9 +0,0 @@
/.vscode/
/build/
/Debug
/.cache/
.clangd
compile_commands.json
STM32Make.make
/.metadata/
openocd.cfg

File diff suppressed because it is too large Load Diff

View File

@ -1,39 +0,0 @@
#ifndef INC_ADBMS_ABSTRACTION_H_
#define INC_ADBMS_ABSTRACTION_H_
#include "ADBMS_Driver.h"
#define mV_from_ADBMS6830(x) (((((int16_t)(x))) * 0.150) + 1500)
// Macro to convert voltage in mV to the internal format for under/over voltage thresholds.
// Calculation: internal = (mV - 1500) / (16 * 0.15) = (mV - 1500) / 2.4.
// To perform integer arithmetic with rounding, we compute:
// internal = ((mV - 1500) * 5 + 6) / 12
#define mV_to_ADBMS6830(mV) ((((mV) - 1500) * 5 + 6) / 12)
HAL_StatusTypeDef amsReset();
HAL_StatusTypeDef initAMS(SPI_HandleTypeDef* hspi);
HAL_StatusTypeDef amsWakeUp();
HAL_StatusTypeDef amsCellMeasurement(Cell_Module (*module)[N_BMS]);
HAL_StatusTypeDef amsAuxAndStatusMeasurement(Cell_Module (*module)[N_BMS]);
HAL_StatusTypeDef amsConfigBalancing(const uint32_t channels[static N_BMS], uint8_t dutyCycle);
HAL_StatusTypeDef amsStartBalancing();
HAL_StatusTypeDef amsStopBalancing();
HAL_StatusTypeDef amsSelfTest();
HAL_StatusTypeDef amsConfigOverUnderVoltage(uint16_t overVoltage, uint16_t underVoltage); //arguments in mV
HAL_StatusTypeDef amsCheckUnderOverVoltage(Cell_Module (*module)[N_BMS]);
HAL_StatusTypeDef amsClearFlag();
HAL_StatusTypeDef amsClearAux();
HAL_StatusTypeDef amsClearOVUV();
HAL_StatusTypeDef amsReadCellVoltages(Cell_Module (*module)[N_BMS]);
#endif /* INC_ADBMS_ABSTRACTION_H_ */

View File

@ -0,0 +1,40 @@
#ifndef INC_ADBMS_ABSTRACTION_H_
#define INC_ADBMS_ABSTRACTION_H_
#include "ADBMS_Driver.h"
#include "ADBMS_Intern.h"
#define mV_from_ADBMS6830(x) (((((int16_t)(x))) * 0.150) + 1500)
// Macro to convert voltage in mV to the internal format for under/over voltage thresholds.
// Calculation: internal = (mV - 1500) / (16 * 0.15) = (mV - 1500) / 2.4.
// To perform integer arithmetic with rounding, we compute:
// internal = ((mV - 1500) * 5 + 6) / 12
#define mV_to_ADBMS6830(mV) ((((mV) - 1500) * 5 + 6) / 12)
ADBMS_Internal_Status amsReset();
ADBMS_Internal_Status initAMS(USER_PTR_TYPE ptr);
ADBMS_Internal_Status amsWakeUp();
ADBMS_Internal_Status amsCellMeasurement(Cell_Module (*module)[N_BMS]);
ADBMS_Internal_Status amsAuxAndStatusMeasurement(Cell_Module (*module)[N_BMS]);
ADBMS_Internal_Status amsConfigBalancing(const uint32_t channels[static N_BMS], uint8_t dutyCycle);
ADBMS_Internal_Status amsStartBalancing();
ADBMS_Internal_Status amsStopBalancing();
ADBMS_Internal_Status amsSelfTest();
ADBMS_Internal_Status amsConfigOverUnderVoltage(uint16_t overVoltage, uint16_t underVoltage); //arguments in mV
ADBMS_Internal_Status amsCheckUnderOverVoltage(Cell_Module (*module)[N_BMS]);
ADBMS_Internal_Status amsClearFlag();
ADBMS_Internal_Status amsClearAux();
ADBMS_Internal_Status amsClearOVUV();
ADBMS_Internal_Status amsReadCellVoltages(Cell_Module (*module)[N_BMS]);
#endif /* INC_ADBMS_ABSTRACTION_H_ */

View File

@ -1,11 +1,10 @@
#ifndef ADBMS_DRIVER_H #ifndef ADBMS_DRIVER_H
#define ADBMS_DRIVER_H #define ADBMS_DRIVER_H
#include "ADBMS_Intern.h"
#include "config_ADBMS6830.h" #include "config_ADBMS6830.h"
#include <stdint.h> #include <stdint.h>
#define ERROR_TIME_THRESH 150 // ms
typedef enum : uint16_t { typedef enum : uint16_t {
ADBMS_NO_ERROR = 0, ADBMS_NO_ERROR = 0,
ADBMS_OVERTEMP, ADBMS_OVERTEMP,
@ -91,7 +90,7 @@ typedef struct {
extern Cell_Module modules[N_BMS]; extern Cell_Module modules[N_BMS];
[[gnu::nonnull]] ADBMS_DetailedStatus AMS_Init(SPI_HandleTypeDef* hspi); [[gnu::nonnull]] ADBMS_DetailedStatus AMS_Init(USER_PTR_TYPE ptr);
ADBMS_DetailedStatus AMS_Idle_Loop(); ADBMS_DetailedStatus AMS_Idle_Loop();

View File

@ -0,0 +1,83 @@
#pragma once
#ifndef __ADBMS_INTERN_H
#define __ADBMS_INTERN_H
#include <stdint.h>
#include "stm32h7xx_hal.h"
#include "main.h"
typedef enum {
ADBMS_OK = 0,
ADBMS_ERROR,
ADBMS_BUSY,
ADBMS_TIMEOUT,
} ADBMS_Internal_Status;
[[maybe_unused, gnu::always_inline]]
static inline void mcuAdbmsCSLow() {
HAL_GPIO_WritePin(AMS_CS_GPIO_Port, AMS_CS_Pin, GPIO_PIN_RESET);
}
[[maybe_unused, gnu::always_inline]]
static inline void mcuAdbmsCSHigh() {
HAL_GPIO_WritePin(AMS_CS_GPIO_Port, AMS_CS_Pin, GPIO_PIN_SET);
}
// user_ptr is passed to AMS_Init and could be used to pass the SPI handle
// the BMS code does not modify it in any way
#define USER_PTR_TYPE SPI_HandleTypeDef*
[[maybe_unused, gnu::always_inline, gnu::access(read_only, 2, 3), gnu::nonnull(1)]]
static inline ADBMS_Internal_Status mcuSPITransmit(USER_PTR_TYPE user_ptr, const uint8_t* buffer, uint8_t buffersize, uint32_t timeout) {
const HAL_StatusTypeDef status = HAL_SPI_Transmit(user_ptr, buffer, buffersize, timeout);
return (status == HAL_OK) ? ADBMS_OK : ADBMS_ERROR;
}
[[maybe_unused, gnu::always_inline, gnu::access(read_write, 2, 3), gnu::nonnull(1)]]
static inline ADBMS_Internal_Status mcuSPIReceive(USER_PTR_TYPE user_ptr, uint8_t* buffer, uint8_t buffersize, uint32_t timeout) {
const HAL_StatusTypeDef status = HAL_SPI_Receive(user_ptr, buffer, buffersize, timeout);
return (status == HAL_OK) ? ADBMS_OK : ADBMS_ERROR;
}
[[maybe_unused, gnu::always_inline, gnu::access(read_write, 2, 4), gnu::access(read_only, 3, 4), gnu::nonnull(1, 2)]]
static inline ADBMS_Internal_Status mcuSPITransmitReceive(USER_PTR_TYPE user_ptr, uint8_t* rxbuffer, const uint8_t* txbuffer, uint8_t buffersize, uint32_t timeout) {
const HAL_StatusTypeDef status = HAL_SPI_TransmitReceive(user_ptr, txbuffer, rxbuffer, buffersize, timeout);
return (status == HAL_OK) ? ADBMS_OK : ADBMS_ERROR;
}
// Delay by `delay` milliseconds
[[maybe_unused, gnu::always_inline]]
static inline void mcuDelay(uint32_t delay) {
HAL_Delay(delay);
}
// Optional logging, leave as is if not needed
#if !ADBMS_NO_LOGGING_DEFS
#define LOG_PREFIX "[ADBMS] "
#include "log.h"
enum {
ADBMS_LOG_LEVEL_FATAL = 0,
ADBMS_LOG_LEVEL_ERROR,
ADBMS_LOG_LEVEL_WARNING,
ADBMS_LOG_LEVEL_INFO,
ADBMS_LOG_LEVEL_DEBUG,
ADBMS_LOG_LEVEL_NOISY,
};
// Returns a timestamp in milliseconds
// Only used for logging
[[maybe_unused, gnu::always_inline]]
static inline uint32_t mcuGetTime() {
return HAL_GetTick();
}
#define debug_log(level, ...) log_message((log_level_t)level, __VA_ARGS__)
#define debug_log_cont(level, ...) log_message_cont((log_level_t)level, __VA_ARGS__)
#define DEBUG_CHANNEL_ENABLED(level) log_is_level_enabled((log_level_t)level)
#endif // ADBMS_NO_LOGGING_DEFS
#endif // __ADBMS_INTERN_H

View File

@ -2,11 +2,10 @@
#define ADBMS_LL_DRIVER_H_ #define ADBMS_LL_DRIVER_H_
#include "config_ADBMS6830.h" #include "config_ADBMS6830.h"
#include "ADBMS_Intern.h"
#include <stddef.h>
#include <stdint.h> #include <stdint.h>
uint8_t adbmsDriverInit(SPI_HandleTypeDef* hspi);
//2 command + 2 PEC + (data + 2 DPEC) per BMS //2 command + 2 PEC + (data + 2 DPEC) per BMS
#define CMD_BUFFER_SIZE(datalen) (4 + (N_BMS * ((datalen) + 2))) #define CMD_BUFFER_SIZE(datalen) (4 + (N_BMS * ((datalen) + 2)))
@ -15,32 +14,31 @@ uint8_t adbmsDriverInit(SPI_HandleTypeDef* hspi);
#define CMD_EMPTY_BUFFER ((uint8_t[CMD_BUFFER_SIZE(0)]){0}) #define CMD_EMPTY_BUFFER ((uint8_t[CMD_BUFFER_SIZE(0)]){0})
#define CMD_EMPTY_BUFFER_SIZE CMD_BUFFER_SIZE(0) #define CMD_EMPTY_BUFFER_SIZE CMD_BUFFER_SIZE(0)
HAL_StatusTypeDef ___writeCMD(uint16_t command, uint8_t * args, size_t arglen); ADBMS_Internal_Status ___writeCMD(uint16_t command, uint8_t * args, size_t arglen);
[[gnu::access(read_write, 2, 4), gnu::nonnull(2), gnu::always_inline]] //add dummy size variable for bounds checking, should be optimized out [[gnu::access(read_write, 2, 4), gnu::nonnull(2), gnu::always_inline]] //add dummy size variable for bounds checking, should be optimized out
static inline HAL_StatusTypeDef __writeCMD(uint16_t command, uint8_t * args, size_t arglen, size_t) { static inline ADBMS_Internal_Status __writeCMD(uint16_t command, uint8_t * args, size_t arglen, size_t) {
return ___writeCMD(command, args, arglen); return ___writeCMD(command, args, arglen);
} }
#define writeCMD(command, args, arglen) \ #define writeCMD(command, args, arglen) \
__writeCMD(command, args, arglen, CMD_BUFFER_SIZE(arglen)) __writeCMD(command, args, arglen, CMD_BUFFER_SIZE(arglen))
HAL_StatusTypeDef ___readCMD(uint16_t command, uint8_t * buffer, size_t arglen); ADBMS_Internal_Status ___readCMD(uint16_t command, uint8_t * buffer, size_t arglen);
[[gnu::access(read_write, 2, 4), gnu::nonnull(2), gnu::always_inline]] //add dummy size variable for bounds checking, should be optimized out [[gnu::access(read_write, 2, 4), gnu::nonnull(2), gnu::always_inline]] //add dummy size variable for bounds checking, should be optimized out
static inline HAL_StatusTypeDef __readCMD(uint16_t command, uint8_t * buffer, size_t arglen, size_t) { static inline ADBMS_Internal_Status __readCMD(uint16_t command, uint8_t * buffer, size_t arglen, size_t) {
return ___readCMD(command, buffer, arglen); return ___readCMD(command, buffer, arglen);
} }
#define readCMD(command, buffer, buflen) \ #define readCMD(command, buffer, buflen) \
__readCMD(command, buffer, buflen, CMD_BUFFER_SIZE(buflen)) __readCMD(command, buffer, buflen, CMD_BUFFER_SIZE(buflen))
HAL_StatusTypeDef __pollCMD(uint16_t command, uint8_t waitTime); ADBMS_Internal_Status __pollCMD(uint16_t command, uint8_t waitTime);
#define pollCMD(command) \ #define pollCMD(command) \
__pollCMD(command, (N_BMS * 2) + 1) //poll is only valid after 2 * N_BMS clock cycles, +1 for safety, see datasheet page 55 __pollCMD(command, (N_BMS * 2) + 1) //poll is only valid after 2 * N_BMS clock cycles, +1 for safety, see datasheet page 55
uint8_t wakeUpCmd(); void initSPI(USER_PTR_TYPE ptr);
static inline void mcuDelay(uint16_t delay) { HAL_Delay(delay); };
#endif /* ADBMS_LL_DRIVER_H_ */ #endif /* ADBMS_LL_DRIVER_H_ */

View File

@ -2,32 +2,31 @@
#include "ADBMS_CMD_Defines.h" #include "ADBMS_CMD_Defines.h"
#include "ADBMS_LL_Driver.h" #include "ADBMS_LL_Driver.h"
#include "config_ADBMS6830.h" #include "config_ADBMS6830.h"
#include "ADBMS_Intern.h"
#include <stddef.h> #include <stddef.h>
#define SWO_LOG_PREFIX "[ADBMS] "
#include "swo_log.h"
static const char* const HAL_Statuses[] = {"HAL_OK", "HAL_ERROR", "HAL_BUSY", "HAL_TIMEOUT"}; static const char* const ADBMS_Statuses[] = {"ADBMS_OK", "ADBMS_ERROR", "ADBMS_BUSY", "ADBMS_TIMEOUT"};
#define CHECK_RETURN(x) \ #define CHECK_RETURN(x) \
do { \ do { \
HAL_StatusTypeDef status = x; \ ADBMS_Internal_Status status = x; \
if (status != 0) { \ if (status != 0) { \
debug_log(LOG_LEVEL_ERROR, "in %s:%d@%s: %s failed with status %d (%s)", __FILE_NAME__, __LINE__, __func__,\ debug_log(ADBMS_LOG_LEVEL_ERROR, "in %s:%d@%s: %s failed with status %d (%s)", __FILE_NAME__, __LINE__, __func__,\
#x, status, \ #x, status, \
(status < (sizeof(HAL_Statuses) / sizeof(HAL_Statuses[0]))) ? HAL_Statuses[status] : "Unknown"); \ (status < (sizeof(ADBMS_Statuses) / sizeof(ADBMS_Statuses[0]))) ? ADBMS_Statuses[status] : "Unknown"); \
return status; \ return status; \
} \ } \
} while (0) } while (0)
HAL_StatusTypeDef amsReset() { ADBMS_Internal_Status amsReset() {
amsWakeUp(); amsWakeUp();
readCMD(SRST, CMD_EMPTY_BUFFER, 0); readCMD(SRST, CMD_EMPTY_BUFFER, 0);
amsWakeUp(); amsWakeUp();
uint8_t sidbuffer[CMD_BUFFER_SIZE(SID_GROUP_SIZE)] = {}; uint8_t sidbuffer[CMD_BUFFER_SIZE(SID_GROUP_SIZE)] = {};
if (readCMD(RDSID, sidbuffer, SID_GROUP_SIZE) != HAL_OK) { if (readCMD(RDSID, sidbuffer, SID_GROUP_SIZE) != ADBMS_OK) {
bool nonzero = false; bool nonzero = false;
for (size_t i = 0; i < N_BMS; i++) { for (size_t i = 0; i < N_BMS; i++) {
if (sidbuffer[BUFFER_BMS_OFFSET(i, SID_GROUP_SIZE)] != 0) { if (sidbuffer[BUFFER_BMS_OFFSET(i, SID_GROUP_SIZE)] != 0) {
@ -35,27 +34,27 @@ HAL_StatusTypeDef amsReset() {
} }
} }
if (nonzero) { if (nonzero) {
debug_log(LOG_LEVEL_ERROR, debug_log(ADBMS_LOG_LEVEL_ERROR,
"CRC failure when reading BMS IDs, but some IDs are nonzero. --- Intermittent connection?"); "CRC failure when reading BMS IDs, but some IDs are nonzero. --- Intermittent connection?");
} else { } else {
debug_log(LOG_LEVEL_ERROR, "CRC failure when reading BMS IDs, all IDs are zero. --- No connection?"); debug_log(ADBMS_LOG_LEVEL_ERROR, "CRC failure when reading BMS IDs, all IDs are zero. --- No connection?");
} }
return HAL_ERROR; return ADBMS_ERROR;
} }
debug_log(LOG_LEVEL_INFO, "BMS reset complete"); debug_log(ADBMS_LOG_LEVEL_INFO, "BMS reset complete");
if (DEBUG_CHANNEL_ENABLED(LOG_LEVEL_INFO)) { if (DEBUG_CHANNEL_ENABLED(ADBMS_LOG_LEVEL_INFO)) {
debug_log(LOG_LEVEL_INFO, "Found IDs: "); debug_log(ADBMS_LOG_LEVEL_INFO, "Found IDs: ");
for (size_t i = 0; i < N_BMS; i++) { for (size_t i = 0; i < N_BMS; i++) {
uint64_t id = 0; uint64_t id = 0;
for (size_t j = 0; j < SID_GROUP_SIZE; j++) { for (size_t j = 0; j < SID_GROUP_SIZE; j++) {
id |= sidbuffer[BUFFER_BMS_OFFSET(i, SID_GROUP_SIZE) + j] << (j * 8); id |= sidbuffer[BUFFER_BMS_OFFSET(i, SID_GROUP_SIZE) + j] << (j * 8);
} }
modules[i].bmsID = id; modules[i].bmsID = id;
debug_log_cont(LOG_LEVEL_INFO, "0x%08lx%08lx ", (uint32_t)(id >> 32), (uint32_t)(id & 0xFFFFFFFF)); //newlib does not support %llu debug_log_cont(ADBMS_LOG_LEVEL_INFO, "0x%08lx%08lx ", (uint32_t)(id >> 32), (uint32_t)(id & 0xFFFFFFFF)); //newlib does not support %llu
} }
} }
@ -72,27 +71,25 @@ HAL_StatusTypeDef amsReset() {
CHECK_RETURN(writeCMD(ADCV | ADCV_CONT | ADCV_RD, flagsbuffer, 0)); //start continuous cell voltage measurement with redundancy 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 CHECK_RETURN(writeCMD(ADAX | ADAX_CONV_ALL, flagsbuffer, 0)); //start aux measurement
return HAL_OK; return ADBMS_OK;
} }
HAL_StatusTypeDef initAMS(SPI_HandleTypeDef* hspi) { ADBMS_Internal_Status initAMS(USER_PTR_TYPE ptr) {
// pull MSTR High for Microcontroller mode ADBMS6822 initSPI(ptr); // Initialize the SPI interface
HAL_GPIO_WritePin(MSTR1_GPIO_Port, MSTR1_Pin, GPIO_PIN_SET);
adbmsDriverInit(hspi);
return amsReset(); return amsReset();
} }
HAL_StatusTypeDef amsWakeUp() { ADBMS_Internal_Status amsWakeUp() {
return __pollCMD(PLADC, 100); //wake up ADBMS6830, wait for T_wake = 200 us (100 cycles at 500 kHz) return __pollCMD(PLADC, 100); //wake up ADBMS6830, wait for T_wake = 200 us (100 cycles at 500 kHz)
} }
HAL_StatusTypeDef amsCellMeasurement(Cell_Module (*module)[N_BMS]) { ADBMS_Internal_Status amsCellMeasurement(Cell_Module (*module)[N_BMS]) {
#warning check conversion counter to ensure that continuous conversion has not been stopped #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 #warning check for OW conditions: ADSV | ADSV_OW_0 / ADSV_OW_1
return amsReadCellVoltages(module); return amsReadCellVoltages(module);
} }
HAL_StatusTypeDef amsAuxAndStatusMeasurement(Cell_Module (*module)[N_BMS]) { ADBMS_Internal_Status 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)); CHECK_RETURN(readCMD(RDSTATC, rxbuf, STATUS_GROUP_C_SIZE));
for (size_t i = 0; i < N_BMS; i++) { for (size_t i = 0; i < N_BMS; i++) {
@ -117,8 +114,8 @@ HAL_StatusTypeDef amsAuxAndStatusMeasurement(Cell_Module (*module)[N_BMS]) {
(*module)[i].status.OSCCHK = (rxbuf[offset + 5] >> 0) & 0x01; (*module)[i].status.OSCCHK = (rxbuf[offset + 5] >> 0) & 0x01;
} }
if (pollCMD(PLAUX) == HAL_BUSY) { if (pollCMD(PLAUX) == ADBMS_BUSY) {
// return HAL_BUSY; // return ADBMS_BUSY;
} }
constexpr size_t auxGroupSizes[] = {AUX_GROUP_A_SIZE, AUX_GROUP_B_SIZE, AUX_GROUP_C_SIZE, AUX_GROUP_D_SIZE}; constexpr size_t auxGroupSizes[] = {AUX_GROUP_A_SIZE, AUX_GROUP_B_SIZE, AUX_GROUP_C_SIZE, AUX_GROUP_D_SIZE};
@ -153,12 +150,12 @@ HAL_StatusTypeDef amsAuxAndStatusMeasurement(Cell_Module (*module)[N_BMS]) {
CHECK_RETURN(writeCMD(ADAX | ADAX_CONV_ALL, rxbuf, 0)); // start aux conversion for next iteration CHECK_RETURN(writeCMD(ADAX | ADAX_CONV_ALL, rxbuf, 0)); // start aux conversion for next iteration
return HAL_OK; return ADBMS_OK;
} }
HAL_StatusTypeDef amsConfigBalancing(const uint32_t channels[static N_BMS], uint8_t dutyCycle) { ADBMS_Internal_Status amsConfigBalancing(const uint32_t channels[static N_BMS], uint8_t dutyCycle) {
if (dutyCycle > 0x0F) { if (dutyCycle > 0x0F) {
return HAL_ERROR; // only 4 bits are allowed for dutyCycle return ADBMS_ERROR; // only 4 bits are allowed for dutyCycle
} }
uint8_t rxbufA[CMD_BUFFER_SIZE(PWM_GROUP_A_SIZE)] = {}; uint8_t rxbufA[CMD_BUFFER_SIZE(PWM_GROUP_A_SIZE)] = {};
@ -184,13 +181,13 @@ HAL_StatusTypeDef amsConfigBalancing(const uint32_t channels[static N_BMS], uint
// log the new PWM settings // log the new PWM settings
// output is: PWM - [BMS_ID]: [PWM0] ... [PWM16] // output is: PWM - [BMS_ID]: [PWM0] ... [PWM16]
if (DEBUG_CHANNEL_ENABLED(LOG_LEVEL_DEBUG)) { if (DEBUG_CHANNEL_ENABLED(ADBMS_LOG_LEVEL_DEBUG)) {
debug_log(LOG_LEVEL_DEBUG, "PWM - %d: ", i); debug_log(ADBMS_LOG_LEVEL_DEBUG, "PWM - %d: ", i);
for (size_t j = 0; j < 6; j++) { for (size_t j = 0; j < 6; j++) {
debug_log_cont(LOG_LEVEL_DEBUG, "%x %x ", rxbufA[offsetA + j] & 0x0F, rxbufA[offsetA + j] >> 4); debug_log_cont(ADBMS_LOG_LEVEL_DEBUG, "%x %x ", rxbufA[offsetA + j] & 0x0F, rxbufA[offsetA + j] >> 4);
} }
for (size_t j = 0; j < 2; j++) { 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(ADBMS_LOG_LEVEL_DEBUG, "%x %x ", rxbufB[offsetB + j] & 0x0F, rxbufB[offsetB + j] >> 4);
} }
} }
} }
@ -198,19 +195,19 @@ HAL_StatusTypeDef amsConfigBalancing(const uint32_t channels[static N_BMS], uint
CHECK_RETURN(writeCMD(WRPWMA, rxbufA, PWM_GROUP_A_SIZE)); CHECK_RETURN(writeCMD(WRPWMA, rxbufA, PWM_GROUP_A_SIZE));
CHECK_RETURN(writeCMD(WRPWMB, rxbufB, PWM_GROUP_B_SIZE)); CHECK_RETURN(writeCMD(WRPWMB, rxbufB, PWM_GROUP_B_SIZE));
return HAL_OK; return ADBMS_OK;
} }
HAL_StatusTypeDef amsStartBalancing() { return writeCMD(UNMUTE, CMD_EMPTY_BUFFER, 0); } ADBMS_Internal_Status amsStartBalancing() { return writeCMD(UNMUTE, CMD_EMPTY_BUFFER, 0); }
HAL_StatusTypeDef amsStopBalancing() { return writeCMD(MUTE, CMD_EMPTY_BUFFER, 0); } ADBMS_Internal_Status amsStopBalancing() { return writeCMD(MUTE, CMD_EMPTY_BUFFER, 0); }
HAL_StatusTypeDef amsSelfTest() { return 0; } ADBMS_Internal_Status amsSelfTest() { return 0; }
HAL_StatusTypeDef amsConfigOverUnderVoltage(uint16_t overVoltage, uint16_t underVoltage) { ADBMS_Internal_Status 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)] = {};
debug_log(LOG_LEVEL_INFO, "Configuring OV/UV thresholds to %u mV (%u internal) / %u mV (%u internal)", overVoltage, debug_log(ADBMS_LOG_LEVEL_INFO, "Configuring OV/UV thresholds to %u mV (%u internal) / %u mV (%u internal)", overVoltage,
mV_to_ADBMS6830(overVoltage), underVoltage, mV_to_ADBMS6830(underVoltage)); mV_to_ADBMS6830(overVoltage), underVoltage, mV_to_ADBMS6830(underVoltage));
CHECK_RETURN(readCMD(RDCFGB, buffer, CFG_GROUP_B_SIZE)); CHECK_RETURN(readCMD(RDCFGB, buffer, CFG_GROUP_B_SIZE));
@ -219,8 +216,8 @@ HAL_StatusTypeDef amsConfigOverUnderVoltage(uint16_t overVoltage, uint16_t under
underVoltage = mV_to_ADBMS6830(underVoltage); underVoltage = mV_to_ADBMS6830(underVoltage);
if (underVoltage & 0xF000 || overVoltage & 0xF000) { // only 12 bits allowed if (underVoltage & 0xF000 || overVoltage & 0xF000) { // only 12 bits allowed
debug_log(LOG_LEVEL_ERROR, "Invalid OV/UV thresholds: %u mV / %u mV", overVoltage, underVoltage); debug_log(ADBMS_LOG_LEVEL_ERROR, "Invalid OV/UV thresholds: %u mV / %u mV", overVoltage, underVoltage);
return HAL_ERROR; return ADBMS_ERROR;
} }
for (size_t i = 0; i < N_BMS; i++) { for (size_t i = 0; i < N_BMS; i++) {
@ -240,7 +237,7 @@ HAL_StatusTypeDef amsConfigOverUnderVoltage(uint16_t overVoltage, uint16_t under
return writeCMD(WRCFGB, buffer, CFG_GROUP_B_SIZE); return writeCMD(WRCFGB, buffer, CFG_GROUP_B_SIZE);
} }
HAL_StatusTypeDef amsCheckUnderOverVoltage(Cell_Module (*module)[N_BMS]) { ADBMS_Internal_Status amsCheckUnderOverVoltage(Cell_Module (*module)[N_BMS]) {
uint8_t regbuffer[CMD_BUFFER_SIZE(STATUS_GROUP_D_SIZE)] = {}; uint8_t regbuffer[CMD_BUFFER_SIZE(STATUS_GROUP_D_SIZE)] = {};
CHECK_RETURN(readCMD(RDSTATD, regbuffer, STATUS_GROUP_D_SIZE)); CHECK_RETURN(readCMD(RDSTATD, regbuffer, STATUS_GROUP_D_SIZE));
@ -265,19 +262,19 @@ HAL_StatusTypeDef amsCheckUnderOverVoltage(Cell_Module (*module)[N_BMS]) {
return writeCMD(CLOVUV, buffer, STATUS_GROUP_D_SIZE); // flags are latched, so we need to clear them return writeCMD(CLOVUV, buffer, STATUS_GROUP_D_SIZE); // flags are latched, so we need to clear them
} }
HAL_StatusTypeDef amsClearFlag() { ADBMS_Internal_Status amsClearFlag() {
uint8_t buffer[CMD_BUFFER_SIZE(6)] = {[0 ... CMD_BUFFER_SIZE(6) - 1] = 0xFF}; uint8_t buffer[CMD_BUFFER_SIZE(6)] = {[0 ... CMD_BUFFER_SIZE(6) - 1] = 0xFF};
return writeCMD(CLRFLAG, buffer, 6); return writeCMD(CLRFLAG, buffer, 6);
} }
HAL_StatusTypeDef amsClearAux() { return writeCMD(CLRAUX, CMD_EMPTY_BUFFER, 0); } ADBMS_Internal_Status amsClearAux() { return writeCMD(CLRAUX, CMD_EMPTY_BUFFER, 0); }
HAL_StatusTypeDef amsClearOVUV() { ADBMS_Internal_Status amsClearOVUV() {
uint8_t buffer[CMD_BUFFER_SIZE(6)] = {[0 ... CMD_BUFFER_SIZE(6) - 1] = 0xFF}; uint8_t buffer[CMD_BUFFER_SIZE(6)] = {[0 ... CMD_BUFFER_SIZE(6) - 1] = 0xFF};
return writeCMD(CLOVUV, buffer, 6); return writeCMD(CLOVUV, buffer, 6);
} }
HAL_StatusTypeDef amsReadCellVoltages(Cell_Module (*module)[N_BMS]) { ADBMS_Internal_Status 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)); CHECK_RETURN(readCMD(RDCVA, rxbuffer, CV_GROUP_A_SIZE));
@ -326,12 +323,12 @@ HAL_StatusTypeDef amsReadCellVoltages(Cell_Module (*module)[N_BMS]) {
(*module)[i].cellVoltages[15] = mV_from_ADBMS6830(rxbuffer[offset + 0] | (rxbuffer[offset + 1] << 8)); (*module)[i].cellVoltages[15] = mV_from_ADBMS6830(rxbuffer[offset + 0] | (rxbuffer[offset + 1] << 8));
} }
return HAL_OK; return ADBMS_OK;
} }
// Each selected BMS must have a corresponding address, and the data array for that BMS must be at least datalens[i] // Each selected BMS must have a corresponding address, and the data array for that BMS must be at least datalens[i]
// bytes long // bytes long
HAL_StatusTypeDef amsSendI2C(const uint8_t addresses[static N_BMS], uint8_t* data[static N_BMS], ADBMS_Internal_Status 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) { const uint8_t datalens[static N_BMS], uint32_t bms_mask) {
uint8_t buffer[CMD_BUFFER_SIZE(COMM_GROUP_SIZE)] = {}; uint8_t buffer[CMD_BUFFER_SIZE(COMM_GROUP_SIZE)] = {};
@ -402,12 +399,12 @@ HAL_StatusTypeDef amsSendI2C(const uint8_t addresses[static N_BMS], uint8_t* dat
CHECK_RETURN(writeCMD(WRCOMM, buffer, COMM_GROUP_SIZE)); CHECK_RETURN(writeCMD(WRCOMM, buffer, COMM_GROUP_SIZE));
__pollCMD(STCOMM, 72); __pollCMD(STCOMM, 72);
return HAL_OK; return ADBMS_OK;
} }
// Each selected BMS must have a corresponding address, and the data array for that BMS must be at least datalens[i] // Each selected BMS must have a corresponding address, and the data array for that BMS must be at least datalens[i]
// bytes long // bytes long
HAL_StatusTypeDef amsReadI2C(const uint8_t addresses[static N_BMS], uint8_t* data[static N_BMS], ADBMS_Internal_Status 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) { const uint8_t datalens[static N_BMS], uint32_t bms_mask) {
uint8_t buffer[CMD_BUFFER_SIZE(COMM_GROUP_SIZE)] = {}; uint8_t buffer[CMD_BUFFER_SIZE(COMM_GROUP_SIZE)] = {};
@ -511,5 +508,5 @@ HAL_StatusTypeDef amsReadI2C(const uint8_t addresses[static N_BMS], uint8_t* dat
} }
} }
return HAL_OK; return ADBMS_OK;
} }

View File

@ -1,12 +1,10 @@
#include "ADBMS_Abstraction.h" #include "ADBMS_Abstraction.h"
#include "ADBMS_Driver.h" #include "ADBMS_Driver.h"
#include "config_ADBMS6830.h" #include "config_ADBMS6830.h"
#include "stm32h7xx_hal.h" #include "ADBMS_Intern.h"
#include <stdint.h> #include <stdint.h>
#include <string.h> #include <string.h>
#define SWO_LOG_PREFIX "[ADBMS] "
#include "swo_log.h"
Cell_Module modules[N_BMS] = {}; Cell_Module modules[N_BMS] = {};
@ -25,15 +23,14 @@ struct pollingTimes pollingTimes = {0, 0};
static constexpr ADBMS_DetailedStatus NO_ERROR = {ADBMS_NO_ERROR}; static constexpr ADBMS_DetailedStatus NO_ERROR = {ADBMS_NO_ERROR};
ADBMS_DetailedStatus AMS_Init(SPI_HandleTypeDef* hspi) { ADBMS_DetailedStatus AMS_Init(USER_PTR_TYPE ptr) {
debug_log(LOG_LEVEL_INFO, "ADBMS6830B HAL - configured for %d controllers and %d cells per controller...", N_BMS, debug_log(ADBMS_LOG_LEVEL_INFO, "ADBMS6830B HAL - configured for %d controllers and %d cells per controller...", N_BMS,
N_CELLS); N_CELLS);
if (initAMS(hspi) != HAL_OK) { if (initAMS(ptr) != ADBMS_OK) {
debug_log(LOG_LEVEL_ERROR, "ADBMS6830B HAL - initialization failed"); debug_log(ADBMS_LOG_LEVEL_ERROR, "ADBMS6830B HAL - initialization failed");
return (ADBMS_DetailedStatus){ADBMS_INTERNAL_BMS_FAULT, -1}; return (ADBMS_DetailedStatus){ADBMS_INTERNAL_BMS_FAULT, -1};
} }
pollingTimes = (struct pollingTimes){HAL_GetTick(), HAL_GetTick()};
packetChecksumFails = 0; packetChecksumFails = 0;
deviceSleeps = 0; deviceSleeps = 0;
return NO_ERROR; return NO_ERROR;
@ -58,7 +55,7 @@ ADBMS_DetailedStatus AMS_Idle_Loop() {
// 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
} }
packetChecksumFails += (amsAuxAndStatusMeasurement(&modules) == HAL_ERROR); packetChecksumFails += (amsAuxAndStatusMeasurement(&modules) == ADBMS_ERROR);
int match = 0; int match = 0;
if ((match = any(module.status.SLEEP))) { if ((match = any(module.status.SLEEP))) {
@ -66,7 +63,7 @@ ADBMS_DetailedStatus AMS_Idle_Loop() {
if (deviceSleeps > MAX_DEVICE_SLEEP) { if (deviceSleeps > MAX_DEVICE_SLEEP) {
return (ADBMS_DetailedStatus){ADBMS_INTERNAL_BMS_TIMEOUT, match - 1}; return (ADBMS_DetailedStatus){ADBMS_INTERNAL_BMS_TIMEOUT, match - 1};
} else { } else {
debug_log(LOG_LEVEL_WARNING, "BMS %d unexpectedly in sleep mode, resetting...", match - 1); debug_log(ADBMS_LOG_LEVEL_WARNING, "BMS %d unexpectedly in sleep mode, resetting...", match - 1);
amsReset(); amsReset();
} }
} }
@ -77,22 +74,22 @@ ADBMS_DetailedStatus AMS_Idle_Loop() {
// iteration. // iteration.
amsClearFlag(); amsClearFlag();
// Log specific BMS fault details // Log specific BMS fault details
debug_log(LOG_LEVEL_ERROR, "Fault on BMS %d: ", match - 1); debug_log(ADBMS_LOG_LEVEL_ERROR, "Fault on BMS %d: ", match - 1);
auto faultyModule = &modules[match - 1]; auto faultyModule = &modules[match - 1];
if (faultyModule->status.CS_FLT) debug_log_cont(LOG_LEVEL_ERROR, "CS_FLT "); if (faultyModule->status.CS_FLT) debug_log_cont(ADBMS_LOG_LEVEL_ERROR, "CS_FLT ");
if (faultyModule->status.SPIFLT) debug_log_cont(LOG_LEVEL_ERROR, "SPIFLT "); if (faultyModule->status.SPIFLT) debug_log_cont(ADBMS_LOG_LEVEL_ERROR, "SPIFLT ");
if (faultyModule->status.CMED) debug_log_cont(LOG_LEVEL_ERROR, "CMED "); if (faultyModule->status.CMED) debug_log_cont(ADBMS_LOG_LEVEL_ERROR, "CMED ");
if (faultyModule->status.SMED) debug_log_cont(LOG_LEVEL_ERROR, "SMED "); if (faultyModule->status.SMED) debug_log_cont(ADBMS_LOG_LEVEL_ERROR, "SMED ");
if (faultyModule->status.VDE) debug_log_cont(LOG_LEVEL_ERROR, "VDE "); if (faultyModule->status.VDE) debug_log_cont(ADBMS_LOG_LEVEL_ERROR, "VDE ");
if (faultyModule->status.VDEL) debug_log_cont(LOG_LEVEL_ERROR, "VDEL "); if (faultyModule->status.VDEL) debug_log_cont(ADBMS_LOG_LEVEL_ERROR, "VDEL ");
if (faultyModule->status.OSCCHK) debug_log_cont(LOG_LEVEL_ERROR, "OSCCHK "); if (faultyModule->status.OSCCHK) debug_log_cont(ADBMS_LOG_LEVEL_ERROR, "OSCCHK ");
if (faultyModule->status.TMODCHK) debug_log_cont(LOG_LEVEL_ERROR, "TMODCHK "); if (faultyModule->status.TMODCHK) debug_log_cont(ADBMS_LOG_LEVEL_ERROR, "TMODCHK ");
return (ADBMS_DetailedStatus){ADBMS_INTERNAL_BMS_FAULT, match - 1}; return (ADBMS_DetailedStatus){ADBMS_INTERNAL_BMS_FAULT, match - 1};
} }
packetChecksumFails += (amsCellMeasurement(&modules) == HAL_ERROR); packetChecksumFails += (amsCellMeasurement(&modules) == ADBMS_ERROR);
packetChecksumFails += (amsCheckUnderOverVoltage(&modules) == HAL_ERROR); packetChecksumFails += (amsCheckUnderOverVoltage(&modules) == ADBMS_ERROR);
if (packetChecksumFails > MAX_PACKET_CHECKSUM_FAILS) { if (packetChecksumFails > MAX_PACKET_CHECKSUM_FAILS) {
return (ADBMS_DetailedStatus){ADBMS_INTERNAL_BMS_CHECKSUM_FAIL, -1}; return (ADBMS_DetailedStatus){ADBMS_INTERNAL_BMS_CHECKSUM_FAIL, -1};

View File

@ -1,11 +1,19 @@
#include "ADBMS_LL_Driver.h" #include "ADBMS_LL_Driver.h"
#include "config_ADBMS6830.h" #include "config_ADBMS6830.h"
#include "stm32h7xx_hal.h" #include "ADBMS_Intern.h"
#include <stdint.h> #include <stdint.h>
#include <strings.h> #include <strings.h>
#define SWO_LOG_PREFIX "[ADBMS] " #if __has_include("stm32h7xx_hal.h")
#include "swo_log.h" #include "stm32h7xx_hal.h"
#define STM32_HAL
#endif
static USER_PTR_TYPE usr_ptr; // SPI_HandleTypeDef*
void initSPI(USER_PTR_TYPE ptr) {
usr_ptr = ptr; // Store the user pointer for SPI communication
}
#define INITIAL_COMMAND_PEC 0x0010 #define INITIAL_COMMAND_PEC 0x0010
#define INITIAL_DATA_PEC 0x0010 #define INITIAL_DATA_PEC 0x0010
@ -17,30 +25,6 @@
#define CRC10_REMAINDER_MASK 0x200 #define CRC10_REMAINDER_MASK 0x200
#define CRC10_RESULT_MASK 0x3FF #define CRC10_RESULT_MASK 0x3FF
SPI_HandleTypeDef* adbmsspi;
uint8_t adbmsDriverInit(SPI_HandleTypeDef* hspi) {
mcuAdbmsCSLow();
HAL_Delay(1);
mcuAdbmsCSHigh();
adbmsspi = hspi;
return 0;
}
static HAL_StatusTypeDef mcuSPITransmit(const uint8_t* buffer, uint8_t buffersize) {
const HAL_StatusTypeDef status = HAL_SPI_Transmit(adbmsspi, buffer, buffersize, ADBMS_SPI_TIMEOUT);
__HAL_SPI_CLEAR_OVRFLAG(adbmsspi);
return status;
}
static HAL_StatusTypeDef mcuSPIReceive(uint8_t* buffer, uint8_t buffersize) {
return HAL_SPI_Receive(adbmsspi, buffer, buffersize, ADBMS_SPI_TIMEOUT);
}
static HAL_StatusTypeDef mcuSPITransmitReceive(uint8_t* rxbuffer, const uint8_t* txbuffer, uint8_t buffersize) {
return HAL_SPI_TransmitReceive(adbmsspi, txbuffer, rxbuffer, buffersize, ADBMS_SPI_TIMEOUT);
}
//command PEC calculation //command PEC calculation
//CRC-15 //CRC-15
//x^15 + x^14 + x^10 + x^8 + x^7 + x^4 + x^3 + 1 //x^15 + x^14 + x^10 + x^8 + x^7 + x^4 + x^3 + 1
@ -122,10 +106,12 @@ static uint8_t checkDataPEC(const uint8_t* data, uint8_t len) {
return (computeCRC10(data, len, false) == 0) ? 0 : 1; return (computeCRC10(data, len, false) == 0) ? 0 : 1;
} }
static const char* const HAL_Statuses[] = {"HAL_OK", "HAL_ERROR", "HAL_BUSY", "HAL_TIMEOUT"}; static const char* const ADBMS_Statuses[] = {"ADBMS_OK", "ADBMS_ERROR", "ADBMS_BUSY", "ADBMS_TIMEOUT"};
#ifdef STM32_HAL // feel free to replace this with your own SPI error handling
static void print_spi_details() { static void print_spi_details() {
const uint32_t spi_error = HAL_SPI_GetError(adbmsspi); extern SPI_HandleTypeDef * usr_ptr;
const uint32_t spi_error = HAL_SPI_GetError(usr_ptr);
typedef struct { typedef struct {
uint32_t mask; uint32_t mask;
@ -154,24 +140,26 @@ static void print_spi_details() {
constexpr size_t numErrors = sizeof(errors) / sizeof(errors[0]); constexpr size_t numErrors = sizeof(errors) / sizeof(errors[0]);
for (size_t i = 0; i < numErrors; i++) { for (size_t i = 0; i < numErrors; i++) {
if (spi_error & errors[i].mask) { if (spi_error & errors[i].mask) {
debug_log_cont(LOG_LEVEL_ERROR, "%s ", errors[i].label); debug_log_cont(ADBMS_LOG_LEVEL_ERROR, "%s ", errors[i].label);
} }
} }
} }
#endif
HAL_StatusTypeDef ___writeCMD(uint16_t command, uint8_t * args, size_t arglen) {
HAL_StatusTypeDef ret; ADBMS_Internal_Status ___writeCMD(uint16_t command, uint8_t * args, size_t arglen) {
ADBMS_Internal_Status ret;
if (arglen > 0) { if (arglen > 0) {
args[0] = (command >> 8) & 0xFF; args[0] = (command >> 8) & 0xFF;
args[1] = (command) & 0xFF; args[1] = (command) & 0xFF;
if (DEBUG_CHANNEL_ENABLED(LOG_LEVEL_NOISY)) { if (DEBUG_CHANNEL_ENABLED(ADBMS_LOG_LEVEL_NOISY)) {
debug_log(LOG_LEVEL_NOISY, "%lu W | %02X %02X ", HAL_GetTick(), args[0], args[1]); debug_log(ADBMS_LOG_LEVEL_NOISY, "%lu W | %02X %02X ", mcuGetTime(), args[0], args[1]);
for (size_t i = 0; i < N_BMS; i++) { for (size_t i = 0; i < N_BMS; i++) {
debug_log_cont(LOG_LEVEL_NOISY, "%d: ", i); debug_log_cont(ADBMS_LOG_LEVEL_NOISY, "%d: ", i);
for (size_t j = 0; j < arglen; j++) { for (size_t j = 0; j < arglen; j++) {
debug_log_cont(LOG_LEVEL_NOISY, "%02X ", args[BUFFER_BMS_OFFSET(i, arglen) + j]); debug_log_cont(ADBMS_LOG_LEVEL_NOISY, "%02X ", args[BUFFER_BMS_OFFSET(i, arglen) + j]);
} }
} }
} }
@ -185,7 +173,7 @@ HAL_StatusTypeDef ___writeCMD(uint16_t command, uint8_t * args, size_t arglen) {
} }
mcuAdbmsCSLow(); mcuAdbmsCSLow();
ret = mcuSPITransmit(args, CMD_BUFFER_SIZE(arglen)); ret = mcuSPITransmit(usr_ptr, args, CMD_BUFFER_SIZE(arglen), ADBMS_SPI_TIMEOUT);
mcuAdbmsCSHigh(); mcuAdbmsCSHigh();
} else { } else {
args[0] = (command >> 8) & 0xFF; args[0] = (command >> 8) & 0xFF;
@ -193,97 +181,103 @@ HAL_StatusTypeDef ___writeCMD(uint16_t command, uint8_t * args, size_t arglen) {
calculateCommandPEC(args, 4); calculateCommandPEC(args, 4);
mcuAdbmsCSLow(); mcuAdbmsCSLow();
ret = mcuSPITransmit(args, 4); ret = mcuSPITransmit(usr_ptr, args, 4, ADBMS_SPI_TIMEOUT);
mcuAdbmsCSHigh(); mcuAdbmsCSHigh();
} }
if (ret != HAL_OK) { if (ret != ADBMS_OK) {
debug_log(LOG_LEVEL_ERROR, "STM32 SPI HAL returned error %s", HAL_Statuses[ret]); debug_log(ADBMS_LOG_LEVEL_ERROR, "SPI HAL returned error %s", ADBMS_Statuses[ret]);
debug_log(LOG_LEVEL_ERROR, "SPI error bits: "); #ifdef STM32_HAL
debug_log(ADBMS_LOG_LEVEL_ERROR, "SPI error bits: ");
print_spi_details(); print_spi_details();
#endif
} }
return ret; return ret;
} }
HAL_StatusTypeDef ___readCMD(uint16_t command, uint8_t * buffer, size_t arglen) { ADBMS_Internal_Status ___readCMD(uint16_t command, uint8_t * buffer, size_t arglen) {
buffer[0] = (command >> 8) & 0xFF; buffer[0] = (command >> 8) & 0xFF;
buffer[1] = (command)&0xFF; buffer[1] = (command)&0xFF;
calculateCommandPEC(buffer, 4); calculateCommandPEC(buffer, 4);
mcuAdbmsCSLow(); mcuAdbmsCSLow();
const HAL_StatusTypeDef status = mcuSPITransmitReceive(buffer, buffer, CMD_BUFFER_SIZE(arglen)); const ADBMS_Internal_Status status = mcuSPITransmitReceive(usr_ptr, buffer, buffer, CMD_BUFFER_SIZE(arglen), ADBMS_SPI_TIMEOUT);
mcuAdbmsCSHigh(); mcuAdbmsCSHigh();
if (status != HAL_OK) { if (status != ADBMS_OK) {
debug_log(LOG_LEVEL_ERROR, "STM32 SPI HAL returned error %s", HAL_Statuses[status]); debug_log(ADBMS_LOG_LEVEL_ERROR, "SPI HAL returned error %s", ADBMS_Statuses[status]);
debug_log(LOG_LEVEL_ERROR, "SPI error bits: "); #ifdef STM32_HAL
debug_log(ADBMS_LOG_LEVEL_ERROR, "SPI error bits: ");
print_spi_details(); print_spi_details();
#endif
return status; return status;
} }
//[[maybe_unused]] uint8_t commandCounter = buffer[sizeof(buffer) - 2] & 0xFC; //command counter is bits 7-2 //[[maybe_unused]] uint8_t commandCounter = buffer[sizeof(buffer) - 2] & 0xFC; //command counter is bits 7-2
//TODO: check command counter? //TODO: check command counter?
if (DEBUG_CHANNEL_ENABLED(LOG_LEVEL_NOISY)) { if (DEBUG_CHANNEL_ENABLED(ADBMS_LOG_LEVEL_NOISY)) {
debug_log(LOG_LEVEL_NOISY, "%lu R | %02X %02X ", HAL_GetTick(), command >> 8, command & 0xFF); debug_log(ADBMS_LOG_LEVEL_NOISY, "%lu R | %02X %02X ", mcuGetTime(), command >> 8, command & 0xFF);
//print out data bytes //print out data bytes
if (arglen > 0) { if (arglen > 0) {
for (size_t i = 0; i < N_BMS; i++) { for (size_t i = 0; i < N_BMS; i++) {
debug_log_cont(LOG_LEVEL_NOISY, "%d: ", i); debug_log_cont(ADBMS_LOG_LEVEL_NOISY, "%d: ", i);
for (size_t j = 0; j < arglen; j++) { for (size_t j = 0; j < arglen; j++) {
debug_log_cont(LOG_LEVEL_NOISY, "%02X ", buffer[BUFFER_BMS_OFFSET(i, arglen) + j]); debug_log_cont(ADBMS_LOG_LEVEL_NOISY, "%02X ", buffer[BUFFER_BMS_OFFSET(i, arglen) + j]);
} }
} }
} }
} }
if (arglen == 0) { if (arglen == 0) {
return HAL_OK; //no data to check return ADBMS_OK; //no data to check
} }
//check data PEC //check data PEC
for (size_t i = 0; i < N_BMS; i++) { for (size_t i = 0; i < N_BMS; i++) {
const size_t offset = BUFFER_BMS_OFFSET(i, arglen); const size_t offset = BUFFER_BMS_OFFSET(i, arglen);
if (checkDataPEC(&buffer[offset], arglen + 2) != 0) { if (checkDataPEC(&buffer[offset], arglen + 2) != 0) {
debug_log(LOG_LEVEL_ERROR, "Invalid data PEC when reading BMS %d", i); debug_log(ADBMS_LOG_LEVEL_ERROR, "Invalid data PEC when reading BMS %d", i);
debug_log(LOG_LEVEL_ERROR, "Received: "); debug_log(ADBMS_LOG_LEVEL_ERROR, "Received: ");
for (size_t j = 0; j < arglen + 2; j++) { for (size_t j = 0; j < arglen + 2; j++) {
debug_log_cont(LOG_LEVEL_ERROR, "%02X ", buffer[offset + j]); debug_log_cont(ADBMS_LOG_LEVEL_ERROR, "%02X ", buffer[offset + j]);
} }
debug_log_cont(LOG_LEVEL_ERROR, "| %02X %02X ", buffer[offset + arglen], buffer[offset + arglen + 1]); //print out the DPEC debug_log_cont(ADBMS_LOG_LEVEL_ERROR, "| %02X %02X ", buffer[offset + arglen], buffer[offset + arglen + 1]); //print out the DPEC
debug_log(LOG_LEVEL_ERROR, " DATA ^"); debug_log(ADBMS_LOG_LEVEL_ERROR, " DATA ^");
//print out spaces until start of DPEC //print out spaces until start of DPEC
for (size_t j = 0; j < arglen - 1; j++) { for (size_t j = 0; j < arglen - 1; j++) {
debug_log_cont(LOG_LEVEL_ERROR, (arglen < 2) ? "" : "^^^"); debug_log_cont(ADBMS_LOG_LEVEL_ERROR, (arglen < 2) ? "" : "^^^");
} }
debug_log_cont(LOG_LEVEL_ERROR, "^^ "); debug_log_cont(ADBMS_LOG_LEVEL_ERROR, "^^ ");
debug_log_cont(LOG_LEVEL_ERROR, " PEC ^"); debug_log_cont(ADBMS_LOG_LEVEL_ERROR, " PEC ^");
return HAL_ERROR; return ADBMS_ERROR;
} }
} }
return HAL_OK; return ADBMS_OK;
} }
//check poll command - no data PEC sent back, waitTime is in SPI clock cycles //check poll command - no data PEC sent back, waitTime is in SPI clock cycles
HAL_StatusTypeDef __pollCMD(uint16_t command, uint8_t waitTime) { ADBMS_Internal_Status __pollCMD(uint16_t command, uint8_t waitTime) {
uint8_t buffer[4 + (waitTime / 8) + 1] = {}; //8 cycles per byte, +1 as we round up uint8_t buffer[4 + (waitTime / 8) + 1] = {}; //8 cycles per byte, +1 as we round up
buffer[0] = (command >> 8) & 0xFF; buffer[0] = (command >> 8) & 0xFF;
buffer[1] = (command) & 0xFF; buffer[1] = (command) & 0xFF;
calculateCommandPEC(buffer, 4); calculateCommandPEC(buffer, 4);
mcuAdbmsCSLow(); mcuAdbmsCSLow();
const HAL_StatusTypeDef status = mcuSPITransmitReceive(buffer, buffer, sizeof buffer); const ADBMS_Internal_Status status = mcuSPITransmitReceive(usr_ptr, buffer, buffer, sizeof buffer, ADBMS_SPI_TIMEOUT);
mcuAdbmsCSHigh(); mcuAdbmsCSHigh();
if (status != HAL_OK) { if (status != ADBMS_OK) {
debug_log(LOG_LEVEL_ERROR, "STM32 SPI HAL returned error %s", HAL_Statuses[status]); debug_log(ADBMS_LOG_LEVEL_ERROR, "SPI HAL returned error %s", ADBMS_Statuses[status]);
debug_log(LOG_LEVEL_ERROR, "SPI error bits: "); #ifdef STM32_HAL
debug_log(ADBMS_LOG_LEVEL_ERROR, "SPI error bits: ");
print_spi_details(); print_spi_details();
#endif
return status; return status;
} }
return ((buffer[sizeof buffer] & 0x0F) == 0x0) ? HAL_BUSY : HAL_OK; //SDO goes high when data is ready return ((buffer[sizeof buffer] & 0x0F) == 0x0) ? ADBMS_BUSY : ADBMS_OK; //SDO goes high when data is ready
} }

View File

@ -1,4 +1,5 @@
#include "battery.h" #include "battery.h"
#define ADBMS_NO_LOGGING_DEFS true // fix conficting defines
#include "ADBMS_Driver.h" #include "ADBMS_Driver.h"
#include "NTC.h" #include "NTC.h"
#include "can.h" #include "can.h"
@ -6,6 +7,7 @@
#include "ts_state_machine.h" #include "ts_state_machine.h"
#include <string.h> #include <string.h>
#include <math.h> #include <math.h>
#include "main.h"
#define SWO_LOG_PREFIX "[BATTERY] " #define SWO_LOG_PREFIX "[BATTERY] "
#include "swo_log.h" #include "swo_log.h"
@ -46,7 +48,9 @@ static inline void update_error_window(bool error, int id) {
} }
HAL_StatusTypeDef battery_init(SPI_HandleTypeDef *hspi) { HAL_StatusTypeDef battery_init(SPI_HandleTypeDef *hspi) {
const auto ret = AMS_Init(hspi); // pull MSTR High for Microcontroller mode ADBMS6822
HAL_GPIO_WritePin(MSTR1_GPIO_Port, MSTR1_Pin, GPIO_PIN_SET);
auto const ret = AMS_Init(hspi);
if (ret.status != ADBMS_NO_ERROR) { if (ret.status != ADBMS_NO_ERROR) {
debug_log(LOG_LEVEL_ERROR, "Failed to initialize BMS: %s", debug_log(LOG_LEVEL_ERROR, "Failed to initialize BMS: %s",
ADBMS_Status_ToString(ret.status)); ADBMS_Status_ToString(ret.status));
@ -61,7 +65,7 @@ HAL_StatusTypeDef battery_init(SPI_HandleTypeDef *hspi) {
[[gnu::optimize("no-math-errno")]] [[gnu::optimize("no-math-errno")]]
HAL_StatusTypeDef battery_update() { HAL_StatusTypeDef battery_update() {
const auto ret = AMS_Idle_Loop(); auto const ret = AMS_Idle_Loop();
if (ret.status != ADBMS_NO_ERROR) { if (ret.status != ADBMS_NO_ERROR) {
debug_log(LOG_LEVEL_ERROR, "Error while updating battery data: %s", debug_log(LOG_LEVEL_ERROR, "Error while updating battery data: %s",
ADBMS_Status_ToString(ret.status)); ADBMS_Status_ToString(ret.status));

View File

@ -35,7 +35,7 @@ void can_init(FDCAN_HandleTypeDef *handle) {
ftcan_add_filter(CAN_ID_AMS_DETAILS_FC, 0xFFF); ftcan_add_filter(CAN_ID_AMS_DETAILS_FC, 0xFFF);
ftcan_add_filter(ISOTP_LOG_FC_CAN_ID, 0xFFF); ftcan_add_filter(ISOTP_LOG_FC_CAN_ID, 0xFFF);
const auto status = isotp_add_connection(CAN_ID_AMS_DETAILS_FC, CAN_ID_AMS_DETAILS, ISOTP_FLAGS_NONE); auto const status = isotp_add_connection(CAN_ID_AMS_DETAILS_FC, CAN_ID_AMS_DETAILS, ISOTP_FLAGS_NONE);
if (status < 0) { if (status < 0) {
log_warning("Failed to add ISO-TP connection: %s", isotp_status_to_string((isotp_status_t)status)); log_warning("Failed to add ISO-TP connection: %s", isotp_status_to_string((isotp_status_t)status));
} }
@ -71,7 +71,7 @@ HAL_StatusTypeDef can_send_status() {
HAL_StatusTypeDef can_send_details() { HAL_StatusTypeDef can_send_details() {
static uint8_t module_index = 0; static uint8_t module_index = 0;
static uint8_t data[103] = {}; //sizeof(Cell_Module) + 10 + 1 static uint8_t data[103] = {}; //sizeof(Cell_Module) + 10 + 1
const auto module = &modules[module_index]; auto const module = &modules[module_index];
auto data_ptr = &data[1]; auto data_ptr = &data[1];
isotp_status_t status = isotp_try_add_message(isotp_connection_id, data, sizeof(data)); isotp_status_t status = isotp_try_add_message(isotp_connection_id, data, sizeof(data));
@ -164,7 +164,7 @@ void ftcan_msg_received_cb(uint16_t id, size_t len, const uint8_t *data) {
switch (id) { switch (id) {
case ISOTP_LOG_FC_CAN_ID: case ISOTP_LOG_FC_CAN_ID:
case CAN_ID_AMS_DETAILS_FC: case CAN_ID_AMS_DETAILS_FC:
const auto status = isotp_handle_incoming(id, data, len); auto const status = isotp_handle_incoming(id, data, len);
if (status != ISOTP_OK) { if (status != ISOTP_OK) {
log_debug("Error when handling flow control: %s", isotp_status_to_string(status)); log_debug("Error when handling flow control: %s", isotp_status_to_string(status));
} }

View File

@ -12,7 +12,7 @@
#include "swo_log_backend.h" #include "swo_log_backend.h"
void print_master_status() { void print_master_status() {
const auto backend = swo_log_get_backend(); auto const backend = swo_log_get_backend();
if (!backend->is_enabled(LOG_LEVEL_INFO)) { if (!backend->is_enabled(LOG_LEVEL_INFO)) {
return; // No need to print if the backend is not enabled for this log level return; // No need to print if the backend is not enabled for this log level

View File

@ -8,7 +8,7 @@
#include "swo_log_backend.h" #include "swo_log_backend.h"
void print_battery_info() { void print_battery_info() {
const auto backend = swo_log_get_backend(); auto const backend = swo_log_get_backend();
if (!backend->is_enabled(LOG_LEVEL_INFO)) { if (!backend->is_enabled(LOG_LEVEL_INFO)) {
return; // No need to print if the backend is not enabled for this log level return; // No need to print if the backend is not enabled for this log level

View File

@ -27,7 +27,7 @@ void ts_sm_update() {
ts_state.current_state = TS_ERROR; ts_state.current_state = TS_ERROR;
} }
const auto old_state = ts_state.current_state; auto const old_state = ts_state.current_state;
switch (ts_state.current_state) { switch (ts_state.current_state) {
case TS_INACTIVE: case TS_INACTIVE: