#include "slave_monitoring.h" #include "can.h" #include "main.h" #include "ts_state_machine.h" #include "can-halal.h" #include "stm32h7xx_hal.h" #include #include SlaveHandle slaves[N_SLAVES]; uint16_t min_voltage; int16_t max_temp; static uint8_t slave_id_to_index[128] = {0xFF}; static size_t get_slave_index(uint8_t slave_id) { // Slave IDs are 7-bit, so we can use a 128-element array to map them to // indices. 0xFF is used to mark unseen slave IDs, since the highest index we // could need is N_SLAVES - 1 (i.e. 5). static size_t next_slave_index = 0; if (slave_id_to_index[slave_id] == 0xFF) { if (next_slave_index >= N_SLAVES) { // We've seen more than N_SLAVES slave IDs, this shouldn't happen. Error_Handler(); } slave_id_to_index[slave_id] = next_slave_index; slaves[next_slave_index].id = slave_id; next_slave_index++; } return slave_id_to_index[slave_id]; } void slaves_init() { memset(slave_id_to_index, 0xFF, sizeof(slave_id_to_index)); for (int i = 0; i < N_SLAVES; i++) { slaves[i].id = 0xFF; slaves[i].error.kind = SLAVE_ERR_NONE; slaves[i].last_message = 0; slaves[i].min_voltage = 0; slaves[i].max_voltage = 0; slaves[i].max_temp = 0; } HAL_GPIO_WritePin(SLAVE_POWER_0_GPIO_Port, SLAVE_POWER_0_Pin, GPIO_PIN_SET); HAL_GPIO_WritePin(SLAVE_POWER_1_GPIO_Port, SLAVE_POWER_1_Pin, GPIO_PIN_SET); HAL_GPIO_WritePin(SLAVE_POWER_DSEL_GPIO_Port, SLAVE_POWER_DSEL_Pin, GPIO_PIN_RESET); // TODO: Enable & read out current HAL_GPIO_WritePin(SLAVE_POWER_DEN_GPIO_Port, SLAVE_POWER_DEN_Pin, GPIO_PIN_RESET); } void slaves_check() { int any_slave_error = 0; TSErrorKind slave_error = TS_ERRORKIND_NONE; uint32_t now = HAL_GetTick(); uint16_t min_voltage_new = 0xFFFF; int16_t max_temp_new = 0xFFFF; for (int i = 0; i < N_SLAVES; i++) { // Update timeout errors if (now - slaves[i].last_message >= SLAVE_TIMEOUT) { // Don't overwrite a different error kind if (slaves[i].error.kind == SLAVE_ERR_NONE) { slaves[i].error.kind = SLAVE_ERR_TIMEOUT; can_send_error(TS_ERRORKIND_SLAVE_TIMEOUT, slaves[i].id); } } else if (slaves[i].error.kind == SLAVE_ERR_TIMEOUT) { slaves[i].error.kind = SLAVE_ERR_NONE; } // Determine min/max if (slaves[i].min_voltage < min_voltage_new) { min_voltage_new = slaves[i].min_voltage; } if (slaves[i].max_temp > max_temp_new) { max_temp_new = slaves[i].max_temp; } if (slaves[i].error.kind != SLAVE_ERR_NONE) { any_slave_error = 1; slave_error = (slaves[i].error.kind == SLAVE_ERR_TIMEOUT) ? TS_ERRORKIND_SLAVE_TIMEOUT : TS_ERRORKIND_SLAVE_PANIC; } } min_voltage = min_voltage_new; max_temp = max_temp_new; ts_sm_set_error_source(TS_ERROR_SOURCE_SLAVES, slave_error, any_slave_error); } void slaves_handle_panic(const uint8_t *data) { const uint8_t **ptr = &data; uint8_t slave_id = ftcan_unmarshal_unsigned(ptr, 1); uint8_t idx = get_slave_index(slave_id); uint8_t error_kind = ftcan_unmarshal_unsigned(ptr, 1); switch (error_kind) { case SLAVE_PANIC_OT ... SLAVE_PANIC_INTERNAL_BMS_FAULT: slaves[idx].error.kind = error_kind + 2; //SlaveErrorKind on master is 2 higher than on slave (errors.h in slave firmware) break; default: slaves[idx].error.kind = SLAVE_ERR_UNKNOWN; break; } slaves[idx].error.data = ftcan_unmarshal_unsigned(&data, 4); slaves[idx].last_message = HAL_GetTick(); ts_sm_set_error_source(TS_ERROR_SOURCE_SLAVES, TS_ERRORKIND_SLAVE_PANIC, 1); can_send_error(TS_ERRORKIND_SLAVE_PANIC, slave_id); } void slaves_handle_status(const uint8_t *data) { uint8_t slave_id = data[0] & 0x7F; uint8_t idx = get_slave_index(slave_id); int error = data[0] & 0x80; if (!error) { slaves[idx].error.kind = SLAVE_ERR_NONE; } slaves[idx].soc = data[1]; const uint8_t *ptr = &data[2]; slaves[idx].min_voltage = ftcan_unmarshal_unsigned(&ptr, 2); slaves[idx].max_voltage = ftcan_unmarshal_unsigned(&ptr, 2); slaves[idx].max_temp = ftcan_unmarshal_unsigned(&ptr, 2); slaves[idx].last_message = HAL_GetTick(); } void slaves_handle_log(const uint8_t *data) { // TODO }