From 96b069a5a580dfe37bb0ea3728435d0881ba9c52 Mon Sep 17 00:00:00 2001 From: Kilian Bracher Date: Wed, 22 Jan 2025 18:03:29 +0100 Subject: [PATCH] add daisy chain isospi --- AMS_Master_Code/Core/Inc/swo_log.h | 36 ++-- .../Core/Inc/ADBMS_LL_Driver.h | 43 ++++- .../Core/Src/ADBMS_LL_Driver.c | 166 ++++++++++-------- 3 files changed, 146 insertions(+), 99 deletions(-) diff --git a/AMS_Master_Code/Core/Inc/swo_log.h b/AMS_Master_Code/Core/Inc/swo_log.h index d3ed1f7..a727821 100644 --- a/AMS_Master_Code/Core/Inc/swo_log.h +++ b/AMS_Master_Code/Core/Inc/swo_log.h @@ -52,6 +52,12 @@ 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; \ +}) + +[[gnu::nonnull(1), gnu::null_terminated_string_arg(1)]] static inline void __swo_print(const char *str, unsigned int channel) { if (!__ITM_channel_enabled(channel)) { return; @@ -61,22 +67,18 @@ static inline void __swo_print(const char *str, unsigned int channel) { } } -// Print a message to the SWO interface -// -// Each log level is printed to a different ITM channel -[[gnu::format(printf, 2, 3)]] -static inline void debug_log(enum log_level_t level, const char *msg, ...) { - va_list args; - va_start(args, msg); - char buffer[MAX_MESSAGE_LENGTH]; - size_t len = vsnprintf(buffer, sizeof(buffer), msg, args); - va_end(args); - __swo_print(log_level_names[level], level); - __swo_print(buffer, level); - if (len >= sizeof(buffer)) { - __swo_print(" [message length exceeded] ", level); - } - __swo_putc('\n', level); -} +#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_print(log_level_names[level], level); \ + __swo_print(buffer, level); \ + if (len >= sizeof(buffer)) { \ + __swo_print(" [message length exceeded] ", level); \ + } \ + __swo_putc('\n', level); \ + } \ + } while (0) #endif /* __SWO_LOG_H */ diff --git a/AMS_Master_Code/Core/Lib/ADBMS6830B_Driver/Core/Inc/ADBMS_LL_Driver.h b/AMS_Master_Code/Core/Lib/ADBMS6830B_Driver/Core/Inc/ADBMS_LL_Driver.h index f3ccee8..11088e1 100755 --- a/AMS_Master_Code/Core/Lib/ADBMS6830B_Driver/Core/Inc/ADBMS_LL_Driver.h +++ b/AMS_Master_Code/Core/Lib/ADBMS6830B_Driver/Core/Inc/ADBMS_LL_Driver.h @@ -8,6 +8,7 @@ #ifndef ADBMS_LL_DRIVER_H_ #define ADBMS_LL_DRIVER_H_ +#include "config_ADBMS6830.h" #include "stm32h7xx_hal.h" #include #define TARGET_STM32 @@ -20,14 +21,48 @@ typedef uint32_t uint32; uint8 adbmsDriverInit(SPI_HandleTypeDef* hspi); -uint8 writeCMD(uint16 command, uint8* args, uint8 arglen); -uint8 readCMD(uint16 command, uint8* buffer, uint8 buflen); -uint8 pollCMD(uint16 command); +//2 command + 2 PEC + (data + 2 DPEC) per BMS +#define CMD_BUFFER_SIZE(datalen) (4 + (N_BMS * (datalen + 2))) + +//macro to function for better type checking (access attribute) +[[gnu::access(read_only, 4, 1)]] +static inline void __modify_writeCMD_args(size_t arglen, uint8_t args[static restrict N_BMS * (arglen + 2)], uint8_t bms, uint8_t * restrict data) { + for (uint8_t i = 0; i < arglen; i++) { + args[(bms * (arglen + 2)) + i] = data[i]; + } +} + +#define modify_writeCMD_args(args, bms, data) \ + static_assert(bms < N_BMS, "bms out of range"); \ + __modify_writeCMD_args(args.arglen, args.args + 4, bms, data) + + +HAL_StatusTypeDef ___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 +static inline HAL_StatusTypeDef __writeCMD(uint16_t command, uint8_t * args, size_t arglen, size_t _) { + return ___writeCMD(command, args, arglen); +} + +#define writeCMD(command, args, arglen) \ + __writeCMD(command, args, arglen, CMD_BUFFER_SIZE(arglen)) + +[[gnu::access(read_write, 2, 3), gnu::nonnull(2)]] +HAL_StatusTypeDef __readCMD(uint16_t command, uint8_t * buffer, size_t buflen); + +#define readCMD(command, buffer, buflen) ({ \ + HAL_StatusTypeDef status = __readCMD(command, buffer, buflen); \ + buffer += 4; /* skip command and PEC */ \ + status; \ +}) + +uint8_t pollCMD(uint16_t command); + void mcuAdbmsCSLow(); void mcuAdbmsCSHigh(); uint8 wakeUpCmd(); -static inline void mcuDelay(uint16 delay) { HAL_Delay(delay); }; +static inline void mcuDelay(uint16_t delay) { HAL_Delay(delay); }; #endif /* ADBMS_LL_DRIVER_H_ */ 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 4c85cdf..2c96b39 100755 --- 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 @@ -8,8 +8,11 @@ #include "ADBMS_LL_Driver.h" #include "ADBMS_CMD_MAKROS.h" #include "config_ADBMS6830.h" +#include "stm32h7xx_hal.h" +#include "swo_log.h" #include #include +#include #define INITIAL_COMMAND_PEC 0x0010 #define INITIAL_DATA_PEC 0x0010 @@ -19,7 +22,7 @@ SPI_HandleTypeDef* adbmsspi; uint8_t command_queue[N_BMS][12] = {0}; -uint8 adbmsDriverInit(SPI_HandleTypeDef* hspi) { +uint8_t adbmsDriverInit(SPI_HandleTypeDef* hspi) { mcuAdbmsCSLow(); HAL_Delay(1); mcuAdbmsCSHigh(); @@ -27,42 +30,34 @@ uint8 adbmsDriverInit(SPI_HandleTypeDef* hspi) { return 0; } -uint8 mcuSPITransmit(uint8* buffer, uint8 buffersize) { - HAL_StatusTypeDef status; - uint8 rxbuf[buffersize]; - status = HAL_SPI_TransmitReceive(adbmsspi, buffer, rxbuf, buffersize, - ADBMS_SPI_TIMEOUT); - __HAL_SPI_CLEAR_OVRFLAG(adbmsspi); - return status; +static HAL_StatusTypeDef mcuSPITransmit(uint8_t* buffer, uint8_t buffersize) { + HAL_StatusTypeDef status; + status = HAL_SPI_Transmit(adbmsspi, buffer, buffersize, ADBMS_SPI_TIMEOUT); + __HAL_SPI_CLEAR_OVRFLAG(adbmsspi); + return status; } -uint8 mcuSPIReceive(uint8* buffer, uint8 buffersize) { - HAL_StatusTypeDef status; - status = HAL_SPI_Receive(adbmsspi, buffer, buffersize, ADBMS_SPI_TIMEOUT); - return status; +static HAL_StatusTypeDef mcuSPIReceive(uint8_t* buffer, uint8_t buffersize) { + return HAL_SPI_Receive(adbmsspi, buffer, buffersize, ADBMS_SPI_TIMEOUT); } -uint8 mcuSPITransmitReceive(uint8* rxbuffer, uint8* txbuffer, - uint8 buffersize) { - HAL_StatusTypeDef status; - status = HAL_SPI_TransmitReceive(adbmsspi, txbuffer, rxbuffer, buffersize, - ADBMS_SPI_TIMEOUT); - return status; +static HAL_StatusTypeDef mcuSPITransmitReceive(uint8_t* rxbuffer, uint8_t* txbuffer, uint8_t buffersize) { + return HAL_SPI_TransmitReceive(adbmsspi, txbuffer, rxbuffer, buffersize, ADBMS_SPI_TIMEOUT); } //command PEC calculation //CRC-15 //x^15 + x^14 + x^10 + x^8 + x^7 + x^4 + x^3 + 1 -static uint16 updateCommandPEC(uint16 currentPEC, uint8 din) { +static uint16 updateCommandPEC(uint16 currentPEC, uint8_t din) { din = (din >> 7) & 0x01; - uint8 in0 = din ^ ((currentPEC >> 14) & 0x01); - uint8 in3 = in0 ^ ((currentPEC >> 2) & 0x01); - uint8 in4 = in0 ^ ((currentPEC >> 3) & 0x01); - uint8 in7 = in0 ^ ((currentPEC >> 6) & 0x01); - uint8 in8 = in0 ^ ((currentPEC >> 7) & 0x01); - uint8 in10 = in0 ^ ((currentPEC >> 9) & 0x01); - uint8 in14 = in0 ^ ((currentPEC >> 13) & 0x01); + uint8_t in0 = din ^ ((currentPEC >> 14) & 0x01); + uint8_t in3 = in0 ^ ((currentPEC >> 2) & 0x01); + uint8_t in4 = in0 ^ ((currentPEC >> 3) & 0x01); + uint8_t in7 = in0 ^ ((currentPEC >> 6) & 0x01); + uint8_t in8 = in0 ^ ((currentPEC >> 7) & 0x01); + uint8_t in10 = in0 ^ ((currentPEC >> 9) & 0x01); + uint8_t in14 = in0 ^ ((currentPEC >> 13) & 0x01); uint16 newPEC = 0; @@ -85,12 +80,12 @@ static uint16 updateCommandPEC(uint16 currentPEC, uint8 din) { return newPEC; } -static uint8 calculateCommandPEC(uint8_t* data, uint8_t datalen) { +static uint8_t calculateCommandPEC(uint8_t* data, uint8_t datalen) { uint16 currentpec = INITIAL_COMMAND_PEC; if (datalen >= 3) { for (int i = 0; i < (datalen - 2); i++) { for (int n = 0; n < 8; n++) { - uint8 din = data[i] << (n); + uint8_t din = data[i] << (n); currentpec = updateCommandPEC(currentpec, din); } } @@ -103,7 +98,7 @@ static uint8 calculateCommandPEC(uint8_t* data, uint8_t datalen) { } } -static uint8 checkCommandPEC(uint8* data, uint8 datalen) { +static uint8_t checkCommandPEC(uint8_t* data, uint8_t datalen) { if (datalen <= 3) { return 255; } @@ -112,13 +107,13 @@ static uint8 checkCommandPEC(uint8* data, uint8 datalen) { for (int i = 0; i < (datalen - 2); i++) { for (int n = 0; n < 8; n++) { - uint8 din = data[i] << (n); + uint8_t din = data[i] << (n); currentpec = updateCommandPEC(currentpec, din); } } - uint8 pechigh = (currentpec >> 7) & 0xFF; - uint8 peclow = (currentpec << 1) & 0xFF; + uint8_t pechigh = (currentpec >> 7) & 0xFF; + uint8_t peclow = (currentpec << 1) & 0xFF; if ((pechigh == data[datalen - 2]) && (peclow == data[datalen - 1])) { return 0; @@ -174,7 +169,7 @@ static uint16_t pec10_calc(bool rx_cmd, int len, uint8_t* data) { typedef uint16_t crc; static crc F_CRC_CalculaCheckSum(uint8_t const AF_Datos[], uint16_t VF_nBytes); -static uint8 calculateDataPEC(uint8_t* data, uint8_t datalen) { +static uint8_t calculateDataPEC(uint8_t* data, uint8_t datalen) { if (datalen >= 3) { @@ -185,7 +180,7 @@ static uint8 calculateDataPEC(uint8_t* data, uint8_t datalen) { data[datalen - 2] = (currentpec >> 8) & 0xFF; data[datalen - 1] = currentpec & 0xFF; - volatile uint8 result = pec10_calc(true, datalen, data); + volatile uint8_t result = pec10_calc(true, datalen, data); return 0; } else { @@ -193,7 +188,7 @@ static uint8 calculateDataPEC(uint8_t* data, uint8_t datalen) { } } -static uint8 checkDataPEC(uint8* data, uint8 len) { +static uint8_t checkDataPEC(uint8_t* data, uint8_t len) { if (len <= 2) { return 255; } @@ -238,12 +233,12 @@ static crc F_CRC_CalculaCheckSum(uint8_t const AF_Datos[], uint16_t VF_nBytes) { return (VP_CRCTableValue ^ 0x0000); } -static uint16 updateDataPEC(uint16 currentPEC, uint8 din) { +static uint16 updateDataPEC(uint16 currentPEC, uint8_t din) { din = (din >> 7) & 0x01; - uint8 in0 = din ^ ((currentPEC >> 9) & 0x01); - uint8 in2 = in0 ^ ((currentPEC >> 1) & 0x01); - uint8 in3 = in0 ^ ((currentPEC >> 2) & 0x01); - uint8 in7 = in0 ^ ((currentPEC >> 6) & 0x01); + uint8_t in0 = din ^ ((currentPEC >> 9) & 0x01); + uint8_t in2 = in0 ^ ((currentPEC >> 1) & 0x01); + uint8_t in3 = in0 ^ ((currentPEC >> 2) & 0x01); + uint8_t in7 = in0 ^ ((currentPEC >> 6) & 0x01); uint16 newPEC = 0; @@ -259,78 +254,93 @@ static uint16 updateDataPEC(uint16 currentPEC, uint8 din) { return newPEC; } - -uint8 writeCMD(uint16 command, uint8* args, uint8 arglen) { - uint8 ret; + +HAL_StatusTypeDef ___writeCMD(uint16_t command, uint8_t * args, size_t arglen) { + HAL_StatusTypeDef ret = HAL_OK; if (arglen > 0) { - uint8 buffer[6 + arglen]; //command + PEC (2 bytes) + data + DPEC (2 bytes) - buffer[0] = (command >> 8) & 0xFF; - buffer[1] = (command) & 0xFF; + args[0] = (command >> 8) & 0xFF; + args[1] = (command) & 0xFF; - calculateCommandPEC(buffer, 4); + if (DEBUG_CHANNEL_ENABLED(LOG_LEVEL_NOISY)) { + debug_log(LOG_LEVEL_NOISY, "%d W | %x %x ", HAL_GetTick(), args[0], args[1]); - for (uint8 i = 0; i < arglen; i++) { - buffer[4 + i] = args[i]; + //print out data bytes + for (size_t i = 0; i < N_BMS; i++) { + debug_log(LOG_LEVEL_NOISY, "%d: ", i); + for (size_t j = 0; j < arglen; j++) { + debug_log(LOG_LEVEL_NOISY, "%x ", args[4 + (i * (arglen + 2)) + j]); + } + } + + debug_log(LOG_LEVEL_NOISY, "\n"); } - calculateDataPEC(&buffer[4], arglen + 2); //DPEC is calculated over the data, not the command, and placed at the end of the data + calculateCommandPEC(args, 4); + for (size_t i = 0; i < N_BMS; i++) { + calculateDataPEC(&args[4 + (i * (arglen + 2))], arglen + 2); //DPEC is calculated over the data, not the command, and placed at the end of the data + } + mcuAdbmsCSLow(); - ret = mcuSPITransmit(buffer, 6 + arglen); + ret = mcuSPITransmit(args, CMD_BUFFER_SIZE(arglen)); mcuAdbmsCSHigh(); } else { - uint8 buffer[4]; - buffer[0] = (command >> 8) & 0xFF; - buffer[1] = (command) & 0xFF; - calculateCommandPEC(buffer, 4); + args[0] = (command >> 8) & 0xFF; + args[1] = (command) & 0xFF; + calculateCommandPEC(args, 4); mcuAdbmsCSLow(); - - ret = mcuSPITransmit(buffer, 4); - + ret = mcuSPITransmit(args, 4); mcuAdbmsCSHigh(); } return ret; } -uint8 readCMD(uint16 command, uint8* buffer, uint8 buflen) { - uint8 txbuffer[6 + buflen]; - uint8 rxbuffer[6 + buflen]; - txbuffer[0] = (command >> 8) & 0xFF; - txbuffer[1] = (command)&0xFF; - calculateCommandPEC(txbuffer, 4); + +HAL_StatusTypeDef __readCMD(uint16_t command, uint8_t * buffer, size_t buflen) { + buffer[0] = (command >> 8) & 0xFF; + buffer[1] = (command)&0xFF; + calculateCommandPEC(buffer, 4); mcuAdbmsCSLow(); - uint8 status = mcuSPITransmitReceive(rxbuffer, txbuffer, 6 + buflen); + HAL_StatusTypeDef status = mcuSPITransmitReceive(buffer, buffer, buflen); mcuAdbmsCSHigh(); - if (status != 0) { - return status; - } + if (status != HAL_OK) return status; - for (uint8 i = 0; i < buflen; i++) { - buffer[i] = rxbuffer[i + 4]; - } - - [[maybe_unused]] uint8 commandCounter = rxbuffer[sizeof(rxbuffer) - 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? + + if (DEBUG_CHANNEL_ENABLED(LOG_LEVEL_NOISY)) { + debug_log(LOG_LEVEL_NOISY, "%d R | %x %x ", HAL_GetTick(), command >> 8, command & 0xFF); + + //print out data bytes + for (size_t i = 0; i < N_BMS; i++) { + debug_log(LOG_LEVEL_NOISY, "%d: ", i); + for (size_t j = 0; j < buflen; j++) { + debug_log(LOG_LEVEL_NOISY, "%x ", buffer[4 + (i * (buflen + 2)) + j]); + } + } + + debug_log(LOG_LEVEL_NOISY, "\n"); + } - return checkDataPEC(&rxbuffer[4], buflen + 2); + return checkDataPEC(&buffer[4], buflen + 2); } //check poll command - no data PEC sent back -uint8 pollCMD(uint16 command) { - uint8 txbuffer[5] = {}; - uint8 rxbuffer[5] = {}; +uint8_t pollCMD(uint16_t command) { + uint8_t txbuffer[5] = {}; + uint8_t rxbuffer[5] = {}; txbuffer[0] = (command >> 8) & 0xFF; txbuffer[1] = (command)&0xFF; calculateCommandPEC(txbuffer, 4); mcuAdbmsCSLow(); - uint8 status = mcuSPITransmitReceive(rxbuffer, txbuffer, 5); + uint8_t status = mcuSPITransmitReceive(rxbuffer, txbuffer, 5); mcuAdbmsCSHigh(); if (status != 0) {