Author SHA1 Message Date
Andrey 4b1c98d57f Убрать поздний триггер из разрешения адреса захвата
Продвигать кольцевой указатель на каждом отсчёте и заранее вычислять начало pretrigger.
Сохранить точный адрес срабатывания без дополнительного такта задержки.
2026-11-13 20:33:18 +03:00
Andrey b724b40b84 Добавить многоклиентный CAN и общий транспорт FTDI
Выделить переносимое C-ядро CAN485 и Linux-порт SocketCAN/RS485 с наблюдателями и одним владельцем передачи.
Подключить Qt CAN к общему менеджеру консоли, сохранив независимое закрытие каналов.
2026-11-13 20:33:18 +03:00
Andrey 41f5bf5e94 Добавить общий кодек и Qt-порт Modbus
Реализовать маршруты TCP/RTU, корреляцию ответов, настройки и общий канал Linux-консоли FTDI.
Проверить протокольные эталоны и взаимодействие Qt с единым C-ядром.
2026-11-13 20:32:52 +03:00
Andrey a640f98f74 Добавить непрерывные окна и цифровой триггер Scope 2026-11-09 02:51:28 +03:00
Andrey f0edb70dbe Добавить ядро цифрового Scope и адаптер декодеров DSView 2026-11-09 02:03:13 +03:00
Andrey 6d59c3812c Улучшить обработку пропусков RJ2 и сборку DSView 2026-11-09 00:58:14 +03:00
Andrey e144c3e86a Добавить общие блоки Zynq, Ethernet DSView и декодер ШИМ 2026-11-09 00:15:26 +03:00
Andrey fa2ab3cc65 Merge origin/ump-v4 into main
Combine Flash CAN updates, signal processing and HOPE pin fixes with current Modbus/GAS, STM32 ports and CCS release exports. Resolve protocol, documentation and Qt conflicts; deduplicate Android JNI sources and include gauge/IGBT sources in host builds.
2026-11-07 01:32:27 +03:00
Andrey 5d2831794d Merge origin/main: resolve ProtoCAN Boot conflicts and preserve legacy STM32 ports 2026-11-07 01:15:26 +03:00
Andrey a1b2835457 Добавить общий каталог сигналов и плавную анимацию кота
Добавить общую модель двухканальных сигналов и анимированных XY-сцен
для предпросмотра, экспорта CSV и подготовки синхронных каналов.
Построить округлый силуэт кота кривыми Безье, добавить овальные глаза,
загнутый хвост и плавную походку: 32 позы по 125 точек, всего 4000 пар.

Проверка: 71 тест каталога, диапазонов, CSV и управления генератором.
2026-11-06 23:48:41 +03:00
Andrey dc4b0ab71b Исправить распиновку входов IGBT платы HOPE 2026-11-06 23:08:18 +03:00
Andrey cf75c5c855 Добавить общую графику прибора DEIF для HDMI 2026-11-06 21:21:36 +03:00
Andrey 491fa11569 Добавить аппаратные импульсы IGBT для HOPE G474 2026-11-06 16:33:17 +03:00
Andrey 149d19f3f9 Добавить аппаратный IGBT v4 и автономный стенд DEIF
Реализовать наносекундное управление IGBT для HOPE STM32G474 и клиент обмена с проверкой версии и записанных параметров.
Расширить Android/JNI API DEIF, настройки и локальную симуляцию; добавить тесты и документацию.
2026-11-06 16:25:47 +03:00
Andrey 45a34db657 Исправить каталог выпуска прошивки TMS320F2812
Размещать основной SCI8-комплект F2812 в flash, включая BIN, OUT, HEX,
карты, manifest и SHA-256. Передавать выбранный путь в указатель
последней сборки и экспорт; сохранить раскладку остальных процессоров.

Добавить проверку раскладки, паспортов и экспорта и описать правило.
Проверка: пять тестов общей сборки и реальный postbuild текущего OUT;
побайтовая сверка BIN после переноса.
2026-11-06 16:20:37 +03:00
Andrey bf5f094249 Расширить DEIF и генератор сигналов, подключить исходники KDiff3
Добавить общую модель сигналов XY и адаптировать генератор к двум каналам.
Расширить Android-порт DEIF общим контроллером рабочей области и проверками.
Подключить официальный репозиторий KDiff3 вложенным подмодулем.
2026-10-29 23:32:03 +03:00
Andrey 41e24629ce Расширить DEIF, загрузку CAN и общую обработку сигналов
Добавить общее ядро DEIF, эмуляцию приборов и переносимые панели Python/Qt.
Расширить загрузчики F2812 и F28335, обновление Flash и профиль STM Invertor.
Добавить альтернативный МНК Eigen, модели неисправностей и диагностику сигналов.
Обновить справочники устройств, проекты CCS и регрессионные проверки.
2026-10-24 15:40:51 +03:00
Andrey e52ba797e4 feat(set-protocol): Добавь DEIF XDi, STM Invertor и порт HOPE G474
Объедини реализацию DEIF в C99-ядре, чтобы Python и Android
использовали один кодек и общие эталонные кадры.
Добавь две GAS-проекции единой карты STM Invertor и аппаратные
порты эмулятора и загрузчика для платы HOPE STM32G474VET6.

Проверки: сборка MSVC Debug, 24 теста CTest, 30 тестов Python
и 29 дополнительных проверок, синтаксис 16 файлов Python.
2026-10-24 15:39:59 +03:00
Andrey 83fb9b6fe8 Обнови спецификацию и таблицы единого Modbus 2026-10-23 16:15:37 +03:00
Andrey 41f5b879fc Объедини Modbus в один тип с функциями и количеством 1–4 2026-10-23 16:15:11 +03:00
Andrey f17c124f0e docs: Согласуй документацию ProtoCAN и инструментов сборки
Обнови спецификацию GAS 0x3/0x4, реестр устройств и описание загрузочных сервисов одновременно в Markdown, HTML и XLSX.

Свяжи новые аппаратные порты, глобальное время и сборку C2000/ПЛИС с корневыми инструкциями, чтобы проекты подключались по одному актуальному контракту.
2026-10-23 14:16:22 +03:00
Andrey 2da7e7b525 feat(global-time): Добавь общие часы и порт TMS320F28335
Вынеси программные часы, коррекцию по ProtoCAN RTCSETUP и атомарную метку логгера в переносимое ядро без глобального состояния.

Подключи eCAN-A и CPU Timer2 отдельным портом F28335; зафиксируй календарные границы, переполнение, задержку RX и защиту IRQ в хостовых тестах.
2026-10-23 14:16:21 +03:00
Andrey 62c0492bfd feat(firmware-build): Добавь сборку и паспорта проектов ПЛИС
Подключи ISE, Vivado и Quartus к общему итератору версии и HDL-паспорту. Проверяй новый bit/sof до создания manifest, SHA-256 и архива выпуска.

Добавь установку локальных команд ISE, инструкции переноса и регрессионные проверки успешных и прерванных сборок.
2026-10-23 14:16:21 +03:00
Andrey 5bf3167064 build(firmware-info): Объедини подготовку и выпуск образов C2000
Направь CCS precompile/postcompile в общий c2000_build, чтобы резервирование версии, проверка EEPROM, MAP, SCI8 и Flash выполнялись одним процессом перед экспортом.

Сохраняй варианты eeprom, flash, can и rs в одном проверенном комплекте с manifest и SHA-256. Ошибка проверки блокирует постоянный выпуск и копирование устаревших образов.
2026-10-23 14:16:20 +03:00
Andrey c6390ae1c9 feat(protocan-boot): Добавь порты MCU и сервисы загрузки
Обеспечь единый процесс обновления для STM32F103/F407/G474 и TMS320F2812/F28335: discovery, служебные ответы, BUSY, тайм-аут сессии и подтверждение приложения. Добавь самостоятельные проекты CCS, аппаратные хранилища и Python-клиент.

Совместимость: структуры конфигурации и порта расширены, поэтому потребители должны пересобраться и обнулить новые поля. Для C28x callbacks используют pcan_boot_byte_t; периодический pcan_boot_poll обслуживает discovery и настроенный тайм-аут.
2026-10-23 14:16:19 +03:00
Andrey 876b58517c feat(set-protocol): Раздели GAS и добавь пакетный сбор регистров
Сохрани адресацию отдельных регистров GAS 0x3 и выдели слотам тип 0x4 с маской Word0. Добавь единое C-ядро GAS_WATCH2, тонкие Python/JNI-порты и проверки общих эталонных байтов.

Совместимость: тип 0x4 больше не обслуживает Modbus Coil. Потребителям PCAN_MSG_MODBUS_COIL и ProtoCanMsgToModbusCoil нужно перейти на GAS_SLOT и отдельный API слотов; регистровый GAS остаётся на 0x3.
2026-10-23 14:14:48 +03:00
Andrey 6ecf057a86 feat(c2000-linker): Добавить помощник настройки линкера C2000
Добавить генерацию карт COFF для TMS320F28335 и TMS320F2812, проверку CMD/MAP и русскую инструкцию.

Проверки: 14 тестов, включая четыре реальные линковки TI для RAM и Flash.
2026-10-19 16:33:40 +03:00
Andrey d42f2e1622 Перенести итератор версии прошивки в общий генератор
Увеличивать версию при прямом подключении precompile из CCS и Keil.
Сохранять счётчик атомарно и оставлять ручной режим без включённого флага.
Добавить проверки итератора и обновить примеры подключения.
2026-10-19 12:02:07 +03:00
Andrey 0c4eab4615 Добавить общий конструктор CAN-кадров для Qt 2026-10-17 14:43:13 +03:00
Andrey 5af8a8e9c8 Добавить общую Qt-консоль с фильтрами и экспортом 2026-10-17 14:43:12 +03:00
Andrey f613101124 Перезапускать импульс светодиода при каждом приёме пакета 2026-10-17 14:43:12 +03:00
Andrey cf65439400 Добавить выпуск и экспорт Flash-образов C2000 2026-10-17 14:43:11 +03:00
Andrey a5e46d4627 Расширить обмен по шинам, CAN-адаптеры и обработку графиков
Добавить очереди операций PBUS/SBUS, общую консоль, настройки Candle и SLCAN, декодеры DSView и обработку плотных графиков. Обновить протокол Бальзам и проверки общих компонентов.
2026-10-17 14:36:14 +03:00
Andrey 95c8b8ac7d Поддержать компактные записи логгера УМП v4
Разрешить 12-словные записи в запросах RTU и CAN. Распознавать статус v4 и декодировать оставшиеся сигналы с сохранением поддержки архивов v2/v3.
2026-10-12 12:26:37 +03:00
Andrey 32e2fbedc0 Поддержать компактные записи логгера УМП v4
Разрешить 12-словные записи в запросах RTU и CAN. Распознавать статус v4 и декодировать оставшиеся сигналы с сохранением поддержки архивов v2/v3.
2026-10-12 12:25:52 +03:00
Andrey bbb4bc2b9d Уточнить обработку плотных трендов и восстановление сигналов 2026-10-12 00:48:15 +03:00
Andrey 20454ff7fa Добавить поддержку GAS 167 и УМП, улучшить обмен по CAN и последовательному порту 2026-10-11 21:23:21 +03:00
Andrey 3c0f6fd9e6 Добавить загрузку F28335 по ProtoCAN и сервисные команды клиента 2026-10-11 03:24:44 +03:00
Andrey f6d45b70d4 Добавить порты ProtoCAN для STM32 и F28335 с загрузкой A/B 2026-10-11 03:24:41 +03:00
Andrey f1a7bcd8bc Support shared serial ports and optional verification in TMS flashing 2026-10-09 16:41:47 +03:00
Andrey 226c2ca599 chore(merge): объедини pysetterminal с main
Сохрани актуальный генератор firmware identity с экспортом всей папки сборки и временем UTC+3 при объединении веток.
2026-10-09 11:04:32 +03:00
Andrey f2956b54cd merge(deif): объедини Android-компоненты с main 2026-10-09 10:55:08 +03:00
Andrey 86ece3ea90 Extract reusable byte work panel with configurable terminal addressing 2026-10-09 08:56:16 +03:00
Andrey fe9b5a246e Checkpoint EEPROM, firmware analysis and instrument protocol updates 2026-10-08 21:51:44 +03:00
Andrey b0c0c05cfa Add shared PySetTerminal with asynchronous cancellable macros 2026-10-08 18:34:41 +03:00
Andrey eab8dc5e0a fix(firmware-build): support CCS artifact paths and bootstrap identity config 2026-10-08 17:57:04 +03:00
Andrey 131f306131 fix(firmware-info): используй UTC+3 в именах папок
Переведи только время имени архива в UTC+3, сохрани UTC в метаданных и заголовке. Проверь переход на следующий день и копирование текущей папки.
2026-10-08 17:05:04 +03:00
Andrey 4fc0ad4e14 feat(firmware-info): копируй папку текущей сборки целиком
Добавь каталог назначения последним аргументом postcompile CCS и Keil. Копируй только архив текущего запуска с сохранением имени папки, всех файлов и проверкой SHA-256. Обнови MD-команды и проверки выбора папки, вложенных файлов и ошибок экспорта.
2026-10-08 16:26:21 +03:00
Andrey da055c2787 feat(firmware-info): архивируй сборки по хешу и дате
Создай в postcompile CCS и Keil папку по commit исходников и UTC-времени precompile. Сохрани точные образы, manifest, SHA-256 и метаданные, сохраняя прежние выходные файлы. Опиши копирование каталогов в SETGUI и проверь разные даты, целостность и Git-метаданные.
2026-10-08 15:31:13 +03:00
Andrey 8fc2e1b5cf fix(firmware-info): подключи Keil к JSON-схеме версии
Добавь prepare/seal для Keil через общий identity.py, образец конфигурации и команды Before/After Build. Для новой схемы не требуется отдельная release-конфигурация CMD или SETGUI. Проверь HEX/BIN, SHA-256, аргументы и пути с пробелами.
2026-10-08 15:13:34 +03:00
Andrey b5b2d1ae37 feat(firmware-info): добавь pre/post-build для CCS и Keil
Подключи общий генератор версии и SCI8-конвертацию через templates. Сохрани метаданные и SHA-256 готового BIN, совместимость с Python 3.8 и прежний SETGUI preflight. Опиши настройку CCS и локальное копирование результатов.
2026-10-08 14:58:27 +03:00
Andrey c011c2957b Track completed Single acquisitions and persist recent addresses 2026-10-07 12:32:29 +03:00
Andrey 6047ceac89 Pause automatic waveform transfers on hardware Stop 2026-10-07 12:22:00 +03:00
Andrey 79b0cde20e Add native QCustomPlot renderer and shared plot adapters 2026-10-07 11:33:14 +03:00
Andrey 90046de7fd Добавить идентификацию прошивки и чтение EEPROM Бальзам-167 2026-10-05 17:48:23 +03:00
Andrey 0e3d89e1ee Добавить протокол DEIF, диагностику CAN и сохранение сессий 2026-10-04 23:34:26 +03:00
Andrey 6c08eece61 Улучшить две шкалы, навигацию и формулы графиков 2026-10-04 23:34:26 +03:00
Andrey c7294830f9 Add shared CAN monitor sessions, protocol selection and HEX/DEC display 2026-10-03 22:53:51 +03:00
Andrey 427fc70100 docs: добавь поясняющие комментарии к модулям и инструментам 2026-10-02 16:46:19 +03:00
Andrey 6cbce6c360 Согласовать демо логгера УМП с постинтервалом в десять процентов банка 2026-10-02 16:41:26 +03:00
Andrey 3463e95eb3 Добавить общее перетаскивание графиков и независимые шкалы амплитуд 2026-10-02 16:41:26 +03:00
Andrey 025a3fde28 Исправить порядок слов BALZAM CAN и добавить поддержку пульта МПУ 2026-10-02 16:41:25 +03:00
992 changed files with 128735 additions and 1310 deletions
+3
View File
@@ -0,0 +1,3 @@
[submodule "third_party/kdiff3"]
path = third_party/kdiff3
url = https://invent.kde.org/sdk/kdiff3.git
+1 -1
View File
@@ -84,7 +84,7 @@ STM32F103RC, STM32F103ZE и STM32G474CE объявляют поддержку з
возвращают `PNAND_ERROR_WRITE_PROTECTED`, пока плата и порт не доработаны.
Рабочий пример полноценного G474-порта находится в соседнем проекте
`candleLight_fw`: `src/device/device_g4.c` отвечает за clock/GPIO,
`CANdle_stm32` (candleLight): `src/device/device_g4.c` отвечает за clock/GPIO,
`src/can/m_can.c` — за FDCAN, а `include/config.h` — за привязку платы
STM32G474VET6. Эти файлы остаются в прошивке, поскольку зависят от STM32 HAL,
USB gs_usb и конкретной разводки адаптера; переносимая логика протоколов
+20 -2
View File
@@ -24,6 +24,18 @@ templates/
## Что лежит
### FPGA и DSView
| Блок | Назначение |
|---|---|
| [Блоки логического анализатора](hdl/logic-analyzer/README.md) | Аппаратный триггер, BRAM, AXI и кольцевой буфер DDR |
| [Осциллограф](hdl/scope-acquisition/README.md) | Синхронизация каналов ADC, триггер, буфер и выдача записи |
| [Ethernet в FPGA](hdl/logic-udp-ethernet/README.md) | RGMII, MDIO для RTL8211F, UDP-поток и буфер восьми входов |
| [HDMI-отрисовка](hdl/logic-hdmi-preview/README.md) | График восьми цифровых каналов из входов или потока |
| [Трёхфазный ШИМ](hdl/vfd-pwm/README.md) | DDS, рампа, комплементарные выходы и мёртвое время |
| [DSView Ethernet](tools/dsview/zynq-ethernet/README.md) | Нативное подключение TCP/UDP, запуск и остановка |
| [ZNET](c/zynq-net/README.md) | C99-кодек Ethernet-команд ввода-вывода |
### C
| Библиотека | Что делает | Зависимости | Что нужно от платформы |
@@ -40,9 +52,10 @@ templates/
| [`c/set-protocol/ports/stm32f407-devboard-v1`](c/set-protocol/ports/stm32f407-devboard-v1) | доступ SETGUI к Modbus-регистрам F407 через CAN485 DevBoard_V1 | `pcan_modbus_server`, STM32 HAL CAN | bxCAN FIFO0 и callbacks карты регистров |
| [`c/set-protocol/ports/stm32-bxcan`](c/set-protocol/ports/stm32-bxcan) | порт прикладного ProtoCAN для STM32, бывший SETCAN; сохранён API `PROTOCAN_*` | STM32 HAL CAN/RTC/TIM + общее ядро `pcan_id` | classic bxCAN; настройки платы предоставляет прошивка |
| [`c/set-protocol/ports/tms320f2812`](c/set-protocol/ports/tms320f2812) | SETProtocol v2 firmware service по segmented classic CAN | `set_protocol`, `set_can`, `set_firmware` | CAN TX, Flash erase/write/read, optional signature policy и reboot |
| [`c/protocan-boot`](c/protocan-boot) | адресная прошивка по ProtoCAN: A/B-слоты, сессия, CRC32, verify и rollback-контракт | C99 | CAN TX, erase/write Flash, boot metadata, проверка образа и reboot |
| [`c/protocan-boot`](c/protocan-boot) | адресная прошивка по ProtoCAN: A/B-слоты, сессия, CRC32, verify и rollback-контракт | C99 | **STM32F103C8/F407VE/G474VE и TMS320F2812/F28335-порты в комплекте**; проекты STM32 подключены через templates, есть boot main и вход из приложения |
| [`c/rs485-boot`](c/rs485-boot) | прошивка по RS-485 в формате SETGUI v1: потоковый parser, CRC32 и resume | C99 | UART TX/RX, DE, Flash — **порты STM32F103 и STM32G474VET в комплекте** |
| [`c/rtc-service`](c/rtc-service) | RTC с резервированным backup-томом | `stdint.h` | доступ к RTC и backup-памяти — **порт K1921VK028 в комплекте** |
| [`c/global-time`](c/global-time) | программные часы 1 мс, ProtoCAN RTCSETUP, готовность платы и атомарная метка логгера | C99 | IRQ lock, CAN TX, такт 1 мс — **порт TMS320F28335 eCAN-A / CPU Timer2 в комплекте** |
| [`c/firmware-info`](c/firmware-info) | SemVer, build stamp и git build ID работающего образа | C99 | config-порты STM32F1/F4/G4 и К1921ВК028; упаковка для Modbus/SETGUI |
| [`c/parallel-nand`](c/parallel-nand) | parallel NAND x8: raw read/program/erase, профили Micron MT29F1G08 и Hynix HY27UF084G2M, bad-block marker и банковое окно GAS для SETGUI | C99, опционально `set-protocol/pcan_gas` | **порты TMS320F2812, STM32F103RC/ZE, STM32F407VE и STM32G474CEU6; запись требует управляемого WP#** |
@@ -62,8 +75,13 @@ templates/
### Инструменты
Исходники внешних приложений находятся в [`third_party`](third_party/README.md):
[`third_party/kdiff3`](third_party/kdiff3) содержит официальный репозиторий KDiff3
как вложенный Git submodule для развития сравнения файлов и каталогов в SETGUI.
| Инструмент | Что делает |
|---|---|
| [`tools/firmware-build/fpga`](tools/firmware-build/fpga/README.md) | общий итератор версии и HDL-паспорт для Xilinx ISE, Vivado и Altera/Intel Quartus; контроль `.bit`/`.sof`, manifest, SHA-256 и архив |
| [`tools/firmware-publish`](tools/firmware-publish) | единый BAT и конфигурации для проверки и публикации `.hex` Keil / `.bin` CCS 12 в каталоге SETGUI |
Общие тренды для Android GUI и SETGUI: [формат JSON, C99-ядро и адаптеры](c/set-protocol/docs/GUI_TRENDS.md).
@@ -118,7 +136,7 @@ git subtree pull --prefix lib/templates https://git.rd12.ru/Andrey/templates.git
| `KONOR_ds18b20` | st7789, keypad, menu, eeprom-ft24c256, can-sensor, ds18b20, firmware-info |
| `OpticalTester` | st7789, keypad, menu, eeprom-ft24c256 |
| `CAN_to_RS485` | set-protocol legacy transport, python/protocan |
| `candleLight_fw` | эталон разделения общей логики и G431/G474 FDCAN-порта; общий ProtoCAN Boot переносится по контракту `protocan-boot` |
| `CANdle_stm32` (candleLight) | G431/G474 FDCAN board-support; CAN/UART-загрузчик G474 и вход из приложения подключены к `protocan-boot/ports/stm32g474` через templates |
| `SETGUI` | python/protocan |
| `SETGUI`, Android GUI и новые устройства SET | set-protocol |
| `k1921vk028` | rtc-service |
+4
View File
@@ -1,3 +1,7 @@
# Сборка библиотеки can_sensor. Состав исходников и публичные include-пути задают подключение
# к проекту потребителя. Файл также собирает и регистрирует хостовые проверки; запускать их
# следует через CTest из каталога сборки.
cmake_minimum_required(VERSION 3.13)
project(can_sensor C)
+6
View File
@@ -1,3 +1,9 @@
/*
* Обмен настройками датчиков DS18B20 через однокадровые сообщения SETCAN. ROM идентифицирует
* датчик независимо от его позиции; прикладное состояние и отправка CAN предоставляются через
* интерфейс библиотеки.
*/
/**
* @file can_sensor.c
* @brief Однокадровый транспорт SETCAN SETTINGS для локаций DS18B20.
+6
View File
@@ -1,3 +1,9 @@
/*
* Обмен настройками датчиков DS18B20 через однокадровые сообщения SETCAN. ROM идентифицирует
* датчик независимо от его позиции; прикладное состояние и отправка CAN предоставляются через
* интерфейс библиотеки.
*/
/**
* @file can_sensor.h
* @brief Портируемый транспорт SETTINGS для привязки DS18B20 к локации.
@@ -1,3 +1,9 @@
/*
* Прямой bxCAN-порт датчиков для STM32F1 без HAL. Регистры контроллера обеспечивают передачу и
* приём SETCAN, а конфигурация платы задаёт подключение шины; это аппаратная реализация
* интерфейса can_sensor.
*/
/**
* @file can_sensor_stm32f1.c
* @brief Опросный порт can-sensor на bxCAN STM32F1 без STM32 HAL.
@@ -1,3 +1,9 @@
/*
* Прямой bxCAN-порт датчиков для STM32F1 без HAL. Регистры контроллера обеспечивают передачу и
* приём SETCAN, а конфигурация платы задаёт подключение шины; это аппаратная реализация
* интерфейса can_sensor.
*/
/**
* @file can_sensor_stm32f1.h
* @brief Опросный порт can-sensor на bxCAN микроконтроллеров STM32F1.
@@ -1,3 +1,9 @@
/*
* Конфигурация can-sensor для порта stm32f1. Макросы задают параметры сборки и ограничения,
* используемые исходниками этого модуля. Это образец для проекта: значения выводов, размеров
* памяти и параметров устройства необходимо согласовать с целевой платой.
*/
/**
* @file can_sensor_stm32f1_config.f103.template.h
* @brief Шаблон выводов CAN1 для STM32F103 без ремапа.
+6
View File
@@ -1,3 +1,9 @@
/*
* Проверки can_sensor: фиксируют ожидаемое поведение на воспроизводимых входных данных.
* Тестовые значения и подмены окружения относятся к проверке контракта; они не являются
* настройками рабочего устройства.
*/
#include "can_sensor.h"
#include <stdio.h>
+15
View File
@@ -0,0 +1,15 @@
cmake_minimum_required(VERSION 3.16) # Эта версия поддерживает используемые target_compile_features и CTest без платформенных расширений.
project(can485_monitor C) # Переносимое ядро собирается независимо от Linux-порта и приложения SETGUI.
add_library(can485_monitor STATIC src/can485_monitor.c) # Все платформы связываются с одним обработчиком команд и wire-форматов.
target_include_directories(can485_monitor PUBLIC include) # Потребитель получает только публичный C-контракт библиотеки.
target_compile_features(can485_monitor PUBLIC c_std_99) # Ядро не требует C11 и платформенных расширений языка.
include(CTest) # Стандартный BUILD_TESTING управляет автономной проверкой библиотеки.
if(BUILD_TESTING) # Host-проверка не требует Linux, Qt и физической CAN-шины.
add_executable(test_can485_monitor tests/test_can485_monitor.c) # Использует независимые wire-векторы и фикстуру аппаратных отказов.
target_link_libraries(test_can485_monitor PRIVATE can485_monitor) # Проверяет настоящую библиотеку, не тестовую копию алгоритма.
add_test(NAME can485_monitor_contract COMMAND test_can485_monitor) # Регистрирует единый поведенческий контракт для всех аппаратных портов.
endif() # Завершает необязательную сборку тестов.
if(CMAKE_SYSTEM_NAME STREQUAL "Linux") # Linux-заголовки не попадают в сборки ESP32, Windows и других MCU.
add_executable(zynq-can485d ports/zynq-linux/main.c) # SocketCAN, USB и Ethernet реализуются только аппаратным портом.
target_link_libraries(zynq-can485d PRIVATE can485_monitor) # Linux использует ровно то же C99-ядро, что host-проверка.
endif() # Завершает платформенную часть библиотеки.
+82
View File
@@ -0,0 +1,82 @@
# CAN485 monitor
Общее C99-ядро команд CAN485 DevBoard/SETGUI и Linux-порт для PS CAN Zynq.
Протоколы CAN (SETCAN, ProtoCAN, УМП, Balsam, DEIF и остальные) разбираются
существующими библиотеками `templates/python`, без копий в проекте платы.
Слои: SETGUI BoardTab → `qt_ports/can485_port.py` → Ethernet TCP или USB tty →
`ports/zynq-linux/main.c` → `can485_monitor.c` → SocketCAN / RS485 / каталог SD.
В ядре нет Linux, Qt, HAL, выделения памяти и глобального контекста.
| Файл | Назначение и зависимости |
|---|---|
| `include/can485_monitor.h` | Контракт C99, `stdint.h`, `stddef.h` |
| `src/can485_monitor.c` | Проверка команд, фильтр, маршруты, AA55/CRC8, строки CAN |
| `ports/zynq-linux/main.c` | SocketCAN, rtnetlink, TCP, USB tty, UART RS485, SD, POSIX/Linux |
| `tests/test_can485_monitor.c` | Эталонный пакет, ошибки/границы, маршрутизация, отказы оборудования |
Порт предоставляет четыре callback: `emit(context,line)`,
`configure(context,kbps,mode,running)`, `send(context,frame,source)` и
`control(context,command)`. `source=0` означает CAN, `source=1` — RS485.
`configure` и `send` возвращают 1 только после принятия операции драйвером.
Аппаратный ACK этим результатом не подтверждается. Контекст и буферы принадлежат приложению.
```c
#include "can485_monitor.h" /* Подключает переносимое ядро библиотеки. */
void example(cm_port port) { /* Аппаратные callback передаются вызывающей платформой. */
cm_monitor state; /* Контекст не разделяется с другим экземпляром моста. */
cm_init(&state, port); /* CAN остановлен, оба направления маршрута выключены. */
cm_command(&state, "V"); /* Версия и статус не меняют оборудование. */
cm_command(&state, "S125"); /* Запрашивает CAN 125 кбит/с через аппаратный callback. */
cm_command(&state, "M1"); /* Listen-only запрещает ручной TX и RS485→CAN. */
cm_frame frame = {0x123, 2, 0, {0xAB, 0xCD}}; /* STD ID и два исходных байта. */
cm_receive(&state, &frame, 0, 12345); /* Приём CAN в момент 12,345 с монотонного времени. */
cm_status(&state, 12345, "sd=idle"); /* Статус содержит только известные платформе поля. */
} /* Реальная плата передаёт только фактически принятые кадры в cm_receive. */
```
Поддержаны команды `V ? H S M O C F Q R B T X Z L D G I` и Linux-расширение
`Ncan0` / `Ncan1`. Команды строго проверяются целиком. RS485-пакет:
`AA 55 FLAGS ID[4]be DLC DATA[8] CRC8(FLAGS..DATA, poly=0x07, init=0)`.
CAN STD/EXT/RTR сохраняются. DATA TX через `T` повторяет контракт существующего ESP GUI.
Linux-порт запускается с CAN остановленным, маршрутами и записью SD выключенными.
`S`/`M`/`O` запускают CAN; `C` останавливает интерфейс. Настройка через rtnetlink
требует root или `CAP_NET_ADMIN`; RAW CAN — соответствующих прав Linux.
M2 требует реальной поддержки `CAN_CTRLMODE_PRESUME_ACK`; ошибка драйвера
не маскируется под успешный no-ack. Фильтр программный и не отключает аппаратный ACK.
TCP-порт по умолчанию **37579**, один управляющий клиент. Подключённый USB
может получать поток, но команды второго транспорта возвращают `#ERR busy`.
Второй TCP-клиент не вытесняет первого. При обрыве владельца маршруты выключаются,
его SD-download отменяется. Медленный клиент отключается при заполнении очереди 64 КиБ.
Служба не включает периодический CAN TX: этот таймер принадлежит SETGUI и
останавливается при отключении. Смена `N` закрывает только собственный CAN socket.
`--usb /dev/ttyGS0` использует USB OTG CDC ACM, если образ Linux предоставляет
gadget serial. Также допустим выделенный UART через USB-UART, свободный от
console/getty. Разъём USB HOST и USB-JTAG сами по себе CDC не создают.
USB и RS485 должны использовать разные tty. RTS/CTS выключены. RS485 требует
физического трансивера с аппаратным управлением направлением либо предварительной
настройки драйвера UART; Linux-порт не переключает произвольные GPIO платы.
Для штатной USB-UART Linux-консоли Qt-порт предоставляет
`Can485Port.start_console_tunnel(port=37579)`: запускает `nc` из уже открытой
root shell к той же службе. Готовность определяется реальным `#INFO`, а не
открытием COM. При закрытии Ctrl-C завершает собственный nc, в пределах
400 мс проверяется возврат shell prompt и выполнение `stty sane`.
Поле `console_restored` позволяет аппаратному тесту проверить этот результат.
SD — заранее выбранный каталог `--logs`, например `/mnt/sd/can-logs`.
Журналы `can_*.csv` содержат совместимые текстовые строки кадров; импорт SETGUI
распознаёт этот формат автоматически. Выдача файла асинхронная, блоками 128 байт,
с проверяемыми offset/size/CRC32. Путь ограничен одним каталогом, `..` и symlink
запрещены. Запись SD выключается перед чтением. `vin`, TEC и REC не выдумываются,
если платформа не получила реальные значения.
Используется: Zynq RK7020 (`demo/can485`) и CAN-панель SETGUI (`pc/zynq_can_panel.py`).
Для единого физического источника задавайте одинаковый **TEMPLATES_ROOT** при
запуске SETGUI и сборке ARM (`build.ps1 -Templates <тот же каталог>`).
После изменения Python перезапустите приложение; изменение C требует пересборки
службы, изменение встроенных библиотек EXE — пересборки EXE. Подмодули разных
checkout обновляются явно: Git не обновляет уже собранную прошивку автоматически.
+24
View File
@@ -0,0 +1,24 @@
#ifndef CAN485_MONITOR_H /* Защищает публичный контракт монитора от повторного включения. */
#define CAN485_MONITOR_H /* Одинаковое ядро обслуживает команды DevBoard на разных платформах. */
#include <stdint.h> /* Фиксирует размеры CAN ID, счётчиков и байтов независимо от процессора. */
#include <stddef.h> /* Размеры выходных строк выражены штатным типом size_t. */
typedef struct { uint32_t id; uint8_t dlc, flags, data[8]; } cm_frame; /* flags: бит 0 EXT, бит 1 RTR; Classic CAN содержит до восьми байтов. */
typedef struct { /* Платформа предоставляет ввод-вывод, не копируя разбор команд. */
void (*emit)(void *, const char *); /* Принимает одну законченную строку с LF для Ethernet, USB и журнала. */
int (*configure)(void *, unsigned, unsigned, int); /* Применяет битрейт в кбит/с, режим M0/M1/M2 и состояние драйвера; ноль означает ошибку. */
int (*send)(void *, const cm_frame *, int); /* Передаёт кадр в CAN при source=0 либо в RS485 при source=1; успех означает принятие локальным драйвером. */
int (*control)(void *, const char *); /* Обслуживает аппаратную скорость B и файловые L/D/G/I; ответы формирует сам порт. */
void *context; /* Контекст принадлежит вызывающему коду и позволяет иметь несколько независимых мостов. */
} cm_port; /* В ядре нет HAL, Linux, Qt, динамической памяти и глобального состояния. */
typedef struct { /* Состояние протокола отделено от сетевых клиентов и файловых дескрипторов. */
cm_port port; unsigned bitrate, mode, route, baud, running; /* Скорости заданы в кбит/с для CAN и бод для RS485; route использует два младших бита направлений. */
uint32_t filter_id, filter_mask, rx, tx, rsrx, rstx, buserr, dropcan, droprs, rscrc; /* Счётчики относятся к фактическим операциям порта; фильтр сравнивает только 29 бит ID. */
uint64_t now; /* Последнее подтверждённое монотонное время позволяет ответу V сохранять реальный uptime между периодическими статусами. */
} cm_monitor; /* Всё изменяемое состояние хранится в экземпляре вызывающего приложения. */
void cm_init(cm_monitor *, cm_port); /* Инициализирует остановленный CAN 125 кбит/с, normal, маршруты выключены и RS485 512000 бод. */
void cm_command(cm_monitor *, const char *); /* Проверяет полную команду без CR/LF и применяет её только после успешной валидации. */
void cm_receive(cm_monitor *, const cm_frame *, int, uint64_t); /* Принимает кадр CAN=0 либо RS485=1 и монотонное время в миллисекундах. */
void cm_status(cm_monitor *, uint64_t, const char *); /* Печатает совместимый #STAT; дополнительная строка содержит подтверждённые поля SD/Linux. */
int cm_packet_decode(const uint8_t *, cm_frame *); /* Проверяет все 17 байт AA55/CRC8, формат ID и DLC до маршрутизации RS485. */
void cm_packet_encode(const cm_frame *, uint8_t *); /* Формирует RS485 AA55, FLAGS, ID big-endian, DLC, восемь байтов и CRC8/0x07. */
#endif /* Завершает независимый публичный контракт CAN485 monitor. */
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
+5 -1
View File
@@ -1,3 +1,7 @@
# Сборка библиотеки candle. Состав исходников и публичные include-пути задают подключение к
# проекту потребителя. Платформенные зависимости и условия сборки задаются здесь, а не в
# прикладных исходниках.
cmake_minimum_required(VERSION 3.15)
project(candle C)
if(NOT WIN32)
@@ -5,5 +9,5 @@ if(NOT WIN32)
endif()
add_library(candle SHARED candle.c candle_ctrl_req.c candle.def)
target_compile_definitions(candle PRIVATE UNICODE _UNICODE)
target_link_libraries(candle PRIVATE setupapi winusb ole32 advapi32)
target_link_libraries(candle PRIVATE setupapi winusb ole32 advapi32 cfgmgr32) # Configuration Manager сопоставляет интерфейсы CAN и DFU по родительскому USB-узлу.
target_include_directories(candle PUBLIC ${CMAKE_CURRENT_SOURCE_DIR})
+155 -4
View File
@@ -19,6 +19,12 @@
*/
/*
* Доступ к CAN-адаптерам candleLight/gs_usb в Windows через WinUSB. Перечисление устройств,
* открытие канала и обмен кадрами образуют отдельный транспортный слой; он не интерпретирует
* прикладные регистры SETProtocol.
*/
#include "candle.h"
#include <stdarg.h>
@@ -28,6 +34,86 @@
#include "candle_defs.h"
#include "candle_ctrl_req.h"
#include "ch_9.h"
#include <cfgmgr32.h> /* Сопоставляет интерфейсы CAN и DFU по общему родительскому USB-устройству Windows. */
static DWORD candle_dfu_parent(const wchar_t *path, DEVINST *parent) /* Возвращает родителя интерфейса, чтобы команда не попала в другой подключённый адаптер. */
{ /* Начало поиска физического USB-устройства по пути выбранного CAN-интерфейса. */
HDEVINFO devices = SetupDiCreateDeviceInfoList(NULL, NULL); /* Создаёт временный набор SetupAPI без перечисления посторонних устройств. */
if (devices == INVALID_HANDLE_VALUE) return GetLastError(); /* Сохраняет причину отказа создания набора Windows. */
SP_DEVICE_INTERFACE_DATA iface = {0}; /* Подготавливает описание интерфейса для открытия по точному пути. */
iface.cbSize = sizeof(iface); /* Передаёт SetupAPI размер структуры текущей разрядности процесса. */
SP_DEVINFO_DATA info = {0}; /* Получает идентификатор узла PnP выбранного интерфейса. */
info.cbSize = sizeof(info); /* Указывает размер структуры устройства согласно контракту SetupAPI. */
DWORD size = 0, error = ERROR_SUCCESS; /* Хранит требуемое число байтов и итоговый код Windows. */
if (!SetupDiOpenDeviceInterfaceW(devices, path, 0, &iface)) error = GetLastError(); /* Открывает только заданный путь, сохраняя ошибку исчезнувшего устройства. */
if (!error) SetupDiGetDeviceInterfaceDetailW(devices, &iface, NULL, 0, &size, NULL); /* Узнаёт объём буфера переменной длины для пути USB-интерфейса. */
PSP_DEVICE_INTERFACE_DETAIL_DATA_W detail = size ? malloc(size) : NULL; /* Выделяет буфер только после успешного определения его размера. */
if (!error && !detail) error = size ? ERROR_NOT_ENOUGH_MEMORY : GetLastError(); /* Отличает нехватку памяти от ошибки поиска описания. */
if (detail) { /* Обрабатывает описание только при наличии выделенного буфера. */
detail->cbSize = sizeof(*detail); /* Согласует размер заголовка с архитектурой Win32 или Win64. */
if (!SetupDiGetDeviceInterfaceDetailW(devices, &iface, detail, size, NULL, &info)) error = GetLastError(); /* Получает узел интерфейса из SetupAPI. */
else if (CM_Get_Parent(parent, info.DevInst, 0) != CR_SUCCESS) error = ERROR_NOT_FOUND; /* Получает общий родительский узел составного USB-адаптера. */
free(detail); /* Освобождает описание после получения идентификатора родителя. */
} /* Завершает работу с описанием интерфейса. */
SetupDiDestroyDeviceInfoList(devices); /* Освобождает набор SetupAPI при любом результате поиска. */
return error; /* Возвращает ноль при успехе либо причину отказа Windows. */
} /* Завершает сопоставление интерфейса с физическим USB-устройством. */
uint32_t __stdcall candle_dev_enter_dfu(const wchar_t *can_path, uint8_t status[6]) /* Возвращает код Windows и шестибайтовый DFU_GETSTATUS согласно DFU 1.1. */
{ /* Начало отдельного сеанса управляющего интерфейса обновления. */
if (!can_path || !status) return ERROR_INVALID_PARAMETER; /* Запрещает отсутствие точного пути адаптера или выходного буфера статуса. */
memset(status, 0, 6); /* Исключает использование неинициализированных полей ответа при ошибке USB. */
DEVINST wanted_parent = 0; /* Запоминает физический адаптер, выбранный пользователем до остановки CAN. */
DWORD error = candle_dfu_parent(can_path, &wanted_parent); /* Ищет родителя по сохранённому пути CAN, не заменяя его первым найденным устройством. */
if (error) return error; /* Прерывает переход, если выбранный адаптер уже исчез из PnP. */
GUID guid = {0xc25b4308, 0x04d3, 0x11e6, {0xb3, 0xea, 0x60, 0x57, 0x18, 0x9e, 0x64, 0x43}}; /* GUID интерфейса обновления из дескриптора CANable 2.5. */
HDEVINFO devices = SetupDiGetClassDevsW(&guid, NULL, NULL, DIGCF_PRESENT | DIGCF_DEVICEINTERFACE); /* Перечисляет только подключённые интерфейсы обновления CANable 2.5. */
if (devices == INVALID_HANDLE_VALUE) return GetLastError(); /* Возвращает отказ SetupAPI без попытки послать команду. */
error = ERROR_NOT_FOUND; /* Отсутствие интерфейса обновления не считается успешным входом в DFU. */
for (DWORD index = 0; ; ++index) { /* Проверяет интерфейсы до точного совпадения физического устройства. */
SP_DEVICE_INTERFACE_DATA iface = {0}; /* Создаёт независимое описание очередного DFU-интерфейса. */
iface.cbSize = sizeof(iface); /* Задаёт обязательный размер структуры SetupAPI. */
if (!SetupDiEnumDeviceInterfaces(devices, NULL, &guid, index, &iface)) { /* Завершает обход либо сообщает ошибку перечисления. */
if (GetLastError() != ERROR_NO_MORE_ITEMS) error = GetLastError(); /* Отличает штатный конец списка от отказа Windows. */
break; /* Выходит из обхода после исчерпания интерфейсов или ошибки. */
} /* Завершает проверку результата перечисления. */
DWORD size = 0; /* Хранит размер описания очередного интерфейса в байтах. */
SetupDiGetDeviceInterfaceDetailW(devices, &iface, NULL, 0, &size, NULL); /* Определяет буфер для полного пути интерфейса обновления. */
if (!size) { error = GetLastError(); break; } /* Не продолжает работу с неполным результатом SetupAPI. */
PSP_DEVICE_INTERFACE_DETAIL_DATA_W detail = malloc(size); /* Выделяет описание с достаточным местом для USB-пути. */
if (!detail) { error = ERROR_NOT_ENOUGH_MEMORY; break; } /* Не допускает обращения к отсутствующему буферу. */
detail->cbSize = sizeof(*detail); /* Сохраняет ABI описания интерфейса Windows. */
if (!SetupDiGetDeviceInterfaceDetailW(devices, &iface, detail, size, NULL, NULL)) { /* Получает путь, который можно передать CreateFileW. */
error = GetLastError(); free(detail); break; /* Сохраняет ошибку и освобождает буфер перед выходом. */
} /* Завершает чтение пути интерфейса. */
DEVINST parent = 0; /* Хранит родителя текущего кандидата на обновление. */
if (candle_dfu_parent(detail->DevicePath, &parent) || parent != wanted_parent) { /* Исключает каждый интерфейс другого физического адаптера. */
free(detail); continue; /* Освобождает описание неподходящего кандидата и продолжает поиск. */
} /* Завершает проверку принадлежности выбранному USB-адаптеру. */
HANDLE file = CreateFileW(detail->DevicePath, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED, NULL); /* Эксклюзивно открывает интерфейс обновления выбранного устройства для WinUSB. */
free(detail); /* Путь больше не нужен после открытия системного дескриптора. */
if (file == INVALID_HANDLE_VALUE) { error = GetLastError(); break; } /* Не скрывает отсутствие доступа или занятость интерфейса. */
WINUSB_INTERFACE_HANDLE usb = NULL; /* Хранит отдельный WinUSB-сеанс интерфейса обновления без CAN bulk endpoint. */
error = ERROR_SUCCESS; /* Сбрасывает исходное отсутствие интерфейса после точного совпадения устройства. */
if (!WinUsb_Initialize(file, &usb)) error = GetLastError(); /* Проверяет наличие рабочего WinUSB-драйвера DFU runtime. */
USB_INTERFACE_DESCRIPTOR descriptor = {0}; /* Получает реальный номер и класс открытого интерфейса. */
if (!error && !WinUsb_QueryInterfaceSettings(usb, 0, &descriptor)) error = GetLastError(); /* Не предполагает, что произвольный WinUSB-интерфейс поддерживает DFU. */
if (!error && (descriptor.bInterfaceClass != 0xFE || descriptor.bInterfaceSubClass != 1 || descriptor.bInterfaceProtocol != 1)) error = ERROR_NOT_SUPPORTED; /* Проверяет класс приложения, подкласс DFU и runtime-протокол по DFU 1.1. */
ULONG timeout = 500, transferred = 0; /* Ограничивает управляющий USB-запрос 500 миллисекундами и учитывает длину ответа. */
if (!error && !WinUsb_SetPipePolicy(usb, 0, PIPE_TRANSFER_TIMEOUT, sizeof(timeout), &timeout)) error = GetLastError(); /* Устанавливает тайм-аут endpoint 0, чтобы отсутствующий ответ не блокировал программу. */
WINUSB_SETUP_PACKET packet = {0}; /* Обнуляет поля USB SETUP перед запросом перехода в загрузчик. */
packet.RequestType = 0x21; packet.Request = 0; packet.Value = 1000; packet.Index = descriptor.bInterfaceNumber; /* DFU_DETACH: class/interface OUT, запрос 0, ожидаемое время отключения 1000 мс. */
if (!error && !WinUsb_ControlTransfer(usb, packet, NULL, 0, &transferred, NULL)) error = GetLastError(); /* Отправляет DETACH и требует подтверждённой USB-транзакции. */
packet.RequestType = 0xA1; packet.Request = 3; packet.Value = 0; packet.Length = 6; /* DFU_GETSTATUS: class/interface IN, запрос 3, ответ ровно 6 байт по DFU 1.1. */
if (!error && !WinUsb_ControlTransfer(usb, packet, status, 6, &transferred, NULL)) error = GetLastError(); /* Проверяет результат до отложенного перехода прошивки через 300 мс. */
if (!error && transferred != 6) error = ERROR_INVALID_DATA; /* Не трактует укороченный ответ как подтверждение входа в загрузчик. */
if (usb) WinUsb_Free(usb); /* Освобождает WinUSB до появления загрузчика с другим VID/PID. */
CloseHandle(file); /* Освобождает файловый дескриптор после успеха и при любой ошибке USB. */
break; /* Не отправляет DETACH повторно и не переключается на другой адаптер при отказе. */
} /* Завершает поиск и обработку единственного выбранного адаптера. */
SetupDiDestroyDeviceInfoList(devices); /* Освобождает перечень интерфейсов при любом результате. */
return error; /* Статус прошивки возвращается отдельно от системной ошибки USB. */
} /* Завершает управление DFU runtime без записи flash или изменения образа. */
static bool candle_dev_interal_open(candle_handle hdev);
@@ -650,6 +736,30 @@ bool __stdcall DLL candle_dev_open(candle_handle hdev)
}
bool __stdcall DLL candle_dev_get_product(candle_handle hdev, wchar_t *product, uint32_t capacity) /* Читает USB Product String открытого адаптера в буфер UTF-16; capacity измеряется в wchar_t, включая завершающий ноль. */
{ /* Начало чтения отображаемого имени без изменения режима CAN. */
if (!product || !capacity) return false; /* Не пишет в отсутствующий либо пустой выходной буфер. */
product[0] = 0; /* Сохраняет пустую строку при любом отказе чтения дескриптора. */
candle_device_t *dev = (candle_device_t*)hdev; /* Получает уже открытый WinUSB-сеанс выбранного физического адаптера. */
if (!dev || !dev->winUSBHandle) return false; /* Не открывает устройство заново и не обращается к закрытому интерфейсу. */
USB_DEVICE_DESCRIPTOR descriptor = {0}; /* Получает индекс строки продукта из стандартного дескриптора устройства. */
ULONG received = 0; /* Хранит фактически полученное количество байтов управляющего ответа. */
if (!WinUsb_GetDescriptor(dev->winUSBHandle, 1, 0, 0, (PUCHAR)&descriptor, sizeof(descriptor), &received) || received != sizeof(descriptor)) return false; /* Тип 1 обозначает Device Descriptor по USB 2.0; неполный ответ не используется. */
UCHAR string_index = descriptor.iProduct; /* Для обычных адаптеров использует объявленный устройством индекс USB Product String. */
if (descriptor.idVendor == 0x1D50 && descriptor.idProduct == 0x606F) string_index = 2; /* В CANable Candlelight имя продукта имеет индекс 2; WinUSB может подменять iProduct индексом имени интерфейса, как описано в штатном примере проекта. */
if (!string_index) return false; /* Нулевой iProduct означает, что устройство не предоставляет имя продукта. */
UCHAR raw[256] = {0}; /* Буфер вмещает строковый дескриптор USB, чей однобайтовый bLength ограничен 255 байтами. */
USHORT language = 0x0409; /* Использует английский идентификатор USB как резервный вариант для устройств без списка языков. */
if (WinUsb_GetDescriptor(dev->winUSBHandle, 3, 0, 0, raw, sizeof(raw), &received) && received >= 4 && raw[0] >= 4 && raw[1] == 3) language = (USHORT)(raw[2] | ((USHORT)raw[3] << 8)); /* Тип 3 и индекс 0 возвращают список LANGID; выбирает первый язык, предоставленный адаптером. */
if (!WinUsb_GetDescriptor(dev->winUSBHandle, 3, string_index, language, raw, sizeof(raw), &received)) return false; /* Читает именно строку продукта на поддерживаемом устройством языке. */
if (received < 2 || raw[1] != 3 || raw[0] < 2 || raw[0] > received || (raw[0] & 1)) return false; /* Проверяет тип, размер и чётное число байтов UTF-16 перед копированием в выходной буфер. */
uint32_t count = (raw[0] - 2) / 2; /* Исключает двухбайтовый заголовок и переводит длину UTF-16LE из байтов в число кодовых единиц. */
if (count >= capacity) return false; /* Не обрезает индивидуальный номер в конце имени и оставляет место для завершающего нуля. */
for (uint32_t index = 0; index < count; ++index) product[index] = (wchar_t)(raw[2 + index * 2] | ((USHORT)raw[3 + index * 2] << 8)); /* Явно собирает кодовые единицы UTF-16LE без предположений о выравнивании массива байтов. */
product[count] = 0; /* Завершает строку для безопасного чтения через ctypes и отображения в Qt. */
return count > 0; /* Пустое имя оставляет интерфейсу стандартную резервную подпись адаптера. */
} /* Завершает получение настоящего имени из прошивки USB-адаптера. */
bool __stdcall DLL candle_dev_get_timestamp_us(candle_handle hdev, uint32_t *timestamp_us)
{
return candle_ctrl_get_timestamp(hdev, timestamp_us);
@@ -817,6 +927,38 @@ bool __stdcall DLL candle_channel_stop(candle_handle hdev, uint8_t ch)
return candle_ctrl_set_device_mode(dev, ch, CANDLE_DEVMODE_RESET, 0);
}
bool __stdcall DLL candle_channel_start_configured(candle_handle hdev, uint8_t ch, uint32_t flags) /* Новый вход сохраняет прежний ABI start и позволяет отключать HW_TIMESTAMP. */
{ /* Явно выбранные Python-флаги должны попасть в прошивку без автоматического дополнения. */
return candle_ctrl_set_device_mode((candle_device_t*)hdev, ch, CANDLE_DEVMODE_START, flags); /* Передаём точную маску после проверки возможностей на уровне транспорта. */
} /* Завершение запуска с явно заданными параметрами. */
bool __stdcall DLL candle_channel_get_data_capabilities(candle_handle hdev, uint8_t ch, candle_capability_t *cap) /* Экспортируем чтение FD-пределов для расчёта тайминга на любой частоте CAN. */
{ /* Общая форма capability позволяет повторно использовать валидатор номинального тайминга. */
return candle_ctrl_data_capability((candle_device_t*)hdev, ch, cap); /* USB-запрос возвращает реальные пределы выбранного канала. */
} /* Завершение получения возможностей быстрой фазы. */
bool __stdcall DLL candle_channel_set_termination(candle_handle hdev, uint8_t ch, uint32_t state) /* Значения 0 и 1 соответствуют OFF и ON стандарта gs_usb. */
{ /* Проверка исключает отправку неопределённого состояния в прошивку. */
return state <= 1 && candle_ctrl_termination((candle_device_t*)hdev, ch, &state, true); /* Выполняем запись только для допустимого состояния. */
} /* Завершение переключения терминатора. */
bool __stdcall DLL candle_channel_get_termination(candle_handle hdev, uint8_t ch, uint32_t *state) /* Чтение состояния не меняет топологию CAN. */
{ /* Используем тот же формат 32-битного значения, что и при записи. */
return candle_ctrl_termination((candle_device_t*)hdev, ch, state, false); /* false выбирает USB_DIR_IN и GET_TERMINATION. */
} /* Завершение чтения терминатора. */
bool __stdcall DLL candle_channel_get_diagnostics(candle_handle hdev, uint8_t ch, uint32_t *state, uint32_t *rxerr, uint32_t *txerr) /* Сохраняем счётчики, которые старый get_state отбрасывал. */
{ /* Диагностика выполняется только для уже открытого устройства. */
candle_device_state_t data = {0}; /* Полная структура протокола содержит три слова: состояние, RX и TX. */
if (!candle_ctrl_get_state((candle_device_t*)hdev, ch, &data)) { /* Не возвращаем нулевые счётчики как будто запрос был успешным. */
return false; /* Причина USB-отказа уже записана управляющим запросом. */
} /* Дальнейшее копирование относится только к подтверждённому ответу. */
*state = data.state; /* Сохраняем состояние Error-active, Warning, Passive, Bus-off, Stopped или Sleeping. */
*rxerr = data.rxerr; /* Счётчик ошибок приёма измеряется в единицах CAN-контроллера. */
*txerr = data.txerr; /* Счётчик ошибок передачи помогает отличать отсутствие ACK от ошибок приёма. */
return true; /* Все три выходных значения относятся к одному USB-ответу. */
} /* Завершение расширенной диагностики канала. */
/* Write len bytes from buf to the OUT pipe, aborting after 300 ms.
* Writes are serialised by writeMutex in CandleApiInterface so dev->txEvent
* is never accessed by two threads simultaneously. */
@@ -1011,14 +1153,13 @@ bool __stdcall DLL candle_fd_frame_read(candle_handle hdev, candle_fd_frame_t *f
}
dev->rxurbs[urb_num].pending = false;
/* Minimum: classic CAN header (12 bytes) + at least 8 data bytes = 20 bytes */
static const DWORD classic_min = sizeof(candle_frame_t) - 4;
if (bytes_transfered < classic_min) {
const DWORD header_size = 12; /* Заголовок gs_usb занимает 12 байт в Classic и FD; короткий FD может не содержать восьми байтов данных. */
if (bytes_transfered < header_size) { /* До чтения flags и DLC проверяем наличие полного заголовка. */
candle_prepare_read(dev, urb_num);
candle_logf(L"fd read too small urb=%u bytes=%lu min=%lu",
urb_num,
bytes_transfered,
classic_min);
header_size); /* Минимальная длина здесь относится к заголовку, а payload проверяется после определения формата. */
dev->last_error = CANDLE_ERR_READ_SIZE;
return false;
}
@@ -1041,6 +1182,11 @@ bool __stdcall DLL candle_fd_frame_read(candle_handle hdev, candle_fd_frame_t *f
if (is_fd_frame) {
/* can_dlc is at byte offset 8 in both classic and FD wire frames. */
const uint8_t raw_dlc = dev->rxurbs[urb_num].buf[8];
if (raw_dlc > 15) { /* FD DLC является четырёхбитным кодом и не может содержать значения выше 15. */
candle_prepare_read(dev, urb_num); /* Повреждённый USB-пакет не должен останавливать последующий приём. */
dev->last_error = CANDLE_ERR_READ_SIZE; /* Неверный DLC считается ошибкой формата входного кадра. */
return false; /* Не превращаем повреждённый DLC в пустой успешный FD-кадр. */
} /* Далее длина безопасно вычисляется по таблице CAN FD. */
const DWORD data_len = candle_dlc_to_len(raw_dlc);
const DWORD min_size = 12 + data_len; /* header + data, without timestamp */
@@ -1071,6 +1217,11 @@ bool __stdcall DLL candle_fd_frame_read(candle_handle hdev, candle_fd_frame_t *f
}
/* else: timestamp stays zero from memset above */
} else {
if (bytes_transfered < sizeof(candle_frame_t) - sizeof(uint32_t)) { /* Classic-пакет обязан содержать весь восьмибайтовый буфер данных, даже при меньшем DLC. */
candle_prepare_read(dev, urb_num); /* Возобновляем соответствующий URB после отклонения неполного пакета. */
dev->last_error = CANDLE_ERR_READ_SIZE; /* Не допускаем чтение неполученных данных из локальной структуры. */
return false; /* Повреждённый Classic-пакет не попадает в Python через FD API. */
} /* Минимальный размер Classic теперь проверен отдельно от коротких FD. */
/* Classic CAN frame — copy into FD struct, fixing the timestamp position */
candle_frame_t classic;
DWORD copy_len = (bytes_transfered < sizeof(classic)) ? bytes_transfered : sizeof(classic);
+16
View File
@@ -1,4 +1,10 @@
; Доступ к CAN-адаптерам candleLight/gs_usb в Windows через WinUSB. Перечисление устройств,
; открытие канала и обмен кадрами образуют отдельный транспортный слой; он не интерпретирует
; прикладные регистры SETProtocol.
EXPORTS
candle_dev_get_product ; Имя продукта из USB-дескриптора прошивки для списка адаптеров SETGUI.
candle_dev_enter_dfu ; Переход через отдельный DFU runtime-интерфейс того же физического USB-адаптера.
candle_list_scan
candle_list_free
candle_list_length
@@ -27,3 +33,13 @@ EXPORTS
candle_frame_data
candle_frame_timestamp_us
candle_dev_last_error
candle_channel_start_configured ; Точная маска запуска с управляемыми аппаратными метками.
candle_channel_get_data_capabilities ; Пределы тайминга быстрой фазы CAN FD.
candle_channel_set_termination ; Переключение встроенного терминатора.
candle_channel_get_termination ; Чтение состояния встроенного терминатора.
candle_channel_get_diagnostics ; Состояние и счётчики ошибок CAN.
candle_channel_set_data_timing ; Тайминг фазы данных CAN FD.
candle_fd_frame_send ; Отправка полного кадра CAN FD до 64 байт.
candle_fd_frame_read ; Приём FD и Classic без обрезания данных.
candle_fd_frame_type ; Различение RX, TX echo и ошибок FD.
candle_fd_frame_id ; Получение CAN ID из структуры FD.
+13
View File
@@ -20,6 +20,12 @@
*/
/*
* Доступ к CAN-адаптерам candleLight/gs_usb в Windows через WinUSB. Перечисление устройств,
* открытие канала и обмен кадрами образуют отдельный транспортный слой; он не интерпретирует
* прикладные регистры SETProtocol.
*/
#pragma once
#include <stdint.h>
#include <stdbool.h>
@@ -240,7 +246,9 @@ bool __stdcall DLL candle_list_length(candle_list_handle list, uint8_t *len);
bool __stdcall DLL candle_dev_get(candle_list_handle list, uint8_t dev_num, candle_handle *hdev);
bool __stdcall DLL candle_dev_get_state(candle_handle hdev, candle_devstate_t *state);
wchar_t * __stdcall DLL candle_dev_get_path(candle_handle hdev);
bool __stdcall DLL candle_dev_get_product(candle_handle hdev, wchar_t *product, uint32_t capacity); /* Возвращает USB Product String в UTF-16; capacity включает завершающий ноль и измеряется в wchar_t. */
bool __stdcall DLL candle_dev_open(candle_handle hdev);
uint32_t __stdcall DLL candle_dev_enter_dfu(const wchar_t *can_path, uint8_t status[6]); /* Переводит выбранный физический адаптер в DFU и возвращает Win32-код плюс ответ DFU_GETSTATUS. */
bool __stdcall DLL candle_dev_get_timestamp_us(candle_handle hdev, uint32_t *timestamp_us);
bool __stdcall DLL candle_dev_close(candle_handle hdev);
bool __stdcall DLL candle_dev_free(candle_handle hdev);
@@ -253,6 +261,11 @@ bool __stdcall DLL candle_channel_set_timing(candle_handle hdev, uint8_t ch, can
bool __stdcall DLL candle_channel_set_bitrate(candle_handle hdev, uint8_t ch, uint32_t bitrate);
bool __stdcall DLL candle_channel_start(candle_handle hdev, uint8_t ch, uint32_t flags);
bool __stdcall DLL candle_channel_stop(candle_handle hdev, uint8_t ch);
bool __stdcall DLL candle_channel_start_configured(candle_handle hdev, uint8_t ch, uint32_t flags); /* Запускаем с точной маской без принудительного включения аппаратных меток. */
bool __stdcall DLL candle_channel_get_data_capabilities(candle_handle hdev, uint8_t ch, candle_capability_t *cap); /* Возвращаем пределы тайминга быстрой фазы FD. */
bool __stdcall DLL candle_channel_set_termination(candle_handle hdev, uint8_t ch, uint32_t state); /* Состояние терминатора: 0 — выключен, 1 — включён. */
bool __stdcall DLL candle_channel_get_termination(candle_handle hdev, uint8_t ch, uint32_t *state); /* Чтение не меняет подключение встроенного резистора. */
bool __stdcall DLL candle_channel_get_diagnostics(candle_handle hdev, uint8_t ch, uint32_t *state, uint32_t *rxerr, uint32_t *txerr); /* Передаём состояние CAN и оба счётчика ошибок без потери данных ответа. */
bool __stdcall DLL candle_frame_send(candle_handle hdev, uint8_t ch, candle_frame_t *frame);
bool __stdcall DLL candle_frame_read(candle_handle hdev, candle_frame_t *frame, uint32_t timeout_ms);
+28 -2
View File
@@ -19,6 +19,11 @@
*/
/*
* Управляющие USB-запросы адаптера candleLight: конфигурация, временные параметры CAN и режим
* канала. Эти транзакции идут через control endpoint и отличаются от потока CAN-кадров.
*/
#include "candle_ctrl_req.h"
#include "ch_9.h"
@@ -34,8 +39,10 @@ enum {
CANDLE_TIMESTAMP_GET = 6,
/* 7: IDENTIFY, 8: GET_USER_ID, 9: SET_USER_ID (not used here) */
CANDLE_BREQ_DATA_BITTIMING = 10,
/* 11: SET_TERMINATION, not used here */
CANDLE_BREQ_GET_STATE = 12,
CANDLE_BREQ_BT_CONST_EXT = 11, /* Расширенные пределы номинальной и быстрой фазы согласно gs_usb. */
CANDLE_BREQ_SET_TERMINATION = 12, /* Запрос gs_usb 12 переключает встроенный резистор окончания шины. */
CANDLE_BREQ_GET_TERMINATION = 13, /* Запрос gs_usb 13 читает текущее состояние терминатора. */
CANDLE_BREQ_GET_STATE = 14, /* Стандартный GET_STATE имеет номер 14; номер 12 принадлежит терминатору. */
CANDLE_BREQ_BUS_OFF_RECOVERY = 32,
};
@@ -232,3 +239,22 @@ bool candle_ctrl_bus_off_recover(candle_device_t *dev, uint8_t channel)
dev->last_error = rc ? CANDLE_ERR_OK : CANDLE_ERR_SET_DEVICE_MODE;
return rc;
}
bool candle_ctrl_data_capability(candle_device_t *dev, uint8_t channel, candle_capability_t *cap) /* Структура gs_usb BT_CONST_EXT содержит десять общих и восемь быстрых полей uint32. */
{ /* Используем массив, поскольку протокол содержит только однородные 32-битные значения без отступов. */
uint32_t fields[18] = {0}; /* 18 полей по 4 байта образуют стандартный ответ размером 72 байта. */
bool rc = usb_control_msg(dev->winUSBHandle, CANDLE_BREQ_BT_CONST_EXT, USB_DIR_IN|USB_TYPE_VENDOR|USB_RECIP_INTERFACE, channel, 0, fields, sizeof(fields)); /* Запрашиваем пределы именно выбранного CAN-канала. */
if (rc) { /* Выходная структура должна меняться только после успешного USB-ответа. */
memcpy(cap, fields, 2 * sizeof(uint32_t)); /* Маска функций и частота CAN общие для обеих фаз. */
memcpy(&cap->tseg1_min, &fields[10], 8 * sizeof(uint32_t)); /* Поля DTSEG1…DBRP_INC заменяют номинальные пределы структуры capability. */
} /* При отказе вызывающий код получит false и не использует нулевые пределы. */
dev->last_error = rc ? CANDLE_ERR_OK : CANDLE_ERR_GET_BITTIMING_CONST; /* Сохраняем диагностический код чтения аппаратных ограничений. */
return rc; /* Успех означает наличие полной структуры пределов быстрой фазы. */
} /* Завершение запроса расширенных возможностей FD. */
bool candle_ctrl_termination(candle_device_t *dev, uint8_t channel, uint32_t *state, bool write) /* Переключение терминатора использует стандартные SET=12 и GET=13. */
{ /* Состояние передаётся одним 32-битным словом согласно протоколу gs_usb. */
bool rc = usb_control_msg(dev->winUSBHandle, write ? CANDLE_BREQ_SET_TERMINATION : CANDLE_BREQ_GET_TERMINATION, (write ? USB_DIR_OUT : USB_DIR_IN)|USB_TYPE_VENDOR|USB_RECIP_INTERFACE, channel, 0, state, sizeof(*state)); /* Номер CAN-канала передаётся в wValue, а wIndex равен нулю по спецификации. */
dev->last_error = rc ? CANDLE_ERR_OK : CANDLE_ERR_SET_DEVICE_MODE; /* Ошибка настройки доступна Python через candle_dev_last_error. */
return rc; /* Не выдаём успешное переключение при отказе USB-контроллера. */
} /* Завершение управления встроенным окончанием шины. */
+7
View File
@@ -20,6 +20,11 @@
*/
/*
* Управляющие USB-запросы адаптера candleLight: конфигурация, временные параметры CAN и режим
* канала. Эти транзакции идут через control endpoint и отличаются от потока CAN-кадров.
*/
#pragma once
#include "candle_defs.h"
@@ -46,4 +51,6 @@ bool candle_ctrl_set_data_bittiming(candle_device_t *dev, uint8_t channel, candl
bool candle_ctrl_get_timestamp(candle_device_t *dev, uint32_t *current_timestamp);
bool candle_ctrl_get_state(candle_device_t *dev, uint8_t channel, candle_device_state_t *data);
bool candle_ctrl_bus_off_recover(candle_device_t *dev, uint8_t channel);
bool candle_ctrl_data_capability(candle_device_t *dev, uint8_t channel, candle_capability_t *cap); /* Читаем пределы быстрой фазы CAN FD отдельным запросом расширенной структуры. */
bool candle_ctrl_termination(candle_device_t *dev, uint8_t channel, uint32_t *state, bool write); /* Передаём состояние терминатора: 0 — выключен, 1 — включён. */
+6
View File
@@ -20,6 +20,12 @@
*/
/*
* Двоичные структуры и константы gs_usb, общие для драйвера и USB-адаптера. Размеры полей и
* упаковка определяют совместимость с прошивкой: менять их как обычные внутренние структуры
* нельзя.
*/
#pragma once
#include <stdint.h>
+5
View File
@@ -19,6 +19,11 @@
*/
/*
* Типы стандартных USB-дескрипторов и запросов из главы 9 спецификации USB. Драйвер использует
* их для описания устройства и конечных точек; это транспортные определения, а не формат CAN.
*/
#pragma once
#define USB_DIR_OUT 0 /* to device */
+4
View File
@@ -1,3 +1,7 @@
# Сборка библиотеки ds18b20_ds2480. Состав исходников и публичные include-пути задают
# подключение к проекту потребителя. Файл также собирает и регистрирует хостовые проверки;
# запускать их следует через CTest из каталога сборки.
cmake_minimum_required(VERSION 3.13)
project(ds18b20_ds2480 C)
add_library(ds18b20_ds2480 STATIC ds2480.c ds18b20_ds2480.c)
+6
View File
@@ -1,3 +1,9 @@
/*
* Команды DS18B20 поверх интерфейса DS2480B: адресация ROM, преобразование температуры и
* scratchpad. Транспортный статус следует проверять до использования результата; сырая
* температура сохраняет знаковое представление датчика.
*/
#include "ds18b20_ds2480.h"
#include <string.h>
+6
View File
@@ -1,3 +1,9 @@
/*
* Команды DS18B20 поверх интерфейса DS2480B: адресация ROM, преобразование температуры и
* scratchpad. Транспортный статус следует проверять до использования результата; сырая
* температура сохраняет знаковое представление датчика.
*/
#ifndef DS18B20_DS2480_H
#define DS18B20_DS2480_H
#include "ds2480.h"
+6
View File
@@ -1,3 +1,9 @@
/*
* UART-мост DS2480B для операций 1-Wire: сброс, обмен битами и байтами, поиск устройств и
* управление питанием. После ошибки связи состояние готовности сбрасывается, чтобы следующий
* обмен не продолжался в неизвестном режиме моста.
*/
#include "ds2480.h"
static ds2480_status fault(ds2480 *bus, ds2480_status status)
+6
View File
@@ -1,3 +1,9 @@
/*
* UART-мост DS2480B для операций 1-Wire: сброс, обмен битами и байтами, поиск устройств и
* управление питанием. После ошибки связи состояние готовности сбрасывается, чтобы следующий
* обмен не продолжался в неизвестном режиме моста.
*/
#ifndef DS2480_H
#define DS2480_H
+6
View File
@@ -1,3 +1,9 @@
/*
* Минимальный блокирующий пример: подготовить мост DS2480B, найти первый датчик, запустить
* преобразование и прочитать температуру. Обратные вызовы UART и задержек предоставляет плата;
* ожидание преобразования входит во время вызова.
*/
#include "ds18b20_ds2480.h"
/* board_port supplies the four callbacks documented in ds2480.h.
@@ -1,3 +1,9 @@
/*
* UART-порт DS2480B для STM32F4. Подготовка линии и очистка ошибок USART отделены от команд
* датчика; после сбоя обмена мост должен пройти предусмотренное восстановление до продолжения
* работы с 1-Wire.
*/
#include "ds2480_stm32f4_hal.h"
#define RX_ERRORS (USART_SR_ORE | USART_SR_NE | USART_SR_FE | USART_SR_PE)
@@ -1,3 +1,9 @@
/*
* UART-порт DS2480B для STM32F4. Подготовка линии и очистка ошибок USART отделены от команд
* датчика; после сбоя обмена мост должен пройти предусмотренное восстановление до продолжения
* работы с 1-Wire.
*/
#ifndef DS2480_STM32F4_HAL_H
#define DS2480_STM32F4_HAL_H
@@ -1,3 +1,11 @@
/*
* Проверки stm32f4xx_hal: фиксируют ожидаемое поведение на воспроизводимых входных данных.
* Сценарии для навигации по файлу:
* test_clear
* Тестовые значения и подмены окружения относятся к проверке контракта; они не являются
* настройками рабочего устройства.
*/
/* Host-only HAL model, never add this directory to a firmware include path. */
#ifndef TEST_STM32F4_HAL_H
#define TEST_STM32F4_HAL_H
@@ -1,3 +1,11 @@
/*
* Проверки port: фиксируют ожидаемое поведение на воспроизводимых входных данных.
* Сценарии для навигации по файлу:
* test_clear
* Тестовые значения и подмены окружения относятся к проверке контракта; они не являются
* настройками рабочего устройства.
*/
#include "ds2480_stm32f4_hal.h"
#include <assert.h>
#include <stdio.h>
@@ -1,3 +1,9 @@
/*
* Проверки ds18b20_ds2480: фиксируют ожидаемое поведение на воспроизводимых входных данных.
* Тестовые значения и подмены окружения относятся к проверке контракта; они не являются
* настройками рабочего устройства.
*/
#include "ds18b20_ds2480.h"
#include <stdio.h>
#include <stdlib.h>
+4
View File
@@ -1,3 +1,7 @@
# Сборка библиотеки ds18b20. Состав исходников и публичные include-пути задают подключение к
# проекту потребителя. Файл также собирает и регистрирует хостовые проверки; запускать их
# следует через CTest из каталога сборки.
cmake_minimum_required(VERSION 3.13)
project(ds18b20 C)
+6
View File
@@ -1,3 +1,9 @@
/*
* Работа с термометрами DS18B20: поиск по ROM, запуск преобразования, чтение температуры и
* настройка scratchpad. ROM является адресом устройства на общей шине; результат чтения нельзя
* считать действительным до проверки статуса обмена и CRC.
*/
/**
* @file ds18b20.h
* @brief Драйвер термометров DS18B20 поверх шины 1-Wire.
+6
View File
@@ -1,3 +1,9 @@
/*
* Общие операции 1-Wire и обход дерева 64-битных ROM. Поиск разрешает коллизии побитно,
* поэтому обнаружение нескольких устройств не сводится к чтению одного адреса. Электрические
* уровни и длительности импульсов задаёт порт.
*/
/**
* @file onewire.h
* @brief Программная шина 1-Wire на выводе с открытым стоком.
+4
View File
@@ -1,3 +1,7 @@
# Сборка библиотеки ds18b20_instance. Состав исходников и публичные include-пути задают
# подключение к проекту потребителя. Файл также собирает и регистрирует хостовые проверки;
# запускать их следует через CTest из каталога сборки.
cmake_minimum_required(VERSION 3.13)
project(ds18b20_instance C)
add_library(ds18b20_instance STATIC Src/ds18b20.c)
+6
View File
@@ -1,3 +1,9 @@
/*
* Работа с термометрами DS18B20: поиск по ROM, запуск преобразования, чтение температуры и
* настройка scratchpad. ROM является адресом устройства на общей шине; результат чтения нельзя
* считать действительным до проверки статуса обмена и CRC.
*/
#ifndef PORTABLE_DS18B20_H
#define PORTABLE_DS18B20_H
+6
View File
@@ -1,3 +1,9 @@
/*
* Конфигурация ds18b20. Макросы задают параметры сборки и ограничения, используемые
* исходниками этого модуля. Смысл и единицы каждого параметра определяются местом его
* использования; размеры буферов должны быть согласованы у всех потребителей заголовка.
*/
#ifndef PORTABLE_DS18B20_CONFIG_H
#define PORTABLE_DS18B20_CONFIG_H
#define DS18B20_DEFAULT_TIMEOUT_MS 750U
+6
View File
@@ -1,3 +1,9 @@
/*
* Работа с термометрами DS18B20: поиск по ROM, запуск преобразования, чтение температуры и
* настройка scratchpad. ROM является адресом устройства на общей шине; результат чтения нельзя
* считать действительным до проверки статуса обмена и CRC.
*/
#include "ds18b20.h"
#include "ds18b20_config.h"
#include <string.h>
@@ -1,3 +1,7 @@
# Сборка и запуск хостовых проверок экземплярного DS18B20. Скрипт готовит исполняемые тесты
# для проверки поиска ROM и задержек EEPROM без платы; ошибка компиляции или проверки должна
# завершить прогон неуспешно.
$ErrorActionPreference = "Stop"
$out = Join-Path $env:TEMP "test_ds18b20_copy_delay.exe"
$test = Join-Path $PSScriptRoot "test_ds18b20_copy_delay.c"
@@ -1,3 +1,10 @@
/*
* Проверки ds18b20_copy_delay: фиксируют ожидаемое поведение на воспроизводимых входных
* данных.
* Тестовые значения и подмены окружения относятся к проверке контракта; они не являются
* настройками рабочего устройства.
*/
#include "ds18b20.h"
#include <assert.h>
@@ -1,3 +1,10 @@
/*
* Проверки ds18b20_incremental_search: фиксируют ожидаемое поведение на воспроизводимых
* входных данных.
* Тестовые значения и подмены окружения относятся к проверке контракта; они не являются
* настройками рабочего устройства.
*/
/* Model real SEARCH ROM participation: each branch filters the active slaves.
* Fault injection tests transport recovery, not analog cable characteristics. */
#include "ds18b20.h"
@@ -1,3 +1,9 @@
/*
* Конфигурация ds18b20 для порта stm32f1. Макросы задают параметры сборки и ограничения,
* используемые исходниками этого модуля. Это образец для проекта: значения выводов, размеров
* памяти и параметров устройства необходимо согласовать с целевой платой.
*/
/**
* @file onewire_config.f103.template.h
* @brief Шаблон привязки шины 1-Wire для STM32F103 (порт stm32f1).
@@ -1,3 +1,9 @@
/*
* Аппаратные временные слоты 1-Wire на STM32F1: управление линией, чтение уровня и
* микросекундные задержки. Конфигурация выбирает GPIO и таймер; общий алгоритм поиска ROM
* остаётся в onewire.c.
*/
/**
* @file onewire_stm32f1.c
* @brief Порт шины 1-Wire на STM32F1: тайминги, вывод и задержки.
@@ -1,3 +1,9 @@
/*
* Конфигурация ds18b20 для порта stm32f4. Макросы задают параметры сборки и ограничения,
* используемые исходниками этого модуля. Это образец для проекта: значения выводов, размеров
* памяти и параметров устройства необходимо согласовать с целевой платой.
*/
/**
* @file onewire_config.f407.template.h
* @brief Шаблон привязки шины 1-Wire для STM32F407VET6 (порт stm32f4).
@@ -1,3 +1,9 @@
/*
* Аппаратные временные слоты 1-Wire на STM32F4 с открытым стоком. Порт использует
* CMSIS-регистры и параметры onewire_config.h; частота таймера должна соответствовать расчёту
* задержек при обмене с датчиками.
*/
/**
* @file onewire_stm32f4.c
* @brief Порт шины 1-Wire на STM32F4: тайминги, вывод и задержки.

Some files were not shown because too many files have changed in this diff Show More