# Журнал изменений (сессия чата): `fork/CCSModuleSW30Web` Документ фиксирует доработки проекта **CCSModuleSW30Web** в ветке/каталоге форка `/Users/colorbass/STM32CubeIDE/workspace_1.12.0/fork/CCSModuleSW30Web`, обсуждавшиеся и вносившиеся в рамках описанной сессии (UART, ADC/DMA, CP, отладка IRQ, оптимизация `-Ofast` для кода из прерываний). --- ## 1. UART и протокол ### 1.1. UART3 (Everest / `serial.c`) - Таймаут «нет связи с хостом»:** `EVEREST_TIMEOUT_MS` = **5000** мс. - Жёсткий реинициал при отсутствии RX:** `UART3_REINIT_TIMEOUT_MS` = **1500** мс (с защитой от слишком частых реинициалов через `uart3_last_reinit_tick`). - Расширено логирование путей сброса/ошибок приёма и ошибок HAL для диагностики «таймаут без остановки UART3». - Колбэки и вспомогательные функции, вызываемые из контекста прерывания, помечены **`ISR_FAST`** (см. раздел 6): `CCS_RxEventCallback`, `HAL_UART_ErrorCallback`, `uart3_log_hal_error`, `uart3_arm_rx_or_log`, цепочка разбора пакета (`process_received_packet`, `crc16_ibm`, `expected_payload_len`, `apply_command`). ### 1.2. UART2 / `serial_control.c` - Отдельная логика **`SC_UART2_Watchdog()`**, вызывается из **`SC_Task()`** (не из IRQ). - Константы: - **`SC_UART2_REINIT_TIMEOUT_MS`** = **500** мс — порог для жёсткого реинициала при отсутствии пакетов; - **`SC_UART2_PACKET_TIMEOUT_MS`** = **5000** мс — таймаут коммуникации. - Сценарий **новый пакет при `BUSY_TX`**: при необходимости **`Abort_IT`**, сброс направления RS-485, затем повторная инициализация UART и приём `ReceiveToIdle_IT` (защита от обрыва TX из-за агрессивного watchdog). - Отдельная ветка **жёсткого реинициала при `BUSY_TX`** с логом `USART2 BUSY_TX: hard reinit` (отслеживание `sc_uart2_last_busy_tx_reinit_packet_tick`). - HAL-колбэки **`HAL_UARTEx_RxEventCallback`**, **`HAL_UART_TxCpltCallback`** помечены **`ISR_FAST`**. ### 1.3. `SC_SendPacket` и стек CRC/кодирования - Для единообразной оптимизации пути «IRQ → ответ» на функции **`calculate_crc32`**, **`encode_packet`**, **`parse_packet`**, **`process_received_packet`** и публичную **`SC_SendPacket`** добавлен **`ISR_FAST`**. - В **`Core/Inc/serial_control.h`**: подключение **`isr_opt.h`**, прототип **`ISR_FAST void SC_SendPacket(...)`** (согласованность с определением в `.c`). **Замечание:** `SC_SendPacket` вызывается и из основного потока; для GCC вся функция компилируется с `-Ofast`. При необходимости строгого разделения можно вынести отдельную версию «только из IRQ». --- ## 2. Отладочные линии DBG в `stm32f1xx_it.c` На время входа/выхода из выбранных обработчиков прерываний поднимается/опускается соответствующий GPIO — удобно для осциллографа (длительность IRQ). | Линия | Обработчик | |--------|------------| | **DBG1** | `UART5_IRQHandler` | | **DBG2** | `USART2_IRQHandler` | | **DBG3** | `USART3_IRQHandler` | | **DBG4** | `DMA1_Channel1_IRQHandler`, `ADC1_2_IRQHandler`, `TIM3_IRQHandler` | | **DBG5** | `CAN1_RX0_IRQHandler`, `CAN2_TX_IRQHandler`, `CAN2_RX1_IRQHandler` | | — | `USART1_IRQHandler` — без обёртки DBG (по согласованию) | В **`DMA1_Channel1_IRQHandler`** вызывается **`HAL_DMA_IRQHandler(&hdma_adc1)`** для цепочки ADC+DMA. Для всего файла **`stm32f1xx_it.c`** под GCC добавлено: ```c #pragma GCC optimize("Ofast") ``` (в блоке `USER CODE BEGIN Includes`). --- ## 3. ADC: DMA, глобальные данные, колбэк - Файлы **`adc.c` / `adc.h`**: структура **`ADC_ScanData_t`**, глобально **`volatile ADC_ScanData_t adc_data`** с полями сырых каналов (`in3_raw`, `cp_raw`, `ntc1_raw`, `ntc2_raw`, `temp_sensor_raw`, `vrefint_raw` и т.д. по фактическому объявлению в заголовке). - **`HAL_ADC_ConvCpltCallback`**: копирование из буфера DMA в **`adc_data`**, помечен **`ISR_FAST`**. - Публичная **`ADC_ScanStart()`** — запуск сканирования (после калибровки вызывается из инициализации платы). - **`board.c`**: после **`HAL_ADCEx_Calibration_Start`** вызывается **`ADC_ScanStart()`**; **`CONN_ReadTemp`** читает **`adc_data.ntc1_raw` / `ntc2_raw`** вместо блокирующего опроса ADC. **Диагностика (из обсуждения):** если не вызываются **`HAL_ADC_ConvCpltCallback`** / **`HAL_DMA_IRQHandler`**, проверять: срабатывание триггера ADC (например, **TIM3 TRGO**), работу TIM3, порядок инициализации DMA/NVIC, срабатывание **`DMA1_Channel1_IRQHandler`**. --- ## 4. CP (`cp.c` / `cp.h`) - Измерение опоры на **`adc_data.cp_raw`** (и при необходимости **`vrefint_raw`** по текущей реализации в коде). - Логика классификации/порогов приведена к варианту, согласованному с основным **CCSModuleSW30Web** (не форк). - Сэмпл по таймеру: уход от тяжёлой работы в IRQ OC — использование **`HAL_TIM_OC_Start`** без прерывания по сравнению, обновление напряжения в **`CP_GetVoltage()`** / основном цикле (**`CP_Loop`** опирается на **`CP_GetState()`** и т.п. по фактическому коду). --- ## 5. Отладочный UART (`debug.c`) При **`#ifndef USE_WEB_INTERFACE`** (или эквивалентной ветке сборки в файле): колбэк **`HAL_UARTEx_RxEventCallback`** и **`debug_rx_interrupt`** помечены **`ISR_FAST`**. --- ## 6. Оптимизация `-Ofast` для кода из прерываний ### 6.1. Макрос `ISR_FAST` Файл **`Core/Inc/isr_opt.h`**: - **GCC:** `#define ISR_FAST __attribute__((optimize("Ofast")))` - **Иное:** пустой макрос. ### 6.2. Где используется (по состоянию репозитория) | Файл | Элементы с `ISR_FAST` / pragma | |------|--------------------------------| | `stm32f1xx_it.c` | `#pragma GCC optimize("Ofast")` на весь файл (GCC) | | `adc.c` | `HAL_ADC_ConvCpltCallback` | | `serial.c` | `CCS_RxEventCallback`, `HAL_UART_ErrorCallback`, `uart3_log_hal_error`, `uart3_arm_rx_or_log`, `process_received_packet`, `crc16_ibm`, `expected_payload_len`, `apply_command` | | `serial_control.c` | `HAL_UARTEx_RxEventCallback`, `HAL_UART_TxCpltCallback`, `calculate_crc32`, `encode_packet`, `parse_packet`, `process_received_packet`, `SC_SendPacket` | | `serial_control.h` | прототип `SC_SendPacket` + `#include "isr_opt.h"` | | `psu_control.c` | `HAL_CAN_RxFifo1MsgPendingCallback` | | `debug.c` | см. раздел 5 | --- ## 7. Ограничения и переносимость - **`ISR_FAST`** и pragma в **`stm32f1xx_it.c`** рассчитаны на **GCC** (STM32CubeIDE по умолчанию). Для **IAR / ARM Compiler 6** потребуется отдельная стратегия (прагмы/ключи проекта). - **`-Ofast`** допускает агрессивные преобразования с плавающей точкой и перестановки, влияющие на строго воспроизводимую арифметику; для критичных вычислений вне IRQ при необходимости ограничивайте область оптимизации. --- ## 8. Затронутые пути (краткий список) - `Core/Inc/isr_opt.h` — новый/центральный заголовок оптимизации IRQ. - `Core/Inc/serial_control.h` — `isr_opt.h`, `ISR_FAST` у `SC_SendPacket`. - `Core/Src/stm32f1xx_it.c` — DBG, DMA ADC, pragma `Ofast`. - `Core/Src/adc.c`, `Core/Inc/adc.h` — DMA, `adc_data`, `ADC_ScanStart`, колбэк. - `Core/Src/board.c` — калибровка, старт скана, температура из `adc_data`. - `Core/Src/cp.c`, `Core/Inc/cp.h` — CP и ADC. - `Core/Src/serial.c` — UART3, таймауты, логи, `ISR_FAST`. - `Core/Src/serial_control.c` — UART2, watchdog, `ISR_FAST`. - `Core/Src/psu_control.c` — CAN RX callback. - `Core/Src/debug.c` — отладочный UART под условием сборки. - `Core/Src/dma.c`, `gpio.c`, `main.h` — по необходимости для DMA1 Ch1 и DBG-пинов. --- *Документ сгенерирован для фиксации контекста сессии; при дальнейших правках кода имеет смысл обновлять соответствующие разделы вручную.*