Add fire alarm handling for DC30 CCS main controller.

Latch fire alarm until reboot, block recovery commands, and send periodic Everest ESTOP while active.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
raduet
2026-06-10 16:01:22 +02:00
parent 1be17330fa
commit fb766dfa66
18 changed files with 3766 additions and 4113 deletions
+1
View File
@@ -55,6 +55,7 @@ typedef enum __attribute__((packed)){
CONN_ERR_HOTPLUG = 8, // Коннектор неожиданно отключился
CONN_ERR_EV_COMM = 9, // Ошибка протокола связи с электромобилем
CONN_ERR_PSU_FAULT = 10, // Ошибка PSU
CONN_ERR_FIRE_ALARM = 11, // Пожарная тревога (до перезагрузки)
}CONN_Error_t;
+11
View File
@@ -0,0 +1,11 @@
#ifndef INC_FIRE_ALARM_H_
#define INC_FIRE_ALARM_H_
#include <stdint.h>
uint8_t FireAlarm_IsLatched(void);
uint8_t FireAlarm_IsBlockingCommand(uint8_t command_code);
void FireAlarm_Activate(void);
void FireAlarm_Maintain(void);
#endif /* INC_FIRE_ALARM_H_ */
+1 -1
View File
@@ -43,7 +43,7 @@ extern "C" {
/* USER CODE BEGIN EC */
#define FW_VERSION_MAJOR 1
#define FW_VERSION_MINOR 0
#define FW_VERSION_PATCH 17
#define FW_VERSION_PATCH 18
/* USER CODE END EC */
/* Exported macro ------------------------------------------------------------*/
+2
View File
@@ -28,6 +28,8 @@
// Перезагрузка для входа в бутлоадер
#define CMD_DEVICE_RESET 0xB5
// Пожарная тревога (внешний триггер)
#define CMD_FIRE_ALARM 0xB7
// Коды ответов
#define RESP_SUCCESS 0x12
+8
View File
@@ -4,6 +4,7 @@
#include "psu_control.h"
#include "connector.h"
#include "debug.h"
#include "fire_alarm.h"
ChargingConnector_t CONN;
CONN_State_t connectorState;
@@ -19,6 +20,13 @@ void CONN_Init(){
void CONN_Loop(){
static CONN_State_t last_connState = Unknown;
if (FireAlarm_IsLatched()) {
CONN.chargingError = CONN_ERR_FIRE_ALARM;
CONN.EnableOutput = 0;
return;
}
if(last_connState != CONN.connState){
last_connState = CONN.connState;
CONN.connControl = CMD_NONE;
+74
View File
@@ -0,0 +1,74 @@
#include "fire_alarm.h"
#include "serial_control.h"
#include "charger_control.h"
#include "connector.h"
#include "serial.h"
#include "cp.h"
#include "debug.h"
static uint8_t fire_alarm_latched = 0;
static uint32_t fire_alarm_last_estop_tick = 0;
extern CCS_ConnectorState_t CCS_ConnectorState;
uint8_t FireAlarm_IsLatched(void) {
return fire_alarm_latched;
}
uint8_t FireAlarm_IsBlockingCommand(uint8_t command_code) {
if (!fire_alarm_latched) {
return 0;
}
switch (command_code) {
case CMD_GET_STATUS:
case CMD_GET_INFO:
case CMD_GET_LOG:
case CMD_DEVICE_RESET:
return 0;
default:
return 1;
}
}
void FireAlarm_Activate(void) {
if (fire_alarm_latched) {
return;
}
fire_alarm_latched = 1;
CONN.chargingError = CONN_ERR_FIRE_ALARM;
CONN.connControl = CMD_STOP;
CONN.EnableOutput = 0;
log_printf(LOG_ERR, "FIRE ALARM activated\n");
CCS_SendEmergencyStop();
fire_alarm_last_estop_tick = HAL_GetTick();
CP_SetDuty(100);
CCS_ConnectorState = CCS_DISABLED;
CONN_SetState(Disabled);
}
void FireAlarm_Maintain(void) {
if (!fire_alarm_latched) {
return;
}
CONN.chargingError = CONN_ERR_FIRE_ALARM;
CONN.EnableOutput = 0;
CP_SetDuty(100);
if ((int32_t)(HAL_GetTick() - fire_alarm_last_estop_tick) >= 1000) {
CCS_SendEmergencyStop();
fire_alarm_last_estop_tick = HAL_GetTick();
}
if (CCS_ConnectorState != CCS_DISABLED && CCS_ConnectorState != CCS_UNKNOWN) {
CCS_ConnectorState = CCS_DISABLED;
}
if (CONN.connState != Disabled) {
CONN_SetState(Disabled);
}
}
+5
View File
@@ -1,4 +1,5 @@
#include "rgb_controller.h"
#include "fire_alarm.h"
#include "main.h"
#include "string.h"
#include "charger_control.h"
@@ -100,6 +101,10 @@ RGB_Cycle_t color_error = {
};
void LED_Write(){
if(FireAlarm_IsLatched() || CONN.chargingError == CONN_ERR_FIRE_ALARM){
LED_SetColor(&color_error);
return;
}
if(CONN.chargingError != CONN_NO_ERROR){
LED_SetColor(&color_error);
return;
+32 -3
View File
@@ -9,6 +9,7 @@
#include "charger_config.h"
#include "psu_control.h"
#include "serial_control.h"
#include "fire_alarm.h"
extern UART_HandleTypeDef huart3;
extern uint8_t config_initialized;
@@ -175,6 +176,7 @@ void CCS_SerialLoop(void) {
static uint32_t stop_tick = 0;
CCS_UART3_Watchdog();
FireAlarm_Maintain();
if (CONN.connControl != CMD_NONE) {
last_cmd = CONN.connControl;
@@ -216,7 +218,8 @@ void CCS_SerialLoop(void) {
if (((CONN.connControl == CMD_STOP) ||
(CONN.connControl == CMD_FORCE_UNLOCK) ||
(CONN.chargingError != CONN_NO_ERROR)) &&
(CONN.chargingError != CONN_NO_ERROR) ||
FireAlarm_IsLatched()) &&
((int32_t)(HAL_GetTick() - last_stop_sent) > 1000)) {
last_stop_sent = HAL_GetTick();
log_printf(LOG_WARN, "Stopping charging...\n");
@@ -259,6 +262,10 @@ void CCS_SerialLoop(void) {
everest_timed_out = host_timeout_stop;
switch(CCS_ConnectorState){
case CCS_UNKNOWN:
if (FireAlarm_IsLatched()) {
CCS_ConnectorState = CCS_DISABLED;
break;
}
RELAY_Write(RELAY_CP, 0);
CONN_SetState(Unknown);
if (config_initialized && !host_timed_out) {
@@ -268,11 +275,15 @@ void CCS_SerialLoop(void) {
case CCS_DISABLED:
RELAY_Write(RELAY_CP, 0);
CONN_SetState(Disabled);
if ((CONN.chargingError == CONN_NO_ERROR) && !host_timed_out){
if (!FireAlarm_IsLatched() && (CONN.chargingError == CONN_NO_ERROR) && !host_timed_out){
CCS_ConnectorState = CCS_UNPLUGGED;
}
break;
case CCS_UNPLUGGED:
if (FireAlarm_IsLatched()) {
CCS_ConnectorState = CCS_DISABLED;
break;
}
RELAY_Write(RELAY_CP, 1);
CONN_SetState(Unplugged);
if ((cp_state_buffer == EV_STATE_B_CONN_PREP) || (cp_state_buffer == EV_STATE_C_CONN_ACTIVE)){
@@ -285,6 +296,10 @@ void CCS_SerialLoop(void) {
break;
case CCS_AUTH_REQUIRED:
if (FireAlarm_IsLatched()) {
CCS_ConnectorState = CCS_DISABLED;
break;
}
RELAY_Write(RELAY_CP, 1);
CONN_SetState(AuthRequired);
if(CONN.connControl == CMD_START){
@@ -297,6 +312,10 @@ void CCS_SerialLoop(void) {
}
break;
case CCS_CONNECTED:
if (FireAlarm_IsLatched()) {
CCS_ConnectorState = CCS_DISABLED;
break;
}
RELAY_Write(RELAY_CP, 1);
if((CCS_EvseState < Preparing) || (CCS_EvseState == AuthRequired)) {
CONN_SetState(Preparing);
@@ -313,6 +332,10 @@ void CCS_SerialLoop(void) {
}
break;
case CCS_REPLUGGING:
if (FireAlarm_IsLatched()) {
CCS_ConnectorState = CCS_DISABLED;
break;
}
RELAY_Write(RELAY_CP, 0);
CONN_SetState(Replugging);
if((int32_t)(HAL_GetTick() - replug_tick) > 1000){
@@ -335,7 +358,13 @@ void CCS_SerialLoop(void) {
}
// 10s timeout: enforce safe-state until host communication recovers.
if (host_timeout_stop) {
if (FireAlarm_IsLatched()) {
CONN.EnableOutput = 0;
CP_SetDuty(100);
if (CCS_ConnectorState != CCS_DISABLED && CCS_ConnectorState != CCS_UNKNOWN) {
CCS_ConnectorState = CCS_DISABLED;
}
} else if (host_timeout_stop) {
CONN.EnableOutput = 0;
CCS_EvseState = Unknown;
CP_SetDuty(100);
+11
View File
@@ -4,6 +4,7 @@
#include "board.h"
#include "psu_control.h"
#include "debug.h"
#include "fire_alarm.h"
#include <string.h>
#ifdef USE_WEB_INTERFACE
@@ -27,6 +28,11 @@ void SC_CommandHandler(ReceivedCommand_t* cmd) {
uint8_t response_code = RESP_FAILED;
if (FireAlarm_IsBlockingCommand(cmd->command)) {
SC_SendPacket(NULL, 0, RESP_FAILED);
return;
}
switch (cmd->command) {
// Команды БЕЗ аргументов
case CMD_GET_STATUS:
@@ -86,6 +92,11 @@ void SC_CommandHandler(ReceivedCommand_t* cmd) {
// }
response_code = RESP_FAILED;
break;
case CMD_FIRE_ALARM:
FireAlarm_Activate();
response_code = RESP_SUCCESS;
break;
case CMD_DEVICE_RESET:
// 2. Отправляем SUCCESS (хост может успеть получить его перед ребутом)
SC_SendPacket(NULL, 0, RESP_SUCCESS);