Binary files /Users/colorbass/STM32CubeIDE/workspace_1.12.0/CCSModuleSW30Web/Core/.DS_Store and /Users/colorbass/STM32CubeIDE/workspace_1.12.0/fork/CCSModuleSW30Web/Core/.DS_Store differ
diff -ruN /Users/colorbass/STM32CubeIDE/workspace_1.12.0/CCSModuleSW30Web/Core/Inc/adc.h /Users/colorbass/STM32CubeIDE/workspace_1.12.0/fork/CCSModuleSW30Web/Core/Inc/adc.h
--- /Users/colorbass/STM32CubeIDE/workspace_1.12.0/CCSModuleSW30Web/Core/Inc/adc.h	2024-07-12 12:59:02
+++ /Users/colorbass/STM32CubeIDE/workspace_1.12.0/fork/CCSModuleSW30Web/Core/Inc/adc.h	2026-05-04 19:45:24
@@ -1,52 +1,63 @@
-/* USER CODE BEGIN Header */
-/**
-  ******************************************************************************
-  * @file    adc.h
-  * @brief   This file contains all the function prototypes for
-  *          the adc.c file
-  ******************************************************************************
-  * @attention
-  *
-  * Copyright (c) 2024 STMicroelectronics.
-  * All rights reserved.
-  *
-  * This software is licensed under terms that can be found in the LICENSE file
-  * in the root directory of this software component.
-  * If no LICENSE file comes with this software, it is provided AS-IS.
-  *
-  ******************************************************************************
-  */
-/* USER CODE END Header */
-/* Define to prevent recursive inclusion -------------------------------------*/
-#ifndef __ADC_H__
-#define __ADC_H__
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/* Includes ------------------------------------------------------------------*/
-#include "main.h"
-
-/* USER CODE BEGIN Includes */
-
-/* USER CODE END Includes */
-
-extern ADC_HandleTypeDef hadc1;
-
-/* USER CODE BEGIN Private defines */
-
-/* USER CODE END Private defines */
-
-void MX_ADC1_Init(void);
-
-/* USER CODE BEGIN Prototypes */
-
-/* USER CODE END Prototypes */
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* __ADC_H__ */
-
+/* USER CODE BEGIN Header */
+/**
+  ******************************************************************************
+  * @file    adc.h
+  * @brief   This file contains all the function prototypes for
+  *          the adc.c file
+  ******************************************************************************
+  * @attention
+  *
+  * Copyright (c) 2024 STMicroelectronics.
+  * All rights reserved.
+  *
+  * This software is licensed under terms that can be found in the LICENSE file
+  * in the root directory of this software component.
+  * If no LICENSE file comes with this software, it is provided AS-IS.
+  *
+  ******************************************************************************
+  */
+/* USER CODE END Header */
+/* Define to prevent recursive inclusion -------------------------------------*/
+#ifndef __ADC_H__
+#define __ADC_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Includes ------------------------------------------------------------------*/
+#include "main.h"
+
+/* USER CODE BEGIN Includes */
+#include <stdint.h>
+
+/* USER CODE END Includes */
+
+extern ADC_HandleTypeDef hadc1;
+
+/* USER CODE BEGIN Private defines */
+typedef struct {
+  uint16_t in3_raw;         /* Rank1: ADC_CHANNEL_3  */
+  uint16_t cp_raw;          /* Rank2: ADC_CHANNEL_4  */
+  uint16_t ntc1_raw;        /* Rank3: ADC_CHANNEL_8  */
+  uint16_t ntc2_raw;        /* Rank4: ADC_CHANNEL_9  */
+  uint16_t temp_sensor_raw; /* Rank5: ADC_CHANNEL_TEMPSENSOR */
+  uint16_t vrefint_raw;     /* Rank6: ADC_CHANNEL_VREFINT */
+} ADC_ScanData_t;
+extern volatile ADC_ScanData_t adc_data;
+
+/* USER CODE END Private defines */
+
+void MX_ADC1_Init(void);
+
+/* USER CODE BEGIN Prototypes */
+void ADC_ScanStart(void);
+
+/* USER CODE END Prototypes */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __ADC_H__ */
+
diff -ruN /Users/colorbass/STM32CubeIDE/workspace_1.12.0/CCSModuleSW30Web/Core/Inc/board.h /Users/colorbass/STM32CubeIDE/workspace_1.12.0/fork/CCSModuleSW30Web/Core/Inc/board.h
--- /Users/colorbass/STM32CubeIDE/workspace_1.12.0/CCSModuleSW30Web/Core/Inc/board.h	2026-04-28 19:15:10
+++ /Users/colorbass/STM32CubeIDE/workspace_1.12.0/fork/CCSModuleSW30Web/Core/Inc/board.h	2026-04-03 18:20:51
@@ -55,8 +55,7 @@
 	uint8_t stationType;        // Байт 4: тип станции
 	uint8_t boardVersion;       // Байт 5: версия платы
 	uint8_t addrEdcan;          // Байт 6: адрес EDCAN
-	uint8_t maxPower;          // Байт 7: максимальная мощность станции (5кВт/bit)
-	uint8_t reserved[56];       // Байты 8-63: зарезервированы
+	uint8_t reserved[57];       // Байты 7-63: зарезервированы
 } InfoBlock_t;
 
 extern InfoBlock_t *InfoBlock;
diff -ruN /Users/colorbass/STM32CubeIDE/workspace_1.12.0/CCSModuleSW30Web/Core/Inc/dma.h /Users/colorbass/STM32CubeIDE/workspace_1.12.0/fork/CCSModuleSW30Web/Core/Inc/dma.h
--- /Users/colorbass/STM32CubeIDE/workspace_1.12.0/CCSModuleSW30Web/Core/Inc/dma.h	1970-01-01 03:00:00
+++ /Users/colorbass/STM32CubeIDE/workspace_1.12.0/fork/CCSModuleSW30Web/Core/Inc/dma.h	2026-05-04 17:27:13
@@ -0,0 +1,52 @@
+/* USER CODE BEGIN Header */
+/**
+  ******************************************************************************
+  * @file    dma.h
+  * @brief   This file contains all the function prototypes for
+  *          the dma.c file
+  ******************************************************************************
+  * @attention
+  *
+  * Copyright (c) 2026 STMicroelectronics.
+  * All rights reserved.
+  *
+  * This software is licensed under terms that can be found in the LICENSE file
+  * in the root directory of this software component.
+  * If no LICENSE file comes with this software, it is provided AS-IS.
+  *
+  ******************************************************************************
+  */
+/* USER CODE END Header */
+/* Define to prevent recursive inclusion -------------------------------------*/
+#ifndef __DMA_H__
+#define __DMA_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Includes ------------------------------------------------------------------*/
+#include "main.h"
+
+/* DMA memory to memory transfer handles -------------------------------------*/
+
+/* USER CODE BEGIN Includes */
+
+/* USER CODE END Includes */
+
+/* USER CODE BEGIN Private defines */
+
+/* USER CODE END Private defines */
+
+void MX_DMA_Init(void);
+
+/* USER CODE BEGIN Prototypes */
+
+/* USER CODE END Prototypes */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __DMA_H__ */
+
diff -ruN /Users/colorbass/STM32CubeIDE/workspace_1.12.0/CCSModuleSW30Web/Core/Inc/main.h /Users/colorbass/STM32CubeIDE/workspace_1.12.0/fork/CCSModuleSW30Web/Core/Inc/main.h
--- /Users/colorbass/STM32CubeIDE/workspace_1.12.0/CCSModuleSW30Web/Core/Inc/main.h	2026-04-08 12:11:02
+++ /Users/colorbass/STM32CubeIDE/workspace_1.12.0/fork/CCSModuleSW30Web/Core/Inc/main.h	2026-05-04 20:04:46
@@ -43,7 +43,7 @@
 /* USER CODE BEGIN EC */
 #define FW_VERSION_MAJOR 1
 #define FW_VERSION_MINOR 0
-#define FW_VERSION_PATCH 10
+#define FW_VERSION_PATCH 15
 /* USER CODE END EC */
 
 /* Exported macro ------------------------------------------------------------*/
@@ -59,6 +59,8 @@
 /* USER CODE END EFP */
 
 /* Private defines -----------------------------------------------------------*/
+#define DBG1_Pin GPIO_PIN_2
+#define DBG1_GPIO_Port GPIOC
 #define RELAY_CP_Pin GPIO_PIN_3
 #define RELAY_CP_GPIO_Port GPIOC
 #define IN_SW0_Pin GPIO_PIN_1
@@ -67,6 +69,10 @@
 #define IN_SW1_GPIO_Port GPIOA
 #define CP_ADC_Pin GPIO_PIN_4
 #define CP_ADC_GPIO_Port GPIOA
+#define DBG2_Pin GPIO_PIN_5
+#define DBG2_GPIO_Port GPIOA
+#define DBG3_Pin GPIO_PIN_6
+#define DBG3_GPIO_Port GPIOA
 #define CP_PWM_Pin GPIO_PIN_7
 #define CP_PWM_GPIO_Port GPIOA
 #define LOCK_A_Pin GPIO_PIN_4
@@ -91,6 +97,10 @@
 #define RELAY5_GPIO_Port GPIOE
 #define AC_OK_Pin GPIO_PIN_14
 #define AC_OK_GPIO_Port GPIOE
+#define DBG5_Pin GPIO_PIN_10
+#define DBG5_GPIO_Port GPIOB
+#define DBG4_Pin GPIO_PIN_11
+#define DBG4_GPIO_Port GPIOB
 #define RELAY_CC_Pin GPIO_PIN_15
 #define RELAY_CC_GPIO_Port GPIOA
 #define RELAY_DC_Pin GPIO_PIN_3
diff -ruN /Users/colorbass/STM32CubeIDE/workspace_1.12.0/CCSModuleSW30Web/Core/Inc/psu_control.h /Users/colorbass/STM32CubeIDE/workspace_1.12.0/fork/CCSModuleSW30Web/Core/Inc/psu_control.h
--- /Users/colorbass/STM32CubeIDE/workspace_1.12.0/CCSModuleSW30Web/Core/Inc/psu_control.h	2026-04-10 11:09:25
+++ /Users/colorbass/STM32CubeIDE/workspace_1.12.0/fork/CCSModuleSW30Web/Core/Inc/psu_control.h	2026-04-03 18:20:51
@@ -88,7 +88,6 @@
 	// Дополнительные параметры для одного модуля DC30
 	uint32_t power_limit;    // лимит мощности [кВт]
 	uint8_t  hv_mode;        // HV-режим (ограничение напряжения)
-	uint32_t hv_tick;        // таймер для задержки входа в HV-режим
 
 	uint32_t tempAmbient;    // температура окружающего воздуха (из PSU_04)
 	union { uint8_t raw; PSU_Status0_t bits; } status0;  // modularForm0
diff -ruN /Users/colorbass/STM32CubeIDE/workspace_1.12.0/CCSModuleSW30Web/Core/Inc/serial.h /Users/colorbass/STM32CubeIDE/workspace_1.12.0/fork/CCSModuleSW30Web/Core/Inc/serial.h
--- /Users/colorbass/STM32CubeIDE/workspace_1.12.0/CCSModuleSW30Web/Core/Inc/serial.h	2026-04-13 20:01:45
+++ /Users/colorbass/STM32CubeIDE/workspace_1.12.0/fork/CCSModuleSW30Web/Core/Inc/serial.h	2026-04-26 21:15:56
@@ -11,15 +11,14 @@
 void CCS_SendEmergencyStop(void);
 void CCS_SendStart(void);
 void CCS_RxEventCallback(UART_HandleTypeDef *huart, uint16_t size);
-void CCS_RxArm(void);
+void HAL_UART_ErrorCallback(UART_HandleTypeDef *huart);
 
 typedef enum {
-    CCS_UNKNOWN = 0,
-    CCS_DISABLED = 1,
-    CCS_UNPLUGGED = 2,
-    CCS_AUTH_REQUIRED = 3,
-    CCS_CONNECTED = 4,
-    CCS_REPLUGGING = 5,
+    CCS_DISABLED = 0,
+    CCS_UNPLUGGED = 1,
+    CCS_AUTH_REQUIRED = 2,
+    CCS_CONNECTED = 3,
+    CCS_REPLUGGING = 4,
 } CCS_ConnectorState_t;
 
 typedef enum {
diff -ruN /Users/colorbass/STM32CubeIDE/workspace_1.12.0/CCSModuleSW30Web/Core/Inc/serial_control.h /Users/colorbass/STM32CubeIDE/workspace_1.12.0/fork/CCSModuleSW30Web/Core/Inc/serial_control.h
--- /Users/colorbass/STM32CubeIDE/workspace_1.12.0/CCSModuleSW30Web/Core/Inc/serial_control.h	2026-04-13 19:38:22
+++ /Users/colorbass/STM32CubeIDE/workspace_1.12.0/fork/CCSModuleSW30Web/Core/Inc/serial_control.h	2026-05-04 19:45:25
@@ -4,6 +4,7 @@
 #include "main.h"
 #include <string.h>
 #include "charger_control.h"
+#include "isr_opt.h"
 
 #define USE_WEB_INTERFACE
 
@@ -159,10 +160,6 @@
     // Переменные для передачи команды
     volatile ReceivedCommand_t received_command;
     volatile uint8_t command_ready;
-    volatile uint8_t response_pending;
-    volatile uint8_t response_code;
-    volatile uint8_t rx_error_pending;
-    volatile uint32_t rx_error_code;
 
     // Время отправки последнего пакета
     volatile uint32_t tx_tick;
@@ -172,7 +169,7 @@
 // Публичные методы
 void SC_Init();
 void SC_Task();
-void SC_SendPacket(const uint8_t* payload, uint16_t payload_len, uint8_t response_code);
+ISR_FAST void SC_SendPacket(const uint8_t* payload, uint16_t payload_len, uint8_t response_code);
 
 // Внешняя функция обработки команд (определена в serial_handler.c)
 extern void SC_CommandHandler(ReceivedCommand_t* cmd);
diff -ruN /Users/colorbass/STM32CubeIDE/workspace_1.12.0/CCSModuleSW30Web/Core/Inc/stm32f1xx_hal_conf.h /Users/colorbass/STM32CubeIDE/workspace_1.12.0/fork/CCSModuleSW30Web/Core/Inc/stm32f1xx_hal_conf.h
--- /Users/colorbass/STM32CubeIDE/workspace_1.12.0/CCSModuleSW30Web/Core/Inc/stm32f1xx_hal_conf.h	2025-12-02 18:39:36
+++ /Users/colorbass/STM32CubeIDE/workspace_1.12.0/fork/CCSModuleSW30Web/Core/Inc/stm32f1xx_hal_conf.h	2026-05-04 17:27:16
@@ -42,7 +42,7 @@
 /*#define HAL_CORTEX_MODULE_ENABLED   */
 #define HAL_CRC_MODULE_ENABLED
 /*#define HAL_DAC_MODULE_ENABLED   */
-/*#define HAL_DMA_MODULE_ENABLED   */
+#define HAL_DMA_MODULE_ENABLED
 /*#define HAL_ETH_MODULE_ENABLED   */
 /*#define HAL_FLASH_MODULE_ENABLED   */
 #define HAL_GPIO_MODULE_ENABLED
diff -ruN /Users/colorbass/STM32CubeIDE/workspace_1.12.0/CCSModuleSW30Web/Core/Inc/stm32f1xx_it.h /Users/colorbass/STM32CubeIDE/workspace_1.12.0/fork/CCSModuleSW30Web/Core/Inc/stm32f1xx_it.h
--- /Users/colorbass/STM32CubeIDE/workspace_1.12.0/CCSModuleSW30Web/Core/Inc/stm32f1xx_it.h	2026-03-19 02:09:09
+++ /Users/colorbass/STM32CubeIDE/workspace_1.12.0/fork/CCSModuleSW30Web/Core/Inc/stm32f1xx_it.h	2026-05-04 17:46:02
@@ -55,6 +55,8 @@
 void DebugMon_Handler(void);
 void PendSV_Handler(void);
 void SysTick_Handler(void);
+void DMA1_Channel1_IRQHandler(void);
+void ADC1_2_IRQHandler(void);
 void CAN1_RX0_IRQHandler(void);
 void TIM3_IRQHandler(void);
 void USART1_IRQHandler(void);
diff -ruN /Users/colorbass/STM32CubeIDE/workspace_1.12.0/CCSModuleSW30Web/Core/Src/adc.c /Users/colorbass/STM32CubeIDE/workspace_1.12.0/fork/CCSModuleSW30Web/Core/Src/adc.c
--- /Users/colorbass/STM32CubeIDE/workspace_1.12.0/CCSModuleSW30Web/Core/Src/adc.c	2026-03-17 20:01:20
+++ /Users/colorbass/STM32CubeIDE/workspace_1.12.0/fork/CCSModuleSW30Web/Core/Src/adc.c	2026-05-04 19:45:24
@@ -1,135 +1,234 @@
-/* USER CODE BEGIN Header */
-/**
-  ******************************************************************************
-  * @file    adc.c
-  * @brief   This file provides code for the configuration
-  *          of the ADC instances.
-  ******************************************************************************
-  * @attention
-  *
-  * Copyright (c) 2024 STMicroelectronics.
-  * All rights reserved.
-  *
-  * This software is licensed under terms that can be found in the LICENSE file
-  * in the root directory of this software component.
-  * If no LICENSE file comes with this software, it is provided AS-IS.
-  *
-  ******************************************************************************
-  */
-/* USER CODE END Header */
-/* Includes ------------------------------------------------------------------*/
-#include "adc.h"
-
-/* USER CODE BEGIN 0 */
-
-/* USER CODE END 0 */
-
-ADC_HandleTypeDef hadc1;
-
-/* ADC1 init function */
-void MX_ADC1_Init(void)
-{
-
-  /* USER CODE BEGIN ADC1_Init 0 */
-
-  /* USER CODE END ADC1_Init 0 */
-
-  ADC_ChannelConfTypeDef sConfig = {0};
-
-  /* USER CODE BEGIN ADC1_Init 1 */
-
-  /* USER CODE END ADC1_Init 1 */
-
-  /** Common config
-  */
-  hadc1.Instance = ADC1;
-  hadc1.Init.ScanConvMode = ADC_SCAN_DISABLE;
-  hadc1.Init.ContinuousConvMode = DISABLE;
-  hadc1.Init.DiscontinuousConvMode = DISABLE;
-  hadc1.Init.ExternalTrigConv = ADC_SOFTWARE_START;
-  hadc1.Init.DataAlign = ADC_DATAALIGN_RIGHT;
-  hadc1.Init.NbrOfConversion = 1;
-  if (HAL_ADC_Init(&hadc1) != HAL_OK)
-  {
-    Error_Handler();
-  }
-
-  /** Configure Regular Channel
-  */
-  sConfig.Channel = ADC_CHANNEL_8;
-  sConfig.Rank = ADC_REGULAR_RANK_1;
-  sConfig.SamplingTime = ADC_SAMPLETIME_1CYCLE_5;
-  if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK)
-  {
-    Error_Handler();
-  }
-  /* USER CODE BEGIN ADC1_Init 2 */
-
-  /* USER CODE END ADC1_Init 2 */
-
-}
-
-void HAL_ADC_MspInit(ADC_HandleTypeDef* adcHandle)
-{
-
-  GPIO_InitTypeDef GPIO_InitStruct = {0};
-  if(adcHandle->Instance==ADC1)
-  {
-  /* USER CODE BEGIN ADC1_MspInit 0 */
-
-  /* USER CODE END ADC1_MspInit 0 */
-    /* ADC1 clock enable */
-    __HAL_RCC_ADC1_CLK_ENABLE();
-
-    __HAL_RCC_GPIOA_CLK_ENABLE();
-    __HAL_RCC_GPIOB_CLK_ENABLE();
-    /**ADC1 GPIO Configuration
-    PA3     ------> ADC1_IN3
-    PA4     ------> ADC1_IN4
-    PB0     ------> ADC1_IN8
-    PB1     ------> ADC1_IN9
-    */
-    GPIO_InitStruct.Pin = GPIO_PIN_3|CP_ADC_Pin;
-    GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
-    HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
-
-    GPIO_InitStruct.Pin = ADC_NTC1_Pin|ADC_NTC2_Pin;
-    GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
-    HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
-
-  /* USER CODE BEGIN ADC1_MspInit 1 */
-
-  /* USER CODE END ADC1_MspInit 1 */
-  }
-}
-
-void HAL_ADC_MspDeInit(ADC_HandleTypeDef* adcHandle)
-{
-
-  if(adcHandle->Instance==ADC1)
-  {
-  /* USER CODE BEGIN ADC1_MspDeInit 0 */
-
-  /* USER CODE END ADC1_MspDeInit 0 */
-    /* Peripheral clock disable */
-    __HAL_RCC_ADC1_CLK_DISABLE();
-
-    /**ADC1 GPIO Configuration
-    PA3     ------> ADC1_IN3
-    PA4     ------> ADC1_IN4
-    PB0     ------> ADC1_IN8
-    PB1     ------> ADC1_IN9
-    */
-    HAL_GPIO_DeInit(GPIOA, GPIO_PIN_3|CP_ADC_Pin);
-
-    HAL_GPIO_DeInit(GPIOB, ADC_NTC1_Pin|ADC_NTC2_Pin);
-
-  /* USER CODE BEGIN ADC1_MspDeInit 1 */
-
-  /* USER CODE END ADC1_MspDeInit 1 */
-  }
-}
-
-/* USER CODE BEGIN 1 */
-
-/* USER CODE END 1 */
+/* USER CODE BEGIN Header */
+/**
+  ******************************************************************************
+  * @file    adc.c
+  * @brief   This file provides code for the configuration
+  *          of the ADC instances.
+  ******************************************************************************
+  * @attention
+  *
+  * Copyright (c) 2024 STMicroelectronics.
+  * All rights reserved.
+  *
+  * This software is licensed under terms that can be found in the LICENSE file
+  * in the root directory of this software component.
+  * If no LICENSE file comes with this software, it is provided AS-IS.
+  *
+  ******************************************************************************
+  */
+/* USER CODE END Header */
+/* Includes ------------------------------------------------------------------*/
+#include "adc.h"
+
+/* USER CODE BEGIN 0 */
+#include "isr_opt.h"
+static volatile uint16_t adc_dma_raw[6];
+volatile ADC_ScanData_t adc_data = {0};
+static volatile uint8_t adc_scan_data_ready = 0u;
+
+void ADC_ScanStart(void)
+{
+  if (HAL_ADC_Start_DMA(&hadc1, (uint32_t *)adc_dma_raw, 6u) != HAL_OK)
+  {
+    Error_Handler();
+  }
+}
+
+ISR_FAST void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef *hadc)
+{
+  if (hadc->Instance != ADC1)
+  {
+    return;
+  }
+
+  adc_data.in3_raw = adc_dma_raw[0];
+  adc_data.cp_raw = adc_dma_raw[1];
+  adc_data.ntc1_raw = adc_dma_raw[2];
+  adc_data.ntc2_raw = adc_dma_raw[3];
+  adc_data.temp_sensor_raw = adc_dma_raw[4];
+  adc_data.vrefint_raw = adc_dma_raw[5];
+  adc_scan_data_ready = 1u;
+}
+
+/* USER CODE END 0 */
+
+ADC_HandleTypeDef hadc1;
+DMA_HandleTypeDef hdma_adc1;
+
+/* ADC1 init function */
+void MX_ADC1_Init(void)
+{
+
+  /* USER CODE BEGIN ADC1_Init 0 */
+
+  /* USER CODE END ADC1_Init 0 */
+
+  ADC_ChannelConfTypeDef sConfig = {0};
+
+  /* USER CODE BEGIN ADC1_Init 1 */
+
+  /* USER CODE END ADC1_Init 1 */
+
+  /** Common config
+  */
+  hadc1.Instance = ADC1;
+  hadc1.Init.ScanConvMode = ADC_SCAN_ENABLE;
+  hadc1.Init.ContinuousConvMode = DISABLE;
+  hadc1.Init.DiscontinuousConvMode = DISABLE;
+  hadc1.Init.ExternalTrigConv = ADC_EXTERNALTRIGCONV_T3_TRGO;
+  hadc1.Init.DataAlign = ADC_DATAALIGN_RIGHT;
+  hadc1.Init.NbrOfConversion = 6;
+  if (HAL_ADC_Init(&hadc1) != HAL_OK)
+  {
+    Error_Handler();
+  }
+
+  /** Configure Regular Channel
+  */
+  sConfig.Channel = ADC_CHANNEL_3;
+  sConfig.Rank = ADC_REGULAR_RANK_1;
+  sConfig.SamplingTime = ADC_SAMPLETIME_41CYCLES_5;
+  if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK)
+  {
+    Error_Handler();
+  }
+
+  /** Configure Regular Channel
+  */
+  sConfig.Channel = ADC_CHANNEL_4;
+  sConfig.Rank = ADC_REGULAR_RANK_2;
+  if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK)
+  {
+    Error_Handler();
+  }
+
+  /** Configure Regular Channel
+  */
+  sConfig.Channel = ADC_CHANNEL_8;
+  sConfig.Rank = ADC_REGULAR_RANK_3;
+  if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK)
+  {
+    Error_Handler();
+  }
+
+  /** Configure Regular Channel
+  */
+  sConfig.Channel = ADC_CHANNEL_9;
+  sConfig.Rank = ADC_REGULAR_RANK_4;
+  if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK)
+  {
+    Error_Handler();
+  }
+
+  /** Configure Regular Channel
+  */
+  sConfig.Channel = ADC_CHANNEL_TEMPSENSOR;
+  sConfig.Rank = ADC_REGULAR_RANK_5;
+  if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK)
+  {
+    Error_Handler();
+  }
+
+  /** Configure Regular Channel
+  */
+  sConfig.Channel = ADC_CHANNEL_VREFINT;
+  sConfig.Rank = ADC_REGULAR_RANK_6;
+  if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK)
+  {
+    Error_Handler();
+  }
+  /* USER CODE BEGIN ADC1_Init 2 */
+
+  /* USER CODE END ADC1_Init 2 */
+
+}
+
+void HAL_ADC_MspInit(ADC_HandleTypeDef* adcHandle)
+{
+
+  GPIO_InitTypeDef GPIO_InitStruct = {0};
+  if(adcHandle->Instance==ADC1)
+  {
+  /* USER CODE BEGIN ADC1_MspInit 0 */
+
+  /* USER CODE END ADC1_MspInit 0 */
+    /* ADC1 clock enable */
+    __HAL_RCC_ADC1_CLK_ENABLE();
+
+    __HAL_RCC_GPIOA_CLK_ENABLE();
+    __HAL_RCC_GPIOB_CLK_ENABLE();
+    /**ADC1 GPIO Configuration
+    PA3     ------> ADC1_IN3
+    PA4     ------> ADC1_IN4
+    PB0     ------> ADC1_IN8
+    PB1     ------> ADC1_IN9
+    */
+    GPIO_InitStruct.Pin = GPIO_PIN_3|CP_ADC_Pin;
+    GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
+    HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
+
+    GPIO_InitStruct.Pin = ADC_NTC1_Pin|ADC_NTC2_Pin;
+    GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
+    HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
+
+    /* ADC1 DMA Init */
+    /* ADC1 Init */
+    hdma_adc1.Instance = DMA1_Channel1;
+    hdma_adc1.Init.Direction = DMA_PERIPH_TO_MEMORY;
+    hdma_adc1.Init.PeriphInc = DMA_PINC_DISABLE;
+    hdma_adc1.Init.MemInc = DMA_MINC_ENABLE;
+    hdma_adc1.Init.PeriphDataAlignment = DMA_PDATAALIGN_HALFWORD;
+    hdma_adc1.Init.MemDataAlignment = DMA_MDATAALIGN_HALFWORD;
+    hdma_adc1.Init.Mode = DMA_CIRCULAR;
+    hdma_adc1.Init.Priority = DMA_PRIORITY_HIGH;
+    if (HAL_DMA_Init(&hdma_adc1) != HAL_OK)
+    {
+      Error_Handler();
+    }
+
+    __HAL_LINKDMA(adcHandle,DMA_Handle,hdma_adc1);
+
+    /* ADC1 interrupt Init */
+    HAL_NVIC_SetPriority(ADC1_2_IRQn, 0, 0);
+    HAL_NVIC_EnableIRQ(ADC1_2_IRQn);
+  /* USER CODE BEGIN ADC1_MspInit 1 */
+
+  /* USER CODE END ADC1_MspInit 1 */
+  }
+}
+
+void HAL_ADC_MspDeInit(ADC_HandleTypeDef* adcHandle)
+{
+
+  if(adcHandle->Instance==ADC1)
+  {
+  /* USER CODE BEGIN ADC1_MspDeInit 0 */
+
+  /* USER CODE END ADC1_MspDeInit 0 */
+    /* Peripheral clock disable */
+    __HAL_RCC_ADC1_CLK_DISABLE();
+
+    /**ADC1 GPIO Configuration
+    PA3     ------> ADC1_IN3
+    PA4     ------> ADC1_IN4
+    PB0     ------> ADC1_IN8
+    PB1     ------> ADC1_IN9
+    */
+    HAL_GPIO_DeInit(GPIOA, GPIO_PIN_3|CP_ADC_Pin);
+
+    HAL_GPIO_DeInit(GPIOB, ADC_NTC1_Pin|ADC_NTC2_Pin);
+
+    /* ADC1 DMA DeInit */
+    HAL_DMA_DeInit(adcHandle->DMA_Handle);
+
+    /* ADC1 interrupt Deinit */
+    HAL_NVIC_DisableIRQ(ADC1_2_IRQn);
+  /* USER CODE BEGIN ADC1_MspDeInit 1 */
+
+  /* USER CODE END ADC1_MspDeInit 1 */
+  }
+}
+
+/* USER CODE BEGIN 1 */
+
+/* USER CODE END 1 */
diff -ruN /Users/colorbass/STM32CubeIDE/workspace_1.12.0/CCSModuleSW30Web/Core/Src/board.c /Users/colorbass/STM32CubeIDE/workspace_1.12.0/fork/CCSModuleSW30Web/Core/Src/board.c
--- /Users/colorbass/STM32CubeIDE/workspace_1.12.0/CCSModuleSW30Web/Core/Src/board.c	2026-04-07 18:10:34
+++ /Users/colorbass/STM32CubeIDE/workspace_1.12.0/fork/CCSModuleSW30Web/Core/Src/board.c	2026-05-04 19:40:26
@@ -1,11 +1,10 @@
 
 #include "main.h"
 #include "board.h"
+#include "adc.h"
 #include "tim.h"
 #include "sma_filter.h"
 
-extern ADC_HandleTypeDef hadc1;
-
 //TODO:
 //TEMP READ
 // Connector temperature sensors
@@ -89,14 +88,15 @@
 
 void Init_Peripheral(){
     HAL_ADCEx_Calibration_Start(&hadc1);
+    ADC_ScanStart();
 
     RELAY_Write(RELAY_AUX0, 0);
     RELAY_Write(RELAY_AUX1, 0);
     RELAY_Write(RELAY3, 0);
     RELAY_Write(RELAY_DC, 0);
     RELAY_Write(RELAY_AC, 0);
-    RELAY_Write(RELAY_CP, 0);
-    RELAY_Write(RELAY_CC, 0);
+    RELAY_Write(RELAY_CP, 1);
+    RELAY_Write(RELAY_CC, 1);
     RELAY_Write(RELAY_DC1, 0);
 
     SMAFilter_Init(&conn_temp_adc_filter[0]);
@@ -130,27 +130,11 @@
 }
 
 int16_t CONN_ReadTemp(uint8_t ch){
-	ADC_LockBlocking();
+    uint32_t adcValue = 0u;
+    adcValue = ch ? adc_data.ntc2_raw : adc_data.ntc1_raw;
 
-	//TODO
-	if(ch)ADC_Select_Channel(ADC_CHANNEL_8);
-	else ADC_Select_Channel(ADC_CHANNEL_9);
-    // Начало конверсии
-    HAL_ADC_Start(&hadc1);
-
-
-    // Ожидание окончания конверсии
-    HAL_ADC_PollForConversion(&hadc1, HAL_MAX_DELAY);
-
-    // Получение значения
-    uint32_t adcValue = HAL_ADC_GetValue(&hadc1);
-
-    // Остановка АЦП (по желанию)
-    HAL_ADC_Stop(&hadc1);
-
     int32_t adc_filtered = SMAFilter_Update(&conn_temp_adc_filter[ch ? 1u : 0u], (int32_t)adcValue);
     if((uint32_t)adc_filtered > 4000u) {
-    	ADC_Unlock();
     	return 20; //Термодатчик не подключен
     }
 
@@ -161,7 +145,6 @@
 
     float temp = pt1000_to_temperature(calculate_NTC_resistance((int)adc_filtered, Vref, Vin, R));
 
-    ADC_Unlock();
     return (int16_t)temp;
 
 }
diff -ruN /Users/colorbass/STM32CubeIDE/workspace_1.12.0/CCSModuleSW30Web/Core/Src/charger_control.c /Users/colorbass/STM32CubeIDE/workspace_1.12.0/fork/CCSModuleSW30Web/Core/Src/charger_control.c
--- /Users/colorbass/STM32CubeIDE/workspace_1.12.0/CCSModuleSW30Web/Core/Src/charger_control.c	2026-04-13 19:38:22
+++ /Users/colorbass/STM32CubeIDE/workspace_1.12.0/fork/CCSModuleSW30Web/Core/Src/charger_control.c	2026-04-03 18:20:51
@@ -7,6 +7,7 @@
 
 ChargingConnector_t CONN;
 CONN_State_t connectorState;
+extern uint8_t config_initialized;
 
 void CONN_Init(){
 
@@ -42,7 +43,16 @@
     /* CCS state machine is handled in serial.c.
      * Keep this task lightweight for scheduler compatibility.
      */
-    return;
+    if (CONN.chargingError != CONN_NO_ERROR) {
+        CONN_SetState(Disabled);
+        return;
+    }
+
+    if (connectorState == Unknown && config_initialized) {
+        CONN_SetState(Unplugged);
+    } else if (connectorState == Disabled && CONN.chargingError == CONN_NO_ERROR) {
+        CONN_SetState(Unplugged);
+    }
 }
 
 void CONN_SetState(CONN_State_t state){
diff -ruN /Users/colorbass/STM32CubeIDE/workspace_1.12.0/CCSModuleSW30Web/Core/Src/cp.c /Users/colorbass/STM32CubeIDE/workspace_1.12.0/fork/CCSModuleSW30Web/Core/Src/cp.c
--- /Users/colorbass/STM32CubeIDE/workspace_1.12.0/CCSModuleSW30Web/Core/Src/cp.c	2026-04-26 21:15:56
+++ /Users/colorbass/STM32CubeIDE/workspace_1.12.0/fork/CCSModuleSW30Web/Core/Src/cp.c	2026-05-04 18:41:45
@@ -3,6 +3,7 @@
 #include "board.h"
 #include "tim.h"
 #include <stdint.h>
+#include <stdlib.h>
 
 #define MAX_DUTY 450
 
@@ -10,29 +11,22 @@
 static uint8_t cp_duty = 0;
 CP_State_t fake_cp_state = EV_STATE_ACQUIRING;
 
-static uint32_t CP_ReadAdcChannel(uint32_t ch) {
-    uint32_t adc = 0;
-
-    ADC_Select_Channel(ch);
-    HAL_ADC_Start(&hadc1);
-    HAL_ADC_PollForConversion(&hadc1, 10);
-    adc = HAL_ADC_GetValue(&hadc1);
-    HAL_ADC_Stop(&hadc1);
-
-    return adc;
-}
 #define VREFINT_CAL_ADDR ((uint16_t*)0x1FFFF7BA) // для STM32F1!
 
 static int32_t CP_ReadVoltageMv(void)
 {
-    uint32_t adc = 0;
-    int32_t v_adc_mv = 0;
-    int32_t v_out_mv = 0;
+    uint32_t adc_cp = adc_data.cp_raw;
+    uint32_t adc_vref = adc_data.vrefint_raw; // нужно измерять!
 
-    adc = CP_ReadAdcChannel((uint32_t)4u);
-    v_adc_mv = (int32_t)((adc * 3300u) / 4095u);
-    v_out_mv = ((v_adc_mv - 1723) * 1000) / 130;
+    // VREFINT в мВ (берётся из даташита или калибровки MCU)
+    const int32_t VREFINT_MV = 1210;
 
+    // напряжение на входе АЦП
+    int32_t v_adc_mv = (adc_cp * VREFINT_MV) / adc_vref;
+
+    // дальше твоя формула
+    int32_t v_out_mv = ((v_adc_mv - 1723) * 7704) / 1000;
+
     return v_out_mv;
 }
 
@@ -50,7 +44,7 @@
 #endif
 
     HAL_TIM_PWM_Start(&htim3, TIM_CHANNEL_2);
-    HAL_TIM_OC_Start_IT(&htim3, TIM_CHANNEL_1);
+    HAL_TIM_OC_Start(&htim3, TIM_CHANNEL_1);
 }
 
 void CP_SetDuty(uint8_t percentage) {
@@ -71,11 +65,12 @@
 }
 
 int32_t CP_GetVoltage(void) {
+    cp_voltage_mv = CP_ReadVoltageMv();
     return cp_voltage_mv;
 }
 
 CP_State_t CP_GetState(void) {
-    int32_t voltage_real = cp_voltage_mv;
+    int32_t voltage_real = CP_GetVoltage();
 
     if(fake_cp_state != EV_STATE_ACQUIRING) {
         return fake_cp_state;
@@ -100,16 +95,5 @@
 
 void CP_Loop(void) {
     (void)CP_GetState();
-}
-
-void HAL_TIM_OC_DelayElapsedCallback(TIM_HandleTypeDef *htim)
-{
-    if (htim->Instance == TIM3 && htim->Channel == HAL_TIM_ACTIVE_CHANNEL_1) {
-        if (ADC_TryLock() == 0u) {
-            return;
-        }
-        cp_voltage_mv = CP_ReadVoltageMv();
-        ADC_Unlock();
-    }
 }
 
diff -ruN /Users/colorbass/STM32CubeIDE/workspace_1.12.0/CCSModuleSW30Web/Core/Src/debug.c /Users/colorbass/STM32CubeIDE/workspace_1.12.0/fork/CCSModuleSW30Web/Core/Src/debug.c
--- /Users/colorbass/STM32CubeIDE/workspace_1.12.0/CCSModuleSW30Web/Core/Src/debug.c	2026-04-10 11:21:13
+++ /Users/colorbass/STM32CubeIDE/workspace_1.12.0/fork/CCSModuleSW30Web/Core/Src/debug.c	2026-05-04 19:45:25
@@ -148,3 +148,220 @@
 	return result;
 }
 
+#ifndef USE_WEB_INTERFACE
+
+#include "isr_opt.h"
+
+extern UART_HandleTypeDef huart2;
+
+
+uint8_t  debug_rx_buffer[256];
+uint8_t debug_cmd_received;
+uint8_t debug_rx_buffer_size = 0;
+
+
+ISR_FAST 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);
+	}
+}
+
+ISR_FAST void debug_rx_interrupt(UART_HandleTypeDef *huart, uint16_t Size){
+	debug_rx_buffer[Size] = '\0';
+	debug_rx_buffer_size = Size;
+	debug_cmd_received = 1;
+}
+
+void debug_init(){
+	HAL_UARTEx_ReceiveToIdle_IT(&huart2,debug_rx_buffer,255);
+}
+
+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) {
+        log_printf(LOG_INFO, "Resetting...\n");
+        NVIC_SystemReset();
+
+    } else if (strncmp((const char*)buffer, "relayaux", length) == 0) {
+        log_printf(LOG_INFO, "Relaying...\n");
+        RELAY_Write(RELAY_AUX, 1);
+        HAL_Delay(2000);
+        RELAY_Write(RELAY_AUX, 0);
+    } else if (strncmp((const char*)buffer, "relaycc", length) == 0) {
+        log_printf(LOG_INFO, "Relaying...\n");
+        RELAY_Write(RELAY_CC, 1);
+        HAL_Delay(200);
+        RELAY_Write(RELAY_CC, 0);
+    } else if (strncmp((const char*)buffer, "relaydc", length) == 0) {
+        log_printf(LOG_INFO, "Relaying...\n");
+        RELAY_Write(RELAY_DC, 1);
+        HAL_Delay(200);
+        RELAY_Write(RELAY_DC, 0);
+    } else if (strncmp((const char*)buffer, "relayac", length) == 0) {
+        log_printf(LOG_INFO, "Relaying...\n");
+        RELAY_Write(RELAY_AC, 1);
+        HAL_Delay(200);
+        RELAY_Write(RELAY_AC, 0);
+
+    } else if (strncmp((const char*)buffer, "adc", length) == 0) {
+        log_printf(LOG_INFO, "CC1=%.2f\n", CONN_CC_GetAdc());
+
+    } else if (strncmp((const char*)buffer, "lock_state", length) == 0) {
+        log_printf(LOG_INFO, "Lock state=%d\n", GBT_LockGetState());
+
+    } else if (strncmp((const char*)buffer, "lock_lock", length) == 0) {
+        log_printf(LOG_INFO, "Locked\n");
+        GBT_Lock(1);
+
+    } else if (strncmp((const char*)buffer, "lock_unlock", length) == 0) {
+        log_printf(LOG_INFO, "Unlocked\n");
+        GBT_Lock(0);
+
+    } else if (strncmp((const char*)buffer, "complete", length) == 0) {
+    	CONN_SetState(Finished);
+
+    } else if (strncmp((const char*)buffer, "start", length) == 0) {
+        log_printf(LOG_INFO, "Started\n");
+        GBT_Start();
+
+    } else if (strncmp((const char*)buffer, "stop", length) == 0) {
+        log_printf(LOG_INFO, "Stopped\n");
+        GBT_StopEVSE(GBT_CST_SUSPENDS_ARTIFICIALLY);
+
+    } else if (strncmp((const char*)buffer, "stop1", length) == 0) {
+        log_printf(LOG_INFO, "Stopped\n");
+        GBT_ForceStop();
+
+//    } else if (strncmp((const char*)buffer, "force", length) == 0) {
+//        log_printf(LOG_INFO, "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:
+    		log_printf(LOG_INFO, "GBT_CC_UNKNOWN\n");
+    		break;
+    	case GBT_CC_12V:
+    		log_printf(LOG_INFO, "GBT_CC_12V\n");
+    		break;
+    	case GBT_CC_6V:
+    		log_printf(LOG_INFO, "GBT_CC_6V\n");
+    		break;
+    	case GBT_CC_4V:
+    		log_printf(LOG_INFO, "GBT_CC_4V\n");
+    		break;
+    	case GBT_CC_2V:
+    		log_printf(LOG_INFO, "GBT_CC_2V\n");
+    		break;
+
+    	}
+    } else if (strncmp((const char*)buffer, "temp", length) == 0) {
+    	log_printf(LOG_INFO, "temp1 %d\n",GBT_ReadTemp(0));
+    	log_printf(LOG_INFO, "temp2 %d\n",GBT_ReadTemp(1));
+    } else if (strncmp((const char*)buffer, "info1", length) == 0) {
+        log_printf(LOG_INFO, "Battery info:\n");
+        log_printf(LOG_INFO, "maxCV %dV\n",GBT_BATStat.maxCellVoltage/100); 		// 0.01v/bit
+        log_printf(LOG_INFO, "maxCC %dA\n",GBT_BATStat.maxChargingCurrent/10); 	// 0.1A/bit
+        log_printf(LOG_INFO, "totE %dkWh\n",GBT_BATStat.totalEnergy/10); 			// 0.1kWh
+        log_printf(LOG_INFO, "maxCV %dV\n",GBT_BATStat.maxChargingVoltage/10); 	// 0.1V/ bit
+        log_printf(LOG_INFO, "maxT %dC\n",(int16_t)GBT_BATStat.maxTemp-50); 		// 1C/bit, -50C offset
+        log_printf(LOG_INFO, "SOC %dp\n",GBT_BATStat.SOC/10); 					// 0.1%/bit , 0..100%
+        log_printf(LOG_INFO, "Volt. %dV\n",GBT_BATStat.measVoltage/10); 			// 0.1V/bit
+
+    } else if (strncmp((const char*)buffer, "info2", length) == 0) {
+        log_printf(LOG_INFO, "EV info:\n");
+        log_printf(LOG_INFO, "GBT_ver V%d.%d%d\n",GBT_EVInfo.version[0],GBT_EVInfo.version[1],GBT_EVInfo.version[2]);
+        log_printf(LOG_INFO, "Battery type: %d\n",GBT_EVInfo.batteryType);
+        log_printf(LOG_INFO, "Battery capacity: %d\n", GBT_EVInfo.batteryCapacity);	// 0.1Ah/bit
+    	log_printf(LOG_INFO, "Battery voltage: %d\n", GBT_EVInfo.batteryVoltage);  	// 0.1V/bit
+    	log_printf(LOG_INFO, "Battery vendor: %.4s\n", GBT_EVInfo.batteryVendor); 	// Battery vendor (ASCII string)
+    	log_printf(LOG_INFO, "Battery SN: %lu\n", GBT_EVInfo.batterySN);			// int
+    	log_printf(LOG_INFO, "Battery manufacture date: %02d.%02d.%04d\n", GBT_EVInfo.batteryManuD, GBT_EVInfo.batteryManuM ,GBT_EVInfo.batteryManuY+1985);		// year (offset 1985)
+    	log_printf(LOG_INFO, "Battery cycles: %d\n", GBT_EVInfo.batteryCycleCount); //uint24_t
+    	log_printf(LOG_INFO, "Own auto: %d\n", GBT_EVInfo.ownAuto);			// 0 = lizing, 1 = own auto
+    	log_printf(LOG_INFO, "EVIN: %.17s\n", GBT_EVInfo.EVIN);			//EVIN
+    	log_printf(LOG_INFO, "EV_SW_VER: %.8s\n", GBT_EVInfo.EV_SW_VER);
+
+    } else if (strncmp((const char*)buffer, "info3", length) == 0) {
+        log_printf(LOG_INFO, "GBT_MaxLoad info:\n");
+        log_printf(LOG_INFO, "Output max current: %d\n",GBT_MaxLoad.maxOutputCurrent);
+        log_printf(LOG_INFO, "Output min current: %d\n",GBT_MaxLoad.minOutputCurrent);
+        log_printf(LOG_INFO, "Output max voltage: %d\n",GBT_MaxLoad.maxOutputVoltage);
+        log_printf(LOG_INFO, "Output min voltage: %d\n",GBT_MaxLoad.minOutputVoltage);
+        log_printf(LOG_INFO, "\nGBT_ChargerInfo info:\n");
+        log_printf(LOG_INFO, "BMS Recognized: %d\n",GBT_ChargerInfo.bmsIdentified);
+        log_printf(LOG_INFO, "Charger location: %.3s\n",GBT_ChargerInfo.chargerLocation);
+        log_printf(LOG_INFO, "Charger number: %lu\n",GBT_ChargerInfo.chargerNumber);
+
+
+    } else if (strncmp((const char*)buffer, "help", length) == 0) {
+        log_printf(LOG_INFO, "Command list:\n");
+        log_printf(LOG_INFO, "reset\n");
+        log_printf(LOG_INFO, "help\n");
+        log_printf(LOG_INFO, "cc_state\n");
+        log_printf(LOG_INFO, "lock_lock\n");
+        log_printf(LOG_INFO, "lock_unlock\n");
+        log_printf(LOG_INFO, "lock_state\n");
+        log_printf(LOG_INFO, "adc\n");
+        log_printf(LOG_INFO, "relay(cc,aux,ac,dc)\n");
+        log_printf(LOG_INFO, "start\n");
+        log_printf(LOG_INFO, "stop\n");
+        log_printf(LOG_INFO, "stop1\n");
+//        log_printf(LOG_INFO, "force\n");
+        log_printf(LOG_INFO, "temp\n");
+        log_printf(LOG_INFO, "info1\n");
+        log_printf(LOG_INFO, "info2\n");
+        log_printf(LOG_INFO, "info3\n");
+        log_printf(LOG_INFO, "time\n");
+        log_printf(LOG_INFO, "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);
+
+		log_printf(LOG_INFO, "Year: %d\n", parts->tm_year + 1900);
+		log_printf(LOG_INFO, "Month: %d\n", parts->tm_mon + 1);
+		log_printf(LOG_INFO, "Day: %d\n", parts->tm_mday);
+		log_printf(LOG_INFO, "Hour: %d\n", parts->tm_hour);
+		log_printf(LOG_INFO, "Minute: %d\n", parts->tm_min);
+		log_printf(LOG_INFO, "Second: %d\n", parts->tm_sec);
+
+    } else if (strncmp((const char*)buffer, "cantest", length) == 0) {
+    	//GBT_SendCHM();
+    	GBT_Error(0xFDF0C0FC); //BRM Timeout
+        log_printf(LOG_INFO, "can test\n");
+
+    } else {
+        log_printf(LOG_INFO, "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;
+	}
+}
+
+#else
+
+#endif // USE_WEB_INTERFACE
diff -ruN /Users/colorbass/STM32CubeIDE/workspace_1.12.0/CCSModuleSW30Web/Core/Src/dma.c /Users/colorbass/STM32CubeIDE/workspace_1.12.0/fork/CCSModuleSW30Web/Core/Src/dma.c
--- /Users/colorbass/STM32CubeIDE/workspace_1.12.0/CCSModuleSW30Web/Core/Src/dma.c	1970-01-01 03:00:00
+++ /Users/colorbass/STM32CubeIDE/workspace_1.12.0/fork/CCSModuleSW30Web/Core/Src/dma.c	2026-05-04 17:27:13
@@ -0,0 +1,55 @@
+/* USER CODE BEGIN Header */
+/**
+  ******************************************************************************
+  * @file    dma.c
+  * @brief   This file provides code for the configuration
+  *          of all the requested memory to memory DMA transfers.
+  ******************************************************************************
+  * @attention
+  *
+  * Copyright (c) 2026 STMicroelectronics.
+  * All rights reserved.
+  *
+  * This software is licensed under terms that can be found in the LICENSE file
+  * in the root directory of this software component.
+  * If no LICENSE file comes with this software, it is provided AS-IS.
+  *
+  ******************************************************************************
+  */
+/* USER CODE END Header */
+
+/* Includes ------------------------------------------------------------------*/
+#include "dma.h"
+
+/* USER CODE BEGIN 0 */
+
+/* USER CODE END 0 */
+
+/*----------------------------------------------------------------------------*/
+/* Configure DMA                                                              */
+/*----------------------------------------------------------------------------*/
+
+/* USER CODE BEGIN 1 */
+
+/* USER CODE END 1 */
+
+/**
+  * Enable DMA controller clock
+  */
+void MX_DMA_Init(void)
+{
+
+  /* DMA controller clock enable */
+  __HAL_RCC_DMA1_CLK_ENABLE();
+
+  /* DMA interrupt init */
+  /* DMA1_Channel1_IRQn interrupt configuration */
+  HAL_NVIC_SetPriority(DMA1_Channel1_IRQn, 0, 0);
+  HAL_NVIC_EnableIRQ(DMA1_Channel1_IRQn);
+
+}
+
+/* USER CODE BEGIN 2 */
+
+/* USER CODE END 2 */
+
diff -ruN /Users/colorbass/STM32CubeIDE/workspace_1.12.0/CCSModuleSW30Web/Core/Src/gpio.c /Users/colorbass/STM32CubeIDE/workspace_1.12.0/fork/CCSModuleSW30Web/Core/Src/gpio.c
--- /Users/colorbass/STM32CubeIDE/workspace_1.12.0/CCSModuleSW30Web/Core/Src/gpio.c	2026-03-19 00:22:07
+++ /Users/colorbass/STM32CubeIDE/workspace_1.12.0/fork/CCSModuleSW30Web/Core/Src/gpio.c	2026-05-04 16:27:39
@@ -54,20 +54,27 @@
   __HAL_RCC_GPIOD_CLK_ENABLE();
 
   /*Configure GPIO pin Output Level */
-  HAL_GPIO_WritePin(GPIOC, RELAY_CP_Pin|LOCK_A_Pin|LOCK_B_Pin, GPIO_PIN_RESET);
+  HAL_GPIO_WritePin(GPIOC, DBG1_Pin|RELAY_CP_Pin|LOCK_A_Pin|LOCK_B_Pin, GPIO_PIN_RESET);
 
   /*Configure GPIO pin Output Level */
+  HAL_GPIO_WritePin(GPIOA, DBG2_Pin|DBG3_Pin|RELAY_CC_Pin, GPIO_PIN_RESET);
+
+  /*Configure GPIO pin Output Level */
   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(RELAY_CC_GPIO_Port, RELAY_CC_Pin, GPIO_PIN_RESET);
+  HAL_GPIO_WritePin(GPIOB, DBG5_Pin|DBG4_Pin|EE_WP_Pin, GPIO_PIN_RESET);
 
   /*Configure GPIO pin Output Level */
   HAL_GPIO_WritePin(GPIOD, RELAY_DC_Pin|USART2_DIR_Pin, GPIO_PIN_RESET);
 
-  /*Configure GPIO pin Output Level */
-  HAL_GPIO_WritePin(EE_WP_GPIO_Port, EE_WP_Pin, GPIO_PIN_RESET);
+  /*Configure GPIO pin : DBG1_Pin */
+  GPIO_InitStruct.Pin = DBG1_Pin;
+  GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
+  GPIO_InitStruct.Pull = GPIO_NOPULL;
+  GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
+  HAL_GPIO_Init(DBG1_GPIO_Port, &GPIO_InitStruct);
 
   /*Configure GPIO pins : RELAY_CP_Pin LOCK_A_Pin LOCK_B_Pin */
   GPIO_InitStruct.Pin = RELAY_CP_Pin|LOCK_A_Pin|LOCK_B_Pin;
@@ -88,6 +95,13 @@
   GPIO_InitStruct.Pull = GPIO_PULLDOWN;
   HAL_GPIO_Init(IN_SW1_GPIO_Port, &GPIO_InitStruct);
 
+  /*Configure GPIO pins : DBG2_Pin DBG3_Pin */
+  GPIO_InitStruct.Pin = DBG2_Pin|DBG3_Pin;
+  GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
+  GPIO_InitStruct.Pull = GPIO_NOPULL;
+  GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
+  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;
   GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
@@ -102,6 +116,13 @@
   GPIO_InitStruct.Pull = GPIO_NOPULL;
   GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
   HAL_GPIO_Init(GPIOE, &GPIO_InitStruct);
+
+  /*Configure GPIO pins : DBG5_Pin DBG4_Pin */
+  GPIO_InitStruct.Pin = DBG5_Pin|DBG4_Pin;
+  GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
+  GPIO_InitStruct.Pull = GPIO_NOPULL;
+  GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
+  HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
 
   /*Configure GPIO pin : RELAY_CC_Pin */
   GPIO_InitStruct.Pin = RELAY_CC_Pin;
diff -ruN /Users/colorbass/STM32CubeIDE/workspace_1.12.0/CCSModuleSW30Web/Core/Src/main.c /Users/colorbass/STM32CubeIDE/workspace_1.12.0/fork/CCSModuleSW30Web/Core/Src/main.c
--- /Users/colorbass/STM32CubeIDE/workspace_1.12.0/CCSModuleSW30Web/Core/Src/main.c	2026-04-26 21:15:56
+++ /Users/colorbass/STM32CubeIDE/workspace_1.12.0/fork/CCSModuleSW30Web/Core/Src/main.c	2026-05-04 18:58:41
@@ -1,332 +1,304 @@
-/* USER CODE BEGIN Header */
-/* USER CODE END Header */
-/* Includes ------------------------------------------------------------------*/
-#include "main.h"
-#include "adc.h"
-#include "can.h"
-#include "crc.h"
-#include "rtc.h"
-#include "tim.h"
-#include "usart.h"
-#include "gpio.h"
-
-/* Private includes ----------------------------------------------------------*/
-/* USER CODE BEGIN Includes */
-#include "can.h"
-#include "board.h"
-#include <stdio.h>
-#include "debug.h"
-#include "soft_rtc.h"
-#include "connector.h"
-#include "serial_control.h"
-#include "charger_config.h"
-#include "serial.h"
-/* USER CODE END Includes */
-
-/* Private typedef -----------------------------------------------------------*/
-/* USER CODE BEGIN PTD */
-
-/* USER CODE END PTD */
-
-/* Private define ------------------------------------------------------------*/
-/* USER CODE BEGIN PD */
-
-/* USER CODE END PD */
-
-/* Private macro -------------------------------------------------------------*/
-/* USER CODE BEGIN PM */
-
-/* USER CODE END PM */
-
-/* Private variables ---------------------------------------------------------*/
-
-/* USER CODE BEGIN PV */
-
-/* USER CODE END PV */
-
-/* Private function prototypes -----------------------------------------------*/
-void SystemClock_Config(void);
-/* USER CODE BEGIN PFP */
-
-/* USER CODE END PFP */
-
-/* Private user code ---------------------------------------------------------*/
-/* USER CODE BEGIN 0 */
-
-/**
-  * @brief  Vector base address configuration. It should no longer be at the start of
-  *         flash memory but moved forward because the first part of flash is
-  *         reserved for the bootloader. Note that this is already done by the
-  *         bootloader before starting this program. Unfortunately, function
-  *         SystemInit() overwrites this change again.
-  * @return none.
-  */
-static void VectorBase_Config(void)
-{
-  /* The constant array with vectors of the vector table is declared externally in the
-   * c-startup code.
-   */
-  extern const unsigned long g_pfnVectors[];
-
-  /* Remap the vector table to where the vector table is located for this program. */
-  SCB->VTOR = (unsigned long)&g_pfnVectors[0];
-}
-
-uint8_t ED_TraceWarning(uint8_t flag, uint8_t id){
-  static uint8_t memory[32];
-  if(id > 31) return 0;
-  uint8_t result = 0;
-  if(memory[id] != flag){
-    result = 1;
-  }
-  memory[id] = flag;
-  return result;
-}
-
-
-void ED_Delay(uint32_t Delay)
-{
-  uint32_t tickstart = HAL_GetTick();
-  uint32_t wait = Delay;
-
-  if (wait < HAL_MAX_DELAY)
-  {
-    wait += (uint32_t)(uwTickFreq);
-  }
-
-  while ((HAL_GetTick() - tickstart) < wait){
-    CCS_SerialLoop();
-    StopButtonControl();
-//    CP_Loop();
-    CONN_Task();
-    LED_Task();
-    SC_Task();
-  }
-}
-
-void StopButtonControl(){
-	static uint32_t tick;
-	static uint32_t hold_time;
-	static uint8_t stop_btn_fault = 1;
-	uint32_t now = HAL_GetTick();
-
-	/* Run no faster than once per 10 ms. */
-	if((now - tick) < 10){
-		return;
-	}
-	tick = now;
-
-	uint8_t pressed = !IN_ReadInput(IN_ESTOP);
-	if(!pressed){
-		stop_btn_fault = 0;
-	}
-
-	if(stop_btn_fault){
-		return;
-	}
-
-	if(pressed){
-		if(hold_time == 0){
-			CONN.connControl = CMD_STOP;
-		}
-		hold_time += 10;
-		if(hold_time == 5000){
-			CONN.connControl = CMD_FORCE_UNLOCK;
-		}
-		if(hold_time > 40000){
-			SC_SendPacket(NULL, 0, RESP_SUCCESS);
-			while(huart2.gState == HAL_UART_STATE_BUSY_TX);
-			HAL_Delay(10);
-			NVIC_SystemReset();
-		}
-	}
-	else{
-		hold_time = 0;
-	}
-}
-
-uint8_t temp0, temp1;
-
-static void CAN1_MinimalReInit(void)
-{
-  HAL_CAN_Stop(&hcan1);
-  MX_CAN1_Init();
-  if (HAL_CAN_Start(&hcan1) != HAL_OK) {
-    Error_Handler();
-  }
-  if (HAL_CAN_ActivateNotification(&hcan1, CAN_IT_RX_FIFO0_MSG_PENDING) != HAL_OK) {
-    Error_Handler();
-  }
-}
-
-/* USER CODE END 0 */
-
-/**
-  * @brief  The application entry point.
-  * @retval int
-  */
-int main(void)
-{
-
-  /* USER CODE BEGIN 1 */
-  VectorBase_Config();
-  /* USER CODE END 1 */
-
-  /* MCU Configuration--------------------------------------------------------*/
-
-  /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
-  HAL_Init();
-
-  /* USER CODE BEGIN Init */
-  HAL_RCC_DeInit();
-  /* USER CODE END Init */
-
-  /* Configure the system clock */
-  SystemClock_Config();
-
-  /* USER CODE BEGIN SysInit */
-
-  /* USER CODE END SysInit */
-
-  /* Initialize all configured peripherals */
-  MX_GPIO_Init();
-  MX_ADC1_Init();
-  MX_CAN1_Init();
-  MX_CAN2_Init();
-  MX_RTC_Init();
-  MX_TIM4_Init();
-  MX_USART2_UART_Init();
-  MX_CRC_Init();
-  MX_UART5_Init();
-  MX_USART1_UART_Init();
-  MX_USART3_UART_Init();
-  MX_TIM3_Init();
-  /* USER CODE BEGIN 2 */
-  Init_Peripheral();
-  LED_Init();
-
-  HAL_Delay(300);
-  CCS_Init();
-  SC_Init();
-  log_printf(LOG_INFO, "CCS module start\n");
-  ReadVersion();
-  log_printf(LOG_INFO, "Serial number: %d\n", infoPacket.serialNumber);
-  log_printf(LOG_INFO, "Board revision: %d\n", infoPacket.boardVersion);
-  log_printf(LOG_INFO, "FW version: %d.%d.%d\n", infoPacket.fw_version_major, infoPacket.fw_version_minor, infoPacket.fw_version_patch);
-  CAN1_MinimalReInit();
-  PSU_Init();
-  CONN_Init();
-
-  /* USER CODE END 2 */
-
-  /* Infinite loop */
-  /* USER CODE BEGIN WHILE */
-  while (1)
-  {
-    /* USER CODE END WHILE */
-
-    /* USER CODE BEGIN 3 */
-
-
-    PSU_ReadWrite();
-    PSU_Task();
-    ED_Delay(10);
-    METER_CalculateEnergy();
-    CONN_Loop();
-    LED_Write();
-    ED_Delay(10);
-
-  }
-  /* USER CODE END 3 */
-}
-
-/**
-  * @brief System Clock Configuration
-  * @retval None
-  */
-void SystemClock_Config(void)
-{
-  RCC_OscInitTypeDef RCC_OscInitStruct = {0};
-  RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
-  RCC_PeriphCLKInitTypeDef PeriphClkInit = {0};
-
-  /** Initializes the RCC Oscillators according to the specified parameters
-  * in the RCC_OscInitTypeDef structure.
-  */
-  RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE|RCC_OSCILLATORTYPE_LSE;
-  RCC_OscInitStruct.HSEState = RCC_HSE_ON;
-  RCC_OscInitStruct.HSEPredivValue = RCC_HSE_PREDIV_DIV5;
-  RCC_OscInitStruct.LSEState = RCC_LSE_ON;
-  RCC_OscInitStruct.HSIState = RCC_HSI_ON;
-  RCC_OscInitStruct.Prediv1Source = RCC_PREDIV1_SOURCE_PLL2;
-  RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
-  RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
-  RCC_OscInitStruct.PLL.PLLMUL = RCC_PLL_MUL9;
-  RCC_OscInitStruct.PLL2.PLL2State = RCC_PLL2_ON;
-  RCC_OscInitStruct.PLL2.PLL2MUL = RCC_PLL2_MUL8;
-  RCC_OscInitStruct.PLL2.HSEPrediv2Value = RCC_HSE_PREDIV2_DIV5;
-  if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
-  {
-    Error_Handler();
-  }
-
-  /** Initializes the CPU, AHB and APB buses clocks
-  */
-  RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
-                              |RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;
-  RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
-  RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
-  RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV2;
-  RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;
-
-  if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_2) != HAL_OK)
-  {
-    Error_Handler();
-  }
-  PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_RTC|RCC_PERIPHCLK_ADC;
-  PeriphClkInit.RTCClockSelection = RCC_RTCCLKSOURCE_LSE;
-  PeriphClkInit.AdcClockSelection = RCC_ADCPCLK2_DIV6;
-  if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInit) != HAL_OK)
-  {
-    Error_Handler();
-  }
-
-  /** Configure the Systick interrupt time
-  */
-  __HAL_RCC_PLLI2S_ENABLE();
-}
-
-/* USER CODE BEGIN 4 */
-
-/* USER CODE END 4 */
-
-/**
-  * @brief  This function is executed in case of error occurrence.
-  * @retval None
-  */
-void Error_Handler(void)
-{
-  /* USER CODE BEGIN Error_Handler_Debug */
-  /* User can add his own implementation to report the HAL error return state */
-  __disable_irq();
-  while (1)
-  {
-  }
-  /* USER CODE END Error_Handler_Debug */
-}
-#ifdef USE_FULL_ASSERT
-/**
-  * @brief  Reports the name of the source file and the source line number
-  *         where the assert_param error has occurred.
-  * @param  file: pointer to the source file name
-  * @param  line: assert_param error line source number
-  * @retval None
-  */
-void assert_failed(uint8_t *file, uint32_t line)
-{
-  /* USER CODE BEGIN 6 */
-  /* User can add his own implementation to report the file name and line number,
-     ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */
-  /* USER CODE END 6 */
-}
-#endif /* USE_FULL_ASSERT */
+/* USER CODE BEGIN Header */
+/* USER CODE END Header */
+/* Includes ------------------------------------------------------------------*/
+#include "main.h"
+#include "adc.h"
+#include "can.h"
+#include "crc.h"
+#include "dma.h"
+#include "rtc.h"
+#include "tim.h"
+#include "usart.h"
+#include "gpio.h"
+
+/* Private includes ----------------------------------------------------------*/
+/* USER CODE BEGIN Includes */
+#include "can.h"
+#include "board.h"
+#include <stdio.h>
+#include "debug.h"
+#include "soft_rtc.h"
+#include "connector.h"
+#include "serial_control.h"
+#include "charger_config.h"
+#include "serial.h"
+/* USER CODE END Includes */
+
+/* Private typedef -----------------------------------------------------------*/
+/* USER CODE BEGIN PTD */
+
+/* USER CODE END PTD */
+
+/* Private define ------------------------------------------------------------*/
+/* USER CODE BEGIN PD */
+
+/* USER CODE END PD */
+
+/* Private macro -------------------------------------------------------------*/
+/* USER CODE BEGIN PM */
+
+/* USER CODE END PM */
+
+/* Private variables ---------------------------------------------------------*/
+
+/* USER CODE BEGIN PV */
+
+/* USER CODE END PV */
+
+/* Private function prototypes -----------------------------------------------*/
+void SystemClock_Config(void);
+/* USER CODE BEGIN PFP */
+
+/* USER CODE END PFP */
+
+/* Private user code ---------------------------------------------------------*/
+/* USER CODE BEGIN 0 */
+
+/**
+  * @brief  Vector base address configuration. It should no longer be at the start of
+  *         flash memory but moved forward because the first part of flash is
+  *         reserved for the bootloader. Note that this is already done by the
+  *         bootloader before starting this program. Unfortunately, function
+  *         SystemInit() overwrites this change again.
+  * @return none.
+  */
+static void VectorBase_Config(void)
+{
+  /* The constant array with vectors of the vector table is declared externally in the
+   * c-startup code.
+   */
+  extern const unsigned long g_pfnVectors[];
+
+  /* Remap the vector table to where the vector table is located for this program. */
+  SCB->VTOR = (unsigned long)&g_pfnVectors[0];
+}
+
+uint8_t ED_TraceWarning(uint8_t flag, uint8_t id){
+  static uint8_t memory[32];
+  if(id > 31) return 0;
+  uint8_t result = 0;
+  if(memory[id] != flag){
+    result = 1;
+  }
+  memory[id] = flag;
+  return result;
+}
+
+
+void ED_Delay(uint32_t Delay)
+{
+  uint32_t tickstart = HAL_GetTick();
+  uint32_t wait = Delay;
+
+  if (wait < HAL_MAX_DELAY)
+  {
+    wait += (uint32_t)(uwTickFreq);
+  }
+
+  while ((HAL_GetTick() - tickstart) < wait){
+    CCS_SerialLoop();
+//    CP_Loop();
+    CONN_Task();
+    LED_Task();
+    SC_Task();
+  }
+}
+
+void StopButtonControl(){
+
+	//Charging do nothing
+	if(!IN_ReadInput(IN_ESTOP)){
+		CONN.connControl = CMD_STOP;
+	}
+
+}
+
+uint8_t temp0, temp1;
+
+static void CAN1_MinimalReInit(void)
+{
+  HAL_CAN_Stop(&hcan1);
+  MX_CAN1_Init();
+  if (HAL_CAN_Start(&hcan1) != HAL_OK) {
+    Error_Handler();
+  }
+  if (HAL_CAN_ActivateNotification(&hcan1, CAN_IT_RX_FIFO0_MSG_PENDING) != HAL_OK) {
+    Error_Handler();
+  }
+}
+
+/* USER CODE END 0 */
+
+/**
+  * @brief  The application entry point.
+  * @retval int
+  */
+int main(void)
+{
+
+  /* USER CODE BEGIN 1 */
+
+	VectorBase_Config();
+  /* USER CODE END 1 */
+
+  /* MCU Configuration--------------------------------------------------------*/
+
+  /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
+  HAL_Init();
+
+  /* USER CODE BEGIN Init */
+  HAL_RCC_DeInit();
+  /* USER CODE END Init */
+
+  /* Configure the system clock */
+  SystemClock_Config();
+
+  /* USER CODE BEGIN SysInit */
+
+  /* USER CODE END SysInit */
+
+  /* Initialize all configured peripherals */
+  MX_GPIO_Init();
+  MX_DMA_Init();
+  MX_ADC1_Init();
+  MX_CAN1_Init();
+  MX_CAN2_Init();
+  MX_RTC_Init();
+  MX_TIM4_Init();
+  MX_USART2_UART_Init();
+  MX_CRC_Init();
+  MX_UART5_Init();
+  MX_USART1_UART_Init();
+  MX_USART3_UART_Init();
+  MX_TIM3_Init();
+  /* USER CODE BEGIN 2 */
+  Init_Peripheral();
+  LED_Init();
+
+  HAL_Delay(300);
+  CCS_Init();
+  SC_Init();
+  log_printf(LOG_INFO, "CCS module start\n");
+  ReadVersion();
+  log_printf(LOG_INFO, "Serial number: %d\n", infoPacket.serialNumber);
+  log_printf(LOG_INFO, "Board revision: %d\n", infoPacket.boardVersion);
+  log_printf(LOG_INFO, "FW version: %d.%d.%d\n", infoPacket.fw_version_major, infoPacket.fw_version_minor, infoPacket.fw_version_patch);
+  CAN1_MinimalReInit();
+  PSU_Init();
+  CONN_Init();
+
+  /* USER CODE END 2 */
+
+  /* Infinite loop */
+  /* USER CODE BEGIN WHILE */
+  while (1)
+  {
+    /* USER CODE END WHILE */
+
+    /* USER CODE BEGIN 3 */
+
+
+    PSU_ReadWrite();
+    PSU_Task();
+    ED_Delay(10);
+    METER_CalculateEnergy();
+    CONN_Loop();
+    LED_Write();
+    ED_Delay(10);
+    StopButtonControl();
+    ED_Delay(50);
+
+  }
+  /* USER CODE END 3 */
+}
+
+/**
+  * @brief System Clock Configuration
+  * @retval None
+  */
+void SystemClock_Config(void)
+{
+  RCC_OscInitTypeDef RCC_OscInitStruct = {0};
+  RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
+  RCC_PeriphCLKInitTypeDef PeriphClkInit = {0};
+
+  /** Initializes the RCC Oscillators according to the specified parameters
+  * in the RCC_OscInitTypeDef structure.
+  */
+  RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE|RCC_OSCILLATORTYPE_LSE;
+  RCC_OscInitStruct.HSEState = RCC_HSE_ON;
+  RCC_OscInitStruct.HSEPredivValue = RCC_HSE_PREDIV_DIV5;
+  RCC_OscInitStruct.LSEState = RCC_LSE_ON;
+  RCC_OscInitStruct.HSIState = RCC_HSI_ON;
+  RCC_OscInitStruct.Prediv1Source = RCC_PREDIV1_SOURCE_PLL2;
+  RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
+  RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
+  RCC_OscInitStruct.PLL.PLLMUL = RCC_PLL_MUL9;
+  RCC_OscInitStruct.PLL2.PLL2State = RCC_PLL2_ON;
+  RCC_OscInitStruct.PLL2.PLL2MUL = RCC_PLL2_MUL8;
+  RCC_OscInitStruct.PLL2.HSEPrediv2Value = RCC_HSE_PREDIV2_DIV5;
+  if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
+  {
+    Error_Handler();
+  }
+
+  /** Initializes the CPU, AHB and APB buses clocks
+  */
+  RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
+                              |RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;
+  RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
+  RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
+  RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV2;
+  RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;
+
+  if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_2) != HAL_OK)
+  {
+    Error_Handler();
+  }
+  PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_RTC|RCC_PERIPHCLK_ADC;
+  PeriphClkInit.RTCClockSelection = RCC_RTCCLKSOURCE_LSE;
+  PeriphClkInit.AdcClockSelection = RCC_ADCPCLK2_DIV6;
+  if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInit) != HAL_OK)
+  {
+    Error_Handler();
+  }
+
+  /** Configure the Systick interrupt time
+  */
+  __HAL_RCC_PLLI2S_ENABLE();
+}
+
+/* USER CODE BEGIN 4 */
+
+/* USER CODE END 4 */
+
+/**
+  * @brief  This function is executed in case of error occurrence.
+  * @retval None
+  */
+void Error_Handler(void)
+{
+  /* USER CODE BEGIN Error_Handler_Debug */
+  /* User can add his own implementation to report the HAL error return state */
+  __disable_irq();
+  while (1)
+  {
+  }
+  /* USER CODE END Error_Handler_Debug */
+}
+#ifdef USE_FULL_ASSERT
+/**
+  * @brief  Reports the name of the source file and the source line number
+  *         where the assert_param error has occurred.
+  * @param  file: pointer to the source file name
+  * @param  line: assert_param error line source number
+  * @retval None
+  */
+void assert_failed(uint8_t *file, uint32_t line)
+{
+  /* USER CODE BEGIN 6 */
+  /* User can add his own implementation to report the file name and line number,
+     ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */
+  /* USER CODE END 6 */
+}
+#endif /* USE_FULL_ASSERT */
diff -ruN /Users/colorbass/STM32CubeIDE/workspace_1.12.0/CCSModuleSW30Web/Core/Src/psu_control.c /Users/colorbass/STM32CubeIDE/workspace_1.12.0/fork/CCSModuleSW30Web/Core/Src/psu_control.c
--- /Users/colorbass/STM32CubeIDE/workspace_1.12.0/CCSModuleSW30Web/Core/Src/psu_control.c	2026-04-10 11:09:38
+++ /Users/colorbass/STM32CubeIDE/workspace_1.12.0/fork/CCSModuleSW30Web/Core/Src/psu_control.c	2026-05-04 19:45:24
@@ -8,6 +8,7 @@
 #include "charger_control.h"
 #include "board.h"
 #include "debug.h"
+#include "isr_opt.h"
 
 PSU_02_t PSU_02;
 PSU_04_t PSU_04;
@@ -39,7 +40,7 @@
 	return HAL_GetTick() - PSU0.statetick;
 }
 
-void HAL_CAN_RxFifo1MsgPendingCallback(CAN_HandleTypeDef *hcan){
+ISR_FAST void HAL_CAN_RxFifo1MsgPendingCallback(CAN_HandleTypeDef *hcan){
 
 	static CAN_RxHeaderTypeDef RxHeader;
 	static uint8_t RxData[8] = {0,};
@@ -149,7 +150,6 @@
 
 	PSU0.power_limit = PSU_MAX_POWER; // kW
 	PSU0.hv_mode     = 0;
-	PSU0.hv_tick     = 0;
 
 	PSU_Enable(0, 0);
 }
@@ -262,19 +262,14 @@
 	}
 	CONN.RequestedPower = CONN.RequestedCurrent * CONN.RequestedVoltage / 10;
 
-
 	if(PSU0.ready){
-		PSU_SetVoltageCurrent(0, CONN.RequestedVoltage, CONN.RequestedCurrent); // Normal mode
-		ED_Delay(CAN_DELAY);
-		if(CONN.MeasuredVoltage > 490){
-			if(PSU0.hv_tick == 0){
-				PSU0.hv_tick = HAL_GetTick();
-			}else if((HAL_GetTick() - PSU0.hv_tick) >= 10000){
-				PSU0.hv_mode = 1;
-			}
+		if (CONN.RequestedVoltage == 500) { // fake
+			PSU_SetVoltageCurrent(0, 300, 10); // Normal mode
 		}else{
-			PSU0.hv_tick = 0;
+			PSU_SetVoltageCurrent(0, CONN.RequestedVoltage, CONN.RequestedCurrent); // Normal mode
 		}
+		ED_Delay(CAN_DELAY);
+		if(CONN.MeasuredVoltage>490) PSU0.hv_mode = 1;
 	}
 
 	// PSU_SetHVMode(0, PSU0.hv_mode); // auto set, no need
@@ -348,7 +343,6 @@
 	case PSU_READY:
 		// модуль готов, но выключен
 		PSU0.hv_mode = 0;
-		PSU0.hv_tick = 0;
 
 		RELAY_Write(RELAY_DC, 0);
 		if(!PSU0.ready){
diff -ruN /Users/colorbass/STM32CubeIDE/workspace_1.12.0/CCSModuleSW30Web/Core/Src/rgb_controller.c /Users/colorbass/STM32CubeIDE/workspace_1.12.0/fork/CCSModuleSW30Web/Core/Src/rgb_controller.c
--- /Users/colorbass/STM32CubeIDE/workspace_1.12.0/CCSModuleSW30Web/Core/Src/rgb_controller.c	2026-04-10 14:37:04
+++ /Users/colorbass/STM32CubeIDE/workspace_1.12.0/fork/CCSModuleSW30Web/Core/Src/rgb_controller.c	2026-04-03 18:20:51
@@ -2,7 +2,6 @@
 #include "main.h"
 #include "string.h"
 #include "charger_control.h"
-#include "board.h"
 
 #include "tim.h"
 
@@ -11,22 +10,13 @@
 
 RGB_Cycle_t color_estop = {
 	.Color1 = { .R = 250, .G = 0, .B = 0 },
-	.Color2 = { .R = 0, .G = 0, .B = 0 },
-	.Tr = 10,
-	.Th = 5,
-	.Tf = 10,
-	.Tl = 5,
+	.Color2 = { .R = 250, .G = 0, .B = 0 },
+	.Tr = 50,
+	.Th = 50,
+	.Tf = 50,
+	.Tl = 50,
  };
 
- RGB_Cycle_t color_unlock = {
-	.Color1 = { .R = 255, .G = 0, .B = 0 },
-	.Color2 = { .R = 0, .G = 0, .B = 0 },
-	.Tr = 10,
-	.Th = 10,
-	.Tf = 10,
-	.Tl = 10,
- };
-
 RGB_Cycle_t color_unknown = {
 	.Color1 = { .R = 64, .G = 0, .B = 0 },
 	.Color2 = { .R = 64, .G = 0, .B = 0 },
@@ -64,12 +54,12 @@
 };
 
 RGB_Cycle_t color_preparing = {
-	.Color1 = { .R = 0, .G = 0, .B = 255 },
-	.Color2 = { .R = 0, .G = 0, .B = 0 },
-	.Tr = 10,
+	.Color1 = { .R = 0, .G = 0, .B = 250 },
+	.Color2 = { .R = 0, .G = 0, .B = 250 },
+	.Tr = 50,
 	.Th = 10,
-	.Tf = 10,
-	.Tl = 10,
+	.Tf = 50,
+	.Tl = 0,
 };
 
 RGB_Cycle_t color_charging = {
@@ -102,14 +92,6 @@
 void LED_Write(){
     if(CONN.chargingError != CONN_NO_ERROR){
       LED_SetColor(&color_error);
-      return;
-    }
-    if(CONN.connControl == CMD_FORCE_UNLOCK){
-      LED_SetColor(&color_unlock);
-      return;
-    }
-    if(CONN.connControl == CMD_STOP){
-      LED_SetColor(&color_estop);
       return;
     }
     switch(CONN.connState){
diff -ruN /Users/colorbass/STM32CubeIDE/workspace_1.12.0/CCSModuleSW30Web/Core/Src/serial.c /Users/colorbass/STM32CubeIDE/workspace_1.12.0/fork/CCSModuleSW30Web/Core/Src/serial.c
--- /Users/colorbass/STM32CubeIDE/workspace_1.12.0/CCSModuleSW30Web/Core/Src/serial.c	2026-05-01 17:52:54
+++ /Users/colorbass/STM32CubeIDE/workspace_1.12.0/fork/CCSModuleSW30Web/Core/Src/serial.c	2026-05-04 19:56:33
@@ -3,6 +3,7 @@
 #include "connector.h"
 #include "board.h"
 #include "debug.h"
+#include "isr_opt.h"
 #include <stdint.h>
 #include <string.h>
 #include "charger_config.h"
@@ -28,12 +29,9 @@
 #define CMD_INTERVAL 10
 #define MAX_TX_BUFFER_SIZE 256
 #define MAX_RX_BUFFER_SIZE 256
+#define EVEREST_TIMEOUT_MS 5000u
+#define UART3_REINIT_TIMEOUT_MS 1500u
 
-/* Everest requests 500 V → БП реально 300 V / 1 A, в STATE отдаём 500 V. */
-#define FAKE_EVREQ_VOLTAGE_V   500u
-#define FAKE_PSU_VOLTAGE_V     300u
-#define FAKE_PSU_CURRENT_0P1A   10u
-
 static uint8_t rx_buffer[MAX_RX_BUFFER_SIZE];
 static uint8_t tx_buffer[MAX_TX_BUFFER_SIZE];
 
@@ -44,66 +42,111 @@
 static uint8_t pwm_duty_percent = 100;
 uint8_t isolation_enable = 0;
 static uint32_t last_host_seen = 0;
-static uint8_t fake_500_voltage_mode = 0;
+static uint8_t everest_timed_out = 0;
+static uint32_t last_everest_timeout_log_tick = 0;
+static uint32_t uart3_last_packet_tick = 0;
+static uint32_t uart3_last_reinit_tick = 0;
 static CP_State_t cp_state_buffer = EV_STATE_ACQUIRING;
 
 CCS_State_t CCS_State;
 CCS_EvInfo_t CCS_EvInfo;
 CONN_State_t CCS_EvseState;
-CCS_ConnectorState_t CCS_ConnectorState = CCS_UNKNOWN;
+CCS_ConnectorState_t CCS_ConnectorState = CCS_UNPLUGGED;
 
-static uint8_t process_received_packet(const uint8_t* packet, uint16_t packet_len);
+ISR_FAST static uint8_t process_received_packet(const uint8_t* packet, uint16_t packet_len);
+static void CCS_UART3_Watchdog(void);
 
-void CCS_RxEventCallback(UART_HandleTypeDef *huart, uint16_t size) {
+ISR_FAST static void uart3_log_hal_error(uint8_t uart_num, uint32_t err) {
+    if (err == HAL_UART_ERROR_NONE) {
+        log_printf(LOG_ERR, "UART%u HAL error decode: NONE\n", uart_num);
+        return;
+    }
+    log_printf(LOG_ERR, "UART%u HAL error decode: %s%s%s%s%s%s raw=0x%08lx\n",
+               uart_num,
+               (err & HAL_UART_ERROR_PE) ? "PE " : "",
+               (err & HAL_UART_ERROR_NE) ? "NE " : "",
+               (err & HAL_UART_ERROR_FE) ? "FE " : "",
+               (err & HAL_UART_ERROR_ORE) ? "ORE " : "",
+               (err & HAL_UART_ERROR_DMA) ? "DMA " : "",
+#ifdef HAL_UART_ERROR_INVALID_CALLBACK
+               (err & HAL_UART_ERROR_INVALID_CALLBACK) ? "INV_CB " : "",
+#else
+               "",
+#endif
+               (unsigned long)err);
+}
+
+ISR_FAST static void uart3_arm_rx_or_log(const char *where) {
+    HAL_StatusTypeDef st = HAL_UARTEx_ReceiveToIdle_IT(&huart3, rx_buffer, sizeof(rx_buffer));
+    if (st == HAL_OK) {
+        return;
+    }
+    uint32_t err_after = HAL_UART_GetError(&huart3);
+    log_printf(LOG_ERR,
+               "UART3 RX arm failed (%s): HAL_Status=%d err_after=0x%08lx\n",
+               where, (int)st, (unsigned long)err_after);
+    uart3_log_hal_error(3u, err_after);
+    if (err_after != HAL_UART_ERROR_NONE) {
+        (void)HAL_UART_Abort_IT(&huart3);
+    }
+}
+
+ISR_FAST void CCS_RxEventCallback(UART_HandleTypeDef *huart, uint16_t size) {
     if (huart != &huart3) {
+        log_printf(LOG_WARN, "UART3 RX drop: wrong huart in RxEventCallback (size=%u)\n",
+                   (unsigned)size);
         return;
     }
-    if (size > 0 && size <= sizeof(rx_buffer)) {
-        process_received_packet(rx_buffer, size);
+    if (size == 0u) {
+        log_printf(LOG_WARN, "UART3 RX drop: RxEvent size=0 (idle, no payload)\n");
+        uart3_arm_rx_or_log("RxEventCallback");
+        return;
     }
+    if (size > sizeof(rx_buffer)) {
+        log_printf(LOG_ERR, "UART3 RX drop: size=%u > rx_buffer %u (overflow, not parsed)\n",
+                   (unsigned)size, (unsigned)sizeof(rx_buffer));
+        uart3_arm_rx_or_log("RxEventCallback");
+        return;
+    }
+    uart3_last_packet_tick = HAL_GetTick();
+    uart3_last_reinit_tick = uart3_last_packet_tick;
+    process_received_packet(rx_buffer, size);
+    uart3_arm_rx_or_log("RxEventCallback");
 }
 
-void CCS_RxArm(void) {
-    if ((&huart3)->RxState == HAL_UART_STATE_READY) {
-        (void)HAL_UARTEx_ReceiveToIdle_IT(&huart3, rx_buffer, sizeof(rx_buffer));
+ISR_FAST void HAL_UART_ErrorCallback(UART_HandleTypeDef *huart) {
+    uint32_t error = HAL_UART_GetError(huart);
+    uint8_t uart_num =
+        (huart == &huart2) ? 2 :
+        (huart == &huart3) ? 3 :
+        (huart == &huart5) ? 5 : 0;
+    log_printf(LOG_ERR,
+               "UART%u HAL error (ISR): raw=0x%08lx — RX may be corrupted until re-arm\n",
+               uart_num, (unsigned long)error);
+    uart3_log_hal_error(uart_num, error);
+    (void)HAL_UART_Abort_IT(huart);
+    if (huart == &huart3) {
+        uart3_arm_rx_or_log("ErrorCallback");
     }
 }
 
+
+
 void CCS_SerialLoop(void) {
     static uint32_t replug_tick = 0;
     static uint32_t replug_watchdog_tick = 0;
     static uint32_t replug_watchdog1_tick = 0;
     static uint32_t last_state_sent = 0;
-    static uint32_t force_unlock_tick = 0;
-    static uint32_t stop_tick = 0;
 
-    CCS_RxArm();
+    if ((&huart3)->RxState == HAL_UART_STATE_READY) {
+        uart3_arm_rx_or_log("SerialLoop");
+    }
 
+    CCS_UART3_Watchdog();
+
     /* Read CP once per loop and use buffered value below. */
     cp_state_buffer = CP_GetState();
 
-    if (CONN.connControl == CMD_FORCE_UNLOCK) {
-        if (force_unlock_tick == 0) {
-            force_unlock_tick = HAL_GetTick();
-        } else if ((HAL_GetTick() - force_unlock_tick) >= 10000) {
-            CONN.connControl = CMD_NONE;
-            force_unlock_tick = 0;
-        }
-    } else {
-        force_unlock_tick = 0;
-    }
-
-    if (CONN.connControl == CMD_STOP) {
-        if (stop_tick == 0) {
-            stop_tick = HAL_GetTick();
-        } else if ((HAL_GetTick() - stop_tick) >= 1000) {
-            CONN.connControl = CMD_NONE;
-            stop_tick = 0;
-        }
-    } else {
-        stop_tick = 0;
-    }
-
     if (CONN.connControl != CMD_NONE) {
         last_cmd = CONN.connControl;
     }
@@ -121,14 +164,10 @@
         }
 
         if (((CONN.connControl == CMD_STOP) ||
-             (CONN.connControl == CMD_FORCE_UNLOCK) ||
              (CONN.chargingError != CONN_NO_ERROR)) &&
             ((HAL_GetTick() - last_stop_sent) > 1000)) {
             last_stop_sent = HAL_GetTick();
             log_printf(LOG_WARN, "Stopping charging...\n");
-            if (CONN.connControl == CMD_FORCE_UNLOCK) {
-                CP_SetDuty(100);
-            }
             CCS_SendEmergencyStop();
         }
 
@@ -143,101 +182,102 @@
     (void)replug_watchdog_tick;
     (void)replug_watchdog1_tick;
 
-    uint8_t host_timed_out = (last_host_seen > 0 && (HAL_GetTick() - last_host_seen) > 5000u);
-    uint8_t has_charging_error = 0;//(CONN.chargingError != CONN_NO_ERROR);
+    if (!config_initialized) {
+        // Keep connector in Unknown until host sends valid SET_CONFIG.
+        RELAY_Write(RELAY_CP, 1);
+        CONN_SetState(Unknown);
+    } else {
+        switch(CCS_ConnectorState){
+            case CCS_DISABLED:
+                RELAY_Write(RELAY_CP, 0);
+                CONN_SetState(Disabled);
+                if (CONN.chargingError == CONN_NO_ERROR){
+                    CCS_ConnectorState = CCS_UNPLUGGED;
+                }
+                break;
+            case CCS_UNPLUGGED:
+                RELAY_Write(RELAY_CP, 1);
+                CONN_SetState(Unplugged);
+                if ((cp_state_buffer == EV_STATE_B_CONN_PREP) || (cp_state_buffer == EV_STATE_C_CONN_ACTIVE)){
+                    CCS_ConnectorState = CCS_AUTH_REQUIRED;
+                }
+                if (CONN.chargingError != CONN_NO_ERROR){
+                    log_printf(LOG_ERR, "Charging error %d, state -> disabled\n", CONN.chargingError);
+                    CCS_ConnectorState = CCS_DISABLED;
+                }
 
-    switch(CCS_ConnectorState){
-        case CCS_UNKNOWN:
-            RELAY_Write(RELAY_CP, 0);
-            CONN_SetState(Unknown);
-            if (config_initialized && !host_timed_out) {
-                CCS_ConnectorState = CCS_UNPLUGGED;
-            }
-            break;
-        case CCS_DISABLED:
-            RELAY_Write(RELAY_CP, 0);
-            CONN_SetState(Disabled);
-            if ((CONN.chargingError == CONN_NO_ERROR) && !host_timed_out){
-                CCS_ConnectorState = CCS_UNPLUGGED;
-            }
-            break;
-        case CCS_UNPLUGGED:
-            RELAY_Write(RELAY_CP, 1);
-            CONN_SetState(Unplugged);
-            if ((cp_state_buffer == EV_STATE_B_CONN_PREP) || (cp_state_buffer == EV_STATE_C_CONN_ACTIVE)){
-                CCS_ConnectorState = CCS_AUTH_REQUIRED;
-            }
-            if (CONN.chargingError != CONN_NO_ERROR){
-                log_printf(LOG_ERR, "Charging error %d, state -> disabled\n", CONN.chargingError);
-                CCS_ConnectorState = CCS_DISABLED;
-            }
-
-            break;
-        case CCS_AUTH_REQUIRED:
-            RELAY_Write(RELAY_CP, 1);
-            CONN_SetState(AuthRequired);
-            if(CONN.connControl == CMD_START){
-                log_printf(LOG_INFO, "Charging permitted, start charging\n");
-                CCS_ConnectorState = CCS_CONNECTED;
-            }
-            if (cp_state_buffer == EV_STATE_A_IDLE){
-                log_printf(LOG_INFO, "Car unplugged\n");
-                CCS_ConnectorState = CCS_UNPLUGGED;
-            }
-            break;
-        case CCS_CONNECTED:
-            RELAY_Write(RELAY_CP, 1);
-            if(CCS_EvseState < Preparing) {
-                CONN_SetState(Preparing);
-            } else {
-                CONN_SetState(CCS_EvseState);
-            }
-            if (cp_state_buffer == EV_STATE_A_IDLE){
-                log_printf(LOG_INFO, "Car unplugged\n");
-                CCS_ConnectorState = CCS_UNPLUGGED;
-            }
-            if(REPLUG > 0){
-                log_printf(LOG_INFO, "Replugging...\n");
-                CCS_ConnectorState = CCS_REPLUGGING;
-            }
-            break;
-        case CCS_REPLUGGING:
-            RELAY_Write(RELAY_CP, 0);
-            CONN_SetState(Replugging);
-            if((HAL_GetTick() - replug_tick) > 1000){
-                replug_tick = HAL_GetTick();
-                if(REPLUG > 0){
-                    if (REPLUG != 0xFF) REPLUG--;
+                break;
+            case CCS_AUTH_REQUIRED:
+                RELAY_Write(RELAY_CP, 1);
+                CONN_SetState(AuthRequired);
+                if(CONN.connControl == CMD_START){
+                    log_printf(LOG_INFO, "Charging permitted, start charging\n");
+                    CCS_ConnectorState = CCS_CONNECTED;
+                }
+                if (cp_state_buffer == EV_STATE_A_IDLE){
+                    log_printf(LOG_INFO, "Car unplugged\n");
+                    CCS_ConnectorState = CCS_UNPLUGGED;
+                }
+                break;
+            case CCS_CONNECTED:
+                RELAY_Write(RELAY_CP, 1);
+                if(CCS_EvseState < Preparing) {
+                    CONN_SetState(Preparing);
                 } else {
-                    log_printf(LOG_INFO, "Replugging finished, but car unplugged\n");
+                    CONN_SetState(CCS_EvseState);
+                }
+                if (cp_state_buffer == EV_STATE_A_IDLE){
+                    log_printf(LOG_INFO, "Car unplugged\n");
                     CCS_ConnectorState = CCS_UNPLUGGED;
                 }
-            }
+                if(REPLUG > 0){
+                    log_printf(LOG_INFO, "Replugging...\n");
+                    CCS_ConnectorState = CCS_REPLUGGING;
+                }
+                break;
+            case CCS_REPLUGGING:
+                RELAY_Write(RELAY_CP, 0);
+                CONN_SetState(Replugging);
+                if((HAL_GetTick() - replug_tick) > 1000){
+                    replug_tick = HAL_GetTick();
+                    if(REPLUG > 0){
+                        if (REPLUG != 0xFF) REPLUG--;
+                    } else {
+                        log_printf(LOG_INFO, "Replugging finished, but car unplugged\n");
+                        CCS_ConnectorState = CCS_UNPLUGGED;
+                    }
+                }
 
-            if(REPLUG == 0){
-                if(cp_state_buffer == EV_STATE_B_CONN_PREP){
-                    log_printf(LOG_INFO, "Replugging finished, car plugged, state -> auth required\n");
-                    CCS_ConnectorState = CCS_AUTH_REQUIRED;
+                if(REPLUG == 0){
+                    if(cp_state_buffer == EV_STATE_B_CONN_PREP){
+                        log_printf(LOG_INFO, "Replugging finished, car plugged, state -> auth required\n");
+                        CCS_ConnectorState = CCS_AUTH_REQUIRED;
+                    }
                 }
-            }
-            break;
+                break;
+        }
     }
 
-    if (has_charging_error &&
-        CCS_ConnectorState != CCS_DISABLED &&
-        CCS_ConnectorState != CCS_UNKNOWN) {
-        log_printf(LOG_ERR, "Charging error %d, state -> disabled\n", CONN.chargingError);
-        CCS_ConnectorState = CCS_DISABLED;
-    }
+    // If Everest timeout happened, keep safe-state and limit log frequency.
+    // The safe-state must remain until we receive a valid packet from the host.
+    if (everest_timed_out) {
+        if (last_everest_timeout_log_tick == 0 ||
+            (HAL_GetTick() - last_everest_timeout_log_tick) >= EVEREST_TIMEOUT_MS) {
+            log_printf(LOG_ERR, "Everest timeout\n");
+            last_everest_timeout_log_tick = HAL_GetTick();
+        }
+        CONN.EnableOutput = 0;
+        CCS_EvseState = Unknown;
+        CP_SetDuty(100);
+    } else if (last_host_seen > 0 && (HAL_GetTick() - last_host_seen) > EVEREST_TIMEOUT_MS) {
+        log_printf(LOG_ERR, "Everest timeout\n");
+        everest_timed_out = 1;
+        last_host_seen = HAL_GetTick(); // reset after the first timeout
+        last_everest_timeout_log_tick = HAL_GetTick();
 
-    if (host_timed_out) {
         CONN.EnableOutput = 0;
         CCS_EvseState = Unknown;
         CP_SetDuty(100);
-        if (CCS_ConnectorState != CCS_DISABLED && CCS_ConnectorState != CCS_UNKNOWN) {
-            log_printf(LOG_ERR, "Everest timeout\n");
-            CCS_ConnectorState = CCS_DISABLED;
-        }
     } else {
         if (last_cmd == CMD_STOP) {
             CONN.EnableOutput = 0;
@@ -266,11 +306,13 @@
 	CCS_MaxLoad.maxCurrent = PSU_MAX_CURRENT*10; //100A
 	CCS_MaxLoad.minCurrent = PSU_MIN_CURRENT*10; //1A
 	CCS_MaxLoad.maxPower = PSU_MAX_POWER; //30000W
+    uart3_last_packet_tick = HAL_GetTick();
+    uart3_last_reinit_tick = uart3_last_packet_tick;
     CCS_SendResetReason();
     log_printf(LOG_INFO, "CCS init\n");
 }
 
-static uint16_t crc16_ibm(const uint8_t* data, uint16_t length) {
+ISR_FAST static uint16_t crc16_ibm(const uint8_t* data, uint16_t length) {
     uint16_t crc = 0xFFFFu;
     for (uint16_t i = 0; i < length; i++) {
         crc ^= data[i];
@@ -304,7 +346,7 @@
 static void CCS_SendPacket(uint8_t cmd, const void* payload, uint16_t payload_len) {
     uint16_t len = CCS_BuildPacket(cmd, payload, payload_len, tx_buffer, sizeof(tx_buffer));
     if (len > 0) {
-        HAL_UART_Transmit(&huart3, tx_buffer, len, 1000);
+        HAL_UART_Transmit_IT(&huart3, tx_buffer, len);
     }
     last_cmd_sent = HAL_GetTick();
 }
@@ -342,9 +384,7 @@
     CCS_State.DutyCycle = CP_GetDuty();
     CCS_State.OutputEnabled = PSU0.CONT_enabled;
     CCS_State.MeasuredVoltage = (uint16_t)CONN.MeasuredVoltage;
-    if (fake_500_voltage_mode) {
-        CCS_State.MeasuredVoltage = FAKE_EVREQ_VOLTAGE_V;
-    }
+    if (CONN.RequestedVoltage == 500) CCS_State.MeasuredVoltage = 500; // fake
     CCS_State.MeasuredCurrent = (uint16_t)CONN.MeasuredCurrent;
     CCS_State.Power = CCS_Power;
     CCS_State.Energy = CCS_Energy;
@@ -366,7 +406,7 @@
     CCS_SendPacket(CMD_M2E_STATE, &CCS_State, sizeof(CCS_State));
 }
 
-static uint16_t expected_payload_len(uint8_t cmd) {
+ISR_FAST static uint16_t expected_payload_len(uint8_t cmd) {
     switch (cmd) {
         case CMD_E2M_PWM_DUTY:           return sizeof(e2m_pwm_duty_t);
         case CMD_E2M_ENABLE_OUTPUT:      return sizeof(e2m_enable_output_t);
@@ -382,18 +422,18 @@
     }
 }
 
-static void apply_command(uint8_t cmd, const uint8_t* payload, uint16_t payload_len) {
+ISR_FAST static void apply_command(uint8_t cmd, const uint8_t* payload, uint16_t payload_len) {
     (void)payload_len;
     last_host_seen = HAL_GetTick();
+    everest_timed_out = 0;
+    last_everest_timeout_log_tick = 0;
     switch (cmd) {
         case CMD_E2M_PWM_DUTY: {
             const e2m_pwm_duty_t* p = (const e2m_pwm_duty_t*)payload;
             uint8_t duty = p->pwm_duty_percent;
             if (duty > 100) duty = 100;
             pwm_duty_percent = duty;
-            if (CONN.connControl != CMD_FORCE_UNLOCK) {
-                CP_SetDuty(duty);
-            }
+            CP_SetDuty(duty);
             break;
         }
         case CMD_E2M_ENABLE_OUTPUT: {
@@ -405,9 +445,9 @@
             const e2m_reset_t* p = (const e2m_reset_t*)payload;
             if (p->reset) {
                 log_printf(LOG_WARN, "Everest reset command\n");
-                CCS_SendResetReason();
-                HAL_Delay(10);
-                NVIC_SystemReset();
+                // CCS_SendResetReason();
+                // HAL_Delay(10);
+                // NVIC_SystemReset();
             }
             break;
         }
@@ -419,15 +459,8 @@
         }
         case CMD_E2M_SET_OUTPUT_VOLTAGE: {
             const e2m_set_output_t* p = (const e2m_set_output_t*)payload;
-            if (p->voltage_V == FAKE_EVREQ_VOLTAGE_V) {
-                fake_500_voltage_mode = 1u;
-                CONN.RequestedVoltage = FAKE_PSU_VOLTAGE_V;
-                CONN.WantedCurrent = FAKE_PSU_CURRENT_0P1A;
-            } else {
-                fake_500_voltage_mode = 0u;
-                CONN.RequestedVoltage = p->voltage_V;
-                CONN.WantedCurrent = p->current_0p1A;
-            }
+            CONN.RequestedVoltage = p->voltage_V;
+            CONN.WantedCurrent = p->current_0p1A;
             break;
         }
         case CMD_E2M_ISOLATION_CONTROL: {
@@ -454,32 +487,54 @@
             break;
         }
         default:
+            log_printf(LOG_WARN,
+                       "UART3 RX warn: cmd 0x%02x CRC/len OK but no switch case (expected_payload vs apply_command)\n",
+                       cmd);
             break;
     }
 }
 
-static uint8_t process_received_packet(const uint8_t* packet, uint16_t packet_len) {
-    if (packet_len < 3) return 0;
+ISR_FAST static uint8_t process_received_packet(const uint8_t* packet, uint16_t packet_len) {
+    if (packet_len < 3u) {
+        if (packet_len == 0u) {
+            log_printf(LOG_WARN, "UART3 RX drop: too_short len=0 (empty chunk)\n");
+        } else if (packet_len == 1u) {
+            log_printf(LOG_WARN, "UART3 RX drop: too_short len=1 b0=0x%02x\n", packet[0]);
+        } else {
+            log_printf(LOG_WARN, "UART3 RX drop: too_short len=2 b0=0x%02x b1=0x%02x\n",
+                       packet[0], packet[1]);
+        }
+        return 0;
+    }
 
     uint8_t cmd = packet[0];
-    uint16_t payload_len = (uint16_t)(packet_len - 3);
+    uint16_t payload_len = (uint16_t)(packet_len - 3u);
 
     uint16_t received_crc = (uint16_t)packet[packet_len - 2u] |
                             (uint16_t)packet[packet_len - 1u] << 8;
 
-    uint16_t calculated_crc = crc16_ibm(packet, (uint16_t)(1 + payload_len));
+    uint16_t calculated_crc = crc16_ibm(packet, (uint16_t)(1u + payload_len));
     if (received_crc != calculated_crc) {
-        log_printf(LOG_ERR, "Packet CRC error\n");
+        log_printf(LOG_ERR,
+                   "UART3 RX drop: crc_mismatch cmd=0x%02x total_len=%u payload_len=%u "
+                   "crc_rx=0x%04x crc_calc=0x%04x\n",
+                   cmd, (unsigned)packet_len, (unsigned)payload_len,
+                   (unsigned)received_crc, (unsigned)calculated_crc);
         return 0;
     }
 
     uint16_t expected_len = expected_payload_len(cmd);
-    if (expected_len == 0xFFFF) {
-        log_printf(LOG_WARN, "Unknown cmd 0x%02x\n", cmd);
+    if (expected_len == 0xFFFFu) {
+        log_printf(LOG_WARN,
+                   "UART3 RX drop: unknown_cmd cmd=0x%02x total_len=%u payload_len=%u\n",
+                   cmd, (unsigned)packet_len, (unsigned)payload_len);
         return 0;
     }
     if (expected_len != payload_len) {
-        log_printf(LOG_ERR, "Packet len mismatch cmd=0x%02x\n", cmd);
+        log_printf(LOG_ERR,
+                   "UART3 RX drop: len_mismatch cmd=0x%02x expected_payload=%u got_payload=%u "
+                   "total_len=%u\n",
+                   cmd, (unsigned)expected_len, (unsigned)payload_len, (unsigned)packet_len);
         return 0;
     }
 
@@ -490,5 +545,22 @@
     }
 
     return 1;
+}
+
+static void CCS_UART3_Watchdog(void) {
+    const uint32_t now = HAL_GetTick();
+    const uint32_t since_last_packet = now - uart3_last_packet_tick;
+
+    if ((since_last_packet >= UART3_REINIT_TIMEOUT_MS) &&
+        ((now - uart3_last_reinit_tick) >= UART3_REINIT_TIMEOUT_MS)) {
+        (void)HAL_UART_Abort_IT(&huart3);
+        (void)HAL_UART_DeInit(&huart3);
+        (void)HAL_UART_Init(&huart3);
+        (void)HAL_UARTEx_ReceiveToIdle_IT(&huart3, rx_buffer, sizeof(rx_buffer));
+        log_printf(LOG_ERR,
+                   "UART3 RX recover: stalled (no RxEvent data for %ums), hard reinit\n",
+                   (unsigned)UART3_REINIT_TIMEOUT_MS);
+        uart3_last_reinit_tick = now;
+    }
 }
 
diff -ruN /Users/colorbass/STM32CubeIDE/workspace_1.12.0/CCSModuleSW30Web/Core/Src/serial_control.c /Users/colorbass/STM32CubeIDE/workspace_1.12.0/fork/CCSModuleSW30Web/Core/Src/serial_control.c
--- /Users/colorbass/STM32CubeIDE/workspace_1.12.0/CCSModuleSW30Web/Core/Src/serial_control.c	2026-05-01 17:54:34
+++ /Users/colorbass/STM32CubeIDE/workspace_1.12.0/fork/CCSModuleSW30Web/Core/Src/serial_control.c	2026-05-04 19:49:47
@@ -3,14 +3,14 @@
 #include "board.h"
 #include "serial.h"
 #include "debug.h"
+#include "isr_opt.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);
-static void SC_ArmUart5Rx(void);
+ISR_FAST static uint32_t calculate_crc32(const uint8_t* data, uint16_t length);
+ISR_FAST static uint16_t encode_packet(const uint8_t* payload, uint16_t payload_len, uint8_t* output, uint8_t response_code);
+ISR_FAST static uint8_t parse_packet(const uint8_t* packet_data, uint16_t packet_len, ReceivedCommand_t* out_cmd);
+ISR_FAST static uint8_t process_received_packet(SerialControl_t *ctx, const uint8_t* packet_data, uint16_t packet_len);
+static void SC_UART2_Watchdog(void);
 
 uint8_t test_crc_invalid = 0;
 
@@ -18,7 +18,15 @@
 // Контекст для приема пакетов по UART5 (однонаправленный UART)
 static SerialControl_t serial_iso;
 volatile SC_Source_t g_sc_command_source = SC_SOURCE_UART2;
+static volatile uint8_t sc_uart2_timed_out = 0;
+static uint32_t sc_uart2_last_packet_tick = 0;
+static uint32_t sc_uart2_last_reinit_tick = 0;
+/** Событие приёма по UART2 при активной передаче (см. HAL_UARTEx_RxEventCallback / SC_UART2_Watchdog). */
+static volatile uint8_t sc_uart2_rx_during_tx = 0;
 
+#define SC_UART2_REINIT_TIMEOUT_MS      500u
+#define SC_UART2_PACKET_TIMEOUT_MS     5000u
+
 StatusPacket_t statusPacket = {
     .SOC = 0,
     .Energy = 0,
@@ -75,12 +83,28 @@
     // Обнуляем структуру
     memset(&serial_control, 0, sizeof(SerialControl_t));
     memset(&serial_iso, 0, sizeof(serial_iso));
+    sc_uart2_timed_out = 0;
+    sc_uart2_last_packet_tick = HAL_GetTick();
+    sc_uart2_last_reinit_tick = sc_uart2_last_packet_tick;
+    sc_uart2_rx_during_tx = 0;
 }
 
 void SC_Task() {
+    SC_UART2_Watchdog();
+
 	// Запуск приема в режиме прерывания с ожиданием idle
-    SC_ArmUart2Rx();
-    SC_ArmUart5Rx();
+    if ((huart2.RxState == HAL_UART_STATE_READY) && (serial_control.command_ready == 0)) {
+        if ((HAL_UARTEx_ReceiveToIdle_IT(&huart2, serial_control.rx_buffer, MAX_RX_BUFFER_SIZE - 1) != HAL_OK) &&
+            (HAL_UART_GetError(&huart2) != HAL_UART_ERROR_NONE)) {
+            (void)HAL_UART_Abort_IT(&huart2);
+        }
+    }
+    if (huart5.RxState == HAL_UART_STATE_READY) {
+        if ((HAL_UARTEx_ReceiveToIdle_IT(&huart5, serial_iso.rx_buffer, MAX_RX_BUFFER_SIZE - 1) != HAL_OK) &&
+            (HAL_UART_GetError(&huart5) != HAL_UART_ERROR_NONE)) {
+            (void)HAL_UART_Abort_IT(&huart5);
+        }
+    }
     
     // Проверка таймаута отправки пакета (больше 100 мс)
     if (huart2.gState == HAL_UART_STATE_BUSY_TX && serial_control.tx_tick != 0) {
@@ -95,80 +119,51 @@
 
     // Проверка наличия принятой команды для обработки
     if (serial_control.command_ready && (huart2.gState != HAL_UART_STATE_BUSY_TX)) {
-        g_sc_command_source = SC_SOURCE_UART2;
+//        HAL_Delay(2);
         SC_CommandHandler(&serial_control.received_command);
+        if ((HAL_UARTEx_ReceiveToIdle_IT(&huart2, serial_control.rx_buffer, MAX_RX_BUFFER_SIZE - 1) != HAL_OK) &&
+            (HAL_UART_GetError(&huart2) != HAL_UART_ERROR_NONE)) {
+            (void)HAL_UART_Abort_IT(&huart2);
+        }
         serial_control.command_ready = 0; // Сбрасываем флаг
-        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 = 0;
-    }
-
-    if (serial_iso.command_ready) {
-        g_sc_command_source = SC_SOURCE_UART5;
-        SC_CommandHandler((ReceivedCommand_t*)&serial_iso.received_command);
-        serial_iso.command_ready = 0;
-        SC_ArmUart5Rx();
-    }
 }
 
-void HAL_UARTEx_RxEventCallback(UART_HandleTypeDef *huart, uint16_t Size) {
+ISR_FAST 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 = 1;
-            serial_control.response_code = RESP_INVALID;
-            SC_ArmUart2Rx();
+        if (huart2.gState == HAL_UART_STATE_BUSY_TX) {
+            sc_uart2_rx_during_tx = 1u;
         }
+        sc_uart2_last_packet_tick = HAL_GetTick();
+        sc_uart2_last_reinit_tick = sc_uart2_last_packet_tick;
+        sc_uart2_timed_out = 0;
+        if(!process_received_packet(&serial_control, serial_control.rx_buffer, Size)){
+            SC_SendPacket(NULL, 0, RESP_INVALID);
+        }
+        g_sc_command_source = SC_SOURCE_UART2;
+        HAL_UARTEx_ReceiveToIdle_IT(&huart2, serial_control.rx_buffer, MAX_RX_BUFFER_SIZE - 1);
     } else if (huart->Instance == huart5.Instance) {
-        if (!process_received_packet(&serial_iso, serial_iso.rx_buffer, Size)) {
-            SC_ArmUart5Rx();
+        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);
         }
+        HAL_UARTEx_ReceiveToIdle_IT(&huart5, serial_iso.rx_buffer, MAX_RX_BUFFER_SIZE - 1);
     } else if (huart->Instance == huart3.Instance) {
         CCS_RxEventCallback(huart, Size);
     }
 }
 
-void HAL_UART_ErrorCallback(UART_HandleTypeDef *huart) {
+ISR_FAST void HAL_UART_TxCpltCallback(UART_HandleTypeDef *huart) {
     if (huart->Instance == huart2.Instance) {
-        uint32_t uart_error = HAL_UART_GetError(huart);
-        log_printf(LOG_WARN, "USART2 rx error: 0x%08lx\n", uart_error);
-        SC_ArmUart2Rx();
-    } else if (huart->Instance == huart5.Instance) {
-        uint32_t uart_error = HAL_UART_GetError(huart);
-        log_printf(LOG_WARN, "UART5 rx error: 0x%08lx\n", uart_error);
-        SC_ArmUart5Rx();
-    } else if (huart->Instance == huart3.Instance) {
-        uint32_t uart_error = HAL_UART_GetError(huart);
-        log_printf(LOG_WARN, "USART3 rx error: 0x%08lx\n", uart_error);
-        CCS_RxArm();
-    }
-}
-
-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 = 0;
     }
 }
 
-static void SC_ArmUart2Rx(void) {
-    if ((&huart2)->RxState == HAL_UART_STATE_READY && serial_control.command_ready == 0) {
-        (void)HAL_UARTEx_ReceiveToIdle_IT(&huart2, serial_control.rx_buffer, MAX_RX_BUFFER_SIZE - 1);
-    }
-}
-
-static void SC_ArmUart5Rx(void) {
-    if ((&huart5)->RxState == HAL_UART_STATE_READY && serial_iso.command_ready == 0) {
-        (void)HAL_UARTEx_ReceiveToIdle_IT(&huart5, serial_iso.rx_buffer, MAX_RX_BUFFER_SIZE - 1);
-    }
-}
-
 // Приватные функции реализации
 
 // Полностью программная реализация CRC-32 (полином CRC32_POLYNOMIAL, порядок little-endian)
-static uint32_t calculate_crc32(const uint8_t* data, uint16_t length) {
+ISR_FAST static uint32_t calculate_crc32(const uint8_t* data, uint16_t length) {
     uint32_t crc = 0xFFFFFFFFu;
 
     for (uint16_t i = 0; i < length; i++) {
@@ -185,7 +180,7 @@
     return crc ^ 0xFFFFFFFFu;
 }
 
-static uint16_t encode_packet(const uint8_t* payload, uint16_t payload_len, uint8_t* output, uint8_t response_code) {
+ISR_FAST 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;
@@ -218,7 +213,7 @@
     return out_index;
 }
 
-void SC_SendPacket(const uint8_t* payload, uint16_t payload_len, uint8_t response_code) {
+ISR_FAST 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 > 0) {
@@ -229,13 +224,15 @@
 
         HAL_GPIO_WritePin(USART2_DIR_GPIO_Port, USART2_DIR_Pin, GPIO_PIN_SET);
 
+        sc_uart2_rx_during_tx = 0u;
+
         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) {
+ISR_FAST static uint8_t parse_packet(const uint8_t* packet_data, uint16_t packet_len, ReceivedCommand_t* out_cmd) {
     // if (test_crc_invalid && (packet_data[1] != CMD_GET_STATUS)) {
     //     test_crc_invalid--;
     //     return 0;
@@ -268,12 +265,50 @@
     return 1;
 }
 
-static uint8_t process_received_packet(SerialControl_t *ctx, const uint8_t* packet_data, uint16_t packet_len) {
+ISR_FAST 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 0;
     }
 
     ctx->command_ready = 1;
     return 1;
+}
+
+static void SC_UART2_Watchdog(void) {
+    const uint32_t now = HAL_GetTick();
+    const uint32_t since_last_packet = now - sc_uart2_last_packet_tick;
+
+    if ((huart2.gState == HAL_UART_STATE_BUSY_TX) && (sc_uart2_rx_during_tx != 0u)) {
+        HAL_GPIO_WritePin(USART2_DIR_GPIO_Port, USART2_DIR_Pin, GPIO_PIN_RESET);
+        (void)HAL_UART_Abort_IT(&huart2);
+        (void)HAL_UART_DeInit(&huart2);
+        (void)HAL_UART_Init(&huart2);
+        (void)HAL_UARTEx_ReceiveToIdle_IT(&huart2, serial_control.rx_buffer, MAX_RX_BUFFER_SIZE - 1);
+        serial_control.tx_tick = 0;
+        sc_uart2_rx_during_tx = 0u;
+        sc_uart2_last_reinit_tick = now;
+        log_printf(LOG_ERR, "USART2 BUSY_TX: hard reinit\n");
+        return;
+    }
+
+    if (since_last_packet >= SC_UART2_PACKET_TIMEOUT_MS) {
+        if (sc_uart2_timed_out == 0u) {
+            serial_control.command_ready = 0;
+        }
+        sc_uart2_timed_out = 1;
+    } else {
+        sc_uart2_timed_out = 0;
+    }
+
+    if ((since_last_packet >= SC_UART2_REINIT_TIMEOUT_MS) &&
+        ((now - sc_uart2_last_reinit_tick) >= SC_UART2_REINIT_TIMEOUT_MS)) {
+        HAL_GPIO_WritePin(USART2_DIR_GPIO_Port, USART2_DIR_Pin, GPIO_PIN_RESET);
+        (void)HAL_UART_Abort_IT(&huart2);
+        (void)HAL_UART_DeInit(&huart2);
+        (void)HAL_UART_Init(&huart2);
+        (void)HAL_UARTEx_ReceiveToIdle_IT(&huart2, serial_control.rx_buffer, MAX_RX_BUFFER_SIZE - 1);
+        sc_uart2_last_reinit_tick = now;
+        log_printf(LOG_ERR, "USART2 stalled: hard reinit\n");
+    }
 }
 
diff -ruN /Users/colorbass/STM32CubeIDE/workspace_1.12.0/CCSModuleSW30Web/Core/Src/stm32f1xx_it.c /Users/colorbass/STM32CubeIDE/workspace_1.12.0/fork/CCSModuleSW30Web/Core/Src/stm32f1xx_it.c
--- /Users/colorbass/STM32CubeIDE/workspace_1.12.0/CCSModuleSW30Web/Core/Src/stm32f1xx_it.c	2026-03-19 02:08:31
+++ /Users/colorbass/STM32CubeIDE/workspace_1.12.0/fork/CCSModuleSW30Web/Core/Src/stm32f1xx_it.c	2026-05-04 19:45:24
@@ -1,321 +1,354 @@
-/* USER CODE BEGIN Header */
-/**
-  ******************************************************************************
-  * @file    stm32f1xx_it.c
-  * @brief   Interrupt Service Routines.
-  ******************************************************************************
-  * @attention
-  *
-  * Copyright (c) 2024 STMicroelectronics.
-  * All rights reserved.
-  *
-  * This software is licensed under terms that can be found in the LICENSE file
-  * in the root directory of this software component.
-  * If no LICENSE file comes with this software, it is provided AS-IS.
-  *
-  ******************************************************************************
-  */
-/* USER CODE END Header */
-
-/* Includes ------------------------------------------------------------------*/
-#include "main.h"
-#include "stm32f1xx_it.h"
-/* Private includes ----------------------------------------------------------*/
-/* USER CODE BEGIN Includes */
-/* USER CODE END Includes */
-
-/* Private typedef -----------------------------------------------------------*/
-/* USER CODE BEGIN TD */
-
-/* USER CODE END TD */
-
-/* Private define ------------------------------------------------------------*/
-/* USER CODE BEGIN PD */
-
-/* USER CODE END PD */
-
-/* Private macro -------------------------------------------------------------*/
-/* USER CODE BEGIN PM */
-
-/* USER CODE END PM */
-
-/* Private variables ---------------------------------------------------------*/
-/* USER CODE BEGIN PV */
-
-/* USER CODE END PV */
-
-/* Private function prototypes -----------------------------------------------*/
-/* USER CODE BEGIN PFP */
-
-/* USER CODE END PFP */
-
-/* Private user code ---------------------------------------------------------*/
-/* USER CODE BEGIN 0 */
-
-/* USER CODE END 0 */
-
-/* External variables --------------------------------------------------------*/
-extern CAN_HandleTypeDef hcan1;
-extern CAN_HandleTypeDef hcan2;
-extern TIM_HandleTypeDef htim3;
-extern UART_HandleTypeDef huart5;
-extern UART_HandleTypeDef huart1;
-extern UART_HandleTypeDef huart2;
-extern UART_HandleTypeDef huart3;
-/* USER CODE BEGIN EV */
-
-/* USER CODE END EV */
-
-/******************************************************************************/
-/*           Cortex-M3 Processor Interruption and Exception Handlers          */
-/******************************************************************************/
-/**
-  * @brief This function handles Non maskable interrupt.
-  */
-void NMI_Handler(void)
-{
-  /* USER CODE BEGIN NonMaskableInt_IRQn 0 */
-
-  /* USER CODE END NonMaskableInt_IRQn 0 */
-  /* USER CODE BEGIN NonMaskableInt_IRQn 1 */
-  while (1)
-  {
-  }
-  /* USER CODE END NonMaskableInt_IRQn 1 */
-}
-
-/**
-  * @brief This function handles Hard fault interrupt.
-  */
-void HardFault_Handler(void)
-{
-  /* USER CODE BEGIN HardFault_IRQn 0 */
-
-  /* USER CODE END HardFault_IRQn 0 */
-  while (1)
-  {
-    /* USER CODE BEGIN W1_HardFault_IRQn 0 */
-    /* USER CODE END W1_HardFault_IRQn 0 */
-  }
-}
-
-/**
-  * @brief This function handles Memory management fault.
-  */
-void MemManage_Handler(void)
-{
-  /* USER CODE BEGIN MemoryManagement_IRQn 0 */
-
-  /* USER CODE END MemoryManagement_IRQn 0 */
-  while (1)
-  {
-    /* USER CODE BEGIN W1_MemoryManagement_IRQn 0 */
-    /* USER CODE END W1_MemoryManagement_IRQn 0 */
-  }
-}
-
-/**
-  * @brief This function handles Prefetch fault, memory access fault.
-  */
-void BusFault_Handler(void)
-{
-  /* USER CODE BEGIN BusFault_IRQn 0 */
-
-  /* USER CODE END BusFault_IRQn 0 */
-  while (1)
-  {
-    /* USER CODE BEGIN W1_BusFault_IRQn 0 */
-    /* USER CODE END W1_BusFault_IRQn 0 */
-  }
-}
-
-/**
-  * @brief This function handles Undefined instruction or illegal state.
-  */
-void UsageFault_Handler(void)
-{
-  /* USER CODE BEGIN UsageFault_IRQn 0 */
-
-  /* USER CODE END UsageFault_IRQn 0 */
-  while (1)
-  {
-    /* USER CODE BEGIN W1_UsageFault_IRQn 0 */
-    /* USER CODE END W1_UsageFault_IRQn 0 */
-  }
-}
-
-/**
-  * @brief This function handles System service call via SWI instruction.
-  */
-void SVC_Handler(void)
-{
-  /* USER CODE BEGIN SVCall_IRQn 0 */
-
-  /* USER CODE END SVCall_IRQn 0 */
-  /* USER CODE BEGIN SVCall_IRQn 1 */
-
-  /* USER CODE END SVCall_IRQn 1 */
-}
-
-/**
-  * @brief This function handles Debug monitor.
-  */
-void DebugMon_Handler(void)
-{
-  /* USER CODE BEGIN DebugMonitor_IRQn 0 */
-
-  /* USER CODE END DebugMonitor_IRQn 0 */
-  /* USER CODE BEGIN DebugMonitor_IRQn 1 */
-
-  /* USER CODE END DebugMonitor_IRQn 1 */
-}
-
-/**
-  * @brief This function handles Pendable request for system service.
-  */
-void PendSV_Handler(void)
-{
-  /* USER CODE BEGIN PendSV_IRQn 0 */
-
-  /* USER CODE END PendSV_IRQn 0 */
-  /* USER CODE BEGIN PendSV_IRQn 1 */
-
-  /* USER CODE END PendSV_IRQn 1 */
-}
-
-/**
-  * @brief This function handles System tick timer.
-  */
-void SysTick_Handler(void)
-{
-  /* USER CODE BEGIN SysTick_IRQn 0 */
-
-  /* USER CODE END SysTick_IRQn 0 */
-  HAL_IncTick();
-  /* USER CODE BEGIN SysTick_IRQn 1 */
-
-  /* USER CODE END SysTick_IRQn 1 */
-}
-
-/******************************************************************************/
-/* STM32F1xx Peripheral Interrupt Handlers                                    */
-/* Add here the Interrupt Handlers for the used peripherals.                  */
-/* For the available peripheral interrupt handler names,                      */
-/* please refer to the startup file (startup_stm32f1xx.s).                    */
-/******************************************************************************/
-
-/**
-  * @brief This function handles CAN1 RX0 interrupt.
-  */
-void CAN1_RX0_IRQHandler(void)
-{
-  /* USER CODE BEGIN CAN1_RX0_IRQn 0 */
-
-  /* USER CODE END CAN1_RX0_IRQn 0 */
-  HAL_CAN_IRQHandler(&hcan1);
-  /* USER CODE BEGIN CAN1_RX0_IRQn 1 */
-
-  /* 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 USART1 global interrupt.
-  */
-void USART1_IRQHandler(void)
-{
-  /* USER CODE BEGIN USART1_IRQn 0 */
-
-  /* USER CODE END USART1_IRQn 0 */
-  HAL_UART_IRQHandler(&huart1);
-  /* USER CODE BEGIN USART1_IRQn 1 */
-
-  /* USER CODE END USART1_IRQn 1 */
-}
-
-/**
-  * @brief This function handles USART2 global interrupt.
-  */
-void USART2_IRQHandler(void)
-{
-  /* USER CODE BEGIN USART2_IRQn 0 */
-
-  /* USER CODE END USART2_IRQn 0 */
-  HAL_UART_IRQHandler(&huart2);
-  /* USER CODE BEGIN USART2_IRQn 1 */
-
-  /* USER CODE END USART2_IRQn 1 */
-}
-
-/**
-  * @brief This function handles USART3 global interrupt.
-  */
-void USART3_IRQHandler(void)
-{
-  /* USER CODE BEGIN USART3_IRQn 0 */
-
-  /* USER CODE END USART3_IRQn 0 */
-  HAL_UART_IRQHandler(&huart3);
-  /* USER CODE BEGIN USART3_IRQn 1 */
-
-  /* USER CODE END USART3_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.
-  */
-void CAN2_TX_IRQHandler(void)
-{
-  /* USER CODE BEGIN CAN2_TX_IRQn 0 */
-
-  /* USER CODE END CAN2_TX_IRQn 0 */
-  HAL_CAN_IRQHandler(&hcan2);
-  /* USER CODE BEGIN CAN2_TX_IRQn 1 */
-
-  /* USER CODE END CAN2_TX_IRQn 1 */
-}
-
-/**
-  * @brief This function handles CAN2 RX1 interrupt.
-  */
-void CAN2_RX1_IRQHandler(void)
-{
-  /* USER CODE BEGIN CAN2_RX1_IRQn 0 */
-
-  /* USER CODE END CAN2_RX1_IRQn 0 */
-  HAL_CAN_IRQHandler(&hcan2);
-  /* USER CODE BEGIN CAN2_RX1_IRQn 1 */
-
-  /* USER CODE END CAN2_RX1_IRQn 1 */
-}
-
-/* USER CODE BEGIN 1 */
-
-/* USER CODE END 1 */
+/* USER CODE BEGIN Header */
+/**
+  ******************************************************************************
+  * @file    stm32f1xx_it.c
+  * @brief   Interrupt Service Routines.
+  ******************************************************************************
+  * @attention
+  *
+  * Copyright (c) 2024 STMicroelectronics.
+  * All rights reserved.
+  *
+  * This software is licensed under terms that can be found in the LICENSE file
+  * in the root directory of this software component.
+  * If no LICENSE file comes with this software, it is provided AS-IS.
+  *
+  ******************************************************************************
+  */
+/* USER CODE END Header */
+
+/* Includes ------------------------------------------------------------------*/
+#include "main.h"
+#include "stm32f1xx_it.h"
+/* Private includes ----------------------------------------------------------*/
+/* USER CODE BEGIN Includes */
+#if defined(__GNUC__)
+#pragma GCC optimize("Ofast")
+#endif
+/* USER CODE END Includes */
+
+/* Private typedef -----------------------------------------------------------*/
+/* USER CODE BEGIN TD */
+
+/* USER CODE END TD */
+
+/* Private define ------------------------------------------------------------*/
+/* USER CODE BEGIN PD */
+
+/* USER CODE END PD */
+
+/* Private macro -------------------------------------------------------------*/
+/* USER CODE BEGIN PM */
+
+/* USER CODE END PM */
+
+/* Private variables ---------------------------------------------------------*/
+/* USER CODE BEGIN PV */
+
+/* USER CODE END PV */
+
+/* Private function prototypes -----------------------------------------------*/
+/* USER CODE BEGIN PFP */
+
+/* USER CODE END PFP */
+
+/* Private user code ---------------------------------------------------------*/
+/* USER CODE BEGIN 0 */
+
+/* USER CODE END 0 */
+
+/* External variables --------------------------------------------------------*/
+extern DMA_HandleTypeDef hdma_adc1;
+extern ADC_HandleTypeDef hadc1;
+extern CAN_HandleTypeDef hcan1;
+extern CAN_HandleTypeDef hcan2;
+extern TIM_HandleTypeDef htim3;
+extern UART_HandleTypeDef huart5;
+extern UART_HandleTypeDef huart1;
+extern UART_HandleTypeDef huart2;
+extern UART_HandleTypeDef huart3;
+/* USER CODE BEGIN EV */
+
+/* USER CODE END EV */
+
+/******************************************************************************/
+/*           Cortex-M3 Processor Interruption and Exception Handlers          */
+/******************************************************************************/
+/**
+  * @brief This function handles Non maskable interrupt.
+  */
+void NMI_Handler(void)
+{
+  /* USER CODE BEGIN NonMaskableInt_IRQn 0 */
+
+  /* USER CODE END NonMaskableInt_IRQn 0 */
+  /* USER CODE BEGIN NonMaskableInt_IRQn 1 */
+  while (1)
+  {
+  }
+  /* USER CODE END NonMaskableInt_IRQn 1 */
+}
+
+/**
+  * @brief This function handles Hard fault interrupt.
+  */
+void HardFault_Handler(void)
+{
+  /* USER CODE BEGIN HardFault_IRQn 0 */
+
+  /* USER CODE END HardFault_IRQn 0 */
+  while (1)
+  {
+    /* USER CODE BEGIN W1_HardFault_IRQn 0 */
+    /* USER CODE END W1_HardFault_IRQn 0 */
+  }
+}
+
+/**
+  * @brief This function handles Memory management fault.
+  */
+void MemManage_Handler(void)
+{
+  /* USER CODE BEGIN MemoryManagement_IRQn 0 */
+
+  /* USER CODE END MemoryManagement_IRQn 0 */
+  while (1)
+  {
+    /* USER CODE BEGIN W1_MemoryManagement_IRQn 0 */
+    /* USER CODE END W1_MemoryManagement_IRQn 0 */
+  }
+}
+
+/**
+  * @brief This function handles Prefetch fault, memory access fault.
+  */
+void BusFault_Handler(void)
+{
+  /* USER CODE BEGIN BusFault_IRQn 0 */
+
+  /* USER CODE END BusFault_IRQn 0 */
+  while (1)
+  {
+    /* USER CODE BEGIN W1_BusFault_IRQn 0 */
+    /* USER CODE END W1_BusFault_IRQn 0 */
+  }
+}
+
+/**
+  * @brief This function handles Undefined instruction or illegal state.
+  */
+void UsageFault_Handler(void)
+{
+  /* USER CODE BEGIN UsageFault_IRQn 0 */
+
+  /* USER CODE END UsageFault_IRQn 0 */
+  while (1)
+  {
+    /* USER CODE BEGIN W1_UsageFault_IRQn 0 */
+    /* USER CODE END W1_UsageFault_IRQn 0 */
+  }
+}
+
+/**
+  * @brief This function handles System service call via SWI instruction.
+  */
+void SVC_Handler(void)
+{
+  /* USER CODE BEGIN SVCall_IRQn 0 */
+
+  /* USER CODE END SVCall_IRQn 0 */
+  /* USER CODE BEGIN SVCall_IRQn 1 */
+
+  /* USER CODE END SVCall_IRQn 1 */
+}
+
+/**
+  * @brief This function handles Debug monitor.
+  */
+void DebugMon_Handler(void)
+{
+  /* USER CODE BEGIN DebugMonitor_IRQn 0 */
+
+  /* USER CODE END DebugMonitor_IRQn 0 */
+  /* USER CODE BEGIN DebugMonitor_IRQn 1 */
+
+  /* USER CODE END DebugMonitor_IRQn 1 */
+}
+
+/**
+  * @brief This function handles Pendable request for system service.
+  */
+void PendSV_Handler(void)
+{
+  /* USER CODE BEGIN PendSV_IRQn 0 */
+
+  /* USER CODE END PendSV_IRQn 0 */
+  /* USER CODE BEGIN PendSV_IRQn 1 */
+
+  /* USER CODE END PendSV_IRQn 1 */
+}
+
+/**
+  * @brief This function handles System tick timer.
+  */
+void SysTick_Handler(void)
+{
+  /* USER CODE BEGIN SysTick_IRQn 0 */
+
+  /* USER CODE END SysTick_IRQn 0 */
+  HAL_IncTick();
+  /* USER CODE BEGIN SysTick_IRQn 1 */
+
+  /* USER CODE END SysTick_IRQn 1 */
+}
+
+/******************************************************************************/
+/* STM32F1xx Peripheral Interrupt Handlers                                    */
+/* Add here the Interrupt Handlers for the used peripherals.                  */
+/* For the available peripheral interrupt handler names,                      */
+/* please refer to the startup file (startup_stm32f1xx.s).                    */
+/******************************************************************************/
+
+/**
+  * @brief This function handles DMA1 channel1 global interrupt.
+  */
+void DMA1_Channel1_IRQHandler(void)
+{
+  /* USER CODE BEGIN DMA1_Channel1_IRQn 0 */
+  HAL_GPIO_WritePin(DBG4_GPIO_Port, DBG4_Pin, GPIO_PIN_SET);
+  /* USER CODE END DMA1_Channel1_IRQn 0 */
+  HAL_DMA_IRQHandler(&hdma_adc1);
+  /* USER CODE BEGIN DMA1_Channel1_IRQn 1 */
+HAL_GPIO_WritePin(DBG4_GPIO_Port, DBG4_Pin, GPIO_PIN_RESET);
+  /* USER CODE END DMA1_Channel1_IRQn 1 */
+}
+
+/**
+  * @brief This function handles ADC1 and ADC2 global interrupts.
+  */
+void ADC1_2_IRQHandler(void)
+{
+  /* USER CODE BEGIN ADC1_2_IRQn 0 */
+HAL_GPIO_WritePin(DBG4_GPIO_Port, DBG4_Pin, GPIO_PIN_SET);
+  /* USER CODE END ADC1_2_IRQn 0 */
+  HAL_ADC_IRQHandler(&hadc1);
+  /* USER CODE BEGIN ADC1_2_IRQn 1 */
+HAL_GPIO_WritePin(DBG4_GPIO_Port, DBG4_Pin, GPIO_PIN_RESET);
+  /* USER CODE END ADC1_2_IRQn 1 */
+}
+
+/**
+  * @brief This function handles CAN1 RX0 interrupt.
+  */
+void CAN1_RX0_IRQHandler(void)
+{
+  /* USER CODE BEGIN CAN1_RX0_IRQn 0 */
+  HAL_GPIO_WritePin(DBG5_GPIO_Port, DBG5_Pin, GPIO_PIN_SET);
+  /* USER CODE END CAN1_RX0_IRQn 0 */
+  HAL_CAN_IRQHandler(&hcan1);
+  /* USER CODE BEGIN CAN1_RX0_IRQn 1 */
+  HAL_GPIO_WritePin(DBG5_GPIO_Port, DBG5_Pin, GPIO_PIN_RESET);
+  /* USER CODE END CAN1_RX0_IRQn 1 */
+}
+
+/**
+  * @brief This function handles TIM3 global interrupt.
+  */
+void TIM3_IRQHandler(void)
+{
+  /* USER CODE BEGIN TIM3_IRQn 0 */
+  HAL_GPIO_WritePin(DBG4_GPIO_Port, DBG4_Pin, GPIO_PIN_SET);
+  /* USER CODE END TIM3_IRQn 0 */
+  HAL_TIM_IRQHandler(&htim3);
+  /* USER CODE BEGIN TIM3_IRQn 1 */
+  HAL_GPIO_WritePin(DBG4_GPIO_Port, DBG4_Pin, GPIO_PIN_RESET);
+  /* USER CODE END TIM3_IRQn 1 */
+}
+
+/**
+  * @brief This function handles USART1 global interrupt.
+  */
+void USART1_IRQHandler(void)
+{
+  /* USER CODE BEGIN USART1_IRQn 0 */
+
+  /* USER CODE END USART1_IRQn 0 */
+  HAL_UART_IRQHandler(&huart1);
+  /* USER CODE BEGIN USART1_IRQn 1 */
+
+  /* USER CODE END USART1_IRQn 1 */
+}
+
+/**
+  * @brief This function handles USART2 global interrupt.
+  */
+void USART2_IRQHandler(void)
+{
+  /* USER CODE BEGIN USART2_IRQn 0 */
+  HAL_GPIO_WritePin(DBG2_GPIO_Port, DBG2_Pin, GPIO_PIN_SET);
+  /* USER CODE END USART2_IRQn 0 */
+  HAL_UART_IRQHandler(&huart2);
+  /* USER CODE BEGIN USART2_IRQn 1 */
+  HAL_GPIO_WritePin(DBG2_GPIO_Port, DBG2_Pin, GPIO_PIN_RESET);
+  /* USER CODE END USART2_IRQn 1 */
+}
+
+/**
+  * @brief This function handles USART3 global interrupt.
+  */
+void USART3_IRQHandler(void)
+{
+  /* USER CODE BEGIN USART3_IRQn 0 */
+  HAL_GPIO_WritePin(DBG3_GPIO_Port, DBG3_Pin, GPIO_PIN_SET);
+  /* USER CODE END USART3_IRQn 0 */
+  HAL_UART_IRQHandler(&huart3);
+  /* USER CODE BEGIN USART3_IRQn 1 */
+  HAL_GPIO_WritePin(DBG3_GPIO_Port, DBG3_Pin, GPIO_PIN_RESET);
+  /* USER CODE END USART3_IRQn 1 */
+}
+
+/**
+  * @brief This function handles UART5 global interrupt.
+  */
+void UART5_IRQHandler(void)
+{
+  /* USER CODE BEGIN UART5_IRQn 0 */
+  HAL_GPIO_WritePin(DBG1_GPIO_Port, DBG1_Pin, GPIO_PIN_SET);
+  /* USER CODE END UART5_IRQn 0 */
+  HAL_UART_IRQHandler(&huart5);
+  /* USER CODE BEGIN UART5_IRQn 1 */
+  HAL_GPIO_WritePin(DBG1_GPIO_Port, DBG1_Pin, GPIO_PIN_RESET);
+  /* USER CODE END UART5_IRQn 1 */
+}
+
+/**
+  * @brief This function handles CAN2 TX interrupt.
+  */
+void CAN2_TX_IRQHandler(void)
+{
+  /* USER CODE BEGIN CAN2_TX_IRQn 0 */
+  HAL_GPIO_WritePin(DBG5_GPIO_Port, DBG5_Pin, GPIO_PIN_SET);
+  /* USER CODE END CAN2_TX_IRQn 0 */
+  HAL_CAN_IRQHandler(&hcan2);
+  /* USER CODE BEGIN CAN2_TX_IRQn 1 */
+  HAL_GPIO_WritePin(DBG5_GPIO_Port, DBG5_Pin, GPIO_PIN_RESET);
+  /* USER CODE END CAN2_TX_IRQn 1 */
+}
+
+/**
+  * @brief This function handles CAN2 RX1 interrupt.
+  */
+void CAN2_RX1_IRQHandler(void)
+{
+  /* USER CODE BEGIN CAN2_RX1_IRQn 0 */
+  HAL_GPIO_WritePin(DBG5_GPIO_Port, DBG5_Pin, GPIO_PIN_SET);
+  /* USER CODE END CAN2_RX1_IRQn 0 */
+  HAL_CAN_IRQHandler(&hcan2);
+  /* USER CODE BEGIN CAN2_RX1_IRQn 1 */
+  HAL_GPIO_WritePin(DBG5_GPIO_Port, DBG5_Pin, GPIO_PIN_RESET);
+  /* USER CODE END CAN2_RX1_IRQn 1 */
+}
+
+/* USER CODE BEGIN 1 */
+
+/* USER CODE END 1 */
diff -ruN /Users/colorbass/STM32CubeIDE/workspace_1.12.0/CCSModuleSW30Web/Core/Src/tim.c /Users/colorbass/STM32CubeIDE/workspace_1.12.0/fork/CCSModuleSW30Web/Core/Src/tim.c
--- /Users/colorbass/STM32CubeIDE/workspace_1.12.0/CCSModuleSW30Web/Core/Src/tim.c	2026-03-19 02:09:51
+++ /Users/colorbass/STM32CubeIDE/workspace_1.12.0/fork/CCSModuleSW30Web/Core/Src/tim.c	2026-05-04 17:59:57
@@ -57,31 +57,31 @@
   {
     Error_Handler();
   }
-  if (HAL_TIM_PWM_Init(&htim3) != HAL_OK)
+  if (HAL_TIM_OC_Init(&htim3) != HAL_OK)
   {
     Error_Handler();
   }
-  if (HAL_TIM_OC_Init(&htim3) != HAL_OK)
+  if (HAL_TIM_PWM_Init(&htim3) != HAL_OK)
   {
     Error_Handler();
   }
-  sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET;
+  sMasterConfig.MasterOutputTrigger = TIM_TRGO_OC1;
   sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;
   if (HAL_TIMEx_MasterConfigSynchronization(&htim3, &sMasterConfig) != HAL_OK)
   {
     Error_Handler();
   }
-  sConfigOC.OCMode = TIM_OCMODE_PWM1;
-  sConfigOC.Pulse = 0;
+  sConfigOC.OCMode = TIM_OCMODE_TIMING;
+  sConfigOC.Pulse = 1;
   sConfigOC.OCPolarity = TIM_OCPOLARITY_HIGH;
   sConfigOC.OCFastMode = TIM_OCFAST_DISABLE;
-  if (HAL_TIM_PWM_ConfigChannel(&htim3, &sConfigOC, TIM_CHANNEL_2) != HAL_OK)
+  if (HAL_TIM_OC_ConfigChannel(&htim3, &sConfigOC, TIM_CHANNEL_1) != HAL_OK)
   {
     Error_Handler();
   }
-  sConfigOC.OCMode = TIM_OCMODE_TIMING;
-  sConfigOC.Pulse = 1;
-  if (HAL_TIM_OC_ConfigChannel(&htim3, &sConfigOC, TIM_CHANNEL_1) != HAL_OK)
+  sConfigOC.OCMode = TIM_OCMODE_PWM1;
+  sConfigOC.Pulse = 0;
+  if (HAL_TIM_PWM_ConfigChannel(&htim3, &sConfigOC, TIM_CHANNEL_2) != HAL_OK)
   {
     Error_Handler();
   }
diff -ruN /Users/colorbass/STM32CubeIDE/workspace_1.12.0/CCSModuleSW30Web/Core/Startup/startup_stm32f107vctx.s /Users/colorbass/STM32CubeIDE/workspace_1.12.0/fork/CCSModuleSW30Web/Core/Startup/startup_stm32f107vctx.s
--- /Users/colorbass/STM32CubeIDE/workspace_1.12.0/CCSModuleSW30Web/Core/Startup/startup_stm32f107vctx.s	2025-12-12 01:47:25
+++ /Users/colorbass/STM32CubeIDE/workspace_1.12.0/fork/CCSModuleSW30Web/Core/Startup/startup_stm32f107vctx.s	2026-04-27 17:45:55
@@ -59,7 +59,6 @@
   .weak Reset_Handler
   .type Reset_Handler, %function
 Reset_Handler:
-	ldr   sp, =_estack     /* set stack pointer */
 
 /* Call the clock system initialization function.*/
     bl  SystemInit
