big refactoring: J1939, log output, state machine bug fixes

This commit is contained in:
2026-05-07 22:12:13 +03:00
parent 137c9d3c8d
commit 7a74ef1367
49 changed files with 2574 additions and 684 deletions
+1 -1
View File
@@ -17,7 +17,7 @@ typedef enum{
RELAY_3,
RELAY_4,
RELAY_5,
RELAY_CP,
}relay_t;
typedef enum{
+2
View File
@@ -222,6 +222,7 @@ extern GBT_BSM_t GBT_BatteryStatus;
extern GBT_CSD_t GBT_ChargerStop;
extern uint8_t GBT_BRO;
extern uint8_t cc_enable;
extern uint8_t GBT_Charger_Enable;
@@ -254,6 +255,7 @@ void GBT_SendBRO(uint8_t state);
void GBT_SendBCL(void);
void GBT_SendBCS(void);
void GBT_SendBSM(void);
void GBT_SendBST(uint32_t causeCode);
void GBT_SendBSD(void);
+23 -1
View File
@@ -75,13 +75,35 @@ typedef struct {
uint8_t connectorType; // 0 - NONE, 1 - GBT, 2 - CCS (для EV всегда GBT)
} CONN_t;
extern CONN_t CONN;
extern CONN_t CONN[2];
void CONN_Init();
void CONN_Task();
void CONN_SetState(CONN_State_t state);
void CONN_CC_ReadStateFiltered(void);
uint8_t CONN_CC_GetStateRaw();
uint8_t CONN_CC_GetState();
float CONN_CC_GetAdc();
// STM32(EV) -> EVerest (EVSE)
// uint8_t SOC; // State of charge [%] // 2
// uint16_t RequestedVoltage; // 1V/bit
// uint16_t RequestedCurrent; // 0.1A/bit
// uint16_t MeasuredVoltage; // 1V/bit
// uint16_t MeasuredCurrent; // 0.1A/bit
// uint8_t ContactorEnabled; // 1 - enabled, 0 - disabled (команда на замыкание контактора)
// cp_state
// stop ????
// EVerest (EVSE) -> STM32(EV)
// uint16_t MeasuredVoltageSE; // 1V/bit
// uint16_t MeasuredCurrentSE; // 0.1A/bit
// uint8_t enableLoad; // 1 - enabled, 0 - disabled (команда на включение контактора)
// cp_state
// pwm_value
#endif /* INC_CONNECTOR_H_ */
+28
View File
@@ -0,0 +1,28 @@
#ifndef INC_CP_H_
#define INC_CP_H_
#include "main.h"
typedef enum {
EV_STATE_A_IDLE = 0,
EV_STATE_B_CONN_PREP = 1,
EV_STATE_C_CONN_ACTIVE = 2,
EV_STATE_D_CONN_ACT_VENT = 3,
EV_STATE_E_NO_POWER = 4,
EV_STATE_F_ERROR = 5,
EV_STATE_ACQUIRING = 6,
} CP_State_t;
typedef struct {
uint32_t frequency_hz;
uint8_t duty_percent;
uint8_t valid;
} CP_Measurement_t;
extern volatile CP_State_t cp_state;
void CP_Init(void);
void CP_Task(void);
CP_Measurement_t CP_GetMeasurement(void);
#endif /* INC_CP_H_ */
+7 -3
View File
@@ -8,9 +8,13 @@
#ifndef SRC_DEBUG_H_
#define SRC_DEBUG_H_
void debug_task();
void debug_init();
void debug_rx_interrupt(UART_HandleTypeDef *huart, uint16_t Size);
#include <stdint.h>
#include "edcan.h"
void debug_buffer_add(const uint8_t* data, uint16_t len);
uint16_t debug_buffer_available(void);
void debug_buffer_send(void);
int log_printf(int level, const char *format, ...);
#endif /* SRC_DEBUG_H_ */
+20
View File
@@ -27,11 +27,31 @@ typedef struct{
uint32_t tick;
}j_receive_t;
typedef struct{
uint32_t ExtId;
uint8_t DLC;
uint8_t data[8];
uint32_t tick;
}j1939_rx_frame_t;
typedef struct{
uint32_t ExtId;
uint8_t DLC;
uint8_t data[8];
}j1939_tx_frame_t;
extern j_receive_t j_rx;
void J_SendCTS(j_receive_t rx);
void J_SendACK(j_receive_t rx);
void J1939_ExchangeRxBuffer(void);
void J1939_ExchangeTxBuffer(void);
void J1939_InitBuffers(void);
uint16_t J1939_GetRxBufferCount(void);
uint16_t J1939_GetTxBufferCount(void);
uint32_t J1939_GetRxOverflowCount(void);
uint32_t J1939_GetTxOverflowCount(void);
void GBT_CAN_ReInit();
+6
View File
@@ -0,0 +1,6 @@
#pragma once
#include "main.h"
void LOAD_Init();
void LOAD_Task();
+16 -8
View File
@@ -57,12 +57,20 @@ void Error_Handler(void);
/* USER CODE END EFP */
/* Private defines -----------------------------------------------------------*/
#define CP_STATE_F_Pin GPIO_PIN_2
#define CP_STATE_F_GPIO_Port GPIOC
#define CP_RELAY_Pin GPIO_PIN_3
#define CP_RELAY_GPIO_Port GPIOC
#define IN_SW0_Pin GPIO_PIN_1
#define IN_SW0_GPIO_Port GPIOA
#define IN_SW1_Pin GPIO_PIN_2
#define IN_SW1_GPIO_Port GPIOA
#define CP_STATE_C_Pin GPIO_PIN_5
#define CP_STATE_C_GPIO_Port GPIOA
#define ADC_CC1_Pin GPIO_PIN_6
#define ADC_CC1_GPIO_Port GPIOA
#define CP_PWM_Pin GPIO_PIN_7
#define CP_PWM_GPIO_Port GPIOA
#define LOCK_A_Pin GPIO_PIN_4
#define LOCK_A_GPIO_Port GPIOC
#define LOCK_B_Pin GPIO_PIN_5
@@ -73,16 +81,16 @@ void Error_Handler(void);
#define ADC_NTC2_GPIO_Port GPIOB
#define IN0_Pin GPIO_PIN_7
#define IN0_GPIO_Port GPIOE
#define RELAY5_Pin GPIO_PIN_8
#define RELAY5_GPIO_Port GPIOE
#define RELAY4_Pin GPIO_PIN_9
#define RELAY4_GPIO_Port GPIOE
#define RELAY1_Pin GPIO_PIN_8
#define RELAY1_GPIO_Port GPIOE
#define RELAY2_Pin GPIO_PIN_9
#define RELAY2_GPIO_Port GPIOE
#define RELAY3_Pin GPIO_PIN_10
#define RELAY3_GPIO_Port GPIOE
#define RELAY2_Pin GPIO_PIN_11
#define RELAY2_GPIO_Port GPIOE
#define RELAY1_Pin GPIO_PIN_12
#define RELAY1_GPIO_Port GPIOE
#define RELAY4_Pin GPIO_PIN_11
#define RELAY4_GPIO_Port GPIOE
#define RELAY5_Pin GPIO_PIN_12
#define RELAY5_GPIO_Port GPIOE
#define AC_OK_Pin GPIO_PIN_14
#define AC_OK_GPIO_Port GPIOE
#define RELAY_CC_Pin GPIO_PIN_15
+130
View File
@@ -0,0 +1,130 @@
#ifndef SERIAL_CONTROL_H
#define SERIAL_CONTROL_H
#include <stdint.h>
#include "main.h"
#include "connector.h"
/* Read-only commands */
#define CMD_GET_INFO 0x01
#define CMD_ISOLATION_STATUS 0x01 /* UART5 isolation block packet */
#define CMD_GET_GBT_STATUS 0x02
#define CMD_GET_CCS_STATUS 0x03
#define CMD_GET_LOG 0x50
#define CMD_GET_LOG_CONTINUE 0x51
/* GBT control commands */
#define CMD_GBT_CC_ENABLE 0x10
#define CMD_GBT_STOP 0x11
#define CMD_GBT_SET_SOC 0x12
#define CMD_GBT_SET_REQUEST 0x13
#define CMD_GBT_SET_VIN 0x18
/* CCS control commands */
#define CMD_CCS_SET_STATE 0x20
#define CMD_CCS_ENABLE_LOAD 0x24
/* Response codes */
#define RESP_SUCCESS 0x12
#define RESP_FAILED 0x13
#define RESP_INVALID 0x14
#define MAX_TX_BUFFER_SIZE 256
#define MAX_RX_BUFFER_SIZE 256
#define CRC32_POLYNOMIAL ((uint32_t)0xEDB88320)
typedef struct __attribute__((packed)) {
uint8_t command;
uint8_t argument_length;
void *argument;
} ReceivedCommand_t;
typedef enum {
SC_SOURCE_UART2 = 0,
SC_SOURCE_UART5 = 1,
} SC_Source_t;
typedef struct __attribute__((packed)) {
uint8_t isolationStatus;
uint16_t isolationResistance;
int16_t voltageHigh;
int16_t voltageLow;
int16_t voltageComm;
} IsolationStatusPacket_t;
typedef struct __attribute__((packed)) {
uint16_t requestedVoltage; /* 1V/bit */
uint16_t requestedCurrent; /* 0.1A/bit */
} EvSetLimits_t;
typedef struct __attribute__((packed)) {
uint16_t measuredVoltage; /* 1V/bit */
uint16_t measuredCurrent; /* 0.1A/bit */
} EvSetMeasured_t;
typedef struct __attribute__((packed)) {
uint8_t connector_type; /* 0x01 (GBT) */
uint16_t requestedVoltage; /* V */
uint16_t requestedCurrent; /* 0.1A/bit */
uint16_t measuredVoltageSE; /* V */
uint16_t measuredCurrentSE; /* 0.1A/bit */
uint16_t measuredVoltage; /* 1V/bit */
uint16_t measuredCurrent; /* 0.1A/bit */
uint8_t cc_enabled;
uint8_t contactorEnabled;
CONN_Error_t chargingError;
uint8_t EvseConnected;
uint8_t soc; /* % */
uint8_t vin[17];
uint8_t cc_state;
uint8_t logs_available;
CONN_State_t connState;
} GBT_MonitorPacket_t;
typedef struct __attribute__((packed)) {
uint8_t connector_type; /* 0x02 (CCS) */
uint16_t measuredVoltage; /* 1V/bit */
uint16_t measuredCurrent; /* 0.1A/bit */
uint8_t cp_enabled;
uint8_t contactorEnabled;
CONN_Error_t chargingError;
uint8_t EvseConnected;
uint8_t soc; /* % */
uint8_t cp_state; /* A/B/C/D/E/... enum value */
uint8_t cp_pwm_duty; /* % */
CONN_State_t connState;
} CCS_MonitorPacket_t;
typedef struct __attribute__((packed)) {
uint16_t serialNumber;
uint8_t boardVersion;
uint8_t stationType;
uint16_t fw_version_major;
uint16_t fw_version_minor;
uint16_t fw_version_patch;
} InfoPacket_t;
typedef struct SerialControl_t SerialControl_t;
struct SerialControl_t {
uint8_t tx_buffer[MAX_TX_BUFFER_SIZE];
uint8_t rx_buffer[MAX_RX_BUFFER_SIZE];
volatile ReceivedCommand_t received_command;
volatile uint8_t command_ready;
volatile uint8_t response_pending;
volatile uint8_t response_code;
volatile uint32_t tx_tick;
};
void SC_Init(void);
void SC_Task(void);
void SC_SendPacket(const uint8_t *payload, uint16_t payload_len, uint8_t response_code);
void SC_CommandHandler(ReceivedCommand_t *cmd);
extern SerialControl_t serial_control;
extern GBT_MonitorPacket_t gbtMonitorPacket;
extern CCS_MonitorPacket_t ccsMonitorPacket;
extern InfoPacket_t infoPacket;
extern IsolationStatusPacket_t ISO;
extern volatile SC_Source_t g_sc_command_source;
#endif /* SERIAL_CONTROL_H */
+2
View File
@@ -56,7 +56,9 @@ void DebugMon_Handler(void);
void PendSV_Handler(void);
void SysTick_Handler(void);
void CAN1_RX0_IRQHandler(void);
void TIM3_IRQHandler(void);
void USART2_IRQHandler(void);
void UART5_IRQHandler(void);
void CAN2_TX_IRQHandler(void);
void CAN2_RX1_IRQHandler(void);
/* USER CODE BEGIN EFP */
+3
View File
@@ -32,12 +32,15 @@ extern "C" {
/* USER CODE END Includes */
extern TIM_HandleTypeDef htim3;
extern TIM_HandleTypeDef htim4;
/* USER CODE BEGIN Private defines */
/* USER CODE END Private defines */
void MX_TIM3_Init(void);
void MX_TIM4_Init(void);
void HAL_TIM_MspPostInit(TIM_HandleTypeDef *htim);
+4 -2
View File
@@ -85,11 +85,12 @@ void HAL_ADC_MspInit(ADC_HandleTypeDef* adcHandle)
__HAL_RCC_GPIOB_CLK_ENABLE();
/**ADC1 GPIO Configuration
PA3 ------> ADC1_IN3
PA4 ------> ADC1_IN4
PA6 ------> ADC1_IN6
PB0 ------> ADC1_IN8
PB1 ------> ADC1_IN9
*/
GPIO_InitStruct.Pin = GPIO_PIN_3|ADC_CC1_Pin;
GPIO_InitStruct.Pin = GPIO_PIN_3|GPIO_PIN_4|ADC_CC1_Pin;
GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
@@ -116,11 +117,12 @@ void HAL_ADC_MspDeInit(ADC_HandleTypeDef* adcHandle)
/**ADC1 GPIO Configuration
PA3 ------> ADC1_IN3
PA4 ------> ADC1_IN4
PA6 ------> ADC1_IN6
PB0 ------> ADC1_IN8
PB1 ------> ADC1_IN9
*/
HAL_GPIO_DeInit(GPIOA, GPIO_PIN_3|ADC_CC1_Pin);
HAL_GPIO_DeInit(GPIOA, GPIO_PIN_3|GPIO_PIN_4|ADC_CC1_Pin);
HAL_GPIO_DeInit(GPIOB, ADC_NTC1_Pin|ADC_NTC2_Pin);
+3 -1
View File
@@ -20,6 +20,7 @@ void RELAY_Write(relay_t num, uint8_t state){
if(num==RELAY_4)HAL_GPIO_WritePin(RELAY4_GPIO_Port, RELAY4_Pin, state);
if(num==RELAY_5)HAL_GPIO_WritePin(RELAY5_GPIO_Port, RELAY5_Pin, state);
if(num==RELAY_CC)HAL_GPIO_WritePin(RELAY_CC_GPIO_Port, RELAY_CC_Pin, state);
if(num==RELAY_CP)HAL_GPIO_WritePin(CP_RELAY_GPIO_Port, CP_RELAY_Pin, state);
}
@@ -74,7 +75,8 @@ void Init_Peripheral(){
RELAY_Write(RELAY_3, 0);
RELAY_Write(RELAY_4, 0);
RELAY_Write(RELAY_5, 0);
RELAY_Write(RELAY_CC, 1);
RELAY_Write(RELAY_CC, 0);
RELAY_Write(RELAY_CP, 0);
}
+98 -43
View File
@@ -15,6 +15,7 @@
#include "edcan.h"
#include "connector.h"
#include "soft_rtc.h"
#include "debug.h"
uint8_t GBT_CC_GetStateRaw();
@@ -49,6 +50,7 @@ GBT_CCS_t GBT_ChargerCurrentStatus;
GBT_CSD_t GBT_ChargerStop;
uint8_t GBT_BRO;
uint8_t cc_enable;
uint32_t GBT_TimeChargingStarted;
@@ -57,17 +59,28 @@ uint32_t GBT_ErrorCode;
GBT_StopSource_t GBT_StopSource;
static uint32_t GBT_EVSE_last_rx_tick;
#define GBT_EV_HANDSHAKE_TIMEOUT_MS 10000U
#define GBT_EV_WAIT_READY_TIMEOUT_MS 10000U
#define GBT_EV_CHARGING_RX_TIMEOUT_MS 3000U
void GBT_Init(){
GBT_State = GBT_DISABLED;
CONN.connControl = CMD_NONE;
CONN[0].connControl = CMD_NONE;
cc_enable = 0U;
memcpy(GBT_EVInfo.EVIN, "EDISON_TEST_EVIN_", 17);
memcpy(GBT_EVInfo.EV_SW_VER, "1.0.0", 8);
GBT_Reset();
}
void GBT_ChargerTask(){
RELAY_Write(RELAY_CC, cc_enable);
//GBT_LockTask();
if(j_rx.state == 2){
GBT_EVSE_last_rx_tick = HAL_GetTick();
switch (j_rx.PGN){
case 0x2600: // CHM EVSE->EV (старт/версия GB/T)
GBT_CHM_recv = 1;
@@ -93,10 +106,12 @@ void GBT_ChargerTask(){
case 0x1200: // CCS EVSE->EV (текущий статус зарядника)
memcpy(&GBT_ChargerCurrentStatus, j_rx.data, sizeof(GBT_ChargerCurrentStatus));
CONN.enableLoad = GBT_ChargerCurrentStatus.chargingPermissible;
CONN.ChargingTime = GBT_ChargerCurrentStatus.chargingTime;
CONN.MeasuredVoltageSE = GBT_ChargerCurrentStatus.outputVoltage / 10;
CONN.MeasuredCurrentSE = 4000 - GBT_ChargerCurrentStatus.outputCurrent;
if(GBT_State == GBT_EV_CHARGING) {
CONN[0].enableLoad = GBT_ChargerCurrentStatus.chargingPermissible;
}
CONN[0].ChargingTime = GBT_ChargerCurrentStatus.chargingTime;
CONN[0].MeasuredVoltageSE = GBT_ChargerCurrentStatus.outputVoltage / 10;
CONN[0].MeasuredCurrentSE = 4000 - GBT_ChargerCurrentStatus.outputCurrent;
break;
case 0x1A00: // CST EVSE->EV (остановка зарядки по инициативе EVSE)
@@ -115,11 +130,18 @@ void GBT_ChargerTask(){
j_rx.state = 0;
}
if((connectorState == Unplugged) && (GBT_State != GBT_DISABLED)){
log_printf(LOG_INFO, "Car unplugged, resetting charge session\n");
CONN[0].enableLoad = 0;
GBT_Reset();
return;
}
if((HAL_GetTick() - GBT_delay_start) < GBT_delay){
//waiting
}else switch (GBT_State){
case GBT_DISABLED:
CONN.enableLoad = 0;
CONN[0].enableLoad = 0;
// if(connectorState == Preparing){
// GBT_Reset();
// GBT_SwitchState(GBT_EV_CONNECTING);
@@ -133,25 +155,31 @@ void GBT_ChargerTask(){
GBT_Delay(250);
if (GBT_CHM_recv) {
log_printf(LOG_INFO, "CHM received, starting EV handshake\n");
GBT_SwitchState(GBT_EV_HANDSHAKE);
break;
}
if (GBT_StateTick() > 10000) {
GBT_Error(0xFCF0C0FC);
EDCAN_printf(LOG_WARN, "CHM timeout\n");
log_printf(LOG_WARN, "CHM timeout\n");
}
break;
case GBT_EV_HANDSHAKE:
// 2) Постоянно шлём BHM, ждём CRM (0x0100, первый раз 0x00)
GBT_MaxVoltage.maxOutputVoltage = 4500; // 450V
GBT_MaxVoltage.maxOutputVoltage = CONN[0].RequestedVoltage * 10;
if (j_rx.state == 0) GBT_SendBHM();
GBT_Delay(250);
if (GBT_CRM_recv) {
log_printf(LOG_INFO, "CRM received, sending BRM (EV identification)\n");
GBT_SwitchState(GBT_EV_RECOGNITION);
break;
}
if (GBT_StateTick() > GBT_EV_HANDSHAKE_TIMEOUT_MS) {
GBT_Error(0xFCF0C0FD);
log_printf(LOG_WARN, "CRM timeout in EV_HANDSHAKE\n");
}
break;
@@ -171,19 +199,18 @@ void GBT_ChargerTask(){
GBT_EVInfo.batteryCycleCount = 666;
GBT_EVInfo.ownAuto = 1;
GBT_EVInfo.rsvd0 = 0;
memcpy(GBT_EVInfo.EVIN, "EDISON_TEST_EVIN_", 17);
memcpy(GBT_EVInfo.EV_SW_VER, "1.0.0", 8);
if (j_rx.state == 0) GBT_SendBRM(); // TODO CHUNKED SEND
GBT_Delay(250);
if ((GBT_CRM_recv) && (GBT_ChargerInfo.bmsIdentified == 0xAA)) {
log_printf(LOG_INFO, "EV identified by charger, sending BCP\n");
GBT_SwitchState(GBT_EV_CHARGING_PARAMETERS);
break;
}
if (GBT_StateTick() > 5000) {
GBT_Error(0xFCF1C0FC);
EDCAN_printf(LOG_WARN, "CRM(0xAA) timeout (wait BCP)\n");
log_printf(LOG_WARN, "CRM(0xAA) timeout (wait BCP)\n");
}
break;
@@ -193,12 +220,13 @@ void GBT_ChargerTask(){
GBT_Delay(250);
if (GBT_CML_recv) {
log_printf(LOG_INFO, "CML received, starting BMS initialization\n");
GBT_SwitchState(GBT_EV_BMS_INIT);
break;
}
if (GBT_StateTick() > 5000) {
GBT_Error(0xFCF4C0FC);
EDCAN_printf(LOG_WARN, "CML timeout\n");
log_printf(LOG_WARN, "CML timeout\n");
}
break;
case GBT_EV_BMS_INIT:
@@ -206,6 +234,7 @@ void GBT_ChargerTask(){
if (j_rx.state == 0) GBT_SendBRO(0x00);
GBT_Delay(250);
if (GBT_StateTick() > 1500) {
log_printf(LOG_INFO, "BMS initialized, waiting charger ready signal\n");
GBT_SwitchState(GBT_EV_WAIT_CHARGER_READY);
break;
}
@@ -219,17 +248,23 @@ void GBT_ChargerTask(){
GBT_Delay(250);
if (GBT_CRO_val == 0xAA) {
log_printf(LOG_INFO, "Charger ready, entering active charging\n");
GBT_SwitchState(GBT_EV_CHARGING);
GBT_TimeChargingStarted = get_Current_Time();
GBT_EVSE_last_rx_tick = HAL_GetTick();
break;
}
if (GBT_StateTick() > GBT_EV_WAIT_READY_TIMEOUT_MS) {
GBT_Error(0xFCF2C0FD);
log_printf(LOG_WARN, "CRO(0xAA) timeout in EV_WAIT_CHARGER_READY\n");
}
break;
case GBT_EV_CHARGING:
// Основной режим зарядки: EV периодически шлёт BCS/BSM.
GBT_ReqPower.requestedVoltage = CONN.RequestedVoltage * 10;
GBT_ReqPower.requestedCurrent = 4000 - CONN.RequestedCurrent;
GBT_ReqPower.requestedVoltage = CONN[0].RequestedVoltage * 10;
GBT_ReqPower.requestedCurrent = 4000 - CONN[0].RequestedCurrent;
GBT_ReqPower.chargingMode = 1;
GBT_BATStat.maxCellVoltage = 320;
@@ -237,23 +272,32 @@ void GBT_ChargerTask(){
GBT_BATStat.totalEnergy = 6;
GBT_BATStat.maxChargingVoltage = 500;
GBT_BATStat.maxTemp = 70;
GBT_BATStat.SOC = CONN.SOC;
GBT_BATStat.measVoltage = CONN.MeasuredVoltage;
GBT_BATStat.SOC = CONN[0].SOC;
GBT_BATStat.measVoltage = CONN[0].MeasuredVoltage;
// Стоп по инициативе EVSE (получили CST)
if (GBT_CST_recv) {
log_printf(LOG_INFO, "Charging stop requested by EVSE (CST)\n");
GBT_StopEVSE(GBT_CST_SUDDENSTOP);
break;
}
// Стоп по команде с машины (EDCAN)
if (CONN.connControl == CMD_STOP) {
if (CONN[0].connControl == CMD_STOP) {
CONN[0].connControl = CMD_NONE;
log_printf(LOG_INFO, "Charging stop requested by EV command\n");
GBT_StopEV(GBT_CST_BMS_ACTIVELY_SUSPENDS);
break;
}
if (IN_ReadInput(IN_ESTOP)) {
log_printf(LOG_INFO, "Charging stop requested by emergency input\n");
GBT_StopEV(GBT_CST_BMS_ACTIVELY_SUSPENDS);
break;
}
if ((HAL_GetTick() - GBT_EVSE_last_rx_tick) > GBT_EV_CHARGING_RX_TIMEOUT_MS) {
log_printf(LOG_WARN, "EVSE RX timeout in EV_CHARGING\n");
GBT_StopEVSE(GBT_CST_SUDDENSTOP);
break;
}
GBT_SendBCS();
GBT_SendBCL();
@@ -263,14 +307,23 @@ void GBT_ChargerTask(){
case GBT_STOP:
GBT_Delay(10);
CONN.enableLoad = 0;
// EV шлёт BSD (Battery Stop Data), не CST (CST шлёт EVSE)
GBT_SendBSD();
CONN[0].enableLoad = 0;
if (GBT_StopSource == GBT_STOP_EV) {
// EV-инициированный stop: сначала BST, ждём ответный CST, потом BSD.
GBT_SendBST(GBT_StopCauseCode);
if (GBT_CST_recv) {
GBT_SendBSD();
}
} else {
// EVSE-инициированный stop: EV сразу отвечает BSD.
GBT_SendBSD();
}
if (GBT_StateTick() > 10000) {
EDCAN_printf(LOG_WARN, "CSD Timeout\n");
log_printf(LOG_WARN, "CSD Timeout\n");
GBT_Error(0xFCF0C0FD); // CSD timeout
}
if (GBT_CSD_recv) {
log_printf(LOG_INFO, "CSD received, finalizing charge session\n");
GBT_SwitchState(GBT_STOP_CSD);
}
break;
@@ -279,6 +332,7 @@ void GBT_ChargerTask(){
// EV не шлёт CSD (финальный отчёт шлёт EVSE). Ждём 2.5 с и завершаем.
GBT_Delay(250);
if (GBT_StateTick() > 2500) {
log_printf(LOG_INFO, "Charge session completed\n");
GBT_SwitchState(GBT_COMPLETE);
}
break;
@@ -301,8 +355,8 @@ void GBT_ChargerTask(){
default:
GBT_SwitchState(GBT_DISABLED);
}
if (CONN_CC_GetState()==GBT_CC_4V) CONN.EvseConnected = 1;
else CONN.EvseConnected = 0;
if (CONN_CC_GetState()==GBT_CC_4V) CONN[0].EvseConnected = 1;
else CONN[0].EvseConnected = 0;
}
@@ -311,18 +365,18 @@ void GBT_SwitchState(gbtState_t state){
GBT_State = state;
GBT_state_tick = HAL_GetTick();
if(GBT_State == GBT_DISABLED) EDCAN_printf(LOG_INFO, "GBT_DISABLED\n");
if(GBT_State == GBT_EV_CONNECTING) EDCAN_printf(LOG_INFO, "GBT_EV_CONNECTING\n");
if(GBT_State == GBT_EV_HANDSHAKE) EDCAN_printf(LOG_INFO, "GBT_EV_HANDSHAKE\n");
if(GBT_State == GBT_EV_RECOGNITION) EDCAN_printf(LOG_INFO, "GBT_EV_RECOGNITION\n");
if(GBT_State == GBT_EV_CHARGING_PARAMETERS) EDCAN_printf(LOG_INFO, "GBT_EV_CHARGING_PARAMETERS\n");
if(GBT_State == GBT_EV_BMS_INIT) EDCAN_printf(LOG_INFO, "GBT_EV_BMS_INIT\n");
if(GBT_State == GBT_EV_WAIT_CHARGER_READY) EDCAN_printf(LOG_INFO, "GBT_EV_WAIT_CHARGER_READY\n");
if(GBT_State == GBT_EV_CHARGING) EDCAN_printf(LOG_INFO, "GBT_EV_CHARGING\n");
if(GBT_State == GBT_STOP) EDCAN_printf(LOG_INFO, "GBT_STOP\n");
if(GBT_State == GBT_STOP_CSD) EDCAN_printf(LOG_INFO, "GBT_STOP_CSD\n");
if(GBT_State == GBT_ERROR) EDCAN_printf(LOG_WARN, "GBT_ERROR\n");
if(GBT_State == GBT_COMPLETE) EDCAN_printf(LOG_INFO, "GBT_COMPLETE\n");
if(GBT_State == GBT_DISABLED) log_printf(LOG_DEBUG, "DBG_STATE: GBT_DISABLED\n");
if(GBT_State == GBT_EV_CONNECTING) log_printf(LOG_DEBUG, "DBG_STATE: GBT_EV_CONNECTING\n");
if(GBT_State == GBT_EV_HANDSHAKE) log_printf(LOG_DEBUG, "DBG_STATE: GBT_EV_HANDSHAKE\n");
if(GBT_State == GBT_EV_RECOGNITION) log_printf(LOG_DEBUG, "DBG_STATE: GBT_EV_RECOGNITION\n");
if(GBT_State == GBT_EV_CHARGING_PARAMETERS) log_printf(LOG_DEBUG, "DBG_STATE: GBT_EV_CHARGING_PARAMETERS\n");
if(GBT_State == GBT_EV_BMS_INIT) log_printf(LOG_DEBUG, "DBG_STATE: GBT_EV_BMS_INIT\n");
if(GBT_State == GBT_EV_WAIT_CHARGER_READY) log_printf(LOG_DEBUG, "DBG_STATE: GBT_EV_WAIT_CHARGER_READY\n");
if(GBT_State == GBT_EV_CHARGING) log_printf(LOG_DEBUG, "DBG_STATE: GBT_EV_CHARGING\n");
if(GBT_State == GBT_STOP) log_printf(LOG_DEBUG, "DBG_STATE: GBT_STOP\n");
if(GBT_State == GBT_STOP_CSD) log_printf(LOG_DEBUG, "DBG_STATE: GBT_STOP_CSD\n");
if(GBT_State == GBT_COMPLETE) log_printf(LOG_DEBUG, "DBG_STATE: GBT_COMPLETE\n");
if(GBT_State == GBT_ERROR) log_printf(LOG_WARN, "State machine entered ERROR state\n");
}
@@ -337,7 +391,7 @@ void GBT_Delay(uint32_t delay){
}
void GBT_StopEV(uint32_t causecode){ // --> Suspend EV
if (CONN.chargingError){
if (CONN[0].chargingError){
GBT_StopSource = GBT_STOP_EVSE;
}else{
GBT_StopSource = GBT_STOP_EV;
@@ -361,13 +415,13 @@ void GBT_StopOCPP(uint32_t causecode){ // --> Finished
void GBT_ForceStop(){ // --> Suspend EV
GBT_StopSource = GBT_STOP_EV;
// Отключаем силовой контактор батареи со стороны EV
CONN.enableLoad = 0;
CONN[0].enableLoad = 0;
GBT_SwitchState(GBT_COMPLETE);
}
void GBT_Error(uint32_t errorcode){ // --> Suspend EV
GBT_StopSource = GBT_STOP_EV;
EDCAN_printf(LOG_WARN, "GBT Error code: 0x%X\n", errorcode);
log_printf(LOG_WARN, "GBT Error code: 0x%X\n", errorcode);
GBT_ErrorCode = errorcode;
GBT_SwitchState(GBT_ERROR);
}
@@ -381,11 +435,11 @@ void GBT_Reset(){
GBT_CST_recv = 0;
GBT_CSD_recv = 0;
GBT_CRO_val = 0x00;
CONN.SOC = 0;
CONN.enableLoad = 0;
CONN.RequestedCurrent = 1000;
CONN.RequestedVoltage = 400;
CONN.chargingError = 0;
CONN[0].SOC = 0;
CONN[0].enableLoad = 0;
CONN[0].RequestedCurrent = 1000;
CONN[0].RequestedVoltage = 400;
CONN[0].chargingError = 0;
memset(&GBT_EVInfo, 0, sizeof (GBT_EVInfo));
memset(&GBT_BATStat, 0, sizeof (GBT_BATStat));
memset(&GBT_ReqPower, 0, sizeof (GBT_ReqPower));
@@ -399,4 +453,5 @@ void GBT_Reset(){
GBT_CurrPower.requestedVoltage = 500; //50V
GBT_TimeChargingStarted = 0;
GBT_BRO = 0x00;
GBT_EVSE_last_rx_tick = HAL_GetTick();
}
+34 -24
View File
@@ -7,12 +7,14 @@
#include "connector.h"
#include "board.h"
#include "edcan.h"
#include "debug.h"
#include <string.h>
#include <charger_gbt.h>
CONN_State_t connectorState;
CONN_t CONN;
// CONN[0] - GB/T, CONN[1] - CCS (reserved for future use)
CONN_t CONN[2];
uint8_t CC_STATE_FILTERED;
@@ -20,19 +22,18 @@ static void CONN_UpdateEdcanOutput(void);
void CONN_Init(){
memset(&CONN, 0, sizeof(CONN));
CONN.connControl = CMD_NONE;
CONN[0].connControl = CMD_NONE;
CONN_SetState(Unknown);
}
void CONN_Task(){
switch (connectorState){
case Unknown:
CONN_SetState(Unplugged);
break;
case Disabled:
if(CONN.chargingError == 0) {
if(CONN[0].chargingError == 0) {
CONN_SetState(Unplugged);
}
break;
@@ -40,10 +41,11 @@ void CONN_Task(){
{
// Обновляем признак физического подключения разъёма по уровню CC
if(CONN_CC_GetState() == GBT_CC_4V){
CONN.EvseConnected = 1;
CONN[0].EvseConnected = 1;
log_printf(LOG_INFO, "Charger plugged, waiting for 12V AUX\n");
CONN_SetState(AuthRequired);
}else{
CONN.EvseConnected = 0;
CONN[0].EvseConnected = 0;
}
break;
}
@@ -52,6 +54,7 @@ void CONN_Task(){
{
// Если уровень CC вернулся к 6/12В – считаем, что коннектор выдернули
if(CONN_CC_GetState() != GBT_CC_4V){
log_printf(LOG_INFO, "Charger unplugged\n");
CONN_SetState(Unplugged);
GBT_Reset();
break;
@@ -59,6 +62,7 @@ void CONN_Task(){
// Как только появляется 12V AUX от станции – переходим в Preparing (инициализация протокола)
if(IN_ReadInput(IN_0) == 1){
log_printf(LOG_INFO, "12V AUX detected, starting session\n");
CONN_SetState(Preparing);
GBT_SwitchState(GBT_EV_CONNECTING);
}
@@ -69,11 +73,15 @@ void CONN_Task(){
// Ожидаем переход стейт-машины GB/T в режим зарядки.
// Как только GBT_State уходит в режим CHARGING – считаем, что начался заряд.
if(GBT_State == GBT_EV_CHARGING){
log_printf(LOG_INFO, "Charging started\n");
CONN_SetState(Charging);
}
if(IN_ReadInput(IN_0) == 0){
CONN_SetState(Unplugged);
GBT_Reset();
// if(IN_ReadInput(IN_0) == 0){
// CONN_SetState(Unplugged);
// GBT_Reset();
// }
if(GBT_State == GBT_DISABLED){
CONN_SetState(Finished);
}
break;
@@ -84,6 +92,7 @@ void CONN_Task(){
CONN_SetState(Finished);
}
if(IN_ReadInput(IN_0) == 0){
log_printf(LOG_INFO, "12V AUX removed, finishing session\n");
CONN_SetState(Finished);
}
break;
@@ -91,6 +100,7 @@ void CONN_Task(){
case Finished: // Сессия завершена, ждём окончания и возможного переподключения
// Когда GB/T стейт-машина полностью вернулась в исходное состояние,
// можно считать сессию закрытой и вернуться в Unplugged.
cc_enable = 0;
if(CONN_CC_GetState() != GBT_CC_4V){
CONN_SetState(Unplugged);
GBT_Reset();
@@ -111,22 +121,22 @@ void CONN_Task(){
void CONN_SetState(CONN_State_t state){
connectorState = state;
CONN.connState = state;
CONN[0].connState = state;
if(connectorState == Unknown) EDCAN_printf(LOG_INFO,"Unknown\n");
if(connectorState == Unplugged) EDCAN_printf(LOG_INFO,"Unplugged\n");
if(connectorState == Disabled) EDCAN_printf(LOG_INFO,"Disabled\n");
if(connectorState == Preparing) EDCAN_printf(LOG_INFO,"Preparing\n");
if(connectorState == AuthRequired) EDCAN_printf(LOG_INFO,"AuthRequired\n");
if(connectorState == WaitingForEnergy) EDCAN_printf(LOG_INFO,"WaitingForEnergy\n");
if(connectorState == ChargingPausedEV) EDCAN_printf(LOG_INFO,"ChargingPausedEV\n");
if(connectorState == ChargingPausedEVSE) EDCAN_printf(LOG_INFO,"ChargingPausedEVSE\n");
if(connectorState == Charging) EDCAN_printf(LOG_INFO,"Charging\n");
if(connectorState == AuthTimeout) EDCAN_printf(LOG_INFO,"AuthTimeout\n");
if(connectorState == Finished) EDCAN_printf(LOG_INFO,"Finished\n");
if(connectorState == FinishedEVSE) EDCAN_printf(LOG_INFO,"FinishedEVSE\n");
if(connectorState == FinishedEV) EDCAN_printf(LOG_INFO,"FinishedEV\n");
if(connectorState == Replugging) EDCAN_printf(LOG_INFO,"Replugging\n");
if(connectorState == Unknown) log_printf(LOG_DEBUG,"ConnState: Unknown\n");
if(connectorState == Unplugged) log_printf(LOG_DEBUG,"ConnState: Unplugged\n");
if(connectorState == Disabled) log_printf(LOG_DEBUG,"ConnState: Disabled\n");
if(connectorState == Preparing) log_printf(LOG_DEBUG,"ConnState: Preparing\n");
if(connectorState == AuthRequired) log_printf(LOG_DEBUG,"ConnState: AuthRequired\n");
if(connectorState == WaitingForEnergy) log_printf(LOG_DEBUG,"ConnState: WaitingForEnergy\n");
if(connectorState == ChargingPausedEV) log_printf(LOG_DEBUG,"ConnState: ChargingPausedEV\n");
if(connectorState == ChargingPausedEVSE) log_printf(LOG_DEBUG,"ConnState: ChargingPausedEVSE\n");
if(connectorState == Charging) log_printf(LOG_DEBUG,"ConnState: Charging\n");
if(connectorState == AuthTimeout) log_printf(LOG_DEBUG,"ConnState: AuthTimeout\n");
if(connectorState == Finished) log_printf(LOG_DEBUG,"ConnState: Finished\n");
if(connectorState == FinishedEVSE) log_printf(LOG_DEBUG,"ConnState: FinishedEVSE\n");
if(connectorState == FinishedEV) log_printf(LOG_DEBUG,"ConnState: FinishedEV\n");
if(connectorState == Replugging) log_printf(LOG_DEBUG,"ConnState: Replugging\n");
}
+194
View File
@@ -0,0 +1,194 @@
#include "cp.h"
#include "tim.h"
#define CP_CAPTURE_TARGET_CLK_HZ 1000000U
#define CP_INPUT_SIGNAL_INVERTED 1U
typedef enum {
CP_WAIT_RISING_1 = 0,
CP_WAIT_FALLING,
CP_WAIT_RISING_2
} CP_CaptureState_t;
static volatile CP_CaptureState_t cp_capture_state = CP_WAIT_RISING_1;
static volatile uint32_t cp_rise_1 = 0;
static volatile uint32_t cp_fall = 0;
static volatile uint32_t cp_rise_2 = 0;
static volatile uint32_t cp_last_update_ms = 0;
static volatile CP_Measurement_t cp_measurement = {0, 0, 0};
static uint32_t CP_TicksDiff(uint32_t now, uint32_t prev, uint32_t arr);
static uint32_t CP_GetTimerClockHz(void);
static void CP_ApplyStateOutputs(void);
static uint32_t CP_GetTim3InputClockHz(void);
void CP_Init(void) {
TIM_IC_InitTypeDef sConfigIC = {0};
uint32_t tim3_input_clk = CP_GetTim3InputClockHz();
uint32_t target_prescaler = 0U;
if (tim3_input_clk > CP_CAPTURE_TARGET_CLK_HZ) {
target_prescaler = (tim3_input_clk / CP_CAPTURE_TARGET_CLK_HZ) - 1U;
}
if (target_prescaler > 0xFFFFU) {
target_prescaler = 0xFFFFU;
}
__HAL_TIM_SET_PRESCALER(&htim3, (uint16_t)target_prescaler);
__HAL_TIM_SET_COUNTER(&htim3, 0U);
sConfigIC.ICPolarity = TIM_INPUTCHANNELPOLARITY_RISING;
sConfigIC.ICSelection = TIM_ICSELECTION_DIRECTTI;
sConfigIC.ICPrescaler = TIM_ICPSC_DIV1;
sConfigIC.ICFilter = 2;
HAL_TIM_IC_ConfigChannel(&htim3, &sConfigIC, TIM_CHANNEL_2);
cp_capture_state = CP_WAIT_RISING_1;
cp_measurement.valid = 0;
cp_last_update_ms = HAL_GetTick();
CP_ApplyStateOutputs();
HAL_TIM_IC_Start_IT(&htim3, TIM_CHANNEL_2);
}
void CP_Task(void) {
CP_ApplyStateOutputs();
if ((HAL_GetTick() - cp_last_update_ms) > 200U) {
cp_measurement.valid = 0;
cp_measurement.frequency_hz = 0;
cp_measurement.duty_percent = 0;
}
}
CP_Measurement_t CP_GetMeasurement(void) {
CP_Measurement_t snapshot;
__disable_irq();
snapshot = cp_measurement;
__enable_irq();
return snapshot;
}
void HAL_TIM_IC_CaptureCallback(TIM_HandleTypeDef *htim) {
if ((htim->Instance != TIM3) || (htim->Channel != HAL_TIM_ACTIVE_CHANNEL_2)) {
return;
}
uint32_t captured = HAL_TIM_ReadCapturedValue(htim, TIM_CHANNEL_2);
uint32_t arr = __HAL_TIM_GET_AUTORELOAD(htim);
TIM_RESET_CAPTUREPOLARITY(htim, TIM_CHANNEL_2);
if (cp_capture_state == CP_WAIT_RISING_1) {
cp_rise_1 = captured;
cp_capture_state = CP_WAIT_FALLING;
TIM_SET_CAPTUREPOLARITY(htim, TIM_CHANNEL_2, TIM_INPUTCHANNELPOLARITY_FALLING);
return;
}
if (cp_capture_state == CP_WAIT_FALLING) {
cp_fall = captured;
cp_capture_state = CP_WAIT_RISING_2;
TIM_SET_CAPTUREPOLARITY(htim, TIM_CHANNEL_2, TIM_INPUTCHANNELPOLARITY_RISING);
return;
}
cp_rise_2 = captured;
cp_capture_state = CP_WAIT_RISING_1;
TIM_SET_CAPTUREPOLARITY(htim, TIM_CHANNEL_2, TIM_INPUTCHANNELPOLARITY_RISING);
uint32_t period_ticks = CP_TicksDiff(cp_rise_2, cp_rise_1, arr);
uint32_t high_ticks = CP_TicksDiff(cp_fall, cp_rise_1, arr);
uint32_t timer_clk = CP_GetTimerClockHz();
if ((period_ticks == 0U) || (high_ticks > period_ticks) || (timer_clk == 0U)) {
cp_measurement.valid = 0;
return;
}
cp_measurement.frequency_hz = timer_clk / period_ticks;
uint32_t duty_high = (high_ticks * 100U + (period_ticks / 2U)) / period_ticks; /* rounded */
if (duty_high > 100U) {
duty_high = 100U;
}
uint32_t duty = duty_high;
#if CP_INPUT_SIGNAL_INVERTED
duty = 100U - duty_high;
#endif
cp_measurement.duty_percent = (uint8_t)duty;
cp_measurement.valid = 1;
cp_last_update_ms = HAL_GetTick();
}
static uint32_t CP_TicksDiff(uint32_t now, uint32_t prev, uint32_t arr) {
if (now >= prev) {
return now - prev;
}
return (arr - prev + 1U) + now;
}
static uint32_t CP_GetTimerClockHz(void) {
uint32_t timclk = CP_GetTim3InputClockHz();
uint32_t prescaler = htim3.Instance->PSC;
return timclk / (prescaler + 1U);
}
static uint32_t CP_GetTim3InputClockHz(void) {
RCC_ClkInitTypeDef clk_init = {0};
uint32_t flash_latency = 0U;
uint32_t pclk1 = HAL_RCC_GetPCLK1Freq();
HAL_RCC_GetClockConfig(&clk_init, &flash_latency);
if (clk_init.APB1CLKDivider == RCC_HCLK_DIV1) {
return pclk1;
}
return pclk1 * 2U;
}
static void CP_ApplyStateOutputs(void) {
static CP_State_t last_state = (CP_State_t)0xFF;
if (last_state == cp_state) {
return;
}
switch (cp_state) {
case EV_STATE_A_IDLE:
HAL_GPIO_WritePin(CP_RELAY_GPIO_Port, CP_RELAY_Pin, GPIO_PIN_RESET);
HAL_GPIO_WritePin(CP_STATE_C_GPIO_Port, CP_STATE_C_Pin, GPIO_PIN_RESET);
HAL_GPIO_WritePin(CP_STATE_F_GPIO_Port, CP_STATE_F_Pin, GPIO_PIN_RESET);
break;
case EV_STATE_B_CONN_PREP:
HAL_GPIO_WritePin(CP_RELAY_GPIO_Port, CP_RELAY_Pin, GPIO_PIN_SET);
HAL_GPIO_WritePin(CP_STATE_C_GPIO_Port, CP_STATE_C_Pin, GPIO_PIN_RESET);
HAL_GPIO_WritePin(CP_STATE_F_GPIO_Port, CP_STATE_F_Pin, GPIO_PIN_RESET);
break;
case EV_STATE_C_CONN_ACTIVE:
HAL_GPIO_WritePin(CP_RELAY_GPIO_Port, CP_RELAY_Pin, GPIO_PIN_SET);
HAL_GPIO_WritePin(CP_STATE_C_GPIO_Port, CP_STATE_C_Pin, GPIO_PIN_SET);
HAL_GPIO_WritePin(CP_STATE_F_GPIO_Port, CP_STATE_F_Pin, GPIO_PIN_RESET);
break;
case EV_STATE_F_ERROR:
HAL_GPIO_WritePin(CP_RELAY_GPIO_Port, CP_RELAY_Pin, GPIO_PIN_SET);
HAL_GPIO_WritePin(CP_STATE_C_GPIO_Port, CP_STATE_C_Pin, GPIO_PIN_RESET);
HAL_GPIO_WritePin(CP_STATE_F_GPIO_Port, CP_STATE_F_Pin, GPIO_PIN_SET);
break;
case EV_STATE_D_CONN_ACT_VENT:
HAL_GPIO_WritePin(CP_RELAY_GPIO_Port, CP_RELAY_Pin, GPIO_PIN_SET);
HAL_GPIO_WritePin(CP_STATE_C_GPIO_Port, CP_STATE_C_Pin, GPIO_PIN_SET);
HAL_GPIO_WritePin(CP_STATE_F_GPIO_Port, CP_STATE_F_Pin, GPIO_PIN_RESET);
break;
case EV_STATE_E_NO_POWER:
HAL_GPIO_WritePin(CP_RELAY_GPIO_Port, CP_RELAY_Pin, GPIO_PIN_SET);
HAL_GPIO_WritePin(CP_STATE_C_GPIO_Port, CP_STATE_C_Pin, GPIO_PIN_RESET);
HAL_GPIO_WritePin(CP_STATE_F_GPIO_Port, CP_STATE_F_Pin, GPIO_PIN_SET);
break;
case EV_STATE_ACQUIRING:
default:
HAL_GPIO_WritePin(CP_RELAY_GPIO_Port, CP_RELAY_Pin, GPIO_PIN_SET);
HAL_GPIO_WritePin(CP_STATE_F_GPIO_Port, CP_STATE_F_Pin, GPIO_PIN_RESET);
HAL_GPIO_WritePin(CP_STATE_C_GPIO_Port, CP_STATE_C_Pin, GPIO_PIN_RESET);
break;
}
last_state = cp_state;
}
Executable → Regular
+155 -199
View File
@@ -1,226 +1,182 @@
/*
* debug.c
*
* Created on: Apr 16, 2024
* Author: colorbass
*/
#include "main.h"
#include <stdio.h>
#include <string.h>
#include <stdint.h>
#include <stdarg.h>
#include "debug.h"
#include "board.h"
#include "charger_gbt.h"
#include "serial_control.h"
#include "usart.h"
#include <time.h>
#include <connector.h>
#define DEBUG_BUFFER_SIZE 1024
#define DEBUG_BUFFER_MAX_COUNT 128
#define LOG_BUFFER_SIZE 128
uint8_t debug_rx_buffer[256];
uint8_t debug_cmd_received;
uint8_t debug_rx_buffer_size = 0;
typedef struct {
uint8_t buffer[DEBUG_BUFFER_SIZE];
volatile uint16_t write_index;
volatile uint16_t read_index;
volatile uint16_t count;
} DebugBuffer_t;
extern UART_HandleTypeDef huart2;
static DebugBuffer_t debug_buffer = {
.buffer = {0},
.write_index = 0,
.read_index = 0,
.count = 0
};
static uint8_t log_buffer[LOG_BUFFER_SIZE];
static void debug_uart1_write(const uint8_t *data, uint16_t len)
{
/* Best-effort debug mirror to USART1 (PA9/PA10), safe for IRQ context. */
for (uint16_t i = 0; i < len; i++) {
uint32_t timeout = 10000U;
while (((USART1->SR & USART_SR_TXE) == 0U) && (timeout > 0U)) {
timeout--;
}
if (timeout == 0U) {
return;
}
USART1->DR = data[i];
}
}
#if defined(__GNUC__)
int _write(int fd, char * ptr, int len)
{
HAL_GPIO_WritePin(USART2_DIR_GPIO_Port, USART2_DIR_Pin, 1);
HAL_UART_Transmit(&huart2, (uint8_t *) ptr, len, HAL_MAX_DELAY);
HAL_GPIO_WritePin(USART2_DIR_GPIO_Port, USART2_DIR_Pin, 0);
(void)fd;
debug_buffer_add((const uint8_t*)ptr, (uint16_t)len);
return len;
}
#endif
void HAL_UARTEx_RxEventCallback(UART_HandleTypeDef *huart, uint16_t Size){
// if(huart->Instance == USART1){
// mm_rx_interrupt(huart, Size);
// }
if(huart->Instance == USART2){
debug_rx_interrupt(huart, Size);
void debug_buffer_add(const uint8_t* data, uint16_t len)
{
debug_uart1_write(data, len);
__disable_irq();
for (uint16_t i = 0; i < len; i++) {
if (debug_buffer.count >= DEBUG_BUFFER_SIZE) {
debug_buffer.read_index = (debug_buffer.read_index + 1U) % DEBUG_BUFFER_SIZE;
debug_buffer.count--;
}
debug_buffer.buffer[debug_buffer.write_index] = data[i];
debug_buffer.write_index = (debug_buffer.write_index + 1U) % DEBUG_BUFFER_SIZE;
debug_buffer.count++;
}
__enable_irq();
}
void debug_rx_interrupt(UART_HandleTypeDef *huart, uint16_t Size){
debug_rx_buffer[Size] = '\0';
debug_rx_buffer_size = Size;
debug_cmd_received = 1;
uint16_t debug_buffer_available(void)
{
__disable_irq();
uint16_t count = debug_buffer.count;
__enable_irq();
return count;
}
void debug_init(){
HAL_UARTEx_ReceiveToIdle_IT(&huart2,debug_rx_buffer,255);
//mm_schedule_write(0x01, 0x0000, 0x0800);
// mm_schedule_write(0x02, 0x00FF, 0xFFFF);
//for (int i=0;i<60;i++)
// mm_schedule_write(0x02, 0x0000, 0xFF00);
// mm_schedule_write(0x01, 0x0000, 0x0100);
// mm_schedule_write(0x01, 0x0000, 0x0100);
}
void parse_command(uint8_t* buffer, size_t length) {
// ignore \r \n symbols
size_t i = 0;
for (i = 0; i < length; i++) {
if (buffer[i] == '\r' || buffer[i] == '\n') {
buffer[i] = '\0';
length = i;
break;
}
}
if (buffer[0] == 0) return;
if (strncmp((const char*)buffer, "reset", length) == 0) {
printf("Resetting...\n");
NVIC_SystemReset();
} else if (strncmp((const char*)buffer, "relayaux", length) == 0) {
printf("Relaying...\n");
RELAY_Write(RELAY_1, 1);
HAL_Delay(200);
RELAY_Write(RELAY_1, 0);
} else if (strncmp((const char*)buffer, "relaycc", length) == 0) {
printf("Relaying...\n");
RELAY_Write(RELAY_CC, 1);
HAL_Delay(200);
RELAY_Write(RELAY_CC, 0);
// } else if (strncmp((const char*)buffer, "voltage", length) == 0) {
// printf("Voltaging...\n");
// mm_schedule_read(0x02, 0x0001);
} else if (strncmp((const char*)buffer, "adc", length) == 0) {
printf("CC1=%.2f\n", CONN_CC_GetAdc());
// } else if (strncmp((const char*)buffer, "lock_state", length) == 0) {
// printf("AUX/Lock state=%d\n", GBT_LockGetState());
} else if (strncmp((const char*)buffer, "complete", length) == 0) {
CONN_SetState(Finished);
} else if (strncmp((const char*)buffer, "start", length) == 0) {
printf("Started\n");
GBT_SwitchState(GBT_EV_CONNECTING);
} else if (strncmp((const char*)buffer, "stop", length) == 0) {
printf("Stopped\n");
GBT_StopEVSE(GBT_CST_SUSPENDS_ARTIFICIALLY);
} else if (strncmp((const char*)buffer, "stop1", length) == 0) {
printf("Stopped\n");
GBT_ForceStop();
// } else if (strncmp((const char*)buffer, "force", length) == 0) {
// printf("Stopped\n");
// GBT_Lock(1);
// GBT_SwitchState(GBT_S2_LOCKED);
// GBT_Delay(500);
} else if (strncmp((const char*)buffer, "cc_state", length) == 0) {
switch(CONN_CC_GetState()){
case GBT_CC_UNKNOWN:
printf("GBT_CC_UNKNOWN\n");
break;
case GBT_CC_12V:
printf("GBT_CC_12V\n");
break;
case GBT_CC_6V:
printf("GBT_CC_6V\n");
break;
case GBT_CC_4V:
printf("GBT_CC_4V\n");
break;
case GBT_CC_2V:
printf("GBT_CC_2V\n");
break;
}
} else if (strncmp((const char*)buffer, "temp", length) == 0) {
printf("temp1 %d\n",GBT_ReadTemp(0));
printf("temp2 %d\n",GBT_ReadTemp(1));
} else if (strncmp((const char*)buffer, "info1", length) == 0) {
printf("Battery info:\n");
printf("maxCV %dV\n",GBT_BATStat.maxCellVoltage/100); // 0.01v/bit
printf("maxCC %dA\n",GBT_BATStat.maxChargingCurrent/10); // 0.1A/bit
printf("totE %dkWh\n",GBT_BATStat.totalEnergy/10); // 0.1kWh
printf("maxCV %dV\n",GBT_BATStat.maxChargingVoltage/10); // 0.1V/ bit
printf("maxT %dC\n",(int16_t)GBT_BATStat.maxTemp-50); // 1C/bit, -50C offset
printf("SOC %dp\n",GBT_BATStat.SOC/10); // 0.1%/bit , 0..100%
printf("Volt. %dV\n",GBT_BATStat.measVoltage/10); // 0.1V/bit
} else if (strncmp((const char*)buffer, "info2", length) == 0) {
printf("EV info:\n");
printf("GBT_ver V%d.%d%d\n",GBT_EVInfo.version[0],GBT_EVInfo.version[1],GBT_EVInfo.version[2]);
printf("Battery type: %d\n",GBT_EVInfo.batteryType);
printf("Battery capacity: %d\n", GBT_EVInfo.batteryCapacity); // 0.1Ah/bit
printf("Battery voltage: %d\n", GBT_EVInfo.batteryVoltage); // 0.1V/bit
printf("Battery vendor: %.4s\n", GBT_EVInfo.batteryVendor); // Battery vendor (ASCII string)
printf("Battery SN: %lu\n", GBT_EVInfo.batterySN); // int
printf("Battery manufacture date: %02d.%02d.%04d\n", GBT_EVInfo.batteryManuD, GBT_EVInfo.batteryManuM ,GBT_EVInfo.batteryManuY+1985); // year (offset 1985)
printf("Battery cycles: %d\n", GBT_EVInfo.batteryCycleCount); //uint24_t
printf("Own auto: %d\n", GBT_EVInfo.ownAuto); // 0 = lizing, 1 = own auto
printf("EVIN: %.17s\n", GBT_EVInfo.EVIN); //EVIN
printf("EV_SW_VER: %.8s\n", GBT_EVInfo.EV_SW_VER);
} else if (strncmp((const char*)buffer, "info3", length) == 0) {
printf("GBT_MaxLoad info:\n");
printf("Output max current: %d\n",GBT_MaxLoad.maxOutputCurrent);
printf("Output min current: %d\n",GBT_MaxLoad.minOutputCurrent);
printf("Output max voltage: %d\n",GBT_MaxLoad.maxOutputVoltage);
printf("Output min voltage: %d\n",GBT_MaxLoad.minOutputVoltage);
printf("\nGBT_ChargerInfo info:\n");
printf("BMS Recognized: %d\n",GBT_ChargerInfo.bmsIdentified);
printf("Charger location: %.3s\n",GBT_ChargerInfo.chargerLocation);
printf("Charger number: %lu\n",GBT_ChargerInfo.chargerNumber);
} else if (strncmp((const char*)buffer, "help", length) == 0) {
printf("Command list:\n");
printf("reset\n");
printf("help\n");
printf("cc_state\n");
printf("lock_state\n");
printf("adc\n");
printf("relay(cc,aux)\n");
printf("start\n");
printf("stop\n");
printf("stop1\n");
// printf("force\n");
printf("temp\n");
printf("info1\n");
printf("info2\n");
printf("info3\n");
printf("time\n");
printf("cantest\n");
//TODO: info commands
} else if (strncmp((const char*)buffer, "time", length) == 0) {
time_t unix_time = (time_t)get_Current_Time();
struct tm *parts = localtime(&unix_time);
printf("Year: %d\n", parts->tm_year + 1900);
printf("Month: %d\n", parts->tm_mon + 1);
printf("Day: %d\n", parts->tm_mday);
printf("Hour: %d\n", parts->tm_hour);
printf("Minute: %d\n", parts->tm_min);
printf("Second: %d\n", parts->tm_sec);
} else if (strncmp((const char*)buffer, "cantest", length) == 0) {
//GBT_SendCHM();
GBT_Error(0xFDF0C0FC); //BRM Timeout
printf("can test\n");
} else {
printf("Unknown command\n");
}
}
void debug_task(){
if(debug_cmd_received){
parse_command(debug_rx_buffer, debug_rx_buffer_size);
HAL_UARTEx_ReceiveToIdle_IT(&huart2,debug_rx_buffer,255);
debug_cmd_received = 0;
void debug_buffer_send(void)
{
__disable_irq();
if (debug_buffer.count == 0U) {
__enable_irq();
return;
}
uint16_t bytes_to_send = debug_buffer.count;
if (bytes_to_send > DEBUG_BUFFER_MAX_COUNT) {
bytes_to_send = DEBUG_BUFFER_MAX_COUNT;
}
uint16_t bytes_to_end = DEBUG_BUFFER_SIZE - debug_buffer.read_index;
if (bytes_to_send > bytes_to_end) {
bytes_to_send = bytes_to_end;
}
if (bytes_to_send == debug_buffer.count) {
SC_SendPacket(&debug_buffer.buffer[debug_buffer.read_index], bytes_to_send, CMD_GET_LOG);
} else {
SC_SendPacket(&debug_buffer.buffer[debug_buffer.read_index], bytes_to_send, CMD_GET_LOG_CONTINUE);
}
debug_buffer.read_index = (debug_buffer.read_index + bytes_to_send) % DEBUG_BUFFER_SIZE;
debug_buffer.count -= bytes_to_send;
__enable_irq();
}
int log_printf(int level, const char *format, ...)
{
va_list args;
int result;
const char *tag;
int written;
EDCAN_LogLevel_t current_level;
EDCAN_LogLevel_t msg_level;
if(level < LOG_EMERG || level > LOG_DEBUG){
return 0;
}
msg_level = (EDCAN_LogLevel_t)level;
current_level = EDCAN_GetLogLevel();
if(msg_level > current_level){
return 0;
}
switch(level){
case LOG_EMERG:
tag = "[EMR] ";
break;
case LOG_ALERT:
tag = "[ALT] ";
break;
case LOG_CRIT:
tag = "[CRT] ";
break;
case LOG_ERR:
tag = "[ERR] ";
break;
case LOG_WARN:
tag = "[WRN] ";
break;
case LOG_NOTICE:
tag = "[NTC] ";
break;
case LOG_INFO:
tag = "[INF] ";
break;
case LOG_DEBUG:
tag = "[DBG] ";
break;
default:
tag = "[LOG] ";
break;
}
log_buffer[0] = (uint8_t)level;
written = snprintf((char*)&log_buffer[1], LOG_BUFFER_SIZE - 2, "EV %s", tag);
if(written < 0){
return written;
}
if(written >= (LOG_BUFFER_SIZE - 2)){
written = LOG_BUFFER_SIZE - 2;
}
va_start(args, format);
result = vsnprintf((char*)&log_buffer[1 + written], LOG_BUFFER_SIZE - 2 - written, format, args);
va_end(args);
if (result < 0) {
return result;
}
if (result >= (LOG_BUFFER_SIZE - 2 - written)) {
result = LOG_BUFFER_SIZE - 2 - written;
}
log_buffer[1 + written + result] = '\0';
debug_buffer_add(log_buffer, (uint16_t)(2 + written + result));
return result + written;
}
+5
View File
@@ -50,6 +50,11 @@ void GBT_SendBSM(void){
J_SendPacket(0x1300, 6, sizeof(GBT_BatteryStatus), (uint8_t*)&GBT_BatteryStatus);
}
// BST: запрос остановки зарядки со стороны EV
void GBT_SendBST(uint32_t causeCode){
J_SendPacket(0x1900, 6, sizeof(causeCode), (uint8_t*)&causeCode);
}
// BSD: статус батареи при завершении
void GBT_SendBSD(void){
J_SendPacket(0x1C00, 6, sizeof(GBT_BATStat), (uint8_t*)&GBT_BATStat);
+18 -18
View File
@@ -54,14 +54,14 @@ void MX_GPIO_Init(void)
__HAL_RCC_GPIOD_CLK_ENABLE();
/*Configure GPIO pin Output Level */
HAL_GPIO_WritePin(GPIOC, LOCK_A_Pin|LOCK_B_Pin, GPIO_PIN_RESET);
HAL_GPIO_WritePin(GPIOC, CP_STATE_F_Pin|CP_RELAY_Pin|LOCK_A_Pin|LOCK_B_Pin, GPIO_PIN_RESET);
/*Configure GPIO pin Output Level */
HAL_GPIO_WritePin(GPIOE, RELAY5_Pin|RELAY4_Pin|RELAY3_Pin|RELAY2_Pin
|RELAY1_Pin, GPIO_PIN_RESET);
HAL_GPIO_WritePin(GPIOA, CP_STATE_C_Pin|RELAY_CC_Pin, GPIO_PIN_RESET);
/*Configure GPIO pin Output Level */
HAL_GPIO_WritePin(RELAY_CC_GPIO_Port, RELAY_CC_Pin, GPIO_PIN_RESET);
HAL_GPIO_WritePin(GPIOE, RELAY1_Pin|RELAY2_Pin|RELAY3_Pin|RELAY4_Pin
|RELAY5_Pin, GPIO_PIN_RESET);
/*Configure GPIO pin Output Level */
HAL_GPIO_WritePin(GPIOD, RELAY_DC_Pin|USART2_DIR_Pin, GPIO_PIN_RESET);
@@ -69,18 +69,25 @@ void MX_GPIO_Init(void)
/*Configure GPIO pin Output Level */
HAL_GPIO_WritePin(EE_WP_GPIO_Port, EE_WP_Pin, GPIO_PIN_RESET);
/*Configure GPIO pins : CP_STATE_F_Pin CP_RELAY_Pin LOCK_A_Pin LOCK_B_Pin */
GPIO_InitStruct.Pin = CP_STATE_F_Pin|CP_RELAY_Pin|LOCK_A_Pin|LOCK_B_Pin;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);
/*Configure GPIO pins : IN_SW0_Pin IN_SW1_Pin */
GPIO_InitStruct.Pin = IN_SW0_Pin|IN_SW1_Pin;
GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
GPIO_InitStruct.Pull = GPIO_PULLUP;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
/*Configure GPIO pins : LOCK_A_Pin LOCK_B_Pin */
GPIO_InitStruct.Pin = LOCK_A_Pin|LOCK_B_Pin;
/*Configure GPIO pins : CP_STATE_C_Pin RELAY_CC_Pin */
GPIO_InitStruct.Pin = CP_STATE_C_Pin|RELAY_CC_Pin;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
/*Configure GPIO pins : IN0_Pin AC_OK_Pin ISO_IN_Pin */
GPIO_InitStruct.Pin = IN0_Pin|AC_OK_Pin|ISO_IN_Pin;
@@ -88,22 +95,15 @@ void MX_GPIO_Init(void)
GPIO_InitStruct.Pull = GPIO_NOPULL;
HAL_GPIO_Init(GPIOE, &GPIO_InitStruct);
/*Configure GPIO pins : RELAY5_Pin RELAY4_Pin RELAY3_Pin RELAY2_Pin
RELAY1_Pin */
GPIO_InitStruct.Pin = RELAY5_Pin|RELAY4_Pin|RELAY3_Pin|RELAY2_Pin
|RELAY1_Pin;
/*Configure GPIO pins : RELAY1_Pin RELAY2_Pin RELAY3_Pin RELAY4_Pin
RELAY5_Pin */
GPIO_InitStruct.Pin = RELAY1_Pin|RELAY2_Pin|RELAY3_Pin|RELAY4_Pin
|RELAY5_Pin;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
HAL_GPIO_Init(GPIOE, &GPIO_InitStruct);
/*Configure GPIO pin : RELAY_CC_Pin */
GPIO_InitStruct.Pin = RELAY_CC_Pin;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
HAL_GPIO_Init(RELAY_CC_GPIO_Port, &GPIO_InitStruct);
/*Configure GPIO pins : RELAY_DC_Pin USART2_DIR_Pin */
GPIO_InitStruct.Pin = RELAY_DC_Pin|USART2_DIR_Pin;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
+427 -93
View File
@@ -11,107 +11,272 @@
#include "string.h"
#include "can.h"
#include "edcan.h"
#include "debug.h"
#include <string.h>
extern GBT_BCL_t GBT_ReqPower;
extern GBT_BCL_t GBT_CurrPower;
j_receive_t j_rx;
void HAL_CAN_RxFifo0MsgPendingCallback(CAN_HandleTypeDef *hcan)
{
CAN_RxHeaderTypeDef RxHeader;
uint8_t RxData[8] = {0,};
typedef struct{
uint8_t data[256];
uint32_t PGN;
uint16_t size;
uint8_t packets;
uint8_t next_packet;
uint8_t step;
uint8_t state; // 0=idle, 1=wait CTS, 2=wait ACK
uint32_t tick;
}j_transmit_t;
if(HAL_CAN_GetRxMessage(hcan, CAN_RX_FIFO0, &RxHeader, RxData) == HAL_OK)
{
if((RxHeader.ExtId & 0x00FFFF) == ((J_ID_EV << 8) | J_ID_SE)){ // SA, DA match
switch ((RxHeader.ExtId>>8) & 0x00FF00){
static j_transmit_t j_tx;
case 0xEC00: //PGN Connection Management Message
if(RxData[0] == 16){ //Request to Send
/* Set the RTS values */
j_rx.size = RxData[1] | (RxData[2]<<8);
j_rx.packet = 1;
j_rx.packets = RxData[3];
j_rx.step = 2; //TODO
j_rx.step_cts_remain = j_rx.step;
j_rx.PGN = (RxData[7] << 16) | (RxData[6] << 8) | RxData[5];
if(j_rx.size<256) { //TODO: valid check
J_SendCTS(j_rx);
j_rx.state = 1;
}
}
if(RxData[0] == 255){ //Connection Abort
j_rx.state = 0;
}
#define J1939_BUFFER_SIZE 64U
//if(RxData[0] == 32){}//Broadcast Announce Message
/*
* 1CEC56F4 10 31 00 07 07 00 02 00
* 1CECF456 11 02 01 FF FF 00 02 00
* 1CEB56F4 01 01 01 00 03 46 05 40
* 1CEC56F4 FF FF FF FF FF 00 00 00
*/
typedef struct {
j1939_rx_frame_t buffer[J1939_BUFFER_SIZE];
uint16_t head;
uint16_t tail;
uint16_t count;
uint32_t overflow;
} j1939_rx_ring_t;
break;
typedef struct {
j1939_tx_frame_t buffer[J1939_BUFFER_SIZE];
uint16_t head;
uint16_t tail;
uint16_t count;
uint8_t busy;
uint32_t overflow;
} j1939_tx_ring_t;
case 0xEB00: //PGN Data Message
if(j_rx.state != 1) break;
if((RxData[0]>0) && (RxData[0]<35)){ //Array limit check
if(j_rx.packet == RxData[0]){ //step check
memcpy (&j_rx.data[(RxData[0]-1)*7], &RxData[1],7);
j_rx.packet++;
if(j_rx.packet > j_rx.packets){
//End of transmission
J_SendACK(j_rx);
static j1939_rx_ring_t j_rxbuf;
static j1939_tx_ring_t j_txbuf;
static uint32_t j_tx_watchdog_last_log_tick;
j_rx.state = 2;
}else{
if(j_rx.step_cts_remain > 0) j_rx.step_cts_remain--;
if(j_rx.step_cts_remain == 0){
J_SendCTS(j_rx);
j_rx.step_cts_remain = 2;
}
}
}
}
break;
#define J1939_CRITICAL_ENTER() __disable_irq()
#define J1939_CRITICAL_EXIT() __enable_irq()
case 0x1E00: //PGN BEM (ERROR)
//Error force stop
// --> Suspend EV
EDCAN_printf(LOG_WARN, "BEM Received, force stopping...\n");
EDCAN_printf(LOG_WARN, "BEM: %02X %02X %02X %02X", RxData[0], RxData[1], RxData[2], RxData[3]);
EDCAN_printf(LOG_WARN, " %02X %02X %02X %02X\n", RxData[4], RxData[5], RxData[6], RxData[7]);
GBT_ForceStop();
break;
static void J_SendTpRts(void);
static void J_SendTpDtRange(uint8_t start_packet, uint8_t count);
static void J_TxCheckTimeout(void);
static void J_TxReset(void);
static void J1939_ProcessRxFrame(const j1939_rx_frame_t *frame);
static void J1939_RxBufferAdd(const j1939_rx_frame_t *frame);
static uint8_t J1939_RxBufferGet(j1939_rx_frame_t *frame);
static void J1939_TxBufferAdd(const j1939_tx_frame_t *frame);
static uint8_t J1939_TxBufferPeek(j1939_tx_frame_t *frame);
static void J1939_TxBufferDropFirst(void);
static void J1939_TxQueueByPgn(uint32_t PGN, uint8_t pri, uint8_t DLC, const uint8_t *data, uint8_t pad_ff);
case 0x1900: //PGN BST (STOP)
//Normal stop
#define J1939_TP_CTS_WAIT_TIMEOUT_MS 1000U
#define J1939_TP_ACK_WAIT_TIMEOUT_MS 1000U
// --> Suspend EV
EDCAN_printf(LOG_WARN, "BST Received, stopping...\n");
EDCAN_printf(LOG_WARN, "BST: %02X %02X %02X %02X", RxData[0], RxData[1], RxData[2], RxData[3]);
EDCAN_printf(LOG_WARN, " %02X %02X %02X %02X\n", RxData[4], RxData[5], RxData[6], RxData[7]);
GBT_StopEV(GBT_CST_BMS_ACTIVELY_SUSPENDS);
static void J_TxReset(void){
if(j_tx.state != 0){
log_printf(LOG_WARN, "J1939 chunk send failed: TX session reset (state=%u pgn=0x%lX next=%u/%u)\n",
j_tx.state, j_tx.PGN, j_tx.next_packet, j_tx.packets);
}
memset(&j_tx, 0, sizeof(j_tx));
}
break;
void J1939_InitBuffers(void){
memset(&j_rxbuf, 0, sizeof(j_rxbuf));
memset(&j_txbuf, 0, sizeof(j_txbuf));
j_tx_watchdog_last_log_tick = 0U;
J_TxReset();
}
default:
if(j_rx.state == 0){//TODO protections
//Short packet
j_rx.size = RxHeader.DLC;
j_rx.packet = 1;
j_rx.packets = 1;
j_rx.step = 1;
j_rx.step_cts_remain = 0;
j_rx.PGN = (RxHeader.ExtId>>8) & 0x00FF00;
j_rx.state = 2;
memcpy (j_rx.data, RxData, j_rx.size);
}
}
}
}
uint16_t J1939_GetRxBufferCount(void){
uint16_t c;
J1939_CRITICAL_ENTER();
c = j_rxbuf.count;
J1939_CRITICAL_EXIT();
return c;
}
uint16_t J1939_GetTxBufferCount(void){
uint16_t c;
J1939_CRITICAL_ENTER();
c = j_txbuf.count;
J1939_CRITICAL_EXIT();
return c;
}
uint32_t J1939_GetRxOverflowCount(void){
return j_rxbuf.overflow;
}
uint32_t J1939_GetTxOverflowCount(void){
return j_txbuf.overflow;
}
void HAL_CAN_RxFifo0MsgPendingCallback(CAN_HandleTypeDef *hcan){
j1939_rx_frame_t frame;
CAN_RxHeaderTypeDef rx_header;
uint8_t rx_data[8] = {0};
if(HAL_CAN_GetRxMessage(hcan, CAN_RX_FIFO0, &rx_header, rx_data) != HAL_OK) return;
frame.ExtId = rx_header.ExtId;
frame.DLC = rx_header.DLC;
frame.tick = HAL_GetTick();
memcpy(frame.data, rx_data, sizeof(frame.data));
J1939_RxBufferAdd(&frame);
}
static void J1939_ProcessRxFrame(const j1939_rx_frame_t *frame){
uint32_t pgn;
if((frame->ExtId & 0x00FFFF) != ((J_ID_EV << 8) | J_ID_SE)) return; // SA, DA match
switch ((frame->ExtId >> 8) & 0x00FF00){
case 0xEC00:
if(frame->data[0] == 16){ // RTS
j_rx.size = frame->data[1] | (frame->data[2] << 8);
j_rx.packet = 1;
j_rx.packets = frame->data[3];
j_rx.step = 2;
j_rx.step_cts_remain = j_rx.step;
j_rx.PGN = (frame->data[7] << 16) | (frame->data[6] << 8) | frame->data[5];
if(j_rx.size < 256){
J_SendCTS(j_rx);
j_rx.state = 1;
}
}
if(frame->data[0] == 17){ // CTS
pgn = (frame->data[7] << 16) | (frame->data[6] << 8) | frame->data[5];
if((j_tx.state == 1) && (pgn == j_tx.PGN)){
uint8_t req_count = frame->data[1];
uint8_t req_start_packet = frame->data[2];
log_printf(LOG_DEBUG, "J1939 event: TP CTS received (pgn=0x%lX cnt=%u start=%u exp=%u)\n",
pgn, req_count, req_start_packet, j_tx.next_packet);
if(req_count == 0){
log_printf(LOG_DEBUG, "J1939 event: TP CTS wait (pgn=0x%lX)\n", j_tx.PGN);
}else{
j_tx.tick = frame->tick;
J_SendTpDtRange(req_start_packet, req_count);
}
}else{
log_printf(LOG_WARN, "J1939 chunk send failed: CTS ignored (tx_state=%u tx_pgn=0x%lX rx_pgn=0x%lX)\n",
j_tx.state, j_tx.PGN, pgn);
}
}
if(frame->data[0] == 19){ // ACK
pgn = (frame->data[7] << 16) | (frame->data[6] << 8) | frame->data[5];
if((j_tx.state == 2) && (pgn == j_tx.PGN)){
log_printf(LOG_DEBUG, "J1939 event: TP ACK received, TX complete (pgn=0x%lX)\n", pgn);
j_tx.state = 0;
}
}
if(frame->data[0] == 255){
j_rx.state = 0;
J_TxReset();
}
break;
case 0xEB00:
if(j_rx.state != 1) return;
if((frame->data[0] > 0) && (frame->data[0] < 35) && (j_rx.packet == frame->data[0])){
memcpy(&j_rx.data[(frame->data[0]-1)*7], &frame->data[1], 7);
j_rx.packet++;
if(j_rx.packet > j_rx.packets){
J_SendACK(j_rx);
j_rx.state = 2;
}else{
if(j_rx.step_cts_remain > 0) j_rx.step_cts_remain--;
if(j_rx.step_cts_remain == 0){
J_SendCTS(j_rx);
j_rx.step_cts_remain = 2;
}
}
}
break;
case 0x1E00:
log_printf(LOG_WARN, "J1939 fault received: BEM, forcing stop (data=%02X %02X %02X %02X %02X %02X %02X %02X)\n",
frame->data[0], frame->data[1], frame->data[2], frame->data[3],
frame->data[4], frame->data[5], frame->data[6], frame->data[7]);
GBT_ForceStop();
break;
case 0x1900:
/* Repeated BST frames during STOP flow are normal on the bus.
* Handle/log only once to avoid flooding UART logs.
*/
if((GBT_State != GBT_STOP) && (GBT_State != GBT_STOP_CSD) && (GBT_State != GBT_COMPLETE)){
log_printf(LOG_DEBUG, "J1939 event: BST received, initiating stop flow (data=%02X %02X %02X %02X %02X %02X %02X %02X)\n",
frame->data[0], frame->data[1], frame->data[2], frame->data[3],
frame->data[4], frame->data[5], frame->data[6], frame->data[7]);
GBT_StopEV(GBT_CST_BMS_ACTIVELY_SUSPENDS);
}
break;
default:
if(j_rx.state == 0){
j_rx.size = frame->DLC;
j_rx.packet = 1;
j_rx.packets = 1;
j_rx.step = 1;
j_rx.step_cts_remain = 0;
j_rx.PGN = (frame->ExtId >> 8) & 0x00FF00;
j_rx.state = 2;
memcpy(j_rx.data, frame->data, j_rx.size);
}
break;
}
}
void J1939_ExchangeRxBuffer(void){
j1939_rx_frame_t frame;
J_TxCheckTimeout();
if(J1939_RxBufferGet(&frame)){
J1939_ProcessRxFrame(&frame);
}
}
void J1939_ExchangeTxBuffer(void){
j1939_tx_frame_t frame;
CAN_TxHeaderTypeDef tx_header;
uint32_t tx_mailbox;
HAL_StatusTypeDef tx_status;
if(HAL_CAN_GetTxMailboxesFreeLevel(&hcan1) == 0) return;
/* Atomically reserve first queued frame without holding IRQ over HAL call */
J1939_CRITICAL_ENTER();
if(j_txbuf.busy || (j_txbuf.count == 0U)){
J1939_CRITICAL_EXIT();
return;
}
j_txbuf.busy = 1U;
frame = j_txbuf.buffer[j_txbuf.tail];
J1939_CRITICAL_EXIT();
tx_header.ExtId = frame.ExtId;
tx_header.RTR = CAN_RTR_DATA;
tx_header.IDE = CAN_ID_EXT;
tx_header.DLC = frame.DLC;
tx_status = HAL_CAN_AddTxMessage(&hcan1, &tx_header, frame.data, &tx_mailbox);
J1939_CRITICAL_ENTER();
if((tx_status == HAL_OK) && (j_txbuf.count > 0U)){
j_txbuf.tail = (j_txbuf.tail + 1U) % J1939_BUFFER_SIZE;
j_txbuf.count--;
}
j_txbuf.busy = 0U;
J1939_CRITICAL_EXIT();
if(tx_status != HAL_OK){
log_printf(LOG_WARN, "J1939 send failed: CAN TX error (st=%d extid=0x%lX dlc=%u free_mb=%lu err=0x%lX)\n",
(int)tx_status, frame.ExtId, frame.DLC, HAL_CAN_GetTxMailboxesFreeLevel(&hcan1), HAL_CAN_GetError(&hcan1));
if((tx_status == HAL_ERROR) && (HAL_CAN_GetError(&hcan1) & HAL_CAN_ERROR_NOT_INITIALIZED)){
log_printf(LOG_WARN, "J1939 send failed: CAN not initialized, reinitializing\n");
GBT_CAN_ReInit();
}
}
}
void GBT_CAN_ReInit(){
@@ -120,24 +285,119 @@ void GBT_CAN_ReInit(){
HAL_CAN_Start(&hcan1);
HAL_CAN_ActivateNotification(&hcan1, CAN_IT_RX_FIFO0_MSG_PENDING);
GBT_CAN_FilterInit();
J1939_InitBuffers();
}
void J_SendPacket(uint32_t PGN, uint8_t pri, uint8_t DLC, uint8_t *data){
J_TxCheckTimeout();
CAN_TxHeaderTypeDef tx_header;
uint32_t tx_mailbox;
if(DLC > 8){
/* Transport protocol for multi-packet payloads */
if(DLC > sizeof(j_tx.data)) return;
if(j_tx.state != 0){
log_printf(LOG_WARN, "J1939 chunk send failed: TX busy (state=%u req_pgn=0x%lX cur_pgn=0x%lX)\n",
j_tx.state, PGN, j_tx.PGN);
return;
}
tx_header.ExtId = (pri << 26) | (PGN << 8) | (J_ID_SE << 8) | J_ID_EV;
tx_header.RTR = CAN_RTR_DATA;
tx_header.IDE = CAN_ID_EXT;
tx_header.DLC = DLC;
memset(&j_tx, 0, sizeof(j_tx));
memcpy(j_tx.data, data, DLC);
j_tx.PGN = PGN;
j_tx.size = DLC;
j_tx.packets = (DLC + 6) / 7;
j_tx.next_packet = 1;
j_tx.step = 2;
j_tx.state = 1;
j_tx.tick = HAL_GetTick();
log_printf(LOG_DEBUG, "J1939 event: TP RTS sent (pgn=0x%lX size=%u packets=%u)\n",
j_tx.PGN, j_tx.size, j_tx.packets);
//TODO buffer wait
HAL_CAN_AddTxMessage(&hcan1, &tx_header, data, &tx_mailbox);
//HAL_Delay(2);
J_SendTpRts();
return;
}
J1939_TxQueueByPgn(PGN, pri, DLC, data, 1);
}
static void J_TxCheckTimeout(void){
if(j_tx.state != 0){
uint32_t now = HAL_GetTick();
if((now - j_tx_watchdog_last_log_tick) >= 500U){
log_printf(LOG_DEBUG, "J1939 event: TP TX watchdog (state=%u pgn=0x%lX next=%u/%u age=%lu)\n",
j_tx.state, j_tx.PGN, j_tx.next_packet, j_tx.packets, (now - j_tx.tick));
j_tx_watchdog_last_log_tick = now;
}
}else{
j_tx_watchdog_last_log_tick = HAL_GetTick();
}
if((j_tx.state == 1) && ((HAL_GetTick() - j_tx.tick) > J1939_TP_CTS_WAIT_TIMEOUT_MS)){
log_printf(LOG_WARN, "J1939 chunk send failed: CTS timeout (pgn=0x%lX), resetting TX session\n", j_tx.PGN);
J_TxReset();
}else if((j_tx.state == 2) && ((HAL_GetTick() - j_tx.tick) > J1939_TP_ACK_WAIT_TIMEOUT_MS)){
log_printf(LOG_WARN, "J1939 chunk send failed: ACK timeout (pgn=0x%lX), resetting TX session\n", j_tx.PGN);
J_TxReset();
}
}
static void J_SendTpRts(void){
uint8_t data[8];
data[0] = 16; // CONTROL_BYTE_TP_CM_RTS
data[1] = j_tx.size & 0xFF;
data[2] = j_tx.size >> 8;
data[3] = j_tx.packets;
data[4] = j_tx.step; // max packets before next CTS
data[5] = j_tx.PGN;
data[6] = j_tx.PGN >> 8;
data[7] = j_tx.PGN >> 16;
J1939_TxQueueByPgn(0x00EC00, 7, 8, data, 0);
}
static void J_SendTpDtRange(uint8_t start_packet, uint8_t count){
uint8_t dt[8];
uint8_t packet;
uint8_t i;
uint16_t idx;
if(j_tx.state != 1){
log_printf(LOG_WARN, "J1939 chunk send failed: TP DT ignored (invalid TX state=%u)\n", j_tx.state);
return;
}
if((start_packet == 0) || (start_packet > j_tx.packets)) return;
if(count == 0) return;
if(start_packet != j_tx.next_packet){
log_printf(LOG_WARN, "J1939 chunk send failed: TP desync (start=%u expected=%u), resetting TX session\n", start_packet, j_tx.next_packet);
J_TxReset();
return;
}
if((start_packet + count - 1) > j_tx.packets){
count = j_tx.packets - start_packet + 1;
}
for(packet = 0; packet < count; packet++){
uint8_t seq = start_packet + packet;
dt[0] = seq;
idx = (uint16_t)(seq - 1) * 7;
for(i = 0; i < 7; i++){
if((idx + i) < j_tx.size) dt[i + 1] = j_tx.data[idx + i];
else dt[i + 1] = 0xFF;
}
J1939_TxQueueByPgn(0x00EB00, 7, 8, dt, 0);
}
log_printf(LOG_DEBUG, "J1939 event: TP DT sent (pgn=0x%lX start=%u cnt=%u)\n", j_tx.PGN, start_packet, count);
j_tx.next_packet = start_packet + count;
j_tx.tick = HAL_GetTick();
if(j_tx.next_packet > j_tx.packets){
j_tx.state = 2; // wait ACK
}else{
j_tx.state = 1; // wait next CTS
}
}
//void J_SendPacketLong(){
// //TODO (no need)
//}
@@ -195,3 +455,77 @@ void GBT_CAN_FilterInit(){
}
}
static void J1939_RxBufferAdd(const j1939_rx_frame_t *frame){
J1939_CRITICAL_ENTER();
j_rxbuf.buffer[j_rxbuf.head] = *frame;
j_rxbuf.head = (j_rxbuf.head + 1U) % J1939_BUFFER_SIZE;
if(j_rxbuf.count == J1939_BUFFER_SIZE){
j_rxbuf.tail = (j_rxbuf.tail + 1U) % J1939_BUFFER_SIZE;
j_rxbuf.overflow++;
log_printf(LOG_WARN, "J1939 RX buffer overflow: dropped oldest frame, overflow_count=%lu\n", j_rxbuf.overflow);
}else{
j_rxbuf.count++;
}
J1939_CRITICAL_EXIT();
}
static uint8_t J1939_RxBufferGet(j1939_rx_frame_t *frame){
uint8_t ok = 0;
J1939_CRITICAL_ENTER();
if(j_rxbuf.count > 0){
*frame = j_rxbuf.buffer[j_rxbuf.tail];
j_rxbuf.tail = (j_rxbuf.tail + 1U) % J1939_BUFFER_SIZE;
j_rxbuf.count--;
ok = 1;
}
J1939_CRITICAL_EXIT();
return ok;
}
static void J1939_TxBufferAdd(const j1939_tx_frame_t *frame){
J1939_CRITICAL_ENTER();
j_txbuf.buffer[j_txbuf.head] = *frame;
j_txbuf.head = (j_txbuf.head + 1U) % J1939_BUFFER_SIZE;
if(j_txbuf.count == J1939_BUFFER_SIZE){
j_txbuf.tail = (j_txbuf.tail + 1U) % J1939_BUFFER_SIZE;
j_txbuf.overflow++;
log_printf(LOG_WARN, "J1939 TX buffer overflow: dropped oldest frame, overflow_count=%lu\n", j_txbuf.overflow);
}else{
j_txbuf.count++;
}
J1939_CRITICAL_EXIT();
}
static uint8_t J1939_TxBufferPeek(j1939_tx_frame_t *frame){
uint8_t ok = 0;
J1939_CRITICAL_ENTER();
if(j_txbuf.count > 0){
*frame = j_txbuf.buffer[j_txbuf.tail];
ok = 1;
}
J1939_CRITICAL_EXIT();
return ok;
}
static void J1939_TxBufferDropFirst(void){
J1939_CRITICAL_ENTER();
if(j_txbuf.count > 0){
j_txbuf.tail = (j_txbuf.tail + 1U) % J1939_BUFFER_SIZE;
j_txbuf.count--;
}
J1939_CRITICAL_EXIT();
}
static void J1939_TxQueueByPgn(uint32_t PGN, uint8_t pri, uint8_t DLC, const uint8_t *data, uint8_t pad_ff){
j1939_tx_frame_t frame;
uint8_t i;
frame.ExtId = (pri << 26) | (PGN << 8) | (J_ID_SE << 8) | J_ID_EV;
frame.DLC = DLC;
for(i = 0; i < 8; i++){
if(i < DLC) frame.data[i] = data[i];
else frame.data[i] = pad_ff ? 0xFF : 0x00;
}
J1939_TxBufferAdd(&frame);
}
+45
View File
@@ -0,0 +1,45 @@
#include "load.h"
#include "board.h"
#include "debug.h"
#include "connector.h"
#define COOLDOWN_TIME 60000
void LOAD_Init(){
RELAY_Write(RELAY_1, 0);
RELAY_Write(RELAY_2, 0);
RELAY_Write(RELAY_3, 0);
RELAY_Write(RELAY_4, 0);
RELAY_Write(RELAY_5, 0);
}
void LOAD_Task(){
static uint32_t load_tick = 0;
if(CONN[0].enableLoad || CONN[1].enableLoad){
load_tick = HAL_GetTick();
}
if((HAL_GetTick() - load_tick < COOLDOWN_TIME) && (load_tick!=0)){
RELAY_Write(RELAY_1, 1);
}else{
RELAY_Write(RELAY_1, 0);
}
if(CONN[0].enableLoad){
RELAY_Write(RELAY_2, 1);
}else{
RELAY_Write(RELAY_2, 0);
}
if(CONN[1].enableLoad){
RELAY_Write(RELAY_3, 1);
}else{
RELAY_Write(RELAY_3, 0);
}
// if(CONN[0].enableLoad && CONN[1].enableLoad){ // объединение нагрузок
// RELAY_Write(RELAY_4, 0);
// }else{
// RELAY_Write(RELAY_4, 1);
// }
}
+20 -9
View File
@@ -30,13 +30,15 @@
#include "can.h"
#include "board.h"
#include <stdio.h>
#include "debug.h"
#include "charger_gbt.h"
#include "soft_rtc.h"
#include "j1939.h"
#include "connector.h"
#include "rgb_controller.h"
#include "serial_control.h"
#include "cp.h"
#include "debug.h"
#include "load.h"
/* USER CODE END Includes */
/* Private typedef -----------------------------------------------------------*/
@@ -60,6 +62,7 @@
/* Private variables ---------------------------------------------------------*/
/* USER CODE BEGIN PV */
volatile CP_State_t cp_state = EV_STATE_B_CONN_PREP;
/* USER CODE END PV */
@@ -116,23 +119,26 @@ int main(void)
MX_UART5_Init();
MX_USART1_UART_Init();
MX_USART3_UART_Init();
MX_TIM3_Init();
/* USER CODE BEGIN 2 */
CAN_ReInit();
Init_Peripheral();
LED_Init();
LOAD_Init();
HAL_Delay(300);
GBT_Init();
set_Time(1721651966);
printf("Startup (type \'help\' for command list)\n");
debug_init();
EDCAN_Init(0x00);
EDCAN_printf(LOG_INFO, "Startup FW %d.%d.%d\n", FWVER_MAJOR, FWVER_MINOR, FWVER_PATCH);
// printf("Startup serial control enabled\n");
EDCAN_Init(InfoBlock->addrEdcan);
log_printf(LOG_INFO, "Startup FW %d.%d.%d\n", FWVER_MAJOR, FWVER_MINOR, FWVER_PATCH);
//EDCAN_Init(0x20); //Адрес EDCAN
GBT_CAN_ReInit();
CAN_ReInit();
CONN_Init();
SC_Init();
CP_Init();
/* USER CODE END 2 */
/* Infinite loop */
@@ -142,10 +148,15 @@ int main(void)
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
// HAL_Delay(1);
CONN[1].MeasuredVoltage = ISO.voltageComm;
LOAD_Task();
EDCAN_Loop();
//can_task();
debug_task();
J1939_ExchangeRxBuffer();
J1939_ExchangeTxBuffer();
SC_Task();
CP_Task();
CONN_CC_ReadStateFiltered();
// GBT_ManageLock();
CONN_Task();
+2 -2
View File
@@ -90,11 +90,11 @@ RGB_Cycle_t color_error = {
};
void LED_Write(){
if(CONN.chargingError != CONN_NO_ERROR){
if(CONN[0].chargingError != CONN_NO_ERROR){
LED_SetColor(&color_error);
return;
}
switch(CONN.connState){
switch(CONN[0].connState){
case Unknown:
LED_SetColor(&color_unknown);
break;
+191
View File
@@ -0,0 +1,191 @@
#include "serial_control.h"
#include "usart.h"
#include "charger_gbt.h"
#include "edcan_config.h"
#include "string.h"
static uint32_t calculate_crc32(const uint8_t *data, uint16_t length);
static uint16_t encode_packet(const uint8_t *payload, uint16_t payload_len, uint8_t *output, uint8_t response_code);
static uint8_t parse_packet(const uint8_t *packet_data, uint16_t packet_len, ReceivedCommand_t *out_cmd);
static uint8_t process_received_packet(SerialControl_t *ctx, const uint8_t *packet_data, uint16_t packet_len);
static void SC_ArmUart2Rx(void);
SerialControl_t serial_control;
static SerialControl_t serial_iso;
volatile SC_Source_t g_sc_command_source = SC_SOURCE_UART2;
GBT_MonitorPacket_t gbtMonitorPacket = {
.connector_type = 0x01,
};
CCS_MonitorPacket_t ccsMonitorPacket = {
.connector_type = 0x02,
};
InfoPacket_t infoPacket = {
.serialNumber = 0,
.boardVersion = 0,
.stationType = 0,
.fw_version_major = 0,
.fw_version_minor = 0,
.fw_version_patch = 0,
};
void SC_Init(void) {
memset(&serial_control, 0, sizeof(serial_control));
memset(&serial_iso, 0, sizeof(serial_iso));
}
void SC_Task(void) {
SC_ArmUart2Rx();
if ((&huart5)->RxState == HAL_UART_STATE_READY) {
(void)HAL_UARTEx_ReceiveToIdle_IT(&huart5, serial_iso.rx_buffer, MAX_RX_BUFFER_SIZE - 1);
}
if (huart2.gState == HAL_UART_STATE_BUSY_TX && serial_control.tx_tick != 0U) {
if ((HAL_GetTick() - serial_control.tx_tick) > 100U) {
HAL_UART_Abort_IT(&huart2);
HAL_GPIO_WritePin(USART2_DIR_GPIO_Port, USART2_DIR_Pin, GPIO_PIN_RESET);
serial_control.tx_tick = 0U;
}
}
if (serial_control.command_ready && (huart2.gState != HAL_UART_STATE_BUSY_TX)) {
SC_CommandHandler((ReceivedCommand_t *)&serial_control.received_command);
serial_control.command_ready = 0U;
SC_ArmUart2Rx();
}
if (serial_control.response_pending && (huart2.gState != HAL_UART_STATE_BUSY_TX)) {
SC_SendPacket(NULL, 0, serial_control.response_code);
serial_control.response_pending = 0U;
}
}
void HAL_UARTEx_RxEventCallback(UART_HandleTypeDef *huart, uint16_t Size) {
if (huart->Instance == huart2.Instance) {
if (!process_received_packet(&serial_control, serial_control.rx_buffer, Size)) {
serial_control.response_pending = 1U;
serial_control.response_code = RESP_INVALID;
SC_ArmUart2Rx();
} else {
g_sc_command_source = SC_SOURCE_UART2;
}
} else if (huart->Instance == huart5.Instance) {
if (process_received_packet(&serial_iso, serial_iso.rx_buffer, Size)) {
g_sc_command_source = SC_SOURCE_UART5;
SC_CommandHandler((ReceivedCommand_t *)&serial_iso.received_command);
}
(void)HAL_UARTEx_ReceiveToIdle_IT(&huart5, serial_iso.rx_buffer, MAX_RX_BUFFER_SIZE - 1);
}
}
void HAL_UART_ErrorCallback(UART_HandleTypeDef *huart) {
if (huart->Instance == huart2.Instance) {
SC_ArmUart2Rx();
}
}
void HAL_UART_TxCpltCallback(UART_HandleTypeDef *huart) {
if (huart->Instance == huart2.Instance) {
HAL_GPIO_WritePin(USART2_DIR_GPIO_Port, USART2_DIR_Pin, GPIO_PIN_RESET);
serial_control.tx_tick = 0U;
}
}
static void SC_ArmUart2Rx(void) {
if ((&huart2)->RxState == HAL_UART_STATE_READY && serial_control.command_ready == 0U) {
(void)HAL_UARTEx_ReceiveToIdle_IT(&huart2, serial_control.rx_buffer, MAX_RX_BUFFER_SIZE - 1);
}
}
static uint32_t calculate_crc32(const uint8_t *data, uint16_t length) {
uint32_t crc = 0xFFFFFFFFu;
for (uint16_t i = 0; i < length; i++) {
crc ^= data[i];
for (uint8_t bit = 0; bit < 8; bit++) {
if (crc & 0x1u) {
crc = (crc >> 1) ^ CRC32_POLYNOMIAL;
} else {
crc >>= 1;
}
}
}
return crc ^ 0xFFFFFFFFu;
}
static uint16_t encode_packet(const uint8_t *payload, uint16_t payload_len, uint8_t *output, uint8_t response_code) {
uint16_t out_index = 0;
output[out_index++] = response_code;
if (payload != NULL) {
for (uint16_t i = 0; i < payload_len; i++) {
output[out_index++] = payload[i];
if (out_index >= MAX_TX_BUFFER_SIZE - 5) {
return 0;
}
}
}
uint32_t crc = calculate_crc32(output, out_index);
uint8_t *crc_bytes = (uint8_t *)&crc;
for (uint8_t i = 0; i < 4; i++) {
output[out_index++] = crc_bytes[i];
if (out_index >= MAX_TX_BUFFER_SIZE - 1) {
return 0;
}
}
return out_index;
}
void SC_SendPacket(const uint8_t *payload, uint16_t payload_len, uint8_t response_code) {
uint16_t packet_len = encode_packet(payload, payload_len, serial_control.tx_buffer, response_code);
if (packet_len > 0U) {
if (huart2.gState == HAL_UART_STATE_BUSY_TX) {
HAL_UART_Abort_IT(&huart2);
HAL_GPIO_WritePin(USART2_DIR_GPIO_Port, USART2_DIR_Pin, GPIO_PIN_RESET);
}
HAL_GPIO_WritePin(USART2_DIR_GPIO_Port, USART2_DIR_Pin, GPIO_PIN_SET);
HAL_UART_Transmit_IT(&huart2, serial_control.tx_buffer, packet_len);
serial_control.tx_tick = HAL_GetTick();
}
}
static uint8_t parse_packet(const uint8_t *packet_data, uint16_t packet_len, ReceivedCommand_t *out_cmd) {
if (packet_len < 5U || packet_len > MAX_RX_BUFFER_SIZE) {
return 0U;
}
uint16_t payload_length = packet_len - 4U;
uint32_t received_checksum =
((uint32_t)packet_data[payload_length] << 0) |
((uint32_t)packet_data[payload_length + 1U] << 8) |
((uint32_t)packet_data[payload_length + 2U] << 16) |
((uint32_t)packet_data[payload_length + 3U] << 24);
uint32_t calculated_checksum = calculate_crc32(packet_data, payload_length);
if (received_checksum != calculated_checksum) {
return 0U;
}
out_cmd->command = packet_data[0];
out_cmd->argument = (void *)&packet_data[1];
out_cmd->argument_length = (uint8_t)(payload_length - 1U);
return 1U;
}
static uint8_t process_received_packet(SerialControl_t *ctx, const uint8_t *packet_data, uint16_t packet_len) {
if (!parse_packet(packet_data, packet_len, (ReceivedCommand_t *)&ctx->received_command)) {
return 0U;
}
ctx->command_ready = 1U;
return 1U;
}
+159
View File
@@ -0,0 +1,159 @@
#include "serial_control.h"
#include "charger_gbt.h"
#include "cp.h"
#include "edcan_config.h"
#include <string.h>
#include "board.h"
#include "debug.h"
static void SC_FillGBTMonitorPacket(void);
static void SC_FillCCSMonitorPacket(void);
static void SC_FillInfoPacket(void);
IsolationStatusPacket_t ISO = {
.isolationResistance = 0xFFFF
};
void SC_CommandHandler(ReceivedCommand_t *cmd) {
uint8_t response_code = RESP_FAILED;
if (cmd->command == CMD_ISOLATION_STATUS) {
if (cmd->argument_length == sizeof(IsolationStatusPacket_t)) {
memcpy(&ISO, cmd->argument, sizeof(IsolationStatusPacket_t));
if (g_sc_command_source == SC_SOURCE_UART5) {
return;
}
response_code = RESP_SUCCESS;
} else {
response_code = RESP_FAILED;
}
SC_SendPacket(NULL, 0, response_code);
return;
}
switch (cmd->command) {
case CMD_GET_GBT_STATUS:
SC_FillGBTMonitorPacket();
SC_SendPacket((const uint8_t *)&gbtMonitorPacket, sizeof(gbtMonitorPacket), CMD_GET_GBT_STATUS);
return;
case CMD_GET_CCS_STATUS:
SC_FillCCSMonitorPacket();
SC_SendPacket((const uint8_t *)&ccsMonitorPacket, sizeof(ccsMonitorPacket), CMD_GET_CCS_STATUS);
return;
case CMD_GET_INFO:
SC_FillInfoPacket();
SC_SendPacket((const uint8_t *)&infoPacket, sizeof(infoPacket), CMD_GET_INFO);
return;
case CMD_GET_LOG:
debug_buffer_send();
return;
case CMD_GBT_CC_ENABLE:
if (cmd->argument_length == sizeof(uint8_t)) {
uint8_t enable = *((uint8_t *)cmd->argument);
cc_enable = enable ? 1U : 0U;
response_code = RESP_SUCCESS;
}
break;
case CMD_GBT_STOP:
if (cmd->argument_length == 0U) {
CONN[0].connControl = CMD_STOP;
response_code = RESP_SUCCESS;
}
break;
case CMD_GBT_SET_REQUEST:
if (cmd->argument_length == sizeof(EvSetLimits_t)) {
EvSetLimits_t *limits = (EvSetLimits_t *)cmd->argument;
CONN[0].RequestedVoltage = limits->requestedVoltage;
CONN[0].RequestedCurrent = limits->requestedCurrent;
response_code = RESP_SUCCESS;
}
break;
case CMD_GBT_SET_SOC:
if (cmd->argument_length == sizeof(uint8_t)) {
CONN[0].SOC = *((uint8_t *)cmd->argument);
response_code = RESP_SUCCESS;
}
break;
case CMD_GBT_SET_VIN:
if (cmd->argument_length == 17U) {
memcpy(GBT_EVInfo.EVIN, cmd->argument, 17U);
response_code = RESP_SUCCESS;
}
break;
case CMD_CCS_SET_STATE:
if (cmd->argument_length == sizeof(uint8_t)) {
cp_state = (CP_State_t)(*((uint8_t *)cmd->argument));
response_code = RESP_SUCCESS;
}
break;
case CMD_CCS_ENABLE_LOAD:
if (cmd->argument_length == sizeof(uint8_t)) {
uint8_t enable = *((uint8_t *)cmd->argument);
CONN[1].enableLoad = enable ? 1U : 0U;
CONN[1].ContactorEnabled = CONN[1].enableLoad;
response_code = RESP_SUCCESS;
}
break;
default:
response_code = RESP_FAILED;
break;
}
SC_SendPacket(NULL, 0, response_code);
}
static void SC_FillInfoPacket(void) {
infoPacket.serialNumber = 0;
infoPacket.boardVersion = 0;
infoPacket.stationType = 0;
infoPacket.fw_version_major = FWVER_MAJOR;
infoPacket.fw_version_minor = FWVER_MINOR;
infoPacket.fw_version_patch = FWVER_PATCH;
}
static void SC_FillGBTMonitorPacket(void) {
gbtMonitorPacket.connector_type = 0x01;
gbtMonitorPacket.requestedVoltage = CONN[0].RequestedVoltage;
gbtMonitorPacket.requestedCurrent = CONN[0].RequestedCurrent;
gbtMonitorPacket.measuredVoltageSE = CONN[0].MeasuredVoltageSE;
gbtMonitorPacket.measuredCurrentSE = CONN[0].MeasuredCurrentSE;
gbtMonitorPacket.measuredVoltage = CONN[0].MeasuredVoltage;
gbtMonitorPacket.measuredCurrent = CONN[0].MeasuredCurrent;
gbtMonitorPacket.cc_enabled = cc_enable;
gbtMonitorPacket.contactorEnabled = CONN[0].ContactorEnabled;
gbtMonitorPacket.chargingError = CONN[0].chargingError;
gbtMonitorPacket.EvseConnected = CONN[0].EvseConnected;
gbtMonitorPacket.soc = CONN[0].SOC;
memcpy(gbtMonitorPacket.vin, GBT_EVInfo.EVIN, sizeof(gbtMonitorPacket.vin));
gbtMonitorPacket.cc_state = CONN_CC_GetState();
gbtMonitorPacket.logs_available = (debug_buffer_available() > 0U) ? 1U : 0U;
gbtMonitorPacket.connState = CONN[0].connState;
}
static void SC_FillCCSMonitorPacket(void) {
CP_Measurement_t cp_meas = CP_GetMeasurement();
ccsMonitorPacket.connector_type = 0x02;
ccsMonitorPacket.measuredVoltage = CONN[1].MeasuredVoltage;
ccsMonitorPacket.measuredCurrent = CONN[1].MeasuredCurrent;
ccsMonitorPacket.cp_enabled = (cp_state != EV_STATE_A_IDLE) ? 1U : 0U;
ccsMonitorPacket.contactorEnabled = CONN[1].ContactorEnabled;
ccsMonitorPacket.chargingError = CONN[1].chargingError;
ccsMonitorPacket.EvseConnected = CONN[1].EvseConnected;
ccsMonitorPacket.soc = CONN[1].SOC;
ccsMonitorPacket.cp_state = (uint8_t)cp_state;
ccsMonitorPacket.cp_pwm_duty = cp_meas.valid ? cp_meas.duty_percent : 0U;
}
Executable → Regular
+30
View File
@@ -57,6 +57,8 @@
/* External variables --------------------------------------------------------*/
extern CAN_HandleTypeDef hcan1;
extern CAN_HandleTypeDef hcan2;
extern TIM_HandleTypeDef htim3;
extern UART_HandleTypeDef huart5;
extern UART_HandleTypeDef huart2;
/* USER CODE BEGIN EV */
@@ -214,6 +216,20 @@ void CAN1_RX0_IRQHandler(void)
/* USER CODE END CAN1_RX0_IRQn 1 */
}
/**
* @brief This function handles TIM3 global interrupt.
*/
void TIM3_IRQHandler(void)
{
/* USER CODE BEGIN TIM3_IRQn 0 */
/* USER CODE END TIM3_IRQn 0 */
HAL_TIM_IRQHandler(&htim3);
/* USER CODE BEGIN TIM3_IRQn 1 */
/* USER CODE END TIM3_IRQn 1 */
}
/**
* @brief This function handles USART2 global interrupt.
*/
@@ -228,6 +244,20 @@ void USART2_IRQHandler(void)
/* USER CODE END USART2_IRQn 1 */
}
/**
* @brief This function handles UART5 global interrupt.
*/
void UART5_IRQHandler(void)
{
/* USER CODE BEGIN UART5_IRQn 0 */
/* USER CODE END UART5_IRQn 0 */
HAL_UART_IRQHandler(&huart5);
/* USER CODE BEGIN UART5_IRQn 1 */
/* USER CODE END UART5_IRQn 1 */
}
/**
* @brief This function handles CAN2 TX interrupt.
*/
+100 -2
View File
@@ -24,8 +24,62 @@
/* USER CODE END 0 */
TIM_HandleTypeDef htim3;
TIM_HandleTypeDef htim4;
/* TIM3 init function */
void MX_TIM3_Init(void)
{
/* USER CODE BEGIN TIM3_Init 0 */
/* USER CODE END TIM3_Init 0 */
TIM_ClockConfigTypeDef sClockSourceConfig = {0};
TIM_MasterConfigTypeDef sMasterConfig = {0};
TIM_IC_InitTypeDef sConfigIC = {0};
/* USER CODE BEGIN TIM3_Init 1 */
/* USER CODE END TIM3_Init 1 */
htim3.Instance = TIM3;
htim3.Init.Prescaler = 0;
htim3.Init.CounterMode = TIM_COUNTERMODE_UP;
htim3.Init.Period = 65535;
htim3.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
htim3.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;
if (HAL_TIM_Base_Init(&htim3) != HAL_OK)
{
Error_Handler();
}
sClockSourceConfig.ClockSource = TIM_CLOCKSOURCE_INTERNAL;
if (HAL_TIM_ConfigClockSource(&htim3, &sClockSourceConfig) != HAL_OK)
{
Error_Handler();
}
if (HAL_TIM_IC_Init(&htim3) != HAL_OK)
{
Error_Handler();
}
sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET;
sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;
if (HAL_TIMEx_MasterConfigSynchronization(&htim3, &sMasterConfig) != HAL_OK)
{
Error_Handler();
}
sConfigIC.ICPolarity = TIM_INPUTCHANNELPOLARITY_RISING;
sConfigIC.ICSelection = TIM_ICSELECTION_DIRECTTI;
sConfigIC.ICPrescaler = TIM_ICPSC_DIV1;
sConfigIC.ICFilter = 4;
if (HAL_TIM_IC_ConfigChannel(&htim3, &sConfigIC, TIM_CHANNEL_2) != HAL_OK)
{
Error_Handler();
}
/* USER CODE BEGIN TIM3_Init 2 */
/* USER CODE END TIM3_Init 2 */
}
/* TIM4 init function */
void MX_TIM4_Init(void)
{
@@ -92,7 +146,32 @@ void MX_TIM4_Init(void)
void HAL_TIM_Base_MspInit(TIM_HandleTypeDef* tim_baseHandle)
{
if(tim_baseHandle->Instance==TIM4)
GPIO_InitTypeDef GPIO_InitStruct = {0};
if(tim_baseHandle->Instance==TIM3)
{
/* USER CODE BEGIN TIM3_MspInit 0 */
/* USER CODE END TIM3_MspInit 0 */
/* TIM3 clock enable */
__HAL_RCC_TIM3_CLK_ENABLE();
__HAL_RCC_GPIOA_CLK_ENABLE();
/**TIM3 GPIO Configuration
PA7 ------> TIM3_CH2
*/
GPIO_InitStruct.Pin = CP_PWM_Pin;
GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
GPIO_InitStruct.Pull = GPIO_NOPULL;
HAL_GPIO_Init(CP_PWM_GPIO_Port, &GPIO_InitStruct);
/* TIM3 interrupt Init */
HAL_NVIC_SetPriority(TIM3_IRQn, 0, 0);
HAL_NVIC_EnableIRQ(TIM3_IRQn);
/* USER CODE BEGIN TIM3_MspInit 1 */
/* USER CODE END TIM3_MspInit 1 */
}
else if(tim_baseHandle->Instance==TIM4)
{
/* USER CODE BEGIN TIM4_MspInit 0 */
@@ -137,7 +216,26 @@ void HAL_TIM_MspPostInit(TIM_HandleTypeDef* timHandle)
void HAL_TIM_Base_MspDeInit(TIM_HandleTypeDef* tim_baseHandle)
{
if(tim_baseHandle->Instance==TIM4)
if(tim_baseHandle->Instance==TIM3)
{
/* USER CODE BEGIN TIM3_MspDeInit 0 */
/* USER CODE END TIM3_MspDeInit 0 */
/* Peripheral clock disable */
__HAL_RCC_TIM3_CLK_DISABLE();
/**TIM3 GPIO Configuration
PA7 ------> TIM3_CH2
*/
HAL_GPIO_DeInit(CP_PWM_GPIO_Port, CP_PWM_Pin);
/* TIM3 interrupt Deinit */
HAL_NVIC_DisableIRQ(TIM3_IRQn);
/* USER CODE BEGIN TIM3_MspDeInit 1 */
/* USER CODE END TIM3_MspDeInit 1 */
}
else if(tim_baseHandle->Instance==TIM4)
{
/* USER CODE BEGIN TIM4_MspDeInit 0 */
+7 -2
View File
@@ -41,7 +41,7 @@ void MX_UART5_Init(void)
/* USER CODE END UART5_Init 1 */
huart5.Instance = UART5;
huart5.Init.BaudRate = 115200;
huart5.Init.BaudRate = 9600;
huart5.Init.WordLength = UART_WORDLENGTH_8B;
huart5.Init.StopBits = UART_STOPBITS_1;
huart5.Init.Parity = UART_PARITY_NONE;
@@ -70,7 +70,7 @@ void MX_USART1_UART_Init(void)
/* USER CODE END USART1_Init 1 */
huart1.Instance = USART1;
huart1.Init.BaudRate = 115200;
huart1.Init.BaudRate = 460800;
huart1.Init.WordLength = UART_WORDLENGTH_8B;
huart1.Init.StopBits = UART_STOPBITS_1;
huart1.Init.Parity = UART_PARITY_NONE;
@@ -173,6 +173,9 @@ void HAL_UART_MspInit(UART_HandleTypeDef* uartHandle)
GPIO_InitStruct.Pull = GPIO_NOPULL;
HAL_GPIO_Init(GPIOD, &GPIO_InitStruct);
/* UART5 interrupt Init */
HAL_NVIC_SetPriority(UART5_IRQn, 0, 0);
HAL_NVIC_EnableIRQ(UART5_IRQn);
/* USER CODE BEGIN UART5_MspInit 1 */
/* USER CODE END UART5_MspInit 1 */
@@ -286,6 +289,8 @@ void HAL_UART_MspDeInit(UART_HandleTypeDef* uartHandle)
HAL_GPIO_DeInit(GPIOD, GPIO_PIN_2);
/* UART5 interrupt Deinit */
HAL_NVIC_DisableIRQ(UART5_IRQn);
/* USER CODE BEGIN UART5_MspDeInit 1 */
/* USER CODE END UART5_MspDeInit 1 */