From 7a74ef13672a0c815e1adfcc976b71a394ebef91 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=90=D1=80=D1=82=D0=B5=D0=BC=20=D0=A7=D0=B0=D0=BC=D0=B0?= =?UTF-8?q?=D0=B9=D0=BA=D0=B8=D0=BD?= Date: Thu, 7 May 2026 22:12:13 +0300 Subject: [PATCH] big refactoring: J1939, log output, state machine bug fixes --- .cproject | 188 +++++++ .gitignore | 177 ++---- .../com.st.stm32cube.ide.mcu.sfrview.prefs | 2 + .settings/language.settings.xml | 25 + .settings/org.eclipse.cdt.core.prefs | 6 + .settings/stm32cubeide.project.prefs | 5 + Core/Inc/board.h | 2 +- Core/Inc/charger_gbt.h | 2 + Core/Inc/connector.h | 24 +- Core/Inc/cp.h | 28 + Core/Inc/debug.h | 10 +- Core/Inc/j1939.h | 20 + Core/Inc/load.h | 6 + Core/Inc/main.h | 24 +- Core/Inc/serial_control.h | 130 +++++ Core/Inc/stm32f1xx_it.h | 2 + Core/Inc/tim.h | 3 + Core/Src/adc.c | 6 +- Core/Src/board.c | 4 +- Core/Src/charger_gbt.c | 141 +++-- Core/Src/connector.c | 58 +- Core/Src/cp.c | 194 +++++++ Core/Src/debug.c | 354 ++++++------ Core/Src/gbt_packet.c | 5 + Core/Src/gpio.c | 36 +- Core/Src/j1939.c | 520 ++++++++++++++---- Core/Src/load.c | 45 ++ Core/Src/main.c | 29 +- Core/Src/rgb_controller.c | 4 +- Core/Src/serial_control.c | 191 +++++++ Core/Src/serial_handler.c | 159 ++++++ Core/Src/stm32f1xx_it.c | 30 + Core/Src/tim.c | 102 +++- Core/Src/usart.c | 9 +- Debug/Core/Src/adc.cyclo | 2 +- Debug/Core/Src/board.cyclo | 16 +- Debug/Core/Src/charger_gbt.cyclo | 22 +- Debug/Core/Src/connector.cyclo | 14 +- Debug/Core/Src/debug.cyclo | 13 +- Debug/Core/Src/gbt_packet.cyclo | 3 +- Debug/Core/Src/j1939.cyclo | 30 +- Debug/Core/Src/main.cyclo | 63 ++- Debug/Core/Src/stm32f1xx_it.cyclo | 28 +- Debug/Core/Src/subdir.mk | 14 +- Debug/Core/Src/usart.cyclo | 2 +- Debug/objects.list | 4 + GBT_J1939_DEBUG_FLOW.md | 180 ++++++ GbTModuleEV.ioc | 158 ++++-- SERIAL_PROTOCOL.md | 168 ++++++ 49 files changed, 2574 insertions(+), 684 deletions(-) create mode 100755 .cproject create mode 100755 .settings/com.st.stm32cube.ide.mcu.sfrview.prefs create mode 100755 .settings/language.settings.xml create mode 100755 .settings/org.eclipse.cdt.core.prefs create mode 100755 .settings/stm32cubeide.project.prefs create mode 100644 Core/Inc/cp.h create mode 100644 Core/Inc/load.h create mode 100644 Core/Inc/serial_control.h create mode 100644 Core/Src/cp.c mode change 100755 => 100644 Core/Src/debug.c create mode 100644 Core/Src/load.c create mode 100644 Core/Src/serial_control.c create mode 100644 Core/Src/serial_handler.c mode change 100755 => 100644 Core/Src/stm32f1xx_it.c create mode 100644 GBT_J1939_DEBUG_FLOW.md create mode 100644 SERIAL_PROTOCOL.md diff --git a/.cproject b/.cproject new file mode 100755 index 0000000..2e87624 --- /dev/null +++ b/.cproject @@ -0,0 +1,188 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/.gitignore b/.gitignore index a81a02d..c36dcd0 100755 --- a/.gitignore +++ b/.gitignore @@ -1,138 +1,55 @@ -# ---> C -# Prerequisites -*.d +# ========================= +# STM32CubeIDE / STM32 GCC +# ========================= -# Object files +# Build output folders +/Debug/ +/Release/ + +# Generated compiler/linker artifacts *.o -*.ko *.obj -*.elf - -# Linker output -*.ilk -*.map -*.exp - -# Precompiled Headers -*.gch -*.pch - -# Libraries -*.lib -*.a -*.la -*.lo - -# Shared objects (inc. Windows DLLs) -*.dll -*.so -*.so.* -*.dylib - -# Executables -*.exe -*.out -*.app -*.i*86 -*.x86_64 -*.hex - -# Debug files -*.dSYM/ +*.d *.su -*.idb -*.pdb - -# Kernel Module Compile Results -*.mod* -*.cmd -.tmp_versions/ -modules.order -Module.symvers -Mkfile.old -dkms.conf - -# ---> CMake -CMakeLists.txt.user -CMakeCache.txt -CMakeFiles -CMakeScripts -Testing -Makefile -cmake_install.cmake -install_manifest.txt -compile_commands.json -CTestTestfile.cmake -_deps - -# ---> Eclipse -.metadata -bin/ -tmp/ -*.tmp -*.bak -*.swp -*~.nib -local.properties -.settings/ -.loadpath -.recommenders - -# External tool builders -.externalToolBuilders/ - -# Locally stored "Eclipse launch configurations" -*.launch - -# PyDev specific (Python IDE for Eclipse) -*.pydevproject - -# CDT-specific (C/C++ Development Tooling) -.cproject - -# CDT- autotools -.autotools - -# Java annotation processor (APT) -.factorypath - -# PDT-specific (PHP Development Tools) -.buildpath - -# sbteclipse plugin -.target - -# Tern plugin -.tern-project - -# TeXlipse plugin -.texlipse - -# STS (Spring Tool Suite) -.springBeans - -# Code Recommenders -.recommenders/ - -# Annotation Processing -.apt_generated/ -.apt_generated_test/ - -# Scala IDE specific (Scala & Java development for Eclipse) -.cache-main -.scala_dependencies -.worksheet - -# Uncomment this line if you wish to ignore the project description file. -# Typically, this file would be tracked if it contains build/dependency configurations: -#.project - -# ---> macOS -.DS_Store - -# ---> STM32CubeIDE / ARM GCC -*.bin *.cyclo *.list +*.map +*.a +*.lib +*.out +*.exp +*.ilk +subdir.mk +sources.mk +objects.mk + +# Firmware and executable deliverables (keep out of source history) +*.elf +*.axf +*.bin +*.hex *.srec *.verilog + +# Captured logs/traces +/logs/ +*.log + +# Local IDE/OS temp files +.DS_Store +*.swp +*.tmp +*.bak +*~ +.metadata/ +.externalToolBuilders/ + +# Local launch configurations +*.launch + +# Keep project descriptors/versioned configuration +!.project +!.cproject +!.settings/ +!.mxproject +!*.ioc diff --git a/.settings/com.st.stm32cube.ide.mcu.sfrview.prefs b/.settings/com.st.stm32cube.ide.mcu.sfrview.prefs new file mode 100755 index 0000000..98a69fc --- /dev/null +++ b/.settings/com.st.stm32cube.ide.mcu.sfrview.prefs @@ -0,0 +1,2 @@ +eclipse.preferences.version=1 +sfrviewstate={"fFavorites"\:{"fLists"\:{}},"fProperties"\:{"fNodeProperties"\:{}}} diff --git a/.settings/language.settings.xml b/.settings/language.settings.xml new file mode 100755 index 0000000..dae24b6 --- /dev/null +++ b/.settings/language.settings.xml @@ -0,0 +1,25 @@ + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/.settings/org.eclipse.cdt.core.prefs b/.settings/org.eclipse.cdt.core.prefs new file mode 100755 index 0000000..c8ec5df --- /dev/null +++ b/.settings/org.eclipse.cdt.core.prefs @@ -0,0 +1,6 @@ +doxygen/doxygen_new_line_after_brief=true +doxygen/doxygen_use_brief_tag=false +doxygen/doxygen_use_javadoc_tags=true +doxygen/doxygen_use_pre_tag=false +doxygen/doxygen_use_structural_commands=false +eclipse.preferences.version=1 diff --git a/.settings/stm32cubeide.project.prefs b/.settings/stm32cubeide.project.prefs new file mode 100755 index 0000000..e3e642d --- /dev/null +++ b/.settings/stm32cubeide.project.prefs @@ -0,0 +1,5 @@ +2F62501ED4689FB349E356AB974DBE57=0A9B2D4C5DCB32842F05F53136A1D1D7 +66BE74F758C12D739921AEA421D593D3=1 +8DF89ED150041C4CBC7CB9A9CAA90856=0A9B2D4C5DCB32842F05F53136A1D1D7 +DC22A860405A8BF2F2C095E5B6529F12=283F84148D7B38E239E7ECD52C68B71F +eclipse.preferences.version=1 diff --git a/Core/Inc/board.h b/Core/Inc/board.h index 5618121..b45c548 100755 --- a/Core/Inc/board.h +++ b/Core/Inc/board.h @@ -17,7 +17,7 @@ typedef enum{ RELAY_3, RELAY_4, RELAY_5, - + RELAY_CP, }relay_t; typedef enum{ diff --git a/Core/Inc/charger_gbt.h b/Core/Inc/charger_gbt.h index 0889995..97881b6 100755 --- a/Core/Inc/charger_gbt.h +++ b/Core/Inc/charger_gbt.h @@ -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); diff --git a/Core/Inc/connector.h b/Core/Inc/connector.h index 5ff26b1..9665825 100755 --- a/Core/Inc/connector.h +++ b/Core/Inc/connector.h @@ -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_ */ diff --git a/Core/Inc/cp.h b/Core/Inc/cp.h new file mode 100644 index 0000000..f98bb29 --- /dev/null +++ b/Core/Inc/cp.h @@ -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_ */ diff --git a/Core/Inc/debug.h b/Core/Inc/debug.h index 1543b68..48bef46 100755 --- a/Core/Inc/debug.h +++ b/Core/Inc/debug.h @@ -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 +#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_ */ diff --git a/Core/Inc/j1939.h b/Core/Inc/j1939.h index 4c6dce5..139c4e8 100755 --- a/Core/Inc/j1939.h +++ b/Core/Inc/j1939.h @@ -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(); diff --git a/Core/Inc/load.h b/Core/Inc/load.h new file mode 100644 index 0000000..e1f0ec9 --- /dev/null +++ b/Core/Inc/load.h @@ -0,0 +1,6 @@ +#pragma once + +#include "main.h" + +void LOAD_Init(); +void LOAD_Task(); \ No newline at end of file diff --git a/Core/Inc/main.h b/Core/Inc/main.h index b4d87da..2cd6224 100644 --- a/Core/Inc/main.h +++ b/Core/Inc/main.h @@ -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 diff --git a/Core/Inc/serial_control.h b/Core/Inc/serial_control.h new file mode 100644 index 0000000..ee703ce --- /dev/null +++ b/Core/Inc/serial_control.h @@ -0,0 +1,130 @@ +#ifndef SERIAL_CONTROL_H +#define SERIAL_CONTROL_H + +#include +#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 */ diff --git a/Core/Inc/stm32f1xx_it.h b/Core/Inc/stm32f1xx_it.h index 5de19e6..2528f6e 100644 --- a/Core/Inc/stm32f1xx_it.h +++ b/Core/Inc/stm32f1xx_it.h @@ -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 */ diff --git a/Core/Inc/tim.h b/Core/Inc/tim.h index 3894a40..39b0151 100644 --- a/Core/Inc/tim.h +++ b/Core/Inc/tim.h @@ -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); diff --git a/Core/Src/adc.c b/Core/Src/adc.c index ed54e8f..50cdc96 100644 --- a/Core/Src/adc.c +++ b/Core/Src/adc.c @@ -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); diff --git a/Core/Src/board.c b/Core/Src/board.c index 40e7944..572b705 100755 --- a/Core/Src/board.c +++ b/Core/Src/board.c @@ -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); } diff --git a/Core/Src/charger_gbt.c b/Core/Src/charger_gbt.c index 3e3e31b..457be06 100755 --- a/Core/Src/charger_gbt.c +++ b/Core/Src/charger_gbt.c @@ -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(); } diff --git a/Core/Src/connector.c b/Core/Src/connector.c index 6b43655..2093225 100755 --- a/Core/Src/connector.c +++ b/Core/Src/connector.c @@ -7,12 +7,14 @@ #include "connector.h" #include "board.h" #include "edcan.h" +#include "debug.h" #include #include 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"); } diff --git a/Core/Src/cp.c b/Core/Src/cp.c new file mode 100644 index 0000000..fa4f377 --- /dev/null +++ b/Core/Src/cp.c @@ -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; +} diff --git a/Core/Src/debug.c b/Core/Src/debug.c old mode 100755 new mode 100644 index 1050a53..931abe3 --- a/Core/Src/debug.c +++ b/Core/Src/debug.c @@ -1,226 +1,182 @@ /* * debug.c - * - * Created on: Apr 16, 2024 - * Author: colorbass */ #include "main.h" #include #include +#include +#include #include "debug.h" -#include "board.h" -#include "charger_gbt.h" +#include "serial_control.h" #include "usart.h" -#include -#include +#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; } diff --git a/Core/Src/gbt_packet.c b/Core/Src/gbt_packet.c index 442703a..064a7df 100755 --- a/Core/Src/gbt_packet.c +++ b/Core/Src/gbt_packet.c @@ -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); diff --git a/Core/Src/gpio.c b/Core/Src/gpio.c index d5b287b..4923abb 100644 --- a/Core/Src/gpio.c +++ b/Core/Src/gpio.c @@ -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; diff --git a/Core/Src/j1939.c b/Core/Src/j1939.c index 50358ce..73a58b6 100755 --- a/Core/Src/j1939.c +++ b/Core/Src/j1939.c @@ -11,107 +11,272 @@ #include "string.h" #include "can.h" #include "edcan.h" +#include "debug.h" +#include 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); +} diff --git a/Core/Src/load.c b/Core/Src/load.c new file mode 100644 index 0000000..578f242 --- /dev/null +++ b/Core/Src/load.c @@ -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); + // } +} \ No newline at end of file diff --git a/Core/Src/main.c b/Core/Src/main.c index 838ba1d..d0deecf 100644 --- a/Core/Src/main.c +++ b/Core/Src/main.c @@ -30,13 +30,15 @@ #include "can.h" #include "board.h" #include -#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(); diff --git a/Core/Src/rgb_controller.c b/Core/Src/rgb_controller.c index b5f211b..d1a52ba 100644 --- a/Core/Src/rgb_controller.c +++ b/Core/Src/rgb_controller.c @@ -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; diff --git a/Core/Src/serial_control.c b/Core/Src/serial_control.c new file mode 100644 index 0000000..251472e --- /dev/null +++ b/Core/Src/serial_control.c @@ -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; +} diff --git a/Core/Src/serial_handler.c b/Core/Src/serial_handler.c new file mode 100644 index 0000000..bcf1aaa --- /dev/null +++ b/Core/Src/serial_handler.c @@ -0,0 +1,159 @@ +#include "serial_control.h" +#include "charger_gbt.h" +#include "cp.h" +#include "edcan_config.h" +#include +#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; +} + diff --git a/Core/Src/stm32f1xx_it.c b/Core/Src/stm32f1xx_it.c old mode 100755 new mode 100644 index 16853bf..e573c79 --- a/Core/Src/stm32f1xx_it.c +++ b/Core/Src/stm32f1xx_it.c @@ -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. */ diff --git a/Core/Src/tim.c b/Core/Src/tim.c index 4961217..36a0a9b 100644 --- a/Core/Src/tim.c +++ b/Core/Src/tim.c @@ -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 */ diff --git a/Core/Src/usart.c b/Core/Src/usart.c index ab44ba1..bef1ff3 100644 --- a/Core/Src/usart.c +++ b/Core/Src/usart.c @@ -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 */ diff --git a/Debug/Core/Src/adc.cyclo b/Debug/Core/Src/adc.cyclo index 52957bf..81e4a6e 100644 --- a/Debug/Core/Src/adc.cyclo +++ b/Debug/Core/Src/adc.cyclo @@ -1,3 +1,3 @@ ../Core/Src/adc.c:30:6:MX_ADC1_Init 3 ../Core/Src/adc.c:72:6:HAL_ADC_MspInit 2 -../Core/Src/adc.c:106:6:HAL_ADC_MspDeInit 2 +../Core/Src/adc.c:107:6:HAL_ADC_MspDeInit 2 diff --git a/Debug/Core/Src/board.cyclo b/Debug/Core/Src/board.cyclo index 2d6d166..5fc9591 100644 --- a/Debug/Core/Src/board.cyclo +++ b/Debug/Core/Src/board.cyclo @@ -1,8 +1,8 @@ -../Core/Src/board.c:16:6:RELAY_Write 7 -../Core/Src/board.c:26:9:IN_ReadInput 9 -../Core/Src/board.c:58:9:GetBoardTemp 1 -../Core/Src/board.c:70:6:Init_Peripheral 1 -../Core/Src/board.c:81:7:pt1000_to_temperature 1 -../Core/Src/board.c:97:7:calculate_NTC_resistance 2 -../Core/Src/board.c:112:9:GBT_ReadTemp 3 -../Core/Src/board.c:147:6:ADC_Select_Channel 2 +../Core/Src/board.c:16:6:RELAY_Write 8 +../Core/Src/board.c:27:9:IN_ReadInput 9 +../Core/Src/board.c:59:9:GetBoardTemp 1 +../Core/Src/board.c:71:6:Init_Peripheral 1 +../Core/Src/board.c:83:7:pt1000_to_temperature 1 +../Core/Src/board.c:99:7:calculate_NTC_resistance 2 +../Core/Src/board.c:114:9:GBT_ReadTemp 3 +../Core/Src/board.c:149:6:ADC_Select_Channel 2 diff --git a/Debug/Core/Src/charger_gbt.cyclo b/Debug/Core/Src/charger_gbt.cyclo index b9e2909..142cd70 100644 --- a/Debug/Core/Src/charger_gbt.cyclo +++ b/Debug/Core/Src/charger_gbt.cyclo @@ -1,11 +1,11 @@ -../Core/Src/charger_gbt.c:60:6:GBT_Init 1 -../Core/Src/charger_gbt.c:67:6:GBT_ChargerTask 53 -../Core/Src/charger_gbt.c:310:6:GBT_SwitchState 13 -../Core/Src/charger_gbt.c:330:10:GBT_StateTick 1 -../Core/Src/charger_gbt.c:334:6:GBT_Delay 1 -../Core/Src/charger_gbt.c:339:6:GBT_StopEV 3 -../Core/Src/charger_gbt.c:349:6:GBT_StopEVSE 2 -../Core/Src/charger_gbt.c:355:6:GBT_StopOCPP 2 -../Core/Src/charger_gbt.c:361:6:GBT_ForceStop 1 -../Core/Src/charger_gbt.c:368:6:GBT_Error 1 -../Core/Src/charger_gbt.c:376:6:GBT_Reset 1 +../Core/Src/charger_gbt.c:68:6:GBT_Init 1 +../Core/Src/charger_gbt.c:78:6:GBT_ChargerTask 61 +../Core/Src/charger_gbt.c:364:6:GBT_SwitchState 13 +../Core/Src/charger_gbt.c:384:10:GBT_StateTick 1 +../Core/Src/charger_gbt.c:388:6:GBT_Delay 1 +../Core/Src/charger_gbt.c:393:6:GBT_StopEV 3 +../Core/Src/charger_gbt.c:403:6:GBT_StopEVSE 2 +../Core/Src/charger_gbt.c:409:6:GBT_StopOCPP 2 +../Core/Src/charger_gbt.c:415:6:GBT_ForceStop 1 +../Core/Src/charger_gbt.c:422:6:GBT_Error 1 +../Core/Src/charger_gbt.c:430:6:GBT_Reset 1 diff --git a/Debug/Core/Src/connector.cyclo b/Debug/Core/Src/connector.cyclo index acdcf9b..3aa85ef 100644 --- a/Debug/Core/Src/connector.cyclo +++ b/Debug/Core/Src/connector.cyclo @@ -1,7 +1,7 @@ -../Core/Src/connector.c:21:6:CONN_Init 1 -../Core/Src/connector.c:27:6:CONN_Task 18 -../Core/Src/connector.c:112:6:CONN_SetState 15 -../Core/Src/connector.c:134:6:CONN_CC_ReadStateFiltered 4 -../Core/Src/connector.c:153:9:CONN_CC_GetState 1 -../Core/Src/connector.c:156:9:CONN_CC_GetStateRaw 9 -../Core/Src/connector.c:183:7:CONN_CC_GetAdc 1 +../Core/Src/connector.c:23:6:CONN_Init 1 +../Core/Src/connector.c:29:6:CONN_Task 18 +../Core/Src/connector.c:122:6:CONN_SetState 15 +../Core/Src/connector.c:144:6:CONN_CC_ReadStateFiltered 4 +../Core/Src/connector.c:163:9:CONN_CC_GetState 1 +../Core/Src/connector.c:166:9:CONN_CC_GetStateRaw 9 +../Core/Src/connector.c:193:7:CONN_CC_GetAdc 1 diff --git a/Debug/Core/Src/debug.cyclo b/Debug/Core/Src/debug.cyclo index 12f5e43..4bd93ed 100644 --- a/Debug/Core/Src/debug.cyclo +++ b/Debug/Core/Src/debug.cyclo @@ -1,7 +1,6 @@ -../Drivers/CMSIS/Include/core_cm3.h:1762:34:__NVIC_SystemReset 1 -../Core/Src/debug.c:26:5:_write 1 -../Core/Src/debug.c:35:6:HAL_UARTEx_RxEventCallback 2 -../Core/Src/debug.c:45:6:debug_rx_interrupt 1 -../Core/Src/debug.c:51:6:debug_init 1 -../Core/Src/debug.c:61:6:parse_command 25 -../Core/Src/debug.c:220:6:debug_task 2 +../Core/Src/debug.c:34:13:debug_uart1_write 5 +../Core/Src/debug.c:50:5:_write 1 +../Core/Src/debug.c:58:6:debug_buffer_add 3 +../Core/Src/debug.c:74:10:debug_buffer_available 1 +../Core/Src/debug.c:82:6:debug_buffer_send 5 +../Core/Src/debug.c:111:5:log_printf 16 diff --git a/Debug/Core/Src/gbt_packet.cyclo b/Debug/Core/Src/gbt_packet.cyclo index 789bbc4..adc87be 100644 --- a/Debug/Core/Src/gbt_packet.cyclo +++ b/Debug/Core/Src/gbt_packet.cyclo @@ -5,4 +5,5 @@ ../Core/Src/gbt_packet.c:39:6:GBT_SendBCL 1 ../Core/Src/gbt_packet.c:44:6:GBT_SendBCS 1 ../Core/Src/gbt_packet.c:49:6:GBT_SendBSM 1 -../Core/Src/gbt_packet.c:54:6:GBT_SendBSD 1 +../Core/Src/gbt_packet.c:54:6:GBT_SendBST 1 +../Core/Src/gbt_packet.c:59:6:GBT_SendBSD 1 diff --git a/Debug/Core/Src/j1939.cyclo b/Debug/Core/Src/j1939.cyclo index 65cbe3a..ad130d3 100644 --- a/Debug/Core/Src/j1939.cyclo +++ b/Debug/Core/Src/j1939.cyclo @@ -1,6 +1,24 @@ -../Core/Src/j1939.c:20:6:HAL_CAN_RxFifo0MsgPendingCallback 20 -../Core/Src/j1939.c:117:6:GBT_CAN_ReInit 1 -../Core/Src/j1939.c:125:6:J_SendPacket 1 -../Core/Src/j1939.c:146:6:J_SendCTS 2 -../Core/Src/j1939.c:164:6:J_SendACK 1 -../Core/Src/j1939.c:179:6:GBT_CAN_FilterInit 2 +../Core/Src/j1939.c:76:13:J_TxReset 2 +../Core/Src/j1939.c:84:6:J1939_InitBuffers 1 +../Core/Src/j1939.c:91:10:J1939_GetRxBufferCount 1 +../Core/Src/j1939.c:99:10:J1939_GetTxBufferCount 1 +../Core/Src/j1939.c:107:10:J1939_GetRxOverflowCount 1 +../Core/Src/j1939.c:111:10:J1939_GetTxOverflowCount 1 +../Core/Src/j1939.c:115:6:HAL_CAN_RxFifo0MsgPendingCallback 2 +../Core/Src/j1939.c:129:13:J1939_ProcessRxFrame 29 +../Core/Src/j1939.c:231:6:J1939_ExchangeRxBuffer 2 +../Core/Src/j1939.c:239:6:J1939_ExchangeTxBuffer 9 +../Core/Src/j1939.c:282:6:GBT_CAN_ReInit 1 +../Core/Src/j1939.c:291:6:J_SendPacket 3 +../Core/Src/j1939.c:322:13:J_TxCheckTimeout 7 +../Core/Src/j1939.c:343:13:J_SendTpRts 1 +../Core/Src/j1939.c:358:13:J_SendTpDtRange 11 +../Core/Src/j1939.c:406:6:J_SendCTS 2 +../Core/Src/j1939.c:424:6:J_SendACK 1 +../Core/Src/j1939.c:439:6:GBT_CAN_FilterInit 2 +../Core/Src/j1939.c:459:13:J1939_RxBufferAdd 2 +../Core/Src/j1939.c:473:16:J1939_RxBufferGet 2 +../Core/Src/j1939.c:486:13:J1939_TxBufferAdd 2 +../Core/Src/j1939.c:500:16:J1939_TxBufferPeek 2 +../Core/Src/j1939.c:511:13:J1939_TxBufferDropFirst 2 +../Core/Src/j1939.c:520:13:J1939_TxQueueByPgn 4 diff --git a/Debug/Core/Src/main.cyclo b/Debug/Core/Src/main.cyclo index e46ac26..44aad39 100644 --- a/Debug/Core/Src/main.cyclo +++ b/Debug/Core/Src/main.cyclo @@ -1,22 +1,23 @@ ../Drivers/CMSIS/Include/core_cm3.h:1762:34:__NVIC_SystemReset 1 -/Users/colorbass/STM32CubeIDE/workspace_1.12.0/lib_EDCAN/edcan.c:41:16:EDCAN_VectorTableIsPlausible 3 -/Users/colorbass/STM32CubeIDE/workspace_1.12.0/lib_EDCAN/edcan.c:49:6:EDCAN_VectorBaseConfigF0 1 -/Users/colorbass/STM32CubeIDE/workspace_1.12.0/lib_EDCAN/edcan.c:84:6:EDCAN_VectorBaseConfigF1 1 -/Users/colorbass/STM32CubeIDE/workspace_1.12.0/lib_EDCAN/edcan.c:171:6:HAL_CAN_RxFifo1MsgPendingCallback 8 -/Users/colorbass/STM32CubeIDE/workspace_1.12.0/lib_EDCAN/edcan.c:198:6:HAL_CAN_TxMailbox0CompleteCallback 2 -/Users/colorbass/STM32CubeIDE/workspace_1.12.0/lib_EDCAN/edcan.c:204:6:HAL_CAN_TxMailbox1CompleteCallback 2 -/Users/colorbass/STM32CubeIDE/workspace_1.12.0/lib_EDCAN/edcan.c:210:6:HAL_CAN_TxMailbox2CompleteCallback 2 -/Users/colorbass/STM32CubeIDE/workspace_1.12.0/lib_EDCAN/edcan.c:221:6:EDCAN_Init 1 -/Users/colorbass/STM32CubeIDE/workspace_1.12.0/lib_EDCAN/edcan.c:240:9:EDCAN_GetBoardVersion 1 -/Users/colorbass/STM32CubeIDE/workspace_1.12.0/lib_EDCAN/edcan.c:250:6:EDCAN_SetSecondID 1 -/Users/colorbass/STM32CubeIDE/workspace_1.12.0/lib_EDCAN/edcan.c:260:6:CAN_ReInit 1 -/Users/colorbass/STM32CubeIDE/workspace_1.12.0/lib_EDCAN/edcan.c:300:6:EDCAN_FilterInit 5 -/Users/colorbass/STM32CubeIDE/workspace_1.12.0/lib_EDCAN/edcan.c:390:6:EDCAN_SendPacketWrite 1 -/Users/colorbass/STM32CubeIDE/workspace_1.12.0/lib_EDCAN/edcan.c:427:6:EDCAN_SendPacketWriteLong 2 -/Users/colorbass/STM32CubeIDE/workspace_1.12.0/lib_EDCAN/edcan.c:451:6:EDCAN_SendPacketRead 1 -/Users/colorbass/STM32CubeIDE/workspace_1.12.0/lib_EDCAN/edcan.c:487:6:EDCAN_SendPacketReadRequest 1 -/Users/colorbass/STM32CubeIDE/workspace_1.12.0/lib_EDCAN/edcan.c:519:6:EDCAN_Loop 5 -/Users/colorbass/STM32CubeIDE/workspace_1.12.0/lib_EDCAN/edcan.c:540:6:EDCAN_SendAlivePacket 1 +/Users/colorbass/STM32CubeIDE/workspace_1.12.0/lib_EDCAN/edcan.c:32:13:EDCAN_SelectInfoBlockAddress 2 +/Users/colorbass/STM32CubeIDE/workspace_1.12.0/lib_EDCAN/edcan.c:54:16:EDCAN_VectorTableIsPlausible 3 +/Users/colorbass/STM32CubeIDE/workspace_1.12.0/lib_EDCAN/edcan.c:62:6:EDCAN_VectorBaseConfigF0 1 +/Users/colorbass/STM32CubeIDE/workspace_1.12.0/lib_EDCAN/edcan.c:97:6:EDCAN_VectorBaseConfigF1 1 +/Users/colorbass/STM32CubeIDE/workspace_1.12.0/lib_EDCAN/edcan.c:184:6:HAL_CAN_RxFifo1MsgPendingCallback 8 +/Users/colorbass/STM32CubeIDE/workspace_1.12.0/lib_EDCAN/edcan.c:211:6:HAL_CAN_TxMailbox0CompleteCallback 2 +/Users/colorbass/STM32CubeIDE/workspace_1.12.0/lib_EDCAN/edcan.c:217:6:HAL_CAN_TxMailbox1CompleteCallback 2 +/Users/colorbass/STM32CubeIDE/workspace_1.12.0/lib_EDCAN/edcan.c:223:6:HAL_CAN_TxMailbox2CompleteCallback 2 +/Users/colorbass/STM32CubeIDE/workspace_1.12.0/lib_EDCAN/edcan.c:234:6:EDCAN_Init 1 +/Users/colorbass/STM32CubeIDE/workspace_1.12.0/lib_EDCAN/edcan.c:254:9:EDCAN_GetBoardVersion 1 +/Users/colorbass/STM32CubeIDE/workspace_1.12.0/lib_EDCAN/edcan.c:265:6:EDCAN_SetSecondID 1 +/Users/colorbass/STM32CubeIDE/workspace_1.12.0/lib_EDCAN/edcan.c:275:6:CAN_ReInit 1 +/Users/colorbass/STM32CubeIDE/workspace_1.12.0/lib_EDCAN/edcan.c:315:6:EDCAN_FilterInit 5 +/Users/colorbass/STM32CubeIDE/workspace_1.12.0/lib_EDCAN/edcan.c:405:6:EDCAN_SendPacketWrite 1 +/Users/colorbass/STM32CubeIDE/workspace_1.12.0/lib_EDCAN/edcan.c:442:6:EDCAN_SendPacketWriteLong 2 +/Users/colorbass/STM32CubeIDE/workspace_1.12.0/lib_EDCAN/edcan.c:466:6:EDCAN_SendPacketRead 1 +/Users/colorbass/STM32CubeIDE/workspace_1.12.0/lib_EDCAN/edcan.c:502:6:EDCAN_SendPacketReadRequest 1 +/Users/colorbass/STM32CubeIDE/workspace_1.12.0/lib_EDCAN/edcan.c:534:6:EDCAN_Loop 5 +/Users/colorbass/STM32CubeIDE/workspace_1.12.0/lib_EDCAN/edcan.c:555:6:EDCAN_SendAlivePacket 1 /Users/colorbass/STM32CubeIDE/workspace_1.12.0/lib_EDCAN/edcan_buffer.c:41:6:EDCAN_TxBufferAdd 2 /Users/colorbass/STM32CubeIDE/workspace_1.12.0/lib_EDCAN/edcan_buffer.c:57:10:EDCAN_getTxBufferElementCount 1 /Users/colorbass/STM32CubeIDE/workspace_1.12.0/lib_EDCAN/edcan_buffer.c:65:6:EDCAN_TxBufferPeekFirst 2 @@ -26,15 +27,17 @@ /Users/colorbass/STM32CubeIDE/workspace_1.12.0/lib_EDCAN/edcan_buffer.c:150:6:EDCAN_RxBufferGet 2 /Users/colorbass/STM32CubeIDE/workspace_1.12.0/lib_EDCAN/edcan_buffer.c:168:10:EDCAN_getRxBufferElementCount 1 /Users/colorbass/STM32CubeIDE/workspace_1.12.0/lib_EDCAN/edcan_buffer.c:176:6:EDCAN_ExchangeRxBuffer 5 -/Users/colorbass/STM32CubeIDE/workspace_1.12.0/lib_EDCAN/edcan_handler.c:40:6:EDCAN_WriteHandler 3 -/Users/colorbass/STM32CubeIDE/workspace_1.12.0/lib_EDCAN/edcan_handler.c:51:6:EDCAN_EnterBootloader 0 -/Users/colorbass/STM32CubeIDE/workspace_1.12.0/lib_EDCAN/edcan_handler.c:56:6:EDCAN_WriteSystemRegister 9 -/Users/colorbass/STM32CubeIDE/workspace_1.12.0/lib_EDCAN/edcan_handler.c:86:9:EDCAN_GetSystemRegisterValue 3 -/Users/colorbass/STM32CubeIDE/workspace_1.12.0/lib_EDCAN/edcan_handler.c:106:9:EDCAN_GetOwnRegisterValue 2 -/Users/colorbass/STM32CubeIDE/workspace_1.12.0/lib_EDCAN/edcan_handler.c:125:6:EDCAN_ReadRequestHandler 5 -/Users/colorbass/STM32CubeIDE/workspace_1.12.0/lib_EDCAN/edcan_log.c:10:6:EDCAN_printf 1 -/Users/colorbass/STM32CubeIDE/workspace_1.12.0/lib_EDCAN/edcan_log.c:31:6:EDCAN_Log 2 -/Users/colorbass/STM32CubeIDE/workspace_1.12.0/lib_EDCAN/edcan_log.c:56:6:EDCAN_SendPacketLog 1 -../Core/Src/main.c:81:5:main 1 -../Core/Src/main.c:169:6:SystemClock_Config 4 -../Core/Src/main.c:229:6:Error_Handler 1 +/Users/colorbass/STM32CubeIDE/workspace_1.12.0/lib_EDCAN/edcan_handler.c:41:6:EDCAN_WriteHandler 3 +/Users/colorbass/STM32CubeIDE/workspace_1.12.0/lib_EDCAN/edcan_handler.c:52:6:EDCAN_EnterBootloader 0 +/Users/colorbass/STM32CubeIDE/workspace_1.12.0/lib_EDCAN/edcan_handler.c:57:6:EDCAN_WriteSystemRegister 11 +/Users/colorbass/STM32CubeIDE/workspace_1.12.0/lib_EDCAN/edcan_handler.c:91:9:EDCAN_GetSystemRegisterValue 5 +/Users/colorbass/STM32CubeIDE/workspace_1.12.0/lib_EDCAN/edcan_handler.c:114:9:EDCAN_GetOwnRegisterValue 2 +/Users/colorbass/STM32CubeIDE/workspace_1.12.0/lib_EDCAN/edcan_handler.c:133:6:EDCAN_ReadRequestHandler 5 +/Users/colorbass/STM32CubeIDE/workspace_1.12.0/lib_EDCAN/edcan_log.c:11:6:EDCAN_SetLogLevel 2 +/Users/colorbass/STM32CubeIDE/workspace_1.12.0/lib_EDCAN/edcan_log.c:18:18:EDCAN_GetLogLevel 2 +/Users/colorbass/STM32CubeIDE/workspace_1.12.0/lib_EDCAN/edcan_log.c:26:6:EDCAN_printf 2 +/Users/colorbass/STM32CubeIDE/workspace_1.12.0/lib_EDCAN/edcan_log.c:51:6:EDCAN_Log 2 +/Users/colorbass/STM32CubeIDE/workspace_1.12.0/lib_EDCAN/edcan_log.c:76:6:EDCAN_SendPacketLog 1 +../Core/Src/main.c:84:5:main 1 +../Core/Src/main.c:180:6:SystemClock_Config 4 +../Core/Src/main.c:240:6:Error_Handler 1 diff --git a/Debug/Core/Src/stm32f1xx_it.cyclo b/Debug/Core/Src/stm32f1xx_it.cyclo index aca5fab..06f3d11 100644 --- a/Debug/Core/Src/stm32f1xx_it.cyclo +++ b/Debug/Core/Src/stm32f1xx_it.cyclo @@ -1,13 +1,15 @@ -../Core/Src/stm32f1xx_it.c:71:6:NMI_Handler 1 -../Core/Src/stm32f1xx_it.c:86:6:HardFault_Handler 1 -../Core/Src/stm32f1xx_it.c:101:6:MemManage_Handler 1 -../Core/Src/stm32f1xx_it.c:116:6:BusFault_Handler 1 -../Core/Src/stm32f1xx_it.c:131:6:UsageFault_Handler 1 -../Core/Src/stm32f1xx_it.c:146:6:SVC_Handler 1 -../Core/Src/stm32f1xx_it.c:159:6:DebugMon_Handler 1 -../Core/Src/stm32f1xx_it.c:172:6:PendSV_Handler 1 -../Core/Src/stm32f1xx_it.c:185:6:SysTick_Handler 1 -../Core/Src/stm32f1xx_it.c:206:6:CAN1_RX0_IRQHandler 1 -../Core/Src/stm32f1xx_it.c:220:6:USART2_IRQHandler 1 -../Core/Src/stm32f1xx_it.c:234:6:CAN2_TX_IRQHandler 1 -../Core/Src/stm32f1xx_it.c:248:6:CAN2_RX1_IRQHandler 1 +../Core/Src/stm32f1xx_it.c:73:6:NMI_Handler 1 +../Core/Src/stm32f1xx_it.c:88:6:HardFault_Handler 1 +../Core/Src/stm32f1xx_it.c:103:6:MemManage_Handler 1 +../Core/Src/stm32f1xx_it.c:118:6:BusFault_Handler 1 +../Core/Src/stm32f1xx_it.c:133:6:UsageFault_Handler 1 +../Core/Src/stm32f1xx_it.c:148:6:SVC_Handler 1 +../Core/Src/stm32f1xx_it.c:161:6:DebugMon_Handler 1 +../Core/Src/stm32f1xx_it.c:174:6:PendSV_Handler 1 +../Core/Src/stm32f1xx_it.c:187:6:SysTick_Handler 1 +../Core/Src/stm32f1xx_it.c:208:6:CAN1_RX0_IRQHandler 1 +../Core/Src/stm32f1xx_it.c:222:6:TIM3_IRQHandler 1 +../Core/Src/stm32f1xx_it.c:236:6:USART2_IRQHandler 1 +../Core/Src/stm32f1xx_it.c:250:6:UART5_IRQHandler 1 +../Core/Src/stm32f1xx_it.c:264:6:CAN2_TX_IRQHandler 1 +../Core/Src/stm32f1xx_it.c:278:6:CAN2_RX1_IRQHandler 1 diff --git a/Debug/Core/Src/subdir.mk b/Debug/Core/Src/subdir.mk index 44cc7bf..8ffc1b1 100644 --- a/Debug/Core/Src/subdir.mk +++ b/Debug/Core/Src/subdir.mk @@ -10,14 +10,18 @@ C_SRCS += \ ../Core/Src/can.c \ ../Core/Src/charger_gbt.c \ ../Core/Src/connector.c \ +../Core/Src/cp.c \ ../Core/Src/debug.c \ ../Core/Src/edcan_handler_user.c \ ../Core/Src/gbt_packet.c \ ../Core/Src/gpio.c \ ../Core/Src/j1939.c \ +../Core/Src/load.c \ ../Core/Src/main.c \ ../Core/Src/rgb_controller.c \ ../Core/Src/rtc.c \ +../Core/Src/serial_control.c \ +../Core/Src/serial_handler.c \ ../Core/Src/soft_rtc.c \ ../Core/Src/stm32f1xx_hal_msp.c \ ../Core/Src/stm32f1xx_it.c \ @@ -33,14 +37,18 @@ C_DEPS += \ ./Core/Src/can.d \ ./Core/Src/charger_gbt.d \ ./Core/Src/connector.d \ +./Core/Src/cp.d \ ./Core/Src/debug.d \ ./Core/Src/edcan_handler_user.d \ ./Core/Src/gbt_packet.d \ ./Core/Src/gpio.d \ ./Core/Src/j1939.d \ +./Core/Src/load.d \ ./Core/Src/main.d \ ./Core/Src/rgb_controller.d \ ./Core/Src/rtc.d \ +./Core/Src/serial_control.d \ +./Core/Src/serial_handler.d \ ./Core/Src/soft_rtc.d \ ./Core/Src/stm32f1xx_hal_msp.d \ ./Core/Src/stm32f1xx_it.d \ @@ -56,14 +64,18 @@ OBJS += \ ./Core/Src/can.o \ ./Core/Src/charger_gbt.o \ ./Core/Src/connector.o \ +./Core/Src/cp.o \ ./Core/Src/debug.o \ ./Core/Src/edcan_handler_user.o \ ./Core/Src/gbt_packet.o \ ./Core/Src/gpio.o \ ./Core/Src/j1939.o \ +./Core/Src/load.o \ ./Core/Src/main.o \ ./Core/Src/rgb_controller.o \ ./Core/Src/rtc.o \ +./Core/Src/serial_control.o \ +./Core/Src/serial_handler.o \ ./Core/Src/soft_rtc.o \ ./Core/Src/stm32f1xx_hal_msp.o \ ./Core/Src/stm32f1xx_it.o \ @@ -81,7 +93,7 @@ Core/Src/%.o Core/Src/%.su Core/Src/%.cyclo: ../Core/Src/%.c Core/Src/subdir.mk clean: clean-Core-2f-Src clean-Core-2f-Src: - -$(RM) ./Core/Src/adc.cyclo ./Core/Src/adc.d ./Core/Src/adc.o ./Core/Src/adc.su ./Core/Src/board.cyclo ./Core/Src/board.d ./Core/Src/board.o ./Core/Src/board.su ./Core/Src/can.cyclo ./Core/Src/can.d ./Core/Src/can.o ./Core/Src/can.su ./Core/Src/charger_gbt.cyclo ./Core/Src/charger_gbt.d ./Core/Src/charger_gbt.o ./Core/Src/charger_gbt.su ./Core/Src/connector.cyclo ./Core/Src/connector.d ./Core/Src/connector.o ./Core/Src/connector.su ./Core/Src/debug.cyclo ./Core/Src/debug.d ./Core/Src/debug.o ./Core/Src/debug.su ./Core/Src/edcan_handler_user.cyclo ./Core/Src/edcan_handler_user.d ./Core/Src/edcan_handler_user.o ./Core/Src/edcan_handler_user.su ./Core/Src/gbt_packet.cyclo ./Core/Src/gbt_packet.d ./Core/Src/gbt_packet.o ./Core/Src/gbt_packet.su ./Core/Src/gpio.cyclo ./Core/Src/gpio.d ./Core/Src/gpio.o ./Core/Src/gpio.su ./Core/Src/j1939.cyclo ./Core/Src/j1939.d ./Core/Src/j1939.o ./Core/Src/j1939.su ./Core/Src/main.cyclo ./Core/Src/main.d ./Core/Src/main.o ./Core/Src/main.su ./Core/Src/rgb_controller.cyclo ./Core/Src/rgb_controller.d ./Core/Src/rgb_controller.o ./Core/Src/rgb_controller.su ./Core/Src/rtc.cyclo ./Core/Src/rtc.d ./Core/Src/rtc.o ./Core/Src/rtc.su ./Core/Src/soft_rtc.cyclo ./Core/Src/soft_rtc.d ./Core/Src/soft_rtc.o ./Core/Src/soft_rtc.su ./Core/Src/stm32f1xx_hal_msp.cyclo ./Core/Src/stm32f1xx_hal_msp.d ./Core/Src/stm32f1xx_hal_msp.o ./Core/Src/stm32f1xx_hal_msp.su ./Core/Src/stm32f1xx_it.cyclo ./Core/Src/stm32f1xx_it.d ./Core/Src/stm32f1xx_it.o ./Core/Src/stm32f1xx_it.su ./Core/Src/syscalls.cyclo ./Core/Src/syscalls.d ./Core/Src/syscalls.o ./Core/Src/syscalls.su ./Core/Src/sysmem.cyclo ./Core/Src/sysmem.d ./Core/Src/sysmem.o ./Core/Src/sysmem.su ./Core/Src/system_stm32f1xx.cyclo ./Core/Src/system_stm32f1xx.d ./Core/Src/system_stm32f1xx.o ./Core/Src/system_stm32f1xx.su ./Core/Src/tim.cyclo ./Core/Src/tim.d ./Core/Src/tim.o ./Core/Src/tim.su ./Core/Src/usart.cyclo ./Core/Src/usart.d ./Core/Src/usart.o ./Core/Src/usart.su + -$(RM) ./Core/Src/adc.cyclo ./Core/Src/adc.d ./Core/Src/adc.o ./Core/Src/adc.su ./Core/Src/board.cyclo ./Core/Src/board.d ./Core/Src/board.o ./Core/Src/board.su ./Core/Src/can.cyclo ./Core/Src/can.d ./Core/Src/can.o ./Core/Src/can.su ./Core/Src/charger_gbt.cyclo ./Core/Src/charger_gbt.d ./Core/Src/charger_gbt.o ./Core/Src/charger_gbt.su ./Core/Src/connector.cyclo ./Core/Src/connector.d ./Core/Src/connector.o ./Core/Src/connector.su ./Core/Src/cp.cyclo ./Core/Src/cp.d ./Core/Src/cp.o ./Core/Src/cp.su ./Core/Src/debug.cyclo ./Core/Src/debug.d ./Core/Src/debug.o ./Core/Src/debug.su ./Core/Src/edcan_handler_user.cyclo ./Core/Src/edcan_handler_user.d ./Core/Src/edcan_handler_user.o ./Core/Src/edcan_handler_user.su ./Core/Src/gbt_packet.cyclo ./Core/Src/gbt_packet.d ./Core/Src/gbt_packet.o ./Core/Src/gbt_packet.su ./Core/Src/gpio.cyclo ./Core/Src/gpio.d ./Core/Src/gpio.o ./Core/Src/gpio.su ./Core/Src/j1939.cyclo ./Core/Src/j1939.d ./Core/Src/j1939.o ./Core/Src/j1939.su ./Core/Src/load.cyclo ./Core/Src/load.d ./Core/Src/load.o ./Core/Src/load.su ./Core/Src/main.cyclo ./Core/Src/main.d ./Core/Src/main.o ./Core/Src/main.su ./Core/Src/rgb_controller.cyclo ./Core/Src/rgb_controller.d ./Core/Src/rgb_controller.o ./Core/Src/rgb_controller.su ./Core/Src/rtc.cyclo ./Core/Src/rtc.d ./Core/Src/rtc.o ./Core/Src/rtc.su ./Core/Src/serial_control.cyclo ./Core/Src/serial_control.d ./Core/Src/serial_control.o ./Core/Src/serial_control.su ./Core/Src/serial_handler.cyclo ./Core/Src/serial_handler.d ./Core/Src/serial_handler.o ./Core/Src/serial_handler.su ./Core/Src/soft_rtc.cyclo ./Core/Src/soft_rtc.d ./Core/Src/soft_rtc.o ./Core/Src/soft_rtc.su ./Core/Src/stm32f1xx_hal_msp.cyclo ./Core/Src/stm32f1xx_hal_msp.d ./Core/Src/stm32f1xx_hal_msp.o ./Core/Src/stm32f1xx_hal_msp.su ./Core/Src/stm32f1xx_it.cyclo ./Core/Src/stm32f1xx_it.d ./Core/Src/stm32f1xx_it.o ./Core/Src/stm32f1xx_it.su ./Core/Src/syscalls.cyclo ./Core/Src/syscalls.d ./Core/Src/syscalls.o ./Core/Src/syscalls.su ./Core/Src/sysmem.cyclo ./Core/Src/sysmem.d ./Core/Src/sysmem.o ./Core/Src/sysmem.su ./Core/Src/system_stm32f1xx.cyclo ./Core/Src/system_stm32f1xx.d ./Core/Src/system_stm32f1xx.o ./Core/Src/system_stm32f1xx.su ./Core/Src/tim.cyclo ./Core/Src/tim.d ./Core/Src/tim.o ./Core/Src/tim.su ./Core/Src/usart.cyclo ./Core/Src/usart.d ./Core/Src/usart.o ./Core/Src/usart.su .PHONY: clean-Core-2f-Src diff --git a/Debug/Core/Src/usart.cyclo b/Debug/Core/Src/usart.cyclo index 73fb3cd..9b978c4 100644 --- a/Debug/Core/Src/usart.cyclo +++ b/Debug/Core/Src/usart.cyclo @@ -3,4 +3,4 @@ ../Core/Src/usart.c:91:6:MX_USART2_UART_Init 2 ../Core/Src/usart.c:120:6:MX_USART3_UART_Init 2 ../Core/Src/usart.c:148:6:HAL_UART_MspInit 5 -../Core/Src/usart.c:270:6:HAL_UART_MspDeInit 5 +../Core/Src/usart.c:273:6:HAL_UART_MspDeInit 5 diff --git a/Debug/objects.list b/Debug/objects.list index 512aeae..41948c0 100644 --- a/Debug/objects.list +++ b/Debug/objects.list @@ -3,14 +3,18 @@ "./Core/Src/can.o" "./Core/Src/charger_gbt.o" "./Core/Src/connector.o" +"./Core/Src/cp.o" "./Core/Src/debug.o" "./Core/Src/edcan_handler_user.o" "./Core/Src/gbt_packet.o" "./Core/Src/gpio.o" "./Core/Src/j1939.o" +"./Core/Src/load.o" "./Core/Src/main.o" "./Core/Src/rgb_controller.o" "./Core/Src/rtc.o" +"./Core/Src/serial_control.o" +"./Core/Src/serial_handler.o" "./Core/Src/soft_rtc.o" "./Core/Src/stm32f1xx_hal_msp.o" "./Core/Src/stm32f1xx_it.o" diff --git a/GBT_J1939_DEBUG_FLOW.md b/GBT_J1939_DEBUG_FLOW.md new file mode 100644 index 0000000..afdb146 --- /dev/null +++ b/GBT_J1939_DEBUG_FLOW.md @@ -0,0 +1,180 @@ +# GB/T + J1939 Debug Flow (CAN ExtId) + +Документ для ручного дебага обмена EV <-> EVSE по CAN (J1939 TP + short PGN). + +## 1) Базовая структура CAN Extended ID (29-bit) + +В проекте используется формула: + +- `ExtId = (priority << 26) | (PGN << 8) | (SA << 8) | DA` + +Где: +- `priority` — обычно `6` или `7` +- `PGN` — Parameter Group Number +- `SA` — Source Address +- `DA` — Destination Address + +Адреса в ваших прошивках: +- `EVSE (SE)` = `0x56` +- `EV` = `0xF4` + +Примеры: +- `0x181056F4` -> short PGN `0x1000` (BCL), `SA=0x56`, `DA=0xF4` +- `0x1CEC56F4` -> TP.CM от `0x56` к `0xF4` +- `0x1CECF456` -> TP.CM от `0xF4` к `0x56` +- `0x1CEB56F4` -> TP.DT от `0x56` к `0xF4` + + +## 2) Какие PGN short, какие TP + +Short (<=8 байт, один CAN кадр): +- `0x0900` BRO +- `0x0A00` CRO +- `0x1000` BCL (5 байт) +- `0x1200` CCS +- `0x1300` BSM (7 байт) +- `0x1A00` CST + +Через TP (>8 байт): +- `0x0200` BRM (49 байт) +- `0x0600` BCP (13 байт) +- `0x1100` BCS (9 байт) + + +## 3) Нормальная последовательность (высокоуровнево) + +1. Handshake/recognition: +- CHM/CRM/BRM/BCP/CML/BRO/CRO + +2. Переход в заряд: +- EVSE `S8 -> S9` +- EV начинает слать BCL/BSM/BCS +- EVSE принимает BCL и переходит `S9 -> S10` + +3. Во время зарядки: +- EV регулярно шлет: + - BCL (short) + - BSM (short) + - BCS (TP, `PGN=0x1100`) +- EVSE регулярно шлет CCS + + +## 4) Нормальная TP-сессия для BCS (`PGN=0x1100`, size=9, packets=2) + +### Шаг 1: RTS (originator -> responder) + +ID: +- от EV к EVSE: `1CEC F4 56` (`0x1CECF456`) + +Data (TP.CM_RTS): +- `byte0 = 0x10` (RTS) +- `byte1..2 = total_size` (LSB/MSB), для BCS: `0x09 0x00` +- `byte3 = total_packets`, для BCS: `0x02` +- `byte4 = max_packets_per_CTS` (часто `0x02`) +- `byte5..7 = PGN` в little-endian (`00 11 00` для `0x1100`) + +### Шаг 2: CTS (responder -> originator) + +ID: +- от EVSE к EV: `1CEC 56 F4` (`0x1CEC56F4`) + +Data (TP.CM_CTS): +- `byte0 = 0x11` (CTS) +- `byte1 = allowed_packet_count` +- `byte2 = next_packet_number` (обычно `1` для новой сессии) +- `byte3..4 = 0xFF` +- `byte5..7 = PGN` (`00 11 00`) + +### Шаг 3: DT (originator -> responder) + +ID: +- `1CEB F4 56` (EV -> EVSE) + +Data (TP.DT): +- `byte0 = seq` (`1`, потом `2`) +- `byte1..7 = payload chunk` + +Для 9 байт: +- DT#1 несет первые 7 байт +- DT#2 несет оставшиеся 2 байта + заполнение `0xFF` + +### Шаг 4: ACK (responder -> originator) + +ID: +- `1CEC 56 F4` (EVSE -> EV) + +Data (TP.CM_EndOfMsgACK): +- `byte0 = 0x13` (ACK) +- `byte1..2 = total_size` (`09 00`) +- `byte3 = total_packets` (`02`) +- `byte4 = 0xFF` +- `byte5..7 = PGN` (`00 11 00`) + + +## 5) Как понять по логу, что сессия "правильная" + +Для каждого `RTS(0x1100)` должен быть полный шаблон: +- `RTS` -> `CTS` -> `DT #1` -> `DT #2` -> `ACK` + +Если есть `RTS`, но нет `CTS`: +- проблема на стороне responder (EVSE) TX/фильтр/перегрузка + +Если есть `CTS`, но нет `DT`: +- проблема на стороне originator (EV) RX/парсинг/состояние + +Если есть `DT`, но нет `ACK`: +- проблема на стороне responder reassembly/timeout + + +## 6) Поля основных GB/T пакетов (payload) + +### BCL (`PGN 0x1000`, short, 5 bytes) +Структура: +- `requestedVoltage` (`uint16`, 0.1V/bit) +- `requestedCurrent` (`uint16`, 0.1A/bit, в вашем коде может интерпретироваться как `4000 - value`) +- `chargingMode` (`uint8`, `0x01` CV, `0x02` CC) + +### BCS (`PGN 0x1100`, TP, 9 bytes) +Структура: +- `measuredChargingVoltage` (`uint16`) +- `measuredChargingCurrent` (`uint16`) +- `highestVoltageOfBatteryCell` (`uint16`) +- `currentChargeState` (`uint8`) +- `estimatedRemainingChargingTime` (`uint16`) + +### BSM (`PGN 0x1300`, short, 7 bytes) +Структура: +- max/temperature индексы и статусы: + - `singleBatteryHighestVoltageSerNo` + - `batteryHighestTemp` + - `batteryHighestTempSerNo` + - `batteryLowestTemp` + - `batteryLowestTempSerNo` + - `batteryCellVoltageState` + - `batteryStatus` + + +## 7) Тайминги TP из J1939 (важное для дебага) + +Ключевые reference значения: +- `Tr = 200 ms` +- `Th = 500 ms` +- `T1 = 750 ms` +- `T2 = 1250 ms` +- `T3 = 1250 ms` +- `T4 = 1050 ms` + +Практически: +- если responder выдал CTS, originator не должен задерживать DT дольше допусков +- если originator отправил RTS/DT, responder должен ответить CTS/ACK в окне таймаутов + + +## 8) Мини-чеклист при "вдруг стопнулось" + +1. Найти последний `RTS` по `PGN=0x1100`. +2. Проверить, был ли `CTS` на шине с тем же `PGN`. +3. Проверить наличие `DT#1/#2`. +4. Проверить `ACK`. +5. Если цепочка оборвалась: + - зафиксировать на каком шаге; + - сопоставить с UART логом state machine (`S9/S10`, `TP timeout`, `BCS timeout`). diff --git a/GbTModuleEV.ioc b/GbTModuleEV.ioc index c68fe63..d7d166e 100755 --- a/GbTModuleEV.ioc +++ b/GbTModuleEV.ioc @@ -37,69 +37,76 @@ Mcu.CPN=STM32F107VCT6 Mcu.Family=STM32F1 Mcu.IP0=ADC1 Mcu.IP1=CAN1 -Mcu.IP10=USART2 -Mcu.IP11=USART3 +Mcu.IP10=USART1 +Mcu.IP11=USART2 +Mcu.IP12=USART3 Mcu.IP2=CAN2 Mcu.IP3=NVIC Mcu.IP4=RCC Mcu.IP5=RTC Mcu.IP6=SYS -Mcu.IP7=TIM4 -Mcu.IP8=UART5 -Mcu.IP9=USART1 -Mcu.IPNb=12 +Mcu.IP7=TIM3 +Mcu.IP8=TIM4 +Mcu.IP9=UART5 +Mcu.IPNb=13 Mcu.Name=STM32F107V(B-C)Tx Mcu.Package=LQFP100 Mcu.Pin0=PC14-OSC32_IN Mcu.Pin1=PC15-OSC32_OUT -Mcu.Pin10=PB0 -Mcu.Pin11=PB1 -Mcu.Pin12=PE7 -Mcu.Pin13=PE8 -Mcu.Pin14=PE9 -Mcu.Pin15=PE10 -Mcu.Pin16=PE11 -Mcu.Pin17=PE12 -Mcu.Pin18=PE14 -Mcu.Pin19=PD13 +Mcu.Pin10=PA5 +Mcu.Pin11=PA6 +Mcu.Pin12=PA7 +Mcu.Pin13=PC4 +Mcu.Pin14=PC5 +Mcu.Pin15=PB0 +Mcu.Pin16=PB1 +Mcu.Pin17=PE7 +Mcu.Pin18=PE8 +Mcu.Pin19=PE9 Mcu.Pin2=OSC_IN -Mcu.Pin20=PD14 -Mcu.Pin21=PD15 -Mcu.Pin22=PA9 -Mcu.Pin23=PA10 -Mcu.Pin24=PA13 -Mcu.Pin25=PA14 -Mcu.Pin26=PA15 -Mcu.Pin27=PC10 -Mcu.Pin28=PC11 -Mcu.Pin29=PC12 +Mcu.Pin20=PE10 +Mcu.Pin21=PE11 +Mcu.Pin22=PE12 +Mcu.Pin23=PE14 +Mcu.Pin24=PD13 +Mcu.Pin25=PD14 +Mcu.Pin26=PD15 +Mcu.Pin27=PA9 +Mcu.Pin28=PA10 +Mcu.Pin29=PA13 Mcu.Pin3=OSC_OUT -Mcu.Pin30=PD0 -Mcu.Pin31=PD1 -Mcu.Pin32=PD2 -Mcu.Pin33=PD3 -Mcu.Pin34=PD4 -Mcu.Pin35=PD5 -Mcu.Pin36=PD6 -Mcu.Pin37=PD7 -Mcu.Pin38=PB3 -Mcu.Pin39=PB4 -Mcu.Pin4=PA1 -Mcu.Pin40=PB5 -Mcu.Pin41=PB6 -Mcu.Pin42=PB7 -Mcu.Pin43=PB8 -Mcu.Pin44=PB9 -Mcu.Pin45=PE1 -Mcu.Pin46=VP_RTC_VS_RTC_Activate -Mcu.Pin47=VP_SYS_VS_Systick -Mcu.Pin48=VP_TIM4_VS_ClockSourceINT -Mcu.Pin5=PA2 -Mcu.Pin6=PA3 -Mcu.Pin7=PA6 -Mcu.Pin8=PC4 -Mcu.Pin9=PC5 -Mcu.PinsNb=49 +Mcu.Pin30=PA14 +Mcu.Pin31=PA15 +Mcu.Pin32=PC10 +Mcu.Pin33=PC11 +Mcu.Pin34=PC12 +Mcu.Pin35=PD0 +Mcu.Pin36=PD1 +Mcu.Pin37=PD2 +Mcu.Pin38=PD3 +Mcu.Pin39=PD4 +Mcu.Pin4=PC2 +Mcu.Pin40=PD5 +Mcu.Pin41=PD6 +Mcu.Pin42=PD7 +Mcu.Pin43=PB3 +Mcu.Pin44=PB4 +Mcu.Pin45=PB5 +Mcu.Pin46=PB6 +Mcu.Pin47=PB7 +Mcu.Pin48=PB8 +Mcu.Pin49=PB9 +Mcu.Pin5=PC3 +Mcu.Pin50=PE1 +Mcu.Pin51=VP_RTC_VS_RTC_Activate +Mcu.Pin52=VP_SYS_VS_Systick +Mcu.Pin53=VP_TIM3_VS_ClockSourceINT +Mcu.Pin54=VP_TIM4_VS_ClockSourceINT +Mcu.Pin6=PA1 +Mcu.Pin7=PA2 +Mcu.Pin8=PA3 +Mcu.Pin9=PA4 +Mcu.PinsNb=55 Mcu.ThirdPartyNb=0 Mcu.UserConstants= Mcu.UserName=STM32F107VCTx @@ -118,6 +125,8 @@ NVIC.PendSV_IRQn=true\:0\:0\:false\:false\:true\:false\:false\:false NVIC.PriorityGroup=NVIC_PRIORITYGROUP_4 NVIC.SVCall_IRQn=true\:0\:0\:false\:false\:true\:false\:false\:false NVIC.SysTick_IRQn=true\:15\:0\:false\:false\:true\:false\:true\:false +NVIC.TIM3_IRQn=true\:0\:0\:false\:false\:true\:true\:true\:true +NVIC.UART5_IRQn=true\:0\:0\:false\:false\:true\:true\:true\:true NVIC.USART2_IRQn=true\:0\:0\:false\:false\:true\:true\:true\:true NVIC.UsageFault_IRQn=true\:0\:0\:false\:false\:true\:false\:false\:false OSC_IN.Mode=HSE-External-Oscillator @@ -147,10 +156,20 @@ PA2.Locked=true PA2.Signal=GPIO_Input PA3.Locked=true PA3.Signal=ADCx_IN3 +PA4.Locked=true +PA4.Signal=ADCx_IN4 +PA5.GPIOParameters=GPIO_Label +PA5.GPIO_Label=CP_STATE_C +PA5.Locked=true +PA5.Signal=GPIO_Output PA6.GPIOParameters=GPIO_Label PA6.GPIO_Label=ADC_CC1 PA6.Locked=true PA6.Signal=ADCx_IN6 +PA7.GPIOParameters=GPIO_Label +PA7.GPIO_Label=CP_PWM +PA7.Locked=true +PA7.Signal=S_TIM3_CH2 PA9.Locked=true PA9.Mode=Asynchronous PA9.Signal=USART1_TX @@ -196,6 +215,14 @@ PC14-OSC32_IN.Mode=LSE-External-Oscillator PC14-OSC32_IN.Signal=RCC_OSC32_IN PC15-OSC32_OUT.Mode=LSE-External-Oscillator PC15-OSC32_OUT.Signal=RCC_OSC32_OUT +PC2.GPIOParameters=GPIO_Label +PC2.GPIO_Label=CP_STATE_F +PC2.Locked=true +PC2.Signal=GPIO_Output +PC3.GPIOParameters=GPIO_Label +PC3.GPIO_Label=CP_RELAY +PC3.Locked=true +PC3.Signal=GPIO_Output PC4.GPIOParameters=GPIO_Label PC4.GPIO_Label=LOCK_A PC4.Locked=true @@ -246,11 +273,11 @@ PE10.GPIO_Label=RELAY3 PE10.Locked=true PE10.Signal=GPIO_Output PE11.GPIOParameters=GPIO_Label -PE11.GPIO_Label=RELAY2 +PE11.GPIO_Label=RELAY4 PE11.Locked=true PE11.Signal=GPIO_Output PE12.GPIOParameters=GPIO_Label -PE12.GPIO_Label=RELAY1 +PE12.GPIO_Label=RELAY5 PE12.Locked=true PE12.Signal=GPIO_Output PE14.GPIOParameters=GPIO_Label @@ -262,11 +289,11 @@ PE7.GPIO_Label=IN0 PE7.Locked=true PE7.Signal=GPIO_Input PE8.GPIOParameters=GPIO_Label -PE8.GPIO_Label=RELAY5 +PE8.GPIO_Label=RELAY1 PE8.Locked=true PE8.Signal=GPIO_Output PE9.GPIOParameters=GPIO_Label -PE9.GPIO_Label=RELAY4 +PE9.GPIO_Label=RELAY2 PE9.Locked=true PE9.Signal=GPIO_Output PinOutPanel.RotationAngle=-90 @@ -285,7 +312,7 @@ ProjectManager.FreePins=false ProjectManager.HalAssertFull=false ProjectManager.HeapSize=0x200 ProjectManager.KeepUserCode=true -ProjectManager.LastFirmware=true +ProjectManager.LastFirmware=false ProjectManager.LibraryCopy=1 ProjectManager.MainLocation=Core/Src ProjectManager.NoMain=false @@ -301,7 +328,7 @@ ProjectManager.ToolChainLocation= ProjectManager.UAScriptAfterPath= ProjectManager.UAScriptBeforePath= ProjectManager.UnderRoot=true -ProjectManager.functionlistsort=1-SystemClock_Config-RCC-false-HAL-false,2-MX_GPIO_Init-GPIO-false-HAL-true,3-MX_ADC1_Init-ADC1-false-HAL-true,4-MX_CAN1_Init-CAN1-false-HAL-true,5-MX_CAN2_Init-CAN2-false-HAL-true,6-MX_RTC_Init-RTC-false-HAL-true,7-MX_TIM4_Init-TIM4-false-HAL-true,8-MX_USART2_UART_Init-USART2-false-HAL-true,9-MX_UART5_Init-UART5-false-HAL-true,10-MX_USART1_UART_Init-USART1-false-HAL-true,11-MX_USART3_UART_Init-USART3-false-HAL-true +ProjectManager.functionlistsort=1-SystemClock_Config-RCC-false-HAL-false,2-MX_GPIO_Init-GPIO-false-HAL-true,3-MX_ADC1_Init-ADC1-false-HAL-true,4-MX_CAN1_Init-CAN1-false-HAL-true,5-MX_CAN2_Init-CAN2-false-HAL-true,6-MX_RTC_Init-RTC-false-HAL-true,7-MX_TIM4_Init-TIM4-false-HAL-true,8-MX_USART2_UART_Init-USART2-false-HAL-true,9-MX_UART5_Init-UART5-false-HAL-true,10-MX_USART1_UART_Init-USART1-false-HAL-true,11-MX_USART3_UART_Init-USART3-false-HAL-true,12-MX_TIM3_Init-TIM3-false-HAL-true RCC.ADCFreqValue=12000000 RCC.ADCPresc=RCC_ADCPCLK2_DIV6 RCC.AHBFreq_Value=72000000 @@ -338,28 +365,37 @@ RCC.USBFreq_Value=48000000 RCC.VCOOutput2Freq_Value=8000000 SH.ADCx_IN3.0=ADC1_IN3,IN3 SH.ADCx_IN3.ConfNb=1 +SH.ADCx_IN4.0=ADC1_IN4,IN4 +SH.ADCx_IN4.ConfNb=1 SH.ADCx_IN6.0=ADC1_IN6 SH.ADCx_IN6.ConfNb=1 SH.ADCx_IN8.0=ADC1_IN8,IN8 SH.ADCx_IN8.ConfNb=1 SH.ADCx_IN9.0=ADC1_IN9,IN9 SH.ADCx_IN9.ConfNb=1 +SH.S_TIM3_CH2.0=TIM3_CH2,Input_Capture2_from_TI2 +SH.S_TIM3_CH2.ConfNb=1 SH.S_TIM4_CH2.0=TIM4_CH2,PWM Generation2 CH2 SH.S_TIM4_CH2.ConfNb=1 SH.S_TIM4_CH3.0=TIM4_CH3,PWM Generation3 CH3 SH.S_TIM4_CH3.ConfNb=1 SH.S_TIM4_CH4.0=TIM4_CH4,PWM Generation4 CH4 SH.S_TIM4_CH4.ConfNb=1 +TIM3.Channel-Input_Capture2_from_TI2=TIM_CHANNEL_2 +TIM3.ICFilter_CH2=4 +TIM3.IPParameters=Channel-Input_Capture2_from_TI2,ICFilter_CH2 TIM4.Channel-PWM\ Generation2\ CH2=TIM_CHANNEL_2 TIM4.Channel-PWM\ Generation3\ CH3=TIM_CHANNEL_3 TIM4.Channel-PWM\ Generation4\ CH4=TIM_CHANNEL_4 TIM4.IPParameters=Channel-PWM Generation2 CH2,Channel-PWM Generation3 CH3,Channel-PWM Generation4 CH4,Prescaler,Period TIM4.Period=100 TIM4.Prescaler=720 -UART5.IPParameters=VirtualMode,Mode +UART5.BaudRate=9600 +UART5.IPParameters=VirtualMode,Mode,BaudRate UART5.Mode=MODE_RX UART5.VirtualMode=Asynchronous -USART1.IPParameters=VirtualMode +USART1.BaudRate=460800 +USART1.IPParameters=VirtualMode,BaudRate USART1.VirtualMode=VM_ASYNC USART2.IPParameters=VirtualMode USART2.VirtualMode=VM_ASYNC @@ -369,6 +405,8 @@ VP_RTC_VS_RTC_Activate.Mode=RTC_Enabled VP_RTC_VS_RTC_Activate.Signal=RTC_VS_RTC_Activate VP_SYS_VS_Systick.Mode=SysTick VP_SYS_VS_Systick.Signal=SYS_VS_Systick +VP_TIM3_VS_ClockSourceINT.Mode=Internal +VP_TIM3_VS_ClockSourceINT.Signal=TIM3_VS_ClockSourceINT VP_TIM4_VS_ClockSourceINT.Mode=Internal VP_TIM4_VS_ClockSourceINT.Signal=TIM4_VS_ClockSourceINT board=custom diff --git a/SERIAL_PROTOCOL.md b/SERIAL_PROTOCOL.md new file mode 100644 index 0000000..99ee770 --- /dev/null +++ b/SERIAL_PROTOCOL.md @@ -0,0 +1,168 @@ +# Serial protocol (GbTModuleEV) + +Актуальная версия протокола для `USART2` (binary packet + CRC32). + +## 1. Транспорт и формат пакета + +- Интерфейс: `USART2` +- Скорость/параметры UART: задаются в CubeMX (`usart.c`) +- Направление (RS485 DIR): управляется прошивкой через `USART2_DIR` + +Формат **команды от хоста**: + +1. `command` (1 byte) +2. `argument` (`N` bytes, может быть 0) +3. `crc32` (4 bytes, little-endian) по данным `command + argument` + +Формат **ответа от устройства**: + +1. `response_code` (1 byte) — обычно код ответа или код команды для data-response +2. `payload` (`N` bytes, может быть 0) +3. `crc32` (4 bytes, little-endian) по данным `response_code + payload` + +### CRC + +- CRC-32 (software), полином: `0xEDB88320` +- Init: `0xFFFFFFFF` +- Final XOR: `0xFFFFFFFF` +- Порядок CRC-байтов в пакете: little-endian + +### Коды ответа + +- `0x12` = `RESP_SUCCESS` +- `0x13` = `RESP_FAILED` +- `0x14` = `RESP_INVALID` (ошибка формата/CRC) + +--- + +## 2. Команды (host -> device) + +## 2.1 Read-only + +- `0x01` `CMD_GET_INFO` + - Arg: none + - Response: `response_code = 0x01`, payload = `InfoPacket_t` + +- `0x02` `CMD_GET_GBT_STATUS` + - Arg: none + - Response: `response_code = 0x02`, payload = `GBT_MonitorPacket_t` + +- `0x03` `CMD_GET_CCS_STATUS` + - Arg: none + - Response: `response_code = 0x03`, payload = `CCS_MonitorPacket_t` + +## 2.2 GBT control + +- `0x10` `CMD_GBT_CC_ENABLE` + - Arg: `uint8_t enable` (`0/1`) + - Action: `RELAY_CC` write + - Ack: `RESP_SUCCESS/RESP_FAILED` + +- `0x11` `CMD_GBT_STOP` + - Arg: none + - Action: `CONN[0].connControl = CMD_STOP` + - Ack: `RESP_SUCCESS/RESP_FAILED` + +- `0x12` `CMD_GBT_SET_SOC` + - Arg: `uint8_t soc` + - Action: `CONN[0].SOC = soc` + - Ack: `RESP_SUCCESS/RESP_FAILED` + +- `0x13` `CMD_GBT_SET_REQUEST` + - Arg: `EvSetLimits_t` + - `uint16_t requestedVoltage` + - `uint16_t requestedCurrent` + - Action: запись в `CONN[0].RequestedVoltage/RequestedCurrent` + - Ack: `RESP_SUCCESS/RESP_FAILED` + +- `0x14` `CMD_GBT_ENABLE_LOAD` + - Arg: `uint8_t enable` (`0/1`) + - Action: + - `CONN[0].enableLoad` + - `CONN[0].ContactorEnabled` + - Ack: `RESP_SUCCESS/RESP_FAILED` + +- `0x18` `CMD_GBT_SET_VIN` + - Arg: `uint8_t vin[17]` + - Action: копирование в `GBT_EVInfo.EVIN` + - Ack: `RESP_SUCCESS/RESP_FAILED` + +## 2.3 CCS control + +- `0x20` `CMD_CCS_SET_STATE` + - Arg: `uint8_t cp_state_enum` + - Action: `cp_state = (CP_State_t)arg` + - Ack: `RESP_SUCCESS/RESP_FAILED` + +- `0x24` `CMD_CCS_ENABLE_LOAD` + - Arg: `uint8_t enable` (`0/1`) + - Action: + - `CONN[1].enableLoad` + - `CONN[1].ContactorEnabled` + - Ack: `RESP_SUCCESS/RESP_FAILED` + +--- + +## 3. Payload structures (packed) + +Все структуры передаются как `__attribute__((packed))`, little-endian для multi-byte полей. + +### 3.1 `InfoPacket_t` (GET_INFO) + +- `uint16_t serialNumber` +- `uint8_t boardVersion` +- `uint8_t stationType` +- `uint16_t fw_version_major` +- `uint16_t fw_version_minor` +- `uint16_t fw_version_patch` + +### 3.2 `GBT_MonitorPacket_t` (GET_GBT_STATUS) + +- `uint8_t connector_type` (`0x01`) +- `uint16_t requestedVoltage` +- `uint16_t requestedCurrent` +- `uint16_t measuredVoltageSE` +- `uint16_t measuredCurrentSE` +- `uint16_t measuredVoltage` +- `uint16_t measuredCurrent` +- `uint8_t cc_enabled` +- `uint8_t contactorEnabled` +- `CONN_Error_t chargingError` (`uint8_t`) +- `uint8_t EvseConnected` +- `uint8_t soc` +- `uint8_t vin[17]` +- `uint8_t cc_state` +- `CONN_State_t connState` (`uint8_t`) + +### 3.3 `CCS_MonitorPacket_t` (GET_CCS_STATUS) + +- `uint8_t connector_type` (`0x02`) +- `uint16_t measuredVoltage` +- `uint16_t measuredCurrent` +- `uint8_t cp_enabled` +- `uint8_t contactorEnabled` +- `CONN_Error_t chargingError` (`uint8_t`) +- `uint8_t EvseConnected` +- `uint8_t soc` +- `uint8_t cp_state` +- `uint8_t cp_pwm_duty` +- `CONN_State_t connState` (`uint8_t`) + +--- + +## 4. Валидация команд + +- Для каждой команды проверяется `argument_length` (по фактическому размеру аргумента). +- Если длина неверная: ответ `RESP_FAILED`. +- Если пакет не проходит parse/CRC: ответ `RESP_INVALID`. + +--- + +## 5. Пример (логический) + +`CMD_GBT_SET_SOC = 0x12`, `soc = 80`: + +- TX body: `[0x12, 0x50]` +- TX full: `[0x12, 0x50, crc0, crc1, crc2, crc3]` +- RX (ack): `[0x12, crc0, crc1, crc2, crc3]` +